Bug 74419 - [completion] Improve code completion support
Summary: [completion] Improve code completion support
Status: RESOLVED FIXED
Alias: None
Product: AJDT
Classification: Tools
Component: UI (show other bugs)
Version: unspecified   Edit
Hardware: PC Windows XP
: P3 enhancement with 2 votes (vote)
Target Milestone: 1.6.4   Edit
Assignee: AJDT-inbox CLA
QA Contact:
URL:
Whiteboard:
Keywords:
: 48705 53733 (view as bug list)
Depends on: 252696
Blocks:
  Show dependency tree
 
Reported: 2004-09-21 09:35 EDT by Luzius Meisser CLA
Modified: 2009-03-13 13:05 EDT (History)
5 users (show)

See Also:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Luzius Meisser CLA 2004-09-21 09:35:39 EDT
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.
Comment 1 Luzius Meisser CLA 2004-09-21 13:31:29 EDT
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
Comment 2 Luzius Meisser CLA 2004-09-22 05:46:48 EDT
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...
Comment 3 Luzius Meisser CLA 2004-09-22 06:05:47 EDT
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.
Comment 4 Luzius Meisser CLA 2004-09-22 06:10:22 EDT
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
Comment 5 Matt Chapman CLA 2004-10-25 12:01:50 EDT
*** Bug 48705 has been marked as a duplicate of this bug. ***
Comment 6 Matt Chapman CLA 2004-10-27 10:04:36 EDT
*** Bug 53733 has been marked as a duplicate of this bug. ***
Comment 7 Sian January CLA 2005-08-04 04:21:22 EDT
*** Bug 105771 has been marked as a duplicate of this bug. ***
Comment 8 Sian January CLA 2005-08-10 06:54:21 EDT
Please see comment 6 on bug 91357 for some code Mik contributed that may help 
any future code completion work.
Comment 9 Sian January CLA 2005-08-16 05:47:33 EDT
Changed severity to enhancement to reflect current status of the feature.
Comment 10 Andrew Eisenberg CLA 2008-10-29 18:19:39 EDT
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.
Comment 11 Andrew Eisenberg CLA 2008-12-11 19:46:26 EST
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.
Comment 12 Andrew Eisenberg CLA 2008-12-11 19:47:25 EST
Won't address all of these limitations by 1.6.3, but hoping to make some good progress.
Comment 13 Andrew Eisenberg CLA 2009-02-03 17:27:19 EST
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.