Community
Participate
Working Groups
The debugger needs to perform code assist against arbitrary source and binary types. For example, in the variables view, when the selected variable is not that of the current stack frame, we need to code assist in the context of the declared type of the selected variable. This is almost like code assisting in a new method in the associated type. If the selected variable is a source type, we can similate the code assist by creating a working copy of the associated compilation unit, but when the type is binary we fail, as we are not able to modify the contents of the binary's assocaited source buffer with the contents in the variables view. Creating working copies for each code assist is also expensive.
What exactly do you want ? New API on code assist taking a snippet and a type (with imports) - note that then no context information would be accessible, except fields/methods in the same type. Or do you want to be able to create a working copy on a classfile, which I don't think is much more expensive than what is already involved in codeassisting anyway.
What we provide is a snippet and a type (with its imports). We do not have a position within the type, as we are creating a snippet relative to the entire type. Thus, creating a working copy of a classfile might work, but we would need to somehow fake a position within the buffer at which to start code assisting. Also, would it be beneficial to be able to code assist relative to a type that does not have source. I.e. just get access to members in the type. In this case working copy would not help. Thus, an API on IType, that just takes a snippet would be the semantics we are looking for. I believe we could do any other magic on our end of the completion request (if we want to provide access to local variables, etc).
We could define an API receiver an IType, a snippet source and some variable information (visible variables like for snippet evaluation). However this wouldn't work if referring to local types, unless we get the entire unit and a snippet insertion position instead. But then, if no source is available no context would be available.
I need to know what you want. a new API on IClassFile to call when the type is binary. And when the type is not binary you create a working copie. or a new API on ICodeAssist (IClassFile and ICompilationUnit) to call when the type is binary or not. the API should look like this complete( char[] codeSnippet, int codeSnippetPosition, char[][] localVariableTypeNames, char[][] localVariableNames, int[] localVariableModifiers, boolean isStatic, boolean isConstructorCall, ICompletionRequestor requestor )
I vote for a new Code Assist API to call when a type is binary or not (the second suggestion). The API you gave is good - I will add some parameter desciprtions to make sure I understand them: complete( char[] codeSnippet, int codeSnippetPosition, char[][] localVariableTypeNames, char[][] localVariableNames, int[] localVariableModifiers, boolean isStatic, boolean isConstructorCall, ICompletionRequestor requestor ) @param codeSnippet - the complete expression that the user has typed in @param codeSnippetPosition - the position with in 'codeSnippet' where the user is performing code assist @param localVariableTypesNames - an array (possibly empty) of fully qualified type names of local variables visible at the current scope @param localVariableNames - an array (possibly empty) of local variable names that are visible at the current scope @param localVariableModifiers - an array (possible empty) of modifiers for local variables (generally, we cannot provide this info since JDI does not tell us if a local if final - but this should be provided for completeness) @param isStatic - whether the current scope is in a static context @param isConsuctorCall - whether the current scope is within a constructor (why do you need this?) @param requestor - the object to report results to How does this behave with local types? Does it just work, or do you need more info?
Parameter 'isConstructorCall' is not necessary.
There are 3 possible context for completion : 1) a compilation unit if a position to insert snippet in source are given,then paramaters are not useful and we can find local type for free. 2) a class file with attached source this case is like the first case. 3) a class file without source in this case parameters are necessary and we can not find local type. But do you need to find local type if you do not have source ? So i suggest a new API : complete( char[] codeSnippet, int codeSnippetInsertionPosition, // <-------- new parameter int codeSnippetPosition, char[][] localVariableTypeNames, char[][] localVariableNames, int[] localVariableModifiers, boolean isStatic, ICompletionRequestor requestor ) @param codeSnippetInsertionPosition- the position with in source where the snippet is inserted. 'codeSnippetInsertionPosition' is used only if we can find source and 'localVariableTypeNames','localVariableNames','localVariableModifiers', 'isS tatic' are used only if we can not find source.
(1) I would like to be able to specify -1 for codesnippet insertion point if we do not have a location. That way I can code assist relative to a type B, and provide access to locals in the stack frame, that do not exist in B (because we are in a stack frame context of A, and B is the type of an instance var of A). (2) How precise to I have to be on the "codeSnippetPosition". I think the best I can do is give the offset of the beginning of the line that has not yet been executed. (3) We could know we are in a local type even if there is no source (based on the receiving type name, like A$1).
Re(1) - sounds evil. You will get a combination of things which might be a little disturbing when trying to evaluate the snippet in the end. You could reach by simple name, variables defined in both stack frame. Is this what you really want to support at runtime ? Re(2) - sounds good enough. Re(3) - in order to figure inner types in the source, we need a source position, or a handle to the binary type (which is what you have in your hands I presume). The type name does help us much, we would need to find out how the compiler (us?) did choose to name it, however with the file debug attributes, we can easily figure a snippet insertion position I guess. But again, this is the information you already have in your hands, see(2).
(1) Yes, a little evil, and we may not do this. However, the reason I do not want to have to specify a code snippet insertion point, is because I do not always know what it is. If I am in the variables view, and have selected an instance var, which is a Vector, I am code assisting against Vector, but not at any particular position. (2) If I know a position, I will give it to you (3)I can likely resolve the handle for the inner type. Again, I may not have a position - what if it were an argument to another method in another type? Then I was code assisting against the argument?
ICodeAssist is not the right place to put this API, because several classes can be in the same compilation unit. IType is a better place
New API added on org.eclipse.jdt.core.IType. /** * Do code completion inside a code snippet in the context of the current type. * * If the type can access to his source code and the insertion position is valid, * then completion is performed againt source. Otherwise the completion is performed * against type structure and given locals variables. * * @param snippet the code snippet * @param insertion the position with in source where the snippet * is inserted. This position must not be in comments. * A possible value is -1, if the position is not known. * @param position the position with in snippet where the user * is performing code assist. * @param localVariableTypesNames an array (possibly empty) of fully qualified * type names of local variables visible at the current scope * @param localVariableNames an array (possibly empty) of local variable names * that are visible at the current scope * @param localVariableModifiers an array (possible empty) of modifiers for * local variables * @param isStatic whether the current scope is in a static context * @param requestor the completion requestor */ void codeComplete( char[] snippet, int insertion, int position, char[][] localVariableTypeNames, char[][] localVariableNames, int[] localVariableModifiers, boolean isStatic, ICompletionRequestor requestor ) throws JavaModelException; Fixed.
I am making use of this new api in the code assist of Display view. I keep getting a method #akeMethod showing up in the list?
I replace my fake method by an initializer to solve this problem.