Closed reprogrammer closed 13 years ago
@vazexqi, @Wanderer777: I couldn't reproduce this problem. However, while trying to reproduce his exception, I got different exceptions when I extracted constants via quick assist. But, I couldn't reproduce any of these problems deterministically. I got suspicious about the way we capture ITypeRoot
when the user invokes a refactoring via quick assists. The problem might be that we get the ITypeRoot
from non-primary working copies. When the user invokes the quick assist menu and begins to hover the mouse on the menu items, Eclipse creates the change for each menu item and previews it to the user. Eclipse might prepare the preview by applying the changes to non-primary working copies. Therefore, CodingSpectator might get the ITypeRoot
from a working copy whose content is different from that of the the primary working copy. I haven't found a way to confirm my hypothesis yet.
@vazexqi, @Wanderer777: I managed to reproduce the exception. The exception happens when the user tries to perform the refactoring on an unsaved file. Since the contents of the file don't reflect the code the user has invoked the refactoring on, CodingSpectator throws an exception when trying to extract the selected text from the file. Note that CodingSpectator used to extract the selected text from the buffer of ITypeRoot
. But, issue #207 led me to use the file instead of the buffer. In summary, the offsets of the selection may not be applicable to the contents of the file or the buffer. Do you have any suggestions for extracting the selections safely?
The selection should be extracted from the corresponding IDocument
. If the document already exists (which means that the file is opened in an editor, either saved or unsaved), the document's contents would reflect exactly what the user (and the invoked refactoring) sees. If the document does not exist yet, a newly created document would reflect the content of the underlying file (which is fine, since the file is not edited). As the starting point, please see method IDocumentProvider#getDocument
and an example of its use in method EditorHelper#getEditedDocument
.
@Wanderer777, @vazexqi: I didn't know that IDocument
reflects what the user sees in the editor. But, switching to IDocument
for computing the code snippet information seems nontrivial, because IDocument
doesn't provide an ITypeRoot
. Currently, CodingSpectator needs an ITypeRoot
to compute the code snippet. CodingSpectator first finds the AST node covering the selected text. Then, it traverses the AST up until the AST node gets big enough. Finally, it uses the text of the found AST node as the code snippet. CodingSpectator doesn't have to rely on the AST for computing code snippets. For example, it could have captured up to a fixed number of characters around the selected text as the code snippet. That is, there are ways to compute the code snippet information without an ITypeRoot
. But, breaking this dependency on ITypeRoot
requires a lot of changes.
Instead of changing the way code snippet information is computed, I'd suggest to compute this information early before the buffer changes. Currently, CodingSpectator stores the ITypeRoot
and ITextSelection
in the RefactoringGlobalStore
in order to compute the code snippet and selected text later when it's about to serialize the refactoring descriptor. I suggest to extract the code snippet information when the selection object is stored in RefactoringGlobalStore
. This approach may not address issue #207. If early computation of code snippet information doesn't fix this issue and issue #207, CodingSpectator has to compute the code snippet information just from the underlying IDocument
.
AST could be obtained from parsing the content of the underlying IDocument
. But first, we need to make sure that this document indeed represents an ICompilationUnit
(which is ITypeRoot
, and we do not need IClassFile
as we are interested only in source code). Thus, we could use IDocument
and still avoid changing the current code snippet computation.
@Wanderer777: You're right. We should be able to get the ITypeRoot
from IDocument
. However, I don't know which method of getting the ITypeRoot
is superior.
Currently, action classes such as ExtractTempAction
get the ITypeRoot
from the editor using the expression EditorUtility.getEditorInputJavaElement(fEditor, false)
.
Do you know which method is more reliable? That is, which method provides us a better ITypeRoot
to extract the code snippet information from (selection offset and length and the code snippet around the selection).
dd44da620afd4c38ab17ddc7a3eb7ace16910090 .. 679f9041d773d5dac95520ec011640f9770b685a compute the code snippet information immediately after a selection for a refactoring is made and before the invocation of the refactoring proceeds. Immediate computation of code snippet information fixes the problem reported in this issue. But, we still need to investigate if getting the ITypeRoot
from IDocument
is better than how action classes are currently getting the ITypeRoot
.
As we discussed on the phone, if the current approach works, lets keep it. I do not know whether changing it to get ITypeRoot
directly from IDocument
is superior, so we can just keep in mind that there is such alternative.
I got the following exception when trying to extract a local variable from a string literal using quick assist.