Community
Participate
Working Groups
Code completion as it is currently implemented in AJDT fails in many cases. I will list these cases in additional comments as well as describe how code completion currently works.
History of code completion in AJDT :) The code completion feature has grown organically - in the beginning was the visible replacement of "aspect" by "class" which enabled some rudimental code completion. The next step was to make this replacement happen in background. Then, step by step, additional completions have been added. But the idea remained the same: feed jdts code completion parser with slightly changed contents. This approach has its limits and for perfect AspectJ aware code completion, we almost certainly need to abandon it and create an own version of the code completion parser. But for the moment, we can be quite happy with the current solution since it covers a good majority of the common completion proposal scenarios. How code completion currently works Level 1 - UI - ContentAssistant (jdt) The ContentAssistant asks the SourceViewerConfiguration of the active editor for the appropriate CompletionProcessor (in our case an AJCompletionProcessor is returned), then calls computeCompletionProposals on that processor and desplays the returned proposals. Level 2 - Filtering - AJCompletionProcessor The AJCompletionProcessor main task is to filter undesired completion proposals (all proposals beginning with "ajc$" are assumed to be AspectJ artefacts and get filtered away). Additionally, it adds the "Note - limited AspectJ support" remark. In case of a .java file, WorkingCopyManagerForCompletionProcessor gets involved to replace the "aspect" keyword by "class ". That's all that happens to .java files so most features are only working with .aj files. Level 3 - Setting up the content jdts CompletionProcesser calls the codeComplete method of AJCompilationUnit. From here, jdts CompletionEngine gets started. But before we can do so, we need to set up the IBuffer of this AJCompilationUnit to look like ordinary java code. Here is an example of what changes are done to the content: Before: public aspect Aspect { int x; public int Foo.bar; pointcut pcut(): execution(* *(..)); public int meth(){ return 7; } public int Class.interMethod(){ //<- code completion activated here return 7; } after() returning (int x): execution(* *(..)){ } } After: public class Aspect { int x; public int ajc$Foo$bar; pointcut pcut() ; public int meth(){ return 7; } public int ajc$Class$interMethod(){ Class thiz0;thiz0.//<- code completion activated here return 7; } after( int x) { org.aspectj.lang.JoinPoint thisJoinPoint; org.aspectj.lang.JoinPoint.StaticPart thisJoinPointStaticPart; } } After this changes, code completion can be executed like on normal java code. I will go into more details in the next comment. Index - List of directly involved ajdt classes: org.eclipse.ajdt.internal.ui.editor.AJSourceViewerConfiguration org.eclipse.ajdt.internal.ui.editor.contentassist.AJCompletionProcessor org.eclipse.ajdt.internal.ui.editor.contentassist.WorkingCopyManagerForCompleti onProcessor org.eclipse.ajdt.internal.contentassist.ProposalRequestorFilter org.eclipse.ajdt.internal.contentassist.ProposalRequestorWrapper org.eclipse.ajdt.internal.codeconversion.AspectsConvertingParser org.eclipse.ajdt.internal.codeconversion.ConversionOptions org.eclipse.ajdt.internal.codeconversion.JavaCompatibleBuffer org.eclipse.ajdt.core.javaelements.AJCompilationUnit
Details about the code changes that happen in background when code completing: 1. Removing of AspectJ specific keywords that confuse the completion parser: - "aspect" becomes "class " - "privileged" becomes " " 2. Removing pointcut designators and perClause - ": [something] ;" becomes " ;" - ": [something] {" becomes " {" - "[perClause] [something] {" becomes " ;" 3. Transforming "returning" and "throwing" - e.g. "after(int x) throwing (Exception e)" becomes "after(int x, Exception e)" Now, AspectJ syntax can be parsed by jdts completion parser without syntax errors. But there are some more changes: 4. Insertion of "thisJoinPoint" and "thisJoinPointStaticPart" At the start of every advice body "org.aspectj.lang.JoinPoint thisJoinPoint; org.aspectj.lang.JoinPoint.StaticPart thisJoinPointStaticPart;" gets inserted. This enables full code completion for thisJoinPoint and thisJoinPointStatcPart. 5. Code completion in intertype method declaration. This is the most problematic case since it contains quite some tweaking and it is quite likely to brake in special cases that I did not think of. You will see why. If we code complete inside an intertype method declaration, a reference to the target class gets inserted, e.g: "void Circle.method(){ getPerimeter().//<- code complete here }" becomes "void Circle.method(){ Circle thiz0;thiz0.getPerimeter().//<- code complete here }" In this case, the place to insert the "Circle thiz0;thiz0." depends on the acutal position code completion is executed at. The check if we are in an intertype method declaration is done in the AJCompilationUnit using its structure model. The name of the target class an the completion position then gets forwarded to the AspectsConvertingParser by setting the according options in the ConversionOptions object that gets passed to the parser. Unfortunately, this is not enough. Let's consider the following case: "void Circle.method(){ String s; //<- code complete here }" If we convert that to "void Circle.method(){ String s; Circle thiz0;thiz0.//<- code complete here }", the String "s" won't show up as a completion option. To prevent that, AJCompilationUnit runs code completion twice, once with the inserted reference to Circle, and once without. From the first run, all proposals for members are taken, and during the second run, all the others (like the local variable "s"). However, there is another problem with this approach. If we have: "void Circle.method(){ String s; s.//<- code complete here }" That will be converted to "void Circle.method(){ String s; Circle thiz0;thiz0.s.//<- code complete here }", which is completely wrong. Most likely (if there is no visible field called "s" in the Circle class), we won't get any completion proposals at all. What the current solution does in this case, is to count the completion proposals obtained during the first run and if none are found, it does not filter away the member proposals from the second run -> we get proposals for the members of String "s". That's the current state of what happens during code completion. As you see, the last case is quite tricky...
So what are the current limitation of AJDT code completions? 1. Intertype members are not shown. When code complete against "x." where "x" is an Object that has members inserted by intertype declarations, we won't see them. 2. "privileged" has no effect 3. no code completion for pointcuts. There are code templates for primitive pointcuts, but apart from that, code completion inside pointcut designators fails. 4. Fragile code completion inside intertype methods. For example, if we declare an inner class inside an intertype method, we will not get any proposals for members of that inner class. That are the most important cases. It is likely that there are some more I did not think of because this is quite a complex issue.
Hi Matt, This bug contains a quite detailed description of the current code completion implementation in AJDT. I will insert references to this bug at the relevant places in the code, so this bug can serve as a central knowledge base for code completion issues. Luzius
*** Bug 48705 has been marked as a duplicate of this bug. ***
*** Bug 53733 has been marked as a duplicate of this bug. ***
*** Bug 105771 has been marked as a duplicate of this bug. ***
Please see comment 6 on bug 91357 for some code Mik contributed that may help any future code completion work.
Changed severity to enhancement to reflect current status of the feature.
Still lots to do here. I am now looking at ITDs and how to include them in the content assist proposal list. Progress on this bug will be documented in bug 252696.
I should open a bug for each of these limitations (In reply to comment #3) > 1. Intertype members are not shown. When code complete against "x." where > "x" is an Object that has members inserted by intertype declarations, > we won't see them. This now works in .aj files. Next will be to implement this for .java files. > 2. "privileged" has no effect Hmmmm...interesting. Would be hard to trick the compiler to get this done. But, if I can grab hold of the types being processed (ie- the SourceTypeElementInfo), I can go through its children and change the modifiers on them to make them all public. I would have to do this in a temporary ElementInfo so it wouldn't be stored. > 3. no code completion for pointcuts. There are code templates for > primitive pointcuts, but apart from that, code completion inside > pointcut designators fails. I would have to add Java types and their methods. Would be *extremely* difficult to be aware of wildcards (although there may be some support for it built in the Open Type Dialog). > 4. Fragile code completion inside intertype methods. For example, if we > declare an inner class inside an intertype method, we will not get > any proposals for members of that inner class. This is true, but getting better.
Won't address all of these limitations by 1.6.3, but hoping to make some good progress.
Lots and lots of progress here. Almost all situations now work. Proposals only available through the privileged keyword does not work. Also, still getting some NPEs in content assist in around advice. Will look at this in other bugs.