Download
Getting Started
Members
Projects
Community
Marketplace
Events
Planet Eclipse
Newsletter
Videos
Participate
Report a Bug
Forums
Mailing Lists
Wiki
IRC
How to Contribute
Working Groups
Automotive
Internet of Things
LocationTech
Long-Term Support
PolarSys
Science
OpenMDM
More
Community
Marketplace
Events
Planet Eclipse
Newsletter
Videos
Participate
Report a Bug
Forums
Mailing Lists
Wiki
IRC
How to Contribute
Working Groups
Automotive
Internet of Things
LocationTech
Long-Term Support
PolarSys
Science
OpenMDM
Toggle navigation
Bugzilla – Attachment 114761 Details for
Bug 247941
[assist] Add progress monitor to code completion
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Requests
|
Help
|
Log In
[x]
|
Terms of Use
|
Copyright Agent
[patch]
Updated patch
bug247941_022.txt (text/plain), 764.94 KB, created by
David Audel
on 2008-10-10 03:21:10 EDT
(
hide
)
Description:
Updated patch
Filename:
MIME Type:
Creator:
David Audel
Created:
2008-10-10 03:21:10 EDT
Size:
764.94 KB
patch
obsolete
>### Eclipse Workspace Patch 1.0 >#P org.eclipse.jdt.core >Index: codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionParser.java >=================================================================== >RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionParser.java,v >retrieving revision 1.198 >diff -u -r1.198 CompletionParser.java >--- codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionParser.java 23 Jul 2008 09:48:45 -0000 1.198 >+++ codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionParser.java 10 Oct 2008 07:19:36 -0000 >@@ -1554,9 +1554,9 @@ > System.arraycopy(labels, 0, labels = new char[labelCount][], 0, labelCount); > > long position = this.identifierPositionStack[this.identifierPtr]; >- CompletionOnBrankStatementLabel statementLabel = >- new CompletionOnBrankStatementLabel( >- kind == K_INSIDE_BREAK_STATEMENT ? CompletionOnBrankStatementLabel.BREAK : CompletionOnBrankStatementLabel.CONTINUE, >+ CompletionOnBranchStatementLabel statementLabel = >+ new CompletionOnBranchStatementLabel( >+ kind == K_INSIDE_BREAK_STATEMENT ? CompletionOnBranchStatementLabel.BREAK : CompletionOnBranchStatementLabel.CONTINUE, > this.identifierStack[this.identifierPtr--], > (int) (position >>> 32), > (int)position, >Index: codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnBrankStatementLabel.java >=================================================================== >RCS file: codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnBrankStatementLabel.java >diff -N codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnBrankStatementLabel.java >--- codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnBrankStatementLabel.java 27 Jun 2008 16:03:59 -0000 1.4 >+++ /dev/null 1 Jan 1970 00:00:00 -0000 >@@ -1,52 +0,0 @@ >-/******************************************************************************* >- * Copyright (c) 2005, 2006 IBM Corporation and others. >- * All rights reserved. This program and the accompanying materials >- * are made available under the terms of the Eclipse Public License v1.0 >- * which accompanies this distribution, and is available at >- * http://www.eclipse.org/legal/epl-v10.html >- * >- * Contributors: >- * IBM Corporation - initial API and implementation >- *******************************************************************************/ >-package org.eclipse.jdt.internal.codeassist.complete; >- >-import org.eclipse.jdt.internal.compiler.ast.BranchStatement; >-import org.eclipse.jdt.internal.compiler.flow.FlowContext; >-import org.eclipse.jdt.internal.compiler.flow.FlowInfo; >-import org.eclipse.jdt.internal.compiler.lookup.BlockScope; >- >-public class CompletionOnBrankStatementLabel extends BranchStatement { >- public static final int BREAK = 1; >- public static final int CONTINUE = 2; >- >- private int kind; >- public char[][] possibleLabels; >- >- public CompletionOnBrankStatementLabel(int kind, char[] l, int s, int e, char[][] possibleLabels) { >- super(l, s, e); >- this.kind = kind; >- this.possibleLabels = possibleLabels; >- } >- >- public FlowInfo analyseCode(BlockScope currentScope, >- FlowContext flowContext, FlowInfo flowInfo) { >- // Is never called >- return null; >- } >- >- public void resolve(BlockScope scope) { >- throw new CompletionNodeFound(this, scope); >- } >- public StringBuffer printStatement(int indent, StringBuffer output) { >- printIndent(indent, output); >- if(this.kind == CONTINUE) { >- output.append("continue "); //$NON-NLS-1$ >- } else { >- output.append("break "); //$NON-NLS-1$ >- } >- output.append("<CompleteOnLabel:"); //$NON-NLS-1$ >- output.append(this.label); >- return output.append(">;"); //$NON-NLS-1$ >- } >- >-} >Index: model/org/eclipse/jdt/internal/core/SourceType.java >=================================================================== >RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SourceType.java,v >retrieving revision 1.145 >diff -u -r1.145 SourceType.java >--- model/org/eclipse/jdt/internal/core/SourceType.java 27 Jun 2008 16:03:51 -0000 1.145 >+++ model/org/eclipse/jdt/internal/core/SourceType.java 10 Oct 2008 07:19:37 -0000 >@@ -74,14 +74,36 @@ > /** > * @see IType > */ >+public void codeComplete(char[] snippet,int insertion,int position,char[][] localVariableTypeNames,char[][] localVariableNames,int[] localVariableModifiers,boolean isStatic,CompletionRequestor requestor, IProgressMonitor monitor) throws JavaModelException { >+ codeComplete(snippet, insertion, position, localVariableTypeNames, localVariableNames, localVariableModifiers, isStatic, requestor, DefaultWorkingCopyOwner.PRIMARY, monitor); >+} >+/** >+ * @see IType >+ */ > public void codeComplete(char[] snippet,int insertion,int position,char[][] localVariableTypeNames,char[][] localVariableNames,int[] localVariableModifiers,boolean isStatic,CompletionRequestor requestor, WorkingCopyOwner owner) throws JavaModelException { >+ codeComplete(snippet, insertion, position, localVariableTypeNames, localVariableNames, localVariableModifiers, isStatic, requestor, owner, null); >+} >+/** >+ * @see IType >+ */ >+public void codeComplete( >+ char[] snippet, >+ int insertion, >+ int position, >+ char[][] localVariableTypeNames, >+ char[][] localVariableNames, >+ int[] localVariableModifiers, >+ boolean isStatic, >+ CompletionRequestor requestor, >+ WorkingCopyOwner owner, >+ IProgressMonitor monitor) throws JavaModelException { > if (requestor == null) { > throw new IllegalArgumentException("Completion requestor cannot be null"); //$NON-NLS-1$ > } > > JavaProject project = (JavaProject) getJavaProject(); > SearchableEnvironment environment = project.newSearchableNameEnvironment(owner); >- CompletionEngine engine = new CompletionEngine(environment, requestor, project.getOptions(true), project, owner); >+ CompletionEngine engine = new CompletionEngine(environment, requestor, project.getOptions(true), project, owner, monitor); > > String source = getCompilationUnit().getSource(); > if (source != null && insertion > -1 && insertion < source.length()) { >Index: model/org/eclipse/jdt/internal/core/ClassFile.java >=================================================================== >RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ClassFile.java,v >retrieving revision 1.143 >diff -u -r1.143 ClassFile.java >--- model/org/eclipse/jdt/internal/core/ClassFile.java 27 Jun 2008 16:03:50 -0000 1.143 >+++ model/org/eclipse/jdt/internal/core/ClassFile.java 10 Oct 2008 07:19:36 -0000 >@@ -122,11 +122,22 @@ > public void codeComplete(int offset, CompletionRequestor requestor) throws JavaModelException { > codeComplete(offset, requestor, DefaultWorkingCopyOwner.PRIMARY); > } >- >+/* (non-Javadoc) >+ * @see org.eclipse.jdt.core.ICodeAssist#codeComplete(int, org.eclipse.jdt.core.CompletionRequestor, org.eclipse.core.runtime.IProgressMonitor) >+ */ >+public void codeComplete(int offset, CompletionRequestor requestor, IProgressMonitor monitor) throws JavaModelException { >+ codeComplete(offset, requestor, DefaultWorkingCopyOwner.PRIMARY, monitor); >+} > /* (non-Javadoc) > * @see org.eclipse.jdt.core.ICodeAssist#codeComplete(int, org.eclipse.jdt.core.CompletionRequestor, org.eclipse.jdt.core.WorkingCopyOwner) > */ > public void codeComplete(int offset, CompletionRequestor requestor, WorkingCopyOwner owner) throws JavaModelException { >+ codeComplete(offset, requestor, owner, null); >+} >+/* (non-Javadoc) >+ * @see org.eclipse.jdt.core.ICodeAssist#codeComplete(int, org.eclipse.jdt.core.CompletionRequestor, org.eclipse.jdt.core.WorkingCopyOwner, org.eclipse.core.runtime.IProgressMonitor) >+ */ >+public void codeComplete(int offset, CompletionRequestor requestor, WorkingCopyOwner owner, IProgressMonitor monitor) throws JavaModelException { > String source = getSource(); > if (source != null) { > BinaryType type = (BinaryType) getType(); >@@ -136,7 +147,7 @@ > null, > type.sourceFileName((IBinaryType) type.getElementInfo()), > getJavaProject()); // use project to retrieve corresponding .java IFile >- codeComplete(cu, cu, offset, requestor, owner, null/*extended context isn't computed*/); >+ codeComplete(cu, cu, offset, requestor, owner, null/*extended context isn't computed*/, monitor); > } > } > >Index: model/org/eclipse/jdt/internal/core/Openable.java >=================================================================== >RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/Openable.java,v >retrieving revision 1.119 >diff -u -r1.119 Openable.java >--- model/org/eclipse/jdt/internal/core/Openable.java 9 Oct 2008 08:45:46 -0000 1.119 >+++ model/org/eclipse/jdt/internal/core/Openable.java 10 Oct 2008 07:19:36 -0000 >@@ -101,7 +101,8 @@ > org.eclipse.jdt.internal.compiler.env.ICompilationUnit unitToSkip, > int position, CompletionRequestor requestor, > WorkingCopyOwner owner, >- ITypeRoot typeRoot) throws JavaModelException { >+ ITypeRoot typeRoot, >+ IProgressMonitor monitor) throws JavaModelException { > if (requestor == null) { > throw new IllegalArgumentException("Completion requestor cannot be null"); //$NON-NLS-1$ > } >@@ -125,7 +126,7 @@ > environment.unitToSkip = unitToSkip; > > // code complete >- CompletionEngine engine = new CompletionEngine(environment, requestor, project.getOptions(true), project, owner); >+ CompletionEngine engine = new CompletionEngine(environment, requestor, project.getOptions(true), project, owner, monitor); > engine.complete(cu, position, 0, typeRoot); > if(performanceStats != null) { > performanceStats.endRun(); >Index: model/org/eclipse/jdt/internal/core/BinaryType.java >=================================================================== >RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/BinaryType.java,v >retrieving revision 1.159 >diff -u -r1.159 BinaryType.java >--- model/org/eclipse/jdt/internal/core/BinaryType.java 27 Jun 2008 16:03:50 -0000 1.159 >+++ model/org/eclipse/jdt/internal/core/BinaryType.java 10 Oct 2008 07:19:36 -0000 >@@ -82,17 +82,38 @@ > public void codeComplete(char[] snippet,int insertion,int position,char[][] localVariableTypeNames,char[][] localVariableNames,int[] localVariableModifiers,boolean isStatic,CompletionRequestor requestor) throws JavaModelException { > codeComplete(snippet, insertion, position, localVariableTypeNames, localVariableNames, localVariableModifiers, isStatic, requestor, DefaultWorkingCopyOwner.PRIMARY); > } >- >+/* >+ * @see IType#codeComplete(char[], int, int, char[][], char[][], int[], boolean, ICompletionRequestor, IProgressMonitor) >+ */ >+public void codeComplete(char[] snippet,int insertion,int position,char[][] localVariableTypeNames,char[][] localVariableNames,int[] localVariableModifiers,boolean isStatic,CompletionRequestor requestor, IProgressMonitor monitor) throws JavaModelException { >+ codeComplete(snippet, insertion, position, localVariableTypeNames, localVariableNames, localVariableModifiers, isStatic, requestor, DefaultWorkingCopyOwner.PRIMARY, monitor); >+} > /* > * @see IType#codeComplete(char[], int, int, char[][], char[][], int[], boolean, ICompletionRequestor, WorkingCopyOwner) > */ > public void codeComplete(char[] snippet,int insertion,int position,char[][] localVariableTypeNames,char[][] localVariableNames,int[] localVariableModifiers,boolean isStatic,CompletionRequestor requestor, WorkingCopyOwner owner) throws JavaModelException { >+ codeComplete(snippet, insertion, position, localVariableTypeNames, localVariableNames, localVariableModifiers, isStatic, requestor, owner, null); >+} >+/* >+ * @see IType#codeComplete(char[], int, int, char[][], char[][], int[], boolean, ICompletionRequestor, WorkingCopyOwner, IProgressMonitor) >+ */ >+public void codeComplete( >+ char[] snippet, >+ int insertion, >+ int position, >+ char[][] localVariableTypeNames, >+ char[][] localVariableNames, >+ int[] localVariableModifiers, >+ boolean isStatic, >+ CompletionRequestor requestor, >+ WorkingCopyOwner owner, >+ IProgressMonitor monitor) throws JavaModelException { > if (requestor == null) { > throw new IllegalArgumentException("Completion requestor cannot be null"); //$NON-NLS-1$ > } > JavaProject project = (JavaProject) getJavaProject(); > SearchableEnvironment environment = project.newSearchableNameEnvironment(owner); >- CompletionEngine engine = new CompletionEngine(environment, requestor, project.getOptions(true), project, owner); >+ CompletionEngine engine = new CompletionEngine(environment, requestor, project.getOptions(true), project, owner, monitor); > > String source = getClassFile().getSource(); > if (source != null && insertion > -1 && insertion < source.length()) { >Index: model/org/eclipse/jdt/internal/core/CompilationUnit.java >=================================================================== >RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/CompilationUnit.java,v >retrieving revision 1.252 >diff -u -r1.252 CompilationUnit.java >--- model/org/eclipse/jdt/internal/core/CompilationUnit.java 5 Sep 2008 13:30:43 -0000 1.252 >+++ model/org/eclipse/jdt/internal/core/CompilationUnit.java 10 Oct 2008 07:19:36 -0000 >@@ -336,18 +336,30 @@ > public void codeComplete(int offset, CompletionRequestor requestor) throws JavaModelException { > codeComplete(offset, requestor, DefaultWorkingCopyOwner.PRIMARY); > } >- >+/* (non-Javadoc) >+ * @see org.eclipse.jdt.core.ICodeAssist#codeComplete(int, org.eclipse.jdt.core.CompletionRequestor, org.eclipse.core.runtime.IProgressMonitor) >+ */ >+public void codeComplete(int offset, CompletionRequestor requestor, IProgressMonitor monitor) throws JavaModelException { >+ codeComplete(offset, requestor, DefaultWorkingCopyOwner.PRIMARY, monitor); >+} > /* (non-Javadoc) > * @see org.eclipse.jdt.core.ICodeAssist#codeComplete(int, org.eclipse.jdt.core.CompletionRequestor, org.eclipse.jdt.core.WorkingCopyOwner) > */ > public void codeComplete(int offset, CompletionRequestor requestor, WorkingCopyOwner workingCopyOwner) throws JavaModelException { >+ codeComplete(offset, requestor, workingCopyOwner, null); >+} >+/* (non-Javadoc) >+ * @see org.eclipse.jdt.core.ICodeAssist#codeComplete(int, org.eclipse.jdt.core.CompletionRequestor, org.eclipse.jdt.core.WorkingCopyOwner, org.eclipse.core.runtime.IProgressMonitor) >+ */ >+public void codeComplete(int offset, CompletionRequestor requestor, WorkingCopyOwner workingCopyOwner, IProgressMonitor monitor) throws JavaModelException { > codeComplete( > this, > isWorkingCopy() ? (org.eclipse.jdt.internal.compiler.env.ICompilationUnit) getOriginalElement() : this, > offset, > requestor, > workingCopyOwner, >- this); >+ this, >+ monitor); > } > > /** >Index: model/org/eclipse/jdt/core/eval/IEvaluationContext.java >=================================================================== >RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/model/org/eclipse/jdt/core/eval/IEvaluationContext.java,v >retrieving revision 1.25 >diff -u -r1.25 IEvaluationContext.java >--- model/org/eclipse/jdt/core/eval/IEvaluationContext.java 27 Jun 2008 16:04:08 -0000 1.25 >+++ model/org/eclipse/jdt/core/eval/IEvaluationContext.java 10 Oct 2008 07:19:36 -0000 >@@ -177,6 +177,34 @@ > int position, > CompletionRequestor requestor) > throws JavaModelException; >+ >+ /** >+ * Performs a code completion at the given position in the given code snippet, >+ * reporting results to the given completion requestor. >+ * <p> >+ * Note that code completion does not involve evaluation. >+ * <p> >+ * >+ * @param codeSnippet the code snippet to complete in >+ * @param position the character position in the code snippet to complete at, >+ * or -1 indicating the beginning of the snippet >+ * @param requestor the code completion requestor capable of accepting all >+ * possible types of completions >+ * @param monitor the progress monitor used to report progress >+ * @exception JavaModelException if code completion could not be performed. Reasons include: >+ * <ul> >+ * <li>The position specified is less than -1 or is greater than the snippet's >+ * length (INDEX_OUT_OF_BOUNDS)</li> >+ * </ul> >+ * @since 3.5 >+ */ >+ public void codeComplete( >+ String codeSnippet, >+ int position, >+ CompletionRequestor requestor, >+ IProgressMonitor monitor) >+ throws JavaModelException; >+ > /** > * Performs a code completion at the given position in the given code snippet, > * reporting results to the given completion requestor. >@@ -210,6 +238,43 @@ > CompletionRequestor requestor, > WorkingCopyOwner owner) > throws JavaModelException; >+ >+ /** >+ * Performs a code completion at the given position in the given code snippet, >+ * reporting results to the given completion requestor. >+ * It considers types in the working copies with the given owner first. In other words, >+ * the owner's working copies will take precedence over their original compilation units >+ * in the workspace. >+ * <p> >+ * Note that if a working copy is empty, it will be as if the original compilation >+ * unit had been deleted. >+ * </p> >+ * <p> >+ * Note that code completion does not involve evaluation. >+ * <p> >+ * >+ * @param codeSnippet the code snippet to complete in >+ * @param position the character position in the code snippet to complete at, >+ * or -1 indicating the beginning of the snippet >+ * @param requestor the code completion requestor capable of accepting all >+ * possible types of completions >+ * @param owner the owner of working copies that take precedence over their original compilation units >+ * @param monitor the progress monitor used to report progress >+ * @exception JavaModelException if code completion could not be performed. Reasons include: >+ * <ul> >+ * <li>The position specified is less than -1 or is greater than the snippet's >+ * length (INDEX_OUT_OF_BOUNDS)</li> >+ * </ul> >+ * @since 3.5 >+ */ >+ public void codeComplete( >+ String codeSnippet, >+ int position, >+ CompletionRequestor requestor, >+ WorkingCopyOwner owner, >+ IProgressMonitor monitor) >+ throws JavaModelException; >+ > /** > * Resolves and returns a collection of Java elements corresponding to the source > * code at the given positions in the given code snippet. >Index: codeassist/org/eclipse/jdt/internal/codeassist/CompletionEngine.java >=================================================================== >RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/CompletionEngine.java,v >retrieving revision 1.377 >diff -u -r1.377 CompletionEngine.java >--- codeassist/org/eclipse/jdt/internal/codeassist/CompletionEngine.java 25 Sep 2008 23:10:30 -0000 1.377 >+++ codeassist/org/eclipse/jdt/internal/codeassist/CompletionEngine.java 10 Oct 2008 07:19:35 -0000 >@@ -14,6 +14,8 @@ > import java.util.Locale; > import java.util.Map; > >+import org.eclipse.core.runtime.IProgressMonitor; >+import org.eclipse.core.runtime.OperationCanceledException; > import org.eclipse.jdt.core.CompletionContext; > import org.eclipse.jdt.core.CompletionFlags; > import org.eclipse.jdt.core.CompletionProposal; >@@ -64,6 +66,7 @@ > import org.eclipse.jdt.internal.core.BinaryTypeConverter; > import org.eclipse.jdt.internal.core.SearchableEnvironment; > import org.eclipse.jdt.internal.core.SourceTypeElementInfo; >+import org.eclipse.jdt.internal.core.util.Messages; > > /** > * This class is the entry point for source completions. >@@ -73,7 +76,43 @@ > public final class CompletionEngine > extends Engine > implements ISearchRequestor, TypeConstants , TerminalTokens , RelevanceConstants, SuffixConstants { >+ >+ private static class AcceptedType { >+ public char[] packageName; >+ public char[] simpleTypeName; >+ public char[][] enclosingTypeNames; >+ public int modifiers; >+ public int accessibility; >+ public boolean mustBeQualified = false; >+ >+ public char[] fullyQualifiedName = null; >+ public char[] qualifiedTypeName = null; >+ public AcceptedType( >+ char[] packageName, >+ char[] simpleTypeName, >+ char[][] enclosingTypeNames, >+ int modifiers, >+ int accessibility) { >+ this.packageName = packageName; >+ this.simpleTypeName = simpleTypeName; >+ this.enclosingTypeNames = enclosingTypeNames; >+ this.modifiers = modifiers; >+ this.accessibility = accessibility; >+ } > >+ public String toString() { >+ StringBuffer buffer = new StringBuffer(); >+ buffer.append('{'); >+ buffer.append(this.packageName); >+ buffer.append(','); >+ buffer.append(this.simpleTypeName); >+ buffer.append(','); >+ buffer.append(CharOperation.concatWith(this.enclosingTypeNames, '.')); >+ buffer.append('}'); >+ return buffer.toString(); >+ } >+ } >+ > public class CompletionProblemFactory extends DefaultProblemFactory { > private int lastErrorStart; > >@@ -133,6 +172,7 @@ > char[] originatingFileName, > int problemId, > String[] problemArguments, >+ int elaborationId, > String[] messageArguments, > int severity, > int start, >@@ -144,6 +184,7 @@ > originatingFileName, > problemId, > problemArguments, >+ elaborationId, > messageArguments, > severity, > start, >@@ -156,7 +197,6 @@ > char[] originatingFileName, > int problemId, > String[] problemArguments, >- int elaborationId, > String[] messageArguments, > int severity, > int start, >@@ -168,7 +208,6 @@ > originatingFileName, > problemId, > problemArguments, >- elaborationId, > messageArguments, > severity, > start, >@@ -188,50 +227,91 @@ > } > } > >- private static class AcceptedType { >- public AcceptedType( >- char[] packageName, >- char[] simpleTypeName, >- char[][] enclosingTypeNames, >- int modifiers, >- int accessibility) { >- this.packageName = packageName; >- this.simpleTypeName = simpleTypeName; >- this.enclosingTypeNames = enclosingTypeNames; >- this.modifiers = modifiers; >- this.accessibility = accessibility; >+ public static char[] createMethodSignature(char[][] parameterPackageNames, char[][] parameterTypeNames, char[] returnTypeSignature) { >+ char[][] parameterTypeSignature = new char[parameterTypeNames.length][]; >+ for (int i = 0; i < parameterTypeSignature.length; i++) { >+ parameterTypeSignature[i] = >+ Signature.createCharArrayTypeSignature( >+ CharOperation.concat( >+ parameterPackageNames[i], >+ CharOperation.replaceOnCopy(parameterTypeNames[i], '.', '$'), '.'), true); > } >- public char[] packageName; >- public char[] simpleTypeName; >- public char[][] enclosingTypeNames; >- public int modifiers; >- public int accessibility; > >- public boolean mustBeQualified = false; >- public char[] fullyQualifiedName = null; >- public char[] qualifiedTypeName = null; >+ return Signature.createMethodSignature( >+ parameterTypeSignature, >+ returnTypeSignature); >+ } > >- public String toString() { >- StringBuffer buffer = new StringBuffer(); >- buffer.append('{'); >- buffer.append(this.packageName); >- buffer.append(','); >- buffer.append(this.simpleTypeName); >- buffer.append(','); >- buffer.append(CharOperation.concatWith(this.enclosingTypeNames, '.')); >- buffer.append('}'); >- return buffer.toString(); >+ public static char[] createMethodSignature(char[][] parameterPackageNames, char[][] parameterTypeNames, char[] returnPackagename, char[] returnTypeName) { >+ char[] returnTypeSignature = >+ returnTypeName == null || returnTypeName.length == 0 >+ ? Signature.createCharArrayTypeSignature(VOID, true) >+ : Signature.createCharArrayTypeSignature( >+ CharOperation.concat( >+ returnPackagename, >+ CharOperation.replaceOnCopy(returnTypeName, '.', '$'), '.'), true); >+ >+ return createMethodSignature( >+ parameterPackageNames, >+ parameterTypeNames, >+ returnTypeSignature); >+ } >+ public static char[] createNonGenericTypeSignature(char[] qualifiedPackageName, char[] qualifiedTypeName) { >+ return Signature.createCharArrayTypeSignature( >+ CharOperation.concat( >+ qualifiedPackageName, >+ CharOperation.replaceOnCopy(qualifiedTypeName, '.', '$'), '.'), true); >+ } >+ >+ public static char[] createTypeSignature(char[] qualifiedPackageName, char[] qualifiedTypeName) { >+ char[] name = new char[qualifiedTypeName.length]; >+ System.arraycopy(qualifiedTypeName, 0, name, 0, qualifiedTypeName.length); >+ >+ int depth = 0; >+ int length = name.length; >+ for (int i = length -1; i >= 0; i--) { >+ switch (name[i]) { >+ case '.': >+ if (depth == 0 && name[i - 1] != '>') { >+ name[i] = '$'; >+ } >+ break; >+ case '<': >+ depth--; >+ break; >+ case '>': >+ depth++; >+ break; >+ } > } >+ return Signature.createCharArrayTypeSignature( >+ CharOperation.concat( >+ qualifiedPackageName, >+ name, '.'), true); > } > >- public HashtableOfObject typeCache; >+ private static char[] getRequiredTypeSignature(TypeBinding typeBinding) { >+ char[] result = null; >+ StringBuffer sig = new StringBuffer(10); >+ >+ sig.append(typeBinding.signature()); > >+ int sigLength = sig.length(); >+ result = new char[sigLength]; >+ sig.getChars(0, sigLength, result, 0); >+ result = CharOperation.replaceOnCopy(result, '/', '.'); >+ return result; >+ } >+ public HashtableOfObject typeCache; >+ > public static boolean DEBUG = false; > public static boolean PERF = false; >- >+ >+ private final static int CHECK_CANCEL_FREQUENCY_IN_FIND_TYPES = 50; >+ > // temporary constants to quickly disabled polish features if necessary > public final static boolean NO_TYPE_COMPLETION_ON_EMPTY_TOKEN = false; >- >+ > private final static char[] ERROR_PATTERN = "*error*".toCharArray(); //$NON-NLS-1$ > private final static char[] EXCEPTION_PATTERN = "*exception*".toCharArray(); //$NON-NLS-1$ > private final static char[] SEMICOLON = new char[] { ';' }; >@@ -243,11 +323,11 @@ > private final static char[] VALUE = "value".toCharArray(); //$NON-NLS-1$ > private final static char[] EXTENDS = "extends".toCharArray(); //$NON-NLS-1$ > private final static char[] SUPER = "super".toCharArray(); //$NON-NLS-1$ >- >+ > private final static char[] DOT = ".".toCharArray(); //$NON-NLS-1$ > > private final static char[] VARARGS = "...".toCharArray(); //$NON-NLS-1$ >- >+ > private final static char[] IMPORT = "import".toCharArray(); //$NON-NLS-1$ > private final static char[] STATIC = "static".toCharArray(); //$NON-NLS-1$ > private final static char[] ON_DEMAND = ".*".toCharArray(); //$NON-NLS-1$ >@@ -257,15 +337,15 @@ > createTypeSignature(CharOperation.concatWith(JAVA_LANG, '.'), OBJECT); > private final static char[] JAVA_LANG_NAME = > CharOperation.concatWith(JAVA_LANG, '.'); >- >+ > private final static int NONE = 0; > private final static int SUPERTYPE = 1; > private final static int SUBTYPE = 2; >- >+ > private final static int FIELD = 0; > private final static int LOCAL = 1; > private final static int ARGUMENT = 2; >- >+ > int expectedTypesPtr = -1; > TypeBinding[] expectedTypes = new TypeBinding[1]; > int expectedTypesFilter; >@@ -275,9 +355,9 @@ > int forbbidenBindingsPtr = -1; > Binding[] forbbidenBindings = new Binding[1]; > int forbbidenBindingsFilter; >- >+ > ImportBinding[] favoriteReferenceBindings; >- >+ > boolean assistNodeIsClass; > boolean assistNodeIsEnum; > boolean assistNodeIsException; >@@ -287,10 +367,11 @@ > boolean assistNodeIsSuperType; > int assistNodeInJavadoc = 0; > boolean assistNodeCanBeSingleMemberAnnotation = false; >- >+ > long targetedElement; >- >+ > WorkingCopyOwner owner; >+ IProgressMonitor monitor; > IJavaProject javaProject; > ITypeRoot typeRoot; > CompletionParser parser; >@@ -312,8 +393,8 @@ > HashtableOfObject knownPkgs = new HashtableOfObject(10); > HashtableOfObject knownTypes = new HashtableOfObject(10); > Scanner nameScanner; >- >- /* >+ >+ /* > static final char[][] mainDeclarations = > new char[][] { > "package".toCharArray(), >@@ -353,7 +434,7 @@ > static final char[][] BASE_TYPE_NAMES = new char[BASE_TYPES_LENGTH][]; > static final int BASE_TYPES_WITHOUT_VOID_LENGTH = BASE_TYPES.length - 1; > static final char[][] BASE_TYPE_NAMES_WITHOUT_VOID = new char[BASE_TYPES_WITHOUT_VOID_LENGTH][]; >- static { >+ static { > for (int i=0; i<BASE_TYPES_LENGTH; i++) { > BASE_TYPE_NAMES[i] = BASE_TYPES[i].simpleName; > } >@@ -361,7 +442,7 @@ > BASE_TYPE_NAMES_WITHOUT_VOID[i] = BASE_TYPES[i].simpleName; > } > } >- >+ > static final char[] classField = "class".toCharArray(); //$NON-NLS-1$ > static final char[] lengthField = "length".toCharArray(); //$NON-NLS-1$ > static final char[] cloneMethod = "clone".toCharArray(); //$NON-NLS-1$ >@@ -375,10 +456,11 @@ > public void setActualReceiverType(ReferenceBinding receiverType) {/* empty */} > public void setDepth(int depth){/* empty */} > public void setFieldIndex(int depth){/* empty */} >- public int sourceStart() { return 0; } > public int sourceEnd() { return 0; } >+ public int sourceStart() { return 0; } > }; > >+ private int foundTypesCount; > private ObjectVector acceptedTypes; > > /** >@@ -403,7 +485,8 @@ > CompletionRequestor requestor, > Map settings, > IJavaProject javaProject, >- WorkingCopyOwner owner) { >+ WorkingCopyOwner owner, >+ IProgressMonitor monitor) { > super(settings); > this.javaProject = javaProject; > this.requestor = requestor; >@@ -429,6 +512,56 @@ > null/*taskPriorities*/, > true/*taskCaseSensitive*/); > this.owner = owner; >+ this.monitor = monitor; >+ } >+ >+ /** >+ * One result of the search consists of a new package. >+ * >+ * NOTE - All package names are presented in their readable form: >+ * Package names are in the form "a.b.c". >+ * The default package is represented by an empty array. >+ */ >+ public void acceptPackage(char[] packageName) { >+ >+ if (this.knownPkgs.containsKey(packageName)) return; >+ >+ this.knownPkgs.put(packageName, this); >+ >+ char[] completion; >+ if(this.resolvingImports) { >+ if(this.resolvingStaticImports) { >+ completion = CharOperation.concat(packageName, new char[] { '.' }); >+ } else { >+ completion = CharOperation.concat(packageName, new char[] { '.', '*', ';' }); >+ } >+ } else { >+ completion = packageName; >+ } >+ >+ int relevance = computeBaseRelevance(); >+ relevance += computeRelevanceForResolution(); >+ relevance += computeRelevanceForInterestingProposal(); >+ relevance += computeRelevanceForCaseMatching(this.qualifiedCompletionToken == null ? this.completionToken : this.qualifiedCompletionToken, packageName); >+ if(!this.resolvingImports) { >+ relevance += computeRelevanceForQualification(true); >+ } >+ relevance += computeRelevanceForRestrictions(IAccessRule.K_ACCESSIBLE); >+ >+ this.noProposal = false; >+ if(!this.requestor.isIgnored(CompletionProposal.PACKAGE_REF)) { >+ InternalCompletionProposal proposal = createProposal(CompletionProposal.PACKAGE_REF, this.actualCompletionPosition); >+ proposal.setDeclarationSignature(packageName); >+ proposal.setPackageName(packageName); >+ proposal.setCompletion(completion); >+ proposal.setReplaceRange(this.startPosition - this.offset, this.endPosition - this.offset); >+ proposal.setTokenRange(this.tokenStart - this.offset, this.tokenEnd - this.offset); >+ proposal.setRelevance(relevance); >+ this.requestor.accept(proposal); >+ if(DEBUG) { >+ this.printDebug(proposal); >+ } >+ } > } > > /** >@@ -445,7 +578,11 @@ > char[][] enclosingTypeNames, > int modifiers, > AccessRestriction accessRestriction) { >- >+ >+ // does not check cancellation for every types to avoid performance loss >+ if ((this.foundTypesCount % CHECK_CANCEL_FREQUENCY_IN_FIND_TYPES) == 0) checkCancel(); >+ this.foundTypesCount++; >+ > if (this.options.checkDeprecation && (modifiers & ClassFileConstants.AccDeprecated) != 0) return; > > if (this.options.checkVisibility) { >@@ -489,67 +626,87 @@ > if(length == 0) return; > > HashtableOfObject onDemandFound = new HashtableOfObject(); >- >- next : for (int i = 0; i < length; i++) { >- AcceptedType acceptedType = (AcceptedType)this.acceptedTypes.elementAt(i); >- char[] packageName = acceptedType.packageName; >- char[] simpleTypeName = acceptedType.simpleTypeName; >- char[][] enclosingTypeNames = acceptedType.enclosingTypeNames; >- int modifiers = acceptedType.modifiers; >- int accessibility = acceptedType.accessibility; >- >- char[] typeName; >- char[] flatEnclosingTypeNames; >- if(enclosingTypeNames == null || enclosingTypeNames.length == 0) { >- flatEnclosingTypeNames = null; >- typeName = simpleTypeName; >- } else { >- flatEnclosingTypeNames = CharOperation.concatWith(acceptedType.enclosingTypeNames, '.'); >- typeName = CharOperation.concat(flatEnclosingTypeNames, simpleTypeName, '.'); >- } >- char[] fullyQualifiedName = CharOperation.concat(packageName, typeName, '.'); >- >- if (this.knownTypes.containsKey(fullyQualifiedName)) continue next; >- >- this.knownTypes.put(fullyQualifiedName, this); >- >- if (this.resolvingImports) { >- if(this.compilerOptions.complianceLevel >= ClassFileConstants.JDK1_4 && packageName.length == 0) { >- continue next; // import of default package is forbidden when compliance is 1.4 or higher >+ >+ try { >+ next : for (int i = 0; i < length; i++) { >+ >+ // does not check cancellation for every types to avoid performance loss >+ if ((i % CHECK_CANCEL_FREQUENCY_IN_FIND_TYPES) == 0) checkCancel(); >+ >+ AcceptedType acceptedType = (AcceptedType)this.acceptedTypes.elementAt(i); >+ char[] packageName = acceptedType.packageName; >+ char[] simpleTypeName = acceptedType.simpleTypeName; >+ char[][] enclosingTypeNames = acceptedType.enclosingTypeNames; >+ int modifiers = acceptedType.modifiers; >+ int accessibility = acceptedType.accessibility; >+ >+ char[] typeName; >+ char[] flatEnclosingTypeNames; >+ if(enclosingTypeNames == null || enclosingTypeNames.length == 0) { >+ flatEnclosingTypeNames = null; >+ typeName = simpleTypeName; >+ } else { >+ flatEnclosingTypeNames = CharOperation.concatWith(acceptedType.enclosingTypeNames, '.'); >+ typeName = CharOperation.concat(flatEnclosingTypeNames, simpleTypeName, '.'); > } >- >- char[] completionName = this.insideQualifiedReference ? simpleTypeName : fullyQualifiedName; >- >- if(this.resolvingStaticImports) { >- if(enclosingTypeNames == null || enclosingTypeNames.length == 0) { >- completionName = CharOperation.concat(completionName, new char[] { '.' }); >- } else if ((modifiers & ClassFileConstants.AccStatic) == 0) { >- continue next; >+ char[] fullyQualifiedName = CharOperation.concat(packageName, typeName, '.'); >+ >+ if (this.knownTypes.containsKey(fullyQualifiedName)) continue next; >+ >+ this.knownTypes.put(fullyQualifiedName, this); >+ >+ if (this.resolvingImports) { >+ if(this.compilerOptions.complianceLevel >= ClassFileConstants.JDK1_4 && packageName.length == 0) { >+ continue next; // import of default package is forbidden when compliance is 1.4 or higher >+ } >+ >+ char[] completionName = this.insideQualifiedReference ? simpleTypeName : fullyQualifiedName; >+ >+ if(this.resolvingStaticImports) { >+ if(enclosingTypeNames == null || enclosingTypeNames.length == 0) { >+ completionName = CharOperation.concat(completionName, new char[] { '.' }); >+ } else if ((modifiers & ClassFileConstants.AccStatic) == 0) { >+ continue next; >+ } else { >+ completionName = CharOperation.concat(completionName, new char[] { ';' }); >+ } > } else { > completionName = CharOperation.concat(completionName, new char[] { ';' }); > } >+ >+ int relevance = computeBaseRelevance(); >+ relevance += computeRelevanceForResolution(); >+ relevance += computeRelevanceForInterestingProposal(); >+ relevance += computeRelevanceForRestrictions(accessibility); >+ relevance += computeRelevanceForCaseMatching(this.completionToken, simpleTypeName); >+ >+ this.noProposal = false; >+ if(!this.requestor.isIgnored(CompletionProposal.TYPE_REF)) { >+ createTypeProposal(packageName, typeName, modifiers, accessibility, completionName, relevance); >+ } > } else { >- completionName = CharOperation.concat(completionName, new char[] { ';' }); >- } >- >- int relevance = computeBaseRelevance(); >- relevance += computeRelevanceForResolution(); >- relevance += computeRelevanceForInterestingProposal(); >- relevance += computeRelevanceForRestrictions(accessibility); >- relevance += computeRelevanceForCaseMatching(this.completionToken, simpleTypeName); >- >- this.noProposal = false; >- if(!this.requestor.isIgnored(CompletionProposal.TYPE_REF)) { >- createTypeProposal(packageName, typeName, modifiers, accessibility, completionName, relevance); >- } >- } else { >- if(!this.importCachesInitialized) { >- initializeImportCaches(); >- } >- >- for (int j = 0; j < this.importCacheCount; j++) { >- char[][] importName = this.importsCache[j]; >- if(CharOperation.equals(typeName, importName[0])) { >+ if(!this.importCachesInitialized) { >+ initializeImportCaches(); >+ } >+ >+ for (int j = 0; j < this.importCacheCount; j++) { >+ char[][] importName = this.importsCache[j]; >+ if(CharOperation.equals(typeName, importName[0])) { >+ proposeType( >+ packageName, >+ simpleTypeName, >+ modifiers, >+ accessibility, >+ typeName, >+ fullyQualifiedName, >+ !CharOperation.equals(fullyQualifiedName, importName[1]), >+ scope); >+ continue next; >+ } >+ } >+ >+ >+ if ((enclosingTypeNames == null || enclosingTypeNames.length == 0 ) && CharOperation.equals(this.currentPackageName, packageName)) { > proposeType( > packageName, > simpleTypeName, >@@ -557,50 +714,43 @@ > accessibility, > typeName, > fullyQualifiedName, >- !CharOperation.equals(fullyQualifiedName, importName[1]), >+ false, > scope); > continue next; >- } >- } >- >- >- if ((enclosingTypeNames == null || enclosingTypeNames.length == 0 ) && CharOperation.equals(this.currentPackageName, packageName)) { >- proposeType( >- packageName, >- simpleTypeName, >- modifiers, >- accessibility, >- typeName, >- fullyQualifiedName, >- false, >- scope); >- continue next; >- } else { >- char[] fullyQualifiedEnclosingTypeOrPackageName = null; >- >- AcceptedType foundType = null; >- if((foundType = (AcceptedType)onDemandFound.get(simpleTypeName)) == null) { >- for (int j = 0; j < this.onDemandImportCacheCount; j++) { >- ImportBinding importBinding = this.onDemandImportsCache[j]; >- >- char[][] importName = importBinding.compoundName; >- char[] importFlatName = CharOperation.concatWith(importName, '.'); >- >- if(fullyQualifiedEnclosingTypeOrPackageName == null) { >- if(enclosingTypeNames != null && enclosingTypeNames.length != 0) { >- fullyQualifiedEnclosingTypeOrPackageName = >- CharOperation.concat( >- packageName, >- flatEnclosingTypeNames, >- '.'); >- } else { >- fullyQualifiedEnclosingTypeOrPackageName = >- packageName; >+ } else { >+ char[] fullyQualifiedEnclosingTypeOrPackageName = null; >+ >+ AcceptedType foundType = null; >+ if((foundType = (AcceptedType)onDemandFound.get(simpleTypeName)) == null) { >+ for (int j = 0; j < this.onDemandImportCacheCount; j++) { >+ ImportBinding importBinding = this.onDemandImportsCache[j]; >+ >+ char[][] importName = importBinding.compoundName; >+ char[] importFlatName = CharOperation.concatWith(importName, '.'); >+ >+ if(fullyQualifiedEnclosingTypeOrPackageName == null) { >+ if(enclosingTypeNames != null && enclosingTypeNames.length != 0) { >+ fullyQualifiedEnclosingTypeOrPackageName = >+ CharOperation.concat( >+ packageName, >+ flatEnclosingTypeNames, >+ '.'); >+ } else { >+ fullyQualifiedEnclosingTypeOrPackageName = >+ packageName; >+ } > } >- } >- if(CharOperation.equals(fullyQualifiedEnclosingTypeOrPackageName, importFlatName)) { >- if(importBinding.isStatic()) { >- if((modifiers & ClassFileConstants.AccStatic) != 0) { >+ if(CharOperation.equals(fullyQualifiedEnclosingTypeOrPackageName, importFlatName)) { >+ if(importBinding.isStatic()) { >+ if((modifiers & ClassFileConstants.AccStatic) != 0) { >+ acceptedType.qualifiedTypeName = typeName; >+ acceptedType.fullyQualifiedName = fullyQualifiedName; >+ onDemandFound.put( >+ simpleTypeName, >+ acceptedType); >+ continue next; >+ } >+ } else { > acceptedType.qualifiedTypeName = typeName; > acceptedType.fullyQualifiedName = fullyQualifiedName; > onDemandFound.put( >@@ -608,82 +758,77 @@ > acceptedType); > continue next; > } >- } else { >- acceptedType.qualifiedTypeName = typeName; >- acceptedType.fullyQualifiedName = fullyQualifiedName; >- onDemandFound.put( >- simpleTypeName, >- acceptedType); >- continue next; > } > } >- } >- } else if(!foundType.mustBeQualified){ >- done : for (int j = 0; j < this.onDemandImportCacheCount; j++) { >- ImportBinding importBinding = this.onDemandImportsCache[j]; >- >- char[][] importName = importBinding.compoundName; >- char[] importFlatName = CharOperation.concatWith(importName, '.'); >- >- if(fullyQualifiedEnclosingTypeOrPackageName == null) { >- if(enclosingTypeNames != null && enclosingTypeNames.length != 0) { >- fullyQualifiedEnclosingTypeOrPackageName = >- CharOperation.concat( >- packageName, >- flatEnclosingTypeNames, >- '.'); >- } else { >- fullyQualifiedEnclosingTypeOrPackageName = >- packageName; >+ } else if(!foundType.mustBeQualified){ >+ done : for (int j = 0; j < this.onDemandImportCacheCount; j++) { >+ ImportBinding importBinding = this.onDemandImportsCache[j]; >+ >+ char[][] importName = importBinding.compoundName; >+ char[] importFlatName = CharOperation.concatWith(importName, '.'); >+ >+ if(fullyQualifiedEnclosingTypeOrPackageName == null) { >+ if(enclosingTypeNames != null && enclosingTypeNames.length != 0) { >+ fullyQualifiedEnclosingTypeOrPackageName = >+ CharOperation.concat( >+ packageName, >+ flatEnclosingTypeNames, >+ '.'); >+ } else { >+ fullyQualifiedEnclosingTypeOrPackageName = >+ packageName; >+ } > } >- } >- if(CharOperation.equals(fullyQualifiedEnclosingTypeOrPackageName, importFlatName)) { >- if(importBinding.isStatic()) { >- if((modifiers & ClassFileConstants.AccStatic) != 0) { >+ if(CharOperation.equals(fullyQualifiedEnclosingTypeOrPackageName, importFlatName)) { >+ if(importBinding.isStatic()) { >+ if((modifiers & ClassFileConstants.AccStatic) != 0) { >+ foundType.mustBeQualified = true; >+ break done; >+ } >+ } else { > foundType.mustBeQualified = true; > break done; > } >- } else { >- foundType.mustBeQualified = true; >- break done; > } > } > } >+ proposeType( >+ packageName, >+ simpleTypeName, >+ modifiers, >+ accessibility, >+ typeName, >+ fullyQualifiedName, >+ true, >+ scope); > } >- proposeType( >- packageName, >- simpleTypeName, >- modifiers, >- accessibility, >- typeName, >- fullyQualifiedName, >- true, >- scope); > } > } >- } >- char[][] keys = onDemandFound.keyTable; >- Object[] values = onDemandFound.valueTable; >- int max = keys.length; >- for (int i = 0; i < max; i++) { >- if(keys[i] != null) { >- AcceptedType value = (AcceptedType) values[i]; >- if(value != null) { >- proposeType( >- value.packageName, >- value.simpleTypeName, >- value.modifiers, >- value.accessibility, >- value.qualifiedTypeName, >- value.fullyQualifiedName, >- value.mustBeQualified, >- scope); >+ >+ char[][] keys = onDemandFound.keyTable; >+ Object[] values = onDemandFound.valueTable; >+ int max = keys.length; >+ for (int i = 0; i < max; i++) { >+ if(keys[i] != null) { >+ AcceptedType value = (AcceptedType) values[i]; >+ if(value != null) { >+ proposeType( >+ value.packageName, >+ value.simpleTypeName, >+ value.modifiers, >+ value.accessibility, >+ value.qualifiedTypeName, >+ value.fullyQualifiedName, >+ value.mustBeQualified, >+ scope); >+ } > } > } >+ } finally { >+ this.acceptedTypes = null; // reset > } >- this.acceptedTypes = null; // reset > } >- >+ > public void acceptUnresolvedName(char[] name) { > int relevance = computeBaseRelevance(); > relevance += computeRelevanceForResolution(false); >@@ -709,6 +854,41 @@ > } > } > } >+ private void addExpectedType(TypeBinding type, Scope scope){ >+ if (type == null || !type.isValidBinding() || type == TypeBinding.NULL) return; >+ >+ // do not add twice the same type >+ for (int i = 0; i <= this.expectedTypesPtr; i++) { >+ if (this.expectedTypes[i] == type) return; >+ } >+ >+ int length = this.expectedTypes.length; >+ if (++this.expectedTypesPtr >= length) >+ System.arraycopy(this.expectedTypes, 0, this.expectedTypes = new TypeBinding[length * 2], 0, length); >+ this.expectedTypes[this.expectedTypesPtr] = type; >+ >+ if(type == scope.getJavaLangObject()) { >+ this.hasJavaLangObjectAsExpectedType = true; >+ } >+ } >+ >+ private void addForbiddenBindings(Binding binding){ >+ if (binding == null) return; >+ >+ int length = this.forbbidenBindings.length; >+ if (++this.forbbidenBindingsPtr >= length) >+ System.arraycopy(this.forbbidenBindings, 0, this.forbbidenBindings = new Binding[length * 2], 0, length); >+ this.forbbidenBindings[this.forbbidenBindingsPtr] = binding; >+ } >+ >+ private void addUninterestingBindings(Binding binding){ >+ if (binding == null) return; >+ >+ int length = this.uninterestingBindings.length; >+ if (++this.uninterestingBindingsPtr >= length) >+ System.arraycopy(this.uninterestingBindings, 0, this.uninterestingBindings = new Binding[length * 2], 0, length); >+ this.uninterestingBindings[this.uninterestingBindingsPtr] = binding; >+ } > > // this code is derived from MethodBinding#areParametersCompatibleWith(TypeBinding[]) > private final boolean areParametersCompatibleWith(TypeBinding[] parameters, TypeBinding[] arguments, boolean isVarargs) { >@@ -741,127 +921,6 @@ > return true; > } > >- private void proposeType(char[] packageName, char[] simpleTypeName, int modifiers, int accessibility, char[] typeName, char[] fullyQualifiedName, boolean isQualified, Scope scope) { >- char[] completionName = fullyQualifiedName; >- if(isQualified) { >- if (packageName == null || packageName.length == 0) >- if (this.unitScope != null && this.unitScope.fPackage.compoundName != CharOperation.NO_CHAR_CHAR) >- return; // ignore types from the default package from outside it >- } else { >- completionName = simpleTypeName; >- } >- >- TypeBinding guessedType = null; >- if ((modifiers & ClassFileConstants.AccAnnotation) != 0 && >- this.assistNodeIsAnnotation && >- (this.targetedElement & TagBits.AnnotationTargetMASK) != 0) { >- char[][] cn = CharOperation.splitOn('.', fullyQualifiedName); >- >- TypeReference ref; >- if (cn.length == 1) { >- ref = new SingleTypeReference(simpleTypeName, 0); >- } else { >- ref = new QualifiedTypeReference(cn,new long[cn.length]); >- } >- >- switch (scope.kind) { >- case Scope.METHOD_SCOPE : >- case Scope.BLOCK_SCOPE : >- guessedType = ref.resolveType((BlockScope)scope); >- break; >- case Scope.CLASS_SCOPE : >- guessedType = ref.resolveType((ClassScope)scope); >- break; >- } >- >- if (guessedType == null || !guessedType.isValidBinding()) return; >- >- if (!hasPossibleAnnotationTarget(guessedType, scope)) return; >- } >- >- int relevance = computeBaseRelevance(); >- relevance += computeRelevanceForResolution(); >- relevance += computeRelevanceForInterestingProposal(); >- relevance += computeRelevanceForRestrictions(accessibility); >- relevance += computeRelevanceForCaseMatching(this.completionToken, simpleTypeName); >- relevance += computeRelevanceForExpectingType(packageName, simpleTypeName); >- relevance += computeRelevanceForQualification(isQualified); >- >- int kind = modifiers & (ClassFileConstants.AccInterface | ClassFileConstants.AccEnum | ClassFileConstants.AccAnnotation); >- switch (kind) { >- case ClassFileConstants.AccAnnotation: >- case ClassFileConstants.AccAnnotation | ClassFileConstants.AccInterface: >- relevance += computeRelevanceForAnnotation(); >- if (guessedType != null) relevance += computeRelevanceForAnnotationTarget(guessedType); >- relevance += computeRelevanceForInterface(); >- break; >- case ClassFileConstants.AccEnum: >- relevance += computeRelevanceForEnum(); >- break; >- case ClassFileConstants.AccInterface: >- relevance += computeRelevanceForInterface(); >- break; >- default: >- relevance += computeRelevanceForClass(); >- relevance += computeRelevanceForException(simpleTypeName); >- break; >- } >- >- this.noProposal = false; >- if(!this.requestor.isIgnored(CompletionProposal.TYPE_REF)) { >- createTypeProposal(packageName, typeName, modifiers, accessibility, completionName, relevance); >- } >- } >- >- /** >- * One result of the search consists of a new package. >- * >- * NOTE - All package names are presented in their readable form: >- * Package names are in the form "a.b.c". >- * The default package is represented by an empty array. >- */ >- public void acceptPackage(char[] packageName) { >- >- if (this.knownPkgs.containsKey(packageName)) return; >- >- this.knownPkgs.put(packageName, this); >- >- char[] completion; >- if(this.resolvingImports) { >- if(this.resolvingStaticImports) { >- completion = CharOperation.concat(packageName, new char[] { '.' }); >- } else { >- completion = CharOperation.concat(packageName, new char[] { '.', '*', ';' }); >- } >- } else { >- completion = packageName; >- } >- >- int relevance = computeBaseRelevance(); >- relevance += computeRelevanceForResolution(); >- relevance += computeRelevanceForInterestingProposal(); >- relevance += computeRelevanceForCaseMatching(this.qualifiedCompletionToken == null ? this.completionToken : this.qualifiedCompletionToken, packageName); >- if(!this.resolvingImports) { >- relevance += computeRelevanceForQualification(true); >- } >- relevance += computeRelevanceForRestrictions(IAccessRule.K_ACCESSIBLE); >- >- this.noProposal = false; >- if(!this.requestor.isIgnored(CompletionProposal.PACKAGE_REF)) { >- InternalCompletionProposal proposal = createProposal(CompletionProposal.PACKAGE_REF, this.actualCompletionPosition); >- proposal.setDeclarationSignature(packageName); >- proposal.setPackageName(packageName); >- proposal.setCompletion(completion); >- proposal.setReplaceRange(this.startPosition - this.offset, this.endPosition - this.offset); >- proposal.setTokenRange(this.tokenStart - this.offset, this.tokenEnd - this.offset); >- proposal.setRelevance(relevance); >- this.requestor.accept(proposal); >- if(DEBUG) { >- this.printDebug(proposal); >- } >- } >- } >- > private void buildContext( > ASTNode astNode, > ASTNode astNodeParent, >@@ -991,6 +1050,12 @@ > } > } > >+ private void checkCancel() { >+ if (this.monitor != null && this.monitor.isCanceled()) { >+ throw new OperationCanceledException(); >+ } >+ } >+ > private boolean complete( > ASTNode astNode, > ASTNode astNodeParent, >@@ -1012,501 +1077,600 @@ > buildContext(astNode, astNodeParent, compilationUnitDeclaration, qualifiedBinding, scope); > > if (astNode instanceof CompletionOnFieldType) { >- >- CompletionOnFieldType field = (CompletionOnFieldType) astNode; >- CompletionOnSingleTypeReference type = (CompletionOnSingleTypeReference) field.type; >- this.completionToken = type.token; >- setSourceAndTokenRange(type.sourceStart, type.sourceEnd); >- >- findTypesAndPackages(this.completionToken, scope, true, true, new ObjectVector()); >- if (!this.requestor.isIgnored(CompletionProposal.KEYWORD)) { >- findKeywordsForMember(this.completionToken, field.modifiers); >- } >- >- if (!field.isLocalVariable && field.modifiers == ClassFileConstants.AccDefault) { >- SourceTypeBinding enclosingType = scope.enclosingSourceType(); >- if (!enclosingType.isAnnotationType()) { >- if (!this.requestor.isIgnored(CompletionProposal.METHOD_DECLARATION)) { >- findMethods( >- this.completionToken, >- null, >- null, >- enclosingType, >- scope, >- new ObjectVector(), >- false, >- false, >- true, >- null, >- null, >- false, >- false, >- true, >- null, >- null, >- null, >- false, >- null, >- -1, >- -1); >- } >- if (!this.requestor.isIgnored(CompletionProposal.POTENTIAL_METHOD_DECLARATION)) { >- proposeNewMethod(this.completionToken, enclosingType); >- } >- } >- } >+ completionOnFieldType(astNode, scope); > } else if (astNode instanceof CompletionOnMethodReturnType) { >- >- CompletionOnMethodReturnType method = (CompletionOnMethodReturnType) astNode; >- SingleTypeReference type = (CompletionOnSingleTypeReference) method.returnType; >- this.completionToken = type.token; >- setSourceAndTokenRange(type.sourceStart, type.sourceEnd); >- findTypesAndPackages(this.completionToken, scope.parent, true, true, new ObjectVector()); >- if (!this.requestor.isIgnored(CompletionProposal.KEYWORD)) { >- findKeywordsForMember(this.completionToken, method.modifiers); >+ completionOnMethodReturnType(astNode, scope); >+ } else if (astNode instanceof CompletionOnSingleNameReference) { >+ completionOnSingleNameReference(astNode, astNodeParent, scope, insideTypeAnnotation); >+ } else if (astNode instanceof CompletionOnSingleTypeReference) { >+ completionOnSingleTypeReference(astNode, astNodeParent, qualifiedBinding, scope); >+ } else if (astNode instanceof CompletionOnQualifiedNameReference) { >+ completionOnQualifiedNameReference(astNode, enclosingNode, qualifiedBinding, scope, insideTypeAnnotation); >+ } else if (astNode instanceof CompletionOnQualifiedTypeReference) { >+ completionOnQualifiedTypeReference(astNode, astNodeParent, qualifiedBinding, scope); >+ } else if (astNode instanceof CompletionOnMemberAccess) { >+ completionOnMemberAccess(astNode, enclosingNode, qualifiedBinding, scope, insideTypeAnnotation); >+ } else if (astNode instanceof CompletionOnMessageSend) { >+ completionOnMessageSend(astNode, qualifiedBinding, scope); >+ } else if (astNode instanceof CompletionOnExplicitConstructorCall) { >+ completionOnExplicitConstructorCall(astNode, qualifiedBinding, scope); >+ } else if (astNode instanceof CompletionOnQualifiedAllocationExpression) { >+ completionOnQualifiedAllocationExpression(astNode, qualifiedBinding, scope); >+ } else if (astNode instanceof CompletionOnClassLiteralAccess) { >+ completionOnClassLiteralAccess(astNode, qualifiedBinding, scope); >+ } else if (astNode instanceof CompletionOnMethodName) { >+ completionOnMethodName(astNode, scope); >+ } else if (astNode instanceof CompletionOnFieldName) { >+ completionOnFieldName(astNode, scope); >+ } else if (astNode instanceof CompletionOnLocalName) { >+ completionOnLocalOrArgumentName(astNode, scope); >+ } else if (astNode instanceof CompletionOnArgumentName) { >+ completionOnLocalOrArgumentName(astNode, scope); >+ } else if (astNode instanceof CompletionOnKeyword) { >+ completionOnKeyword(astNode); >+ } else if (astNode instanceof CompletionOnParameterizedQualifiedTypeReference) { >+ completionOnParameterizedQualifiedTypeReference(astNode, astNodeParent, qualifiedBinding, scope); >+ } else if (astNode instanceof CompletionOnMarkerAnnotationName) { >+ completionOnMarkerAnnotationName(astNode, qualifiedBinding, scope); >+ } else if (astNode instanceof CompletionOnMemberValueName) { >+ completionOnMemberValueName(astNode, astNodeParent, scope, insideTypeAnnotation); >+ } else if(astNode instanceof CompletionOnBranchStatementLabel) { >+ completionOnBranchStatementLabel(astNode); >+ } else if(astNode instanceof CompletionOnMessageSendName) { >+ completionOnMessageSendName(astNode, qualifiedBinding, scope); >+ // Completion on Javadoc nodes >+ } else if ((astNode.bits & ASTNode.InsideJavadoc) != 0) { >+ if (astNode instanceof CompletionOnJavadocSingleTypeReference) { >+ completionOnJavadocSingleTypeReference(astNode, scope); >+ } else if (astNode instanceof CompletionOnJavadocQualifiedTypeReference) { >+ completionOnJavadocQualifiedTypeReference(astNode, qualifiedBinding, scope); >+ } else if (astNode instanceof CompletionOnJavadocFieldReference) { >+ completionOnJavadocFieldReference(astNode, scope); >+ } else if (astNode instanceof CompletionOnJavadocMessageSend) { >+ completionOnJavadocMessageSend(astNode, qualifiedBinding, scope); >+ } else if (astNode instanceof CompletionOnJavadocAllocationExpression) { >+ completionOnJavadocAllocationExpression(astNode, qualifiedBinding, scope); >+ } else if (astNode instanceof CompletionOnJavadocParamNameReference) { >+ completionOnJavadocParamNameReference(astNode); >+ } else if (astNode instanceof CompletionOnJavadocTypeParamReference) { >+ completionOnJavadocTypeParamReference(astNode); >+ } else if (astNode instanceof CompletionOnJavadocTag) { >+ completionOnJavadocTag(astNode); > } >+ } >+ return true; >+ } > >- if (method.modifiers == ClassFileConstants.AccDefault) { >- SourceTypeBinding enclosingType = scope.enclosingSourceType(); >- if (!enclosingType.isAnnotationType()) { >- if (!this.requestor.isIgnored(CompletionProposal.METHOD_DECLARATION)) { >- findMethods( >- this.completionToken, >- null,null, >- scope.enclosingSourceType(), >- scope, >- new ObjectVector(), >- false, >- false, >- true, >- null, >- null, >- false, >- false, >- true, >- null, >- null, >- null, >- false, >- null, >- -1, >- -1); >- } >- if (!this.requestor.isIgnored(CompletionProposal.POTENTIAL_METHOD_DECLARATION)) { >- proposeNewMethod(this.completionToken, scope.enclosingSourceType()); >- } >- } >- } >- } else if (astNode instanceof CompletionOnSingleNameReference) { >+ /** >+ * Ask the engine to compute a completion at the specified position >+ * of the given compilation unit. >+ * >+ * No return >+ * completion results are answered through a requestor. >+ * >+ * @param sourceUnit org.eclipse.jdt.internal.compiler.env.ICompilationUnit >+ * the source of the current compilation unit. >+ * >+ * @param completionPosition int >+ * a position in the source where the completion is taking place. >+ * This position is relative to the source provided. >+ */ >+ public void complete(ICompilationUnit sourceUnit, int completionPosition, int pos, ITypeRoot root) { > >- CompletionOnSingleNameReference singleNameReference = (CompletionOnSingleNameReference) astNode; >- this.completionToken = singleNameReference.token; >- SwitchStatement switchStatement = astNodeParent instanceof SwitchStatement ? (SwitchStatement) astNodeParent : null; >- if (switchStatement != null >- && switchStatement.expression.resolvedType != null >- && switchStatement.expression.resolvedType.isEnum()) { >- if (!this.requestor.isIgnored(CompletionProposal.FIELD_REF)) { >- this.assistNodeIsEnum = true; >- findEnumConstantsFromSwithStatement(this.completionToken, (SwitchStatement) astNodeParent); >- } >- } else if (this.expectedTypesPtr > -1 && this.expectedTypes[0].isAnnotationType()) { >- findTypesAndPackages(this.completionToken, scope, false, false, new ObjectVector()); >- } else { >- if (this.expectedTypesPtr > -1) { >- this.assistNodeIsEnum = true; >- done : for (int i = 0; i <= this.expectedTypesPtr; i++) { >- if (!this.expectedTypes[i].isEnum()) { >- this.assistNodeIsEnum = false; >- break done; >- } >- } >+ if(DEBUG) { >+ System.out.print("COMPLETION IN "); //$NON-NLS-1$ >+ System.out.print(sourceUnit.getFileName()); >+ System.out.print(" AT POSITION "); //$NON-NLS-1$ >+ System.out.println(completionPosition); >+ System.out.println("COMPLETION - Source :"); //$NON-NLS-1$ >+ System.out.println(sourceUnit.getContents()); >+ } >+ if (this.monitor != null) this.monitor.beginTask(Messages.engine_completing, IProgressMonitor.UNKNOWN); >+ this.requestor.beginReporting(); >+ boolean contextAccepted = false; >+ try { >+ this.fileName = sourceUnit.getFileName(); >+ this.actualCompletionPosition = completionPosition - 1; >+ this.offset = pos; >+ this.typeRoot = root; >+ >+ this.checkCancel(); >+ >+ // for now until we can change the UI. >+ CompilationResult result = new CompilationResult(sourceUnit, 1, 1, this.compilerOptions.maxProblemsPerUnit); >+ CompilationUnitDeclaration parsedUnit = this.parser.dietParse(sourceUnit, result, this.actualCompletionPosition); > >+ // boolean completionNodeFound = false; >+ if (parsedUnit != null) { >+ if(DEBUG) { >+ System.out.println("COMPLETION - Diet AST :"); //$NON-NLS-1$ >+ System.out.println(parsedUnit.toString()); > } >- if (scope instanceof BlockScope && !this.requestor.isIgnored(CompletionProposal.LOCAL_VARIABLE_REF)) { >- char[][] alreadyDefinedName = computeAlreadyDefinedName((BlockScope)scope, singleNameReference); > >- findUnresolvedReference( >- singleNameReference.sourceStart, >- singleNameReference.sourceEnd, >- (BlockScope)scope, >- alreadyDefinedName); >- } >- findVariablesAndMethods( >- this.completionToken, >- scope, >- singleNameReference, >- scope, >- insideTypeAnnotation, >- singleNameReference.isInsideAnnotationAttribute); >- // can be the start of a qualified type name >- findTypesAndPackages(this.completionToken, scope, true, false, new ObjectVector()); >- if (!this.requestor.isIgnored(CompletionProposal.KEYWORD)) { >- if (this.completionToken != null && this.completionToken.length != 0) { >- findKeywords(this.completionToken, singleNameReference.possibleKeywords, false, false); >- } else { >- findTrueOrFalseKeywords(singleNameReference.possibleKeywords); >+ // scan the package & import statements first >+ if (parsedUnit.currentPackage instanceof CompletionOnPackageReference) { >+ contextAccepted = true; >+ buildContext(parsedUnit.currentPackage, null, parsedUnit, null, null); >+ if(!this.requestor.isIgnored(CompletionProposal.PACKAGE_REF)) { >+ findPackages((CompletionOnPackageReference) parsedUnit.currentPackage); > } >- } >- if (singleNameReference.canBeExplicitConstructor && !this.requestor.isIgnored(CompletionProposal.METHOD_REF)){ >- if (CharOperation.prefixEquals(this.completionToken, Keywords.THIS, false)) { >- ReferenceBinding ref = scope.enclosingSourceType(); >- findExplicitConstructors(Keywords.THIS, ref, (MethodScope)scope, singleNameReference); >- } else if (CharOperation.prefixEquals(this.completionToken, Keywords.SUPER, false)) { >- ReferenceBinding ref = scope.enclosingSourceType(); >- findExplicitConstructors(Keywords.SUPER, ref.superclass(), (MethodScope)scope, singleNameReference); >+ if(this.noProposal && this.problem != null) { >+ this.requestor.completionFailure(this.problem); >+ if(DEBUG) { >+ this.printDebug(this.problem); >+ } > } >+ return; > } >- } >- >- } else if (astNode instanceof CompletionOnSingleTypeReference) { > >- CompletionOnSingleTypeReference singleRef = (CompletionOnSingleTypeReference) astNode; >- >- this.completionToken = singleRef.token; >- >- this.assistNodeIsClass = singleRef.isClass(); >- this.assistNodeIsException = singleRef.isException(); >- this.assistNodeIsInterface = singleRef.isInterface(); >- this.assistNodeIsConstructor = singleRef.isConstructorType; >- this.assistNodeIsSuperType = singleRef.isSuperType(); >- >- // can be the start of a qualified type name >- if (qualifiedBinding == null) { >- if (this.completionToken.length == 0 && >- (astNodeParent instanceof ParameterizedSingleTypeReference || >- astNodeParent instanceof ParameterizedQualifiedTypeReference)) { >- this.setSourceAndTokenRange(astNode.sourceStart, astNode.sourceStart - 1, false); >+ ImportReference[] imports = parsedUnit.imports; >+ if (imports != null) { >+ for (int i = 0, length = imports.length; i < length; i++) { >+ ImportReference importReference = imports[i]; >+ if (importReference instanceof CompletionOnImportReference) { >+ this.lookupEnvironment.buildTypeBindings(parsedUnit, null /*no access restriction*/); >+ if ((this.unitScope = parsedUnit.scope) != null) { >+ contextAccepted = true; >+ buildContext(importReference, null, parsedUnit, null, null); > >- findParameterizedType((TypeReference)astNodeParent, scope); >- } else { >- ObjectVector typesFound = new ObjectVector(); >- if (this.assistNodeIsException && astNodeParent instanceof TryStatement) { >- findExceptionFromTryStatement( >- this.completionToken, >- null, >- scope.enclosingSourceType(), >- (BlockScope)scope, >- typesFound); >- } >- findTypesAndPackages(this.completionToken, scope, this.assistNodeIsConstructor, false, typesFound); >- } >- } else if (!this.requestor.isIgnored(CompletionProposal.TYPE_REF)) { >- findMemberTypes( >- this.completionToken, >- (ReferenceBinding) qualifiedBinding, >- scope, >- scope.enclosingSourceType(), >- false, >- false, >- false, >- false, >- !this.assistNodeIsConstructor, >- null, >- new ObjectVector(), >- null, >- null, >- null, >- false); >- } >- } else if (astNode instanceof CompletionOnQualifiedNameReference) { >+ long positions = importReference.sourcePositions[importReference.sourcePositions.length - 1]; >+ setSourceAndTokenRange((int) (positions >>> 32), (int) positions); > >- this.insideQualifiedReference = true; >- CompletionOnQualifiedNameReference ref = >- (CompletionOnQualifiedNameReference) astNode; >- this.completionToken = ref.completionIdentifier; >- long completionPosition = ref.sourcePositions[ref.sourcePositions.length - 1]; >+ char[][] oldTokens = importReference.tokens; >+ int tokenCount = oldTokens.length; >+ if (tokenCount == 1) { >+ findImports((CompletionOnImportReference)importReference, true); >+ } else if(tokenCount > 1){ >+ this.insideQualifiedReference = true; > >- if (qualifiedBinding.problemId() == ProblemReasons.NotFound) { >- setSourceAndTokenRange((int) (completionPosition >>> 32), (int) completionPosition); >- // complete field members with missing fields type >- // class X { >- // Missing f; >- // void foo() { >- // f.| >- // } >- // } >- if (this.assistNodeInJavadoc == 0 && >- (this.requestor.isAllowingRequiredProposals(CompletionProposal.FIELD_REF, CompletionProposal.TYPE_REF) || >- this.requestor.isAllowingRequiredProposals(CompletionProposal.METHOD_REF, CompletionProposal.TYPE_REF) || >- this.requestor.isAllowingRequiredProposals(CompletionProposal.TYPE_REF, CompletionProposal.TYPE_REF))) { >- if(ref.tokens.length == 1) { >- boolean foundSomeFields = findFieldsAndMethodsFromMissingFieldType(ref.tokens[0], scope, ref, insideTypeAnnotation); >+ char[] lastToken = oldTokens[tokenCount - 1]; >+ char[][] qualifierTokens = CharOperation.subarray(oldTokens, 0, tokenCount - 1); > >- if (!foundSomeFields) { >- findMembersFromMissingType( >- ref.tokens[0], >- ref.sourcePositions[0], >- null, >- scope, >- ref, >- ref.isInsideAnnotationAttribute); >- } >- } >- } >- } else if (qualifiedBinding instanceof VariableBinding) { >- setSourceAndTokenRange((int) (completionPosition >>> 32), (int) completionPosition); >- TypeBinding receiverType = ((VariableBinding) qualifiedBinding).type; >- if (receiverType != null && (receiverType.tagBits & TagBits.HasMissingType) == 0) { >- ObjectVector fieldsFound = new ObjectVector(); >- ObjectVector methodsFound = new ObjectVector(); >+ Binding binding = this.unitScope.getTypeOrPackage(qualifierTokens); >+ if(binding != null) { >+ if(binding instanceof PackageBinding) { >+ findImports((CompletionOnImportReference)importReference, false); >+ } else { >+ ReferenceBinding ref = (ReferenceBinding) binding; > >- findFieldsAndMethods( >- this.completionToken, >- receiverType.capture(scope, ref.sourceEnd), >- scope, >- fieldsFound, >- methodsFound, >- ref, >- scope, >- false, >- false, >- null, >- null, >- null, >- false, >- null, >- -1, >- -1); >+ if(!this.requestor.isIgnored(CompletionProposal.TYPE_REF)) { >+ findImportsOfMemberTypes(lastToken, ref, importReference.isStatic()); >+ } >+ if(importReference.isStatic()) { > >- findFieldsAndMethodsFromCastedReceiver( >- enclosingNode, >- qualifiedBinding, >- scope, >- fieldsFound, >- methodsFound, >- ref, >- scope, >- ref); >+ if(!this.requestor.isIgnored(CompletionProposal.FIELD_REF)) { >+ findImportsOfStaticFields(lastToken, ref); >+ } >+ if(!this.requestor.isIgnored(CompletionProposal.METHOD_NAME_REFERENCE)) { >+ findImportsOfStaticMethods(lastToken, ref); >+ } >+ } >+ } >+ } >+ } > >- } else if (this.assistNodeInJavadoc == 0 && >- (this.requestor.isAllowingRequiredProposals(CompletionProposal.FIELD_REF, CompletionProposal.TYPE_REF) || >- this.requestor.isAllowingRequiredProposals(CompletionProposal.METHOD_REF, CompletionProposal.TYPE_REF))) { >- boolean proposeField = !this.requestor.isIgnored(CompletionProposal.FIELD_REF); >- boolean proposeMethod = !this.requestor.isIgnored(CompletionProposal.METHOD_REF); >- if (proposeField || proposeMethod) { >- if(ref.tokens.length == 1) { >- if (qualifiedBinding instanceof LocalVariableBinding) { >- // complete local variable members with missing variables type >- // class X { >- // void foo() { >- // Missing f; >- // f.| >- // } >- // } >- LocalVariableBinding localVariableBinding = (LocalVariableBinding) qualifiedBinding; >- findFieldsAndMethodsFromMissingType( >- localVariableBinding.declaration.type, >- localVariableBinding.declaringScope, >- ref, >- scope); >- } else { >- // complete field members with missing fields type >- // class X { >- // Missing f; >- // void foo() { >- // f.| >- // } >- // } >- findFieldsAndMethodsFromMissingFieldType(ref.tokens[0], scope, ref, insideTypeAnnotation); >+ if(this.noProposal && this.problem != null) { >+ this.requestor.completionFailure(this.problem); >+ if(DEBUG) { >+ this.printDebug(this.problem); >+ } >+ } > } >- >+ return; >+ } else if(importReference instanceof CompletionOnKeyword) { >+ contextAccepted = true; >+ buildContext(importReference, null, parsedUnit, null, null); >+ if(!this.requestor.isIgnored(CompletionProposal.KEYWORD)) { >+ setSourceAndTokenRange(importReference.sourceStart, importReference.sourceEnd); >+ CompletionOnKeyword keyword = (CompletionOnKeyword)importReference; >+ findKeywords(keyword.getToken(), keyword.getPossibleKeywords(), false, false); >+ } >+ if(this.noProposal && this.problem != null) { >+ this.requestor.completionFailure(this.problem); >+ if(DEBUG) { >+ this.printDebug(this.problem); >+ } >+ } >+ return; > } > } > } > >- } else if (qualifiedBinding instanceof ReferenceBinding && !(qualifiedBinding instanceof TypeVariableBinding)) { >- boolean isInsideAnnotationAttribute = ref.isInsideAnnotationAttribute; >- ReferenceBinding receiverType = (ReferenceBinding) qualifiedBinding; >- setSourceAndTokenRange((int) (completionPosition >>> 32), (int) completionPosition); >+ if (parsedUnit.types != null) { >+ try { >+ this.lookupEnvironment.buildTypeBindings(parsedUnit, null /*no access restriction*/); > >- findMembers( >- this.completionToken, >- receiverType, >- scope, >- ref, >- isInsideAnnotationAttribute, >- null, >- null, >- null, >- false); >- >- } else if (qualifiedBinding instanceof PackageBinding) { >- >- setSourceRange(astNode.sourceStart, (int) completionPosition); >- setTokenRange((int) (completionPosition >>> 32), (int) completionPosition); >+ if ((this.unitScope = parsedUnit.scope) != null) { >+ this.source = sourceUnit.getContents(); >+ this.lookupEnvironment.completeTypeBindings(parsedUnit, true); >+ parsedUnit.scope.faultInTypes(); >+ parseBlockStatements(parsedUnit, this.actualCompletionPosition); >+ if(DEBUG) { >+ System.out.println("COMPLETION - AST :"); //$NON-NLS-1$ >+ System.out.println(parsedUnit.toString()); >+ } >+ parsedUnit.resolve(); >+ } >+ } catch (CompletionNodeFound e) { >+ // completionNodeFound = true; >+ if (e.astNode != null) { >+ // if null then we found a problem in the completion node >+ if(DEBUG) { >+ System.out.print("COMPLETION - Completion node : "); //$NON-NLS-1$ >+ System.out.println(e.astNode.toString()); >+ if(this.parser.assistNodeParent != null) { >+ System.out.print("COMPLETION - Parent Node : "); //$NON-NLS-1$ >+ System.out.println(this.parser.assistNodeParent); >+ } >+ } >+ this.lookupEnvironment.unitBeingCompleted = parsedUnit; // better resilient to further error reporting >+ contextAccepted = >+ complete( >+ e.astNode, >+ this.parser.assistNodeParent, >+ this.parser.enclosingNode, >+ parsedUnit, >+ e.qualifiedBinding, >+ e.scope, >+ e.insideTypeAnnotation); >+ } >+ } >+ } >+ } > >- // replace to the end of the completion identifier >- findTypesAndSubpackages(this.completionToken, (PackageBinding) qualifiedBinding, scope); >+ if(this.noProposal && this.problem != null) { >+ if(!contextAccepted) { >+ contextAccepted = true; >+ InternalCompletionContext context = new InternalCompletionContext(); >+ context.setOffset(completionPosition - this.offset); >+ context.setTokenKind(CompletionContext.TOKEN_KIND_UNKNOWN); >+ if (this.requestor.isExtendedContextRequired()) context.setExtended(); >+ this.requestor.acceptContext(context); >+ } >+ this.requestor.completionFailure(this.problem); >+ if(DEBUG) { >+ this.printDebug(this.problem); >+ } > } >- } else if (astNode instanceof CompletionOnQualifiedTypeReference) { >+ /* Ignore package, import, class & interface keywords for now... >+ if (!completionNodeFound) { >+ if (parsedUnit == null || parsedUnit.types == null) { >+ // this is not good enough... can still be trying to define a second type >+ CompletionScanner scanner = (CompletionScanner) this.parser.scanner; >+ setSourceRange(scanner.completedIdentifierStart, scanner.completedIdentifierEnd); >+ findKeywords(scanner.completionIdentifier, mainDeclarations, null); >+ } >+ // currently have no way to know if extends/implements are possible keywords >+ } >+ */ >+ } catch (IndexOutOfBoundsException e) { // work-around internal failure - 1GEMF6D >+ if(DEBUG) { >+ System.out.println("Exception caught by CompletionEngine:"); //$NON-NLS-1$ >+ e.printStackTrace(System.out); >+ } >+ } catch (InvalidCursorLocation e) { // may eventually report a usefull error >+ if(DEBUG) { >+ System.out.println("Exception caught by CompletionEngine:"); //$NON-NLS-1$ >+ e.printStackTrace(System.out); >+ } >+ } catch (AbortCompilation e) { // ignore this exception for now since it typically means we cannot find java.lang.Object >+ if(DEBUG) { >+ System.out.println("Exception caught by CompletionEngine:"); //$NON-NLS-1$ >+ e.printStackTrace(System.out); >+ } >+ } catch (CompletionNodeFound e){ // internal failure - bugs 5618 >+ if(DEBUG) { >+ System.out.println("Exception caught by CompletionEngine:"); //$NON-NLS-1$ >+ e.printStackTrace(System.out); >+ } >+ } finally { >+ if(!contextAccepted) { >+ contextAccepted = true; >+ InternalCompletionContext context = new InternalCompletionContext(); >+ context.setTokenKind(CompletionContext.TOKEN_KIND_UNKNOWN); >+ context.setOffset(completionPosition - this.offset); >+ if (this.requestor.isExtendedContextRequired()) context.setExtended(); >+ this.requestor.acceptContext(context); >+ } >+ this.requestor.endReporting(); >+ if (this.monitor != null) this.monitor.done(); >+ reset(); >+ } >+ } > >- this.insideQualifiedReference = true; >+ public void complete(IType type, char[] snippet, int position, char[][] localVariableTypeNames, char[][] localVariableNames, int[] localVariableModifiers, boolean isStatic){ >+ if(this.requestor != null){ >+ this.requestor.beginReporting(); >+ } >+ boolean contextAccepted = false; >+ IType topLevelType = type; >+ while(topLevelType.getDeclaringType() != null) { >+ topLevelType = topLevelType.getDeclaringType(); >+ } > >- CompletionOnQualifiedTypeReference ref = >- (CompletionOnQualifiedTypeReference) astNode; >+ this.fileName = topLevelType.getParent().getElementName().toCharArray(); >+ CompilationResult compilationResult = new CompilationResult(this.fileName, 1, 1, this.compilerOptions.maxProblemsPerUnit); > >- this.assistNodeIsClass = ref.isClass(); >- this.assistNodeIsException = ref.isException(); >- this.assistNodeIsInterface = ref.isInterface(); >- this.assistNodeIsSuperType = ref.isSuperType(); >+ CompilationUnitDeclaration compilationUnit = null; > >- this.completionToken = ref.completionIdentifier; >- long completionPosition = ref.sourcePositions[ref.tokens.length]; >+ try { >+ // TypeConverter is used instead of SourceTypeConverter because the type >+ // to convert can be a binary type or a source type >+ TypeDeclaration typeDeclaration = null; >+ if (type instanceof SourceType) { >+ SourceType sourceType = (SourceType) type; >+ ISourceType info = (ISourceType) sourceType.getElementInfo(); >+ compilationUnit = SourceTypeConverter.buildCompilationUnit( >+ new ISourceType[] {info},//sourceTypes[0] is always toplevel here >+ SourceTypeConverter.FIELD_AND_METHOD // need field and methods >+ | SourceTypeConverter.MEMBER_TYPE, // need member types >+ // no need for field initialization >+ this.problemReporter, >+ compilationResult); >+ if (compilationUnit.types != null) >+ typeDeclaration = compilationUnit.types[0]; >+ } else { >+ compilationUnit = new CompilationUnitDeclaration(this.problemReporter, compilationResult, 0); >+ typeDeclaration = new BinaryTypeConverter(this.parser.problemReporter(), compilationResult, null/*no need to remember type names*/).buildTypeDeclaration(type, compilationUnit); >+ } > >- // get the source positions of the completion identifier >- if (qualifiedBinding.problemId() == ProblemReasons.NotFound) { >- setSourceAndTokenRange((int) (completionPosition >>> 32), (int) completionPosition); >- if (this.assistNodeInJavadoc == 0 && >- (this.requestor.isAllowingRequiredProposals(CompletionProposal.TYPE_REF, CompletionProposal.TYPE_REF))) { >- if(ref.tokens.length == 1) { >- findMemberTypesFromMissingType( >- ref.tokens[0], >- ref.sourcePositions[0], >- scope); >- } >- } >- } else if (qualifiedBinding instanceof ReferenceBinding && !(qualifiedBinding instanceof TypeVariableBinding)) { >- if (!this.requestor.isIgnored(CompletionProposal.TYPE_REF)) { >- setSourceAndTokenRange((int) (completionPosition >>> 32), (int) completionPosition); >- >- ObjectVector typesFound = new ObjectVector(); >- >- if (this.assistNodeIsException && astNodeParent instanceof TryStatement) { >- findExceptionFromTryStatement( >- this.completionToken, >- (ReferenceBinding)qualifiedBinding, >- scope.enclosingSourceType(), >- (BlockScope)scope, >- typesFound); >- } >+ if(typeDeclaration != null) { >+ // build AST from snippet >+ Initializer fakeInitializer = parseSnippeInitializer(snippet, position, localVariableTypeNames, localVariableNames, localVariableModifiers, isStatic); > >- findMemberTypes( >- this.completionToken, >- (ReferenceBinding) qualifiedBinding, >- scope, >- scope.enclosingSourceType(), >- false, >- false, >- typesFound, >- null, >- null, >- null, >- false); >+ // merge AST >+ FieldDeclaration[] oldFields = typeDeclaration.fields; >+ FieldDeclaration[] newFields = null; >+ if (oldFields != null) { >+ newFields = new FieldDeclaration[oldFields.length + 1]; >+ System.arraycopy(oldFields, 0, newFields, 0, oldFields.length); >+ newFields[oldFields.length] = fakeInitializer; >+ } else { >+ newFields = new FieldDeclaration[] {fakeInitializer}; > } >- } else if (qualifiedBinding instanceof PackageBinding) { >+ typeDeclaration.fields = newFields; > >- setSourceRange(astNode.sourceStart, (int) completionPosition); >- setTokenRange((int) (completionPosition >>> 32), (int) completionPosition); >- // replace to the end of the completion identifier >- findTypesAndSubpackages(this.completionToken, (PackageBinding) qualifiedBinding, scope); >- } >- } else if (astNode instanceof CompletionOnMemberAccess) { >- this.insideQualifiedReference = true; >- CompletionOnMemberAccess access = (CompletionOnMemberAccess) astNode; >- long completionPosition = access.nameSourcePosition; >- setSourceAndTokenRange((int) (completionPosition >>> 32), (int) completionPosition); >+ if(DEBUG) { >+ System.out.println("SNIPPET COMPLETION AST :"); //$NON-NLS-1$ >+ System.out.println(compilationUnit.toString()); >+ } > >- this.completionToken = access.token; >+ if (compilationUnit.types != null) { >+ try { >+ this.lookupEnvironment.buildTypeBindings(compilationUnit, null /*no access restriction*/); > >- if (qualifiedBinding.problemId() == ProblemReasons.NotFound) { >- // complete method members with missing return type >- // class X { >- // Missing f() {return null;} >- // void foo() { >- // f().| >- // } >- // } >- if (this.assistNodeInJavadoc == 0 && >- (this.requestor.isAllowingRequiredProposals(CompletionProposal.FIELD_REF, CompletionProposal.TYPE_REF) || >- this.requestor.isAllowingRequiredProposals(CompletionProposal.METHOD_REF, CompletionProposal.TYPE_REF))) { >- ProblemMethodBinding problemMethodBinding = (ProblemMethodBinding) qualifiedBinding; >- findFieldsAndMethodsFromMissingReturnType( >- problemMethodBinding.selector, >- problemMethodBinding.parameters, >- scope, >- access, >- insideTypeAnnotation); >+ if ((this.unitScope = compilationUnit.scope) != null) { >+ this.lookupEnvironment.completeTypeBindings(compilationUnit, true); >+ compilationUnit.scope.faultInTypes(); >+ compilationUnit.resolve(); >+ } >+ } catch (CompletionNodeFound e) { >+ // completionNodeFound = true; >+ if (e.astNode != null) { >+ // if null then we found a problem in the completion node >+ contextAccepted = >+ complete( >+ e.astNode, >+ this.parser.assistNodeParent, >+ this.parser.enclosingNode, >+ compilationUnit, >+ e.qualifiedBinding, >+ e.scope, >+ e.insideTypeAnnotation); >+ } >+ } > } >- } else { >- if (!access.isInsideAnnotation) { >- if (!this.requestor.isIgnored(CompletionProposal.KEYWORD)) { >- findKeywords(this.completionToken, new char[][]{Keywords.NEW}, false, false); >+ if(this.noProposal && this.problem != null) { >+ if(!contextAccepted) { >+ contextAccepted = true; >+ InternalCompletionContext context = new InternalCompletionContext(); >+ if (this.requestor.isExtendedContextRequired()) context.setExtended(); >+ this.requestor.acceptContext(context); > } >- >- ObjectVector fieldsFound = new ObjectVector(); >- ObjectVector methodsFound = new ObjectVector(); >- >- boolean superCall = access.receiver instanceof SuperReference; >- >- findFieldsAndMethods( >- this.completionToken, >- ((TypeBinding) qualifiedBinding).capture(scope, access.receiver.sourceEnd), >- scope, >- fieldsFound, >- methodsFound, >- access, >- scope, >- false, >- superCall, >- null, >- null, >- null, >- false, >- null, >- -1, >- -1); >- >- if (!superCall) { >- findFieldsAndMethodsFromCastedReceiver( >- enclosingNode, >- qualifiedBinding, >- scope, >- fieldsFound, >- methodsFound, >- access, >- scope, >- access.receiver); >+ this.requestor.completionFailure(this.problem); >+ if(DEBUG) { >+ this.printDebug(this.problem); > } > } > } >- >- } else if (astNode instanceof CompletionOnMessageSend) { >+ } catch (IndexOutOfBoundsException e) { // work-around internal failure - 1GEMF6D (added with fix of 99629) >+ if(DEBUG) { >+ System.out.println("Exception caught by CompletionEngine:"); //$NON-NLS-1$ >+ e.printStackTrace(System.out); >+ } >+ } catch (InvalidCursorLocation e) { // may eventually report a usefull error (added to fix 99629) >+ if(DEBUG) { >+ System.out.println("Exception caught by CompletionEngine:"); //$NON-NLS-1$ >+ e.printStackTrace(System.out); >+ } >+ } catch (AbortCompilation e) { // ignore this exception for now since it typically means we cannot find java.lang.Object (added with fix of 99629) >+ if(DEBUG) { >+ System.out.println("Exception caught by CompletionEngine:"); //$NON-NLS-1$ >+ e.printStackTrace(System.out); >+ } >+ } catch (CompletionNodeFound e){ // internal failure - bugs 5618 (added with fix of 99629) >+ if(DEBUG) { >+ System.out.println("Exception caught by CompletionEngine:"); //$NON-NLS-1$ >+ e.printStackTrace(System.out); >+ } >+ } catch(JavaModelException e) { >+ // Do nothing >+ } >+ if(!contextAccepted) { >+ contextAccepted = true; >+ InternalCompletionContext context = new InternalCompletionContext(); >+ if (this.requestor.isExtendedContextRequired()) context.setExtended(); >+ this.requestor.acceptContext(context); >+ } >+ if(this.requestor != null){ >+ this.requestor.endReporting(); >+ } >+ } >+ >+ private void completionOnBranchStatementLabel(ASTNode astNode) { >+ if (!this.requestor.isIgnored(CompletionProposal.LABEL_REF)) { >+ CompletionOnBranchStatementLabel label = (CompletionOnBranchStatementLabel) astNode; >+ this.completionToken = label.label; >+ findLabels(this.completionToken, label.possibleLabels); >+ } >+ } >+ >+ private void completionOnClassLiteralAccess(ASTNode astNode, Binding qualifiedBinding, Scope scope) { >+ if (!this.requestor.isIgnored(CompletionProposal.FIELD_REF)) { >+ CompletionOnClassLiteralAccess access = (CompletionOnClassLiteralAccess) astNode; >+ setSourceAndTokenRange(access.classStart, access.sourceEnd); >+ this.completionToken = access.completionIdentifier; >+ findClassField( >+ this.completionToken, >+ (TypeBinding) qualifiedBinding, >+ scope, >+ null, >+ null, >+ null, >+ false); >+ } >+ } >+ >+ private void completionOnExplicitConstructorCall(ASTNode astNode, Binding qualifiedBinding, Scope scope) { >+ if (!this.requestor.isIgnored(CompletionProposal.METHOD_REF)) { > setSourceAndTokenRange(astNode.sourceStart, astNode.sourceEnd, false); >+ CompletionOnExplicitConstructorCall constructorCall = (CompletionOnExplicitConstructorCall) astNode; >+ TypeBinding[] argTypes = computeTypes(constructorCall.arguments); >+ findConstructors( >+ (ReferenceBinding) qualifiedBinding, >+ argTypes, >+ scope, >+ constructorCall, >+ false); >+ } >+ } >+ >+ private void completionOnFieldName(ASTNode astNode, Scope scope) { >+ if (!this.requestor.isIgnored(CompletionProposal.VARIABLE_DECLARATION)) { >+ CompletionOnFieldName field = (CompletionOnFieldName) astNode; > >- CompletionOnMessageSend messageSend = (CompletionOnMessageSend) astNode; >- TypeBinding[] argTypes = computeTypes(messageSend.arguments); >- this.completionToken = messageSend.selector; >- if (qualifiedBinding == null) { >- if (!this.requestor.isIgnored(CompletionProposal.METHOD_REF)) { >- ObjectVector methodsFound = new ObjectVector(); >+ FieldBinding[] fields = scope.enclosingSourceType().fields(); >+ char[][] excludeNames = new char[fields.length][]; >+ for(int i = 0 ; i < fields.length ; i++){ >+ excludeNames[i] = fields[i].name; >+ } > >- findImplicitMessageSends(this.completionToken, argTypes, scope, messageSend, scope, methodsFound); >+ this.completionToken = field.realName; > >- findLocalMethodsFromStaticImports( >+ findVariableNames(field.realName, field.type, excludeNames, null, FIELD, field.modifiers); >+ } >+ } >+ >+ private void completionOnFieldType(ASTNode astNode, Scope scope) { >+ CompletionOnFieldType field = (CompletionOnFieldType) astNode; >+ CompletionOnSingleTypeReference type = (CompletionOnSingleTypeReference) field.type; >+ this.completionToken = type.token; >+ setSourceAndTokenRange(type.sourceStart, type.sourceEnd); >+ >+ findTypesAndPackages(this.completionToken, scope, true, true, new ObjectVector()); >+ if (!this.requestor.isIgnored(CompletionProposal.KEYWORD)) { >+ findKeywordsForMember(this.completionToken, field.modifiers); >+ } >+ >+ if (!field.isLocalVariable && field.modifiers == ClassFileConstants.AccDefault) { >+ SourceTypeBinding enclosingType = scope.enclosingSourceType(); >+ if (!enclosingType.isAnnotationType()) { >+ if (!this.requestor.isIgnored(CompletionProposal.METHOD_DECLARATION)) { >+ findMethodDeclarations( > this.completionToken, >+ enclosingType, > scope, >- messageSend, >- scope, >- true, >- methodsFound, >- true); >+ new ObjectVector(), >+ null, >+ null, >+ null, >+ false); >+ } >+ if (!this.requestor.isIgnored(CompletionProposal.POTENTIAL_METHOD_DECLARATION)) { >+ proposeNewMethod(this.completionToken, enclosingType); >+ } >+ } >+ } >+ } >+ //TODO >+ private void completionOnJavadocAllocationExpression(ASTNode astNode, Binding qualifiedBinding, Scope scope) { >+ // setSourceRange(astNode.sourceStart, astNode.sourceEnd, false); >+ >+ CompletionOnJavadocAllocationExpression allocExpression = (CompletionOnJavadocAllocationExpression) astNode; >+ this.javadocTagPosition = allocExpression.tagSourceStart; >+ int rangeStart = astNode.sourceStart; >+ if (allocExpression.type.isThis()) { >+ if (allocExpression.completeInText()) { >+ rangeStart = allocExpression.separatorPosition; >+ } >+ } else if (allocExpression.completeInText()) { >+ rangeStart = allocExpression.type.sourceStart; >+ } >+ setSourceAndTokenRange(rangeStart, astNode.sourceEnd, false); >+ TypeBinding[] argTypes = computeTypes(allocExpression.arguments); >+ >+ ReferenceBinding ref = (ReferenceBinding) qualifiedBinding; >+ if (!this.requestor.isIgnored(CompletionProposal.METHOD_REF) && ref.isClass()) { >+ findConstructors(ref, argTypes, scope, allocExpression, false); >+ } >+ } >+ //TODO >+ private void completionOnJavadocFieldReference(ASTNode astNode, Scope scope) { >+ this.insideQualifiedReference = true; >+ CompletionOnJavadocFieldReference fieldRef = (CompletionOnJavadocFieldReference) astNode; >+ this.completionToken = fieldRef.token; >+ long completionPosition = fieldRef.nameSourcePosition; >+ this.javadocTagPosition = fieldRef.tagSourceStart; >+ >+ if (fieldRef.actualReceiverType != null && fieldRef.actualReceiverType.isValidBinding()) { >+ ReferenceBinding receiverType = (ReferenceBinding) fieldRef.actualReceiverType; >+ int rangeStart = (int) (completionPosition >>> 32); >+ if (fieldRef.receiver.isThis()) { >+ if (fieldRef.completeInText()) { >+ rangeStart = fieldRef.separatorPosition; > } >- } else if (!this.requestor.isIgnored(CompletionProposal.METHOD_REF)) { >+ } else if (fieldRef.completeInText()) { >+ rangeStart = fieldRef.receiver.sourceStart; >+ } >+ setSourceAndTokenRange(rangeStart, (int) completionPosition); >+ >+ if (!this.requestor.isIgnored(CompletionProposal.FIELD_REF) >+ || !this.requestor.isIgnored(CompletionProposal.JAVADOC_FIELD_REF)) { >+ findFields(this.completionToken, >+ receiverType, >+ scope, >+ new ObjectVector(), >+ new ObjectVector(), >+ false, /*not only static */ >+ fieldRef, >+ scope, >+ false, >+ true, >+ null, >+ null, >+ null, >+ false, >+ null, >+ -1, >+ -1); >+ } >+ >+ if (!this.requestor.isIgnored(CompletionProposal.METHOD_REF) >+ || !this.requestor.isIgnored(CompletionProposal.JAVADOC_METHOD_REF)) { > findMethods( > this.completionToken, > null, >- argTypes, >- (ReferenceBinding)((ReferenceBinding) qualifiedBinding).capture(scope, messageSend.receiver.sourceEnd), >+ null, >+ receiverType, > scope, > new ObjectVector(), >+ false, /*not only static */ > false, >- true, >- false, >- messageSend, >+ fieldRef, > scope, > false, >- messageSend.receiver instanceof SuperReference, > false, >+ true, > null, > null, > null, >@@ -1514,443 +1678,466 @@ > null, > -1, > -1); >+ if (fieldRef.actualReceiverType instanceof ReferenceBinding) { >+ ReferenceBinding refBinding = (ReferenceBinding)fieldRef.actualReceiverType; >+ if (this.completionToken == null >+ || CharOperation.prefixEquals(this.completionToken, refBinding.sourceName) >+ || (this.options.camelCaseMatch && CharOperation.camelCaseMatch(this.completionToken, refBinding.sourceName))) { >+ findConstructors(refBinding, null, scope, fieldRef, false); >+ } >+ } > } >- } else if (astNode instanceof CompletionOnExplicitConstructorCall) { >- if (!this.requestor.isIgnored(CompletionProposal.METHOD_REF)) { >- setSourceAndTokenRange(astNode.sourceStart, astNode.sourceEnd, false); >- >- CompletionOnExplicitConstructorCall constructorCall = >- (CompletionOnExplicitConstructorCall) astNode; >- TypeBinding[] argTypes = computeTypes(constructorCall.arguments); >- findConstructors( >- (ReferenceBinding) qualifiedBinding, >- argTypes, >- scope, >- constructorCall, >- false); >- } >- } else if (astNode instanceof CompletionOnQualifiedAllocationExpression) { >- setSourceAndTokenRange(astNode.sourceStart, astNode.sourceEnd, false); >+ } >+ } >+ //TODO >+ private void completionOnJavadocMessageSend(ASTNode astNode, Binding qualifiedBinding, Scope scope) { >+ CompletionOnJavadocMessageSend messageSend = (CompletionOnJavadocMessageSend) astNode; >+ TypeBinding[] argTypes = null; //computeTypes(messageSend.arguments); >+ this.completionToken = messageSend.selector; >+ this.javadocTagPosition = messageSend.tagSourceStart; > >- CompletionOnQualifiedAllocationExpression allocExpression = >- (CompletionOnQualifiedAllocationExpression) astNode; >- TypeBinding[] argTypes = computeTypes(allocExpression.arguments); >+ // Set source range >+ int rangeStart = astNode.sourceStart; >+ if (messageSend.receiver.isThis()) { >+ if (messageSend.completeInText()) { >+ rangeStart = messageSend.separatorPosition; >+ } >+ } else if (messageSend.completeInText()) { >+ rangeStart = messageSend.receiver.sourceStart; >+ } >+ setSourceAndTokenRange(rangeStart, astNode.sourceEnd, false); > >- ReferenceBinding ref = (ReferenceBinding) qualifiedBinding; >- if (!this.requestor.isIgnored(CompletionProposal.METHOD_REF) >- && ref.isClass() >- && !ref.isAbstract()) { >- findConstructors( >- ref, >- argTypes, >- scope, >- allocExpression, >- false); >+ if (qualifiedBinding == null) { >+ if (!this.requestor.isIgnored(CompletionProposal.METHOD_REF)) { >+ findImplicitMessageSends(this.completionToken, argTypes, scope, messageSend, scope, new ObjectVector()); > } >- if (!this.requestor.isIgnored(CompletionProposal.ANONYMOUS_CLASS_DECLARATION) >- && !ref.isFinal() >- && !ref.isEnum()){ >- findAnonymousType( >- ref, >- argTypes, >+ } else if (!this.requestor.isIgnored(CompletionProposal.METHOD_REF)) { >+ findMethods( >+ this.completionToken, >+ null, >+ argTypes, >+ (ReferenceBinding) ((ReferenceBinding) qualifiedBinding).capture(scope, messageSend.receiver.sourceEnd), >+ scope, >+ new ObjectVector(), >+ false, >+ false/* prefix match */, >+ messageSend, >+ scope, >+ false, >+ messageSend.receiver instanceof SuperReference, >+ true, >+ null, >+ null, >+ null, >+ false, >+ null, >+ -1, >+ -1); >+ } >+ } >+ //TODO >+ private void completionOnJavadocParamNameReference(ASTNode astNode) { >+ if (!this.requestor.isIgnored(CompletionProposal.JAVADOC_PARAM_REF)) { >+ CompletionOnJavadocParamNameReference paramRef = (CompletionOnJavadocParamNameReference) astNode; >+ setSourceAndTokenRange(paramRef.tagSourceStart, paramRef.tagSourceEnd); >+ findJavadocParamNames(paramRef.token, paramRef.missingParams, false); >+ findJavadocParamNames(paramRef.token, paramRef.missingTypeParams, true); >+ } >+ } >+ //TODO >+ private void completionOnJavadocQualifiedTypeReference(ASTNode astNode, Binding qualifiedBinding, Scope scope) { >+ this.insideQualifiedReference = true; >+ >+ CompletionOnJavadocQualifiedTypeReference typeRef = (CompletionOnJavadocQualifiedTypeReference) astNode; >+ this.completionToken = typeRef.completionIdentifier; >+ long completionPosition = typeRef.sourcePositions[typeRef.tokens.length]; >+ this.javadocTagPosition = typeRef.tagSourceStart; >+ >+ // get the source positions of the completion identifier >+ if (qualifiedBinding instanceof ReferenceBinding && !(qualifiedBinding instanceof TypeVariableBinding)) { >+ if (!this.requestor.isIgnored(CompletionProposal.TYPE_REF) || >+ ((this.assistNodeInJavadoc & CompletionOnJavadoc.TEXT) != 0 && !this.requestor.isIgnored(CompletionProposal.JAVADOC_TYPE_REF))) { >+ int rangeStart = typeRef.completeInText() ? typeRef.sourceStart : (int) (completionPosition >>> 32); >+ setSourceAndTokenRange(rangeStart, (int) completionPosition); >+ findMemberTypes( >+ this.completionToken, >+ (ReferenceBinding) qualifiedBinding, > scope, >- allocExpression); >+ scope.enclosingSourceType(), >+ false, >+ false, >+ new ObjectVector(), >+ null, >+ null, >+ null, >+ false); > } >- } else if (astNode instanceof CompletionOnClassLiteralAccess) { >- if (!this.requestor.isIgnored(CompletionProposal.FIELD_REF)) { >- CompletionOnClassLiteralAccess access = (CompletionOnClassLiteralAccess) astNode; >- setSourceAndTokenRange(access.classStart, access.sourceEnd); >+ } else if (qualifiedBinding instanceof PackageBinding) { > >- this.completionToken = access.completionIdentifier; >- >- findClassField( >- this.completionToken, >- (TypeBinding) qualifiedBinding, >- scope, >- null, >- null, >- null, >- false); >+ setSourceRange(astNode.sourceStart, (int) completionPosition); >+ int rangeStart = typeRef.completeInText() ? typeRef.sourceStart : (int) (completionPosition >>> 32); >+ setTokenRange(rangeStart, (int) completionPosition); >+ // replace to the end of the completion identifier >+ findTypesAndSubpackages(this.completionToken, (PackageBinding) qualifiedBinding, scope); >+ } >+ } >+ //TODO >+ private void completionOnJavadocSingleTypeReference(ASTNode astNode, Scope scope) { >+ CompletionOnJavadocSingleTypeReference typeRef = (CompletionOnJavadocSingleTypeReference) astNode; >+ this.completionToken = typeRef.token; >+ this.javadocTagPosition = typeRef.tagSourceStart; >+ setSourceAndTokenRange(typeRef.sourceStart, typeRef.sourceEnd); >+ findTypesAndPackages( >+ this.completionToken, >+ scope, >+ (this.assistNodeInJavadoc & CompletionOnJavadoc.BASE_TYPES) != 0, >+ false, >+ new ObjectVector()); >+ } >+ //TODO >+ private void completionOnJavadocTag(ASTNode astNode) { >+ CompletionOnJavadocTag javadocTag = (CompletionOnJavadocTag) astNode; >+ setSourceAndTokenRange(javadocTag.tagSourceStart, javadocTag.sourceEnd); >+ findJavadocBlockTags(javadocTag); >+ findJavadocInlineTags(javadocTag); >+ } >+ //TODO >+ private void completionOnJavadocTypeParamReference(ASTNode astNode) { >+ if (!this.requestor.isIgnored(CompletionProposal.JAVADOC_PARAM_REF)) { >+ CompletionOnJavadocTypeParamReference paramRef = (CompletionOnJavadocTypeParamReference) astNode; >+ setSourceAndTokenRange(paramRef.tagSourceStart, paramRef.tagSourceEnd); >+ findJavadocParamNames(paramRef.token, paramRef.missingParams, true); >+ } >+ } >+ >+ private void completionOnKeyword(ASTNode astNode) { >+ if (!this.requestor.isIgnored(CompletionProposal.KEYWORD)) { >+ CompletionOnKeyword keyword = (CompletionOnKeyword)astNode; >+ findKeywords(keyword.getToken(), keyword.getPossibleKeywords(), keyword.canCompleteEmptyToken(), false); >+ } >+ } >+ >+ private void completionOnLocalOrArgumentName(ASTNode astNode, Scope scope) { >+ if (!this.requestor.isIgnored(CompletionProposal.VARIABLE_DECLARATION)) { >+ LocalDeclaration variable = (LocalDeclaration) astNode; >+ >+ int kind; >+ if (variable instanceof CompletionOnLocalName){ >+ this.completionToken = ((CompletionOnLocalName) variable).realName; >+ kind = LOCAL; >+ } else { >+ CompletionOnArgumentName arg = (CompletionOnArgumentName) variable; >+ this.completionToken = arg.realName; >+ kind = arg.isCatchArgument ? LOCAL : ARGUMENT; > } >- } else if (astNode instanceof CompletionOnMethodName) { >- if (!this.requestor.isIgnored(CompletionProposal.VARIABLE_DECLARATION)) { >- CompletionOnMethodName method = (CompletionOnMethodName) astNode; > >- setSourceAndTokenRange(method.sourceStart, method.selectorEnd); >+ char[][] alreadyDefinedName = computeAlreadyDefinedName((BlockScope)scope, variable); > >- FieldBinding[] fields = scope.enclosingSourceType().fields(); >- char[][] excludeNames = new char[fields.length][]; >- for(int i = 0 ; i < fields.length ; i++){ >- excludeNames[i] = fields[i].name; >- } >- >- this.completionToken = method.selector; >+ char[][] forbiddenNames = findVariableFromUnresolvedReference(variable, (BlockScope)scope, alreadyDefinedName); > >- findVariableNames(this.completionToken, method.returnType, excludeNames, null, FIELD, method.modifiers); >+ LocalVariableBinding[] locals = ((BlockScope)scope).locals; >+ char[][] discouragedNames = new char[locals.length][]; >+ int localCount = 0; >+ for(int i = 0 ; i < locals.length ; i++){ >+ if (locals[i] != null) { >+ discouragedNames[localCount++] = locals[i].name; >+ } > } >- } else if (astNode instanceof CompletionOnFieldName) { >- if (!this.requestor.isIgnored(CompletionProposal.VARIABLE_DECLARATION)) { >- CompletionOnFieldName field = (CompletionOnFieldName) astNode; > >- FieldBinding[] fields = scope.enclosingSourceType().fields(); >- char[][] excludeNames = new char[fields.length][]; >- for(int i = 0 ; i < fields.length ; i++){ >- excludeNames[i] = fields[i].name; >- } >+ System.arraycopy(discouragedNames, 0, discouragedNames = new char[localCount][], 0, localCount); > >- this.completionToken = field.realName; >+ findVariableNames(this.completionToken, variable.type, discouragedNames, forbiddenNames, kind, variable.modifiers); >+ } >+ } >+ >+ private void completionOnMarkerAnnotationName(ASTNode astNode, Binding qualifiedBinding, Scope scope) { >+ CompletionOnMarkerAnnotationName annot = (CompletionOnMarkerAnnotationName) astNode; > >- findVariableNames(field.realName, field.type, excludeNames, null, FIELD, field.modifiers); >+ CompletionOnAnnotationOfType fakeType = (CompletionOnAnnotationOfType)scope.parent.referenceContext(); >+ if (fakeType.annotations[0] == annot) { >+ // When the completion is inside a method body the annotation cannot be accuratly attached to the correct node by completion recovery. >+ // So 'targetedElement' is not computed in this case. >+ if (scope.parent.parent == null || !(scope.parent.parent instanceof MethodScope)) { >+ this.targetedElement = computeTargetedElement(fakeType); > } >- } else if (astNode instanceof CompletionOnLocalName || astNode instanceof CompletionOnArgumentName) { >- if (!this.requestor.isIgnored(CompletionProposal.VARIABLE_DECLARATION)) { >- LocalDeclaration variable = (LocalDeclaration) astNode; > >- int kind; >- if (variable instanceof CompletionOnLocalName){ >- this.completionToken = ((CompletionOnLocalName) variable).realName; >- kind = LOCAL; >- } else { >- CompletionOnArgumentName arg = (CompletionOnArgumentName) variable; >- this.completionToken = arg.realName; >- kind = arg.isCatchArgument ? LOCAL : ARGUMENT; >- } >+ } >+ >+ this.assistNodeIsAnnotation = true; >+ if (annot.type instanceof CompletionOnSingleTypeReference) { >+ CompletionOnSingleTypeReference type = (CompletionOnSingleTypeReference) annot.type; >+ this.completionToken = type.token; >+ setSourceAndTokenRange(type.sourceStart, type.sourceEnd); > >- char[][] alreadyDefinedName = computeAlreadyDefinedName((BlockScope)scope, variable); >+ if (scope.parent.parent != null && >+ !(scope.parent.parent instanceof MethodScope) && >+ !fakeType.isParameter) { > >- char[][] forbiddenNames = findVariableFromUnresolvedReference(variable, (BlockScope)scope, alreadyDefinedName); >+ if (this.completionToken.length <= Keywords.INTERFACE.length >+ && CharOperation.prefixEquals(this.completionToken, Keywords.INTERFACE, false /* ignore case */ >+ )){ >+ int relevance = computeBaseRelevance(); >+ relevance += computeRelevanceForResolution(); >+ relevance += computeRelevanceForInterestingProposal(); >+ relevance += computeRelevanceForCaseMatching(this.completionToken, Keywords.INTERFACE); >+ relevance += computeRelevanceForRestrictions(IAccessRule.K_ACCESSIBLE); // no access restriction for keywords >+ relevance += R_ANNOTATION; // this proposal is most relevant than annotation proposals > >- LocalVariableBinding[] locals = ((BlockScope)scope).locals; >- char[][] discouragedNames = new char[locals.length][]; >- int localCount = 0; >- for(int i = 0 ; i < locals.length ; i++){ >- if (locals[i] != null) { >- discouragedNames[localCount++] = locals[i].name; >+ this.noProposal = false; >+ if(!this.requestor.isIgnored(CompletionProposal.KEYWORD)) { >+ CompletionProposal proposal = createProposal(CompletionProposal.KEYWORD, this.actualCompletionPosition); >+ proposal.setName(Keywords.INTERFACE); >+ proposal.setCompletion(Keywords.INTERFACE); >+ proposal.setReplaceRange(this.startPosition - this.offset, this.endPosition - this.offset); >+ proposal.setTokenRange(this.tokenStart - this.offset, this.tokenEnd - this.offset); >+ proposal.setRelevance(relevance); >+ this.requestor.accept(proposal); >+ if(DEBUG) { >+ this.printDebug(proposal); >+ } > } > } >- >- System.arraycopy(discouragedNames, 0, discouragedNames = new char[localCount][], 0, localCount); >- >- findVariableNames(this.completionToken, variable.type, discouragedNames, forbiddenNames, kind, variable.modifiers); >- } >- } else if (astNode instanceof CompletionOnKeyword) { >- if (!this.requestor.isIgnored(CompletionProposal.KEYWORD)) { >- CompletionOnKeyword keyword = (CompletionOnKeyword)astNode; >- findKeywords(keyword.getToken(), keyword.getPossibleKeywords(), keyword.canCompleteEmptyToken(), false); > } >- } else if (astNode instanceof CompletionOnParameterizedQualifiedTypeReference) { >- if (!this.requestor.isIgnored(CompletionProposal.TYPE_REF)) { >- CompletionOnParameterizedQualifiedTypeReference ref = (CompletionOnParameterizedQualifiedTypeReference) astNode; > >- this.insideQualifiedReference = true; >+ findTypesAndPackages(this.completionToken, scope, false, false, new ObjectVector()); >+ } else if (annot.type instanceof CompletionOnQualifiedTypeReference) { >+ this.insideQualifiedReference = true; > >- this.assistNodeIsClass = ref.isClass(); >- this.assistNodeIsException = ref.isException(); >- this.assistNodeIsInterface = ref.isInterface(); >- this.assistNodeIsSuperType = ref.isSuperType(); >+ CompletionOnQualifiedTypeReference type = (CompletionOnQualifiedTypeReference) annot.type; >+ this.completionToken = type.completionIdentifier; >+ long completionPosition = type.sourcePositions[type.tokens.length]; >+ if (qualifiedBinding instanceof PackageBinding) { > >- this.completionToken = ref.completionIdentifier; >- long completionPosition = ref.sourcePositions[ref.tokens.length]; >+ setSourceRange(astNode.sourceStart, (int) completionPosition); >+ setTokenRange((int) (completionPosition >>> 32), (int) completionPosition); >+ // replace to the end of the completion identifier >+ findTypesAndSubpackages(this.completionToken, (PackageBinding) qualifiedBinding, scope); >+ } else { > setSourceAndTokenRange((int) (completionPosition >>> 32), (int) completionPosition); > >- if (qualifiedBinding.problemId() == ProblemReasons.NotFound || >- (((ReferenceBinding)qualifiedBinding).tagBits & TagBits.HasMissingType) != 0) { >- if (this.assistNodeInJavadoc == 0 && >- (this.requestor.isAllowingRequiredProposals(CompletionProposal.TYPE_REF, CompletionProposal.TYPE_REF))) { >- if(ref.tokens.length == 1) { >- findMemberTypesFromMissingType( >- ref, >- ref.sourcePositions[0], >- scope); >- } >- } >- } else { >- ObjectVector typesFound = new ObjectVector(); >- if (this.assistNodeIsException && astNodeParent instanceof TryStatement) { >- findExceptionFromTryStatement( >- this.completionToken, >- (ReferenceBinding)qualifiedBinding, >- scope.enclosingSourceType(), >- (BlockScope)scope, >- typesFound); >- } >- >- findMemberTypes( >- this.completionToken, >- (ReferenceBinding) qualifiedBinding, >+ findMemberTypes( >+ this.completionToken, >+ (ReferenceBinding) qualifiedBinding, >+ scope, >+ scope.enclosingSourceType(), >+ false, >+ false, >+ new ObjectVector(), >+ null, >+ null, >+ null, >+ false); >+ } >+ } >+ } >+ >+ private void completionOnMemberAccess(ASTNode astNode, ASTNode enclosingNode, Binding qualifiedBinding, >+ Scope scope, boolean insideTypeAnnotation) { >+ this.insideQualifiedReference = true; >+ CompletionOnMemberAccess access = (CompletionOnMemberAccess) astNode; >+ long completionPosition = access.nameSourcePosition; >+ setSourceAndTokenRange((int) (completionPosition >>> 32), (int) completionPosition); >+ >+ this.completionToken = access.token; >+ >+ if (qualifiedBinding.problemId() == ProblemReasons.NotFound) { >+ // complete method members with missing return type >+ // class X { >+ // Missing f() {return null;} >+ // void foo() { >+ // f().| >+ // } >+ // } >+ if (this.assistNodeInJavadoc == 0 && >+ (this.requestor.isAllowingRequiredProposals(CompletionProposal.FIELD_REF, CompletionProposal.TYPE_REF) || >+ this.requestor.isAllowingRequiredProposals(CompletionProposal.METHOD_REF, CompletionProposal.TYPE_REF))) { >+ ProblemMethodBinding problemMethodBinding = (ProblemMethodBinding) qualifiedBinding; >+ findFieldsAndMethodsFromMissingReturnType( >+ problemMethodBinding.selector, >+ problemMethodBinding.parameters, > scope, >- scope.enclosingSourceType(), >- false, >- false, >- typesFound, >- null, >- null, >- null, >- false); >- } >+ access, >+ insideTypeAnnotation); > } >- } else if (astNode instanceof CompletionOnMarkerAnnotationName) { >- CompletionOnMarkerAnnotationName annot = (CompletionOnMarkerAnnotationName) astNode; >- >- CompletionOnAnnotationOfType fakeType = (CompletionOnAnnotationOfType)scope.parent.referenceContext(); >- if (fakeType.annotations[0] == annot) { >- // When the completion is inside a method body the annotation cannot be accuratly attached to the correct node by completion recovery. >- // So 'targetedElement' is not computed in this case. >- if (scope.parent.parent == null || !(scope.parent.parent instanceof MethodScope)) { >- this.targetedElement = computeTargetedElement(fakeType); >+ } else { >+ if (!access.isInsideAnnotation) { >+ if (!this.requestor.isIgnored(CompletionProposal.KEYWORD)) { >+ findKeywords(this.completionToken, new char[][]{Keywords.NEW}, false, false); > } > >- } >- >- this.assistNodeIsAnnotation = true; >- if (annot.type instanceof CompletionOnSingleTypeReference) { >- CompletionOnSingleTypeReference type = (CompletionOnSingleTypeReference) annot.type; >- this.completionToken = type.token; >- setSourceAndTokenRange(type.sourceStart, type.sourceEnd); >- >- if (scope.parent.parent != null && >- !(scope.parent.parent instanceof MethodScope) && >- !fakeType.isParameter) { >- >- if (this.completionToken.length <= Keywords.INTERFACE.length >- && CharOperation.prefixEquals(this.completionToken, Keywords.INTERFACE, false /* ignore case */ >- )){ >- int relevance = computeBaseRelevance(); >- relevance += computeRelevanceForResolution(); >- relevance += computeRelevanceForInterestingProposal(); >- relevance += computeRelevanceForCaseMatching(this.completionToken, Keywords.INTERFACE); >- relevance += computeRelevanceForRestrictions(IAccessRule.K_ACCESSIBLE); // no access restriction for keywords >- relevance += R_ANNOTATION; // this proposal is most relevant than annotation proposals >+ ObjectVector fieldsFound = new ObjectVector(); >+ ObjectVector methodsFound = new ObjectVector(); > >- this.noProposal = false; >- if(!this.requestor.isIgnored(CompletionProposal.KEYWORD)) { >- CompletionProposal proposal = createProposal(CompletionProposal.KEYWORD, this.actualCompletionPosition); >- proposal.setName(Keywords.INTERFACE); >- proposal.setCompletion(Keywords.INTERFACE); >- proposal.setReplaceRange(this.startPosition - this.offset, this.endPosition - this.offset); >- proposal.setTokenRange(this.tokenStart - this.offset, this.tokenEnd - this.offset); >- proposal.setRelevance(relevance); >- this.requestor.accept(proposal); >- if(DEBUG) { >- this.printDebug(proposal); >- } >- } >- } >- } >+ boolean superCall = access.receiver instanceof SuperReference; > >- findTypesAndPackages(this.completionToken, scope, false, false, new ObjectVector()); >- } else if (annot.type instanceof CompletionOnQualifiedTypeReference) { >- this.insideQualifiedReference = true; >- >- CompletionOnQualifiedTypeReference type = (CompletionOnQualifiedTypeReference) annot.type; >- this.completionToken = type.completionIdentifier; >- long completionPosition = type.sourcePositions[type.tokens.length]; >- if (qualifiedBinding instanceof PackageBinding) { >- >- setSourceRange(astNode.sourceStart, (int) completionPosition); >- setTokenRange((int) (completionPosition >>> 32), (int) completionPosition); >- // replace to the end of the completion identifier >- findTypesAndSubpackages(this.completionToken, (PackageBinding) qualifiedBinding, scope); >- } else { >- setSourceAndTokenRange((int) (completionPosition >>> 32), (int) completionPosition); >+ findFieldsAndMethods( >+ this.completionToken, >+ ((TypeBinding) qualifiedBinding).capture(scope, access.receiver.sourceEnd), >+ scope, >+ fieldsFound, >+ methodsFound, >+ access, >+ scope, >+ false, >+ superCall, >+ null, >+ null, >+ null, >+ false, >+ null, >+ -1, >+ -1); > >- findMemberTypes( >- this.completionToken, >- (ReferenceBinding) qualifiedBinding, >- scope, >- scope.enclosingSourceType(), >- false, >- false, >- new ObjectVector(), >- null, >- null, >- null, >- false); >+ if (!superCall) { >+ >+ checkCancel(); >+ >+ findFieldsAndMethodsFromCastedReceiver( >+ enclosingNode, >+ qualifiedBinding, >+ scope, >+ fieldsFound, >+ methodsFound, >+ access, >+ scope, >+ access.receiver); > } > } >- } else if (astNode instanceof CompletionOnMemberValueName) { >- CompletionOnMemberValueName memberValuePair = (CompletionOnMemberValueName) astNode; >- Annotation annotation = (Annotation) astNodeParent; >+ } >+ } >+ >+ private void completionOnMemberValueName(ASTNode astNode, ASTNode astNodeParent, Scope scope, >+ boolean insideTypeAnnotation) { >+ CompletionOnMemberValueName memberValuePair = (CompletionOnMemberValueName) astNode; >+ Annotation annotation = (Annotation) astNodeParent; > >- this.completionToken = memberValuePair.name; >+ this.completionToken = memberValuePair.name; > >- ReferenceBinding annotationType = (ReferenceBinding)annotation.resolvedType; >+ ReferenceBinding annotationType = (ReferenceBinding)annotation.resolvedType; > >- if (annotationType != null && annotationType.isAnnotationType()) { >- if (!this.requestor.isIgnored(CompletionProposal.ANNOTATION_ATTRIBUTE_REF)) { >- findAnnotationAttributes(this.completionToken, annotation.memberValuePairs(), annotationType); >- } >- if (this.assistNodeCanBeSingleMemberAnnotation) { >- if (this.expectedTypesPtr > -1 && this.expectedTypes[0].isAnnotationType()) { >- findTypesAndPackages(this.completionToken, scope, false, false, new ObjectVector()); >- } else { >- if (this.expectedTypesPtr > -1) { >- this.assistNodeIsEnum = true; >- done : for (int i = 0; i <= this.expectedTypesPtr; i++) { >- if (!this.expectedTypes[i].isEnum()) { >- this.assistNodeIsEnum = false; >- break done; >- } >+ if (annotationType != null && annotationType.isAnnotationType()) { >+ if (!this.requestor.isIgnored(CompletionProposal.ANNOTATION_ATTRIBUTE_REF)) { >+ findAnnotationAttributes(this.completionToken, annotation.memberValuePairs(), annotationType); >+ } >+ if (this.assistNodeCanBeSingleMemberAnnotation) { >+ if (this.expectedTypesPtr > -1 && this.expectedTypes[0].isAnnotationType()) { >+ findTypesAndPackages(this.completionToken, scope, false, false, new ObjectVector()); >+ } else { >+ if (this.expectedTypesPtr > -1) { >+ this.assistNodeIsEnum = true; >+ done : for (int i = 0; i <= this.expectedTypesPtr; i++) { >+ if (!this.expectedTypes[i].isEnum()) { >+ this.assistNodeIsEnum = false; >+ break done; > } >- > } >- if (scope instanceof BlockScope && !this.requestor.isIgnored(CompletionProposal.LOCAL_VARIABLE_REF)) { >- char[][] alreadyDefinedName = computeAlreadyDefinedName((BlockScope)scope, FakeInvocationSite); > >- findUnresolvedReference( >- memberValuePair.sourceStart, >- memberValuePair.sourceEnd, >- (BlockScope)scope, >- alreadyDefinedName); >- } >- findVariablesAndMethods( >- this.completionToken, >- scope, >- FakeInvocationSite, >- scope, >- insideTypeAnnotation, >- true); >- // can be the start of a qualified type name >- findTypesAndPackages(this.completionToken, scope, false, false, new ObjectVector()); > } >- } >- } >- } else if(astNode instanceof CompletionOnBrankStatementLabel) { >- if (!this.requestor.isIgnored(CompletionProposal.LABEL_REF)) { >- CompletionOnBrankStatementLabel label = (CompletionOnBrankStatementLabel) astNode; >- >- this.completionToken = label.label; >- >- findLabels(this.completionToken, label.possibleLabels); >- } >- } else if(astNode instanceof CompletionOnMessageSendName) { >- if (!this.requestor.isIgnored(CompletionProposal.METHOD_REF)) { >- CompletionOnMessageSendName messageSend = (CompletionOnMessageSendName) astNode; >+ if (scope instanceof BlockScope && !this.requestor.isIgnored(CompletionProposal.LOCAL_VARIABLE_REF)) { >+ char[][] alreadyDefinedName = computeAlreadyDefinedName((BlockScope)scope, FakeInvocationSite); > >- this.insideQualifiedReference = true; >- this.completionToken = messageSend.selector; >- boolean onlyStatic = false; >- if (messageSend.receiver instanceof NameReference) { >- onlyStatic = ((NameReference)messageSend.receiver).isTypeReference(); >- } else if (!(messageSend.receiver instanceof MessageSend) && >- !(messageSend.receiver instanceof FieldReference) && >- !(messageSend.receiver.isThis())) { >- onlyStatic = true; >- } >- >- TypeBinding receiverType = (TypeBinding)qualifiedBinding; >- >- if(receiverType != null && receiverType instanceof ReferenceBinding) { >- TypeBinding[] typeArgTypes = computeTypesIfCorrect(messageSend.typeArguments); >- if(typeArgTypes != null) { >- findMethods( >- this.completionToken, >- typeArgTypes, >- null, >- (ReferenceBinding)receiverType.capture(scope, messageSend.receiver.sourceEnd), >- scope, >- new ObjectVector(), >- onlyStatic, >- false, >- false, >- messageSend, >- scope, >- false, >- false, >- false, >- null, >- null, >- null, >- false, >- null, >- -1, >- -1); >+ findUnresolvedReference( >+ memberValuePair.sourceStart, >+ memberValuePair.sourceEnd, >+ (BlockScope)scope, >+ alreadyDefinedName); > } >+ findVariablesAndMethods( >+ this.completionToken, >+ scope, >+ FakeInvocationSite, >+ scope, >+ insideTypeAnnotation, >+ true); >+ // can be the start of a qualified type name >+ findTypesAndPackages(this.completionToken, scope, false, false, new ObjectVector()); > } > } >- // Completion on Javadoc nodes >- } else if ((astNode.bits & ASTNode.InsideJavadoc) != 0) { >- if (astNode instanceof CompletionOnJavadocSingleTypeReference) { >+ } >+ } >+ >+ private void completionOnMessageSend(ASTNode astNode, Binding qualifiedBinding, Scope scope) { >+ setSourceAndTokenRange(astNode.sourceStart, astNode.sourceEnd, false); > >- CompletionOnJavadocSingleTypeReference typeRef = (CompletionOnJavadocSingleTypeReference) astNode; >- this.completionToken = typeRef.token; >- this.javadocTagPosition = typeRef.tagSourceStart; >- setSourceAndTokenRange(typeRef.sourceStart, typeRef.sourceEnd); >- findTypesAndPackages( >+ CompletionOnMessageSend messageSend = (CompletionOnMessageSend) astNode; >+ TypeBinding[] argTypes = computeTypes(messageSend.arguments); >+ this.completionToken = messageSend.selector; >+ if (qualifiedBinding == null) { >+ if (!this.requestor.isIgnored(CompletionProposal.METHOD_REF)) { >+ ObjectVector methodsFound = new ObjectVector(); >+ >+ findImplicitMessageSends(this.completionToken, argTypes, scope, messageSend, scope, methodsFound); >+ >+ checkCancel(); >+ >+ findLocalMethodsFromStaticImports( > this.completionToken, > scope, >- (this.assistNodeInJavadoc & CompletionOnJavadoc.BASE_TYPES) != 0, >- false, >- new ObjectVector()); >- >- } else if (astNode instanceof CompletionOnJavadocQualifiedTypeReference) { >+ messageSend, >+ scope, >+ true, >+ methodsFound, >+ true); >+ } >+ } else if (!this.requestor.isIgnored(CompletionProposal.METHOD_REF)) { >+ findMethods( >+ this.completionToken, >+ null, >+ argTypes, >+ (ReferenceBinding)((ReferenceBinding) qualifiedBinding).capture(scope, messageSend.receiver.sourceEnd), >+ scope, >+ new ObjectVector(), >+ false, >+ true, >+ messageSend, >+ scope, >+ false, >+ messageSend.receiver instanceof SuperReference, >+ false, >+ null, >+ null, >+ null, >+ false, >+ null, >+ -1, >+ -1); >+ } >+ } >+ >+ private void completionOnMessageSendName(ASTNode astNode, Binding qualifiedBinding, Scope scope) { >+ if (!this.requestor.isIgnored(CompletionProposal.METHOD_REF)) { >+ CompletionOnMessageSendName messageSend = (CompletionOnMessageSendName) astNode; > >- this.insideQualifiedReference = true; >+ this.insideQualifiedReference = true; >+ this.completionToken = messageSend.selector; >+ boolean onlyStatic = false; >+ if (messageSend.receiver instanceof NameReference) { >+ onlyStatic = ((NameReference)messageSend.receiver).isTypeReference(); >+ } else if (!(messageSend.receiver instanceof MessageSend) && >+ !(messageSend.receiver instanceof FieldReference) && >+ !(messageSend.receiver.isThis())) { >+ onlyStatic = true; >+ } > >- CompletionOnJavadocQualifiedTypeReference typeRef = (CompletionOnJavadocQualifiedTypeReference) astNode; >- this.completionToken = typeRef.completionIdentifier; >- long completionPosition = typeRef.sourcePositions[typeRef.tokens.length]; >- this.javadocTagPosition = typeRef.tagSourceStart; >- >- // get the source positions of the completion identifier >- if (qualifiedBinding instanceof ReferenceBinding && !(qualifiedBinding instanceof TypeVariableBinding)) { >- if (!this.requestor.isIgnored(CompletionProposal.TYPE_REF) || >- ((this.assistNodeInJavadoc & CompletionOnJavadoc.TEXT) != 0 && !this.requestor.isIgnored(CompletionProposal.JAVADOC_TYPE_REF))) { >- int rangeStart = typeRef.completeInText() ? typeRef.sourceStart : (int) (completionPosition >>> 32); >- setSourceAndTokenRange(rangeStart, (int) completionPosition); >- findMemberTypes( >+ TypeBinding receiverType = (TypeBinding)qualifiedBinding; >+ >+ if(receiverType != null && receiverType instanceof ReferenceBinding) { >+ TypeBinding[] typeArgTypes = computeTypesIfCorrect(messageSend.typeArguments); >+ if(typeArgTypes != null) { >+ findMethods( > this.completionToken, >- (ReferenceBinding) qualifiedBinding, >- scope, >- scope.enclosingSourceType(), >- false, >- false, >- new ObjectVector(), >- null, >- null, >+ typeArgTypes, > null, >- false); >- } >- } else if (qualifiedBinding instanceof PackageBinding) { >- >- setSourceRange(astNode.sourceStart, (int) completionPosition); >- int rangeStart = typeRef.completeInText() ? typeRef.sourceStart : (int) (completionPosition >>> 32); >- setTokenRange(rangeStart, (int) completionPosition); >- // replace to the end of the completion identifier >- findTypesAndSubpackages(this.completionToken, (PackageBinding) qualifiedBinding, scope); >- } >- } else if (astNode instanceof CompletionOnJavadocFieldReference) { >- >- this.insideQualifiedReference = true; >- CompletionOnJavadocFieldReference fieldRef = (CompletionOnJavadocFieldReference) astNode; >- this.completionToken = fieldRef.token; >- long completionPosition = fieldRef.nameSourcePosition; >- this.javadocTagPosition = fieldRef.tagSourceStart; >- >- if (fieldRef.actualReceiverType != null && fieldRef.actualReceiverType.isValidBinding()) { >- ReferenceBinding receiverType = (ReferenceBinding) fieldRef.actualReceiverType; >- int rangeStart = (int) (completionPosition >>> 32); >- if (fieldRef.receiver.isThis()) { >- if (fieldRef.completeInText()) { >- rangeStart = fieldRef.separatorPosition; >- } >- } else if (fieldRef.completeInText()) { >- rangeStart = fieldRef.receiver.sourceStart; >- } >- setSourceAndTokenRange(rangeStart, (int) completionPosition); >- >- if (!this.requestor.isIgnored(CompletionProposal.FIELD_REF) >- || !this.requestor.isIgnored(CompletionProposal.JAVADOC_FIELD_REF)) { >- findFields(this.completionToken, >- receiverType, >+ (ReferenceBinding)receiverType.capture(scope, messageSend.receiver.sourceEnd), > scope, > new ObjectVector(), >- new ObjectVector(), >- false, /*not only static */ >- fieldRef, >+ onlyStatic, >+ false, >+ messageSend, > scope, > false, >- true, >+ false, >+ false, > null, > null, > null, >@@ -1958,3115 +2145,2886 @@ > null, > -1, > -1); >- } >+ } >+ } >+ } >+ } >+ >+ private void completionOnMethodName(ASTNode astNode, Scope scope) { >+ if (!this.requestor.isIgnored(CompletionProposal.VARIABLE_DECLARATION)) { >+ CompletionOnMethodName method = (CompletionOnMethodName) astNode; >+ >+ setSourceAndTokenRange(method.sourceStart, method.selectorEnd); >+ >+ FieldBinding[] fields = scope.enclosingSourceType().fields(); >+ char[][] excludeNames = new char[fields.length][]; >+ for(int i = 0 ; i < fields.length ; i++){ >+ excludeNames[i] = fields[i].name; >+ } > >- if (!this.requestor.isIgnored(CompletionProposal.METHOD_REF) >- || !this.requestor.isIgnored(CompletionProposal.JAVADOC_METHOD_REF)) { >- findMethods( >+ this.completionToken = method.selector; >+ >+ findVariableNames(this.completionToken, method.returnType, excludeNames, null, FIELD, method.modifiers); >+ } >+ } >+ >+ private void completionOnMethodReturnType(ASTNode astNode, Scope scope) { >+ CompletionOnMethodReturnType method = (CompletionOnMethodReturnType) astNode; >+ SingleTypeReference type = (CompletionOnSingleTypeReference) method.returnType; >+ this.completionToken = type.token; >+ setSourceAndTokenRange(type.sourceStart, type.sourceEnd); >+ findTypesAndPackages(this.completionToken, scope.parent, true, true, new ObjectVector()); >+ if (!this.requestor.isIgnored(CompletionProposal.KEYWORD)) { >+ findKeywordsForMember(this.completionToken, method.modifiers); >+ } >+ >+ if (method.modifiers == ClassFileConstants.AccDefault) { >+ SourceTypeBinding enclosingType = scope.enclosingSourceType(); >+ if (!enclosingType.isAnnotationType()) { >+ if (!this.requestor.isIgnored(CompletionProposal.METHOD_DECLARATION)) { >+ findMethodDeclarations( > this.completionToken, >- null, >- null, >- receiverType, >+ scope.enclosingSourceType(), > scope, > new ObjectVector(), >- false, /*not only static */ >- false, >- false, >- fieldRef, >- scope, >- false, >- false, >- true, > null, > null, > null, >- false, >- null, >- -1, >- -1); >- if (fieldRef.actualReceiverType instanceof ReferenceBinding) { >- ReferenceBinding refBinding = (ReferenceBinding)fieldRef.actualReceiverType; >- if (this.completionToken == null >- || CharOperation.prefixEquals(this.completionToken, refBinding.sourceName) >- || (this.options.camelCaseMatch && CharOperation.camelCaseMatch(this.completionToken, refBinding.sourceName))) { >- findConstructors(refBinding, null, scope, fieldRef, false); >- } >- } >- } >- } >- } else if (astNode instanceof CompletionOnJavadocMessageSend) { >- >- CompletionOnJavadocMessageSend messageSend = (CompletionOnJavadocMessageSend) astNode; >- TypeBinding[] argTypes = null; //computeTypes(messageSend.arguments); >- this.completionToken = messageSend.selector; >- this.javadocTagPosition = messageSend.tagSourceStart; >- >- // Set source range >- int rangeStart = astNode.sourceStart; >- if (messageSend.receiver.isThis()) { >- if (messageSend.completeInText()) { >- rangeStart = messageSend.separatorPosition; >- } >- } else if (messageSend.completeInText()) { >- rangeStart = messageSend.receiver.sourceStart; >- } >- setSourceAndTokenRange(rangeStart, astNode.sourceEnd, false); >- >- if (qualifiedBinding == null) { >- if (!this.requestor.isIgnored(CompletionProposal.METHOD_REF)) { >- findImplicitMessageSends(this.completionToken, argTypes, scope, messageSend, scope, new ObjectVector()); >- } >- } else if (!this.requestor.isIgnored(CompletionProposal.METHOD_REF)) { >- findMethods( >- this.completionToken, >- null, >- argTypes, >- (ReferenceBinding) ((ReferenceBinding) qualifiedBinding).capture(scope, messageSend.receiver.sourceEnd), >- scope, >- new ObjectVector(), >- false, >- false/* prefix match */, >- false, >- messageSend, >- scope, >- false, >- messageSend.receiver instanceof SuperReference, >- true, >- null, >- null, >- null, >- false, >- null, >- -1, >- -1); >- } >- } else if (astNode instanceof CompletionOnJavadocAllocationExpression) { >-// setSourceRange(astNode.sourceStart, astNode.sourceEnd, false); >- >- CompletionOnJavadocAllocationExpression allocExpression = (CompletionOnJavadocAllocationExpression) astNode; >- this.javadocTagPosition = allocExpression.tagSourceStart; >- int rangeStart = astNode.sourceStart; >- if (allocExpression.type.isThis()) { >- if (allocExpression.completeInText()) { >- rangeStart = allocExpression.separatorPosition; >- } >- } else if (allocExpression.completeInText()) { >- rangeStart = allocExpression.type.sourceStart; >- } >- setSourceAndTokenRange(rangeStart, astNode.sourceEnd, false); >- TypeBinding[] argTypes = computeTypes(allocExpression.arguments); >- >- ReferenceBinding ref = (ReferenceBinding) qualifiedBinding; >- if (!this.requestor.isIgnored(CompletionProposal.METHOD_REF) && ref.isClass()) { >- findConstructors(ref, argTypes, scope, allocExpression, false); >- } >- } else if (astNode instanceof CompletionOnJavadocParamNameReference) { >- if (!this.requestor.isIgnored(CompletionProposal.JAVADOC_PARAM_REF)) { >- CompletionOnJavadocParamNameReference paramRef = (CompletionOnJavadocParamNameReference) astNode; >- setSourceAndTokenRange(paramRef.tagSourceStart, paramRef.tagSourceEnd); >- findJavadocParamNames(paramRef.token, paramRef.missingParams, false); >- findJavadocParamNames(paramRef.token, paramRef.missingTypeParams, true); >+ false); > } >- } else if (astNode instanceof CompletionOnJavadocTypeParamReference) { >- if (!this.requestor.isIgnored(CompletionProposal.JAVADOC_PARAM_REF)) { >- CompletionOnJavadocTypeParamReference paramRef = (CompletionOnJavadocTypeParamReference) astNode; >- setSourceAndTokenRange(paramRef.tagSourceStart, paramRef.tagSourceEnd); >- findJavadocParamNames(paramRef.token, paramRef.missingParams, true); >+ if (!this.requestor.isIgnored(CompletionProposal.POTENTIAL_METHOD_DECLARATION)) { >+ proposeNewMethod(this.completionToken, scope.enclosingSourceType()); > } >- } else if (astNode instanceof CompletionOnJavadocTag) { >- CompletionOnJavadocTag javadocTag = (CompletionOnJavadocTag) astNode; >- setSourceAndTokenRange(javadocTag.tagSourceStart, javadocTag.sourceEnd); >- findJavadocBlockTags(javadocTag); >- findJavadocInlineTags(javadocTag); > } > } >- return true; > } >+ >+ private void completionOnParameterizedQualifiedTypeReference(ASTNode astNode, ASTNode astNodeParent, Binding qualifiedBinding, Scope scope) { >+ if (!this.requestor.isIgnored(CompletionProposal.TYPE_REF)) { >+ CompletionOnParameterizedQualifiedTypeReference ref = (CompletionOnParameterizedQualifiedTypeReference) astNode; > >- private void findFieldsAndMethodsFromCastedReceiver( >- ASTNode enclosingNode, >- Binding qualifiedBinding, >- Scope scope, >- ObjectVector fieldsFound, >- ObjectVector methodsFound, >- InvocationSite invocationSite, >- Scope invocationScope, >- Expression receiver) { >- >- if (enclosingNode == null || !(enclosingNode instanceof IfStatement)) return; >- >- IfStatement ifStatement = (IfStatement)enclosingNode; >+ this.insideQualifiedReference = true; > >- if (!(ifStatement.condition instanceof InstanceOfExpression)) return; >+ this.assistNodeIsClass = ref.isClass(); >+ this.assistNodeIsException = ref.isException(); >+ this.assistNodeIsInterface = ref.isInterface(); >+ this.assistNodeIsSuperType = ref.isSuperType(); > >- InstanceOfExpression instanceOfExpression = (InstanceOfExpression) ifStatement.condition; >+ this.completionToken = ref.completionIdentifier; >+ long completionPosition = ref.sourcePositions[ref.tokens.length]; >+ setSourceAndTokenRange((int) (completionPosition >>> 32), (int) completionPosition); > >- TypeReference instanceOfType = instanceOfExpression.type; >- >- if (instanceOfType.resolvedType == null) return; >- >- boolean findFromAnotherReceiver = false; >- >- char[][] receiverName = null; >- int receiverStart = -1; >- int receiverEnd = -1; >- >- if (receiver instanceof QualifiedNameReference) { >- QualifiedNameReference qualifiedNameReference = (QualifiedNameReference) receiver; >+ if (qualifiedBinding.problemId() == ProblemReasons.NotFound || >+ (((ReferenceBinding)qualifiedBinding).tagBits & TagBits.HasMissingType) != 0) { >+ if (this.assistNodeInJavadoc == 0 && >+ (this.requestor.isAllowingRequiredProposals(CompletionProposal.TYPE_REF, CompletionProposal.TYPE_REF))) { >+ if(ref.tokens.length == 1) { >+ findMemberTypesFromMissingType( >+ ref, >+ ref.sourcePositions[0], >+ scope); >+ } >+ } >+ } else { >+ ObjectVector typesFound = new ObjectVector(); >+ if (this.assistNodeIsException && astNodeParent instanceof TryStatement) { >+ findExceptionFromTryStatement( >+ this.completionToken, >+ (ReferenceBinding)qualifiedBinding, >+ scope.enclosingSourceType(), >+ (BlockScope)scope, >+ typesFound); >+ } >+ >+ checkCancel(); >+ >+ findMemberTypes( >+ this.completionToken, >+ (ReferenceBinding) qualifiedBinding, >+ scope, >+ scope.enclosingSourceType(), >+ false, >+ false, >+ typesFound, >+ null, >+ null, >+ null, >+ false); >+ } >+ } >+ } >+ >+ private void completionOnQualifiedAllocationExpression(ASTNode astNode, Binding qualifiedBinding, Scope scope) { >+ setSourceAndTokenRange(astNode.sourceStart, astNode.sourceEnd, false); > >- receiverName = qualifiedNameReference.tokens; >+ CompletionOnQualifiedAllocationExpression allocExpression = >+ (CompletionOnQualifiedAllocationExpression) astNode; >+ TypeBinding[] argTypes = computeTypes(allocExpression.arguments); >+ >+ ReferenceBinding ref = (ReferenceBinding) qualifiedBinding; >+ if (!this.requestor.isIgnored(CompletionProposal.METHOD_REF) >+ && ref.isClass() >+ && !ref.isAbstract()) { >+ findConstructors( >+ ref, >+ argTypes, >+ scope, >+ allocExpression, >+ false); >+ } >+ >+ checkCancel(); >+ >+ if (!this.requestor.isIgnored(CompletionProposal.ANONYMOUS_CLASS_DECLARATION) >+ && !ref.isFinal() >+ && !ref.isEnum()){ >+ findAnonymousType( >+ ref, >+ argTypes, >+ scope, >+ allocExpression); >+ } >+ } >+ >+ private void completionOnQualifiedNameReference(ASTNode astNode, ASTNode enclosingNode, Binding qualifiedBinding, >+ Scope scope, boolean insideTypeAnnotation) { >+ this.insideQualifiedReference = true; >+ CompletionOnQualifiedNameReference ref = >+ (CompletionOnQualifiedNameReference) astNode; >+ this.completionToken = ref.completionIdentifier; >+ long completionPosition = ref.sourcePositions[ref.sourcePositions.length - 1]; > >- if (receiverName.length != 1) return; >+ if (qualifiedBinding.problemId() == ProblemReasons.NotFound) { >+ setSourceAndTokenRange((int) (completionPosition >>> 32), (int) completionPosition); >+ // complete field members with missing fields type >+ // class X { >+ // Missing f; >+ // void foo() { >+ // f.| >+ // } >+ // } >+ if (this.assistNodeInJavadoc == 0 && >+ (this.requestor.isAllowingRequiredProposals(CompletionProposal.FIELD_REF, CompletionProposal.TYPE_REF) || >+ this.requestor.isAllowingRequiredProposals(CompletionProposal.METHOD_REF, CompletionProposal.TYPE_REF) || >+ this.requestor.isAllowingRequiredProposals(CompletionProposal.TYPE_REF, CompletionProposal.TYPE_REF))) { >+ if(ref.tokens.length == 1) { >+ boolean foundSomeFields = findFieldsAndMethodsFromMissingFieldType(ref.tokens[0], scope, ref, insideTypeAnnotation); >+ >+ if (!foundSomeFields) { >+ >+ checkCancel(); >+ >+ findMembersFromMissingType( >+ ref.tokens[0], >+ ref.sourcePositions[0], >+ null, >+ scope, >+ ref, >+ ref.isInsideAnnotationAttribute); >+ } >+ } >+ } >+ } else if (qualifiedBinding instanceof VariableBinding) { >+ setSourceAndTokenRange((int) (completionPosition >>> 32), (int) completionPosition); >+ TypeBinding receiverType = ((VariableBinding) qualifiedBinding).type; >+ if (receiverType != null && (receiverType.tagBits & TagBits.HasMissingType) == 0) { >+ ObjectVector fieldsFound = new ObjectVector(); >+ ObjectVector methodsFound = new ObjectVector(); > >- receiverStart = (int) (qualifiedNameReference.sourcePositions[0] >>> 32); >- receiverEnd = (int) qualifiedNameReference.sourcePositions[qualifiedNameReference.tokens.length - 1] + 1; >+ findFieldsAndMethods( >+ this.completionToken, >+ receiverType.capture(scope, ref.sourceEnd), >+ scope, >+ fieldsFound, >+ methodsFound, >+ ref, >+ scope, >+ false, >+ false, >+ null, >+ null, >+ null, >+ false, >+ null, >+ -1, >+ -1); >+ >+ checkCancel(); > >- // if (local instanceof X) local.| >- // if (field instanceof X) field.| >- if (instanceOfExpression.expression instanceof SingleNameReference && >- ((SingleNameReference)instanceOfExpression.expression).binding == qualifiedBinding && >- (qualifiedBinding instanceof LocalVariableBinding || qualifiedBinding instanceof FieldBinding)) { >- findFromAnotherReceiver = true; >- } >+ findFieldsAndMethodsFromCastedReceiver( >+ enclosingNode, >+ qualifiedBinding, >+ scope, >+ fieldsFound, >+ methodsFound, >+ ref, >+ scope, >+ ref); > >- // if (this.field instanceof X) field.| >- if (instanceOfExpression.expression instanceof FieldReference) { >- FieldReference fieldReference = (FieldReference)instanceOfExpression.expression; >+ } else if (this.assistNodeInJavadoc == 0 && >+ (this.requestor.isAllowingRequiredProposals(CompletionProposal.FIELD_REF, CompletionProposal.TYPE_REF) || >+ this.requestor.isAllowingRequiredProposals(CompletionProposal.METHOD_REF, CompletionProposal.TYPE_REF))) { >+ boolean proposeField = !this.requestor.isIgnored(CompletionProposal.FIELD_REF); >+ boolean proposeMethod = !this.requestor.isIgnored(CompletionProposal.METHOD_REF); >+ if (proposeField || proposeMethod) { >+ if(ref.tokens.length == 1) { >+ if (qualifiedBinding instanceof LocalVariableBinding) { >+ // complete local variable members with missing variables type >+ // class X { >+ // void foo() { >+ // Missing f; >+ // f.| >+ // } >+ // } >+ LocalVariableBinding localVariableBinding = (LocalVariableBinding) qualifiedBinding; >+ findFieldsAndMethodsFromMissingType( >+ localVariableBinding.declaration.type, >+ localVariableBinding.declaringScope, >+ ref, >+ scope); >+ } else { >+ // complete field members with missing fields type >+ // class X { >+ // Missing f; >+ // void foo() { >+ // f.| >+ // } >+ // } >+ findFieldsAndMethodsFromMissingFieldType(ref.tokens[0], scope, ref, insideTypeAnnotation); >+ } > >- if (fieldReference.receiver instanceof ThisReference && >- qualifiedBinding instanceof FieldBinding && >- fieldReference.binding == qualifiedBinding) { >- findFromAnotherReceiver = true; >+ } > } > } >- } else if (receiver instanceof FieldReference) { >- FieldReference fieldReference1 = (FieldReference) receiver; >- >- receiverStart = fieldReference1.sourceStart; >- receiverEnd = fieldReference1.sourceEnd + 1; > >- if (fieldReference1.receiver instanceof ThisReference) { >+ } else if (qualifiedBinding instanceof ReferenceBinding && !(qualifiedBinding instanceof TypeVariableBinding)) { >+ boolean isInsideAnnotationAttribute = ref.isInsideAnnotationAttribute; >+ ReferenceBinding receiverType = (ReferenceBinding) qualifiedBinding; >+ setSourceAndTokenRange((int) (completionPosition >>> 32), (int) completionPosition); > >- receiverName = new char[][] {THIS, fieldReference1.token}; >+ findMembers( >+ this.completionToken, >+ receiverType, >+ scope, >+ ref, >+ isInsideAnnotationAttribute, >+ null, >+ null, >+ null, >+ false); > >- // if (field instanceof X) this.field.| >- if (instanceOfExpression.expression instanceof SingleNameReference && >- ((SingleNameReference)instanceOfExpression.expression).binding == fieldReference1.binding) { >- findFromAnotherReceiver = true; >- } >+ } else if (qualifiedBinding instanceof PackageBinding) { > >- // if (this.field instanceof X) this.field.| >- if (instanceOfExpression.expression instanceof FieldReference) { >- FieldReference fieldReference2 = (FieldReference)instanceOfExpression.expression; >+ setSourceRange(astNode.sourceStart, (int) completionPosition); >+ setTokenRange((int) (completionPosition >>> 32), (int) completionPosition); > >- if (fieldReference2.receiver instanceof ThisReference && >- fieldReference2.binding == fieldReference1.binding) { >- findFromAnotherReceiver = true; >- } >- } >- } >+ // replace to the end of the completion identifier >+ findTypesAndSubpackages(this.completionToken, (PackageBinding) qualifiedBinding, scope); > } >+ } >+ >+ private void completionOnQualifiedTypeReference(ASTNode astNode, ASTNode astNodeParent, Binding qualifiedBinding, >+ Scope scope) { >+ this.insideQualifiedReference = true; > >- if (findFromAnotherReceiver) { >- TypeBinding receiverTypeBinding = instanceOfType.resolvedType; >- char[] castedReceiver = null; >+ CompletionOnQualifiedTypeReference ref = >+ (CompletionOnQualifiedTypeReference) astNode; > >- char[] castedTypeChars = CharOperation.concatWith(instanceOfType.getTypeName(), '.'); >- if(this.source != null) { >- int memberRefStart = this.startPosition; >+ this.assistNodeIsClass = ref.isClass(); >+ this.assistNodeIsException = ref.isException(); >+ this.assistNodeIsInterface = ref.isInterface(); >+ this.assistNodeIsSuperType = ref.isSuperType(); > >- char[] receiverChars = CharOperation.subarray(this.source, receiverStart, receiverEnd); >- char[] dotChars = CharOperation.subarray(this.source, receiverEnd, memberRefStart); >+ this.completionToken = ref.completionIdentifier; >+ long completionPosition = ref.sourcePositions[ref.tokens.length]; > >- castedReceiver = >- CharOperation.concat( >- CharOperation.concat( >- '(', >- CharOperation.concat( >- CharOperation.concat('(', castedTypeChars, ')'), >- receiverChars), >- ')'), >- dotChars); >- } else { >- castedReceiver = >- CharOperation.concat( >- CharOperation.concat( >- '(', >- CharOperation.concat( >- CharOperation.concat('(', castedTypeChars, ')'), >- CharOperation.concatWith(receiverName, '.')), >- ')'), >- DOT); >+ // get the source positions of the completion identifier >+ if (qualifiedBinding.problemId() == ProblemReasons.NotFound) { >+ setSourceAndTokenRange((int) (completionPosition >>> 32), (int) completionPosition); >+ if (this.assistNodeInJavadoc == 0 && >+ (this.requestor.isAllowingRequiredProposals(CompletionProposal.TYPE_REF, CompletionProposal.TYPE_REF))) { >+ if(ref.tokens.length == 1) { >+ findMemberTypesFromMissingType( >+ ref.tokens[0], >+ ref.sourcePositions[0], >+ scope); >+ } > } >+ } else if (qualifiedBinding instanceof ReferenceBinding && !(qualifiedBinding instanceof TypeVariableBinding)) { >+ if (!this.requestor.isIgnored(CompletionProposal.TYPE_REF)) { >+ setSourceAndTokenRange((int) (completionPosition >>> 32), (int) completionPosition); > >- if (castedReceiver == null) return; >+ ObjectVector typesFound = new ObjectVector(); > >- int oldStartPosition = this.startPosition; >- this.startPosition = receiverStart; >+ if (this.assistNodeIsException && astNodeParent instanceof TryStatement) { >+ findExceptionFromTryStatement( >+ this.completionToken, >+ (ReferenceBinding)qualifiedBinding, >+ scope.enclosingSourceType(), >+ (BlockScope)scope, >+ typesFound); >+ } >+ >+ checkCancel(); > >- findFieldsAndMethods( >+ findMemberTypes( > this.completionToken, >- receiverTypeBinding, >+ (ReferenceBinding) qualifiedBinding, > scope, >- fieldsFound, >- methodsFound, >- invocationSite, >- invocationScope, >+ scope.enclosingSourceType(), > false, > false, >+ typesFound, > null, > null, > null, >- false, >- castedReceiver, >- receiverStart, >- receiverEnd); >+ false); >+ } >+ } else if (qualifiedBinding instanceof PackageBinding) { > >- this.startPosition = oldStartPosition; >+ setSourceRange(astNode.sourceStart, (int) completionPosition); >+ setTokenRange((int) (completionPosition >>> 32), (int) completionPosition); >+ // replace to the end of the completion identifier >+ findTypesAndSubpackages(this.completionToken, (PackageBinding) qualifiedBinding, scope); > } > } >+ >+ private void completionOnSingleNameReference(ASTNode astNode, ASTNode astNodeParent, Scope scope, >+ boolean insideTypeAnnotation) { >+ CompletionOnSingleNameReference singleNameReference = (CompletionOnSingleNameReference) astNode; >+ this.completionToken = singleNameReference.token; >+ SwitchStatement switchStatement = astNodeParent instanceof SwitchStatement ? (SwitchStatement) astNodeParent : null; >+ if (switchStatement != null >+ && switchStatement.expression.resolvedType != null >+ && switchStatement.expression.resolvedType.isEnum()) { >+ if (!this.requestor.isIgnored(CompletionProposal.FIELD_REF)) { >+ this.assistNodeIsEnum = true; >+ findEnumConstantsFromSwithStatement(this.completionToken, (SwitchStatement) astNodeParent); >+ } >+ } else if (this.expectedTypesPtr > -1 && this.expectedTypes[0].isAnnotationType()) { >+ findTypesAndPackages(this.completionToken, scope, false, false, new ObjectVector()); >+ } else { >+ if (this.expectedTypesPtr > -1) { >+ this.assistNodeIsEnum = true; >+ done : for (int i = 0; i <= this.expectedTypesPtr; i++) { >+ if (!this.expectedTypes[i].isEnum()) { >+ this.assistNodeIsEnum = false; >+ break done; >+ } >+ } > >- public void complete(IType type, char[] snippet, int position, char[][] localVariableTypeNames, char[][] localVariableNames, int[] localVariableModifiers, boolean isStatic){ >- if(this.requestor != null){ >- this.requestor.beginReporting(); >- } >- boolean contextAccepted = false; >- IType topLevelType = type; >- while(topLevelType.getDeclaringType() != null) { >- topLevelType = topLevelType.getDeclaringType(); >+ } >+ if (scope instanceof BlockScope && !this.requestor.isIgnored(CompletionProposal.LOCAL_VARIABLE_REF)) { >+ char[][] alreadyDefinedName = computeAlreadyDefinedName((BlockScope)scope, singleNameReference); >+ >+ findUnresolvedReference( >+ singleNameReference.sourceStart, >+ singleNameReference.sourceEnd, >+ (BlockScope)scope, >+ alreadyDefinedName); >+ } >+ >+ checkCancel(); >+ >+ findVariablesAndMethods( >+ this.completionToken, >+ scope, >+ singleNameReference, >+ scope, >+ insideTypeAnnotation, >+ singleNameReference.isInsideAnnotationAttribute); >+ >+ checkCancel(); >+ >+ // can be the start of a qualified type name >+ findTypesAndPackages(this.completionToken, scope, true, false, new ObjectVector()); >+ if (!this.requestor.isIgnored(CompletionProposal.KEYWORD)) { >+ if (this.completionToken != null && this.completionToken.length != 0) { >+ findKeywords(this.completionToken, singleNameReference.possibleKeywords, false, false); >+ } else { >+ findTrueOrFalseKeywords(singleNameReference.possibleKeywords); >+ } >+ } >+ if (singleNameReference.canBeExplicitConstructor && !this.requestor.isIgnored(CompletionProposal.METHOD_REF)){ >+ if (CharOperation.prefixEquals(this.completionToken, Keywords.THIS, false)) { >+ ReferenceBinding ref = scope.enclosingSourceType(); >+ findExplicitConstructors(Keywords.THIS, ref, (MethodScope)scope, singleNameReference); >+ } else if (CharOperation.prefixEquals(this.completionToken, Keywords.SUPER, false)) { >+ ReferenceBinding ref = scope.enclosingSourceType(); >+ findExplicitConstructors(Keywords.SUPER, ref.superclass(), (MethodScope)scope, singleNameReference); >+ } >+ } > } >+ } >+ >+ private void completionOnSingleTypeReference(ASTNode astNode, ASTNode astNodeParent, Binding qualifiedBinding, Scope scope) { >+ CompletionOnSingleTypeReference singleRef = (CompletionOnSingleTypeReference) astNode; > >- this.fileName = topLevelType.getParent().getElementName().toCharArray(); >- CompilationResult compilationResult = new CompilationResult(this.fileName, 1, 1, this.compilerOptions.maxProblemsPerUnit); >+ this.completionToken = singleRef.token; > >- CompilationUnitDeclaration compilationUnit = null; >+ this.assistNodeIsClass = singleRef.isClass(); >+ this.assistNodeIsException = singleRef.isException(); >+ this.assistNodeIsInterface = singleRef.isInterface(); >+ this.assistNodeIsConstructor = singleRef.isConstructorType; >+ this.assistNodeIsSuperType = singleRef.isSuperType(); >+ >+ // can be the start of a qualified type name >+ if (qualifiedBinding == null) { >+ if (this.completionToken.length == 0 && >+ (astNodeParent instanceof ParameterizedSingleTypeReference || >+ astNodeParent instanceof ParameterizedQualifiedTypeReference)) { >+ this.setSourceAndTokenRange(astNode.sourceStart, astNode.sourceStart - 1, false); > >- try { >- // TypeConverter is used instead of SourceTypeConverter because the type >- // to convert can be a binary type or a source type >- TypeDeclaration typeDeclaration = null; >- if (type instanceof SourceType) { >- SourceType sourceType = (SourceType) type; >- ISourceType info = (ISourceType) sourceType.getElementInfo(); >- compilationUnit = SourceTypeConverter.buildCompilationUnit( >- new ISourceType[] {info},//sourceTypes[0] is always toplevel here >- SourceTypeConverter.FIELD_AND_METHOD // need field and methods >- | SourceTypeConverter.MEMBER_TYPE, // need member types >- // no need for field initialization >- this.problemReporter, >- compilationResult); >- if (compilationUnit.types != null) >- typeDeclaration = compilationUnit.types[0]; >+ findParameterizedType((TypeReference)astNodeParent, scope); > } else { >- compilationUnit = new CompilationUnitDeclaration(this.problemReporter, compilationResult, 0); >- typeDeclaration = new BinaryTypeConverter(this.parser.problemReporter(), compilationResult, null/*no need to remember type names*/).buildTypeDeclaration(type, compilationUnit); >- } >- >- if(typeDeclaration != null) { >- // build AST from snippet >- Initializer fakeInitializer = parseSnippeInitializer(snippet, position, localVariableTypeNames, localVariableNames, localVariableModifiers, isStatic); >- >- // merge AST >- FieldDeclaration[] oldFields = typeDeclaration.fields; >- FieldDeclaration[] newFields = null; >- if (oldFields != null) { >- newFields = new FieldDeclaration[oldFields.length + 1]; >- System.arraycopy(oldFields, 0, newFields, 0, oldFields.length); >- newFields[oldFields.length] = fakeInitializer; >- } else { >- newFields = new FieldDeclaration[] {fakeInitializer}; >- } >- typeDeclaration.fields = newFields; >- >- if(DEBUG) { >- System.out.println("SNIPPET COMPLETION AST :"); //$NON-NLS-1$ >- System.out.println(compilationUnit.toString()); >- } >- >- if (compilationUnit.types != null) { >- try { >- this.lookupEnvironment.buildTypeBindings(compilationUnit, null /*no access restriction*/); >- >- if ((this.unitScope = compilationUnit.scope) != null) { >- this.lookupEnvironment.completeTypeBindings(compilationUnit, true); >- compilationUnit.scope.faultInTypes(); >- compilationUnit.resolve(); >- } >- } catch (CompletionNodeFound e) { >- // completionNodeFound = true; >- if (e.astNode != null) { >- // if null then we found a problem in the completion node >- contextAccepted = >- complete( >- e.astNode, >- this.parser.assistNodeParent, >- this.parser.enclosingNode, >- compilationUnit, >- e.qualifiedBinding, >- e.scope, >- e.insideTypeAnnotation); >- } >- } >- } >- if(this.noProposal && this.problem != null) { >- if(!contextAccepted) { >- contextAccepted = true; >- InternalCompletionContext context = new InternalCompletionContext(); >- if (this.requestor.isExtendedContextRequired()) context.setExtended(); >- this.requestor.acceptContext(context); >- } >- this.requestor.completionFailure(this.problem); >- if(DEBUG) { >- this.printDebug(this.problem); >- } >+ ObjectVector typesFound = new ObjectVector(); >+ if (this.assistNodeIsException && astNodeParent instanceof TryStatement) { >+ findExceptionFromTryStatement( >+ this.completionToken, >+ null, >+ scope.enclosingSourceType(), >+ (BlockScope)scope, >+ typesFound); > } >+ >+ checkCancel(); >+ >+ findTypesAndPackages(this.completionToken, scope, this.assistNodeIsConstructor, false, typesFound); > } >- } catch (IndexOutOfBoundsException e) { // work-around internal failure - 1GEMF6D (added with fix of 99629) >- if(DEBUG) { >- System.out.println("Exception caught by CompletionEngine:"); //$NON-NLS-1$ >- e.printStackTrace(System.out); >- } >- } catch (InvalidCursorLocation e) { // may eventually report a usefull error (added to fix 99629) >- if(DEBUG) { >- System.out.println("Exception caught by CompletionEngine:"); //$NON-NLS-1$ >- e.printStackTrace(System.out); >- } >- } catch (AbortCompilation e) { // ignore this exception for now since it typically means we cannot find java.lang.Object (added with fix of 99629) >- if(DEBUG) { >- System.out.println("Exception caught by CompletionEngine:"); //$NON-NLS-1$ >- e.printStackTrace(System.out); >- } >- } catch (CompletionNodeFound e){ // internal failure - bugs 5618 (added with fix of 99629) >- if(DEBUG) { >- System.out.println("Exception caught by CompletionEngine:"); //$NON-NLS-1$ >- e.printStackTrace(System.out); >- } >- } catch(JavaModelException e) { >- // Do nothing >- } >- if(!contextAccepted) { >- contextAccepted = true; >- InternalCompletionContext context = new InternalCompletionContext(); >- if (this.requestor.isExtendedContextRequired()) context.setExtended(); >- this.requestor.acceptContext(context); >- } >- if(this.requestor != null){ >- this.requestor.endReporting(); >+ } else if (!this.requestor.isIgnored(CompletionProposal.TYPE_REF)) { >+ findMemberTypes( >+ this.completionToken, >+ (ReferenceBinding) qualifiedBinding, >+ scope, >+ scope.enclosingSourceType(), >+ false, >+ false, >+ false, >+ false, >+ !this.assistNodeIsConstructor, >+ null, >+ new ObjectVector(), >+ null, >+ null, >+ null, >+ false); > } > } > >- private Initializer parseSnippeInitializer(char[] snippet, int position, char[][] localVariableTypeNames, char[][] localVariableNames, int[] localVariableModifiers, boolean isStatic){ >- StringBuffer prefix = new StringBuffer(); >- prefix.append("public class FakeType {\n "); //$NON-NLS-1$ >- if(isStatic) { >- prefix.append("static "); //$NON-NLS-1$ >- } >- prefix.append("{\n"); //$NON-NLS-1$ >- for (int i = 0; i < localVariableTypeNames.length; i++) { >- ASTNode.printModifiers(localVariableModifiers[i], prefix); >- prefix.append(' '); >- prefix.append(localVariableTypeNames[i]); >- prefix.append(' '); >- prefix.append(localVariableNames[i]); >- prefix.append(';'); >- } >+ private char[][] computeAlreadyDefinedName( >+ BlockScope scope, >+ InvocationSite invocationSite) { >+ ArrayList result = new ArrayList(); > >- char[] fakeSource = CharOperation.concat(prefix.toString().toCharArray(), snippet, "}}".toCharArray());//$NON-NLS-1$ >- this.offset = prefix.length(); >+ boolean staticsOnly = false; > >- String encoding = this.compilerOptions.defaultEncoding; >- BasicCompilationUnit fakeUnit = new BasicCompilationUnit( >- fakeSource, >- null, >- "FakeType.java", //$NON-NLS-1$ >- encoding); >+ Scope currentScope = scope; > >- this.actualCompletionPosition = prefix.length() + position - 1; >+ done1 : while (true) { // done when a COMPILATION_UNIT_SCOPE is found > >- CompilationResult fakeResult = new CompilationResult(fakeUnit, 1, 1, this.compilerOptions.maxProblemsPerUnit); >- CompilationUnitDeclaration fakeAST = this.parser.dietParse(fakeUnit, fakeResult, this.actualCompletionPosition); >+ switch (currentScope.kind) { > >- parseBlockStatements(fakeAST, this.actualCompletionPosition); >+ case Scope.METHOD_SCOPE : >+ // handle the error case inside an explicit constructor call (see MethodScope>>findField) >+ MethodScope methodScope = (MethodScope) currentScope; >+ staticsOnly |= methodScope.isStatic | methodScope.isConstructorCall; > >- return (Initializer)fakeAST.types[0].fields[0]; >- } >+ //$FALL-THROUGH$ >+ case Scope.BLOCK_SCOPE : >+ BlockScope blockScope = (BlockScope) currentScope; > >- /** >- * Ask the engine to compute a completion at the specified position >- * of the given compilation unit. >- * >- * No return >- * completion results are answered through a requestor. >- * >- * @param sourceUnit org.eclipse.jdt.internal.compiler.env.ICompilationUnit >- * the source of the current compilation unit. >- * >- * @param completionPosition int >- * a position in the source where the completion is taking place. >- * This position is relative to the source provided. >- */ >- public void complete(ICompilationUnit sourceUnit, int completionPosition, int pos, ITypeRoot root) { >+ next : for (int i = 0, length = blockScope.locals.length; i < length; i++) { >+ LocalVariableBinding local = blockScope.locals[i]; > >- if(DEBUG) { >- System.out.print("COMPLETION IN "); //$NON-NLS-1$ >- System.out.print(sourceUnit.getFileName()); >- System.out.print(" AT POSITION "); //$NON-NLS-1$ >- System.out.println(completionPosition); >- System.out.println("COMPLETION - Source :"); //$NON-NLS-1$ >- System.out.println(sourceUnit.getContents()); >- } >- this.requestor.beginReporting(); >- boolean contextAccepted = false; >- try { >- this.fileName = sourceUnit.getFileName(); >- this.actualCompletionPosition = completionPosition - 1; >- this.offset = pos; >- this.typeRoot = root; >- // for now until we can change the UI. >- CompilationResult result = new CompilationResult(sourceUnit, 1, 1, this.compilerOptions.maxProblemsPerUnit); >- CompilationUnitDeclaration parsedUnit = this.parser.dietParse(sourceUnit, result, this.actualCompletionPosition); >+ if (local == null) >+ break next; > >- // boolean completionNodeFound = false; >- if (parsedUnit != null) { >- if(DEBUG) { >- System.out.println("COMPLETION - Diet AST :"); //$NON-NLS-1$ >- System.out.println(parsedUnit.toString()); >- } >+ if (local.isSecret()) >+ continue next; > >- // scan the package & import statements first >- if (parsedUnit.currentPackage instanceof CompletionOnPackageReference) { >- contextAccepted = true; >- buildContext(parsedUnit.currentPackage, null, parsedUnit, null, null); >- if(!this.requestor.isIgnored(CompletionProposal.PACKAGE_REF)) { >- findPackages((CompletionOnPackageReference) parsedUnit.currentPackage); >- } >- if(this.noProposal && this.problem != null) { >- this.requestor.completionFailure(this.problem); >- if(DEBUG) { >- this.printDebug(this.problem); >- } >+ result.add(local.name); > } >- return; >- } >- >- ImportReference[] imports = parsedUnit.imports; >- if (imports != null) { >- for (int i = 0, length = imports.length; i < length; i++) { >- ImportReference importReference = imports[i]; >- if (importReference instanceof CompletionOnImportReference) { >- this.lookupEnvironment.buildTypeBindings(parsedUnit, null /*no access restriction*/); >- if ((this.unitScope = parsedUnit.scope) != null) { >- contextAccepted = true; >- buildContext(importReference, null, parsedUnit, null, null); >+ break; > >- long positions = importReference.sourcePositions[importReference.sourcePositions.length - 1]; >- setSourceAndTokenRange((int) (positions >>> 32), (int) positions); >+ case Scope.CLASS_SCOPE : >+ ClassScope classScope = (ClassScope) currentScope; >+ SourceTypeBinding enclosingType = classScope.referenceContext.binding; >+ computeAlreadyDefinedName( >+ enclosingType, >+ classScope, >+ staticsOnly, >+ invocationSite, >+ result); >+ staticsOnly |= enclosingType.isStatic(); >+ break; > >- char[][] oldTokens = importReference.tokens; >- int tokenCount = oldTokens.length; >- if (tokenCount == 1) { >- findImports((CompletionOnImportReference)importReference, true); >- } else if(tokenCount > 1){ >- this.insideQualifiedReference = true; >+ case Scope.COMPILATION_UNIT_SCOPE : >+ break done1; >+ } >+ currentScope = currentScope.parent; >+ } > >- char[] lastToken = oldTokens[tokenCount - 1]; >- char[][] qualifierTokens = CharOperation.subarray(oldTokens, 0, tokenCount - 1); >+ if (result.size() == 0) return CharOperation.NO_CHAR_CHAR; > >- Binding binding = this.unitScope.getTypeOrPackage(qualifierTokens); >- if(binding != null) { >- if(binding instanceof PackageBinding) { >- findImports((CompletionOnImportReference)importReference, false); >- } else { >- ReferenceBinding ref = (ReferenceBinding) binding; >+ return (char[][])result.toArray(new char[result.size()][]); >+ } > >- if(!this.requestor.isIgnored(CompletionProposal.TYPE_REF)) { >- findImportsOfMemberTypes(lastToken, ref, importReference.isStatic()); >- } >- if(importReference.isStatic()) { >+ private void computeAlreadyDefinedName( >+ FieldBinding[] fields, >+ Scope scope, >+ boolean onlyStaticFields, >+ ReferenceBinding receiverType, >+ InvocationSite invocationSite, >+ ArrayList result) { > >- if(!this.requestor.isIgnored(CompletionProposal.FIELD_REF)) { >- findImportsOfStaticFields(lastToken, ref); >- } >- if(!this.requestor.isIgnored(CompletionProposal.METHOD_NAME_REFERENCE)) { >- findImportsOfStaticMethods(lastToken, ref); >- } >- } >- } >- } >- } >+ next : for (int f = fields.length; --f >= 0;) { >+ FieldBinding field = fields[f]; > >- if(this.noProposal && this.problem != null) { >- this.requestor.completionFailure(this.problem); >- if(DEBUG) { >- this.printDebug(this.problem); >- } >- } >- } >- return; >- } else if(importReference instanceof CompletionOnKeyword) { >- contextAccepted = true; >- buildContext(importReference, null, parsedUnit, null, null); >- if(!this.requestor.isIgnored(CompletionProposal.KEYWORD)) { >- setSourceAndTokenRange(importReference.sourceStart, importReference.sourceEnd); >- CompletionOnKeyword keyword = (CompletionOnKeyword)importReference; >- findKeywords(keyword.getToken(), keyword.getPossibleKeywords(), false, false); >- } >- if(this.noProposal && this.problem != null) { >- this.requestor.completionFailure(this.problem); >- if(DEBUG) { >- this.printDebug(this.problem); >- } >- } >- return; >- } >- } >- } >+ if (field.isSynthetic()) continue next; > >- if (parsedUnit.types != null) { >- try { >- this.lookupEnvironment.buildTypeBindings(parsedUnit, null /*no access restriction*/); >+ if (onlyStaticFields && !field.isStatic()) continue next; > >- if ((this.unitScope = parsedUnit.scope) != null) { >- this.source = sourceUnit.getContents(); >- this.lookupEnvironment.completeTypeBindings(parsedUnit, true); >- parsedUnit.scope.faultInTypes(); >- parseBlockStatements(parsedUnit, this.actualCompletionPosition); >- if(DEBUG) { >- System.out.println("COMPLETION - AST :"); //$NON-NLS-1$ >- System.out.println(parsedUnit.toString()); >- } >- parsedUnit.resolve(); >- } >- } catch (CompletionNodeFound e) { >- // completionNodeFound = true; >- if (e.astNode != null) { >- // if null then we found a problem in the completion node >- if(DEBUG) { >- System.out.print("COMPLETION - Completion node : "); //$NON-NLS-1$ >- System.out.println(e.astNode.toString()); >- if(this.parser.assistNodeParent != null) { >- System.out.print("COMPLETION - Parent Node : "); //$NON-NLS-1$ >- System.out.println(this.parser.assistNodeParent); >- } >- } >- this.lookupEnvironment.unitBeingCompleted = parsedUnit; // better resilient to further error reporting >- contextAccepted = >- complete( >- e.astNode, >- this.parser.assistNodeParent, >- this.parser.enclosingNode, >- parsedUnit, >- e.qualifiedBinding, >- e.scope, >- e.insideTypeAnnotation); >- } >+ if (!field.canBeSeenBy(receiverType, invocationSite, scope)) continue next; >+ >+ result.add(field.name); >+ } >+ } >+ >+ private void computeAlreadyDefinedName( >+ SourceTypeBinding receiverType, >+ ClassScope scope, >+ boolean onlyStaticFields, >+ InvocationSite invocationSite, >+ ArrayList result) { >+ >+ ReferenceBinding currentType = receiverType; >+ ReferenceBinding[] interfacesToVisit = null; >+ int nextPosition = 0; >+ do { >+ ReferenceBinding[] itsInterfaces = currentType.superInterfaces(); >+ if (itsInterfaces != Binding.NO_SUPERINTERFACES) { >+ if (interfacesToVisit == null) { >+ interfacesToVisit = itsInterfaces; >+ nextPosition = interfacesToVisit.length; >+ } else { >+ int itsLength = itsInterfaces.length; >+ if (nextPosition + itsLength >= interfacesToVisit.length) >+ System.arraycopy(interfacesToVisit, 0, interfacesToVisit = new ReferenceBinding[nextPosition + itsLength + 5], 0, nextPosition); >+ nextInterface : for (int a = 0; a < itsLength; a++) { >+ ReferenceBinding next = itsInterfaces[a]; >+ for (int b = 0; b < nextPosition; b++) >+ if (next == interfacesToVisit[b]) continue nextInterface; >+ interfacesToVisit[nextPosition++] = next; > } > } > } > >- if(this.noProposal && this.problem != null) { >- if(!contextAccepted) { >- contextAccepted = true; >- InternalCompletionContext context = new InternalCompletionContext(); >- context.setOffset(completionPosition - this.offset); >- context.setTokenKind(CompletionContext.TOKEN_KIND_UNKNOWN); >- if (this.requestor.isExtendedContextRequired()) context.setExtended(); >- this.requestor.acceptContext(context); >- } >- this.requestor.completionFailure(this.problem); >- if(DEBUG) { >- this.printDebug(this.problem); >- } >- } >- /* Ignore package, import, class & interface keywords for now... >- if (!completionNodeFound) { >- if (parsedUnit == null || parsedUnit.types == null) { >- // this is not good enough... can still be trying to define a second type >- CompletionScanner scanner = (CompletionScanner) this.parser.scanner; >- setSourceRange(scanner.completedIdentifierStart, scanner.completedIdentifierEnd); >- findKeywords(scanner.completionIdentifier, mainDeclarations, null); >- } >- // currently have no way to know if extends/implements are possible keywords >- } >- */ >- } catch (IndexOutOfBoundsException e) { // work-around internal failure - 1GEMF6D >- if(DEBUG) { >- System.out.println("Exception caught by CompletionEngine:"); //$NON-NLS-1$ >- e.printStackTrace(System.out); >- } >- } catch (InvalidCursorLocation e) { // may eventually report a usefull error >- if(DEBUG) { >- System.out.println("Exception caught by CompletionEngine:"); //$NON-NLS-1$ >- e.printStackTrace(System.out); >- } >- } catch (AbortCompilation e) { // ignore this exception for now since it typically means we cannot find java.lang.Object >- if(DEBUG) { >- System.out.println("Exception caught by CompletionEngine:"); //$NON-NLS-1$ >- e.printStackTrace(System.out); >- } >- } catch (CompletionNodeFound e){ // internal failure - bugs 5618 >- if(DEBUG) { >- System.out.println("Exception caught by CompletionEngine:"); //$NON-NLS-1$ >- e.printStackTrace(System.out); >- } >- } finally { >- reset(); >- if(!contextAccepted) { >- contextAccepted = true; >- InternalCompletionContext context = new InternalCompletionContext(); >- context.setTokenKind(CompletionContext.TOKEN_KIND_UNKNOWN); >- context.setOffset(completionPosition - this.offset); >- if (this.requestor.isExtendedContextRequired()) context.setExtended(); >- this.requestor.acceptContext(context); >+ FieldBinding[] fields = currentType.availableFields(); >+ if(fields != null && fields.length > 0) { >+ computeAlreadyDefinedName( >+ fields, >+ scope, >+ onlyStaticFields, >+ receiverType, >+ invocationSite, >+ result); > } >- this.requestor.endReporting(); >- } >- } >+ currentType = currentType.superclass(); >+ } while ( currentType != null); > >- private long computeTargetedElement(CompletionOnAnnotationOfType fakeNode) { >- ASTNode annotatedElement = fakeNode.potentialAnnotatedNode; >+ if (interfacesToVisit != null) { >+ for (int i = 0; i < nextPosition; i++) { >+ ReferenceBinding anInterface = interfacesToVisit[i]; >+ FieldBinding[] fields = anInterface.availableFields(); >+ if(fields != null) { >+ computeAlreadyDefinedName( >+ fields, >+ scope, >+ onlyStaticFields, >+ receiverType, >+ invocationSite, >+ result); >+ } > >- if (annotatedElement instanceof TypeDeclaration) { >- TypeDeclaration annotatedTypeDeclaration = (TypeDeclaration) annotatedElement; >- if (TypeDeclaration.kind(annotatedTypeDeclaration.modifiers) == TypeDeclaration.ANNOTATION_TYPE_DECL) { >- return TagBits.AnnotationForAnnotationType | TagBits.AnnotationForType; >- } >- return TagBits.AnnotationForType; >- } else if (annotatedElement instanceof FieldDeclaration) { >- if (fakeNode.isParameter) { >- return TagBits.AnnotationForParameter; >+ ReferenceBinding[] itsInterfaces = anInterface.superInterfaces(); >+ if (itsInterfaces != Binding.NO_SUPERINTERFACES) { >+ int itsLength = itsInterfaces.length; >+ if (nextPosition + itsLength >= interfacesToVisit.length) >+ System.arraycopy(interfacesToVisit, 0, interfacesToVisit = new ReferenceBinding[nextPosition + itsLength + 5], 0, nextPosition); >+ nextInterface : for (int a = 0; a < itsLength; a++) { >+ ReferenceBinding next = itsInterfaces[a]; >+ for (int b = 0; b < nextPosition; b++) >+ if (next == interfacesToVisit[b]) continue nextInterface; >+ interfacesToVisit[nextPosition++] = next; >+ } >+ } > } >- return TagBits.AnnotationForField; >- } else if (annotatedElement instanceof MethodDeclaration) { >- return TagBits.AnnotationForMethod; >- } else if (annotatedElement instanceof Argument) { >- return TagBits.AnnotationForParameter; >- } else if (annotatedElement instanceof ConstructorDeclaration) { >- return TagBits.AnnotationForConstructor; >- } else if (annotatedElement instanceof LocalDeclaration) { >- return TagBits.AnnotationForLocalVariable; >- } else if (annotatedElement instanceof ImportReference) { >- return TagBits.AnnotationForPackage; > } >- return 0; > } > >- private TypeBinding[] computeTypes(Expression[] arguments) { >- if (arguments == null) return null; >- int argsLength = arguments.length; >- TypeBinding[] argTypes = new TypeBinding[argsLength]; >- for (int a = argsLength; --a >= 0;) { >- argTypes[a] = arguments[a].resolvedType; >- } >- return argTypes; >+ int computeBaseRelevance(){ >+ return R_DEFAULT; > } > >- private TypeBinding[] computeTypesIfCorrect(Expression[] arguments) { >- if (arguments == null) return null; >- int argsLength = arguments.length; >- TypeBinding[] argTypes = new TypeBinding[argsLength]; >- for (int a = argsLength; --a >= 0;) { >- TypeBinding typeBinding = arguments[a].resolvedType; >- if(typeBinding == null || !typeBinding.isValidBinding()) return null; >- argTypes[a] = typeBinding; >- } >- return argTypes; >- } >+ private void computeExpectedTypes(ASTNode parent, ASTNode node, Scope scope){ > >- private void findAnnotationAttributes(char[] token, MemberValuePair[] attributesFound, ReferenceBinding annotation) { >- MethodBinding[] methods = annotation.availableMethods(); >- nextAttribute: for (int i = 0; i < methods.length; i++) { >- MethodBinding method = methods[i]; >- >- if(!CharOperation.prefixEquals(token, method.selector, false) >- && !(this.options.camelCaseMatch && CharOperation.camelCaseMatch(token, method.selector))) continue nextAttribute; >+ // default filter >+ this.expectedTypesFilter = SUBTYPE; >+ this.hasJavaLangObjectAsExpectedType = false; > >- int length = attributesFound == null ? 0 : attributesFound.length; >- for (int j = 0; j < length; j++) { >- if(CharOperation.equals(method.selector, attributesFound[j].name, false)) continue nextAttribute; >+ // find types from parent >+ if(parent instanceof AbstractVariableDeclaration) { >+ AbstractVariableDeclaration variable = (AbstractVariableDeclaration)parent; >+ TypeBinding binding = variable.type.resolvedType; >+ if(binding != null) { >+ if(!(variable.initialization instanceof ArrayInitializer)) { >+ addExpectedType(binding, scope); >+ } > } >- >- int relevance = computeBaseRelevance(); >- relevance += computeRelevanceForResolution(); >- relevance += computeRelevanceForInterestingProposal(method); >- relevance += computeRelevanceForCaseMatching(token, method.selector); >- relevance += computeRelevanceForQualification(false); >- relevance += computeRelevanceForRestrictions(IAccessRule.K_ACCESSIBLE); >- >- this.noProposal = false; >- if(!this.requestor.isIgnored(CompletionProposal.ANNOTATION_ATTRIBUTE_REF)) { >- CompletionProposal proposal = createProposal(CompletionProposal.ANNOTATION_ATTRIBUTE_REF, this.actualCompletionPosition); >- proposal.setDeclarationSignature(getSignature(method.declaringClass)); >- proposal.setSignature(getSignature(method.returnType)); >- proposal.setName(method.selector); >- proposal.setCompletion(method.selector); >- proposal.setFlags(method.modifiers); >- proposal.setReplaceRange(this.startPosition - this.offset, this.endPosition - this.offset); >- proposal.setTokenRange(this.tokenStart - this.offset, this.tokenEnd - this.offset); >- proposal.setRelevance(relevance); >- this.requestor.accept(proposal); >- if(DEBUG) { >- this.printDebug(proposal); >+ } else if(parent instanceof Assignment) { >+ TypeBinding binding = ((Assignment)parent).lhs.resolvedType; >+ if(binding != null) { >+ addExpectedType(binding, scope); >+ } >+ } else if(parent instanceof ReturnStatement) { >+ if(scope.methodScope().referenceContext instanceof AbstractMethodDeclaration) { >+ MethodBinding methodBinding = ((AbstractMethodDeclaration) scope.methodScope().referenceContext).binding; >+ TypeBinding binding = methodBinding == null ? null : methodBinding.returnType; >+ if(binding != null) { >+ addExpectedType(binding, scope); > } > } >- } >- } >- private void findAnonymousType( >- ReferenceBinding currentType, >- TypeBinding[] argTypes, >- Scope scope, >- InvocationSite invocationSite) { >+ } else if(parent instanceof CastExpression) { >+ Expression e = ((CastExpression)parent).type; >+ TypeBinding binding = e.resolvedType; >+ if(binding != null){ >+ addExpectedType(binding, scope); >+ this.expectedTypesFilter = SUBTYPE | SUPERTYPE; >+ } >+ } else if(parent instanceof MessageSend) { >+ MessageSend messageSend = (MessageSend) parent; > >- if (currentType.isInterface()) { >- char[] completion = CharOperation.NO_CHAR; >- int relevance = computeBaseRelevance(); >- relevance += computeRelevanceForResolution(); >- relevance += computeRelevanceForInterestingProposal(); >- relevance += computeRelevanceForRestrictions(IAccessRule.K_ACCESSIBLE); >+ if(messageSend.actualReceiverType instanceof ReferenceBinding) { >+ ReferenceBinding binding = (ReferenceBinding)messageSend.actualReceiverType; >+ boolean isStatic = messageSend.receiver.isTypeReference(); > >- this.noProposal = false; >- if(!this.requestor.isIgnored(CompletionProposal.ANONYMOUS_CLASS_DECLARATION)) { >- InternalCompletionProposal proposal = createProposal(CompletionProposal.ANONYMOUS_CLASS_DECLARATION, this.actualCompletionPosition); >- proposal.setDeclarationSignature(getSignature(currentType)); >- proposal.setDeclarationKey(currentType.computeUniqueKey()); >- proposal.setSignature( >- createMethodSignature( >- CharOperation.NO_CHAR_CHAR, >- CharOperation.NO_CHAR_CHAR, >- CharOperation.NO_CHAR, >- CharOperation.NO_CHAR)); >- //proposal.setOriginalSignature(null); >- //proposal.setUniqueKey(null); >- proposal.setDeclarationPackageName(currentType.qualifiedPackageName()); >- proposal.setDeclarationTypeName(currentType.qualifiedSourceName()); >- //proposal.setParameterPackageNames(null); >- //proposal.setParameterTypeNames(null); >- //proposal.setPackageName(null); >- //proposal.setTypeName(null); >- proposal.setCompletion(completion); >- proposal.setFlags(Flags.AccPublic); >- proposal.setReplaceRange(this.endPosition - this.offset, this.endPosition - this.offset); >- proposal.setTokenRange(this.tokenEnd - this.offset, this.tokenEnd - this.offset); >- proposal.setRelevance(relevance); >- this.requestor.accept(proposal); >- if(DEBUG) { >- this.printDebug(proposal); >+ while(binding != null) { >+ computeExpectedTypesForMessageSend( >+ binding, >+ messageSend.selector, >+ messageSend.arguments, >+ (ReferenceBinding)messageSend.actualReceiverType, >+ scope, >+ messageSend, >+ isStatic); >+ computeExpectedTypesForMessageSendForInterface( >+ binding, >+ messageSend.selector, >+ messageSend.arguments, >+ (ReferenceBinding)messageSend.actualReceiverType, >+ scope, >+ messageSend, >+ isStatic); >+ binding = binding.superclass(); > } > } >- } else { >- findConstructors( >- currentType, >- argTypes, >- scope, >- invocationSite, >- true); >- } >- } >- >- private void findClassField( >- char[] token, >- TypeBinding receiverType, >- Scope scope, >- Binding[] missingElements, >- int[] missingElementsStarts, >- int[] missingElementsEnds, >- boolean missingElementsHaveProblems) { >- >- if (token == null) return; >+ } else if(parent instanceof AllocationExpression) { >+ AllocationExpression allocationExpression = (AllocationExpression) parent; > >- if (token.length <= classField.length >- && CharOperation.prefixEquals(token, classField, false /* ignore case */ >- )) { >- int relevance = computeBaseRelevance(); >- relevance += computeRelevanceForResolution(); >- relevance += computeRelevanceForInterestingProposal(); >- relevance += computeRelevanceForCaseMatching(token, classField); >- relevance += computeRelevanceForExpectingType(scope.getJavaLangClass()); >- relevance += computeRelevanceForRestrictions(IAccessRule.K_ACCESSIBLE); //no access restriction for class field >- relevance += R_NON_INHERITED; >+ ReferenceBinding binding = (ReferenceBinding)allocationExpression.type.resolvedType; > >- if (missingElements != null) { >- relevance += computeRelevanceForMissingElements(missingElementsHaveProblems); >+ if(binding != null) { >+ computeExpectedTypesForAllocationExpression( >+ binding, >+ allocationExpression.arguments, >+ scope, >+ allocationExpression); > } >- >- this.noProposal = false; >- if(!isIgnored(CompletionProposal.FIELD_REF, missingElements != null)) { >- InternalCompletionProposal proposal = createProposal(CompletionProposal.FIELD_REF, this.actualCompletionPosition); >- //proposal.setDeclarationSignature(null); >- char[] signature = >- createNonGenericTypeSignature( >- CharOperation.concatWith(JAVA_LANG, '.'), >- CLASS); >- if (this.compilerOptions.sourceLevel > ClassFileConstants.JDK1_4) { >- // add type argument >- char[] typeArgument = getTypeSignature(receiverType); >- int oldLength = signature.length; >- int argumentLength = typeArgument.length; >- int newLength = oldLength + argumentLength + 2; >- System.arraycopy(signature, 0, signature = new char[newLength], 0, oldLength - 1); >- signature[oldLength - 1] = '<'; >- System.arraycopy(typeArgument, 0, signature, oldLength , argumentLength); >- signature[newLength - 2] = '>'; >- signature[newLength - 1] = ';'; >+ } else if(parent instanceof OperatorExpression) { >+ int operator = (parent.bits & ASTNode.OperatorMASK) >> ASTNode.OperatorSHIFT; >+ if(parent instanceof ConditionalExpression) { >+ // for future use >+ } else if(parent instanceof InstanceOfExpression) { >+ InstanceOfExpression e = (InstanceOfExpression) parent; >+ TypeBinding binding = e.expression.resolvedType; >+ if(binding != null){ >+ addExpectedType(binding, scope); >+ this.expectedTypesFilter = SUBTYPE | SUPERTYPE; > } >- proposal.setSignature(signature); >- //proposal.setDeclarationPackageName(null); >- //proposal.setDeclarationTypeName(null); >- proposal.setPackageName(CharOperation.concatWith(JAVA_LANG, '.')); >- proposal.setTypeName(CLASS); >- proposal.setName(classField); >- if (missingElements != null) { >- CompletionProposal[] subProposals = new CompletionProposal[missingElements.length]; >- for (int i = 0; i < missingElements.length; i++) { >- subProposals[i] = >- createRequiredTypeProposal( >- missingElements[i], >- missingElementsStarts[i], >- missingElementsEnds[i], >- relevance); >+ } else if(parent instanceof BinaryExpression) { >+ BinaryExpression binaryExpression = (BinaryExpression) parent; >+ switch(operator) { >+ case OperatorIds.EQUAL_EQUAL : >+ // expected type is not relevant in this case >+ TypeBinding binding = binaryExpression.left.resolvedType; >+ if (binding != null) { >+ addExpectedType(binding, scope); >+ this.expectedTypesFilter = SUBTYPE | SUPERTYPE; >+ } >+ break; >+ case OperatorIds.PLUS : >+ addExpectedType(TypeBinding.SHORT, scope); >+ addExpectedType(TypeBinding.INT, scope); >+ addExpectedType(TypeBinding.LONG, scope); >+ addExpectedType(TypeBinding.FLOAT, scope); >+ addExpectedType(TypeBinding.DOUBLE, scope); >+ addExpectedType(TypeBinding.CHAR, scope); >+ addExpectedType(TypeBinding.BYTE, scope); >+ addExpectedType(scope.getJavaLangString(), scope); >+ break; >+ case OperatorIds.AND_AND : >+ case OperatorIds.OR_OR : >+ case OperatorIds.XOR : >+ addExpectedType(TypeBinding.BOOLEAN, scope); >+ break; >+ default : >+ addExpectedType(TypeBinding.SHORT, scope); >+ addExpectedType(TypeBinding.INT, scope); >+ addExpectedType(TypeBinding.LONG, scope); >+ addExpectedType(TypeBinding.FLOAT, scope); >+ addExpectedType(TypeBinding.DOUBLE, scope); >+ addExpectedType(TypeBinding.CHAR, scope); >+ addExpectedType(TypeBinding.BYTE, scope); >+ break; >+ } >+ if(operator == OperatorIds.LESS) { >+ if(binaryExpression.left instanceof SingleNameReference){ >+ SingleNameReference name = (SingleNameReference) binaryExpression.left; >+ Binding b = scope.getBinding(name.token, Binding.VARIABLE | Binding.TYPE, name, false); >+ if(b instanceof ReferenceBinding) { >+ TypeVariableBinding[] typeVariableBindings =((ReferenceBinding)b).typeVariables(); >+ if(typeVariableBindings != null && typeVariableBindings.length > 0) { >+ addExpectedType(typeVariableBindings[0].firstBound, scope); >+ } >+ >+ } > } >- proposal.setRequiredProposals(subProposals); > } >- proposal.setCompletion(classField); >- proposal.setFlags(Flags.AccStatic | Flags.AccPublic); >- proposal.setReplaceRange(this.startPosition - this.offset, this.endPosition - this.offset); >- proposal.setTokenRange(this.tokenStart - this.offset, this.tokenEnd - this.offset); >- proposal.setRelevance(relevance); >- this.requestor.accept(proposal); >- if(DEBUG) { >- this.printDebug(proposal); >+ } else if(parent instanceof UnaryExpression) { >+ switch(operator) { >+ case OperatorIds.NOT : >+ addExpectedType(TypeBinding.BOOLEAN, scope); >+ break; >+ case OperatorIds.TWIDDLE : >+ addExpectedType(TypeBinding.SHORT, scope); >+ addExpectedType(TypeBinding.INT, scope); >+ addExpectedType(TypeBinding.LONG, scope); >+ addExpectedType(TypeBinding.CHAR, scope); >+ addExpectedType(TypeBinding.BYTE, scope); >+ break; >+ case OperatorIds.PLUS : >+ case OperatorIds.MINUS : >+ case OperatorIds.PLUS_PLUS : >+ case OperatorIds.MINUS_MINUS : >+ addExpectedType(TypeBinding.SHORT, scope); >+ addExpectedType(TypeBinding.INT, scope); >+ addExpectedType(TypeBinding.LONG, scope); >+ addExpectedType(TypeBinding.FLOAT, scope); >+ addExpectedType(TypeBinding.DOUBLE, scope); >+ addExpectedType(TypeBinding.CHAR, scope); >+ addExpectedType(TypeBinding.BYTE, scope); >+ break; >+ } >+ } >+ } else if(parent instanceof ArrayReference) { >+ addExpectedType(TypeBinding.SHORT, scope); >+ addExpectedType(TypeBinding.INT, scope); >+ addExpectedType(TypeBinding.LONG, scope); >+ } else if(parent instanceof ParameterizedSingleTypeReference) { >+ ParameterizedSingleTypeReference ref = (ParameterizedSingleTypeReference) parent; >+ TypeVariableBinding[] typeVariables = ((ReferenceBinding)ref.resolvedType).typeVariables(); >+ int length = ref.typeArguments == null ? 0 : ref.typeArguments.length; >+ if(typeVariables != null && typeVariables.length >= length) { >+ int index = length - 1; >+ while(index > -1 && ref.typeArguments[index] != node) index--; >+ >+ TypeBinding bound = typeVariables[index].firstBound; >+ addExpectedType(bound == null ? scope.getJavaLangObject() : bound, scope); >+ } >+ } else if(parent instanceof ParameterizedQualifiedTypeReference) { >+ ParameterizedQualifiedTypeReference ref = (ParameterizedQualifiedTypeReference) parent; >+ TypeVariableBinding[] typeVariables = ((ReferenceBinding)ref.resolvedType).typeVariables(); >+ TypeReference[][] arguments = ref.typeArguments; >+ if(typeVariables != null) { >+ int iLength = arguments == null ? 0 : arguments.length; >+ done: for (int i = 0; i < iLength; i++) { >+ int jLength = arguments[i] == null ? 0 : arguments[i].length; >+ for (int j = 0; j < jLength; j++) { >+ if(arguments[i][j] == node && typeVariables.length > j) { >+ TypeBinding bound = typeVariables[j].firstBound; >+ addExpectedType(bound == null ? scope.getJavaLangObject() : bound, scope); >+ break done; >+ } >+ } >+ } >+ } >+ } else if(parent instanceof MemberValuePair) { >+ MemberValuePair memberValuePair = (MemberValuePair) parent; >+ if(memberValuePair.binding != null) { >+ addExpectedType(memberValuePair.binding.returnType, scope); >+ } >+ } else if (parent instanceof NormalAnnotation) { >+ NormalAnnotation annotation = (NormalAnnotation) parent; >+ MemberValuePair[] memberValuePairs = annotation.memberValuePairs(); >+ if(memberValuePairs == null || memberValuePairs.length == 0) { >+ if(annotation.resolvedType instanceof ReferenceBinding) { >+ MethodBinding[] methodBindings = >+ ((ReferenceBinding)annotation.resolvedType).availableMethods(); >+ if (methodBindings != null && >+ methodBindings.length > 0 && >+ CharOperation.equals(methodBindings[0].selector, VALUE)) { >+ boolean canBeSingleMemberAnnotation = true; >+ done : for (int i = 1; i < methodBindings.length; i++) { >+ if((methodBindings[i].modifiers & ClassFileConstants.AccAnnotationDefault) == 0) { >+ canBeSingleMemberAnnotation = false; >+ break done; >+ } >+ } >+ if (canBeSingleMemberAnnotation) { >+ this.assistNodeCanBeSingleMemberAnnotation = canBeSingleMemberAnnotation; >+ addExpectedType(methodBindings[0].returnType, scope); >+ } >+ } >+ } >+ } >+ } else if (parent instanceof TryStatement) { >+ boolean isException = false; >+ if (node instanceof CompletionOnSingleTypeReference) { >+ isException = ((CompletionOnSingleTypeReference)node).isException(); >+ } else if (node instanceof CompletionOnQualifiedTypeReference) { >+ isException = ((CompletionOnQualifiedTypeReference)node).isException(); >+ } else if (node instanceof CompletionOnParameterizedQualifiedTypeReference) { >+ isException = ((CompletionOnParameterizedQualifiedTypeReference)node).isException(); >+ } >+ if (isException) { >+ ThrownExceptionFinder thrownExceptionFinder = new ThrownExceptionFinder(); >+ ReferenceBinding[] bindings = thrownExceptionFinder.find((TryStatement) parent, (BlockScope)scope); >+ if (bindings != null && bindings.length > 0) { >+ for (int i = 0; i < bindings.length; i++) { >+ addExpectedType(bindings[i], scope); >+ } >+ this.expectedTypesFilter = SUPERTYPE; >+ } >+ } >+ } else if (parent instanceof SwitchStatement) { >+ SwitchStatement switchStatement = (SwitchStatement) parent; >+ if (switchStatement.expression != null && >+ switchStatement.expression.resolvedType != null) { >+ addExpectedType(switchStatement.expression.resolvedType, scope); >+ } >+ >+ // Expected types for javadoc >+ } else if (parent instanceof Javadoc) { >+ if (scope.kind == Scope.METHOD_SCOPE) { >+ MethodScope methodScope = (MethodScope) scope; >+ AbstractMethodDeclaration methodDecl = methodScope.referenceMethod(); >+ if (methodDecl != null && methodDecl.binding != null) { >+ ReferenceBinding[] exceptions = methodDecl.binding.thrownExceptions; >+ if (exceptions != null) { >+ for (int i = 0; i < exceptions.length; i++) { >+ addExpectedType(exceptions[i], scope); >+ } >+ } > } > } > } >+ >+ if(this.expectedTypesPtr + 1 != this.expectedTypes.length) { >+ System.arraycopy(this.expectedTypes, 0, this.expectedTypes = new TypeBinding[this.expectedTypesPtr + 1], 0, this.expectedTypesPtr + 1); >+ } > } > >- private void findEnumConstants( >- char[] enumConstantName, >- ReferenceBinding enumType, >- Scope invocationScope, >- ObjectVector fieldsFound, >- char[][] alreadyUsedConstants, >- int alreadyUsedConstantCount, >- boolean needQualification) { >+ private void computeExpectedTypesForAllocationExpression( >+ ReferenceBinding binding, >+ Expression[] arguments, >+ Scope scope, >+ InvocationSite invocationSite) { > >- FieldBinding[] fields = enumType.fields(); >+ MethodBinding[] methods = binding.availableMethods(); >+ nextMethod : for (int i = 0; i < methods.length; i++) { >+ MethodBinding method = methods[i]; > >- int enumConstantLength = enumConstantName.length; >- next : for (int f = fields.length; --f >= 0;) { >- FieldBinding field = fields[f]; >+ if (!method.isConstructor()) continue nextMethod; > >- if (field.isSynthetic()) continue next; >+ if (method.isSynthetic()) continue nextMethod; > >- if ((field.modifiers & Flags.AccEnum) == 0) continue next; >+ if (this.options.checkVisibility && !method.canBeSeenBy(invocationSite, scope)) continue nextMethod; > >- if (enumConstantLength > field.name.length) continue next; >+ TypeBinding[] parameters = method.parameters; >+ if(parameters.length < arguments.length) >+ continue nextMethod; > >- if (!CharOperation.prefixEquals(enumConstantName, field.name, false /* ignore case */) >- && !(this.options.camelCaseMatch && CharOperation.camelCaseMatch(enumConstantName, field.name))) continue next; >+ int length = arguments.length - 1; > >- char[] fieldName = field.name; >+ for (int j = 0; j < length; j++) { >+ Expression argument = arguments[j]; >+ TypeBinding argType = argument.resolvedType; >+ if(argType != null && !argType.isCompatibleWith(parameters[j])) >+ continue nextMethod; >+ } > >- for (int i = 0; i < alreadyUsedConstantCount; i++) { >- if(CharOperation.equals(alreadyUsedConstants[i], fieldName)) continue next; >+ TypeBinding expectedType = method.parameters[arguments.length - 1]; >+ if(expectedType != null) { >+ addExpectedType(expectedType, scope); > } >+ } >+ } >+ private void computeExpectedTypesForMessageSend( >+ ReferenceBinding binding, >+ char[] selector, >+ Expression[] arguments, >+ ReferenceBinding receiverType, >+ Scope scope, >+ InvocationSite invocationSite, >+ boolean isStatic) { > >- int relevance = computeBaseRelevance(); >- relevance += computeRelevanceForResolution(); >- relevance += computeRelevanceForInterestingProposal(field); >- relevance += computeRelevanceForCaseMatching(enumConstantName, field.name); >- relevance += computeRelevanceForExpectingType(field.type); >- relevance += computeRelevanceForEnumConstant(field.type); >- relevance += computeRelevanceForQualification(needQualification); >- relevance += computeRelevanceForRestrictions(IAccessRule.K_ACCESSIBLE); >+ MethodBinding[] methods = binding.availableMethods(); >+ nextMethod : for (int i = 0; i < methods.length; i++) { >+ MethodBinding method = methods[i]; > >- this.noProposal = false; >- if (!needQualification) { >- char[] completion = fieldName; >+ if (method.isSynthetic()) continue nextMethod; > >- if(!this.requestor.isIgnored(CompletionProposal.FIELD_REF)) { >- InternalCompletionProposal proposal = createProposal(CompletionProposal.FIELD_REF, this.actualCompletionPosition); >- proposal.setDeclarationSignature(getSignature(field.declaringClass)); >- proposal.setSignature(getSignature(field.type)); >- proposal.setDeclarationPackageName(field.declaringClass.qualifiedPackageName()); >- proposal.setDeclarationTypeName(field.declaringClass.qualifiedSourceName()); >- proposal.setPackageName(field.type.qualifiedPackageName()); >- proposal.setTypeName(field.type.qualifiedSourceName()); >- proposal.setName(field.name); >- proposal.setCompletion(completion); >- proposal.setFlags(field.modifiers); >- proposal.setReplaceRange(this.startPosition - this.offset, this.endPosition - this.offset); >- proposal.setTokenRange(this.tokenStart - this.offset, this.tokenEnd - this.offset); >- proposal.setRelevance(relevance); >- this.requestor.accept(proposal); >- if(DEBUG) { >- this.printDebug(proposal); >- } >- } >+ if (method.isDefaultAbstract()) continue nextMethod; > >- } else { >- TypeBinding visibleType = invocationScope.getType(field.type.sourceName()); >- boolean needImport = visibleType == null || !visibleType.isValidBinding(); >+ if (method.isConstructor()) continue nextMethod; > >- char[] completion = CharOperation.concat(field.type.sourceName(), field.name, '.'); >+ if (isStatic && !method.isStatic()) continue nextMethod; > >- if (!needImport) { >- if(!this.requestor.isIgnored(CompletionProposal.FIELD_REF)) { >- InternalCompletionProposal proposal = createProposal(CompletionProposal.FIELD_REF, this.actualCompletionPosition); >- proposal.setDeclarationSignature(getSignature(field.declaringClass)); >- proposal.setSignature(getSignature(field.type)); >- proposal.setDeclarationPackageName(field.declaringClass.qualifiedPackageName()); >- proposal.setDeclarationTypeName(field.declaringClass.qualifiedSourceName()); >- proposal.setPackageName(field.type.qualifiedPackageName()); >- proposal.setTypeName(field.type.qualifiedSourceName()); >- proposal.setName(field.name); >- proposal.setCompletion(completion); >- proposal.setFlags(field.modifiers); >- proposal.setReplaceRange(this.startPosition - this.offset, this.endPosition - this.offset); >- proposal.setTokenRange(this.tokenStart - this.offset, this.tokenEnd - this.offset); >- proposal.setRelevance(relevance); >- this.requestor.accept(proposal); >- if(DEBUG) { >- this.printDebug(proposal); >- } >- } >- } else { >- if (!this.isIgnored(CompletionProposal.FIELD_REF, CompletionProposal.TYPE_IMPORT)) { >- CompilationUnitDeclaration cu = this.unitScope.referenceContext; >- int importStart = cu.types[0].declarationSourceStart; >- int importEnd = importStart; >- >- ReferenceBinding fieldType = (ReferenceBinding)field.type; >- >- InternalCompletionProposal proposal = createProposal(CompletionProposal.FIELD_REF, this.actualCompletionPosition); >- proposal.setDeclarationSignature(getSignature(field.declaringClass)); >- proposal.setSignature(getSignature(field.type)); >- proposal.setDeclarationPackageName(field.declaringClass.qualifiedPackageName()); >- proposal.setDeclarationTypeName(field.declaringClass.qualifiedSourceName()); >- proposal.setPackageName(field.type.qualifiedPackageName()); >- proposal.setTypeName(field.type.qualifiedSourceName()); >- proposal.setName(field.name); >- proposal.setCompletion(completion); >- proposal.setFlags(field.modifiers); >- proposal.setReplaceRange(this.startPosition - this.offset, this.endPosition - this.offset); >- proposal.setTokenRange(this.tokenStart - this.offset, this.tokenEnd - this.offset); >- proposal.setRelevance(relevance); >+ if (this.options.checkVisibility && !method.canBeSeenBy(receiverType, invocationSite, scope)) continue nextMethod; > >- char[] typeImportCompletion = createImportCharArray(CharOperation.concatWith(fieldType.compoundName, '.'), false, false); >+ if(!CharOperation.equals(method.selector, selector)) continue nextMethod; > >- InternalCompletionProposal typeImportProposal = createProposal(CompletionProposal.TYPE_IMPORT, this.actualCompletionPosition); >- typeImportProposal.nameLookup = this.nameEnvironment.nameLookup; >- typeImportProposal.completionEngine = this; >- char[] packageName = fieldType.qualifiedPackageName(); >- typeImportProposal.setDeclarationSignature(packageName); >- typeImportProposal.setSignature(getSignature(fieldType)); >- typeImportProposal.setPackageName(packageName); >- typeImportProposal.setTypeName(fieldType.qualifiedSourceName()); >- typeImportProposal.setCompletion(typeImportCompletion); >- typeImportProposal.setFlags(fieldType.modifiers); >- typeImportProposal.setAdditionalFlags(CompletionFlags.Default); >- typeImportProposal.setReplaceRange(importStart - this.offset, importEnd - this.offset); >- typeImportProposal.setTokenRange(importStart - this.offset, importEnd - this.offset); >- typeImportProposal.setRelevance(relevance); >+ TypeBinding[] parameters = method.parameters; >+ if(parameters.length < arguments.length) >+ continue nextMethod; > >- proposal.setRequiredProposals(new CompletionProposal[]{typeImportProposal}); >+ int length = arguments.length - 1; > >- this.requestor.accept(proposal); >- if(DEBUG) { >- this.printDebug(proposal); >- } >- } >- } >+ for (int j = 0; j < length; j++) { >+ Expression argument = arguments[j]; >+ TypeBinding argType = argument.resolvedType; >+ if(argType != null && !argType.isCompatibleWith(parameters[j])) >+ continue nextMethod; > } >- } >- } > >- private void findEnumConstantsFromExpectedTypes( >- char[] token, >- Scope invocationScope, >- ObjectVector fieldsFound) { >- int length = this.expectedTypesPtr + 1; >- for (int i = 0; i < length; i++) { >- if (this.expectedTypes[i].isEnum()) { >- findEnumConstants( >- token, >- (ReferenceBinding)this.expectedTypes[i], >- invocationScope, >- fieldsFound, >- CharOperation.NO_CHAR_CHAR, >- 0, >- true); >+ TypeBinding expectedType = method.parameters[arguments.length - 1]; >+ if(expectedType != null) { >+ addExpectedType(expectedType, scope); > } > } >- > } >+ private void computeExpectedTypesForMessageSendForInterface( >+ ReferenceBinding binding, >+ char[] selector, >+ Expression[] arguments, >+ ReferenceBinding receiverType, >+ Scope scope, >+ InvocationSite invocationSite, >+ boolean isStatic) { > >- private void findEnumConstantsFromSwithStatement(char[] enumConstantName, SwitchStatement switchStatement) { >- TypeBinding expressionType = switchStatement.expression.resolvedType; >- if(expressionType != null && expressionType.isEnum()) { >- ReferenceBinding enumType = (ReferenceBinding) expressionType; >+ ReferenceBinding[] itsInterfaces = binding.superInterfaces(); >+ if (itsInterfaces != Binding.NO_SUPERINTERFACES) { >+ ReferenceBinding[] interfacesToVisit = itsInterfaces; >+ int nextPosition = interfacesToVisit.length; > >- CaseStatement[] cases = switchStatement.cases; >+ for (int i = 0; i < nextPosition; i++) { >+ ReferenceBinding currentType = interfacesToVisit[i]; >+ computeExpectedTypesForMessageSend( >+ currentType, >+ selector, >+ arguments, >+ receiverType, >+ scope, >+ invocationSite, >+ isStatic); > >- char[][] alreadyUsedConstants = new char[switchStatement.caseCount][]; >- int alreadyUsedConstantCount = 0; >- for (int i = 0; i < switchStatement.caseCount; i++) { >- Expression caseExpression = cases[i].constantExpression; >- if((caseExpression instanceof SingleNameReference) >- && (caseExpression.resolvedType != null && caseExpression.resolvedType.isEnum())) { >- alreadyUsedConstants[alreadyUsedConstantCount++] = ((SingleNameReference)cases[i].constantExpression).token; >+ if ((itsInterfaces = currentType.superInterfaces()) != Binding.NO_SUPERINTERFACES) { >+ int itsLength = itsInterfaces.length; >+ if (nextPosition + itsLength >= interfacesToVisit.length) >+ System.arraycopy(interfacesToVisit, 0, interfacesToVisit = new ReferenceBinding[nextPosition + itsLength + 5], 0, nextPosition); >+ nextInterface : for (int a = 0; a < itsLength; a++) { >+ ReferenceBinding next = itsInterfaces[a]; >+ for (int b = 0; b < nextPosition; b++) >+ if (next == interfacesToVisit[b]) continue nextInterface; >+ interfacesToVisit[nextPosition++] = next; >+ } > } > } >- >- findEnumConstants( >- enumConstantName, >- enumType, >- null /* doesn't need invocation scope */, >- new ObjectVector(), >- alreadyUsedConstants, >- alreadyUsedConstantCount, >- false); > } > } > >- private void findExceptionFromTryStatement( >- char[] typeName, >- ReferenceBinding exceptionType, >- ReferenceBinding receiverType, >- SourceTypeBinding invocationType, >- BlockScope scope, >- ObjectVector typesFound, >- boolean searchSuperClasses) { >- >- if (searchSuperClasses) { >- ReferenceBinding javaLangThrowable = scope.getJavaLangThrowable(); >- if (exceptionType != javaLangThrowable) { >- ReferenceBinding superClass = exceptionType.superclass(); >- while(superClass != null && superClass != javaLangThrowable) { >- findExceptionFromTryStatement(typeName, superClass, receiverType, invocationType, scope, typesFound, false); >- superClass = superClass.superclass(); >+ private Scope computeForbiddenBindings(ASTNode astNode, ASTNode astNodeParent, Scope scope) { >+ this.forbbidenBindingsFilter = NONE; >+ if(scope instanceof ClassScope) { >+ TypeDeclaration typeDeclaration = ((ClassScope)scope).referenceContext; >+ if(typeDeclaration.superclass == astNode) { >+ addForbiddenBindings(typeDeclaration.binding); >+ return scope.parent; >+ } >+ TypeReference[] superInterfaces = typeDeclaration.superInterfaces; >+ int length = superInterfaces == null ? 0 : superInterfaces.length; >+ for (int i = 0; i < length; i++) { >+ if(superInterfaces[i] == astNode) { >+ addForbiddenBindings(typeDeclaration.binding); >+ return scope.parent; > } > } >- } >- >- if (typeName.length > exceptionType.sourceName.length) >- return; >- >- if (!CharOperation.prefixEquals(typeName, exceptionType.sourceName, false/* ignore case */) >- && !(this.options.camelCaseMatch && CharOperation.camelCaseMatch(typeName, exceptionType.sourceName))) >- return; >- >- if (this.options.checkDeprecation && >- exceptionType.isViewedAsDeprecated() && >- !scope.isDefinedInSameUnit(exceptionType)) >- return; >- >- if (this.options.checkVisibility) { >- if (invocationType != null) { >- if (receiverType != null) { >- if (!exceptionType.canBeSeenBy(receiverType, invocationType)) return; >- } else { >- if (!exceptionType.canBeSeenBy(exceptionType, invocationType)) return; >+ } else { >+ if (astNodeParent != null && astNodeParent instanceof TryStatement) { >+ boolean isException = false; >+ if (astNode instanceof CompletionOnSingleTypeReference) { >+ isException = ((CompletionOnSingleTypeReference)astNode).isException(); >+ } else if (astNode instanceof CompletionOnQualifiedTypeReference) { >+ isException = ((CompletionOnQualifiedTypeReference)astNode).isException(); >+ } else if (astNode instanceof CompletionOnParameterizedQualifiedTypeReference) { >+ isException = ((CompletionOnParameterizedQualifiedTypeReference)astNode).isException(); >+ } >+ if (isException) { >+ Argument[] catchArguments = ((TryStatement) astNodeParent).catchArguments; >+ int length = catchArguments == null ? 0 : catchArguments.length; >+ for (int i = 0; i < length; i++) { >+ TypeBinding caughtException = catchArguments[i].type.resolvedType; >+ if (caughtException != null) { >+ addForbiddenBindings(caughtException); >+ this.knownTypes.put(CharOperation.concat(caughtException.qualifiedPackageName(), caughtException.qualifiedSourceName(), '.'), this); >+ } >+ } >+ this.forbbidenBindingsFilter = SUBTYPE; > } >- } else if(!exceptionType.canBeSeenBy(this.unitScope.fPackage)) { >- return; > } > } >+// else if(scope instanceof MethodScope) { >+// MethodScope methodScope = (MethodScope) scope; >+// if(methodScope.insideTypeAnnotation) { >+// return methodScope.parent.parent; >+// } >+// } >+ return scope; >+ } > >- for (int j = typesFound.size; --j >= 0;) { >- ReferenceBinding otherType = (ReferenceBinding) typesFound.elementAt(j); >- >- if (exceptionType == otherType) >- return; >- >- if (CharOperation.equals(exceptionType.sourceName, otherType.sourceName, true)) { >+ private char[] computePrefix(SourceTypeBinding declarationType, SourceTypeBinding invocationType, boolean isStatic){ > >- if (exceptionType.enclosingType().isSuperclassOf(otherType.enclosingType())) >- return; >+ StringBuffer completion = new StringBuffer(10); > >- if (otherType.enclosingType().isInterface()) >- if (exceptionType.enclosingType() >- .implementsInterface(otherType.enclosingType(), true)) >- return; >+ if (isStatic) { >+ completion.append(declarationType.sourceName()); > >- if (exceptionType.enclosingType().isInterface()) >- if (otherType.enclosingType() >- .implementsInterface(exceptionType.enclosingType(), true)) >- return; >- } >- } >+ } else if (declarationType == invocationType) { >+ completion.append(THIS); > >- typesFound.add(exceptionType); >+ } else { > >- char[] completionName = exceptionType.sourceName(); >+ if (!declarationType.isNestedType()) { > >- boolean isQualified = false; >+ completion.append(declarationType.sourceName()); >+ completion.append('.'); >+ completion.append(THIS); > >- if(!this.insideQualifiedReference) { >- isQualified = true; >+ } else if (!declarationType.isAnonymousType()) { > >- char[] memberPackageName = exceptionType.qualifiedPackageName(); >- char[] memberTypeName = exceptionType.sourceName(); >- char[] memberEnclosingTypeNames = null; >+ completion.append(declarationType.sourceName()); >+ completion.append('.'); >+ completion.append(THIS); > >- ReferenceBinding enclosingType = exceptionType.enclosingType(); >- if (enclosingType != null) { >- memberEnclosingTypeNames = exceptionType.enclosingType().qualifiedSourceName(); > } >+ } > >- Scope currentScope = scope; >- done : while (currentScope != null) { // done when a COMPILATION_UNIT_SCOPE is found >+ return completion.toString().toCharArray(); >+ } > >- switch (currentScope.kind) { >- >- case Scope.METHOD_SCOPE : >- case Scope.BLOCK_SCOPE : >- BlockScope blockScope = (BlockScope) currentScope; >- >- for (int j = 0, length = blockScope.subscopeCount; j < length; j++) { >- >- if (blockScope.subscopes[j] instanceof ClassScope) { >- SourceTypeBinding localType = >- ((ClassScope) blockScope.subscopes[j]).referenceContext.binding; >- >- if (localType == exceptionType) { >- isQualified = false; >- break done; >- } >- } >- } >- break; >- >- case Scope.CLASS_SCOPE : >- SourceTypeBinding type = ((ClassScope)currentScope).referenceContext.binding; >- ReferenceBinding[] memberTypes = type.memberTypes(); >- if (memberTypes != null) { >- for (int j = 0; j < memberTypes.length; j++) { >- if (memberTypes[j] == exceptionType) { >- isQualified = false; >- break done; >- } >- } >- } >- >- >- break; >+ private int computeRelevanceForAnnotation(){ >+ if(this.assistNodeIsAnnotation) { >+ return R_ANNOTATION; >+ } >+ return 0; >+ } > >- case Scope.COMPILATION_UNIT_SCOPE : >- SourceTypeBinding[] types = ((CompilationUnitScope)currentScope).topLevelTypes; >- if (types != null) { >- for (int j = 0; j < types.length; j++) { >- if (types[j] == exceptionType) { >- isQualified = false; >- break done; >- } >- } >- } >- break done; >- } >- currentScope = currentScope.parent; >+ private int computeRelevanceForAnnotationTarget(TypeBinding typeBinding){ >+ if (this.assistNodeIsAnnotation && >+ (this.targetedElement & TagBits.AnnotationTargetMASK) != 0) { >+ long target = typeBinding.getAnnotationTagBits() & TagBits.AnnotationTargetMASK; >+ if(target == 0 || (target & this.targetedElement) != 0) { >+ return R_TARGET; > } >- >- if (isQualified && mustQualifyType(memberPackageName, memberTypeName, memberEnclosingTypeNames, exceptionType.modifiers)) { >- if (memberPackageName == null || memberPackageName.length == 0) >- if (this.unitScope != null && this.unitScope.fPackage.compoundName != CharOperation.NO_CHAR_CHAR) >- return; // ignore types from the default package from outside it >- } else { >- isQualified = false; >+ } >+ return 0; >+ } >+ int computeRelevanceForCaseMatching(char[] token, char[] proposalName){ >+ if (this.options.camelCaseMatch) { >+ if(CharOperation.equals(token, proposalName, true /* do not ignore case */)) { >+ return R_CASE + R_EXACT_NAME; >+ } else if (CharOperation.prefixEquals(token, proposalName, true /* do not ignore case */)) { >+ return R_CASE; >+ } else if (CharOperation.camelCaseMatch(token, proposalName)){ >+ return R_CAMEL_CASE; >+ } else if(CharOperation.equals(token, proposalName, false /* ignore case */)) { >+ return R_EXACT_NAME; > } >- >- if (isQualified) { >- completionName = >- CharOperation.concat( >- memberPackageName, >- CharOperation.concat( >- memberEnclosingTypeNames, >- memberTypeName, >- '.'), >- '.'); >+ } else if (CharOperation.prefixEquals(token, proposalName, true /* do not ignore case */)) { >+ if(CharOperation.equals(token, proposalName, true /* do not ignore case */)) { >+ return R_CASE + R_EXACT_NAME; >+ } else { >+ return R_CASE; > } >+ } else if(CharOperation.equals(token, proposalName, false /* ignore case */)) { >+ return R_EXACT_NAME; > } >+ return 0; >+ } > >- int relevance = computeBaseRelevance(); >- relevance += computeRelevanceForResolution(); >- relevance += computeRelevanceForInterestingProposal(); >- relevance += computeRelevanceForCaseMatching(typeName, exceptionType.sourceName); >- relevance += computeRelevanceForExpectingType(exceptionType); >- relevance += computeRelevanceForRestrictions(IAccessRule.K_ACCESSIBLE); >- if(!this.insideQualifiedReference) { >- relevance += computeRelevanceForQualification(isQualified); >+ private int computeRelevanceForClass(){ >+ if(this.assistNodeIsClass) { >+ return R_CLASS; > } >- relevance += computeRelevanceForClass(); >- relevance += computeRelevanceForException(); >+ return 0; >+ } > >- this.noProposal = false; >- if(!this.requestor.isIgnored(CompletionProposal.TYPE_REF)) { >- createTypeProposal( >- exceptionType, >- exceptionType.qualifiedSourceName(), >- IAccessRule.K_ACCESSIBLE, >- completionName, >- relevance, >- null, >- null, >- null, >- false); >+ private int computeRelevanceForEnum(){ >+ if(this.assistNodeIsEnum) { >+ return R_ENUM; > } >+ return 0; > } > >- private void findExceptionFromTryStatement( >- char[] typeName, >- ReferenceBinding receiverType, >- SourceTypeBinding invocationType, >- BlockScope scope, >- ObjectVector typesFound) { >+ private int computeRelevanceForEnumConstant(TypeBinding proposalType){ >+ if(this.assistNodeIsEnum && >+ proposalType != null && >+ this.expectedTypes != null) { >+ for (int i = 0; i <= this.expectedTypesPtr; i++) { >+ if (proposalType.isEnum() && >+ proposalType == this.expectedTypes[i]) { >+ return R_ENUM + R_ENUM_CONSTANT; >+ } > >- for (int i = 0; i <= this.expectedTypesPtr; i++) { >- ReferenceBinding exceptionType = (ReferenceBinding)this.expectedTypes[i]; >+ } >+ } >+ return 0; >+ } > >- findExceptionFromTryStatement(typeName, exceptionType, receiverType, invocationType, scope, typesFound, true); >+ private int computeRelevanceForException(){ >+ if (this.assistNodeIsException) { >+ return R_EXCEPTION; > } >+ return 0; > } >- private void findExplicitConstructors( >- char[] name, >- ReferenceBinding currentType, >- MethodScope scope, >- InvocationSite invocationSite) { > >- ConstructorDeclaration constructorDeclaration = (ConstructorDeclaration)scope.referenceContext; >- MethodBinding enclosingConstructor = constructorDeclaration.binding; >+ private int computeRelevanceForException(char[] proposalName){ > >- // No visibility checks can be performed without the scope & invocationSite >- MethodBinding[] methods = currentType.availableMethods(); >- if(methods != null) { >- next : for (int f = methods.length; --f >= 0;) { >- MethodBinding constructor = methods[f]; >- if (constructor != enclosingConstructor && constructor.isConstructor()) { >+ if((this.assistNodeIsException || (this.assistNodeInJavadoc & CompletionOnJavadoc.EXCEPTION) != 0 )&& >+ (CharOperation.match(EXCEPTION_PATTERN, proposalName, false) || >+ CharOperation.match(ERROR_PATTERN, proposalName, false))) { >+ return R_EXCEPTION; >+ } >+ return 0; >+ } > >- if (constructor.isSynthetic()) continue next; >+ private int computeRelevanceForExpectingType(char[] packageName, char[] typeName){ >+ if(this.expectedTypes != null) { >+ for (int i = 0; i <= this.expectedTypesPtr; i++) { >+ if(CharOperation.equals(this.expectedTypes[i].qualifiedPackageName(), packageName) && >+ CharOperation.equals(this.expectedTypes[i].qualifiedSourceName(), typeName)) { >+ return R_EXACT_EXPECTED_TYPE; >+ } >+ } >+ if(this.hasJavaLangObjectAsExpectedType) { >+ return R_EXPECTED_TYPE; >+ } >+ } >+ return 0; >+ } > >- if (this.options.checkDeprecation && >- constructor.isViewedAsDeprecated() && >- !scope.isDefinedInSameUnit(constructor.declaringClass)) >- continue next; >+ private int computeRelevanceForExpectingType(TypeBinding proposalType){ >+ if(this.expectedTypes != null && proposalType != null) { >+ int relevance = 0; >+ for (int i = 0; i <= this.expectedTypesPtr; i++) { >+ if((this.expectedTypesFilter & SUBTYPE) != 0 >+ && proposalType.isCompatibleWith(this.expectedTypes[i])) { > >- if (this.options.checkVisibility >- && !constructor.canBeSeenBy(invocationSite, scope)) continue next; >+ if(CharOperation.equals(this.expectedTypes[i].qualifiedPackageName(), proposalType.qualifiedPackageName()) && >+ CharOperation.equals(this.expectedTypes[i].qualifiedSourceName(), proposalType.qualifiedSourceName())) { >+ return R_EXACT_EXPECTED_TYPE; >+ } > >- TypeBinding[] parameters = constructor.parameters; >- int paramLength = parameters.length; >+ relevance = R_EXPECTED_TYPE; >+ } >+ if((this.expectedTypesFilter & SUPERTYPE) != 0 >+ && this.expectedTypes[i].isCompatibleWith(proposalType)) { > >- char[][] parameterPackageNames = new char[paramLength][]; >- char[][] parameterTypeNames = new char[paramLength][]; >- for (int i = 0; i < paramLength; i++) { >- TypeBinding type = parameters[i]; >- parameterPackageNames[i] = type.qualifiedPackageName(); >- parameterTypeNames[i] = type.qualifiedSourceName(); >+ if(CharOperation.equals(this.expectedTypes[i].qualifiedPackageName(), proposalType.qualifiedPackageName()) && >+ CharOperation.equals(this.expectedTypes[i].qualifiedSourceName(), proposalType.qualifiedSourceName())) { >+ return R_EXACT_EXPECTED_TYPE; > } >- char[][] parameterNames = findMethodParameterNames(constructor,parameterTypeNames); > >- char[] completion = CharOperation.NO_CHAR; >- if (this.source != null >- && this.source.length > this.endPosition >- && this.source[this.endPosition] == '(') >- completion = name; >- else >- completion = CharOperation.concat(name, new char[] { '(', ')' }); >+ relevance = R_EXPECTED_TYPE; >+ } >+ } >+ return relevance; >+ } >+ return 0; >+ } > >- int relevance = computeBaseRelevance(); >- relevance += computeRelevanceForResolution(); >- relevance += computeRelevanceForInterestingProposal(); >- relevance += computeRelevanceForCaseMatching(this.completionToken, name); >- relevance += computeRelevanceForRestrictions(IAccessRule.K_ACCESSIBLE); >+ private int computeRelevanceForInheritance(ReferenceBinding receiverType, ReferenceBinding declaringClass) { >+ if (receiverType == declaringClass) return R_NON_INHERITED; >+ return 0; >+ } > >- this.noProposal = false; >- if(!this.requestor.isIgnored(CompletionProposal.METHOD_REF)) { >- InternalCompletionProposal proposal = createProposal(CompletionProposal.METHOD_REF, this.actualCompletionPosition); >- proposal.setDeclarationSignature(getSignature(currentType)); >- proposal.setSignature(getSignature(constructor)); >- MethodBinding original = constructor.original(); >- if(original != constructor) { >- proposal.setOriginalSignature(getSignature(original)); >- } >- proposal.setDeclarationPackageName(currentType.qualifiedPackageName()); >- proposal.setDeclarationTypeName(currentType.qualifiedSourceName()); >- proposal.setParameterPackageNames(parameterPackageNames); >- proposal.setParameterTypeNames(parameterTypeNames); >- //proposal.setPackageName(null); >- //proposal.setTypeName(null); >- proposal.setName(name); >- proposal.setIsContructor(true); >- proposal.setCompletion(completion); >- proposal.setFlags(constructor.modifiers); >- proposal.setReplaceRange(this.startPosition - this.offset, this.endPosition - this.offset); >- proposal.setTokenRange(this.tokenStart - this.offset, this.tokenEnd - this.offset); >- proposal.setRelevance(relevance); >- if(parameterNames != null) proposal.setParameterNames(parameterNames); >- this.requestor.accept(proposal); >- if(DEBUG) { >- this.printDebug(proposal); >- } >- } >+ int computeRelevanceForInterestingProposal(){ >+ return computeRelevanceForInterestingProposal(null); >+ } >+ >+ private int computeRelevanceForInterestingProposal(Binding binding){ >+ if(this.uninterestingBindings != null) { >+ for (int i = 0; i <= this.uninterestingBindingsPtr; i++) { >+ if(this.uninterestingBindings[i] == binding) { >+ return 0; > } > } > } >+ return R_INTERESTING; > } >- private void findConstructors( >- ReferenceBinding currentType, >- TypeBinding[] argTypes, >- Scope scope, >- InvocationSite invocationSite, >- boolean forAnonymousType) { > >- // No visibility checks can be performed without the scope & invocationSite >- MethodBinding[] methods = currentType.availableMethods(); >- if(methods != null) { >- int minArgLength = argTypes == null ? 0 : argTypes.length; >- next : for (int f = methods.length; --f >= 0;) { >- MethodBinding constructor = methods[f]; >- if (constructor.isConstructor()) { >+ private int computeRelevanceForInterface(){ >+ if(this.assistNodeIsInterface) { >+ return R_INTERFACE; >+ } >+ return 0; >+ } > >- if (constructor.isSynthetic()) continue next; >+ private int computeRelevanceForMissingElements(boolean hasProblems) { >+ if (!hasProblems) { >+ return R_NO_PROBLEMS; >+ } >+ return 0; >+ } >+ int computeRelevanceForQualification(boolean prefixRequired) { >+ if(!prefixRequired && !this.insideQualifiedReference) { >+ return R_UNQUALIFIED; >+ } > >- if (this.options.checkDeprecation && >- constructor.isViewedAsDeprecated() && >- !scope.isDefinedInSameUnit(constructor.declaringClass)) >- continue next; >+ if(prefixRequired && this.insideQualifiedReference) { >+ return R_QUALIFIED; >+ } >+ return 0; >+ } > >- if (this.options.checkVisibility >- && !constructor.canBeSeenBy(invocationSite, scope)) { >- if(!forAnonymousType || !constructor.isProtected()) >- continue next; >- } >+ int computeRelevanceForResolution(){ >+ return computeRelevanceForResolution(true); >+ } > >- TypeBinding[] parameters = constructor.parameters; >- int paramLength = parameters.length; >- if (minArgLength > paramLength) >- continue next; >- for (int a = minArgLength; --a >= 0;) >- if (argTypes[a] != null) { // can be null if it could not be resolved properly >- if (!argTypes[a].isCompatibleWith(constructor.parameters[a])) >- continue next; >- } >+ int computeRelevanceForResolution(boolean isResolved){ >+ if (isResolved) { >+ return R_RESOLVED; >+ } >+ return 0; >+ } > >- char[][] parameterPackageNames = new char[paramLength][]; >- char[][] parameterTypeNames = new char[paramLength][]; >- for (int i = 0; i < paramLength; i++) { >- TypeBinding type = parameters[i]; >- parameterPackageNames[i] = type.qualifiedPackageName(); >- parameterTypeNames[i] = type.qualifiedSourceName(); >- } >- char[][] parameterNames = findMethodParameterNames(constructor,parameterTypeNames); >+ int computeRelevanceForRestrictions(int accessRuleKind) { >+ if(accessRuleKind == IAccessRule.K_ACCESSIBLE) { >+ return R_NON_RESTRICTED; >+ } >+ return 0; >+ } > >- char[] completion = CharOperation.NO_CHAR; >- if(forAnonymousType){ >- int relevance = computeBaseRelevance(); >- relevance += computeRelevanceForResolution(); >- relevance += computeRelevanceForInterestingProposal(); >- relevance += computeRelevanceForRestrictions(IAccessRule.K_ACCESSIBLE); >+ private int computeRelevanceForStatic(boolean onlyStatic, boolean isStatic) { >+ if(this.insideQualifiedReference && !onlyStatic && !isStatic) { >+ return R_NON_STATIC; >+ } >+ return 0; >+ } > >- this.noProposal = false; >- if(!this.requestor.isIgnored(CompletionProposal.ANONYMOUS_CLASS_DECLARATION)) { >- InternalCompletionProposal proposal = createProposal(CompletionProposal.ANONYMOUS_CLASS_DECLARATION, this.actualCompletionPosition); >- proposal.setDeclarationSignature(getSignature(currentType)); >- proposal.setDeclarationKey(currentType.computeUniqueKey()); >- proposal.setSignature(getSignature(constructor)); >- MethodBinding original = constructor.original(); >- if(original != constructor) { >- proposal.setOriginalSignature(getSignature(original)); >- } >- proposal.setKey(constructor.computeUniqueKey()); >- proposal.setDeclarationPackageName(currentType.qualifiedPackageName()); >- proposal.setDeclarationTypeName(currentType.qualifiedSourceName()); >- proposal.setParameterPackageNames(parameterPackageNames); >- proposal.setParameterTypeNames(parameterTypeNames); >- //proposal.setPackageName(null); >- //proposal.setTypeName(null); >- proposal.setCompletion(completion); >- proposal.setFlags(constructor.modifiers); >- proposal.setReplaceRange(this.endPosition - this.offset, this.endPosition - this.offset); >- proposal.setTokenRange(this.tokenEnd - this.offset, this.tokenEnd - this.offset); >- proposal.setRelevance(relevance); >- if(parameterNames != null) proposal.setParameterNames(parameterNames); >- this.requestor.accept(proposal); >- if(DEBUG) { >- this.printDebug(proposal); >- } >- } >- } else { >- int relevance = computeBaseRelevance(); >- relevance += computeRelevanceForResolution(); >- relevance += computeRelevanceForInterestingProposal(); >- relevance += computeRelevanceForRestrictions(IAccessRule.K_ACCESSIBLE); >+ private long computeTargetedElement(CompletionOnAnnotationOfType fakeNode) { >+ ASTNode annotatedElement = fakeNode.potentialAnnotatedNode; > >- // Special case for completion in javadoc >- if (this.assistNodeInJavadoc > 0) { >- Expression receiver = null; >- char[] selector = null; >- if (invocationSite instanceof CompletionOnJavadocAllocationExpression) { >- CompletionOnJavadocAllocationExpression alloc = (CompletionOnJavadocAllocationExpression) invocationSite; >- receiver = alloc.type; >- } else if (invocationSite instanceof CompletionOnJavadocFieldReference) { >- CompletionOnJavadocFieldReference fieldRef = (CompletionOnJavadocFieldReference) invocationSite; >- receiver = fieldRef.receiver; >- } >- if (receiver != null) { >- StringBuffer javadocCompletion = new StringBuffer(); >- if (receiver.isThis()) { >- selector = (((JavadocImplicitTypeReference)receiver).token); >- if ((this.assistNodeInJavadoc & CompletionOnJavadoc.TEXT) != 0) { >- javadocCompletion.append('#'); >- } >- } else if (receiver instanceof JavadocSingleTypeReference) { >- JavadocSingleTypeReference typeRef = (JavadocSingleTypeReference) receiver; >- selector = typeRef.token; >- if ((this.assistNodeInJavadoc & CompletionOnJavadoc.TEXT) != 0) { >- javadocCompletion.append(typeRef.token); >- javadocCompletion.append('#'); >- } >- } else if (receiver instanceof JavadocQualifiedTypeReference) { >- JavadocQualifiedTypeReference typeRef = (JavadocQualifiedTypeReference) receiver; >- selector = typeRef.tokens[typeRef.tokens.length-1]; >- if ((this.assistNodeInJavadoc & CompletionOnJavadoc.TEXT) != 0) { >- javadocCompletion.append(CharOperation.concatWith(typeRef.tokens, '.')); >- javadocCompletion.append('#'); >- } >- } >- // Append parameters types >- javadocCompletion.append(selector); >- javadocCompletion.append('('); >- if (constructor.parameters != null) { >- boolean isVarargs = constructor.isVarargs(); >- for (int p=0, ln=constructor.parameters.length; p<ln; p++) { >- if (p>0) javadocCompletion.append(", "); //$NON-NLS-1$ >- TypeBinding argTypeBinding = constructor.parameters[p]; >- if (isVarargs && p == ln - 1) { >- createVargsType(argTypeBinding.erasure(), scope, javadocCompletion); >- } else { >- createType(argTypeBinding.erasure(), scope, javadocCompletion); >- } >- } >- } >- javadocCompletion.append(')'); >- completion = javadocCompletion.toString().toCharArray(); >- } >- } >+ if (annotatedElement instanceof TypeDeclaration) { >+ TypeDeclaration annotatedTypeDeclaration = (TypeDeclaration) annotatedElement; >+ if (TypeDeclaration.kind(annotatedTypeDeclaration.modifiers) == TypeDeclaration.ANNOTATION_TYPE_DECL) { >+ return TagBits.AnnotationForAnnotationType | TagBits.AnnotationForType; >+ } >+ return TagBits.AnnotationForType; >+ } else if (annotatedElement instanceof FieldDeclaration) { >+ if (fakeNode.isParameter) { >+ return TagBits.AnnotationForParameter; >+ } >+ return TagBits.AnnotationForField; >+ } else if (annotatedElement instanceof MethodDeclaration) { >+ return TagBits.AnnotationForMethod; >+ } else if (annotatedElement instanceof Argument) { >+ return TagBits.AnnotationForParameter; >+ } else if (annotatedElement instanceof ConstructorDeclaration) { >+ return TagBits.AnnotationForConstructor; >+ } else if (annotatedElement instanceof LocalDeclaration) { >+ return TagBits.AnnotationForLocalVariable; >+ } else if (annotatedElement instanceof ImportReference) { >+ return TagBits.AnnotationForPackage; >+ } >+ return 0; >+ } >+ private TypeBinding[] computeTypes(Expression[] arguments) { >+ if (arguments == null) return null; >+ int argsLength = arguments.length; >+ TypeBinding[] argTypes = new TypeBinding[argsLength]; >+ for (int a = argsLength; --a >= 0;) { >+ argTypes[a] = arguments[a].resolvedType; >+ } >+ return argTypes; >+ } > >- // Create standard proposal >- this.noProposal = false; >- if(!this.requestor.isIgnored(CompletionProposal.METHOD_REF) && (this.assistNodeInJavadoc & CompletionOnJavadoc.ONLY_INLINE_TAG) == 0) { >- InternalCompletionProposal proposal = createProposal(CompletionProposal.METHOD_REF, this.actualCompletionPosition); >- proposal.setDeclarationSignature(getSignature(currentType)); >- proposal.setSignature(getSignature(constructor)); >- MethodBinding original = constructor.original(); >- if(original != constructor) { >- proposal.setOriginalSignature(getSignature(original)); >- } >- proposal.setDeclarationPackageName(currentType.qualifiedPackageName()); >- proposal.setDeclarationTypeName(currentType.qualifiedSourceName()); >- proposal.setParameterPackageNames(parameterPackageNames); >- proposal.setParameterTypeNames(parameterTypeNames); >- //proposal.setPackageName(null); >- //proposal.setTypeName(null); >- proposal.setName(currentType.sourceName()); >- proposal.setIsContructor(true); >- proposal.setCompletion(completion); >- proposal.setFlags(constructor.modifiers); >- int start = (this.assistNodeInJavadoc > 0) ? this.startPosition : this.endPosition; >- proposal.setReplaceRange(start - this.offset, this.endPosition - this.offset); >- proposal.setTokenRange(this.tokenStart - this.offset, this.tokenEnd - this.offset); >- proposal.setRelevance(relevance); >- if(parameterNames != null) proposal.setParameterNames(parameterNames); >- this.requestor.accept(proposal); >- if(DEBUG) { >- this.printDebug(proposal); >- } >- } >- if ((this.assistNodeInJavadoc & CompletionOnJavadoc.TEXT) != 0 && !this.requestor.isIgnored(CompletionProposal.JAVADOC_METHOD_REF)) { >- char[] javadocCompletion = inlineTagCompletion(completion, JavadocTagConstants.TAG_LINK); >- InternalCompletionProposal proposal = createProposal(CompletionProposal.JAVADOC_METHOD_REF, this.actualCompletionPosition); >- proposal.setDeclarationSignature(getSignature(currentType)); >- proposal.setSignature(getSignature(constructor)); >- MethodBinding original = constructor.original(); >- if(original != constructor) { >- proposal.setOriginalSignature(getSignature(original)); >- } >- proposal.setDeclarationPackageName(currentType.qualifiedPackageName()); >- proposal.setDeclarationTypeName(currentType.qualifiedSourceName()); >- proposal.setParameterPackageNames(parameterPackageNames); >- proposal.setParameterTypeNames(parameterTypeNames); >- //proposal.setPackageName(null); >- //proposal.setTypeName(null); >- proposal.setName(currentType.sourceName()); >- proposal.setIsContructor(true); >- proposal.setCompletion(javadocCompletion); >- proposal.setFlags(constructor.modifiers); >- int start = (this.assistNodeInJavadoc & CompletionOnJavadoc.REPLACE_TAG) != 0 ? this.javadocTagPosition : this.startPosition; >- proposal.setReplaceRange(start - this.offset, this.endPosition - this.offset); >- proposal.setTokenRange(this.tokenStart - this.offset, this.tokenEnd - this.offset); >- proposal.setRelevance(relevance+R_INLINE_TAG); >- if(parameterNames != null) proposal.setParameterNames(parameterNames); >- this.requestor.accept(proposal); >- if(DEBUG) { >- this.printDebug(proposal); >- } >- } >- } >- } >- } >+ private TypeBinding[] computeTypesIfCorrect(Expression[] arguments) { >+ if (arguments == null) return null; >+ int argsLength = arguments.length; >+ TypeBinding[] argTypes = new TypeBinding[argsLength]; >+ for (int a = argsLength; --a >= 0;) { >+ TypeBinding typeBinding = arguments[a].resolvedType; >+ if(typeBinding == null || !typeBinding.isValidBinding()) return null; >+ argTypes[a] = typeBinding; > } >+ return argTypes; > } > >- private char[][] findEnclosingTypeNames(Scope scope){ >- char[][] excludedNames = new char[10][]; >- int excludedNameCount = 0; >- >- Scope currentScope = scope; >- while(currentScope != null) { >- switch (currentScope.kind) { >- case Scope.CLASS_SCOPE : >- ClassScope classScope = (ClassScope) currentScope; >- >- TypeDeclaration typeDeclaration = classScope.referenceContext; >- >- if(excludedNameCount == excludedNames.length) { >- System.arraycopy(excludedNames, 0, excludedNames = new char[excludedNameCount * 2][], 0, excludedNameCount); >- } >- excludedNames[excludedNameCount++] = typeDeclaration.name; >- >- TypeParameter[] classTypeParameters = typeDeclaration.typeParameters; >- if(classTypeParameters != null) { >- for (int i = 0; i < classTypeParameters.length; i++) { >- TypeParameter typeParameter = classTypeParameters[i]; >- if(excludedNameCount == excludedNames.length) { >- System.arraycopy(excludedNames, 0, excludedNames = new char[excludedNameCount * 2][], 0, excludedNameCount); >- } >- excludedNames[excludedNameCount++] = typeParameter.name; >- } >- } >- break; >- case Scope.METHOD_SCOPE : >- MethodScope methodScope = (MethodScope) currentScope; >- if(methodScope.referenceContext instanceof AbstractMethodDeclaration) { >- TypeParameter[] methodTypeParameters = ((AbstractMethodDeclaration)methodScope.referenceContext).typeParameters(); >- if(methodTypeParameters != null) { >- for (int i = 0; i < methodTypeParameters.length; i++) { >- TypeParameter typeParameter = methodTypeParameters[i]; >- if(excludedNameCount == excludedNames.length) { >- System.arraycopy(excludedNames, 0, excludedNames = new char[excludedNameCount * 2][], 0, excludedNameCount); >- } >- excludedNames[excludedNameCount++] = typeParameter.name; >- } >- } >- } >- break; >- } >- >- currentScope = currentScope.parent; >+ private void computeUninterestingBindings(ASTNode parent, Scope scope){ >+ if(parent instanceof LocalDeclaration) { >+ addUninterestingBindings(((LocalDeclaration)parent).binding); >+ } else if (parent instanceof FieldDeclaration) { >+ addUninterestingBindings(((FieldDeclaration)parent).binding); > } >+ } > >- if(excludedNameCount == 0) { >- return CharOperation.NO_CHAR_CHAR; >+ private char[] createImportCharArray(char[] importedElement, boolean isStatic, boolean onDemand) { >+ char[] result = IMPORT; >+ if (isStatic) { >+ result = CharOperation.concat(result, STATIC, ' '); > } >- System.arraycopy(excludedNames, 0, excludedNames = new char[excludedNameCount][], 0, excludedNameCount); >- return excludedNames; >+ result = CharOperation.concat(result, importedElement, ' '); >+ if (onDemand) { >+ result = CharOperation.concat(result, ON_DEMAND); >+ } >+ return CharOperation.concat(result, IMPORT_END); > } > >- // Helper method for findFields(char[], ReferenceBinding, Scope, ObjectVector, boolean) >- private void findFields( >- char[] fieldName, >- FieldBinding[] fields, >- Scope scope, >- ObjectVector fieldsFound, >- ObjectVector localsFound, >- boolean onlyStaticFields, >- ReferenceBinding receiverType, >- InvocationSite invocationSite, >- Scope invocationScope, >- boolean implicitCall, >- boolean canBePrefixed, >- Binding[] missingElements, >- int[] missingElementsStarts, >- int[] missingElementsEnds, >- boolean missingElementsHaveProblems, >- char[] castedReceiver, >- int receiverStart, >- int receiverEnd) { >- >- ObjectVector newFieldsFound = new ObjectVector(); >- // Inherited fields which are hidden by subclasses are filtered out >- // No visibility checks can be performed without the scope & invocationSite >+ private void createMethod(MethodBinding method, char[][] parameterPackageNames, char[][] parameterTypeNames, char[][] parameterNames, Scope scope, StringBuffer completion) { >+ //// Modifiers >+ // flush uninteresting modifiers >+ int insertedModifiers = method.modifiers & ~(ClassFileConstants.AccNative | ClassFileConstants.AccAbstract); >+ if(insertedModifiers != ClassFileConstants.AccDefault){ >+ ASTNode.printModifiers(insertedModifiers, completion); >+ } > >- int fieldLength = fieldName.length; >- next : for (int f = fields.length; --f >= 0;) { >- FieldBinding field = fields[f]; >+ //// Type parameters > >- if (field.isSynthetic()) continue next; >+ TypeVariableBinding[] typeVariableBindings = method.typeVariables; >+ if(typeVariableBindings != null && typeVariableBindings.length != 0) { >+ completion.append('<'); >+ for (int i = 0; i < typeVariableBindings.length; i++) { >+ if(i != 0) { >+ completion.append(','); >+ completion.append(' '); >+ } >+ createTypeVariable(typeVariableBindings[i], scope, completion); >+ } >+ completion.append('>'); >+ completion.append(' '); >+ } > >- if (onlyStaticFields && !field.isStatic()) continue next; >+ //// Return type >+ createType(method.returnType, scope, completion); >+ completion.append(' '); > >- if (fieldLength > field.name.length) continue next; >+ //// Selector >+ completion.append(method.selector); > >- if (!CharOperation.prefixEquals(fieldName, field.name, false /* ignore case */) >- && !(this.options.camelCaseMatch && CharOperation.camelCaseMatch(fieldName, field.name))) continue next; >+ completion.append('('); > >- if (this.options.checkDeprecation && >- field.isViewedAsDeprecated() && >- !scope.isDefinedInSameUnit(field.declaringClass)) >- continue next; >+ ////Parameters >+ TypeBinding[] parameterTypes = method.parameters; >+ int length = parameterTypes.length; >+ for (int i = 0; i < length; i++) { >+ if(i != 0) { >+ completion.append(','); >+ completion.append(' '); >+ } >+ createType(parameterTypes[i], scope, completion); >+ completion.append(' '); >+ if(parameterNames != null){ >+ completion.append(parameterNames[i]); >+ } else { >+ completion.append('%'); >+ } >+ } > >- if (this.options.checkVisibility >- && !field.canBeSeenBy(receiverType, invocationSite, scope)) continue next; >+ completion.append(')'); > >- boolean prefixRequired = false; >+ //// Exceptions >+ ReferenceBinding[] exceptions = method.thrownExceptions; > >- for (int i = fieldsFound.size; --i >= 0;) { >- Object[] other = (Object[])fieldsFound.elementAt(i); >- FieldBinding otherField = (FieldBinding) other[0]; >- ReferenceBinding otherReceiverType = (ReferenceBinding) other[1]; >- if (field == otherField && receiverType == otherReceiverType) >- continue next; >- if (CharOperation.equals(field.name, otherField.name, true)) { >- if (field.declaringClass.isSuperclassOf(otherField.declaringClass)) >- continue next; >- if (otherField.declaringClass.isInterface()) { >- if (field.declaringClass == scope.getJavaLangObject()) >- continue next; >- if (field.declaringClass.implementsInterface(otherField.declaringClass, true)) >- continue next; >- } >- if (field.declaringClass.isInterface()) >- if (otherField.declaringClass.implementsInterface(field.declaringClass, true)) >- continue next; >- if(canBePrefixed) { >- prefixRequired = true; >- } else { >- continue next; >- } >+ if (exceptions != null && exceptions.length > 0){ >+ completion.append(' '); >+ completion.append(THROWS); >+ completion.append(' '); >+ for(int i = 0; i < exceptions.length ; i++){ >+ if(i != 0) { >+ completion.append(' '); >+ completion.append(','); > } >+ createType(exceptions[i], scope, completion); > } >+ } >+ } > >- for (int l = localsFound.size; --l >= 0;) { >- LocalVariableBinding local = (LocalVariableBinding) localsFound.elementAt(l); >- >- if (CharOperation.equals(field.name, local.name, true)) { >- SourceTypeBinding declarationType = scope.enclosingSourceType(); >- if (declarationType.isAnonymousType() && declarationType != invocationScope.enclosingSourceType()) { >- continue next; >- } >- if(canBePrefixed) { >- prefixRequired = true; >- } else { >- continue next; >- } >- break; >- } >- } >+ protected InternalCompletionProposal createProposal(int kind, int completionOffset) { >+ InternalCompletionProposal proposal = (InternalCompletionProposal) CompletionProposal.create(kind, completionOffset - this.offset); >+ proposal.nameLookup = this.nameEnvironment.nameLookup; >+ proposal.completionEngine = this; >+ return proposal; >+ } > >- newFieldsFound.add(new Object[]{field, receiverType}); >- >- char[] completion = field.name; >+ private CompletionProposal createRequiredTypeProposal(Binding binding, int start, int end, int relevance) { >+ InternalCompletionProposal proposal = null; >+ if (binding instanceof ReferenceBinding) { >+ ReferenceBinding typeBinding = (ReferenceBinding) binding; > >- if(prefixRequired || this.options.forceImplicitQualification){ >- char[] prefix = computePrefix(scope.enclosingSourceType(), invocationScope.enclosingSourceType(), field.isStatic()); >- completion = CharOperation.concat(prefix,completion,'.'); >- } >+ char[] packageName = typeBinding.qualifiedPackageName(); >+ char[] typeName = typeBinding.qualifiedSourceName(); >+ char[] fullyQualifiedName = CharOperation.concat(packageName, typeName, '.'); > >+ proposal = createProposal(CompletionProposal.TYPE_REF, this.actualCompletionPosition); >+ proposal.nameLookup = this.nameEnvironment.nameLookup; >+ proposal.completionEngine = this; >+ proposal.setDeclarationSignature(packageName); >+ proposal.setSignature(getRequiredTypeSignature(typeBinding)); >+ proposal.setPackageName(packageName); >+ proposal.setTypeName(typeName); >+ proposal.setCompletion(fullyQualifiedName); >+ proposal.setFlags(typeBinding.modifiers); >+ proposal.setReplaceRange(start - this.offset, end - this.offset); >+ proposal.setTokenRange(start - this.offset, end - this.offset); >+ proposal.setRelevance(relevance); >+ } else if (binding instanceof PackageBinding) { >+ PackageBinding packageBinding = (PackageBinding) binding; > >- if (castedReceiver != null) { >- completion = CharOperation.concat(castedReceiver, completion); >- } >+ char[] packageName = CharOperation.concatWith(packageBinding.compoundName, '.'); > >- // Special case for javadoc completion >- if (this.assistNodeInJavadoc > 0) { >- if (invocationSite instanceof CompletionOnJavadocFieldReference) { >- CompletionOnJavadocFieldReference fieldRef = (CompletionOnJavadocFieldReference) invocationSite; >- if (fieldRef.receiver.isThis()) { >- if (fieldRef.completeInText()) { >- completion = CharOperation.concat(new char[] { '#' }, field.name); >- } >- } else if (fieldRef.completeInText()) { >- if (fieldRef.receiver instanceof JavadocSingleTypeReference) { >- JavadocSingleTypeReference typeRef = (JavadocSingleTypeReference) fieldRef.receiver; >- completion = CharOperation.concat(typeRef.token, field.name, '#'); >- } else if (fieldRef.receiver instanceof JavadocQualifiedTypeReference) { >- JavadocQualifiedTypeReference typeRef = (JavadocQualifiedTypeReference) fieldRef.receiver; >- completion = CharOperation.concat(CharOperation.concatWith(typeRef.tokens, '.'), field.name, '#'); >- } >- } >- } >- } >+ proposal = createProposal(CompletionProposal.PACKAGE_REF, this.actualCompletionPosition); >+ proposal.setDeclarationSignature(packageName); >+ proposal.setPackageName(packageName); >+ proposal.setCompletion(packageName); >+ proposal.setReplaceRange(start - this.offset, end - this.offset); >+ proposal.setTokenRange(start - this.offset, end - this.offset); >+ proposal.setRelevance(relevance); >+ } >+ return proposal; >+ } > >- int relevance = computeBaseRelevance(); >- relevance += computeRelevanceForResolution(); >- relevance += computeRelevanceForInterestingProposal(field); >- if (fieldName != null) relevance += computeRelevanceForCaseMatching(fieldName, field.name); >- relevance += computeRelevanceForExpectingType(field.type); >- relevance += computeRelevanceForEnumConstant(field.type); >- relevance += computeRelevanceForStatic(onlyStaticFields, field.isStatic()); >- relevance += computeRelevanceForQualification(prefixRequired); >- relevance += computeRelevanceForRestrictions(IAccessRule.K_ACCESSIBLE); >- if (onlyStaticFields && this.insideQualifiedReference) { >- relevance += computeRelevanceForInheritance(receiverType, field.declaringClass); >- } >- if (missingElements != null) { >- relevance += computeRelevanceForMissingElements(missingElementsHaveProblems); >- } >+ private void createType(TypeBinding type, Scope scope, StringBuffer completion) { >+ switch (type.kind()) { >+ case Binding.BASE_TYPE : >+ completion.append(type.sourceName()); >+ break; >+ case Binding.WILDCARD_TYPE : >+ case Binding.INTERSECTION_TYPE : // TODO (david) need to handle intersection type specifically >+ WildcardBinding wildcardBinding = (WildcardBinding) type; >+ completion.append('?'); >+ switch (wildcardBinding.boundKind) { >+ case Wildcard.EXTENDS: >+ completion.append(' '); >+ completion.append(EXTENDS); >+ completion.append(' '); >+ createType(wildcardBinding.bound, scope, completion); >+ if(wildcardBinding.otherBounds != null) { > >- this.noProposal = false; >- if (castedReceiver == null) { >- // Standard proposal >- if (!this.isIgnored(CompletionProposal.FIELD_REF, missingElements != null) && (this.assistNodeInJavadoc & CompletionOnJavadoc.ONLY_INLINE_TAG) == 0) { >- InternalCompletionProposal proposal = createProposal(CompletionProposal.FIELD_REF, this.actualCompletionPosition); >- proposal.setDeclarationSignature(getSignature(field.declaringClass)); >- proposal.setSignature(getSignature(field.type)); >- proposal.setDeclarationPackageName(field.declaringClass.qualifiedPackageName()); >- proposal.setDeclarationTypeName(field.declaringClass.qualifiedSourceName()); >- proposal.setPackageName(field.type.qualifiedPackageName()); >- proposal.setTypeName(field.type.qualifiedSourceName()); >- proposal.setName(field.name); >- if (missingElements != null) { >- CompletionProposal[] subProposals = new CompletionProposal[missingElements.length]; >- for (int i = 0; i < missingElements.length; i++) { >- subProposals[i] = >- createRequiredTypeProposal( >- missingElements[i], >- missingElementsStarts[i], >- missingElementsEnds[i], >- relevance); >+ int length = wildcardBinding.otherBounds.length; >+ for (int i = 0; i < length; i++) { >+ completion.append(' '); >+ completion.append('&'); >+ completion.append(' '); >+ createType(wildcardBinding.otherBounds[i], scope, completion); >+ } > } >- proposal.setRequiredProposals(subProposals); >- } >- proposal.setCompletion(completion); >- proposal.setFlags(field.modifiers); >- proposal.setReplaceRange(this.startPosition - this.offset, this.endPosition - this.offset); >- proposal.setTokenRange(this.tokenStart - this.offset, this.tokenEnd - this.offset); >- proposal.setRelevance(relevance); >- this.requestor.accept(proposal); >- if(DEBUG) { >- this.printDebug(proposal); >- } >+ break; >+ case Wildcard.SUPER: >+ completion.append(' '); >+ completion.append(SUPER); >+ completion.append(' '); >+ createType(wildcardBinding.bound, scope, completion); >+ break; > } >- >- // Javadoc completions >- if ((this.assistNodeInJavadoc & CompletionOnJavadoc.TEXT) != 0 && !this.requestor.isIgnored(CompletionProposal.JAVADOC_FIELD_REF)) { >- char[] javadocCompletion = inlineTagCompletion(completion, JavadocTagConstants.TAG_LINK); >- InternalCompletionProposal proposal = createProposal(CompletionProposal.JAVADOC_FIELD_REF, this.actualCompletionPosition); >- proposal.setDeclarationSignature(getSignature(field.declaringClass)); >- proposal.setSignature(getSignature(field.type)); >- proposal.setDeclarationPackageName(field.declaringClass.qualifiedPackageName()); >- proposal.setDeclarationTypeName(field.declaringClass.qualifiedSourceName()); >- proposal.setPackageName(field.type.qualifiedPackageName()); >- proposal.setTypeName(field.type.qualifiedSourceName()); >- proposal.setName(field.name); >- proposal.setCompletion(javadocCompletion); >- proposal.setFlags(field.modifiers); >- int start = (this.assistNodeInJavadoc & CompletionOnJavadoc.REPLACE_TAG) != 0 ? this.javadocTagPosition : this.startPosition; >- proposal.setReplaceRange(start - this.offset, this.endPosition - this.offset); >- proposal.setTokenRange(this.tokenStart - this.offset, this.tokenEnd - this.offset); >- proposal.setRelevance(relevance+R_INLINE_TAG); >- this.requestor.accept(proposal); >- if(DEBUG) { >- this.printDebug(proposal); >- } >- // Javadoc value completion for static fields >- if (field.isStatic() && !this.requestor.isIgnored(CompletionProposal.JAVADOC_VALUE_REF)) { >- javadocCompletion = inlineTagCompletion(completion, JavadocTagConstants.TAG_VALUE); >- InternalCompletionProposal valueProposal = createProposal(CompletionProposal.JAVADOC_VALUE_REF, this.actualCompletionPosition); >- valueProposal.setDeclarationSignature(getSignature(field.declaringClass)); >- valueProposal.setSignature(getSignature(field.type)); >- valueProposal.setDeclarationPackageName(field.declaringClass.qualifiedPackageName()); >- valueProposal.setDeclarationTypeName(field.declaringClass.qualifiedSourceName()); >- valueProposal.setPackageName(field.type.qualifiedPackageName()); >- valueProposal.setTypeName(field.type.qualifiedSourceName()); >- valueProposal.setName(field.name); >- valueProposal.setCompletion(javadocCompletion); >- valueProposal.setFlags(field.modifiers); >- valueProposal.setReplaceRange(start - this.offset, this.endPosition - this.offset); >- valueProposal.setTokenRange(this.tokenStart - this.offset, this.tokenEnd - this.offset); >- valueProposal.setRelevance(relevance+R_VALUE_TAG); >- this.requestor.accept(valueProposal); >- if(DEBUG) { >- this.printDebug(valueProposal); >- } >- } >+ break; >+ case Binding.ARRAY_TYPE : >+ createType(type.leafComponentType(), scope, completion); >+ int dim = type.dimensions(); >+ for (int i = 0; i < dim; i++) { >+ completion.append('['); >+ completion.append(']'); > } >- } else { >- if(!this.isIgnored(CompletionProposal.FIELD_REF_WITH_CASTED_RECEIVER, missingElements != null)) { >- InternalCompletionProposal proposal = createProposal(CompletionProposal.FIELD_REF_WITH_CASTED_RECEIVER, this.actualCompletionPosition); >- proposal.setDeclarationSignature(getSignature(field.declaringClass)); >- proposal.setSignature(getSignature(field.type)); >- proposal.setReceiverSignature(getSignature(receiverType)); >- proposal.setDeclarationPackageName(field.declaringClass.qualifiedPackageName()); >- proposal.setDeclarationTypeName(field.declaringClass.qualifiedSourceName()); >- proposal.setPackageName(field.type.qualifiedPackageName()); >- proposal.setTypeName(field.type.qualifiedSourceName()); >- proposal.setName(field.name); >- if (missingElements != null) { >- CompletionProposal[] subProposals = new CompletionProposal[missingElements.length]; >- for (int i = 0; i < missingElements.length; i++) { >- subProposals[i] = >- createRequiredTypeProposal( >- missingElements[i], >- missingElementsStarts[i], >- missingElementsEnds[i], >- relevance); >- } >- proposal.setRequiredProposals(subProposals); >- } >- proposal.setCompletion(completion); >- proposal.setFlags(field.modifiers); >- proposal.setReplaceRange(this.startPosition - this.offset, this.endPosition - this.offset); >- proposal.setReceiverRange(receiverStart - this.offset, receiverEnd - this.offset); >- proposal.setTokenRange(this.tokenStart - this.offset, this.tokenEnd - this.offset); >- proposal.setRelevance(relevance); >- this.requestor.accept(proposal); >- if(DEBUG) { >- this.printDebug(proposal); >- } >+ break; >+ case Binding.PARAMETERIZED_TYPE : >+ ParameterizedTypeBinding parameterizedType = (ParameterizedTypeBinding) type; >+ if (type.isMemberType()) { >+ createType(parameterizedType.enclosingType(), scope, completion); >+ completion.append('.'); >+ completion.append(parameterizedType.sourceName); >+ } else { >+ completion.append(CharOperation.concatWith(parameterizedType.genericType().compoundName, '.')); >+ } >+ if (parameterizedType.arguments != null) { >+ completion.append('<'); >+ for (int i = 0, length = parameterizedType.arguments.length; i < length; i++) { >+ if (i != 0) completion.append(','); >+ createType(parameterizedType.arguments[i], scope, completion); >+ } >+ completion.append('>'); > } >+ break; >+ default : >+ char[] packageName = type.qualifiedPackageName(); >+ char[] typeName = type.qualifiedSourceName(); >+ if(mustQualifyType( >+ (ReferenceBinding)type, >+ packageName, >+ scope)) { >+ completion.append(CharOperation.concat(packageName, typeName,'.')); >+ } else { >+ completion.append(type.sourceName()); > } >+ break; > } >- >- fieldsFound.addAll(newFieldsFound); > } > >- private void findFields( >- char[] fieldName, >- ReferenceBinding receiverType, >- Scope scope, >- ObjectVector fieldsFound, >- ObjectVector localsFound, >- boolean onlyStaticFields, >- InvocationSite invocationSite, >- Scope invocationScope, >- boolean implicitCall, >- boolean canBePrefixed, >- Binding[] missingElements, >- int[] missingElementsStarts, >- int[] missingElementsEnds, >- boolean missingElementsHaveProblems, >- char[] castedReceiver, >- int receiverStart, >- int receiverEnd) { >- >- boolean notInJavadoc = this.assistNodeInJavadoc == 0; >- if (fieldName == null && notInJavadoc) >- return; >+ /* >+ * Create a completion proposal for a member type. >+ */ >+ private void createTypeParameterProposal(TypeParameter typeParameter, int relevance) { >+ char[] completionName = typeParameter.name; > >- ReferenceBinding currentType = receiverType; >- ReferenceBinding[] interfacesToVisit = null; >- int nextPosition = 0; >- do { >- ReferenceBinding[] itsInterfaces = currentType.superInterfaces(); >- if (notInJavadoc && itsInterfaces != Binding.NO_SUPERINTERFACES) { >- if (interfacesToVisit == null) { >- interfacesToVisit = itsInterfaces; >- nextPosition = interfacesToVisit.length; >- } else { >- int itsLength = itsInterfaces.length; >- if (nextPosition + itsLength >= interfacesToVisit.length) >- System.arraycopy(interfacesToVisit, 0, interfacesToVisit = new ReferenceBinding[nextPosition + itsLength + 5], 0, nextPosition); >- nextInterface : for (int a = 0; a < itsLength; a++) { >- ReferenceBinding next = itsInterfaces[a]; >- for (int b = 0; b < nextPosition; b++) >- if (next == interfacesToVisit[b]) continue nextInterface; >- interfacesToVisit[nextPosition++] = next; >- } >- } >+ // Create standard type proposal >+ if(!this.requestor.isIgnored(CompletionProposal.TYPE_REF)) { >+ InternalCompletionProposal proposal = (InternalCompletionProposal) CompletionProposal.create(CompletionProposal.TYPE_REF, this.actualCompletionPosition - this.offset); >+ proposal.nameLookup = this.nameEnvironment.nameLookup; >+ proposal.completionEngine = this; >+ proposal.setSignature(getSignature(typeParameter.binding)); >+ proposal.setTypeName(completionName); >+ proposal.setCompletion(completionName); >+ proposal.setFlags(typeParameter.modifiers); >+ proposal.setReplaceRange(this.startPosition - this.offset, this.endPosition - this.offset); >+ proposal.setTokenRange(this.tokenStart - this.offset, this.tokenEnd - this.offset); >+ proposal.setRelevance(relevance); >+ this.requestor.accept(proposal); >+ if(DEBUG) { >+ this.printDebug(proposal); > } >+ } > >- FieldBinding[] fields = currentType.availableFields(); >- if(fields != null && fields.length > 0) { >- findFields( >- fieldName, >- fields, >- scope, >- fieldsFound, >- localsFound, >- onlyStaticFields, >- receiverType, >- invocationSite, >- invocationScope, >- implicitCall, >- canBePrefixed, >- missingElements, >- missingElementsStarts, >- missingElementsEnds, >- missingElementsHaveProblems, >- castedReceiver, >- receiverStart, >- receiverEnd); >+ // Create javadoc text proposal if necessary >+ if ((this.assistNodeInJavadoc & CompletionOnJavadoc.TEXT) != 0 && !this.requestor.isIgnored(CompletionProposal.JAVADOC_TYPE_REF)) { >+ char[] javadocCompletion= inlineTagCompletion(completionName, JavadocTagConstants.TAG_LINK); >+ InternalCompletionProposal proposal = (InternalCompletionProposal) CompletionProposal.create(CompletionProposal.JAVADOC_TYPE_REF, this.actualCompletionPosition - this.offset); >+ proposal.nameLookup = this.nameEnvironment.nameLookup; >+ proposal.completionEngine = this; >+ proposal.setSignature(getSignature(typeParameter.binding)); >+ proposal.setTypeName(javadocCompletion); >+ proposal.setCompletion(javadocCompletion); >+ proposal.setFlags(typeParameter.modifiers); >+ proposal.setReplaceRange(this.startPosition - this.offset, this.endPosition - this.offset); >+ proposal.setTokenRange(this.tokenStart - this.offset, this.tokenEnd - this.offset); >+ proposal.setRelevance(relevance+R_INLINE_TAG); >+ this.requestor.accept(proposal); >+ if(DEBUG) { >+ this.printDebug(proposal); > } >- currentType = currentType.superclass(); >- } while (notInJavadoc && currentType != null); >+ } >+ } > >- if (notInJavadoc && interfacesToVisit != null) { >- for (int i = 0; i < nextPosition; i++) { >- ReferenceBinding anInterface = interfacesToVisit[i]; >- FieldBinding[] fields = anInterface.availableFields(); >- if(fields != null) { >- findFields( >- fieldName, >- fields, >- scope, >- fieldsFound, >- localsFound, >- onlyStaticFields, >- receiverType, >- invocationSite, >- invocationScope, >- implicitCall, >- canBePrefixed, >- missingElements, >- missingElementsStarts, >- missingElementsEnds, >- missingElementsHaveProblems, >- castedReceiver, >- receiverStart, >- receiverEnd); >- } >+ /* >+ * Create a completion proposal for a type. >+ */ >+ private void createTypeProposal(char[] packageName, char[] typeName, int modifiers, int accessibility, char[] completionName, int relevance) { > >- ReferenceBinding[] itsInterfaces = anInterface.superInterfaces(); >- if (itsInterfaces != Binding.NO_SUPERINTERFACES) { >- int itsLength = itsInterfaces.length; >- if (nextPosition + itsLength >= interfacesToVisit.length) >- System.arraycopy(interfacesToVisit, 0, interfacesToVisit = new ReferenceBinding[nextPosition + itsLength + 5], 0, nextPosition); >- nextInterface : for (int a = 0; a < itsLength; a++) { >- ReferenceBinding next = itsInterfaces[a]; >- for (int b = 0; b < nextPosition; b++) >- if (next == interfacesToVisit[b]) continue nextInterface; >- interfacesToVisit[nextPosition++] = next; >- } >- } >+ // Create standard type proposal >+ if(!this.requestor.isIgnored(CompletionProposal.TYPE_REF) && (this.assistNodeInJavadoc & CompletionOnJavadoc.ONLY_INLINE_TAG) == 0) { >+ InternalCompletionProposal proposal = (InternalCompletionProposal) CompletionProposal.create(CompletionProposal.TYPE_REF, this.actualCompletionPosition - this.offset); >+ proposal.nameLookup = this.nameEnvironment.nameLookup; >+ proposal.completionEngine = this; >+ proposal.setDeclarationSignature(packageName); >+ proposal.setSignature(createNonGenericTypeSignature(packageName, typeName)); >+ proposal.setPackageName(packageName); >+ proposal.setTypeName(typeName); >+ proposal.setCompletion(completionName); >+ proposal.setFlags(modifiers); >+ proposal.setReplaceRange(this.startPosition - this.offset, this.endPosition - this.offset); >+ proposal.setTokenRange(this.tokenStart - this.offset, this.tokenEnd - this.offset); >+ proposal.setRelevance(relevance); >+ proposal.setAccessibility(accessibility); >+ this.requestor.accept(proposal); >+ if(DEBUG) { >+ this.printDebug(proposal); >+ } >+ } >+ >+ // Create javadoc text proposal if necessary >+ if ((this.assistNodeInJavadoc & CompletionOnJavadoc.TEXT) != 0 && !this.requestor.isIgnored(CompletionProposal.JAVADOC_TYPE_REF)) { >+ char[] javadocCompletion= inlineTagCompletion(completionName, JavadocTagConstants.TAG_LINK); >+ InternalCompletionProposal proposal = (InternalCompletionProposal) CompletionProposal.create(CompletionProposal.JAVADOC_TYPE_REF, this.actualCompletionPosition - this.offset); >+ proposal.nameLookup = this.nameEnvironment.nameLookup; >+ proposal.completionEngine = this; >+ proposal.setDeclarationSignature(packageName); >+ proposal.setSignature(createNonGenericTypeSignature(packageName, typeName)); >+ proposal.setPackageName(packageName); >+ proposal.setTypeName(typeName); >+ proposal.setCompletion(javadocCompletion); >+ proposal.setFlags(modifiers); >+ int start = (this.assistNodeInJavadoc & CompletionOnJavadoc.REPLACE_TAG) != 0 ? this.javadocTagPosition : this.startPosition; >+ proposal.setReplaceRange(start - this.offset, this.endPosition - this.offset); >+ proposal.setTokenRange(this.tokenStart - this.offset, this.tokenEnd - this.offset); >+ proposal.setRelevance(relevance+R_INLINE_TAG); >+ proposal.setAccessibility(accessibility); >+ this.requestor.accept(proposal); >+ if(DEBUG) { >+ this.printDebug(proposal); > } > } > } > >- protected void findFieldsAndMethodsFromAnotherReceiver( >- char[] token, >- TypeReference receiverType, >- Scope scope, >- ObjectVector fieldsFound, >- ObjectVector methodsFound, >- InvocationSite invocationSite, >- Scope invocationScope, >- boolean implicitCall, >- boolean superCall, >+ /* >+ * Create a completion proposal for a member type. >+ */ >+ private void createTypeProposal( >+ ReferenceBinding refBinding, >+ char[] typeName, >+ int accessibility, >+ char[] completionName, >+ int relevance, > Binding[] missingElements, > int[] missingElementsStarts, > int[] missingElementsEnds, >- boolean missingElementsHaveProblems, >- char[][] receiverName, >- int receiverStart, >- int receiverEnd) { >- >- if (receiverType.resolvedType == null) return; >- >- TypeBinding receiverTypeBinding = receiverType.resolvedType; >- char[] castedReceiver = null; >- >- char[] castedTypeChars = CharOperation.concatWith(receiverType.getTypeName(), '.'); >- if(this.source != null) { >- int memberRefStart = this.startPosition; >+ boolean missingElementsHaveProblems) { > >- char[] receiverChars = CharOperation.subarray(this.source, receiverStart, receiverEnd); >- char[] dotChars = CharOperation.subarray(this.source, receiverEnd, memberRefStart); >+ // Create standard type proposal >+ if(!this.isIgnored(CompletionProposal.TYPE_REF, missingElements != null) && (this.assistNodeInJavadoc & CompletionOnJavadoc.ONLY_INLINE_TAG) == 0) { >+ InternalCompletionProposal proposal = (InternalCompletionProposal) CompletionProposal.create(CompletionProposal.TYPE_REF, this.actualCompletionPosition - this.offset); >+ proposal.nameLookup = this.nameEnvironment.nameLookup; >+ proposal.completionEngine = this; >+ proposal.setDeclarationSignature(refBinding.qualifiedPackageName()); >+ proposal.setSignature(getCompletedTypeSignature(refBinding)); >+ proposal.setPackageName(refBinding.qualifiedPackageName()); >+ proposal.setTypeName(typeName); >+ if (missingElements != null) { >+ CompletionProposal[] subProposals = new CompletionProposal[missingElements.length]; >+ for (int i = 0; i < missingElements.length; i++) { >+ subProposals[i] = >+ createRequiredTypeProposal( >+ missingElements[i], >+ missingElementsStarts[i], >+ missingElementsEnds[i], >+ relevance); >+ } >+ proposal.setRequiredProposals(subProposals); >+ } >+ proposal.setCompletion(completionName); >+ proposal.setFlags(refBinding.modifiers); >+ proposal.setReplaceRange(this.startPosition - this.offset, this.endPosition - this.offset); >+ proposal.setTokenRange(this.tokenStart - this.offset, this.tokenEnd - this.offset); >+ proposal.setRelevance(relevance); >+ this.requestor.accept(proposal); >+ if(DEBUG) { >+ this.printDebug(proposal); >+ } >+ } > >- castedReceiver = >- CharOperation.concat( >- CharOperation.concat( >- '(', >- CharOperation.concat( >- CharOperation.concat('(', castedTypeChars, ')'), >- receiverChars), >- ')'), >- dotChars); >+ // Create javadoc text proposal if necessary >+ if ((this.assistNodeInJavadoc & CompletionOnJavadoc.TEXT) != 0 && !this.requestor.isIgnored(CompletionProposal.JAVADOC_TYPE_REF)) { >+ char[] javadocCompletion= inlineTagCompletion(completionName, JavadocTagConstants.TAG_LINK); >+ InternalCompletionProposal proposal = (InternalCompletionProposal) CompletionProposal.create(CompletionProposal.JAVADOC_TYPE_REF, this.actualCompletionPosition - this.offset); >+ proposal.nameLookup = this.nameEnvironment.nameLookup; >+ proposal.completionEngine = this; >+ proposal.setDeclarationSignature(refBinding.qualifiedPackageName()); >+ proposal.setSignature(getCompletedTypeSignature(refBinding)); >+ proposal.setPackageName(refBinding.qualifiedPackageName()); >+ proposal.setTypeName(typeName); >+ proposal.setCompletion(javadocCompletion); >+ proposal.setFlags(refBinding.modifiers); >+ int start = (this.assistNodeInJavadoc & CompletionOnJavadoc.REPLACE_TAG) != 0 ? this.javadocTagPosition : this.startPosition; >+ proposal.setReplaceRange(start - this.offset, this.endPosition - this.offset); >+ proposal.setTokenRange(this.tokenStart - this.offset, this.tokenEnd - this.offset); >+ proposal.setRelevance(relevance+R_INLINE_TAG); >+ this.requestor.accept(proposal); >+ if(DEBUG) { >+ this.printDebug(proposal); >+ } >+ } >+ } >+ private void createTypeVariable(TypeVariableBinding typeVariable, Scope scope, StringBuffer completion) { >+ completion.append(typeVariable.sourceName); >+ >+ if (typeVariable.superclass != null && typeVariable.firstBound == typeVariable.superclass) { >+ completion.append(' '); >+ completion.append(EXTENDS); >+ completion.append(' '); >+ createType(typeVariable.superclass, scope, completion); >+ } >+ if (typeVariable.superInterfaces != null && typeVariable.superInterfaces != Binding.NO_SUPERINTERFACES) { >+ if (typeVariable.firstBound != typeVariable.superclass) { >+ completion.append(' '); >+ completion.append(EXTENDS); >+ completion.append(' '); >+ } >+ for (int i = 0, length = typeVariable.superInterfaces.length; i < length; i++) { >+ if (i > 0 || typeVariable.firstBound == typeVariable.superclass) { >+ completion.append(' '); >+ completion.append(EXTENDS); >+ completion.append(' '); >+ } >+ createType(typeVariable.superInterfaces[i], scope, completion); >+ } >+ } >+ } >+ private void createVargsType(TypeBinding type, Scope scope, StringBuffer completion) { >+ if (type.isArrayType()) { >+ createType(type.leafComponentType(), scope, completion); >+ int dim = type.dimensions() - 1; >+ for (int i = 0; i < dim; i++) { >+ completion.append('['); >+ completion.append(']'); >+ } >+ completion.append(VARARGS); > } else { >- castedReceiver = >- CharOperation.concat( >- CharOperation.concat( >- '(', >- CharOperation.concat( >- CharOperation.concat('(', castedTypeChars, ')'), >- CharOperation.concatWith(receiverName, '.')), >- ')'), >- DOT); >+ createType(type, scope, completion); > } >+ } >+ private void findAnnotationAttributes(char[] token, MemberValuePair[] attributesFound, ReferenceBinding annotation) { >+ MethodBinding[] methods = annotation.availableMethods(); >+ nextAttribute: for (int i = 0; i < methods.length; i++) { >+ MethodBinding method = methods[i]; > >- if (castedReceiver == null) return; >+ if(!CharOperation.prefixEquals(token, method.selector, false) >+ && !(this.options.camelCaseMatch && CharOperation.camelCaseMatch(token, method.selector))) continue nextAttribute; > >- int oldStartPosition = this.startPosition; >- this.startPosition = receiverStart; >+ int length = attributesFound == null ? 0 : attributesFound.length; >+ for (int j = 0; j < length; j++) { >+ if(CharOperation.equals(method.selector, attributesFound[j].name, false)) continue nextAttribute; >+ } > >- findFieldsAndMethods( >- token, >- receiverTypeBinding, >- scope, >- fieldsFound, >- methodsFound, >- invocationSite, >- invocationScope, >- implicitCall, >- superCall, >- missingElements, >- missingElementsStarts, >- missingElementsEnds, >- missingElementsHaveProblems, >- castedReceiver, >- receiverStart, >- receiverEnd); >+ int relevance = computeBaseRelevance(); >+ relevance += computeRelevanceForResolution(); >+ relevance += computeRelevanceForInterestingProposal(method); >+ relevance += computeRelevanceForCaseMatching(token, method.selector); >+ relevance += computeRelevanceForQualification(false); >+ relevance += computeRelevanceForRestrictions(IAccessRule.K_ACCESSIBLE); > >- this.startPosition = oldStartPosition; >+ this.noProposal = false; >+ if(!this.requestor.isIgnored(CompletionProposal.ANNOTATION_ATTRIBUTE_REF)) { >+ CompletionProposal proposal = createProposal(CompletionProposal.ANNOTATION_ATTRIBUTE_REF, this.actualCompletionPosition); >+ proposal.setDeclarationSignature(getSignature(method.declaringClass)); >+ proposal.setSignature(getSignature(method.returnType)); >+ proposal.setName(method.selector); >+ proposal.setCompletion(method.selector); >+ proposal.setFlags(method.modifiers); >+ proposal.setReplaceRange(this.startPosition - this.offset, this.endPosition - this.offset); >+ proposal.setTokenRange(this.tokenStart - this.offset, this.tokenEnd - this.offset); >+ proposal.setRelevance(relevance); >+ this.requestor.accept(proposal); >+ if(DEBUG) { >+ this.printDebug(proposal); >+ } >+ } >+ } > } >- protected void findFieldsAndMethods( >- char[] token, >- TypeBinding receiverType, >+ private void findAnonymousType( >+ ReferenceBinding currentType, >+ TypeBinding[] argTypes, > Scope scope, >- ObjectVector fieldsFound, >- ObjectVector methodsFound, >- InvocationSite invocationSite, >- Scope invocationScope, >- boolean implicitCall, >- boolean superCall, >- Binding[] missingElements, >- int[] missingElementsStarts, >- int[] missingElementsEnds, >- boolean missingElementsHaveProblems, >- char[] castedReceiver, >- int receiverStart, >- int receiverEnd) { >+ InvocationSite invocationSite) { > >- if (token == null) >- return; >+ if (currentType.isInterface()) { >+ char[] completion = CharOperation.NO_CHAR; >+ int relevance = computeBaseRelevance(); >+ relevance += computeRelevanceForResolution(); >+ relevance += computeRelevanceForInterestingProposal(); >+ relevance += computeRelevanceForRestrictions(IAccessRule.K_ACCESSIBLE); > >- if (receiverType.isBaseType()) >- return; // nothing else is possible with base types >+ this.noProposal = false; >+ if(!this.requestor.isIgnored(CompletionProposal.ANONYMOUS_CLASS_DECLARATION)) { >+ InternalCompletionProposal proposal = createProposal(CompletionProposal.ANONYMOUS_CLASS_DECLARATION, this.actualCompletionPosition); >+ proposal.setDeclarationSignature(getSignature(currentType)); >+ proposal.setDeclarationKey(currentType.computeUniqueKey()); >+ proposal.setSignature( >+ createMethodSignature( >+ CharOperation.NO_CHAR_CHAR, >+ CharOperation.NO_CHAR_CHAR, >+ CharOperation.NO_CHAR, >+ CharOperation.NO_CHAR)); >+ //proposal.setOriginalSignature(null); >+ //proposal.setUniqueKey(null); >+ proposal.setDeclarationPackageName(currentType.qualifiedPackageName()); >+ proposal.setDeclarationTypeName(currentType.qualifiedSourceName()); >+ //proposal.setParameterPackageNames(null); >+ //proposal.setParameterTypeNames(null); >+ //proposal.setPackageName(null); >+ //proposal.setTypeName(null); >+ proposal.setCompletion(completion); >+ proposal.setFlags(Flags.AccPublic); >+ proposal.setReplaceRange(this.endPosition - this.offset, this.endPosition - this.offset); >+ proposal.setTokenRange(this.tokenEnd - this.offset, this.tokenEnd - this.offset); >+ proposal.setRelevance(relevance); >+ this.requestor.accept(proposal); >+ if(DEBUG) { >+ this.printDebug(proposal); >+ } >+ } >+ } else { >+ findConstructors( >+ currentType, >+ argTypes, >+ scope, >+ invocationSite, >+ true); >+ } >+ } >+ private void findClassField( >+ char[] token, >+ TypeBinding receiverType, >+ Scope scope, >+ Binding[] missingElements, >+ int[] missingElementsStarts, >+ int[] missingElementsEnds, >+ boolean missingElementsHaveProblems) { > >- boolean proposeField = >- castedReceiver == null ? >- !this.isIgnored(CompletionProposal.FIELD_REF, missingElements != null) : >- !this.isIgnored(CompletionProposal.FIELD_REF_WITH_CASTED_RECEIVER, missingElements != null) ; >- boolean proposeMethod = >- castedReceiver == null ? >- !this.isIgnored(CompletionProposal.METHOD_REF, missingElements != null) : >- !this.isIgnored(CompletionProposal.METHOD_REF_WITH_CASTED_RECEIVER, missingElements != null); >+ if (token == null) return; > >- if (receiverType.isArrayType()) { >- if (proposeField >- && token.length <= lengthField.length >- && CharOperation.prefixEquals(token, lengthField, false /* ignore case */ >- )) { >+ if (token.length <= classField.length >+ && CharOperation.prefixEquals(token, classField, false /* ignore case */ >+ )) { >+ int relevance = computeBaseRelevance(); >+ relevance += computeRelevanceForResolution(); >+ relevance += computeRelevanceForInterestingProposal(); >+ relevance += computeRelevanceForCaseMatching(token, classField); >+ relevance += computeRelevanceForExpectingType(scope.getJavaLangClass()); >+ relevance += computeRelevanceForRestrictions(IAccessRule.K_ACCESSIBLE); //no access restriction for class field >+ relevance += R_NON_INHERITED; > >- int relevance = computeBaseRelevance(); >- relevance += computeRelevanceForResolution(); >- relevance += computeRelevanceForInterestingProposal(); >- relevance += computeRelevanceForCaseMatching(token,lengthField); >- relevance += computeRelevanceForExpectingType(TypeBinding.INT); >- relevance += computeRelevanceForRestrictions(IAccessRule.K_ACCESSIBLE); // no access restriction for length field >- if (missingElements != null) { >- relevance += computeRelevanceForMissingElements(missingElementsHaveProblems); >+ if (missingElements != null) { >+ relevance += computeRelevanceForMissingElements(missingElementsHaveProblems); >+ } >+ >+ this.noProposal = false; >+ if(!isIgnored(CompletionProposal.FIELD_REF, missingElements != null)) { >+ InternalCompletionProposal proposal = createProposal(CompletionProposal.FIELD_REF, this.actualCompletionPosition); >+ //proposal.setDeclarationSignature(null); >+ char[] signature = >+ createNonGenericTypeSignature( >+ CharOperation.concatWith(JAVA_LANG, '.'), >+ CLASS); >+ if (this.compilerOptions.sourceLevel > ClassFileConstants.JDK1_4) { >+ // add type argument >+ char[] typeArgument = getTypeSignature(receiverType); >+ int oldLength = signature.length; >+ int argumentLength = typeArgument.length; >+ int newLength = oldLength + argumentLength + 2; >+ System.arraycopy(signature, 0, signature = new char[newLength], 0, oldLength - 1); >+ signature[oldLength - 1] = '<'; >+ System.arraycopy(typeArgument, 0, signature, oldLength , argumentLength); >+ signature[newLength - 2] = '>'; >+ signature[newLength - 1] = ';'; > } >- this.noProposal = false; >- if (castedReceiver == null) { >- if(!isIgnored(CompletionProposal.FIELD_REF, missingElements != null)) { >- InternalCompletionProposal proposal = createProposal(CompletionProposal.FIELD_REF, this.actualCompletionPosition); >- proposal.setDeclarationSignature(getSignature(receiverType)); >- proposal.setSignature(INT_SIGNATURE); >- proposal.setTypeName(INT); >- proposal.setName(lengthField); >- if (missingElements != null) { >- CompletionProposal[] subProposals = new CompletionProposal[missingElements.length]; >- for (int i = 0; i < missingElements.length; i++) { >- subProposals[i] = >- createRequiredTypeProposal( >- missingElements[i], >- missingElementsStarts[i], >- missingElementsEnds[i], >- relevance); >- } >- proposal.setRequiredProposals(subProposals); >- } >- proposal.setCompletion(lengthField); >- proposal.setFlags(Flags.AccPublic); >- proposal.setReplaceRange(this.startPosition - this.offset, this.endPosition - this.offset); >- proposal.setTokenRange(this.tokenStart - this.offset, this.tokenEnd - this.offset); >- proposal.setRelevance(relevance); >- this.requestor.accept(proposal); >- if(DEBUG) { >- this.printDebug(proposal); >- } >- } >- } else { >- char[] completion = CharOperation.concat(castedReceiver, lengthField); >- >- if(!this.isIgnored(CompletionProposal.FIELD_REF_WITH_CASTED_RECEIVER, missingElements != null)) { >- InternalCompletionProposal proposal = createProposal(CompletionProposal.FIELD_REF_WITH_CASTED_RECEIVER, this.actualCompletionPosition); >- proposal.setDeclarationSignature(getSignature(receiverType)); >- proposal.setSignature(INT_SIGNATURE); >- proposal.setReceiverSignature(getSignature(receiverType)); >- proposal.setTypeName(INT); >- proposal.setName(lengthField); >- if (missingElements != null) { >- CompletionProposal[] subProposals = new CompletionProposal[missingElements.length]; >- for (int i = 0; i < missingElements.length; i++) { >- subProposals[i] = >- createRequiredTypeProposal( >- missingElements[i], >- missingElementsStarts[i], >- missingElementsEnds[i], >- relevance); >- } >- proposal.setRequiredProposals(subProposals); >- } >- proposal.setCompletion(completion); >- proposal.setFlags(Flags.AccPublic); >- proposal.setReplaceRange(this.startPosition - this.offset, this.endPosition - this.offset); >- proposal.setReceiverRange(receiverStart - this.offset, receiverEnd - this.offset); >- proposal.setTokenRange(this.tokenStart - this.offset, this.tokenEnd - this.offset); >- proposal.setRelevance(relevance); >- this.requestor.accept(proposal); >- if(DEBUG) { >- this.printDebug(proposal); >- } >+ proposal.setSignature(signature); >+ //proposal.setDeclarationPackageName(null); >+ //proposal.setDeclarationTypeName(null); >+ proposal.setPackageName(CharOperation.concatWith(JAVA_LANG, '.')); >+ proposal.setTypeName(CLASS); >+ proposal.setName(classField); >+ if (missingElements != null) { >+ CompletionProposal[] subProposals = new CompletionProposal[missingElements.length]; >+ for (int i = 0; i < missingElements.length; i++) { >+ subProposals[i] = >+ createRequiredTypeProposal( >+ missingElements[i], >+ missingElementsStarts[i], >+ missingElementsEnds[i], >+ relevance); > } >+ proposal.setRequiredProposals(subProposals); >+ } >+ proposal.setCompletion(classField); >+ proposal.setFlags(Flags.AccStatic | Flags.AccPublic); >+ proposal.setReplaceRange(this.startPosition - this.offset, this.endPosition - this.offset); >+ proposal.setTokenRange(this.tokenStart - this.offset, this.tokenEnd - this.offset); >+ proposal.setRelevance(relevance); >+ this.requestor.accept(proposal); >+ if(DEBUG) { >+ this.printDebug(proposal); > } > } >- if (proposeMethod >- && token.length <= cloneMethod.length >- && CharOperation.prefixEquals(token, cloneMethod, false /* ignore case */) >- ) { >- ReferenceBinding objectRef = scope.getJavaLangObject(); >+ } >+ } >+ private void findConstructors( >+ ReferenceBinding currentType, >+ TypeBinding[] argTypes, >+ Scope scope, >+ InvocationSite invocationSite, >+ boolean forAnonymousType) { > >- int relevance = computeBaseRelevance(); >- relevance += computeRelevanceForResolution(); >- relevance += computeRelevanceForInterestingProposal(); >- relevance += computeRelevanceForCaseMatching(token, cloneMethod); >- relevance += computeRelevanceForExpectingType(objectRef); >- relevance += computeRelevanceForStatic(false, false); >- relevance += computeRelevanceForQualification(false); >- relevance += computeRelevanceForRestrictions(IAccessRule.K_ACCESSIBLE); // no access restriction for clone() method >- if (missingElements != null) { >- relevance += computeRelevanceForMissingElements(missingElementsHaveProblems); >- } >- char[] completion; >- if (this.source != null >- && this.source.length > this.endPosition >- && this.source[this.endPosition] == '(') { >- completion = cloneMethod; >- } else { >- completion = CharOperation.concat(cloneMethod, new char[] { '(', ')' }); >- } >+ // No visibility checks can be performed without the scope & invocationSite >+ MethodBinding[] methods = currentType.availableMethods(); >+ if(methods != null) { >+ int minArgLength = argTypes == null ? 0 : argTypes.length; >+ next : for (int f = methods.length; --f >= 0;) { >+ MethodBinding constructor = methods[f]; >+ if (constructor.isConstructor()) { > >- if (castedReceiver != null) { >- completion = CharOperation.concat(castedReceiver, completion); >- } >+ if (constructor.isSynthetic()) continue next; > >- this.noProposal = false; >- if (castedReceiver == null) { >- if (!this.isIgnored(CompletionProposal.METHOD_REF, missingElements != null)) { >- InternalCompletionProposal proposal = createProposal(CompletionProposal.METHOD_REF, this.actualCompletionPosition); >- proposal.setDeclarationSignature(getSignature(receiverType)); >- proposal.setSignature( >- this.compilerOptions.sourceLevel > ClassFileConstants.JDK1_4 && receiverType.isArrayType() ? >- createMethodSignature( >- CharOperation.NO_CHAR_CHAR, >- CharOperation.NO_CHAR_CHAR, >- getSignature(receiverType)) : >- createMethodSignature( >- CharOperation.NO_CHAR_CHAR, >- CharOperation.NO_CHAR_CHAR, >- CharOperation.concatWith(JAVA_LANG, '.'), >- OBJECT)); >- //proposal.setOriginalSignature(null); >- //proposal.setDeclarationPackageName(null); >- //proposal.setDeclarationTypeName(null); >- //proposal.setParameterPackageNames(null); >- //proposal.setParameterTypeNames(null); >- proposal.setPackageName(CharOperation.concatWith(JAVA_LANG, '.')); >- proposal.setTypeName(OBJECT); >- proposal.setName(cloneMethod); >- if (missingElements != null) { >- CompletionProposal[] subProposals = new CompletionProposal[missingElements.length]; >- for (int i = 0; i < missingElements.length; i++) { >- subProposals[i] = >- createRequiredTypeProposal( >- missingElements[i], >- missingElementsStarts[i], >- missingElementsEnds[i], >- relevance); >- } >- proposal.setRequiredProposals(subProposals); >- } >- proposal.setCompletion(completion); >- proposal.setFlags(Flags.AccPublic); >- proposal.setReplaceRange(this.startPosition - this.offset, this.endPosition - this.offset); >- proposal.setTokenRange(this.tokenStart - this.offset, this.tokenEnd - this.offset); >- proposal.setRelevance(relevance); >- this.requestor.accept(proposal); >- if(DEBUG) { >- this.printDebug(proposal); >- } >+ if (this.options.checkDeprecation && >+ constructor.isViewedAsDeprecated() && >+ !scope.isDefinedInSameUnit(constructor.declaringClass)) >+ continue next; >+ >+ if (this.options.checkVisibility >+ && !constructor.canBeSeenBy(invocationSite, scope)) { >+ if(!forAnonymousType || !constructor.isProtected()) >+ continue next; > } >- methodsFound.add(new Object[]{objectRef.getMethods(cloneMethod)[0], objectRef}); >- } else { >- if(!this.isIgnored(CompletionProposal.METHOD_REF_WITH_CASTED_RECEIVER, missingElements != null)) { >- InternalCompletionProposal proposal = createProposal(CompletionProposal.METHOD_REF_WITH_CASTED_RECEIVER, this.actualCompletionPosition); >- proposal.setDeclarationSignature(getSignature(receiverType)); >- proposal.setSignature( >- this.compilerOptions.sourceLevel > ClassFileConstants.JDK1_4 && receiverType.isArrayType() ? >- createMethodSignature( >- CharOperation.NO_CHAR_CHAR, >- CharOperation.NO_CHAR_CHAR, >- getSignature(receiverType)) : >- createMethodSignature( >- CharOperation.NO_CHAR_CHAR, >- CharOperation.NO_CHAR_CHAR, >- CharOperation.concatWith(JAVA_LANG, '.'), >- OBJECT)); >- proposal.setReceiverSignature(getSignature(receiverType)); >- proposal.setPackageName(CharOperation.concatWith(JAVA_LANG, '.')); >- proposal.setTypeName(OBJECT); >- proposal.setName(cloneMethod); >- if (missingElements != null) { >- CompletionProposal[] subProposals = new CompletionProposal[missingElements.length]; >- for (int i = 0; i < missingElements.length; i++) { >- subProposals[i] = >- createRequiredTypeProposal( >- missingElements[i], >- missingElementsStarts[i], >- missingElementsEnds[i], >- relevance); >- } >- proposal.setRequiredProposals(subProposals); >- } >- proposal.setCompletion(completion); >- proposal.setFlags(Flags.AccPublic); >- proposal.setReplaceRange(this.startPosition - this.offset, this.endPosition - this.offset); >- proposal.setReceiverRange(receiverStart - this.offset, receiverEnd - this.offset); >- proposal.setTokenRange(this.tokenStart - this.offset, this.tokenEnd - this.offset); >- proposal.setRelevance(relevance); >- this.requestor.accept(proposal); >- if(DEBUG) { >- this.printDebug(proposal); >+ >+ TypeBinding[] parameters = constructor.parameters; >+ int paramLength = parameters.length; >+ if (minArgLength > paramLength) >+ continue next; >+ for (int a = minArgLength; --a >= 0;) >+ if (argTypes[a] != null) { // can be null if it could not be resolved properly >+ if (!argTypes[a].isCompatibleWith(constructor.parameters[a])) >+ continue next; > } >+ >+ char[][] parameterPackageNames = new char[paramLength][]; >+ char[][] parameterTypeNames = new char[paramLength][]; >+ for (int i = 0; i < paramLength; i++) { >+ TypeBinding type = parameters[i]; >+ parameterPackageNames[i] = type.qualifiedPackageName(); >+ parameterTypeNames[i] = type.qualifiedSourceName(); > } >- } >- } >+ char[][] parameterNames = findMethodParameterNames(constructor,parameterTypeNames); > >- receiverType = scope.getJavaLangObject(); >- } >+ char[] completion = CharOperation.NO_CHAR; >+ if(forAnonymousType){ >+ int relevance = computeBaseRelevance(); >+ relevance += computeRelevanceForResolution(); >+ relevance += computeRelevanceForInterestingProposal(); >+ relevance += computeRelevanceForRestrictions(IAccessRule.K_ACCESSIBLE); > >- if(proposeField) { >- findFields( >- token, >- (ReferenceBinding) receiverType, >- scope, >- fieldsFound, >- new ObjectVector(), >- false, >- invocationSite, >- invocationScope, >- implicitCall, >- false, >- missingElements, >- missingElementsStarts, >- missingElementsEnds, >- missingElementsHaveProblems, >- castedReceiver, >- receiverStart, >- receiverEnd); >- } >+ this.noProposal = false; >+ if(!this.requestor.isIgnored(CompletionProposal.ANONYMOUS_CLASS_DECLARATION)) { >+ InternalCompletionProposal proposal = createProposal(CompletionProposal.ANONYMOUS_CLASS_DECLARATION, this.actualCompletionPosition); >+ proposal.setDeclarationSignature(getSignature(currentType)); >+ proposal.setDeclarationKey(currentType.computeUniqueKey()); >+ proposal.setSignature(getSignature(constructor)); >+ MethodBinding original = constructor.original(); >+ if(original != constructor) { >+ proposal.setOriginalSignature(getSignature(original)); >+ } >+ proposal.setKey(constructor.computeUniqueKey()); >+ proposal.setDeclarationPackageName(currentType.qualifiedPackageName()); >+ proposal.setDeclarationTypeName(currentType.qualifiedSourceName()); >+ proposal.setParameterPackageNames(parameterPackageNames); >+ proposal.setParameterTypeNames(parameterTypeNames); >+ //proposal.setPackageName(null); >+ //proposal.setTypeName(null); >+ proposal.setCompletion(completion); >+ proposal.setFlags(constructor.modifiers); >+ proposal.setReplaceRange(this.endPosition - this.offset, this.endPosition - this.offset); >+ proposal.setTokenRange(this.tokenEnd - this.offset, this.tokenEnd - this.offset); >+ proposal.setRelevance(relevance); >+ if(parameterNames != null) proposal.setParameterNames(parameterNames); >+ this.requestor.accept(proposal); >+ if(DEBUG) { >+ this.printDebug(proposal); >+ } >+ } >+ } else { >+ int relevance = computeBaseRelevance(); >+ relevance += computeRelevanceForResolution(); >+ relevance += computeRelevanceForInterestingProposal(); >+ relevance += computeRelevanceForRestrictions(IAccessRule.K_ACCESSIBLE); > >- if(proposeMethod) { >- findMethods( >- token, >- null, >- null, >- (ReferenceBinding) receiverType, >- scope, >- methodsFound, >- false, >- false, >- false, >- invocationSite, >- invocationScope, >- implicitCall, >- superCall, >- false, >- missingElements, >- missingElementsStarts, >- missingElementsEnds, >- missingElementsHaveProblems, >- castedReceiver, >- receiverStart, >- receiverEnd); >+ // Special case for completion in javadoc >+ if (this.assistNodeInJavadoc > 0) { >+ Expression receiver = null; >+ char[] selector = null; >+ if (invocationSite instanceof CompletionOnJavadocAllocationExpression) { >+ CompletionOnJavadocAllocationExpression alloc = (CompletionOnJavadocAllocationExpression) invocationSite; >+ receiver = alloc.type; >+ } else if (invocationSite instanceof CompletionOnJavadocFieldReference) { >+ CompletionOnJavadocFieldReference fieldRef = (CompletionOnJavadocFieldReference) invocationSite; >+ receiver = fieldRef.receiver; >+ } >+ if (receiver != null) { >+ StringBuffer javadocCompletion = new StringBuffer(); >+ if (receiver.isThis()) { >+ selector = (((JavadocImplicitTypeReference)receiver).token); >+ if ((this.assistNodeInJavadoc & CompletionOnJavadoc.TEXT) != 0) { >+ javadocCompletion.append('#'); >+ } >+ } else if (receiver instanceof JavadocSingleTypeReference) { >+ JavadocSingleTypeReference typeRef = (JavadocSingleTypeReference) receiver; >+ selector = typeRef.token; >+ if ((this.assistNodeInJavadoc & CompletionOnJavadoc.TEXT) != 0) { >+ javadocCompletion.append(typeRef.token); >+ javadocCompletion.append('#'); >+ } >+ } else if (receiver instanceof JavadocQualifiedTypeReference) { >+ JavadocQualifiedTypeReference typeRef = (JavadocQualifiedTypeReference) receiver; >+ selector = typeRef.tokens[typeRef.tokens.length-1]; >+ if ((this.assistNodeInJavadoc & CompletionOnJavadoc.TEXT) != 0) { >+ javadocCompletion.append(CharOperation.concatWith(typeRef.tokens, '.')); >+ javadocCompletion.append('#'); >+ } >+ } >+ // Append parameters types >+ javadocCompletion.append(selector); >+ javadocCompletion.append('('); >+ if (constructor.parameters != null) { >+ boolean isVarargs = constructor.isVarargs(); >+ for (int p=0, ln=constructor.parameters.length; p<ln; p++) { >+ if (p>0) javadocCompletion.append(", "); //$NON-NLS-1$ >+ TypeBinding argTypeBinding = constructor.parameters[p]; >+ if (isVarargs && p == ln - 1) { >+ createVargsType(argTypeBinding.erasure(), scope, javadocCompletion); >+ } else { >+ createType(argTypeBinding.erasure(), scope, javadocCompletion); >+ } >+ } >+ } >+ javadocCompletion.append(')'); >+ completion = javadocCompletion.toString().toCharArray(); >+ } >+ } >+ >+ // Create standard proposal >+ this.noProposal = false; >+ if(!this.requestor.isIgnored(CompletionProposal.METHOD_REF) && (this.assistNodeInJavadoc & CompletionOnJavadoc.ONLY_INLINE_TAG) == 0) { >+ InternalCompletionProposal proposal = createProposal(CompletionProposal.METHOD_REF, this.actualCompletionPosition); >+ proposal.setDeclarationSignature(getSignature(currentType)); >+ proposal.setSignature(getSignature(constructor)); >+ MethodBinding original = constructor.original(); >+ if(original != constructor) { >+ proposal.setOriginalSignature(getSignature(original)); >+ } >+ proposal.setDeclarationPackageName(currentType.qualifiedPackageName()); >+ proposal.setDeclarationTypeName(currentType.qualifiedSourceName()); >+ proposal.setParameterPackageNames(parameterPackageNames); >+ proposal.setParameterTypeNames(parameterTypeNames); >+ //proposal.setPackageName(null); >+ //proposal.setTypeName(null); >+ proposal.setName(currentType.sourceName()); >+ proposal.setIsContructor(true); >+ proposal.setCompletion(completion); >+ proposal.setFlags(constructor.modifiers); >+ int start = (this.assistNodeInJavadoc > 0) ? this.startPosition : this.endPosition; >+ proposal.setReplaceRange(start - this.offset, this.endPosition - this.offset); >+ proposal.setTokenRange(this.tokenStart - this.offset, this.tokenEnd - this.offset); >+ proposal.setRelevance(relevance); >+ if(parameterNames != null) proposal.setParameterNames(parameterNames); >+ this.requestor.accept(proposal); >+ if(DEBUG) { >+ this.printDebug(proposal); >+ } >+ } >+ if ((this.assistNodeInJavadoc & CompletionOnJavadoc.TEXT) != 0 && !this.requestor.isIgnored(CompletionProposal.JAVADOC_METHOD_REF)) { >+ char[] javadocCompletion = inlineTagCompletion(completion, JavadocTagConstants.TAG_LINK); >+ InternalCompletionProposal proposal = createProposal(CompletionProposal.JAVADOC_METHOD_REF, this.actualCompletionPosition); >+ proposal.setDeclarationSignature(getSignature(currentType)); >+ proposal.setSignature(getSignature(constructor)); >+ MethodBinding original = constructor.original(); >+ if(original != constructor) { >+ proposal.setOriginalSignature(getSignature(original)); >+ } >+ proposal.setDeclarationPackageName(currentType.qualifiedPackageName()); >+ proposal.setDeclarationTypeName(currentType.qualifiedSourceName()); >+ proposal.setParameterPackageNames(parameterPackageNames); >+ proposal.setParameterTypeNames(parameterTypeNames); >+ //proposal.setPackageName(null); >+ //proposal.setTypeName(null); >+ proposal.setName(currentType.sourceName()); >+ proposal.setIsContructor(true); >+ proposal.setCompletion(javadocCompletion); >+ proposal.setFlags(constructor.modifiers); >+ int start = (this.assistNodeInJavadoc & CompletionOnJavadoc.REPLACE_TAG) != 0 ? this.javadocTagPosition : this.startPosition; >+ proposal.setReplaceRange(start - this.offset, this.endPosition - this.offset); >+ proposal.setTokenRange(this.tokenStart - this.offset, this.tokenEnd - this.offset); >+ proposal.setRelevance(relevance+R_INLINE_TAG); >+ if(parameterNames != null) proposal.setParameterNames(parameterNames); >+ this.requestor.accept(proposal); >+ if(DEBUG) { >+ this.printDebug(proposal); >+ } >+ } >+ } >+ } >+ } > } > } >+ private char[][] findEnclosingTypeNames(Scope scope){ >+ char[][] excludedNames = new char[10][]; >+ int excludedNameCount = 0; > >- private void findFieldsAndMethodsFromFavorites( >- char[] token, >- Scope scope, >- InvocationSite invocationSite, >+ Scope currentScope = scope; >+ while(currentScope != null) { >+ switch (currentScope.kind) { >+ case Scope.CLASS_SCOPE : >+ ClassScope classScope = (ClassScope) currentScope; >+ >+ TypeDeclaration typeDeclaration = classScope.referenceContext; >+ >+ if(excludedNameCount == excludedNames.length) { >+ System.arraycopy(excludedNames, 0, excludedNames = new char[excludedNameCount * 2][], 0, excludedNameCount); >+ } >+ excludedNames[excludedNameCount++] = typeDeclaration.name; >+ >+ TypeParameter[] classTypeParameters = typeDeclaration.typeParameters; >+ if(classTypeParameters != null) { >+ for (int i = 0; i < classTypeParameters.length; i++) { >+ TypeParameter typeParameter = classTypeParameters[i]; >+ if(excludedNameCount == excludedNames.length) { >+ System.arraycopy(excludedNames, 0, excludedNames = new char[excludedNameCount * 2][], 0, excludedNameCount); >+ } >+ excludedNames[excludedNameCount++] = typeParameter.name; >+ } >+ } >+ break; >+ case Scope.METHOD_SCOPE : >+ MethodScope methodScope = (MethodScope) currentScope; >+ if(methodScope.referenceContext instanceof AbstractMethodDeclaration) { >+ TypeParameter[] methodTypeParameters = ((AbstractMethodDeclaration)methodScope.referenceContext).typeParameters(); >+ if(methodTypeParameters != null) { >+ for (int i = 0; i < methodTypeParameters.length; i++) { >+ TypeParameter typeParameter = methodTypeParameters[i]; >+ if(excludedNameCount == excludedNames.length) { >+ System.arraycopy(excludedNames, 0, excludedNames = new char[excludedNameCount * 2][], 0, excludedNameCount); >+ } >+ excludedNames[excludedNameCount++] = typeParameter.name; >+ } >+ } >+ } >+ break; >+ } >+ >+ currentScope = currentScope.parent; >+ } >+ >+ if(excludedNameCount == 0) { >+ return CharOperation.NO_CHAR_CHAR; >+ } >+ System.arraycopy(excludedNames, 0, excludedNames = new char[excludedNameCount][], 0, excludedNameCount); >+ return excludedNames; >+ } >+ private void findEnumConstants( >+ char[] enumConstantName, >+ ReferenceBinding enumType, > Scope invocationScope, >- ObjectVector localsFound, > ObjectVector fieldsFound, >- ObjectVector methodsFound) { >+ char[][] alreadyUsedConstants, >+ int alreadyUsedConstantCount, >+ boolean needQualification) { > >- ObjectVector methodsFoundFromFavorites = new ObjectVector(); >+ FieldBinding[] fields = enumType.fields(); > >- ImportBinding[] favoriteBindings = getFavoriteReferenceBindings(invocationScope); >+ int enumConstantLength = enumConstantName.length; >+ next : for (int f = fields.length; --f >= 0;) { >+ FieldBinding field = fields[f]; > >- if (favoriteBindings != null && favoriteBindings.length > 0) { >- for (int i = 0; i < favoriteBindings.length; i++) { >- ImportBinding favoriteBinding = favoriteBindings[i]; >- switch (favoriteBinding.resolvedImport.kind()) { >- case Binding.FIELD: >- FieldBinding fieldBinding = (FieldBinding) favoriteBinding.resolvedImport; >- findFieldsFromFavorites( >- token, >- new FieldBinding[]{fieldBinding}, >- scope, >- fieldsFound, >- localsFound, >- fieldBinding.declaringClass, >- invocationSite, >- invocationScope); >- break; >- case Binding.METHOD: >- MethodBinding methodBinding = (MethodBinding) favoriteBinding.resolvedImport; >- MethodBinding[] methods = methodBinding.declaringClass.availableMethods(); >- long range; >- if ((range = ReferenceBinding.binarySearch(methodBinding.selector, methods)) >= 0) { >- int start = (int) range, end = (int) (range >> 32); >- int length = end - start + 1; >- System.arraycopy(methods, start, methods = new MethodBinding[length], 0, length); >- } else { >- methods = Binding.NO_METHODS; >- } >- findLocalMethodsFromFavorites( >- token, >- methods, >- scope, >- methodsFound, >- methodsFoundFromFavorites, >- methodBinding.declaringClass, >- invocationSite, >- invocationScope); >- break; >- case Binding.TYPE: >- ReferenceBinding referenceBinding = (ReferenceBinding) favoriteBinding.resolvedImport; >- if(favoriteBinding.onDemand) { >- findFieldsFromFavorites( >- token, >- referenceBinding.availableFields(), >- scope, >- fieldsFound, >- localsFound, >- referenceBinding, >- invocationSite, >- invocationScope); >+ if (field.isSynthetic()) continue next; > >- findLocalMethodsFromFavorites( >- token, >- referenceBinding.availableMethods(), >- scope, >- methodsFound, >- methodsFoundFromFavorites, >- referenceBinding, >- invocationSite, >- invocationScope); >- } >- break; >- } >+ if ((field.modifiers & Flags.AccEnum) == 0) continue next; >+ >+ if (enumConstantLength > field.name.length) continue next; >+ >+ if (!CharOperation.prefixEquals(enumConstantName, field.name, false /* ignore case */) >+ && !(this.options.camelCaseMatch && CharOperation.camelCaseMatch(enumConstantName, field.name))) continue next; >+ >+ char[] fieldName = field.name; >+ >+ for (int i = 0; i < alreadyUsedConstantCount; i++) { >+ if(CharOperation.equals(alreadyUsedConstants[i], fieldName)) continue next; > } >- } > >- methodsFound.addAll(methodsFoundFromFavorites); >- } >+ int relevance = computeBaseRelevance(); >+ relevance += computeRelevanceForResolution(); >+ relevance += computeRelevanceForInterestingProposal(field); >+ relevance += computeRelevanceForCaseMatching(enumConstantName, field.name); >+ relevance += computeRelevanceForExpectingType(field.type); >+ relevance += computeRelevanceForEnumConstant(field.type); >+ relevance += computeRelevanceForQualification(needQualification); >+ relevance += computeRelevanceForRestrictions(IAccessRule.K_ACCESSIBLE); > >- private boolean findFieldsAndMethodsFromMissingFieldType( >- char[] token, >- Scope scope, >- InvocationSite invocationSite, >- boolean insideTypeAnnotation) { >+ this.noProposal = false; >+ if (!needQualification) { >+ char[] completion = fieldName; > >- boolean foundSomeFields = false; >+ if(!this.requestor.isIgnored(CompletionProposal.FIELD_REF)) { >+ InternalCompletionProposal proposal = createProposal(CompletionProposal.FIELD_REF, this.actualCompletionPosition); >+ proposal.setDeclarationSignature(getSignature(field.declaringClass)); >+ proposal.setSignature(getSignature(field.type)); >+ proposal.setDeclarationPackageName(field.declaringClass.qualifiedPackageName()); >+ proposal.setDeclarationTypeName(field.declaringClass.qualifiedSourceName()); >+ proposal.setPackageName(field.type.qualifiedPackageName()); >+ proposal.setTypeName(field.type.qualifiedSourceName()); >+ proposal.setName(field.name); >+ proposal.setCompletion(completion); >+ proposal.setFlags(field.modifiers); >+ proposal.setReplaceRange(this.startPosition - this.offset, this.endPosition - this.offset); >+ proposal.setTokenRange(this.tokenStart - this.offset, this.tokenEnd - this.offset); >+ proposal.setRelevance(relevance); >+ this.requestor.accept(proposal); >+ if(DEBUG) { >+ this.printDebug(proposal); >+ } >+ } > >- boolean staticsOnly = false; >- Scope currentScope = scope; >+ } else { >+ TypeBinding visibleType = invocationScope.getType(field.type.sourceName()); >+ boolean needImport = visibleType == null || !visibleType.isValidBinding(); > >- done : while (true) { // done when a COMPILATION_UNIT_SCOPE is found >+ char[] completion = CharOperation.concat(field.type.sourceName(), field.name, '.'); > >- switch (currentScope.kind) { >+ if (!needImport) { >+ if(!this.requestor.isIgnored(CompletionProposal.FIELD_REF)) { >+ InternalCompletionProposal proposal = createProposal(CompletionProposal.FIELD_REF, this.actualCompletionPosition); >+ proposal.setDeclarationSignature(getSignature(field.declaringClass)); >+ proposal.setSignature(getSignature(field.type)); >+ proposal.setDeclarationPackageName(field.declaringClass.qualifiedPackageName()); >+ proposal.setDeclarationTypeName(field.declaringClass.qualifiedSourceName()); >+ proposal.setPackageName(field.type.qualifiedPackageName()); >+ proposal.setTypeName(field.type.qualifiedSourceName()); >+ proposal.setName(field.name); >+ proposal.setCompletion(completion); >+ proposal.setFlags(field.modifiers); >+ proposal.setReplaceRange(this.startPosition - this.offset, this.endPosition - this.offset); >+ proposal.setTokenRange(this.tokenStart - this.offset, this.tokenEnd - this.offset); >+ proposal.setRelevance(relevance); >+ this.requestor.accept(proposal); >+ if(DEBUG) { >+ this.printDebug(proposal); >+ } >+ } >+ } else { >+ if (!this.isIgnored(CompletionProposal.FIELD_REF, CompletionProposal.TYPE_IMPORT)) { >+ CompilationUnitDeclaration cu = this.unitScope.referenceContext; >+ int importStart = cu.types[0].declarationSourceStart; >+ int importEnd = importStart; > >- case Scope.METHOD_SCOPE : >- // handle the error case inside an explicit constructor call (see MethodScope>>findField) >- MethodScope methodScope = (MethodScope) currentScope; >- staticsOnly |= methodScope.isStatic | methodScope.isConstructorCall; >- break; >- case Scope.CLASS_SCOPE : >- ClassScope classScope = (ClassScope) currentScope; >- SourceTypeBinding enclosingType = classScope.referenceContext.binding; >- if(!insideTypeAnnotation) { >+ ReferenceBinding fieldType = (ReferenceBinding)field.type; > >- FieldDeclaration[] fields = classScope.referenceContext.fields; >+ InternalCompletionProposal proposal = createProposal(CompletionProposal.FIELD_REF, this.actualCompletionPosition); >+ proposal.setDeclarationSignature(getSignature(field.declaringClass)); >+ proposal.setSignature(getSignature(field.type)); >+ proposal.setDeclarationPackageName(field.declaringClass.qualifiedPackageName()); >+ proposal.setDeclarationTypeName(field.declaringClass.qualifiedSourceName()); >+ proposal.setPackageName(field.type.qualifiedPackageName()); >+ proposal.setTypeName(field.type.qualifiedSourceName()); >+ proposal.setName(field.name); >+ proposal.setCompletion(completion); >+ proposal.setFlags(field.modifiers); >+ proposal.setReplaceRange(this.startPosition - this.offset, this.endPosition - this.offset); >+ proposal.setTokenRange(this.tokenStart - this.offset, this.tokenEnd - this.offset); >+ proposal.setRelevance(relevance); > >- int fieldsCount = fields == null ? 0 : fields.length; >- for (int i = 0; i < fieldsCount; i++) { >- FieldDeclaration fieldDeclaration = fields[i]; >- if (CharOperation.equals(fieldDeclaration.name, token)) { >- FieldBinding fieldBinding = fieldDeclaration.binding; >- if (fieldBinding == null || fieldBinding.type == null || (fieldBinding.type.tagBits & TagBits.HasMissingType) != 0) { >- foundSomeFields = true; >- findFieldsAndMethodsFromMissingType( >- fieldDeclaration.type, >- currentScope, >- invocationSite, >- scope); >- } >- break done; >- } >+ char[] typeImportCompletion = createImportCharArray(CharOperation.concatWith(fieldType.compoundName, '.'), false, false); >+ >+ InternalCompletionProposal typeImportProposal = createProposal(CompletionProposal.TYPE_IMPORT, this.actualCompletionPosition); >+ typeImportProposal.nameLookup = this.nameEnvironment.nameLookup; >+ typeImportProposal.completionEngine = this; >+ char[] packageName = fieldType.qualifiedPackageName(); >+ typeImportProposal.setDeclarationSignature(packageName); >+ typeImportProposal.setSignature(getSignature(fieldType)); >+ typeImportProposal.setPackageName(packageName); >+ typeImportProposal.setTypeName(fieldType.qualifiedSourceName()); >+ typeImportProposal.setCompletion(typeImportCompletion); >+ typeImportProposal.setFlags(fieldType.modifiers); >+ typeImportProposal.setAdditionalFlags(CompletionFlags.Default); >+ typeImportProposal.setReplaceRange(importStart - this.offset, importEnd - this.offset); >+ typeImportProposal.setTokenRange(importStart - this.offset, importEnd - this.offset); >+ typeImportProposal.setRelevance(relevance); >+ >+ proposal.setRequiredProposals(new CompletionProposal[]{typeImportProposal}); >+ >+ this.requestor.accept(proposal); >+ if(DEBUG) { >+ this.printDebug(proposal); > } > } >- staticsOnly |= enclosingType.isStatic(); >- insideTypeAnnotation = false; >- break; >- case Scope.COMPILATION_UNIT_SCOPE : >- break done; >+ } > } >- currentScope = currentScope.parent; > } >- return foundSomeFields; > } >+ private void findEnumConstantsFromExpectedTypes( >+ char[] token, >+ Scope invocationScope, >+ ObjectVector fieldsFound) { >+ int length = this.expectedTypesPtr + 1; >+ for (int i = 0; i < length; i++) { >+ if (this.expectedTypes[i].isEnum()) { >+ findEnumConstants( >+ token, >+ (ReferenceBinding)this.expectedTypes[i], >+ invocationScope, >+ fieldsFound, >+ CharOperation.NO_CHAR_CHAR, >+ 0, >+ true); >+ } >+ } > >- private void findFieldsAndMethodsFromMissingReturnType( >- char[] token, >- TypeBinding[] arguments, >- Scope scope, >- InvocationSite invocationSite, >- boolean insideTypeAnnotation) { >- >- boolean staticsOnly = false; >- Scope currentScope = scope; >+ } >+ private void findEnumConstantsFromSwithStatement(char[] enumConstantName, SwitchStatement switchStatement) { >+ TypeBinding expressionType = switchStatement.expression.resolvedType; >+ if(expressionType != null && expressionType.isEnum()) { >+ ReferenceBinding enumType = (ReferenceBinding) expressionType; > >- done : while (true) { // done when a COMPILATION_UNIT_SCOPE is found >+ CaseStatement[] cases = switchStatement.cases; > >- switch (currentScope.kind) { >+ char[][] alreadyUsedConstants = new char[switchStatement.caseCount][]; >+ int alreadyUsedConstantCount = 0; >+ for (int i = 0; i < switchStatement.caseCount; i++) { >+ Expression caseExpression = cases[i].constantExpression; >+ if((caseExpression instanceof SingleNameReference) >+ && (caseExpression.resolvedType != null && caseExpression.resolvedType.isEnum())) { >+ alreadyUsedConstants[alreadyUsedConstantCount++] = ((SingleNameReference)cases[i].constantExpression).token; >+ } >+ } > >- case Scope.METHOD_SCOPE : >- // handle the error case inside an explicit constructor call (see MethodScope>>findField) >- MethodScope methodScope = (MethodScope) currentScope; >- staticsOnly |= methodScope.isStatic | methodScope.isConstructorCall; >- break; >- case Scope.CLASS_SCOPE : >- ClassScope classScope = (ClassScope) currentScope; >- SourceTypeBinding enclosingType = classScope.referenceContext.binding; >- if(!insideTypeAnnotation) { >+ findEnumConstants( >+ enumConstantName, >+ enumType, >+ null /* doesn't need invocation scope */, >+ new ObjectVector(), >+ alreadyUsedConstants, >+ alreadyUsedConstantCount, >+ false); >+ } >+ } >+ private void findExceptionFromTryStatement( >+ char[] typeName, >+ ReferenceBinding exceptionType, >+ ReferenceBinding receiverType, >+ SourceTypeBinding invocationType, >+ BlockScope scope, >+ ObjectVector typesFound, >+ boolean searchSuperClasses) { > >- AbstractMethodDeclaration[] methods = classScope.referenceContext.methods; >+ if (searchSuperClasses) { >+ ReferenceBinding javaLangThrowable = scope.getJavaLangThrowable(); >+ if (exceptionType != javaLangThrowable) { >+ ReferenceBinding superClass = exceptionType.superclass(); >+ while(superClass != null && superClass != javaLangThrowable) { >+ findExceptionFromTryStatement(typeName, superClass, receiverType, invocationType, scope, typesFound, false); >+ superClass = superClass.superclass(); >+ } >+ } >+ } > >- int methodsCount = methods == null ? 0 : methods.length; >- for (int i = 0; i < methodsCount; i++) { >- AbstractMethodDeclaration methodDeclaration = methods[i]; >- if (methodDeclaration instanceof MethodDeclaration && >- CharOperation.equals(methodDeclaration.selector, token)) { >- MethodDeclaration method = (MethodDeclaration) methodDeclaration; >- MethodBinding methodBinding = method.binding; >- if (methodBinding == null || methodBinding.returnType == null || (methodBinding.returnType.tagBits & TagBits.HasMissingType) != 0) { >- Argument[] parameters = method.arguments; >- int parametersLength = parameters == null ? 0 : parameters.length; >- int argumentsLength = arguments == null ? 0 : arguments.length; >+ if (typeName.length > exceptionType.sourceName.length) >+ return; > >- if (parametersLength == 0) { >- if (argumentsLength == 0) { >- findFieldsAndMethodsFromMissingType( >- method.returnType, >- currentScope, >- invocationSite, >- scope); >- break done; >- } >- } else { >- TypeBinding[] parametersBindings; >- if (methodBinding == null) { // since no binding, extra types from type references >- parametersBindings = new TypeBinding[parametersLength]; >- for (int j = 0; j < parametersLength; j++) { >- TypeBinding parameterType = parameters[j].type.resolvedType; >- if (!parameterType.isValidBinding() && parameterType.closestMatch() != null) { >- parameterType = parameterType.closestMatch(); >- } >- parametersBindings[j] = parameterType; >- } >- } else { >- parametersBindings = methodBinding.parameters; >- } >- if(areParametersCompatibleWith(parametersBindings, arguments, parameters[parametersLength - 1].isVarArgs())) { >- findFieldsAndMethodsFromMissingType( >- method.returnType, >- currentScope, >- invocationSite, >- scope); >- break done; >- } >- } >- } >+ if (!CharOperation.prefixEquals(typeName, exceptionType.sourceName, false/* ignore case */) >+ && !(this.options.camelCaseMatch && CharOperation.camelCaseMatch(typeName, exceptionType.sourceName))) >+ return; > >- } >- } >- } >- staticsOnly |= enclosingType.isStatic(); >- insideTypeAnnotation = false; >- break; >- case Scope.COMPILATION_UNIT_SCOPE : >- break done; >+ if (this.options.checkDeprecation && >+ exceptionType.isViewedAsDeprecated() && >+ !scope.isDefinedInSameUnit(exceptionType)) >+ return; >+ >+ if (this.options.checkVisibility) { >+ if (invocationType != null) { >+ if (receiverType != null) { >+ if (!exceptionType.canBeSeenBy(receiverType, invocationType)) return; >+ } else { >+ if (!exceptionType.canBeSeenBy(exceptionType, invocationType)) return; >+ } >+ } else if(!exceptionType.canBeSeenBy(this.unitScope.fPackage)) { >+ return; > } >- currentScope = currentScope.parent; > } >- } >- >- private void findFieldsAndMethodsFromMissingType( >- TypeReference typeRef, >- final Scope scope, >- final InvocationSite invocationSite, >- final Scope invocationScope) { >- MissingTypesGuesser missingTypesConverter = new MissingTypesGuesser(this); >- MissingTypesGuesser.GuessedTypeRequestor substitutionRequestor = >- new MissingTypesGuesser.GuessedTypeRequestor() { >- public void accept( >- TypeBinding guessedType, >- Binding[] missingElements, >- int[] missingElementsStarts, >- int[] missingElementsEnds, >- boolean hasProblems) { >- findFieldsAndMethods( >- CompletionEngine.this.completionToken, >- guessedType, >- scope, >- new ObjectVector(), >- new ObjectVector(), >- invocationSite, >- invocationScope, >- false, >- false, >- missingElements, >- missingElementsStarts, >- missingElementsEnds, >- hasProblems, >- null, >- -1, >- -1); > >- } >- }; >- missingTypesConverter.guess(typeRef, scope, substitutionRequestor); >- } >+ for (int j = typesFound.size; --j >= 0;) { >+ ReferenceBinding otherType = (ReferenceBinding) typesFound.elementAt(j); > >- private void findFieldsFromFavorites( >- char[] fieldName, >- FieldBinding[] fields, >- Scope scope, >- ObjectVector fieldsFound, >- ObjectVector localsFound, >- ReferenceBinding receiverType, >- InvocationSite invocationSite, >- Scope invocationScope) { >+ if (exceptionType == otherType) >+ return; > >- char[] typeName = CharOperation.concatWith(receiverType.compoundName, '.'); >+ if (CharOperation.equals(exceptionType.sourceName, otherType.sourceName, true)) { > >- int fieldLength = fieldName.length; >- next : for (int f = fields.length; --f >= 0;) { >- FieldBinding field = fields[f]; >+ if (exceptionType.enclosingType().isSuperclassOf(otherType.enclosingType())) >+ return; > >- if (field.isSynthetic()) continue next; >+ if (otherType.enclosingType().isInterface()) >+ if (exceptionType.enclosingType() >+ .implementsInterface(otherType.enclosingType(), true)) >+ return; > >- // only static fields must be proposed >- if (!field.isStatic()) continue next; >+ if (exceptionType.enclosingType().isInterface()) >+ if (otherType.enclosingType() >+ .implementsInterface(exceptionType.enclosingType(), true)) >+ return; >+ } >+ } > >- if (fieldLength > field.name.length) continue next; >+ typesFound.add(exceptionType); > >- if (!CharOperation.prefixEquals(fieldName, field.name, false /* ignore case */) >- && !(this.options.camelCaseMatch && CharOperation.camelCaseMatch(fieldName, field.name))) continue next; >+ char[] completionName = exceptionType.sourceName(); > >- if (this.options.checkDeprecation && >- field.isViewedAsDeprecated() && >- !scope.isDefinedInSameUnit(field.declaringClass)) >- continue next; >+ boolean isQualified = false; > >- if (this.options.checkVisibility >- && !field.canBeSeenBy(receiverType, invocationSite, scope)) continue next; >+ if(!this.insideQualifiedReference) { >+ isQualified = true; > >- for (int i = fieldsFound.size; --i >= 0;) { >- Object[] other = (Object[])fieldsFound.elementAt(i); >- FieldBinding otherField = (FieldBinding) other[0]; >+ char[] memberPackageName = exceptionType.qualifiedPackageName(); >+ char[] memberTypeName = exceptionType.sourceName(); >+ char[] memberEnclosingTypeNames = null; > >- if (field == otherField) continue next; >+ ReferenceBinding enclosingType = exceptionType.enclosingType(); >+ if (enclosingType != null) { >+ memberEnclosingTypeNames = exceptionType.enclosingType().qualifiedSourceName(); > } > >- fieldsFound.add(new Object[]{field, receiverType}); >- >- int relevance = computeBaseRelevance(); >- relevance += computeRelevanceForResolution(); >- relevance += computeRelevanceForInterestingProposal(field); >- if (fieldName != null) relevance += computeRelevanceForCaseMatching(fieldName, field.name); >- relevance += computeRelevanceForExpectingType(field.type); >- relevance += computeRelevanceForEnumConstant(field.type); >- relevance += computeRelevanceForStatic(true, true); >- relevance += computeRelevanceForRestrictions(IAccessRule.K_ACCESSIBLE); >+ Scope currentScope = scope; >+ done : while (currentScope != null) { // done when a COMPILATION_UNIT_SCOPE is found > >- CompilationUnitDeclaration cu = this.unitScope.referenceContext; >- int importStart = cu.types[0].declarationSourceStart; >- int importEnd = importStart; >+ switch (currentScope.kind) { > >- this.noProposal = false; >+ case Scope.METHOD_SCOPE : >+ case Scope.BLOCK_SCOPE : >+ BlockScope blockScope = (BlockScope) currentScope; > >- if (this.compilerOptions.complianceLevel < ClassFileConstants.JDK1_5 || >- !this.options.suggestStaticImport) { >- if (!this.isIgnored(CompletionProposal.FIELD_REF, CompletionProposal.TYPE_IMPORT)) { >- char[] completion = CharOperation.concat(receiverType.sourceName, field.name, '.'); >+ for (int j = 0, length = blockScope.subscopeCount; j < length; j++) { > >- InternalCompletionProposal proposal = createProposal(CompletionProposal.FIELD_REF, this.actualCompletionPosition); >- proposal.setDeclarationSignature(getSignature(field.declaringClass)); >- proposal.setSignature(getSignature(field.type)); >- proposal.setDeclarationPackageName(field.declaringClass.qualifiedPackageName()); >- proposal.setDeclarationTypeName(field.declaringClass.qualifiedSourceName()); >- proposal.setPackageName(field.type.qualifiedPackageName()); >- proposal.setTypeName(field.type.qualifiedSourceName()); >- proposal.setName(field.name); >- proposal.setCompletion(completion); >- proposal.setFlags(field.modifiers); >- proposal.setReplaceRange(this.startPosition - this.offset, this.endPosition - this.offset); >- proposal.setTokenRange(this.tokenStart - this.offset, this.tokenEnd - this.offset); >- proposal.setRelevance(relevance); >+ if (blockScope.subscopes[j] instanceof ClassScope) { >+ SourceTypeBinding localType = >+ ((ClassScope) blockScope.subscopes[j]).referenceContext.binding; > >- char[] typeImportCompletion = createImportCharArray(typeName, false, false); >+ if (localType == exceptionType) { >+ isQualified = false; >+ break done; >+ } >+ } >+ } >+ break; > >- InternalCompletionProposal typeImportProposal = createProposal(CompletionProposal.TYPE_IMPORT, this.actualCompletionPosition); >- typeImportProposal.nameLookup = this.nameEnvironment.nameLookup; >- typeImportProposal.completionEngine = this; >- char[] packageName = receiverType.qualifiedPackageName(); >- typeImportProposal.setDeclarationSignature(packageName); >- typeImportProposal.setSignature(getSignature(receiverType)); >- typeImportProposal.setPackageName(packageName); >- typeImportProposal.setTypeName(receiverType.qualifiedSourceName()); >- typeImportProposal.setCompletion(typeImportCompletion); >- typeImportProposal.setFlags(receiverType.modifiers); >- typeImportProposal.setAdditionalFlags(CompletionFlags.Default); >- typeImportProposal.setReplaceRange(importStart - this.offset, importEnd - this.offset); >- typeImportProposal.setTokenRange(importStart - this.offset, importEnd - this.offset); >- typeImportProposal.setRelevance(relevance); >- >- proposal.setRequiredProposals(new CompletionProposal[]{typeImportProposal}); >- >- this.requestor.accept(proposal); >- if(DEBUG) { >- this.printDebug(proposal); >- } >- } >- } else { >- if (!this.isIgnored(CompletionProposal.FIELD_REF, CompletionProposal.FIELD_IMPORT)) { >- char[] completion = field.name; >- >- InternalCompletionProposal proposal = createProposal(CompletionProposal.FIELD_REF, this.actualCompletionPosition); >- proposal.setDeclarationSignature(getSignature(field.declaringClass)); >- proposal.setSignature(getSignature(field.type)); >- proposal.setDeclarationPackageName(field.declaringClass.qualifiedPackageName()); >- proposal.setDeclarationTypeName(field.declaringClass.qualifiedSourceName()); >- proposal.setPackageName(field.type.qualifiedPackageName()); >- proposal.setTypeName(field.type.qualifiedSourceName()); >- proposal.setName(field.name); >- proposal.setCompletion(completion); >- proposal.setFlags(field.modifiers); >- proposal.setReplaceRange(this.startPosition - this.offset, this.endPosition - this.offset); >- proposal.setTokenRange(this.tokenStart - this.offset, this.tokenEnd - this.offset); >- proposal.setRelevance(relevance); >- >- char[] fieldImportCompletion = createImportCharArray(CharOperation.concat(typeName, field.name, '.'), true, false); >+ case Scope.CLASS_SCOPE : >+ SourceTypeBinding type = ((ClassScope)currentScope).referenceContext.binding; >+ ReferenceBinding[] memberTypes = type.memberTypes(); >+ if (memberTypes != null) { >+ for (int j = 0; j < memberTypes.length; j++) { >+ if (memberTypes[j] == exceptionType) { >+ isQualified = false; >+ break done; >+ } >+ } >+ } > >- InternalCompletionProposal fieldImportProposal = createProposal(CompletionProposal.FIELD_IMPORT, this.actualCompletionPosition); >- fieldImportProposal.setDeclarationSignature(getSignature(field.declaringClass)); >- fieldImportProposal.setSignature(getSignature(field.type)); >- fieldImportProposal.setDeclarationPackageName(field.declaringClass.qualifiedPackageName()); >- fieldImportProposal.setDeclarationTypeName(field.declaringClass.qualifiedSourceName()); >- fieldImportProposal.setPackageName(field.type.qualifiedPackageName()); >- fieldImportProposal.setTypeName(field.type.qualifiedSourceName()); >- fieldImportProposal.setName(field.name); >- fieldImportProposal.setCompletion(fieldImportCompletion); >- fieldImportProposal.setFlags(field.modifiers); >- fieldImportProposal.setAdditionalFlags(CompletionFlags.StaticImport); >- fieldImportProposal.setReplaceRange(importStart - this.offset, importEnd - this.offset); >- fieldImportProposal.setTokenRange(importStart - this.offset, importEnd - this.offset); >- fieldImportProposal.setRelevance(relevance); > >- proposal.setRequiredProposals(new CompletionProposal[]{fieldImportProposal}); >+ break; > >- this.requestor.accept(proposal); >- if(DEBUG) { >- this.printDebug(proposal); >- } >+ case Scope.COMPILATION_UNIT_SCOPE : >+ SourceTypeBinding[] types = ((CompilationUnitScope)currentScope).topLevelTypes; >+ if (types != null) { >+ for (int j = 0; j < types.length; j++) { >+ if (types[j] == exceptionType) { >+ isQualified = false; >+ break done; >+ } >+ } >+ } >+ break done; > } >+ currentScope = currentScope.parent; > } >- } >- } >- >- private void findImports(CompletionOnImportReference importReference, boolean findMembers) { >- char[][] tokens = importReference.tokens; >- >- char[] importName = CharOperation.concatWith(tokens, '.'); > >- if (importName.length == 0) >- return; >- >- char[] lastToken = tokens[tokens.length - 1]; >- if(lastToken != null && lastToken.length == 0) >- importName = CharOperation.concat(importName, new char[]{'.'}); >- >- this.resolvingImports = true; >- this.resolvingStaticImports = importReference.isStatic(); >+ if (isQualified && mustQualifyType(memberPackageName, memberTypeName, memberEnclosingTypeNames, exceptionType.modifiers)) { >+ if (memberPackageName == null || memberPackageName.length == 0) >+ if (this.unitScope != null && this.unitScope.fPackage.compoundName != CharOperation.NO_CHAR_CHAR) >+ return; // ignore types from the default package from outside it >+ } else { >+ isQualified = false; >+ } > >- this.completionToken = lastToken; >- this.qualifiedCompletionToken = importName; >+ if (isQualified) { >+ completionName = >+ CharOperation.concat( >+ memberPackageName, >+ CharOperation.concat( >+ memberEnclosingTypeNames, >+ memberTypeName, >+ '.'), >+ '.'); >+ } >+ } > >- // want to replace the existing .*; >- if(!this.requestor.isIgnored(CompletionProposal.PACKAGE_REF)) { >- int oldStart = this.startPosition; >- int oldEnd = this.endPosition; >- setSourceRange( >- importReference.sourceStart, >- importReference.declarationSourceEnd); >- this.nameEnvironment.findPackages(importName, this); >- setSourceRange( >- oldStart, >- oldEnd - 1, >- false); >+ int relevance = computeBaseRelevance(); >+ relevance += computeRelevanceForResolution(); >+ relevance += computeRelevanceForInterestingProposal(); >+ relevance += computeRelevanceForCaseMatching(typeName, exceptionType.sourceName); >+ relevance += computeRelevanceForExpectingType(exceptionType); >+ relevance += computeRelevanceForRestrictions(IAccessRule.K_ACCESSIBLE); >+ if(!this.insideQualifiedReference) { >+ relevance += computeRelevanceForQualification(isQualified); > } >+ relevance += computeRelevanceForClass(); >+ relevance += computeRelevanceForException(); >+ >+ this.noProposal = false; > if(!this.requestor.isIgnored(CompletionProposal.TYPE_REF)) { >- this.nameEnvironment.findTypes( >- importName, >- findMembers, >- this.options.camelCaseMatch, >- IJavaSearchConstants.TYPE, >- this); >- acceptTypes(null); >+ createTypeProposal( >+ exceptionType, >+ exceptionType.qualifiedSourceName(), >+ IAccessRule.K_ACCESSIBLE, >+ completionName, >+ relevance, >+ null, >+ null, >+ null, >+ false); > } > } >+ private void findExceptionFromTryStatement( >+ char[] typeName, >+ ReferenceBinding receiverType, >+ SourceTypeBinding invocationType, >+ BlockScope scope, >+ ObjectVector typesFound) { > >- private void findImportsOfMemberTypes(char[] typeName, ReferenceBinding ref, boolean onlyStatic) { >- ReferenceBinding[] memberTypes = ref.memberTypes(); >- >- int typeLength = typeName.length; >- next : for (int m = memberTypes.length; --m >= 0;) { >- ReferenceBinding memberType = memberTypes[m]; >- // if (!wantClasses && memberType.isClass()) continue next; >- // if (!wantInterfaces && memberType.isInterface()) continue next; >- >- if (onlyStatic && !memberType.isStatic()) >- continue next; >- >- if (typeLength > memberType.sourceName.length) >- continue next; >- >- if (!CharOperation.prefixEquals(typeName, memberType.sourceName, false/* ignore case */) >- && !(this.options.camelCaseMatch && CharOperation.camelCaseMatch(typeName, memberType.sourceName))) >- continue next; >- >- if (this.options.checkDeprecation && memberType.isViewedAsDeprecated()) continue next; >- >- if (this.options.checkVisibility >- && !memberType.canBeSeenBy(this.unitScope.fPackage)) >- continue next; >- >- char[] completionName = CharOperation.concat(memberType.sourceName, SEMICOLON); >- >- int relevance = computeBaseRelevance(); >- relevance += computeRelevanceForResolution(); >- relevance += computeRelevanceForInterestingProposal(); >- relevance += computeRelevanceForCaseMatching(typeName, memberType.sourceName); >- relevance += computeRelevanceForRestrictions(IAccessRule.K_ACCESSIBLE); >+ for (int i = 0; i <= this.expectedTypesPtr; i++) { >+ ReferenceBinding exceptionType = (ReferenceBinding)this.expectedTypes[i]; > >- if (memberType.isClass()) { >- relevance += computeRelevanceForClass(); >- } else if(memberType.isEnum()) { >- relevance += computeRelevanceForEnum(); >- } else if (memberType.isInterface()) { >- relevance += computeRelevanceForInterface(); >- } >- this.noProposal = false; >- if(!this.requestor.isIgnored(CompletionProposal.TYPE_REF)) { >- createTypeProposal( >- memberType, >- memberType.qualifiedSourceName(), >- IAccessRule.K_ACCESSIBLE, >- completionName, >- relevance, >- null, >- null, >- null, >- false); >- } >+ findExceptionFromTryStatement(typeName, exceptionType, receiverType, invocationType, scope, typesFound, true); > } > } >+ private void findExplicitConstructors( >+ char[] name, >+ ReferenceBinding currentType, >+ MethodScope scope, >+ InvocationSite invocationSite) { > >- private void findImportsOfStaticFields(char[] fieldName, ReferenceBinding ref) { >- FieldBinding[] fields = ref.availableFields(); >+ ConstructorDeclaration constructorDeclaration = (ConstructorDeclaration)scope.referenceContext; >+ MethodBinding enclosingConstructor = constructorDeclaration.binding; > >- int fieldLength = fieldName.length; >- next : for (int m = fields.length; --m >= 0;) { >- FieldBinding field = fields[m]; >+ // No visibility checks can be performed without the scope & invocationSite >+ MethodBinding[] methods = currentType.availableMethods(); >+ if(methods != null) { >+ next : for (int f = methods.length; --f >= 0;) { >+ MethodBinding constructor = methods[f]; >+ if (constructor != enclosingConstructor && constructor.isConstructor()) { > >- if (fieldLength > field.name.length) >- continue next; >+ if (constructor.isSynthetic()) continue next; > >- if (field.isSynthetic()) >- continue next; >+ if (this.options.checkDeprecation && >+ constructor.isViewedAsDeprecated() && >+ !scope.isDefinedInSameUnit(constructor.declaringClass)) >+ continue next; > >- if (!field.isStatic()) >- continue next; >+ if (this.options.checkVisibility >+ && !constructor.canBeSeenBy(invocationSite, scope)) continue next; > >- if (!CharOperation.prefixEquals(fieldName, field.name, false/* ignore case */) >- && !(this.options.camelCaseMatch && CharOperation.camelCaseMatch(fieldName, field.name))) >- continue next; >+ TypeBinding[] parameters = constructor.parameters; >+ int paramLength = parameters.length; > >- if (this.options.checkDeprecation && field.isViewedAsDeprecated()) continue next; >- >- if (this.options.checkVisibility >- && !field.canBeSeenBy(this.unitScope.fPackage)) >- continue next; >+ char[][] parameterPackageNames = new char[paramLength][]; >+ char[][] parameterTypeNames = new char[paramLength][]; >+ for (int i = 0; i < paramLength; i++) { >+ TypeBinding type = parameters[i]; >+ parameterPackageNames[i] = type.qualifiedPackageName(); >+ parameterTypeNames[i] = type.qualifiedSourceName(); >+ } >+ char[][] parameterNames = findMethodParameterNames(constructor,parameterTypeNames); > >- char[] completionName = CharOperation.concat(field.name, SEMICOLON); >+ char[] completion = CharOperation.NO_CHAR; >+ if (this.source != null >+ && this.source.length > this.endPosition >+ && this.source[this.endPosition] == '(') >+ completion = name; >+ else >+ completion = CharOperation.concat(name, new char[] { '(', ')' }); > >- int relevance = computeBaseRelevance(); >- relevance += computeRelevanceForResolution(); >- relevance += computeRelevanceForInterestingProposal(); >- relevance += computeRelevanceForCaseMatching(fieldName, field.name); >- relevance += computeRelevanceForRestrictions(IAccessRule.K_ACCESSIBLE); >+ int relevance = computeBaseRelevance(); >+ relevance += computeRelevanceForResolution(); >+ relevance += computeRelevanceForInterestingProposal(); >+ relevance += computeRelevanceForCaseMatching(this.completionToken, name); >+ relevance += computeRelevanceForRestrictions(IAccessRule.K_ACCESSIBLE); > >- this.noProposal = false; >- if(!this.requestor.isIgnored(CompletionProposal.FIELD_REF)) { >- InternalCompletionProposal proposal = createProposal(CompletionProposal.FIELD_REF, this.actualCompletionPosition); >- proposal.setDeclarationSignature(getSignature(field.declaringClass)); >- proposal.setSignature(getSignature(field.type)); >- proposal.setDeclarationPackageName(field.declaringClass.qualifiedPackageName()); >- proposal.setDeclarationTypeName(field.declaringClass.qualifiedSourceName()); >- proposal.setPackageName(field.type.qualifiedPackageName()); >- proposal.setTypeName(field.type.qualifiedSourceName()); >- proposal.setName(field.name); >- proposal.setCompletion(completionName); >- proposal.setFlags(field.modifiers); >- proposal.setReplaceRange(this.startPosition - this.offset, this.endPosition - this.offset); >- proposal.setTokenRange(this.tokenStart - this.offset, this.tokenEnd - this.offset); >- proposal.setRelevance(relevance); >- this.requestor.accept(proposal); >- if(DEBUG) { >- this.printDebug(proposal); >+ this.noProposal = false; >+ if(!this.requestor.isIgnored(CompletionProposal.METHOD_REF)) { >+ InternalCompletionProposal proposal = createProposal(CompletionProposal.METHOD_REF, this.actualCompletionPosition); >+ proposal.setDeclarationSignature(getSignature(currentType)); >+ proposal.setSignature(getSignature(constructor)); >+ MethodBinding original = constructor.original(); >+ if(original != constructor) { >+ proposal.setOriginalSignature(getSignature(original)); >+ } >+ proposal.setDeclarationPackageName(currentType.qualifiedPackageName()); >+ proposal.setDeclarationTypeName(currentType.qualifiedSourceName()); >+ proposal.setParameterPackageNames(parameterPackageNames); >+ proposal.setParameterTypeNames(parameterTypeNames); >+ //proposal.setPackageName(null); >+ //proposal.setTypeName(null); >+ proposal.setName(name); >+ proposal.setIsContructor(true); >+ proposal.setCompletion(completion); >+ proposal.setFlags(constructor.modifiers); >+ proposal.setReplaceRange(this.startPosition - this.offset, this.endPosition - this.offset); >+ proposal.setTokenRange(this.tokenStart - this.offset, this.tokenEnd - this.offset); >+ proposal.setRelevance(relevance); >+ if(parameterNames != null) proposal.setParameterNames(parameterNames); >+ this.requestor.accept(proposal); >+ if(DEBUG) { >+ this.printDebug(proposal); >+ } >+ } > } > } > } > } >+ // Helper method for findFields(char[], ReferenceBinding, Scope, ObjectVector, boolean) >+ private void findFields( >+ char[] fieldName, >+ FieldBinding[] fields, >+ Scope scope, >+ ObjectVector fieldsFound, >+ ObjectVector localsFound, >+ boolean onlyStaticFields, >+ ReferenceBinding receiverType, >+ InvocationSite invocationSite, >+ Scope invocationScope, >+ boolean implicitCall, >+ boolean canBePrefixed, >+ Binding[] missingElements, >+ int[] missingElementsStarts, >+ int[] missingElementsEnds, >+ boolean missingElementsHaveProblems, >+ char[] castedReceiver, >+ int receiverStart, >+ int receiverEnd) { > >- private void findImportsOfStaticMethods(char[] methodName, ReferenceBinding ref) { >- MethodBinding[] methods = ref.availableMethods(); >+ ObjectVector newFieldsFound = new ObjectVector(); >+ // Inherited fields which are hidden by subclasses are filtered out >+ // No visibility checks can be performed without the scope & invocationSite > >- int methodLength = methodName.length; >- next : for (int m = methods.length; --m >= 0;) { >- MethodBinding method = methods[m]; >+ int fieldLength = fieldName.length; >+ next : for (int f = fields.length; --f >= 0;) { >+ FieldBinding field = fields[f]; > >- if (method.isSynthetic()) continue next; >+ if (field.isSynthetic()) continue next; > >- if (method.isDefaultAbstract()) continue next; >+ if (onlyStaticFields && !field.isStatic()) continue next; > >- if (method.isConstructor()) continue next; >+ if (fieldLength > field.name.length) continue next; > >- if (!method.isStatic()) continue next; >+ if (!CharOperation.prefixEquals(fieldName, field.name, false /* ignore case */) >+ && !(this.options.camelCaseMatch && CharOperation.camelCaseMatch(fieldName, field.name))) continue next; > >- if (this.options.checkDeprecation && method.isViewedAsDeprecated()) continue next; >+ if (this.options.checkDeprecation && >+ field.isViewedAsDeprecated() && >+ !scope.isDefinedInSameUnit(field.declaringClass)) >+ continue next; > > if (this.options.checkVisibility >- && !method.canBeSeenBy(this.unitScope.fPackage)) continue next; >+ && !field.canBeSeenBy(receiverType, invocationSite, scope)) continue next; > >- if (methodLength > method.selector.length) >- continue next; >+ boolean prefixRequired = false; > >- if (!CharOperation.prefixEquals(methodName, method.selector, false/* ignore case */) >- && !(this.options.camelCaseMatch && CharOperation.camelCaseMatch(methodName, method.selector))) >- continue next; >+ for (int i = fieldsFound.size; --i >= 0;) { >+ Object[] other = (Object[])fieldsFound.elementAt(i); >+ FieldBinding otherField = (FieldBinding) other[0]; >+ ReferenceBinding otherReceiverType = (ReferenceBinding) other[1]; >+ if (field == otherField && receiverType == otherReceiverType) >+ continue next; >+ if (CharOperation.equals(field.name, otherField.name, true)) { >+ if (field.declaringClass.isSuperclassOf(otherField.declaringClass)) >+ continue next; >+ if (otherField.declaringClass.isInterface()) { >+ if (field.declaringClass == scope.getJavaLangObject()) >+ continue next; >+ if (field.declaringClass.implementsInterface(otherField.declaringClass, true)) >+ continue next; >+ } >+ if (field.declaringClass.isInterface()) >+ if (otherField.declaringClass.implementsInterface(field.declaringClass, true)) >+ continue next; >+ if(canBePrefixed) { >+ prefixRequired = true; >+ } else { >+ continue next; >+ } >+ } >+ } > >- int length = method.parameters.length; >- char[][] parameterPackageNames = new char[length][]; >- char[][] parameterTypeNames = new char[length][]; >+ for (int l = localsFound.size; --l >= 0;) { >+ LocalVariableBinding local = (LocalVariableBinding) localsFound.elementAt(l); > >- for (int i = 0; i < length; i++) { >- TypeBinding type = method.original().parameters[i]; >- parameterPackageNames[i] = type.qualifiedPackageName(); >- parameterTypeNames[i] = type.qualifiedSourceName(); >+ if (CharOperation.equals(field.name, local.name, true)) { >+ SourceTypeBinding declarationType = scope.enclosingSourceType(); >+ if (declarationType.isAnonymousType() && declarationType != invocationScope.enclosingSourceType()) { >+ continue next; >+ } >+ if(canBePrefixed) { >+ prefixRequired = true; >+ } else { >+ continue next; >+ } >+ break; >+ } > } >- char[][] parameterNames = findMethodParameterNames(method,parameterTypeNames); > >- char[] completionName = CharOperation.concat(method.selector, SEMICOLON); >+ newFieldsFound.add(new Object[]{field, receiverType}); > >- int relevance = computeBaseRelevance(); >- relevance += computeRelevanceForResolution(); >- relevance += computeRelevanceForInterestingProposal(); >- relevance += computeRelevanceForCaseMatching(methodName, method.selector); >- relevance += computeRelevanceForRestrictions(IAccessRule.K_ACCESSIBLE); >+ char[] completion = field.name; > >- this.noProposal = false; >- if(!this.requestor.isIgnored(CompletionProposal.METHOD_NAME_REFERENCE)) { >- InternalCompletionProposal proposal = createProposal(CompletionProposal.METHOD_NAME_REFERENCE, this.actualCompletionPosition); >- proposal.setDeclarationSignature(getSignature(method.declaringClass)); >- proposal.setSignature(getSignature(method)); >- proposal.setDeclarationPackageName(method.declaringClass.qualifiedPackageName()); >- proposal.setDeclarationTypeName(method.declaringClass.qualifiedSourceName()); >- proposal.setParameterPackageNames(parameterPackageNames); >- proposal.setParameterTypeNames(parameterTypeNames); >- proposal.setPackageName(method.returnType.qualifiedPackageName()); >- proposal.setTypeName(method.returnType.qualifiedSourceName()); >- proposal.setName(method.selector); >- proposal.setCompletion(completionName); >- proposal.setFlags(method.modifiers); >- proposal.setReplaceRange(this.startPosition - this.offset, this.endPosition - this.offset); >- proposal.setTokenRange(this.tokenStart - this.offset, this.tokenEnd - this.offset); >- proposal.setRelevance(relevance); >- if(parameterNames != null) proposal.setParameterNames(parameterNames); >- this.requestor.accept(proposal); >- if(DEBUG) { >- this.printDebug(proposal); >- } >+ if(prefixRequired || this.options.forceImplicitQualification){ >+ char[] prefix = computePrefix(scope.enclosingSourceType(), invocationScope.enclosingSourceType(), field.isStatic()); >+ completion = CharOperation.concat(prefix,completion,'.'); > } >- } >- } > >- /* >- * Find javadoc block tags for a given completion javadoc tag node >- */ >- private void findJavadocBlockTags(CompletionOnJavadocTag javadocTag) { >- char[][] possibleTags = javadocTag.getPossibleBlockTags(); >- if (possibleTags == null) return; >- int length = possibleTags.length; >- for (int i=0; i<length; i++) { >- int relevance = computeBaseRelevance(); >- relevance += computeRelevanceForInterestingProposal(); >- relevance += computeRelevanceForRestrictions(IAccessRule.K_ACCESSIBLE); // no access restriction for keywors > >- this.noProposal = false; >- if (!this.requestor.isIgnored(CompletionProposal.JAVADOC_BLOCK_TAG)) { >- char[] possibleTag = possibleTags[i]; >- InternalCompletionProposal proposal = createProposal(CompletionProposal.JAVADOC_BLOCK_TAG, this.actualCompletionPosition); >- proposal.setName(possibleTag); >- int tagLength = possibleTag.length; >- char[] completion = new char[1+tagLength]; >- completion[0] = '@'; >- System.arraycopy(possibleTag, 0, completion, 1, tagLength); >- proposal.setCompletion(completion); >- proposal.setReplaceRange(this.startPosition - this.offset, this.endPosition - this.offset); >- proposal.setTokenRange(this.tokenStart - this.offset, this.tokenEnd - this.offset); >- proposal.setRelevance(relevance); >- this.requestor.accept(proposal); >- if (DEBUG) { >- this.printDebug(proposal); >- } >+ if (castedReceiver != null) { >+ completion = CharOperation.concat(castedReceiver, completion); > } >- } >- } >- >- /* >- * Find javadoc inline tags for a given completion javadoc tag node >- */ >- private void findJavadocInlineTags(CompletionOnJavadocTag javadocTag) { >- char[][] possibleTags = javadocTag.getPossibleInlineTags(); >- if (possibleTags == null) return; >- int length = possibleTags.length; >- for (int i=0; i<length; i++) { >- int relevance = computeBaseRelevance(); >- relevance += computeRelevanceForInterestingProposal(); >- relevance += computeRelevanceForRestrictions(IAccessRule.K_ACCESSIBLE); // no access restriction for keywors > >- this.noProposal = false; >- if (!this.requestor.isIgnored(CompletionProposal.JAVADOC_INLINE_TAG)) { >- char[] possibleTag = possibleTags[i]; >- InternalCompletionProposal proposal = createProposal(CompletionProposal.JAVADOC_INLINE_TAG, this.actualCompletionPosition); >- proposal.setName(possibleTag); >- int tagLength = possibleTag.length; >-// boolean inlineTagStarted = javadocTag.completeInlineTagStarted(); >- char[] completion = new char[2+tagLength+1]; >- completion[0] = '{'; >- completion[1] = '@'; >- System.arraycopy(possibleTag, 0, completion, 2, tagLength); >- // do not add space at end of inline tag (see bug https://bugs.eclipse.org/bugs/show_bug.cgi?id=121026) >- //completion[tagLength+2] = ' '; >- completion[tagLength+2] = '}'; >- proposal.setCompletion(completion); >- proposal.setReplaceRange(this.startPosition - this.offset, this.endPosition - this.offset); >- proposal.setTokenRange(this.tokenStart - this.offset, this.tokenEnd - this.offset); >- proposal.setRelevance(relevance); >- this.requestor.accept(proposal); >- if (DEBUG) { >- this.printDebug(proposal); >+ // Special case for javadoc completion >+ if (this.assistNodeInJavadoc > 0) { >+ if (invocationSite instanceof CompletionOnJavadocFieldReference) { >+ CompletionOnJavadocFieldReference fieldRef = (CompletionOnJavadocFieldReference) invocationSite; >+ if (fieldRef.receiver.isThis()) { >+ if (fieldRef.completeInText()) { >+ completion = CharOperation.concat(new char[] { '#' }, field.name); >+ } >+ } else if (fieldRef.completeInText()) { >+ if (fieldRef.receiver instanceof JavadocSingleTypeReference) { >+ JavadocSingleTypeReference typeRef = (JavadocSingleTypeReference) fieldRef.receiver; >+ completion = CharOperation.concat(typeRef.token, field.name, '#'); >+ } else if (fieldRef.receiver instanceof JavadocQualifiedTypeReference) { >+ JavadocQualifiedTypeReference typeRef = (JavadocQualifiedTypeReference) fieldRef.receiver; >+ completion = CharOperation.concat(CharOperation.concatWith(typeRef.tokens, '.'), field.name, '#'); >+ } >+ } > } > } >- } >- } > >- // what about onDemand types? Ignore them since it does not happen! >- // import p1.p2.A.*; >- private void findKeywords(char[] keyword, char[][] choices, boolean canCompleteEmptyToken, boolean staticFieldsAndMethodOnly) { >- if(choices == null || choices.length == 0) return; >+ int relevance = computeBaseRelevance(); >+ relevance += computeRelevanceForResolution(); >+ relevance += computeRelevanceForInterestingProposal(field); >+ if (fieldName != null) relevance += computeRelevanceForCaseMatching(fieldName, field.name); >+ relevance += computeRelevanceForExpectingType(field.type); >+ relevance += computeRelevanceForEnumConstant(field.type); >+ relevance += computeRelevanceForStatic(onlyStaticFields, field.isStatic()); >+ relevance += computeRelevanceForQualification(prefixRequired); >+ relevance += computeRelevanceForRestrictions(IAccessRule.K_ACCESSIBLE); >+ if (onlyStaticFields && this.insideQualifiedReference) { >+ relevance += computeRelevanceForInheritance(receiverType, field.declaringClass); >+ } >+ if (missingElements != null) { >+ relevance += computeRelevanceForMissingElements(missingElementsHaveProblems); >+ } > >- int length = keyword.length; >- if (canCompleteEmptyToken || length > 0) >- for (int i = 0; i < choices.length; i++) >- if (length <= choices[i].length >- && CharOperation.prefixEquals(keyword, choices[i], false /* ignore case */ >- )){ >- int relevance = computeBaseRelevance(); >- relevance += computeRelevanceForResolution(); >- relevance += computeRelevanceForInterestingProposal(); >- relevance += computeRelevanceForCaseMatching(keyword, choices[i]); >- relevance += computeRelevanceForRestrictions(IAccessRule.K_ACCESSIBLE); // no access restriction for keywords >- if (staticFieldsAndMethodOnly && this.insideQualifiedReference) relevance += R_NON_INHERITED; >+ this.noProposal = false; >+ if (castedReceiver == null) { >+ // Standard proposal >+ if (!this.isIgnored(CompletionProposal.FIELD_REF, missingElements != null) && (this.assistNodeInJavadoc & CompletionOnJavadoc.ONLY_INLINE_TAG) == 0) { >+ InternalCompletionProposal proposal = createProposal(CompletionProposal.FIELD_REF, this.actualCompletionPosition); >+ proposal.setDeclarationSignature(getSignature(field.declaringClass)); >+ proposal.setSignature(getSignature(field.type)); >+ proposal.setDeclarationPackageName(field.declaringClass.qualifiedPackageName()); >+ proposal.setDeclarationTypeName(field.declaringClass.qualifiedSourceName()); >+ proposal.setPackageName(field.type.qualifiedPackageName()); >+ proposal.setTypeName(field.type.qualifiedSourceName()); >+ proposal.setName(field.name); >+ if (missingElements != null) { >+ CompletionProposal[] subProposals = new CompletionProposal[missingElements.length]; >+ for (int i = 0; i < missingElements.length; i++) { >+ subProposals[i] = >+ createRequiredTypeProposal( >+ missingElements[i], >+ missingElementsStarts[i], >+ missingElementsEnds[i], >+ relevance); >+ } >+ proposal.setRequiredProposals(subProposals); >+ } >+ proposal.setCompletion(completion); >+ proposal.setFlags(field.modifiers); >+ proposal.setReplaceRange(this.startPosition - this.offset, this.endPosition - this.offset); >+ proposal.setTokenRange(this.tokenStart - this.offset, this.tokenEnd - this.offset); >+ proposal.setRelevance(relevance); >+ this.requestor.accept(proposal); >+ if(DEBUG) { >+ this.printDebug(proposal); >+ } >+ } > >- if(CharOperation.equals(choices[i], Keywords.TRUE) || CharOperation.equals(choices[i], Keywords.FALSE)) { >- relevance += computeRelevanceForExpectingType(TypeBinding.BOOLEAN); >- relevance += computeRelevanceForQualification(false); >+ // Javadoc completions >+ if ((this.assistNodeInJavadoc & CompletionOnJavadoc.TEXT) != 0 && !this.requestor.isIgnored(CompletionProposal.JAVADOC_FIELD_REF)) { >+ char[] javadocCompletion = inlineTagCompletion(completion, JavadocTagConstants.TAG_LINK); >+ InternalCompletionProposal proposal = createProposal(CompletionProposal.JAVADOC_FIELD_REF, this.actualCompletionPosition); >+ proposal.setDeclarationSignature(getSignature(field.declaringClass)); >+ proposal.setSignature(getSignature(field.type)); >+ proposal.setDeclarationPackageName(field.declaringClass.qualifiedPackageName()); >+ proposal.setDeclarationTypeName(field.declaringClass.qualifiedSourceName()); >+ proposal.setPackageName(field.type.qualifiedPackageName()); >+ proposal.setTypeName(field.type.qualifiedSourceName()); >+ proposal.setName(field.name); >+ proposal.setCompletion(javadocCompletion); >+ proposal.setFlags(field.modifiers); >+ int start = (this.assistNodeInJavadoc & CompletionOnJavadoc.REPLACE_TAG) != 0 ? this.javadocTagPosition : this.startPosition; >+ proposal.setReplaceRange(start - this.offset, this.endPosition - this.offset); >+ proposal.setTokenRange(this.tokenStart - this.offset, this.tokenEnd - this.offset); >+ proposal.setRelevance(relevance+R_INLINE_TAG); >+ this.requestor.accept(proposal); >+ if(DEBUG) { >+ this.printDebug(proposal); > } >- this.noProposal = false; >- if(!this.requestor.isIgnored(CompletionProposal.KEYWORD)) { >- InternalCompletionProposal proposal = createProposal(CompletionProposal.KEYWORD, this.actualCompletionPosition); >- proposal.setName(choices[i]); >- proposal.setCompletion(choices[i]); >- proposal.setReplaceRange(this.startPosition - this.offset, this.endPosition - this.offset); >- proposal.setTokenRange(this.tokenStart - this.offset, this.tokenEnd - this.offset); >- proposal.setRelevance(relevance); >- this.requestor.accept(proposal); >+ // Javadoc value completion for static fields >+ if (field.isStatic() && !this.requestor.isIgnored(CompletionProposal.JAVADOC_VALUE_REF)) { >+ javadocCompletion = inlineTagCompletion(completion, JavadocTagConstants.TAG_VALUE); >+ InternalCompletionProposal valueProposal = createProposal(CompletionProposal.JAVADOC_VALUE_REF, this.actualCompletionPosition); >+ valueProposal.setDeclarationSignature(getSignature(field.declaringClass)); >+ valueProposal.setSignature(getSignature(field.type)); >+ valueProposal.setDeclarationPackageName(field.declaringClass.qualifiedPackageName()); >+ valueProposal.setDeclarationTypeName(field.declaringClass.qualifiedSourceName()); >+ valueProposal.setPackageName(field.type.qualifiedPackageName()); >+ valueProposal.setTypeName(field.type.qualifiedSourceName()); >+ valueProposal.setName(field.name); >+ valueProposal.setCompletion(javadocCompletion); >+ valueProposal.setFlags(field.modifiers); >+ valueProposal.setReplaceRange(start - this.offset, this.endPosition - this.offset); >+ valueProposal.setTokenRange(this.tokenStart - this.offset, this.tokenEnd - this.offset); >+ valueProposal.setRelevance(relevance+R_VALUE_TAG); >+ this.requestor.accept(valueProposal); > if(DEBUG) { >- this.printDebug(proposal); >+ this.printDebug(valueProposal); > } > } > } >- } >- private void findTrueOrFalseKeywords(char[][] choices) { >- if(choices == null || choices.length == 0) return; >- >- if(this.expectedTypesPtr != 0 || this.expectedTypes[0] != TypeBinding.BOOLEAN) return; >- >- for (int i = 0; i < choices.length; i++) { >- if (CharOperation.equals(choices[i], Keywords.TRUE) || >- CharOperation.equals(choices[i], Keywords.FALSE) >- ){ >- int relevance = computeBaseRelevance(); >- relevance += computeRelevanceForResolution(); >- relevance += computeRelevanceForInterestingProposal(); >- relevance += computeRelevanceForCaseMatching(CharOperation.NO_CHAR, choices[i]); >- relevance += computeRelevanceForRestrictions(IAccessRule.K_ACCESSIBLE); // no access restriction for keywors >- relevance += computeRelevanceForExpectingType(TypeBinding.BOOLEAN); >- relevance += computeRelevanceForQualification(false); >- relevance += R_TRUE_OR_FALSE; >- >- this.noProposal = false; >- if(!this.requestor.isIgnored(CompletionProposal.KEYWORD)) { >- InternalCompletionProposal proposal = createProposal(CompletionProposal.KEYWORD, this.actualCompletionPosition); >- proposal.setName(choices[i]); >- proposal.setCompletion(choices[i]); >+ } else { >+ if(!this.isIgnored(CompletionProposal.FIELD_REF_WITH_CASTED_RECEIVER, missingElements != null)) { >+ InternalCompletionProposal proposal = createProposal(CompletionProposal.FIELD_REF_WITH_CASTED_RECEIVER, this.actualCompletionPosition); >+ proposal.setDeclarationSignature(getSignature(field.declaringClass)); >+ proposal.setSignature(getSignature(field.type)); >+ proposal.setReceiverSignature(getSignature(receiverType)); >+ proposal.setDeclarationPackageName(field.declaringClass.qualifiedPackageName()); >+ proposal.setDeclarationTypeName(field.declaringClass.qualifiedSourceName()); >+ proposal.setPackageName(field.type.qualifiedPackageName()); >+ proposal.setTypeName(field.type.qualifiedSourceName()); >+ proposal.setName(field.name); >+ if (missingElements != null) { >+ CompletionProposal[] subProposals = new CompletionProposal[missingElements.length]; >+ for (int i = 0; i < missingElements.length; i++) { >+ subProposals[i] = >+ createRequiredTypeProposal( >+ missingElements[i], >+ missingElementsStarts[i], >+ missingElementsEnds[i], >+ relevance); >+ } >+ proposal.setRequiredProposals(subProposals); >+ } >+ proposal.setCompletion(completion); >+ proposal.setFlags(field.modifiers); > proposal.setReplaceRange(this.startPosition - this.offset, this.endPosition - this.offset); >+ proposal.setReceiverRange(receiverStart - this.offset, receiverEnd - this.offset); > proposal.setTokenRange(this.tokenStart - this.offset, this.tokenEnd - this.offset); > proposal.setRelevance(relevance); > this.requestor.accept(proposal); >@@ -5076,607 +5034,851 @@ > } > } > } >- } >- >- private void findKeywordsForMember(char[] token, int modifiers) { >- char[][] keywords = new char[Keywords.COUNT][]; >- int count = 0; >- >- // visibility >- if((modifiers & ClassFileConstants.AccPrivate) == 0 >- && (modifiers & ClassFileConstants.AccProtected) == 0 >- && (modifiers & ClassFileConstants.AccPublic) == 0) { >- keywords[count++] = Keywords.PROTECTED; >- keywords[count++] = Keywords.PUBLIC; >- if((modifiers & ClassFileConstants.AccAbstract) == 0) { >- keywords[count++] = Keywords.PRIVATE; >- } >- } > >- if((modifiers & ClassFileConstants.AccAbstract) == 0) { >- // abtract >- if((modifiers & ~(ExtraCompilerModifiers.AccVisibilityMASK | ClassFileConstants.AccStatic)) == 0) { >- keywords[count++] = Keywords.ABSTRACT; >- } >+ fieldsFound.addAll(newFieldsFound); >+ } >+ private void findFields( >+ char[] fieldName, >+ ReferenceBinding receiverType, >+ Scope scope, >+ ObjectVector fieldsFound, >+ ObjectVector localsFound, >+ boolean onlyStaticFields, >+ InvocationSite invocationSite, >+ Scope invocationScope, >+ boolean implicitCall, >+ boolean canBePrefixed, >+ Binding[] missingElements, >+ int[] missingElementsStarts, >+ int[] missingElementsEnds, >+ boolean missingElementsHaveProblems, >+ char[] castedReceiver, >+ int receiverStart, >+ int receiverEnd) { > >- // final >- if((modifiers & ClassFileConstants.AccFinal) == 0) { >- keywords[count++] = Keywords.FINAL; >- } >+ boolean notInJavadoc = this.assistNodeInJavadoc == 0; >+ if (fieldName == null && notInJavadoc) >+ return; > >- // static >- if((modifiers & ClassFileConstants.AccStatic) == 0) { >- keywords[count++] = Keywords.STATIC; >- } >- >- boolean canBeField = true; >- boolean canBeMethod = true; >- boolean canBeType = true; >- if((modifiers & ClassFileConstants.AccNative) != 0 >- || (modifiers & ClassFileConstants.AccStrictfp) != 0 >- || (modifiers & ClassFileConstants.AccSynchronized) != 0) { >- canBeField = false; >- canBeType = false; >- } >- >- if((modifiers & ClassFileConstants.AccTransient) != 0 >- || (modifiers & ClassFileConstants.AccVolatile) != 0) { >- canBeMethod = false; >- canBeType = false; >- } >- >- if(canBeField) { >- // transient >- if((modifiers & ClassFileConstants.AccTransient) == 0) { >- keywords[count++] = Keywords.TRANSIENT; >- } >- >- // volatile >- if((modifiers & ClassFileConstants.AccVolatile) == 0) { >- keywords[count++] = Keywords.VOLATILE; >+ ReferenceBinding currentType = receiverType; >+ ReferenceBinding[] interfacesToVisit = null; >+ int nextPosition = 0; >+ do { >+ ReferenceBinding[] itsInterfaces = currentType.superInterfaces(); >+ if (notInJavadoc && itsInterfaces != Binding.NO_SUPERINTERFACES) { >+ if (interfacesToVisit == null) { >+ interfacesToVisit = itsInterfaces; >+ nextPosition = interfacesToVisit.length; >+ } else { >+ int itsLength = itsInterfaces.length; >+ if (nextPosition + itsLength >= interfacesToVisit.length) >+ System.arraycopy(interfacesToVisit, 0, interfacesToVisit = new ReferenceBinding[nextPosition + itsLength + 5], 0, nextPosition); >+ nextInterface : for (int a = 0; a < itsLength; a++) { >+ ReferenceBinding next = itsInterfaces[a]; >+ for (int b = 0; b < nextPosition; b++) >+ if (next == interfacesToVisit[b]) continue nextInterface; >+ interfacesToVisit[nextPosition++] = next; >+ } > } > } > >- if(canBeMethod) { >- // native >- if((modifiers & ClassFileConstants.AccNative) == 0) { >- keywords[count++] = Keywords.NATIVE; >- } >+ FieldBinding[] fields = currentType.availableFields(); >+ if(fields != null && fields.length > 0) { >+ findFields( >+ fieldName, >+ fields, >+ scope, >+ fieldsFound, >+ localsFound, >+ onlyStaticFields, >+ receiverType, >+ invocationSite, >+ invocationScope, >+ implicitCall, >+ canBePrefixed, >+ missingElements, >+ missingElementsStarts, >+ missingElementsEnds, >+ missingElementsHaveProblems, >+ castedReceiver, >+ receiverStart, >+ receiverEnd); >+ } >+ currentType = currentType.superclass(); >+ } while (notInJavadoc && currentType != null); > >- // strictfp >- if((modifiers & ClassFileConstants.AccStrictfp) == 0) { >- keywords[count++] = Keywords.STRICTFP; >+ if (notInJavadoc && interfacesToVisit != null) { >+ for (int i = 0; i < nextPosition; i++) { >+ ReferenceBinding anInterface = interfacesToVisit[i]; >+ FieldBinding[] fields = anInterface.availableFields(); >+ if(fields != null) { >+ findFields( >+ fieldName, >+ fields, >+ scope, >+ fieldsFound, >+ localsFound, >+ onlyStaticFields, >+ receiverType, >+ invocationSite, >+ invocationScope, >+ implicitCall, >+ canBePrefixed, >+ missingElements, >+ missingElementsStarts, >+ missingElementsEnds, >+ missingElementsHaveProblems, >+ castedReceiver, >+ receiverStart, >+ receiverEnd); > } > >- // synchronized >- if((modifiers & ClassFileConstants.AccSynchronized) == 0) { >- keywords[count++] = Keywords.SYNCHRONIZED; >+ ReferenceBinding[] itsInterfaces = anInterface.superInterfaces(); >+ if (itsInterfaces != Binding.NO_SUPERINTERFACES) { >+ int itsLength = itsInterfaces.length; >+ if (nextPosition + itsLength >= interfacesToVisit.length) >+ System.arraycopy(interfacesToVisit, 0, interfacesToVisit = new ReferenceBinding[nextPosition + itsLength + 5], 0, nextPosition); >+ nextInterface : for (int a = 0; a < itsLength; a++) { >+ ReferenceBinding next = itsInterfaces[a]; >+ for (int b = 0; b < nextPosition; b++) >+ if (next == interfacesToVisit[b]) continue nextInterface; >+ interfacesToVisit[nextPosition++] = next; >+ } > } > } >+ } >+ } > >- if(canBeType) { >- keywords[count++] = Keywords.CLASS; >- keywords[count++] = Keywords.INTERFACE; >+ protected void findFieldsAndMethods( >+ char[] token, >+ TypeBinding receiverType, >+ Scope scope, >+ ObjectVector fieldsFound, >+ ObjectVector methodsFound, >+ InvocationSite invocationSite, >+ Scope invocationScope, >+ boolean implicitCall, >+ boolean superCall, >+ Binding[] missingElements, >+ int[] missingElementsStarts, >+ int[] missingElementsEnds, >+ boolean missingElementsHaveProblems, >+ char[] castedReceiver, >+ int receiverStart, >+ int receiverEnd) { > >- if((modifiers & ClassFileConstants.AccFinal) == 0) { >- keywords[count++] = Keywords.ENUM; >- } >- } >- } else { >- // class >- keywords[count++] = Keywords.CLASS; >- keywords[count++] = Keywords.INTERFACE; >- } >- System.arraycopy(keywords, 0, keywords = new char[count][], 0, count); >+ if (token == null) >+ return; > >- findKeywords(token, keywords, false, false); >- } >+ if (receiverType.isBaseType()) >+ return; // nothing else is possible with base types > >- protected void findMembers( >- char[] token, >- ReferenceBinding receiverType, >- Scope scope, >- InvocationSite invocationSite, >- boolean isInsideAnnotationAttribute, >- Binding[] missingElements, >- int[] missingElementsStarts, >- int[] missingElementsEnds, >- boolean missingElementsHaveProblems) { >+ boolean proposeField = >+ castedReceiver == null ? >+ !this.isIgnored(CompletionProposal.FIELD_REF, missingElements != null) : >+ !this.isIgnored(CompletionProposal.FIELD_REF_WITH_CASTED_RECEIVER, missingElements != null) ; >+ boolean proposeMethod = >+ castedReceiver == null ? >+ !this.isIgnored(CompletionProposal.METHOD_REF, missingElements != null) : >+ !this.isIgnored(CompletionProposal.METHOD_REF_WITH_CASTED_RECEIVER, missingElements != null); > >- if (!this.requestor.isIgnored(CompletionProposal.TYPE_REF)) { >- findMemberTypes( >- token, >- receiverType, >- scope, >- scope.enclosingSourceType(), >- false, >- true, >- new ObjectVector(), >- missingElements, >- missingElementsStarts, >- missingElementsEnds, >- missingElementsHaveProblems); >- } >- if (!this.requestor.isIgnored(CompletionProposal.FIELD_REF)) { >- findClassField( >- token, >- receiverType, >- scope, >- missingElements, >- missingElementsStarts, >- missingElementsEnds, >- missingElementsHaveProblems); >- } >+ if (receiverType.isArrayType()) { >+ if (proposeField >+ && token.length <= lengthField.length >+ && CharOperation.prefixEquals(token, lengthField, false /* ignore case */ >+ )) { > >- MethodScope methodScope = null; >- if (!isInsideAnnotationAttribute && >- !this.requestor.isIgnored(CompletionProposal.KEYWORD) && >- ((scope instanceof MethodScope && !((MethodScope)scope).isStatic) >- || ((methodScope = scope.enclosingMethodScope()) != null && !methodScope.isStatic))) { >- if (token.length > 0) { >- findKeywords(token, new char[][]{Keywords.THIS}, false, true); >- } else { > int relevance = computeBaseRelevance(); > relevance += computeRelevanceForResolution(); > relevance += computeRelevanceForInterestingProposal(); >- relevance += computeRelevanceForCaseMatching(this.completionToken, Keywords.THIS); >- relevance += computeRelevanceForRestrictions(IAccessRule.K_ACCESSIBLE); // no access restriction for keywords >- relevance += R_NON_INHERITED; >- >- this.noProposal = false; >- if (!this.requestor.isIgnored(CompletionProposal.KEYWORD)) { >- InternalCompletionProposal proposal = createProposal(CompletionProposal.KEYWORD, this.actualCompletionPosition); >- proposal.setName(Keywords.THIS); >- proposal.setCompletion(Keywords.THIS); >- proposal.setReplaceRange(this.startPosition - this.offset, this.endPosition - this.offset); >- proposal.setTokenRange(this.tokenStart - this.offset, this.tokenEnd - this.offset); >- proposal.setRelevance(relevance); >- this.requestor.accept(proposal); >- if (DEBUG) { >- this.printDebug(proposal); >- } >+ relevance += computeRelevanceForCaseMatching(token,lengthField); >+ relevance += computeRelevanceForExpectingType(TypeBinding.INT); >+ relevance += computeRelevanceForRestrictions(IAccessRule.K_ACCESSIBLE); // no access restriction for length field >+ if (missingElements != null) { >+ relevance += computeRelevanceForMissingElements(missingElementsHaveProblems); > } >- } >- } >- >- if (!this.requestor.isIgnored(CompletionProposal.FIELD_REF)) { >- findFields( >- token, >- receiverType, >- scope, >- new ObjectVector(), >- new ObjectVector(), >- true, >- invocationSite, >- scope, >- false, >- false, >- missingElements, >- missingElementsStarts, >- missingElementsEnds, >- missingElementsHaveProblems, >- null, >- -1, >- -1); >- } >- >- if (!isInsideAnnotationAttribute && !this.requestor.isIgnored(CompletionProposal.METHOD_REF)) { >- findMethods( >+ this.noProposal = false; >+ if (castedReceiver == null) { >+ if(!isIgnored(CompletionProposal.FIELD_REF, missingElements != null)) { >+ InternalCompletionProposal proposal = createProposal(CompletionProposal.FIELD_REF, this.actualCompletionPosition); >+ proposal.setDeclarationSignature(getSignature(receiverType)); >+ proposal.setSignature(INT_SIGNATURE); >+ proposal.setTypeName(INT); >+ proposal.setName(lengthField); >+ if (missingElements != null) { >+ CompletionProposal[] subProposals = new CompletionProposal[missingElements.length]; >+ for (int i = 0; i < missingElements.length; i++) { >+ subProposals[i] = >+ createRequiredTypeProposal( >+ missingElements[i], >+ missingElementsStarts[i], >+ missingElementsEnds[i], >+ relevance); >+ } >+ proposal.setRequiredProposals(subProposals); >+ } >+ proposal.setCompletion(lengthField); >+ proposal.setFlags(Flags.AccPublic); >+ proposal.setReplaceRange(this.startPosition - this.offset, this.endPosition - this.offset); >+ proposal.setTokenRange(this.tokenStart - this.offset, this.tokenEnd - this.offset); >+ proposal.setRelevance(relevance); >+ this.requestor.accept(proposal); >+ if(DEBUG) { >+ this.printDebug(proposal); >+ } >+ } >+ } else { >+ char[] completion = CharOperation.concat(castedReceiver, lengthField); >+ >+ if(!this.isIgnored(CompletionProposal.FIELD_REF_WITH_CASTED_RECEIVER, missingElements != null)) { >+ InternalCompletionProposal proposal = createProposal(CompletionProposal.FIELD_REF_WITH_CASTED_RECEIVER, this.actualCompletionPosition); >+ proposal.setDeclarationSignature(getSignature(receiverType)); >+ proposal.setSignature(INT_SIGNATURE); >+ proposal.setReceiverSignature(getSignature(receiverType)); >+ proposal.setTypeName(INT); >+ proposal.setName(lengthField); >+ if (missingElements != null) { >+ CompletionProposal[] subProposals = new CompletionProposal[missingElements.length]; >+ for (int i = 0; i < missingElements.length; i++) { >+ subProposals[i] = >+ createRequiredTypeProposal( >+ missingElements[i], >+ missingElementsStarts[i], >+ missingElementsEnds[i], >+ relevance); >+ } >+ proposal.setRequiredProposals(subProposals); >+ } >+ proposal.setCompletion(completion); >+ proposal.setFlags(Flags.AccPublic); >+ proposal.setReplaceRange(this.startPosition - this.offset, this.endPosition - this.offset); >+ proposal.setReceiverRange(receiverStart - this.offset, receiverEnd - this.offset); >+ proposal.setTokenRange(this.tokenStart - this.offset, this.tokenEnd - this.offset); >+ proposal.setRelevance(relevance); >+ this.requestor.accept(proposal); >+ if(DEBUG) { >+ this.printDebug(proposal); >+ } >+ } >+ } >+ } >+ if (proposeMethod >+ && token.length <= cloneMethod.length >+ && CharOperation.prefixEquals(token, cloneMethod, false /* ignore case */) >+ ) { >+ ReferenceBinding objectRef = scope.getJavaLangObject(); >+ >+ int relevance = computeBaseRelevance(); >+ relevance += computeRelevanceForResolution(); >+ relevance += computeRelevanceForInterestingProposal(); >+ relevance += computeRelevanceForCaseMatching(token, cloneMethod); >+ relevance += computeRelevanceForExpectingType(objectRef); >+ relevance += computeRelevanceForStatic(false, false); >+ relevance += computeRelevanceForQualification(false); >+ relevance += computeRelevanceForRestrictions(IAccessRule.K_ACCESSIBLE); // no access restriction for clone() method >+ if (missingElements != null) { >+ relevance += computeRelevanceForMissingElements(missingElementsHaveProblems); >+ } >+ char[] completion; >+ if (this.source != null >+ && this.source.length > this.endPosition >+ && this.source[this.endPosition] == '(') { >+ completion = cloneMethod; >+ } else { >+ completion = CharOperation.concat(cloneMethod, new char[] { '(', ')' }); >+ } >+ >+ if (castedReceiver != null) { >+ completion = CharOperation.concat(castedReceiver, completion); >+ } >+ >+ this.noProposal = false; >+ if (castedReceiver == null) { >+ if (!this.isIgnored(CompletionProposal.METHOD_REF, missingElements != null)) { >+ InternalCompletionProposal proposal = createProposal(CompletionProposal.METHOD_REF, this.actualCompletionPosition); >+ proposal.setDeclarationSignature(getSignature(receiverType)); >+ proposal.setSignature( >+ this.compilerOptions.sourceLevel > ClassFileConstants.JDK1_4 && receiverType.isArrayType() ? >+ createMethodSignature( >+ CharOperation.NO_CHAR_CHAR, >+ CharOperation.NO_CHAR_CHAR, >+ getSignature(receiverType)) : >+ createMethodSignature( >+ CharOperation.NO_CHAR_CHAR, >+ CharOperation.NO_CHAR_CHAR, >+ CharOperation.concatWith(JAVA_LANG, '.'), >+ OBJECT)); >+ //proposal.setOriginalSignature(null); >+ //proposal.setDeclarationPackageName(null); >+ //proposal.setDeclarationTypeName(null); >+ //proposal.setParameterPackageNames(null); >+ //proposal.setParameterTypeNames(null); >+ proposal.setPackageName(CharOperation.concatWith(JAVA_LANG, '.')); >+ proposal.setTypeName(OBJECT); >+ proposal.setName(cloneMethod); >+ if (missingElements != null) { >+ CompletionProposal[] subProposals = new CompletionProposal[missingElements.length]; >+ for (int i = 0; i < missingElements.length; i++) { >+ subProposals[i] = >+ createRequiredTypeProposal( >+ missingElements[i], >+ missingElementsStarts[i], >+ missingElementsEnds[i], >+ relevance); >+ } >+ proposal.setRequiredProposals(subProposals); >+ } >+ proposal.setCompletion(completion); >+ proposal.setFlags(Flags.AccPublic); >+ proposal.setReplaceRange(this.startPosition - this.offset, this.endPosition - this.offset); >+ proposal.setTokenRange(this.tokenStart - this.offset, this.tokenEnd - this.offset); >+ proposal.setRelevance(relevance); >+ this.requestor.accept(proposal); >+ if(DEBUG) { >+ this.printDebug(proposal); >+ } >+ } >+ methodsFound.add(new Object[]{objectRef.getMethods(cloneMethod)[0], objectRef}); >+ } else { >+ if(!this.isIgnored(CompletionProposal.METHOD_REF_WITH_CASTED_RECEIVER, missingElements != null)) { >+ InternalCompletionProposal proposal = createProposal(CompletionProposal.METHOD_REF_WITH_CASTED_RECEIVER, this.actualCompletionPosition); >+ proposal.setDeclarationSignature(getSignature(receiverType)); >+ proposal.setSignature( >+ this.compilerOptions.sourceLevel > ClassFileConstants.JDK1_4 && receiverType.isArrayType() ? >+ createMethodSignature( >+ CharOperation.NO_CHAR_CHAR, >+ CharOperation.NO_CHAR_CHAR, >+ getSignature(receiverType)) : >+ createMethodSignature( >+ CharOperation.NO_CHAR_CHAR, >+ CharOperation.NO_CHAR_CHAR, >+ CharOperation.concatWith(JAVA_LANG, '.'), >+ OBJECT)); >+ proposal.setReceiverSignature(getSignature(receiverType)); >+ proposal.setPackageName(CharOperation.concatWith(JAVA_LANG, '.')); >+ proposal.setTypeName(OBJECT); >+ proposal.setName(cloneMethod); >+ if (missingElements != null) { >+ CompletionProposal[] subProposals = new CompletionProposal[missingElements.length]; >+ for (int i = 0; i < missingElements.length; i++) { >+ subProposals[i] = >+ createRequiredTypeProposal( >+ missingElements[i], >+ missingElementsStarts[i], >+ missingElementsEnds[i], >+ relevance); >+ } >+ proposal.setRequiredProposals(subProposals); >+ } >+ proposal.setCompletion(completion); >+ proposal.setFlags(Flags.AccPublic); >+ proposal.setReplaceRange(this.startPosition - this.offset, this.endPosition - this.offset); >+ proposal.setReceiverRange(receiverStart - this.offset, receiverEnd - this.offset); >+ proposal.setTokenRange(this.tokenStart - this.offset, this.tokenEnd - this.offset); >+ proposal.setRelevance(relevance); >+ this.requestor.accept(proposal); >+ if(DEBUG) { >+ this.printDebug(proposal); >+ } >+ } >+ } >+ } >+ >+ receiverType = scope.getJavaLangObject(); >+ } >+ >+ checkCancel(); >+ >+ if(proposeField) { >+ findFields( > token, >- null, >- null, >- receiverType, >+ (ReferenceBinding) receiverType, > scope, >+ fieldsFound, > new ObjectVector(), >- true, >- false, > false, > invocationSite, >+ invocationScope, >+ implicitCall, >+ false, >+ missingElements, >+ missingElementsStarts, >+ missingElementsEnds, >+ missingElementsHaveProblems, >+ castedReceiver, >+ receiverStart, >+ receiverEnd); >+ } >+ >+ if(proposeMethod) { >+ findMethods( >+ token, >+ null, >+ null, >+ (ReferenceBinding) receiverType, > scope, >+ methodsFound, > false, > false, >+ invocationSite, >+ invocationScope, >+ implicitCall, >+ superCall, > false, > missingElements, > missingElementsStarts, > missingElementsEnds, > missingElementsHaveProblems, >- null, >- -1, >- -1); >+ castedReceiver, >+ receiverStart, >+ receiverEnd); > } > } > >- private void findMembersFromMissingType( >- final char[] token, >- final long pos, >- TypeBinding resolveType, >- final Scope scope, >- final InvocationSite invocationSite, >- final boolean isInsideAnnotationAttribute) { >- MissingTypesGuesser missingTypesConverter = new MissingTypesGuesser(this); >- MissingTypesGuesser.GuessedTypeRequestor substitutionRequestor = >- new MissingTypesGuesser.GuessedTypeRequestor() { >- public void accept( >- TypeBinding guessedType, >- Binding[] missingElements, >- int[] missingElementsStarts, >- int[] missingElementsEnds, >- boolean hasProblems) { >- if (guessedType instanceof ReferenceBinding) { >- findMembers( >- CompletionEngine.this.completionToken, >- (ReferenceBinding)guessedType, >- scope, >- invocationSite, >- isInsideAnnotationAttribute, >- missingElements, >- missingElementsStarts, >- missingElementsEnds, >- hasProblems); >- } >- } >- }; >- SingleTypeReference typeRef = new SingleTypeReference(token, pos); >- typeRef.resolvedType = new ProblemReferenceBinding(new char[][]{ token }, null, ProblemReasons.NotFound); >- missingTypesConverter.guess(typeRef, scope, substitutionRequestor); >- } >+ protected void findFieldsAndMethodsFromAnotherReceiver( >+ char[] token, >+ TypeReference receiverType, >+ Scope scope, >+ ObjectVector fieldsFound, >+ ObjectVector methodsFound, >+ InvocationSite invocationSite, >+ Scope invocationScope, >+ boolean implicitCall, >+ boolean superCall, >+ Binding[] missingElements, >+ int[] missingElementsStarts, >+ int[] missingElementsEnds, >+ boolean missingElementsHaveProblems, >+ char[][] receiverName, >+ int receiverStart, >+ int receiverEnd) { > >- // Helper method for findMemberTypes(char[], ReferenceBinding, Scope) >- private void findMemberTypes( >- char[] typeName, >- ReferenceBinding[] memberTypes, >- ObjectVector typesFound, >- ReferenceBinding receiverType, >- SourceTypeBinding invocationType, >- boolean staticOnly, >- boolean staticFieldsAndMethodOnly, >- boolean fromStaticImport, >- boolean checkQualification, >- Scope scope, >- Binding[] missingElements, >- int[] missingElementsStarts, >- int[] missingElementsEnds, >- boolean missingElementsHaveProblems) { >+ if (receiverType.resolvedType == null) return; > >- // Inherited member types which are hidden by subclasses are filtered out >- // No visibility checks can be performed without the scope & invocationSite >- int typeLength = typeName.length; >- next : for (int m = memberTypes.length; --m >= 0;) { >- ReferenceBinding memberType = memberTypes[m]; >- // if (!wantClasses && memberType.isClass()) continue next; >- // if (!wantInterfaces && memberType.isInterface()) continue next; >+ TypeBinding receiverTypeBinding = receiverType.resolvedType; >+ char[] castedReceiver = null; > >- if (staticOnly && !memberType.isStatic()) continue next; >+ char[] castedTypeChars = CharOperation.concatWith(receiverType.getTypeName(), '.'); >+ if(this.source != null) { >+ int memberRefStart = this.startPosition; > >- if (isForbidden(memberType)) continue next; >+ char[] receiverChars = CharOperation.subarray(this.source, receiverStart, receiverEnd); >+ char[] dotChars = CharOperation.subarray(this.source, receiverEnd, memberRefStart); > >- if (typeLength > memberType.sourceName.length) >- continue next; >+ castedReceiver = >+ CharOperation.concat( >+ CharOperation.concat( >+ '(', >+ CharOperation.concat( >+ CharOperation.concat('(', castedTypeChars, ')'), >+ receiverChars), >+ ')'), >+ dotChars); >+ } else { >+ castedReceiver = >+ CharOperation.concat( >+ CharOperation.concat( >+ '(', >+ CharOperation.concat( >+ CharOperation.concat('(', castedTypeChars, ')'), >+ CharOperation.concatWith(receiverName, '.')), >+ ')'), >+ DOT); >+ } > >- if (!CharOperation.prefixEquals(typeName, memberType.sourceName, false/* ignore case */) >- && !(this.options.camelCaseMatch && CharOperation.camelCaseMatch(typeName, memberType.sourceName))) >- continue next; >+ if (castedReceiver == null) return; > >- if (this.options.checkDeprecation && >- memberType.isViewedAsDeprecated() && >- !scope.isDefinedInSameUnit(memberType)) >- continue next; >+ int oldStartPosition = this.startPosition; >+ this.startPosition = receiverStart; > >- if (this.options.checkVisibility) { >- if (invocationType != null && !memberType.canBeSeenBy(receiverType, invocationType)) { >- continue next; >- } else if(invocationType == null && !memberType.canBeSeenBy(this.unitScope.fPackage)) { >- continue next; >- } >- } >+ findFieldsAndMethods( >+ token, >+ receiverTypeBinding, >+ scope, >+ fieldsFound, >+ methodsFound, >+ invocationSite, >+ invocationScope, >+ implicitCall, >+ superCall, >+ missingElements, >+ missingElementsStarts, >+ missingElementsEnds, >+ missingElementsHaveProblems, >+ castedReceiver, >+ receiverStart, >+ receiverEnd); > >- if (this.insideQualifiedReference && >- receiverType.isParameterizedType() && >- memberType.isStatic()) { >- continue next; >- } >+ this.startPosition = oldStartPosition; >+ } >+ private void findFieldsAndMethodsFromCastedReceiver( >+ ASTNode enclosingNode, >+ Binding qualifiedBinding, >+ Scope scope, >+ ObjectVector fieldsFound, >+ ObjectVector methodsFound, >+ InvocationSite invocationSite, >+ Scope invocationScope, >+ Expression receiver) { > >- for (int i = typesFound.size; --i >= 0;) { >- ReferenceBinding otherType = (ReferenceBinding) typesFound.elementAt(i); >+ if (enclosingNode == null || !(enclosingNode instanceof IfStatement)) return; > >- if (memberType == otherType) >- continue next; >+ IfStatement ifStatement = (IfStatement)enclosingNode; > >- if (CharOperation.equals(memberType.sourceName, otherType.sourceName, true)) { >+ if (!(ifStatement.condition instanceof InstanceOfExpression)) return; > >- if (memberType.enclosingType().isSuperclassOf(otherType.enclosingType())) >- continue next; >+ InstanceOfExpression instanceOfExpression = (InstanceOfExpression) ifStatement.condition; > >- if (otherType.enclosingType().isInterface()) >- if (memberType.enclosingType() >- .implementsInterface(otherType.enclosingType(), true)) >- continue next; >+ TypeReference instanceOfType = instanceOfExpression.type; > >- if (memberType.enclosingType().isInterface()) >- if (otherType.enclosingType() >- .implementsInterface(memberType.enclosingType(), true)) >- continue next; >- } >+ if (instanceOfType.resolvedType == null) return; >+ >+ boolean findFromAnotherReceiver = false; >+ >+ char[][] receiverName = null; >+ int receiverStart = -1; >+ int receiverEnd = -1; >+ >+ if (receiver instanceof QualifiedNameReference) { >+ QualifiedNameReference qualifiedNameReference = (QualifiedNameReference) receiver; >+ >+ receiverName = qualifiedNameReference.tokens; >+ >+ if (receiverName.length != 1) return; >+ >+ receiverStart = (int) (qualifiedNameReference.sourcePositions[0] >>> 32); >+ receiverEnd = (int) qualifiedNameReference.sourcePositions[qualifiedNameReference.tokens.length - 1] + 1; >+ >+ // if (local instanceof X) local.| >+ // if (field instanceof X) field.| >+ if (instanceOfExpression.expression instanceof SingleNameReference && >+ ((SingleNameReference)instanceOfExpression.expression).binding == qualifiedBinding && >+ (qualifiedBinding instanceof LocalVariableBinding || qualifiedBinding instanceof FieldBinding)) { >+ findFromAnotherReceiver = true; > } > >- typesFound.add(memberType); >+ // if (this.field instanceof X) field.| >+ if (instanceOfExpression.expression instanceof FieldReference) { >+ FieldReference fieldReference = (FieldReference)instanceOfExpression.expression; > >- if(!this.insideQualifiedReference) { >- if(this.assistNodeIsClass) { >- if(!memberType.isClass()) continue next; >- } else if(this.assistNodeIsInterface) { >- if(!memberType.isInterface() && !memberType.isAnnotationType()) continue next; >- } else if (this.assistNodeIsAnnotation) { >- if(!memberType.isAnnotationType()) continue next; >+ if (fieldReference.receiver instanceof ThisReference && >+ qualifiedBinding instanceof FieldBinding && >+ fieldReference.binding == qualifiedBinding) { >+ findFromAnotherReceiver = true; > } > } >+ } else if (receiver instanceof FieldReference) { >+ FieldReference fieldReference1 = (FieldReference) receiver; > >- char[] completionName = memberType.sourceName(); >+ receiverStart = fieldReference1.sourceStart; >+ receiverEnd = fieldReference1.sourceEnd + 1; > >- boolean isQualified = false; >- if(checkQualification && !fromStaticImport) { >- char[] memberPackageName = memberType.qualifiedPackageName(); >- char[] memberTypeName = memberType.sourceName(); >- char[] memberEnclosingTypeNames = memberType.enclosingType().qualifiedSourceName(); >- if (mustQualifyType(memberPackageName, memberTypeName, memberEnclosingTypeNames, memberType.modifiers)) { >- if (memberPackageName == null || memberPackageName.length == 0) >- if (this.unitScope != null && this.unitScope.fPackage.compoundName != CharOperation.NO_CHAR_CHAR) >- break next; // ignore types from the default package from outside it >- isQualified = true; >- completionName = >- CharOperation.concat( >- memberPackageName, >- CharOperation.concat( >- memberEnclosingTypeNames, >- memberTypeName, >- '.'), >- '.'); >+ if (fieldReference1.receiver instanceof ThisReference) { >+ >+ receiverName = new char[][] {THIS, fieldReference1.token}; >+ >+ // if (field instanceof X) this.field.| >+ if (instanceOfExpression.expression instanceof SingleNameReference && >+ ((SingleNameReference)instanceOfExpression.expression).binding == fieldReference1.binding) { >+ findFromAnotherReceiver = true; > } >- } > >- int relevance = computeBaseRelevance(); >- relevance += computeRelevanceForResolution(); >- relevance += computeRelevanceForInterestingProposal(); >- relevance += computeRelevanceForCaseMatching(typeName, memberType.sourceName); >- relevance += computeRelevanceForExpectingType(memberType); >- relevance += computeRelevanceForRestrictions(IAccessRule.K_ACCESSIBLE); >- if(!this.insideQualifiedReference) { >- relevance += computeRelevanceForQualification(isQualified); >- } >- if (staticFieldsAndMethodOnly && this.insideQualifiedReference) relevance += R_NON_INHERITED; // This criterion doesn't concern types and is added to be balanced with field and method relevance. >+ // if (this.field instanceof X) this.field.| >+ if (instanceOfExpression.expression instanceof FieldReference) { >+ FieldReference fieldReference2 = (FieldReference)instanceOfExpression.expression; > >- if (memberType.isAnnotationType()) { >- relevance += computeRelevanceForAnnotation(); >- relevance += computeRelevanceForAnnotationTarget(memberType); >- } else if (memberType.isClass()) { >- relevance += computeRelevanceForClass(); >- relevance += computeRelevanceForException(memberType.sourceName); >- } else if(memberType.isEnum()) { >- relevance += computeRelevanceForEnum(); >- } else if(memberType.isInterface()) { >- relevance += computeRelevanceForInterface(); >+ if (fieldReference2.receiver instanceof ThisReference && >+ fieldReference2.binding == fieldReference1.binding) { >+ findFromAnotherReceiver = true; >+ } >+ } > } >+ } > >- if (missingElements != null) { >- relevance += computeRelevanceForMissingElements(missingElementsHaveProblems); >- } >+ if (findFromAnotherReceiver) { >+ TypeBinding receiverTypeBinding = instanceOfType.resolvedType; >+ char[] castedReceiver = null; > >- this.noProposal = false; >- createTypeProposal( >- memberType, >- memberType.qualifiedSourceName(), >- IAccessRule.K_ACCESSIBLE, >- completionName, >- relevance, >- missingElements, >- missingElementsStarts, >- missingElementsEnds, >- missingElementsHaveProblems); >- } >- } >+ char[] castedTypeChars = CharOperation.concatWith(instanceOfType.getTypeName(), '.'); >+ if(this.source != null) { >+ int memberRefStart = this.startPosition; > >- protected void findMemberTypes( >- char[] typeName, >- ReferenceBinding receiverType, >- Scope scope, >- SourceTypeBinding typeInvocation, >- boolean staticOnly, >- boolean staticFieldsAndMethodOnly, >- ObjectVector typesFound, >- Binding[] missingElements, >- int[] missingElementsStarts, >- int[] missingElementsEnds, >- boolean missingElementsHaveProblems) { >- findMemberTypes( >- typeName, >- receiverType, >- scope, >- typeInvocation, >- staticOnly, >- staticFieldsAndMethodOnly, >- false, >- false, >- false, >- null, >- typesFound, >- missingElements, >- missingElementsStarts, >- missingElementsEnds, >- missingElementsHaveProblems); >- } >- private void findMemberTypes( >- char[] typeName, >- ReferenceBinding receiverType, >- Scope scope, >- SourceTypeBinding typeInvocation, >- boolean staticOnly, >- boolean staticFieldsAndMethodOnly, >- boolean fromStaticImport, >- boolean checkQualification, >- boolean proposeAllMemberTypes, >- SourceTypeBinding typeToIgnore, >- ObjectVector typesFound, >- Binding[] missingElements, >- int[] missingElementsStarts, >- int[] missingElementsEnds, >- boolean missingElementsHaveProblems) { >+ char[] receiverChars = CharOperation.subarray(this.source, receiverStart, receiverEnd); >+ char[] dotChars = CharOperation.subarray(this.source, receiverEnd, memberRefStart); > >- ReferenceBinding currentType = receiverType; >- if (typeName == null) >- return; >+ castedReceiver = >+ CharOperation.concat( >+ CharOperation.concat( >+ '(', >+ CharOperation.concat( >+ CharOperation.concat('(', castedTypeChars, ')'), >+ receiverChars), >+ ')'), >+ dotChars); >+ } else { >+ castedReceiver = >+ CharOperation.concat( >+ CharOperation.concat( >+ '(', >+ CharOperation.concat( >+ CharOperation.concat('(', castedTypeChars, ')'), >+ CharOperation.concatWith(receiverName, '.')), >+ ')'), >+ DOT); >+ } > >- if (this.insideQualifiedReference >- || typeName.length == 0) { // do not search up the hierarchy >+ if (castedReceiver == null) return; > >- findMemberTypes( >- typeName, >- currentType.memberTypes(), >- typesFound, >- receiverType, >- typeInvocation, >- staticOnly, >- staticFieldsAndMethodOnly, >- fromStaticImport, >- checkQualification, >- scope, >- missingElements, >- missingElementsStarts, >- missingElementsEnds, >- missingElementsHaveProblems); >- return; >- } >+ int oldStartPosition = this.startPosition; >+ this.startPosition = receiverStart; > >- ReferenceBinding[] interfacesToVisit = null; >- int nextPosition = 0; >+ findFieldsAndMethods( >+ this.completionToken, >+ receiverTypeBinding, >+ scope, >+ fieldsFound, >+ methodsFound, >+ invocationSite, >+ invocationScope, >+ false, >+ false, >+ null, >+ null, >+ null, >+ false, >+ castedReceiver, >+ receiverStart, >+ receiverEnd); > >- do { >- ReferenceBinding[] itsInterfaces = currentType.superInterfaces(); >- if (itsInterfaces != null && itsInterfaces != Binding.NO_SUPERINTERFACES) { >- if (interfacesToVisit == null) { >- interfacesToVisit = itsInterfaces; >- nextPosition = interfacesToVisit.length; >- } else { >- int itsLength = itsInterfaces.length; >- if (nextPosition + itsLength >= interfacesToVisit.length) >- System.arraycopy(interfacesToVisit, 0, interfacesToVisit = new ReferenceBinding[nextPosition + itsLength + 5], 0, nextPosition); >- nextInterface : for (int a = 0; a < itsLength; a++) { >- ReferenceBinding next = itsInterfaces[a]; >- for (int b = 0; b < nextPosition; b++) >- if (next == interfacesToVisit[b]) continue nextInterface; >- interfacesToVisit[nextPosition++] = next; >- } >- } >- } >+ this.startPosition = oldStartPosition; >+ } >+ } >+ private void findFieldsAndMethodsFromFavorites( >+ char[] token, >+ Scope scope, >+ InvocationSite invocationSite, >+ Scope invocationScope, >+ ObjectVector localsFound, >+ ObjectVector fieldsFound, >+ ObjectVector methodsFound) { > >- findMemberTypes( >- typeName, >- currentType.memberTypes(), >- typesFound, >- receiverType, >- typeInvocation, >- staticOnly, >- staticFieldsAndMethodOnly, >- fromStaticImport, >- checkQualification, >- scope, >- missingElements, >- missingElementsStarts, >- missingElementsEnds, >- missingElementsHaveProblems); >+ ObjectVector methodsFoundFromFavorites = new ObjectVector(); > >- currentType = currentType.superclass(); >- } while (currentType != null); >+ ImportBinding[] favoriteBindings = getFavoriteReferenceBindings(invocationScope); > >- if(proposeAllMemberTypes) { >- ReferenceBinding[] memberTypes = receiverType.memberTypes(); >- for (int i = 0; i < memberTypes.length; i++) { >- if(memberTypes[i] != typeToIgnore) { >- findSubMemberTypes( >- typeName, >- memberTypes[i], >- scope, >- typeInvocation, >- staticOnly, >- staticFieldsAndMethodOnly, >- fromStaticImport, >- typesFound); >+ if (favoriteBindings != null && favoriteBindings.length > 0) { >+ for (int i = 0; i < favoriteBindings.length; i++) { >+ ImportBinding favoriteBinding = favoriteBindings[i]; >+ switch (favoriteBinding.resolvedImport.kind()) { >+ case Binding.FIELD: >+ FieldBinding fieldBinding = (FieldBinding) favoriteBinding.resolvedImport; >+ findFieldsFromFavorites( >+ token, >+ new FieldBinding[]{fieldBinding}, >+ scope, >+ fieldsFound, >+ localsFound, >+ fieldBinding.declaringClass, >+ invocationSite, >+ invocationScope); >+ break; >+ case Binding.METHOD: >+ MethodBinding methodBinding = (MethodBinding) favoriteBinding.resolvedImport; >+ MethodBinding[] methods = methodBinding.declaringClass.availableMethods(); >+ long range; >+ if ((range = ReferenceBinding.binarySearch(methodBinding.selector, methods)) >= 0) { >+ int start = (int) range, end = (int) (range >> 32); >+ int length = end - start + 1; >+ System.arraycopy(methods, start, methods = new MethodBinding[length], 0, length); >+ } else { >+ methods = Binding.NO_METHODS; >+ } >+ findLocalMethodsFromFavorites( >+ token, >+ methods, >+ scope, >+ methodsFound, >+ methodsFoundFromFavorites, >+ methodBinding.declaringClass, >+ invocationSite, >+ invocationScope); >+ break; >+ case Binding.TYPE: >+ ReferenceBinding referenceBinding = (ReferenceBinding) favoriteBinding.resolvedImport; >+ if(favoriteBinding.onDemand) { >+ findFieldsFromFavorites( >+ token, >+ referenceBinding.availableFields(), >+ scope, >+ fieldsFound, >+ localsFound, >+ referenceBinding, >+ invocationSite, >+ invocationScope); >+ >+ findLocalMethodsFromFavorites( >+ token, >+ referenceBinding.availableMethods(), >+ scope, >+ methodsFound, >+ methodsFoundFromFavorites, >+ referenceBinding, >+ invocationSite, >+ invocationScope); >+ } >+ break; > } > } > } > >- if (interfacesToVisit != null) { >- for (int i = 0; i < nextPosition; i++) { >- ReferenceBinding anInterface = interfacesToVisit[i]; >- findMemberTypes( >- typeName, >- anInterface.memberTypes(), >- typesFound, >- receiverType, >- typeInvocation, >- staticOnly, >- staticFieldsAndMethodOnly, >- fromStaticImport, >- checkQualification, >- scope, >- missingElements, >- missingElementsStarts, >- missingElementsEnds, >- missingElementsHaveProblems); >+ methodsFound.addAll(methodsFoundFromFavorites); >+ } > >- ReferenceBinding[] itsInterfaces = anInterface.superInterfaces(); >- if (itsInterfaces != null && itsInterfaces != Binding.NO_SUPERINTERFACES) { >- int itsLength = itsInterfaces.length; >- if (nextPosition + itsLength >= interfacesToVisit.length) >- System.arraycopy(interfacesToVisit, 0, interfacesToVisit = new ReferenceBinding[nextPosition + itsLength + 5], 0, nextPosition); >- nextInterface : for (int a = 0; a < itsLength; a++) { >- ReferenceBinding next = itsInterfaces[a]; >- for (int b = 0; b < nextPosition; b++) >- if (next == interfacesToVisit[b]) continue nextInterface; >- interfacesToVisit[nextPosition++] = next; >+ private boolean findFieldsAndMethodsFromMissingFieldType( >+ char[] token, >+ Scope scope, >+ InvocationSite invocationSite, >+ boolean insideTypeAnnotation) { >+ >+ boolean foundSomeFields = false; >+ >+ boolean staticsOnly = false; >+ Scope currentScope = scope; >+ >+ done : while (true) { // done when a COMPILATION_UNIT_SCOPE is found >+ >+ switch (currentScope.kind) { >+ >+ case Scope.METHOD_SCOPE : >+ // handle the error case inside an explicit constructor call (see MethodScope>>findField) >+ MethodScope methodScope = (MethodScope) currentScope; >+ staticsOnly |= methodScope.isStatic | methodScope.isConstructorCall; >+ break; >+ case Scope.CLASS_SCOPE : >+ ClassScope classScope = (ClassScope) currentScope; >+ SourceTypeBinding enclosingType = classScope.referenceContext.binding; >+ if(!insideTypeAnnotation) { >+ >+ FieldDeclaration[] fields = classScope.referenceContext.fields; >+ >+ int fieldsCount = fields == null ? 0 : fields.length; >+ for (int i = 0; i < fieldsCount; i++) { >+ FieldDeclaration fieldDeclaration = fields[i]; >+ if (CharOperation.equals(fieldDeclaration.name, token)) { >+ FieldBinding fieldBinding = fieldDeclaration.binding; >+ if (fieldBinding == null || fieldBinding.type == null || (fieldBinding.type.tagBits & TagBits.HasMissingType) != 0) { >+ foundSomeFields = true; >+ findFieldsAndMethodsFromMissingType( >+ fieldDeclaration.type, >+ currentScope, >+ invocationSite, >+ scope); >+ } >+ break done; >+ } >+ } > } >- } >+ staticsOnly |= enclosingType.isStatic(); >+ insideTypeAnnotation = false; >+ break; >+ case Scope.COMPILATION_UNIT_SCOPE : >+ break done; > } >+ currentScope = currentScope.parent; > } >+ return foundSomeFields; > } > >- private void findMemberTypesFromMissingType( >- char[] typeName, >- final long pos, >- final Scope scope) { >- MissingTypesGuesser missingTypesConverter = new MissingTypesGuesser(this); >- MissingTypesGuesser.GuessedTypeRequestor substitutionRequestor = >- new MissingTypesGuesser.GuessedTypeRequestor() { >- public void accept( >- TypeBinding guessedType, >- Binding[] missingElements, >- int[] missingElementsStarts, >- int[] missingElementsEnds, >- boolean hasProblems) { >- if (guessedType instanceof ReferenceBinding) { >- findMemberTypes( >- CompletionEngine.this.completionToken, >- (ReferenceBinding)guessedType, >- scope, >- scope.enclosingSourceType(), >- false, >- false, >- new ObjectVector(), >- missingElements, >- missingElementsStarts, >- missingElementsEnds, >- hasProblems); >+ private void findFieldsAndMethodsFromMissingReturnType( >+ char[] token, >+ TypeBinding[] arguments, >+ Scope scope, >+ InvocationSite invocationSite, >+ boolean insideTypeAnnotation) { >+ >+ boolean staticsOnly = false; >+ Scope currentScope = scope; >+ >+ done : while (true) { // done when a COMPILATION_UNIT_SCOPE is found >+ >+ switch (currentScope.kind) { >+ >+ case Scope.METHOD_SCOPE : >+ // handle the error case inside an explicit constructor call (see MethodScope>>findField) >+ MethodScope methodScope = (MethodScope) currentScope; >+ staticsOnly |= methodScope.isStatic | methodScope.isConstructorCall; >+ break; >+ case Scope.CLASS_SCOPE : >+ ClassScope classScope = (ClassScope) currentScope; >+ SourceTypeBinding enclosingType = classScope.referenceContext.binding; >+ if(!insideTypeAnnotation) { >+ >+ AbstractMethodDeclaration[] methods = classScope.referenceContext.methods; >+ >+ int methodsCount = methods == null ? 0 : methods.length; >+ for (int i = 0; i < methodsCount; i++) { >+ AbstractMethodDeclaration methodDeclaration = methods[i]; >+ if (methodDeclaration instanceof MethodDeclaration && >+ CharOperation.equals(methodDeclaration.selector, token)) { >+ MethodDeclaration method = (MethodDeclaration) methodDeclaration; >+ MethodBinding methodBinding = method.binding; >+ if (methodBinding == null || methodBinding.returnType == null || (methodBinding.returnType.tagBits & TagBits.HasMissingType) != 0) { >+ Argument[] parameters = method.arguments; >+ int parametersLength = parameters == null ? 0 : parameters.length; >+ int argumentsLength = arguments == null ? 0 : arguments.length; >+ >+ if (parametersLength == 0) { >+ if (argumentsLength == 0) { >+ findFieldsAndMethodsFromMissingType( >+ method.returnType, >+ currentScope, >+ invocationSite, >+ scope); >+ break done; >+ } >+ } else { >+ TypeBinding[] parametersBindings; >+ if (methodBinding == null) { // since no binding, extra types from type references >+ parametersBindings = new TypeBinding[parametersLength]; >+ for (int j = 0; j < parametersLength; j++) { >+ TypeBinding parameterType = parameters[j].type.resolvedType; >+ if (!parameterType.isValidBinding() && parameterType.closestMatch() != null) { >+ parameterType = parameterType.closestMatch(); >+ } >+ parametersBindings[j] = parameterType; >+ } >+ } else { >+ parametersBindings = methodBinding.parameters; >+ } >+ if(areParametersCompatibleWith(parametersBindings, arguments, parameters[parametersLength - 1].isVarArgs())) { >+ findFieldsAndMethodsFromMissingType( >+ method.returnType, >+ currentScope, >+ invocationSite, >+ scope); >+ break done; >+ } >+ } >+ } >+ >+ } >+ } > } >- } >- }; >- SingleTypeReference typeRef = new SingleTypeReference(typeName, pos); >- typeRef.resolvedType = new ProblemReferenceBinding(new char[][]{ typeName }, null, ProblemReasons.NotFound); >- missingTypesConverter.guess(typeRef, scope, substitutionRequestor); >+ staticsOnly |= enclosingType.isStatic(); >+ insideTypeAnnotation = false; >+ break; >+ case Scope.COMPILATION_UNIT_SCOPE : >+ break done; >+ } >+ currentScope = currentScope.parent; >+ } > } > >- private void findMemberTypesFromMissingType( >+ private void findFieldsAndMethodsFromMissingType( > TypeReference typeRef, >- final long pos, >- final Scope scope) { >+ final Scope scope, >+ final InvocationSite invocationSite, >+ final Scope invocationScope) { > MissingTypesGuesser missingTypesConverter = new MissingTypesGuesser(this); > MissingTypesGuesser.GuessedTypeRequestor substitutionRequestor = > new MissingTypesGuesser.GuessedTypeRequestor() { >@@ -5686,211 +5888,296 @@ > int[] missingElementsStarts, > int[] missingElementsEnds, > boolean hasProblems) { >- if (guessedType instanceof ReferenceBinding) { >- findMemberTypes( >- CompletionEngine.this.completionToken, >- (ReferenceBinding)guessedType, >- scope, >- scope.enclosingSourceType(), >- false, >- false, >- new ObjectVector(), >- missingElements, >- missingElementsStarts, >- missingElementsEnds, >- hasProblems); >- } >+ findFieldsAndMethods( >+ CompletionEngine.this.completionToken, >+ guessedType, >+ scope, >+ new ObjectVector(), >+ new ObjectVector(), >+ invocationSite, >+ invocationScope, >+ false, >+ false, >+ missingElements, >+ missingElementsStarts, >+ missingElementsEnds, >+ hasProblems, >+ null, >+ -1, >+ -1); >+ > } > }; > missingTypesConverter.guess(typeRef, scope, substitutionRequestor); > } > >- /* >- * Find javadoc parameter names. >- */ >- private void findJavadocParamNames(char[] token, char[][] missingParams, boolean isTypeParam) { >- >- if (missingParams == null) return; >- >- // Get relevance >- int relevance = computeBaseRelevance(); >- relevance += computeRelevanceForInterestingProposal(); >- relevance += computeRelevanceForRestrictions(IAccessRule.K_ACCESSIBLE); // no access restriction for param name >- if (!isTypeParam) relevance += R_INTERESTING; >- >- // Propose missing param >- int length = missingParams.length; >- relevance += length; >- for (int i=0; i<length; i++) { >- char[] argName = missingParams[i]; >- if (token == null || CharOperation.prefixEquals(token, argName)) { >- >- this.noProposal = false; >- if (!this.requestor.isIgnored(CompletionProposal.JAVADOC_PARAM_REF)) { >- InternalCompletionProposal proposal = createProposal(CompletionProposal.JAVADOC_PARAM_REF, this.actualCompletionPosition); >- proposal.setName(argName); >- char[] completion = isTypeParam ? CharOperation.concat('<', argName, '>') : argName; >- proposal.setCompletion(completion); >- proposal.setReplaceRange(this.startPosition - this.offset, this.endPosition - this.offset); >- proposal.setTokenRange(this.tokenStart - this.offset, this.tokenEnd - this.offset); >- proposal.setRelevance(--relevance); >- this.requestor.accept(proposal); >- if (DEBUG) { >- this.printDebug(proposal); >- } >+ private void findFieldsAndMethodsFromStaticImports( >+ char[] token, >+ Scope scope, >+ InvocationSite invocationSite, >+ Scope invocationScope, >+ boolean exactMatch, >+ boolean insideAnnotationAttribute, >+ ObjectVector localsFound, >+ ObjectVector fieldsFound, >+ ObjectVector methodsFound, >+ boolean proposeField, >+ boolean proposeMethod) { >+ // search in static import >+ ImportBinding[] importBindings = scope.compilationUnitScope().imports; >+ for (int i = 0; i < importBindings.length; i++) { >+ ImportBinding importBinding = importBindings[i]; >+ if(importBinding.isValidBinding() && importBinding.isStatic()) { >+ Binding binding = importBinding.resolvedImport; >+ if(binding != null && binding.isValidBinding()) { >+ if(importBinding.onDemand) { >+ if((binding.kind() & Binding.TYPE) != 0) { >+ if(proposeField) { >+ findFields( >+ token, >+ (ReferenceBinding)binding, >+ scope, >+ fieldsFound, >+ localsFound, >+ true, >+ invocationSite, >+ invocationScope, >+ true, >+ false, >+ null, >+ null, >+ null, >+ false, >+ null, >+ -1, >+ -1); >+ } >+ if(proposeMethod && !insideAnnotationAttribute) { >+ findMethods( >+ token, >+ null, >+ null, >+ (ReferenceBinding)binding, >+ scope, >+ methodsFound, >+ true, >+ exactMatch, >+ invocationSite, >+ invocationScope, >+ true, >+ false, >+ false, >+ null, >+ null, >+ null, >+ false, >+ null, >+ -1, >+ -1); >+ } >+ } >+ } else { >+ if ((binding.kind() & Binding.FIELD) != 0) { >+ if(proposeField) { >+ findFields( >+ token, >+ new FieldBinding[]{(FieldBinding)binding}, >+ scope, >+ fieldsFound, >+ localsFound, >+ true, >+ ((FieldBinding)binding).declaringClass, >+ invocationSite, >+ invocationScope, >+ true, >+ false, >+ null, >+ null, >+ null, >+ false, >+ null, >+ -1, >+ -1); >+ } >+ } else if ((binding.kind() & Binding.METHOD) != 0) { >+ if(proposeMethod && !insideAnnotationAttribute) { >+ MethodBinding methodBinding = (MethodBinding)binding; >+ if ((exactMatch && CharOperation.equals(token, methodBinding.selector)) || >+ !exactMatch && CharOperation.prefixEquals(token, methodBinding.selector)) { >+ >+ findLocalMethodsFromStaticImports( >+ methodBinding.selector, >+ methodBinding.declaringClass.methods(), >+ scope, >+ exactMatch, >+ methodsFound, >+ methodBinding.declaringClass, >+ invocationSite); >+ } >+ } >+ } >+ } > } > } > } > } > >- private void findSubMemberTypes( >- char[] typeName, >- ReferenceBinding receiverType, >- Scope scope, >- SourceTypeBinding typeInvocation, >- boolean staticOnly, >- boolean staticFieldsAndMethodOnly, >- boolean fromStaticImport, >- ObjectVector typesFound) { >+ private void findFieldsFromFavorites( >+ char[] fieldName, >+ FieldBinding[] fields, >+ Scope scope, >+ ObjectVector fieldsFound, >+ ObjectVector localsFound, >+ ReferenceBinding receiverType, >+ InvocationSite invocationSite, >+ Scope invocationScope) { > >- ReferenceBinding currentType = receiverType; >- if (typeName == null || typeName.length == 0) >- return; >+ char[] typeName = CharOperation.concatWith(receiverType.compoundName, '.'); > >- if (this.assistNodeIsSuperType && !this.insideQualifiedReference && isForbidden(currentType)) return; // we're trying to find a supertype >+ int fieldLength = fieldName.length; >+ next : for (int f = fields.length; --f >= 0;) { >+ FieldBinding field = fields[f]; > >- findMemberTypes( >- typeName, >- currentType.memberTypes(), >- typesFound, >- receiverType, >- typeInvocation, >- staticOnly, >- staticFieldsAndMethodOnly, >- fromStaticImport, >- true, >- scope, >- null, >- null, >- null, >- false); >+ if (field.isSynthetic()) continue next; > >- ReferenceBinding[] memberTypes = receiverType.memberTypes(); >- next : for (int i = 0; i < memberTypes.length; i++) { >- if (this.options.checkVisibility) { >- if (typeInvocation != null && !memberTypes[i].canBeSeenBy(receiverType, typeInvocation)) { >- continue next; >- } else if(typeInvocation == null && !memberTypes[i].canBeSeenBy(this.unitScope.fPackage)) { >- continue next; >- } >- } >- findSubMemberTypes( >- typeName, >- memberTypes[i], >- scope, >- typeInvocation, >- staticOnly, >- staticFieldsAndMethodOnly, >- fromStaticImport, >- typesFound); >- } >- } >+ // only static fields must be proposed >+ if (!field.isStatic()) continue next; > >- private void findInterfacesMethods( >- char[] selector, >- TypeBinding[] typeArgTypes, >- TypeBinding[] argTypes, >- ReferenceBinding receiverType, >- ReferenceBinding[] itsInterfaces, >- Scope scope, >- ObjectVector methodsFound, >- boolean onlyStaticMethods, >- boolean exactMatch, >- boolean isCompletingDeclaration, >- InvocationSite invocationSite, >- Scope invocationScope, >- boolean implicitCall, >- boolean superCall, >- boolean canBePrefixed, >- Binding[] missingElements, >- int[] missingElementssStarts, >- int[] missingElementsEnds, >- boolean missingElementsHaveProblems, >- char[] castedReceiver, >- int receiverStart, >- int receiverEnd) { >+ if (fieldLength > field.name.length) continue next; > >- if (selector == null) >- return; >+ if (!CharOperation.prefixEquals(fieldName, field.name, false /* ignore case */) >+ && !(this.options.camelCaseMatch && CharOperation.camelCaseMatch(fieldName, field.name))) continue next; > >- if (itsInterfaces != Binding.NO_SUPERINTERFACES) { >- ReferenceBinding[] interfacesToVisit = itsInterfaces; >- int nextPosition = interfacesToVisit.length; >+ if (this.options.checkDeprecation && >+ field.isViewedAsDeprecated() && >+ !scope.isDefinedInSameUnit(field.declaringClass)) >+ continue next; > >- for (int i = 0; i < nextPosition; i++) { >- ReferenceBinding currentType = interfacesToVisit[i]; >- MethodBinding[] methods = currentType.availableMethods(); >- if(methods != null) { >- if(isCompletingDeclaration) { >- findLocalMethodDeclarations( >- selector, >- methods, >- scope, >- methodsFound, >- exactMatch, >- receiverType); >- } else { >- findLocalMethods( >- selector, >- typeArgTypes, >- argTypes, >- methods, >- scope, >- methodsFound, >- onlyStaticMethods, >- exactMatch, >- receiverType, >- invocationSite, >- invocationScope, >- implicitCall, >- superCall, >- canBePrefixed, >- missingElements, >- missingElementssStarts, >- missingElementsEnds, >- missingElementsHaveProblems, >- castedReceiver, >- receiverStart, >- receiverEnd); >- } >- } >+ if (this.options.checkVisibility >+ && !field.canBeSeenBy(receiverType, invocationSite, scope)) continue next; > >- itsInterfaces = currentType.superInterfaces(); >- if (itsInterfaces != null && itsInterfaces != Binding.NO_SUPERINTERFACES) { >- int itsLength = itsInterfaces.length; >- if (nextPosition + itsLength >= interfacesToVisit.length) >- System.arraycopy(interfacesToVisit, 0, interfacesToVisit = new ReferenceBinding[nextPosition + itsLength + 5], 0, nextPosition); >- nextInterface : for (int a = 0; a < itsLength; a++) { >- ReferenceBinding next = itsInterfaces[a]; >- for (int b = 0; b < nextPosition; b++) >- if (next == interfacesToVisit[b]) continue nextInterface; >- interfacesToVisit[nextPosition++] = next; >- } >- } >+ for (int i = fieldsFound.size; --i >= 0;) { >+ Object[] other = (Object[])fieldsFound.elementAt(i); >+ FieldBinding otherField = (FieldBinding) other[0]; >+ >+ if (field == otherField) continue next; > } >- } >- } > >- private void findImplicitMessageSends( >- char[] token, >- TypeBinding[] argTypes, >- Scope scope, >- InvocationSite invocationSite, >- Scope invocationScope, >- ObjectVector methodsFound) { >+ fieldsFound.add(new Object[]{field, receiverType}); > >- if (token == null) >- return; >+ int relevance = computeBaseRelevance(); >+ relevance += computeRelevanceForResolution(); >+ relevance += computeRelevanceForInterestingProposal(field); >+ if (fieldName != null) relevance += computeRelevanceForCaseMatching(fieldName, field.name); >+ relevance += computeRelevanceForExpectingType(field.type); >+ relevance += computeRelevanceForEnumConstant(field.type); >+ relevance += computeRelevanceForStatic(true, true); >+ relevance += computeRelevanceForRestrictions(IAccessRule.K_ACCESSIBLE); >+ >+ CompilationUnitDeclaration cu = this.unitScope.referenceContext; >+ int importStart = cu.types[0].declarationSourceStart; >+ int importEnd = importStart; >+ >+ this.noProposal = false; >+ >+ if (this.compilerOptions.complianceLevel < ClassFileConstants.JDK1_5 || >+ !this.options.suggestStaticImport) { >+ if (!this.isIgnored(CompletionProposal.FIELD_REF, CompletionProposal.TYPE_IMPORT)) { >+ char[] completion = CharOperation.concat(receiverType.sourceName, field.name, '.'); >+ >+ InternalCompletionProposal proposal = createProposal(CompletionProposal.FIELD_REF, this.actualCompletionPosition); >+ proposal.setDeclarationSignature(getSignature(field.declaringClass)); >+ proposal.setSignature(getSignature(field.type)); >+ proposal.setDeclarationPackageName(field.declaringClass.qualifiedPackageName()); >+ proposal.setDeclarationTypeName(field.declaringClass.qualifiedSourceName()); >+ proposal.setPackageName(field.type.qualifiedPackageName()); >+ proposal.setTypeName(field.type.qualifiedSourceName()); >+ proposal.setName(field.name); >+ proposal.setCompletion(completion); >+ proposal.setFlags(field.modifiers); >+ proposal.setReplaceRange(this.startPosition - this.offset, this.endPosition - this.offset); >+ proposal.setTokenRange(this.tokenStart - this.offset, this.tokenEnd - this.offset); >+ proposal.setRelevance(relevance); >+ >+ char[] typeImportCompletion = createImportCharArray(typeName, false, false); >+ >+ InternalCompletionProposal typeImportProposal = createProposal(CompletionProposal.TYPE_IMPORT, this.actualCompletionPosition); >+ typeImportProposal.nameLookup = this.nameEnvironment.nameLookup; >+ typeImportProposal.completionEngine = this; >+ char[] packageName = receiverType.qualifiedPackageName(); >+ typeImportProposal.setDeclarationSignature(packageName); >+ typeImportProposal.setSignature(getSignature(receiverType)); >+ typeImportProposal.setPackageName(packageName); >+ typeImportProposal.setTypeName(receiverType.qualifiedSourceName()); >+ typeImportProposal.setCompletion(typeImportCompletion); >+ typeImportProposal.setFlags(receiverType.modifiers); >+ typeImportProposal.setAdditionalFlags(CompletionFlags.Default); >+ typeImportProposal.setReplaceRange(importStart - this.offset, importEnd - this.offset); >+ typeImportProposal.setTokenRange(importStart - this.offset, importEnd - this.offset); >+ typeImportProposal.setRelevance(relevance); >+ >+ proposal.setRequiredProposals(new CompletionProposal[]{typeImportProposal}); >+ >+ this.requestor.accept(proposal); >+ if(DEBUG) { >+ this.printDebug(proposal); >+ } >+ } >+ } else { >+ if (!this.isIgnored(CompletionProposal.FIELD_REF, CompletionProposal.FIELD_IMPORT)) { >+ char[] completion = field.name; >+ >+ InternalCompletionProposal proposal = createProposal(CompletionProposal.FIELD_REF, this.actualCompletionPosition); >+ proposal.setDeclarationSignature(getSignature(field.declaringClass)); >+ proposal.setSignature(getSignature(field.type)); >+ proposal.setDeclarationPackageName(field.declaringClass.qualifiedPackageName()); >+ proposal.setDeclarationTypeName(field.declaringClass.qualifiedSourceName()); >+ proposal.setPackageName(field.type.qualifiedPackageName()); >+ proposal.setTypeName(field.type.qualifiedSourceName()); >+ proposal.setName(field.name); >+ proposal.setCompletion(completion); >+ proposal.setFlags(field.modifiers); >+ proposal.setReplaceRange(this.startPosition - this.offset, this.endPosition - this.offset); >+ proposal.setTokenRange(this.tokenStart - this.offset, this.tokenEnd - this.offset); >+ proposal.setRelevance(relevance); >+ >+ char[] fieldImportCompletion = createImportCharArray(CharOperation.concat(typeName, field.name, '.'), true, false); >+ >+ InternalCompletionProposal fieldImportProposal = createProposal(CompletionProposal.FIELD_IMPORT, this.actualCompletionPosition); >+ fieldImportProposal.setDeclarationSignature(getSignature(field.declaringClass)); >+ fieldImportProposal.setSignature(getSignature(field.type)); >+ fieldImportProposal.setDeclarationPackageName(field.declaringClass.qualifiedPackageName()); >+ fieldImportProposal.setDeclarationTypeName(field.declaringClass.qualifiedSourceName()); >+ fieldImportProposal.setPackageName(field.type.qualifiedPackageName()); >+ fieldImportProposal.setTypeName(field.type.qualifiedSourceName()); >+ fieldImportProposal.setName(field.name); >+ fieldImportProposal.setCompletion(fieldImportCompletion); >+ fieldImportProposal.setFlags(field.modifiers); >+ fieldImportProposal.setAdditionalFlags(CompletionFlags.StaticImport); >+ fieldImportProposal.setReplaceRange(importStart - this.offset, importEnd - this.offset); >+ fieldImportProposal.setTokenRange(importStart - this.offset, importEnd - this.offset); >+ fieldImportProposal.setRelevance(relevance); >+ >+ proposal.setRequiredProposals(new CompletionProposal[]{fieldImportProposal}); >+ >+ this.requestor.accept(proposal); >+ if(DEBUG) { >+ this.printDebug(proposal); >+ } >+ } >+ } >+ } >+ } >+ private void findImplicitMessageSends( >+ char[] token, >+ TypeBinding[] argTypes, >+ Scope scope, >+ InvocationSite invocationSite, >+ Scope invocationScope, >+ ObjectVector methodsFound) { >+ >+ if (token == null) >+ return; > > boolean staticsOnly = false; > // need to know if we're in a static context (or inside a constructor) >@@ -5917,7 +6204,6 @@ > methodsFound, > staticsOnly, > true, >- false, > invocationSite, > invocationScope, > true, >@@ -5939,137 +6225,188 @@ > scope = scope.parent; > } > } >+ private void findImports(CompletionOnImportReference importReference, boolean findMembers) { >+ char[][] tokens = importReference.tokens; > >- // Helper method for findMethods(char[], TypeBinding[], ReferenceBinding, Scope, ObjectVector, boolean, boolean, boolean) >- private void findLocalMethods( >- char[] methodName, >- TypeBinding[] typeArgTypes, >- TypeBinding[] argTypes, >- MethodBinding[] methods, >- Scope scope, >- ObjectVector methodsFound, >- boolean onlyStaticMethods, >- boolean exactMatch, >- ReferenceBinding receiverType, >- InvocationSite invocationSite, >- Scope invocationScope, >- boolean implicitCall, >- boolean superCall, >- boolean canBePrefixed, >- Binding[] missingElements, >- int[] missingElementsStarts, >- int[] missingElementsEnds, >- boolean missingElementsHaveProblems, >- char[] castedReceiver, >- int receiverStart, >- int receiverEnd) { >+ char[] importName = CharOperation.concatWith(tokens, '.'); > >- ObjectVector newMethodsFound = new ObjectVector(); >- // Inherited methods which are hidden by subclasses are filtered out >- // No visibility checks can be performed without the scope & invocationSite >+ if (importName.length == 0) >+ return; > >- int methodLength = methodName.length; >- int minTypeArgLength = typeArgTypes == null ? 0 : typeArgTypes.length; >- int minArgLength = argTypes == null ? 0 : argTypes.length; >+ char[] lastToken = tokens[tokens.length - 1]; >+ if(lastToken != null && lastToken.length == 0) >+ importName = CharOperation.concat(importName, new char[]{'.'}); > >- next : for (int f = methods.length; --f >= 0;) { >- MethodBinding method = methods[f]; >+ this.resolvingImports = true; >+ this.resolvingStaticImports = importReference.isStatic(); > >- if (method.isSynthetic()) continue next; >+ this.completionToken = lastToken; >+ this.qualifiedCompletionToken = importName; > >- if (method.isDefaultAbstract()) continue next; >+ // want to replace the existing .*; >+ if(!this.requestor.isIgnored(CompletionProposal.PACKAGE_REF)) { >+ int oldStart = this.startPosition; >+ int oldEnd = this.endPosition; >+ setSourceRange( >+ importReference.sourceStart, >+ importReference.declarationSourceEnd); >+ this.nameEnvironment.findPackages(importName, this); >+ setSourceRange( >+ oldStart, >+ oldEnd - 1, >+ false); >+ } >+ if(!this.requestor.isIgnored(CompletionProposal.TYPE_REF)) { >+ this.foundTypesCount = 0; >+ this.nameEnvironment.findTypes( >+ importName, >+ findMembers, >+ this.options.camelCaseMatch, >+ IJavaSearchConstants.TYPE, >+ this); >+ acceptTypes(null); >+ } >+ } > >- if (method.isConstructor()) continue next; >+ private void findImportsOfMemberTypes(char[] typeName, ReferenceBinding ref, boolean onlyStatic) { >+ ReferenceBinding[] memberTypes = ref.memberTypes(); > >- if (this.options.checkDeprecation && >- method.isViewedAsDeprecated() && >- !scope.isDefinedInSameUnit(method.declaringClass)) >+ int typeLength = typeName.length; >+ next : for (int m = memberTypes.length; --m >= 0;) { >+ ReferenceBinding memberType = memberTypes[m]; >+ // if (!wantClasses && memberType.isClass()) continue next; >+ // if (!wantInterfaces && memberType.isInterface()) continue next; >+ >+ if (onlyStatic && !memberType.isStatic()) > continue next; > >- //TODO (david) perhaps the relevance of a void method must be lesser than other methods >- //if (expectedTypesPtr > -1 && method.returnType == BaseTypes.VoidBinding) continue next; >+ if (typeLength > memberType.sourceName.length) >+ continue next; > >- if (onlyStaticMethods && !method.isStatic()) continue next; >+ if (!CharOperation.prefixEquals(typeName, memberType.sourceName, false/* ignore case */) >+ && !(this.options.camelCaseMatch && CharOperation.camelCaseMatch(typeName, memberType.sourceName))) >+ continue next; > >- if (this.options.checkVisibility >- && !method.canBeSeenBy(receiverType, invocationSite, scope)) continue next; >+ if (this.options.checkDeprecation && memberType.isViewedAsDeprecated()) continue next; > >- if(superCall && method.isAbstract()) { >- methodsFound.add(new Object[]{method, receiverType}); >+ if (this.options.checkVisibility >+ && !memberType.canBeSeenBy(this.unitScope.fPackage)) > continue next; >- } > >- if (exactMatch) { >- if (!CharOperation.equals(methodName, method.selector, false /* ignore case */)) { >- continue next; >- } >- } else { >- if (methodLength > method.selector.length) continue next; >- if (!CharOperation.prefixEquals(methodName, method.selector, false /* ignore case */) >- && !(this.options.camelCaseMatch && CharOperation.camelCaseMatch(methodName, method.selector))) { >- continue next; >- } >- } >+ char[] completionName = CharOperation.concat(memberType.sourceName, SEMICOLON); > >- if (minTypeArgLength != 0 && minTypeArgLength != method.typeVariables.length) >- continue next; >+ int relevance = computeBaseRelevance(); >+ relevance += computeRelevanceForResolution(); >+ relevance += computeRelevanceForInterestingProposal(); >+ relevance += computeRelevanceForCaseMatching(typeName, memberType.sourceName); >+ relevance += computeRelevanceForRestrictions(IAccessRule.K_ACCESSIBLE); > >- if (minTypeArgLength != 0) { >- method = scope.environment().createParameterizedGenericMethod(method, typeArgTypes); >+ if (memberType.isClass()) { >+ relevance += computeRelevanceForClass(); >+ } else if(memberType.isEnum()) { >+ relevance += computeRelevanceForEnum(); >+ } else if (memberType.isInterface()) { >+ relevance += computeRelevanceForInterface(); >+ } >+ this.noProposal = false; >+ if(!this.requestor.isIgnored(CompletionProposal.TYPE_REF)) { >+ createTypeProposal( >+ memberType, >+ memberType.qualifiedSourceName(), >+ IAccessRule.K_ACCESSIBLE, >+ completionName, >+ relevance, >+ null, >+ null, >+ null, >+ false); > } >+ } >+ } > >- if (minArgLength > method.parameters.length) >+ private void findImportsOfStaticFields(char[] fieldName, ReferenceBinding ref) { >+ FieldBinding[] fields = ref.availableFields(); >+ >+ int fieldLength = fieldName.length; >+ next : for (int m = fields.length; --m >= 0;) { >+ FieldBinding field = fields[m]; >+ >+ if (fieldLength > field.name.length) > continue next; > >- for (int a = minArgLength; --a >= 0;){ >- if (argTypes[a] != null) { // can be null if it could not be resolved properly >- if (!argTypes[a].isCompatibleWith(method.parameters[a])) { >- continue next; >- } >- } >- } >+ if (field.isSynthetic()) >+ continue next; > >- boolean prefixRequired = false; >+ if (!field.isStatic()) >+ continue next; > >- for (int i = methodsFound.size; --i >= 0;) { >- Object[] other = (Object[]) methodsFound.elementAt(i); >- MethodBinding otherMethod = (MethodBinding) other[0]; >- ReferenceBinding otherReceiverType = (ReferenceBinding) other[1]; >- if (method == otherMethod && receiverType == otherReceiverType) >- continue next; >+ if (!CharOperation.prefixEquals(fieldName, field.name, false/* ignore case */) >+ && !(this.options.camelCaseMatch && CharOperation.camelCaseMatch(fieldName, field.name))) >+ continue next; > >- if (CharOperation.equals(method.selector, otherMethod.selector, true)) { >- if (receiverType == otherReceiverType) { >- if (this.lookupEnvironment.methodVerifier().isMethodSubsignature(otherMethod, method)) { >- if (!superCall || !otherMethod.declaringClass.isInterface()) { >- continue next; >- } >- } >- } else { >- if (this.lookupEnvironment.methodVerifier().isMethodSubsignature(otherMethod, method)) { >- if(receiverType.isAnonymousType()) continue next; >+ if (this.options.checkDeprecation && field.isViewedAsDeprecated()) continue next; > >- if(!superCall) { >- if(!canBePrefixed) continue next; >+ if (this.options.checkVisibility >+ && !field.canBeSeenBy(this.unitScope.fPackage)) >+ continue next; > >- prefixRequired = true; >- } >- } >- } >- } >- } >+ char[] completionName = CharOperation.concat(field.name, SEMICOLON); > >- newMethodsFound.add(new Object[]{method, receiverType}); >+ int relevance = computeBaseRelevance(); >+ relevance += computeRelevanceForResolution(); >+ relevance += computeRelevanceForInterestingProposal(); >+ relevance += computeRelevanceForCaseMatching(fieldName, field.name); >+ relevance += computeRelevanceForRestrictions(IAccessRule.K_ACCESSIBLE); > >- ReferenceBinding superTypeWithSameErasure = (ReferenceBinding)receiverType.findSuperTypeOriginatingFrom(method.declaringClass); >- if (method.declaringClass != superTypeWithSameErasure) { >- MethodBinding[] otherMethods = superTypeWithSameErasure.getMethods(method.selector); >- for (int i = 0; i < otherMethods.length; i++) { >- if(otherMethods[i].original() == method.original()) { >- method = otherMethods[i]; >- } >+ this.noProposal = false; >+ if(!this.requestor.isIgnored(CompletionProposal.FIELD_REF)) { >+ InternalCompletionProposal proposal = createProposal(CompletionProposal.FIELD_REF, this.actualCompletionPosition); >+ proposal.setDeclarationSignature(getSignature(field.declaringClass)); >+ proposal.setSignature(getSignature(field.type)); >+ proposal.setDeclarationPackageName(field.declaringClass.qualifiedPackageName()); >+ proposal.setDeclarationTypeName(field.declaringClass.qualifiedSourceName()); >+ proposal.setPackageName(field.type.qualifiedPackageName()); >+ proposal.setTypeName(field.type.qualifiedSourceName()); >+ proposal.setName(field.name); >+ proposal.setCompletion(completionName); >+ proposal.setFlags(field.modifiers); >+ proposal.setReplaceRange(this.startPosition - this.offset, this.endPosition - this.offset); >+ proposal.setTokenRange(this.tokenStart - this.offset, this.tokenEnd - this.offset); >+ proposal.setRelevance(relevance); >+ this.requestor.accept(proposal); >+ if(DEBUG) { >+ this.printDebug(proposal); > } > } >+ } >+ } >+ >+ private void findImportsOfStaticMethods(char[] methodName, ReferenceBinding ref) { >+ MethodBinding[] methods = ref.availableMethods(); >+ >+ int methodLength = methodName.length; >+ next : for (int m = methods.length; --m >= 0;) { >+ MethodBinding method = methods[m]; >+ >+ if (method.isSynthetic()) continue next; >+ >+ if (method.isDefaultAbstract()) continue next; >+ >+ if (method.isConstructor()) continue next; >+ >+ if (!method.isStatic()) continue next; >+ >+ if (this.options.checkDeprecation && method.isViewedAsDeprecated()) continue next; >+ >+ if (this.options.checkVisibility >+ && !method.canBeSeenBy(this.unitScope.fPackage)) continue next; >+ >+ if (methodLength > method.selector.length) >+ continue next; >+ >+ if (!CharOperation.prefixEquals(methodName, method.selector, false/* ignore case */) >+ && !(this.options.camelCaseMatch && CharOperation.camelCaseMatch(methodName, method.selector))) >+ continue next; > > int length = method.parameters.length; > char[][] parameterPackageNames = new char[length][]; >@@ -6082,647 +6419,552 @@ > } > char[][] parameterNames = findMethodParameterNames(method,parameterTypeNames); > >- char[] completion = CharOperation.NO_CHAR; >- >- int previousStartPosition = this.startPosition; >- int previousTokenStart = this.tokenStart; >- >- // Special case for completion in javadoc >- if (this.assistNodeInJavadoc > 0) { >- Expression receiver = null; >- if (invocationSite instanceof CompletionOnJavadocMessageSend) { >- CompletionOnJavadocMessageSend msg = (CompletionOnJavadocMessageSend) invocationSite; >- receiver = msg.receiver; >- } else if (invocationSite instanceof CompletionOnJavadocFieldReference) { >- CompletionOnJavadocFieldReference fieldRef = (CompletionOnJavadocFieldReference) invocationSite; >- receiver = fieldRef.receiver; >- } >- if (receiver != null) { >- StringBuffer javadocCompletion = new StringBuffer(); >- if (receiver.isThis()) { >- if ((this.assistNodeInJavadoc & CompletionOnJavadoc.TEXT) != 0) { >- javadocCompletion.append('#'); >- } >- } else if ((this.assistNodeInJavadoc & CompletionOnJavadoc.TEXT) != 0) { >- if (receiver instanceof JavadocSingleTypeReference) { >- JavadocSingleTypeReference typeRef = (JavadocSingleTypeReference) receiver; >- javadocCompletion.append(typeRef.token); >- javadocCompletion.append('#'); >- } else if (receiver instanceof JavadocQualifiedTypeReference) { >- JavadocQualifiedTypeReference typeRef = (JavadocQualifiedTypeReference) receiver; >- completion = CharOperation.concat(CharOperation.concatWith(typeRef.tokens, '.'), method.selector, '#'); >- for (int t=0,nt =typeRef.tokens.length; t<nt; t++) { >- if (t>0) javadocCompletion.append('.'); >- javadocCompletion.append(typeRef.tokens[t]); >- } >- javadocCompletion.append('#'); >- } >- } >- javadocCompletion.append(method.selector); >- // Append parameters types >- javadocCompletion.append('('); >- if (method.parameters != null) { >- boolean isVarargs = method.isVarargs(); >- for (int p=0, ln=method.parameters.length; p<ln; p++) { >- if (p>0) javadocCompletion.append(", "); //$NON-NLS-1$ >- TypeBinding argTypeBinding = method.parameters[p]; >- if (isVarargs && p == ln - 1) { >- createVargsType(argTypeBinding.erasure(), scope, javadocCompletion); >- } else { >- createType(argTypeBinding.erasure(), scope,javadocCompletion); >- } >- } >- } >- javadocCompletion.append(')'); >- completion = javadocCompletion.toString().toCharArray(); >- } >- } else { >- // nothing to insert - do not want to replace the existing selector & arguments >- if (!exactMatch) { >- if (this.source != null >- && this.source.length > this.endPosition >- && this.source[this.endPosition] == '(') >- completion = method.selector; >- else >- completion = CharOperation.concat(method.selector, new char[] { '(', ')' }); >- >- if (castedReceiver != null) { >- completion = CharOperation.concat(castedReceiver, completion); >- } >- } else { >- if(prefixRequired && (this.source != null)) { >- completion = CharOperation.subarray(this.source, this.startPosition, this.endPosition); >- } else { >- this.startPosition = this.endPosition; >- } >- this.tokenStart = this.tokenEnd; >- } >- >- if(prefixRequired || this.options.forceImplicitQualification){ >- char[] prefix = computePrefix(scope.enclosingSourceType(), invocationScope.enclosingSourceType(), method.isStatic()); >- completion = CharOperation.concat(prefix,completion,'.'); >- } >- } >+ char[] completionName = CharOperation.concat(method.selector, SEMICOLON); > > int relevance = computeBaseRelevance(); > relevance += computeRelevanceForResolution(); > relevance += computeRelevanceForInterestingProposal(); >- if (methodName != null) relevance += computeRelevanceForCaseMatching(methodName, method.selector); >- relevance += computeRelevanceForExpectingType(method.returnType); >- relevance += computeRelevanceForEnumConstant(method.returnType); >- relevance += computeRelevanceForStatic(onlyStaticMethods, method.isStatic()); >- relevance += computeRelevanceForQualification(prefixRequired); >+ relevance += computeRelevanceForCaseMatching(methodName, method.selector); > relevance += computeRelevanceForRestrictions(IAccessRule.K_ACCESSIBLE); >- if (onlyStaticMethods && this.insideQualifiedReference) { >- relevance += computeRelevanceForInheritance(receiverType, method.declaringClass); >- } >- if (missingElements != null) { >- relevance += computeRelevanceForMissingElements(missingElementsHaveProblems); >- } > > this.noProposal = false; >- >- if (castedReceiver == null) { >- // Standard proposal >- if(!this.isIgnored(CompletionProposal.METHOD_REF, missingElements != null) && (this.assistNodeInJavadoc & CompletionOnJavadoc.ONLY_INLINE_TAG) == 0) { >- InternalCompletionProposal proposal = createProposal(CompletionProposal.METHOD_REF, this.actualCompletionPosition); >- proposal.setDeclarationSignature(getSignature(method.declaringClass)); >- proposal.setSignature(getSignature(method)); >- MethodBinding original = method.original(); >- if(original != method) { >- proposal.setOriginalSignature(getSignature(original)); >- } >- proposal.setDeclarationPackageName(method.declaringClass.qualifiedPackageName()); >- proposal.setDeclarationTypeName(method.declaringClass.qualifiedSourceName()); >- proposal.setParameterPackageNames(parameterPackageNames); >- proposal.setParameterTypeNames(parameterTypeNames); >- proposal.setPackageName(method.returnType.qualifiedPackageName()); >- proposal.setTypeName(method.returnType.qualifiedSourceName()); >- proposal.setName(method.selector); >- if (missingElements != null) { >- CompletionProposal[] subProposals = new CompletionProposal[missingElements.length]; >- for (int i = 0; i < missingElements.length; i++) { >- subProposals[i] = >- createRequiredTypeProposal( >- missingElements[i], >- missingElementsStarts[i], >- missingElementsEnds[i], >- relevance); >- } >- proposal.setRequiredProposals(subProposals); >- } >- proposal.setCompletion(completion); >- proposal.setFlags(method.modifiers); >- proposal.setReplaceRange(this.startPosition - this.offset, this.endPosition - this.offset); >- proposal.setTokenRange(this.tokenStart - this.offset, this.tokenEnd - this.offset); >- proposal.setRelevance(relevance); >- if(parameterNames != null) proposal.setParameterNames(parameterNames); >- this.requestor.accept(proposal); >- if(DEBUG) { >- this.printDebug(proposal); >- } >- } >- >- // Javadoc proposal >- if ((this.assistNodeInJavadoc & CompletionOnJavadoc.TEXT) != 0 && !this.requestor.isIgnored(CompletionProposal.JAVADOC_METHOD_REF)) { >- char[] javadocCompletion = inlineTagCompletion(completion, JavadocTagConstants.TAG_LINK); >- InternalCompletionProposal proposal = createProposal(CompletionProposal.JAVADOC_METHOD_REF, this.actualCompletionPosition); >- proposal.setDeclarationSignature(getSignature(method.declaringClass)); >- proposal.setSignature(getSignature(method)); >- MethodBinding original = method.original(); >- if(original != method) { >- proposal.setOriginalSignature(getSignature(original)); >- } >- proposal.setDeclarationPackageName(method.declaringClass.qualifiedPackageName()); >- proposal.setDeclarationTypeName(method.declaringClass.qualifiedSourceName()); >- proposal.setParameterPackageNames(parameterPackageNames); >- proposal.setParameterTypeNames(parameterTypeNames); >- proposal.setPackageName(method.returnType.qualifiedPackageName()); >- proposal.setTypeName(method.returnType.qualifiedSourceName()); >- proposal.setName(method.selector); >- proposal.setCompletion(javadocCompletion); >- proposal.setFlags(method.modifiers); >- int start = (this.assistNodeInJavadoc & CompletionOnJavadoc.REPLACE_TAG) != 0 ? this.javadocTagPosition : this.startPosition; >- proposal.setReplaceRange(start - this.offset, this.endPosition - this.offset); >- proposal.setTokenRange(this.tokenStart - this.offset, this.tokenEnd - this.offset); >- proposal.setRelevance(relevance+R_INLINE_TAG); >- if(parameterNames != null) proposal.setParameterNames(parameterNames); >- this.requestor.accept(proposal); >- if(DEBUG) { >- this.printDebug(proposal); >- } >- } >- } else { >- if(!this.isIgnored(CompletionProposal.METHOD_REF_WITH_CASTED_RECEIVER, missingElements != null)) { >- InternalCompletionProposal proposal = createProposal(CompletionProposal.METHOD_REF_WITH_CASTED_RECEIVER, this.actualCompletionPosition); >- proposal.setDeclarationSignature(getSignature(method.declaringClass)); >- proposal.setSignature(getSignature(method)); >- MethodBinding original = method.original(); >- if(original != method) { >- proposal.setOriginalSignature(getSignature(original)); >- } >- proposal.setReceiverSignature(getSignature(receiverType)); >- proposal.setDeclarationPackageName(method.declaringClass.qualifiedPackageName()); >- proposal.setDeclarationTypeName(method.declaringClass.qualifiedSourceName()); >- proposal.setParameterPackageNames(parameterPackageNames); >- proposal.setParameterTypeNames(parameterTypeNames); >- proposal.setPackageName(method.returnType.qualifiedPackageName()); >- proposal.setTypeName(method.returnType.qualifiedSourceName()); >- proposal.setName(method.selector); >- if (missingElements != null) { >- CompletionProposal[] subProposals = new CompletionProposal[missingElements.length]; >- for (int i = 0; i < missingElements.length; i++) { >- subProposals[i] = >- createRequiredTypeProposal( >- missingElements[i], >- missingElementsStarts[i], >- missingElementsEnds[i], >- relevance); >- } >- proposal.setRequiredProposals(subProposals); >- } >- proposal.setCompletion(completion); >- proposal.setFlags(method.modifiers); >- proposal.setReplaceRange(this.startPosition - this.offset, this.endPosition - this.offset); >- proposal.setReceiverRange(receiverStart - this.offset, receiverEnd - this.offset); >- proposal.setTokenRange(this.tokenStart - this.offset, this.tokenEnd - this.offset); >- proposal.setRelevance(relevance); >- if(parameterNames != null) proposal.setParameterNames(parameterNames); >- this.requestor.accept(proposal); >- if(DEBUG) { >- this.printDebug(proposal); >- } >+ if(!this.requestor.isIgnored(CompletionProposal.METHOD_NAME_REFERENCE)) { >+ InternalCompletionProposal proposal = createProposal(CompletionProposal.METHOD_NAME_REFERENCE, this.actualCompletionPosition); >+ proposal.setDeclarationSignature(getSignature(method.declaringClass)); >+ proposal.setSignature(getSignature(method)); >+ proposal.setDeclarationPackageName(method.declaringClass.qualifiedPackageName()); >+ proposal.setDeclarationTypeName(method.declaringClass.qualifiedSourceName()); >+ proposal.setParameterPackageNames(parameterPackageNames); >+ proposal.setParameterTypeNames(parameterTypeNames); >+ proposal.setPackageName(method.returnType.qualifiedPackageName()); >+ proposal.setTypeName(method.returnType.qualifiedSourceName()); >+ proposal.setName(method.selector); >+ proposal.setCompletion(completionName); >+ proposal.setFlags(method.modifiers); >+ proposal.setReplaceRange(this.startPosition - this.offset, this.endPosition - this.offset); >+ proposal.setTokenRange(this.tokenStart - this.offset, this.tokenEnd - this.offset); >+ proposal.setRelevance(relevance); >+ if(parameterNames != null) proposal.setParameterNames(parameterNames); >+ this.requestor.accept(proposal); >+ if(DEBUG) { >+ this.printDebug(proposal); > } > } >- this.startPosition = previousStartPosition; >- this.tokenStart = previousTokenStart; > } >- >- methodsFound.addAll(newMethodsFound); > } >+ >+ private void findInterfacesMethodDeclarations( >+ char[] selector, >+ ReferenceBinding receiverType, >+ ReferenceBinding[] itsInterfaces, >+ Scope scope, >+ ObjectVector methodsFound, >+ Binding[] missingElements, >+ int[] missingElementssStarts, >+ int[] missingElementsEnds, >+ boolean missingElementsHaveProblems) { > >- private void findLocalMethodsFromFavorites( >- char[] methodName, >- MethodBinding[] methods, >- Scope scope, >- ObjectVector methodsFound, >- ObjectVector methodsFoundFromFavorites, >- ReferenceBinding receiverType, >- InvocationSite invocationSite, >- Scope invocationScope) { >- >- char[] typeName = CharOperation.concatWith(receiverType.compoundName, '.'); >- >- int methodLength = methodName.length; >- >- next : for (int f = methods.length; --f >= 0;) { >- MethodBinding method = methods[f]; >- >- if (method.isSynthetic()) continue next; >- >- if (method.isDefaultAbstract()) continue next; >- >- if (method.isConstructor()) continue next; >- >- if (this.options.checkDeprecation && >- method.isViewedAsDeprecated() && >- !scope.isDefinedInSameUnit(method.declaringClass)) >- continue next; >- >- if (!method.isStatic()) continue next; >- >- if (this.options.checkVisibility >- && !method.canBeSeenBy(receiverType, invocationSite, scope)) continue next; >+ if (selector == null) >+ return; > >- if (methodLength > method.selector.length) continue next; >+ if (itsInterfaces != Binding.NO_SUPERINTERFACES) { >+ ReferenceBinding[] interfacesToVisit = itsInterfaces; >+ int nextPosition = interfacesToVisit.length; > >- if (!CharOperation.prefixEquals(methodName, method.selector, false /* ignore case */) >- && !(this.options.camelCaseMatch && CharOperation.camelCaseMatch(methodName, method.selector))) { >- continue next; >+ for (int i = 0; i < nextPosition; i++) { >+ ReferenceBinding currentType = interfacesToVisit[i]; >+ MethodBinding[] methods = currentType.availableMethods(); >+ if(methods != null) { >+ findLocalMethodDeclarations( >+ selector, >+ methods, >+ scope, >+ methodsFound, >+ false, >+ receiverType); > } > >- for (int i = methodsFoundFromFavorites.size; --i >= 0;) { >- Object[] other = (Object[]) methodsFoundFromFavorites.elementAt(i); >- MethodBinding otherMethod = (MethodBinding) other[0]; >- >- if (method == otherMethod) continue next; >- >- if (CharOperation.equals(method.selector, otherMethod.selector, true)) { >- if (otherMethod.declaringClass == method.declaringClass && >- this.lookupEnvironment.methodVerifier().isMethodSubsignature(otherMethod, method)) { >- continue next; >- } >+ itsInterfaces = currentType.superInterfaces(); >+ if (itsInterfaces != null && itsInterfaces != Binding.NO_SUPERINTERFACES) { >+ int itsLength = itsInterfaces.length; >+ if (nextPosition + itsLength >= interfacesToVisit.length) >+ System.arraycopy(interfacesToVisit, 0, interfacesToVisit = new ReferenceBinding[nextPosition + itsLength + 5], 0, nextPosition); >+ nextInterface : for (int a = 0; a < itsLength; a++) { >+ ReferenceBinding next = itsInterfaces[a]; >+ for (int b = 0; b < nextPosition; b++) >+ if (next == interfacesToVisit[b]) continue nextInterface; >+ interfacesToVisit[nextPosition++] = next; > } > } >+ } >+ } >+ } >+ >+ private void findInterfacesMethods( >+ char[] selector, >+ TypeBinding[] typeArgTypes, >+ TypeBinding[] argTypes, >+ ReferenceBinding receiverType, >+ ReferenceBinding[] itsInterfaces, >+ Scope scope, >+ ObjectVector methodsFound, >+ boolean onlyStaticMethods, >+ boolean exactMatch, >+ InvocationSite invocationSite, >+ Scope invocationScope, >+ boolean implicitCall, >+ boolean superCall, >+ boolean canBePrefixed, >+ Binding[] missingElements, >+ int[] missingElementssStarts, >+ int[] missingElementsEnds, >+ boolean missingElementsHaveProblems, >+ char[] castedReceiver, >+ int receiverStart, >+ int receiverEnd) { > >- for (int i = methodsFound.size; --i >= 0;) { >- Object[] other = (Object[]) methodsFound.elementAt(i); >- MethodBinding otherMethod = (MethodBinding) other[0]; >+ if (selector == null) >+ return; > >- if (method == otherMethod) continue next; >+ if (itsInterfaces != Binding.NO_SUPERINTERFACES) { >+ ReferenceBinding[] interfacesToVisit = itsInterfaces; >+ int nextPosition = interfacesToVisit.length; > >- if (CharOperation.equals(method.selector, otherMethod.selector, true)) { >- if (this.lookupEnvironment.methodVerifier().isMethodSubsignature(otherMethod, method)) { >- continue next; >- } >- } >+ for (int i = 0; i < nextPosition; i++) { >+ ReferenceBinding currentType = interfacesToVisit[i]; >+ MethodBinding[] methods = currentType.availableMethods(); >+ if(methods != null) { >+ findLocalMethods( >+ selector, >+ typeArgTypes, >+ argTypes, >+ methods, >+ scope, >+ methodsFound, >+ onlyStaticMethods, >+ exactMatch, >+ receiverType, >+ invocationSite, >+ invocationScope, >+ implicitCall, >+ superCall, >+ canBePrefixed, >+ missingElements, >+ missingElementssStarts, >+ missingElementsEnds, >+ missingElementsHaveProblems, >+ castedReceiver, >+ receiverStart, >+ receiverEnd); > } > >- boolean proposeStaticImport = !(this.compilerOptions.complianceLevel < ClassFileConstants.JDK1_5) && >- this.options.suggestStaticImport; >- >- boolean isAlreadyImported = false; >- if (!proposeStaticImport) { >- if(!this.importCachesInitialized) { >- initializeImportCaches(); >- } >- for (int j = 0; j < this.importCacheCount; j++) { >- char[][] importName = this.importsCache[j]; >- if(CharOperation.equals(receiverType.sourceName, importName[0])) { >- if (!CharOperation.equals(typeName, importName[1])) { >- continue next; >- } else { >- isAlreadyImported = true; >- } >- } >+ itsInterfaces = currentType.superInterfaces(); >+ if (itsInterfaces != null && itsInterfaces != Binding.NO_SUPERINTERFACES) { >+ int itsLength = itsInterfaces.length; >+ if (nextPosition + itsLength >= interfacesToVisit.length) >+ System.arraycopy(interfacesToVisit, 0, interfacesToVisit = new ReferenceBinding[nextPosition + itsLength + 5], 0, nextPosition); >+ nextInterface : for (int a = 0; a < itsLength; a++) { >+ ReferenceBinding next = itsInterfaces[a]; >+ for (int b = 0; b < nextPosition; b++) >+ if (next == interfacesToVisit[b]) continue nextInterface; >+ interfacesToVisit[nextPosition++] = next; > } > } >- >- methodsFoundFromFavorites.add(new Object[]{method, receiverType}); >- >- ReferenceBinding superTypeWithSameErasure = (ReferenceBinding)receiverType.findSuperTypeOriginatingFrom(method.declaringClass); >- if (method.declaringClass != superTypeWithSameErasure) { >- MethodBinding[] otherMethods = superTypeWithSameErasure.getMethods(method.selector); >- for (int i = 0; i < otherMethods.length; i++) { >- if(otherMethods[i].original() == method.original()) { >- method = otherMethods[i]; >- } >- } >+ } >+ } >+ } >+ /* >+ * Find javadoc block tags for a given completion javadoc tag node >+ */ >+ private void findJavadocBlockTags(CompletionOnJavadocTag javadocTag) { >+ char[][] possibleTags = javadocTag.getPossibleBlockTags(); >+ if (possibleTags == null) return; >+ int length = possibleTags.length; >+ for (int i=0; i<length; i++) { >+ int relevance = computeBaseRelevance(); >+ relevance += computeRelevanceForInterestingProposal(); >+ relevance += computeRelevanceForRestrictions(IAccessRule.K_ACCESSIBLE); // no access restriction for keywors >+ >+ this.noProposal = false; >+ if (!this.requestor.isIgnored(CompletionProposal.JAVADOC_BLOCK_TAG)) { >+ char[] possibleTag = possibleTags[i]; >+ InternalCompletionProposal proposal = createProposal(CompletionProposal.JAVADOC_BLOCK_TAG, this.actualCompletionPosition); >+ proposal.setName(possibleTag); >+ int tagLength = possibleTag.length; >+ char[] completion = new char[1+tagLength]; >+ completion[0] = '@'; >+ System.arraycopy(possibleTag, 0, completion, 1, tagLength); >+ proposal.setCompletion(completion); >+ proposal.setReplaceRange(this.startPosition - this.offset, this.endPosition - this.offset); >+ proposal.setTokenRange(this.tokenStart - this.offset, this.tokenEnd - this.offset); >+ proposal.setRelevance(relevance); >+ this.requestor.accept(proposal); >+ if (DEBUG) { >+ this.printDebug(proposal); > } >+ } >+ } >+ } > >- int length = method.parameters.length; >- char[][] parameterPackageNames = new char[length][]; >- char[][] parameterTypeNames = new char[length][]; >+ /* >+ * Find javadoc inline tags for a given completion javadoc tag node >+ */ >+ private void findJavadocInlineTags(CompletionOnJavadocTag javadocTag) { >+ char[][] possibleTags = javadocTag.getPossibleInlineTags(); >+ if (possibleTags == null) return; >+ int length = possibleTags.length; >+ for (int i=0; i<length; i++) { >+ int relevance = computeBaseRelevance(); >+ relevance += computeRelevanceForInterestingProposal(); >+ relevance += computeRelevanceForRestrictions(IAccessRule.K_ACCESSIBLE); // no access restriction for keywors > >- for (int i = 0; i < length; i++) { >- TypeBinding type = method.original().parameters[i]; >- parameterPackageNames[i] = type.qualifiedPackageName(); >- parameterTypeNames[i] = type.qualifiedSourceName(); >+ this.noProposal = false; >+ if (!this.requestor.isIgnored(CompletionProposal.JAVADOC_INLINE_TAG)) { >+ char[] possibleTag = possibleTags[i]; >+ InternalCompletionProposal proposal = createProposal(CompletionProposal.JAVADOC_INLINE_TAG, this.actualCompletionPosition); >+ proposal.setName(possibleTag); >+ int tagLength = possibleTag.length; >+// boolean inlineTagStarted = javadocTag.completeInlineTagStarted(); >+ char[] completion = new char[2+tagLength+1]; >+ completion[0] = '{'; >+ completion[1] = '@'; >+ System.arraycopy(possibleTag, 0, completion, 2, tagLength); >+ // do not add space at end of inline tag (see bug https://bugs.eclipse.org/bugs/show_bug.cgi?id=121026) >+ //completion[tagLength+2] = ' '; >+ completion[tagLength+2] = '}'; >+ proposal.setCompletion(completion); >+ proposal.setReplaceRange(this.startPosition - this.offset, this.endPosition - this.offset); >+ proposal.setTokenRange(this.tokenStart - this.offset, this.tokenEnd - this.offset); >+ proposal.setRelevance(relevance); >+ this.requestor.accept(proposal); >+ if (DEBUG) { >+ this.printDebug(proposal); > } >- char[][] parameterNames = findMethodParameterNames(method,parameterTypeNames); >- >- char[] completion = CharOperation.NO_CHAR; >+ } >+ } >+ } > >- int previousStartPosition = this.startPosition; >- int previousTokenStart = this.tokenStart; >+ /* >+ * Find javadoc parameter names. >+ */ >+ private void findJavadocParamNames(char[] token, char[][] missingParams, boolean isTypeParam) { > >- if (this.source != null >- && this.source.length > this.endPosition >- && this.source[this.endPosition] == '(') { >- completion = method.selector; >- } else { >- completion = CharOperation.concat(method.selector, new char[] { '(', ')' }); >- } >+ if (missingParams == null) return; > >- int relevance = computeBaseRelevance(); >- relevance += computeRelevanceForResolution(); >- relevance += computeRelevanceForInterestingProposal(); >- if (methodName != null) relevance += computeRelevanceForCaseMatching(methodName, method.selector); >- relevance += computeRelevanceForExpectingType(method.returnType); >- relevance += computeRelevanceForEnumConstant(method.returnType); >- relevance += computeRelevanceForStatic(true, method.isStatic()); >- relevance += computeRelevanceForQualification(true); >- relevance += computeRelevanceForRestrictions(IAccessRule.K_ACCESSIBLE); >+ // Get relevance >+ int relevance = computeBaseRelevance(); >+ relevance += computeRelevanceForInterestingProposal(); >+ relevance += computeRelevanceForRestrictions(IAccessRule.K_ACCESSIBLE); // no access restriction for param name >+ if (!isTypeParam) relevance += R_INTERESTING; > >- CompilationUnitDeclaration cu = this.unitScope.referenceContext; >- int importStart = cu.types[0].declarationSourceStart; >- int importEnd = importStart; >+ // Propose missing param >+ int length = missingParams.length; >+ relevance += length; >+ for (int i=0; i<length; i++) { >+ char[] argName = missingParams[i]; >+ if (token == null || CharOperation.prefixEquals(token, argName)) { > > this.noProposal = false; >+ if (!this.requestor.isIgnored(CompletionProposal.JAVADOC_PARAM_REF)) { >+ InternalCompletionProposal proposal = createProposal(CompletionProposal.JAVADOC_PARAM_REF, this.actualCompletionPosition); >+ proposal.setName(argName); >+ char[] completion = isTypeParam ? CharOperation.concat('<', argName, '>') : argName; >+ proposal.setCompletion(completion); >+ proposal.setReplaceRange(this.startPosition - this.offset, this.endPosition - this.offset); >+ proposal.setTokenRange(this.tokenStart - this.offset, this.tokenEnd - this.offset); >+ proposal.setRelevance(--relevance); >+ this.requestor.accept(proposal); >+ if (DEBUG) { >+ this.printDebug(proposal); >+ } >+ } >+ } >+ } >+ } > >- if (!proposeStaticImport) { >- if (isAlreadyImported) { >- if (!isIgnored(CompletionProposal.METHOD_REF)) { >- completion = CharOperation.concat(receiverType.sourceName, completion, '.'); >- >- InternalCompletionProposal proposal = createProposal(CompletionProposal.METHOD_REF, this.actualCompletionPosition); >- proposal.setDeclarationSignature(getSignature(method.declaringClass)); >- proposal.setSignature(getSignature(method)); >- MethodBinding original = method.original(); >- if(original != method) { >- proposal.setOriginalSignature(getSignature(original)); >- } >- proposal.setDeclarationPackageName(method.declaringClass.qualifiedPackageName()); >- proposal.setDeclarationTypeName(method.declaringClass.qualifiedSourceName()); >- proposal.setParameterPackageNames(parameterPackageNames); >- proposal.setParameterTypeNames(parameterTypeNames); >- proposal.setPackageName(method.returnType.qualifiedPackageName()); >- proposal.setTypeName(method.returnType.qualifiedSourceName()); >- proposal.setName(method.selector); >- proposal.setCompletion(completion); >- proposal.setFlags(method.modifiers); >- proposal.setReplaceRange(this.startPosition - this.offset, this.endPosition - this.offset); >- proposal.setTokenRange(this.tokenStart - this.offset, this.tokenEnd - this.offset); >- proposal.setRelevance(relevance); >- if(parameterNames != null) proposal.setParameterNames(parameterNames); >+ // what about onDemand types? Ignore them since it does not happen! >+ // import p1.p2.A.*; >+ private void findKeywords(char[] keyword, char[][] choices, boolean canCompleteEmptyToken, boolean staticFieldsAndMethodOnly) { >+ if(choices == null || choices.length == 0) return; > >- this.requestor.accept(proposal); >- if(DEBUG) { >- this.printDebug(proposal); >- } >- } >- } else if (!this.isIgnored(CompletionProposal.METHOD_REF, CompletionProposal.TYPE_IMPORT)) { >- completion = CharOperation.concat(receiverType.sourceName, completion, '.'); >+ int length = keyword.length; >+ if (canCompleteEmptyToken || length > 0) >+ for (int i = 0; i < choices.length; i++) >+ if (length <= choices[i].length >+ && CharOperation.prefixEquals(keyword, choices[i], false /* ignore case */ >+ )){ >+ int relevance = computeBaseRelevance(); >+ relevance += computeRelevanceForResolution(); >+ relevance += computeRelevanceForInterestingProposal(); >+ relevance += computeRelevanceForCaseMatching(keyword, choices[i]); >+ relevance += computeRelevanceForRestrictions(IAccessRule.K_ACCESSIBLE); // no access restriction for keywords >+ if (staticFieldsAndMethodOnly && this.insideQualifiedReference) relevance += R_NON_INHERITED; > >- InternalCompletionProposal proposal = createProposal(CompletionProposal.METHOD_REF, this.actualCompletionPosition); >- proposal.setDeclarationSignature(getSignature(method.declaringClass)); >- proposal.setSignature(getSignature(method)); >- MethodBinding original = method.original(); >- if(original != method) { >- proposal.setOriginalSignature(getSignature(original)); >- } >- proposal.setDeclarationPackageName(method.declaringClass.qualifiedPackageName()); >- proposal.setDeclarationTypeName(method.declaringClass.qualifiedSourceName()); >- proposal.setParameterPackageNames(parameterPackageNames); >- proposal.setParameterTypeNames(parameterTypeNames); >- proposal.setPackageName(method.returnType.qualifiedPackageName()); >- proposal.setTypeName(method.returnType.qualifiedSourceName()); >- proposal.setName(method.selector); >- proposal.setCompletion(completion); >- proposal.setFlags(method.modifiers); >+ if(CharOperation.equals(choices[i], Keywords.TRUE) || CharOperation.equals(choices[i], Keywords.FALSE)) { >+ relevance += computeRelevanceForExpectingType(TypeBinding.BOOLEAN); >+ relevance += computeRelevanceForQualification(false); >+ } >+ this.noProposal = false; >+ if(!this.requestor.isIgnored(CompletionProposal.KEYWORD)) { >+ InternalCompletionProposal proposal = createProposal(CompletionProposal.KEYWORD, this.actualCompletionPosition); >+ proposal.setName(choices[i]); >+ proposal.setCompletion(choices[i]); > proposal.setReplaceRange(this.startPosition - this.offset, this.endPosition - this.offset); > proposal.setTokenRange(this.tokenStart - this.offset, this.tokenEnd - this.offset); > proposal.setRelevance(relevance); >- if(parameterNames != null) proposal.setParameterNames(parameterNames); >- >- char[] typeImportCompletion = createImportCharArray(typeName, false, false); >- >- InternalCompletionProposal typeImportProposal = createProposal(CompletionProposal.TYPE_IMPORT, this.actualCompletionPosition); >- typeImportProposal.nameLookup = this.nameEnvironment.nameLookup; >- typeImportProposal.completionEngine = this; >- char[] packageName = receiverType.qualifiedPackageName(); >- typeImportProposal.setDeclarationSignature(packageName); >- typeImportProposal.setSignature(getSignature(receiverType)); >- typeImportProposal.setPackageName(packageName); >- typeImportProposal.setTypeName(receiverType.qualifiedSourceName()); >- typeImportProposal.setCompletion(typeImportCompletion); >- typeImportProposal.setFlags(receiverType.modifiers); >- typeImportProposal.setAdditionalFlags(CompletionFlags.Default); >- typeImportProposal.setReplaceRange(importStart - this.offset, importEnd - this.offset); >- typeImportProposal.setTokenRange(importStart - this.offset, importEnd - this.offset); >- typeImportProposal.setRelevance(relevance); >- >- proposal.setRequiredProposals(new CompletionProposal[]{typeImportProposal}); >- > this.requestor.accept(proposal); > if(DEBUG) { > this.printDebug(proposal); > } > } >- } else { >- if (!this.isIgnored(CompletionProposal.METHOD_REF, CompletionProposal.METHOD_IMPORT)) { >- InternalCompletionProposal proposal = createProposal(CompletionProposal.METHOD_REF, this.actualCompletionPosition); >- proposal.setDeclarationSignature(getSignature(method.declaringClass)); >- proposal.setSignature(getSignature(method)); >- MethodBinding original = method.original(); >- if(original != method) { >- proposal.setOriginalSignature(getSignature(original)); >- } >- proposal.setDeclarationPackageName(method.declaringClass.qualifiedPackageName()); >- proposal.setDeclarationTypeName(method.declaringClass.qualifiedSourceName()); >- proposal.setParameterPackageNames(parameterPackageNames); >- proposal.setParameterTypeNames(parameterTypeNames); >- proposal.setPackageName(method.returnType.qualifiedPackageName()); >- proposal.setTypeName(method.returnType.qualifiedSourceName()); >- proposal.setName(method.selector); >- proposal.setCompletion(completion); >- proposal.setFlags(method.modifiers); >- proposal.setReplaceRange(this.startPosition - this.offset, this.endPosition - this.offset); >- proposal.setTokenRange(this.tokenStart - this.offset, this.tokenEnd - this.offset); >- proposal.setRelevance(relevance); >- if(parameterNames != null) proposal.setParameterNames(parameterNames); >- >- char[] methodImportCompletion = createImportCharArray(CharOperation.concat(typeName, method.selector, '.'), true, false); >- >- InternalCompletionProposal methodImportProposal = createProposal(CompletionProposal.METHOD_IMPORT, this.actualCompletionPosition); >- methodImportProposal.setDeclarationSignature(getSignature(method.declaringClass)); >- methodImportProposal.setSignature(getSignature(method)); >- if(original != method) { >- proposal.setOriginalSignature(getSignature(original)); >- } >- methodImportProposal.setDeclarationPackageName(method.declaringClass.qualifiedPackageName()); >- methodImportProposal.setDeclarationTypeName(method.declaringClass.qualifiedSourceName()); >- methodImportProposal.setParameterPackageNames(parameterPackageNames); >- methodImportProposal.setParameterTypeNames(parameterTypeNames); >- methodImportProposal.setPackageName(method.returnType.qualifiedPackageName()); >- methodImportProposal.setTypeName(method.returnType.qualifiedSourceName()); >- methodImportProposal.setName(method.selector); >- methodImportProposal.setCompletion(methodImportCompletion); >- methodImportProposal.setFlags(method.modifiers); >- methodImportProposal.setAdditionalFlags(CompletionFlags.StaticImport); >- methodImportProposal.setReplaceRange(importStart - this.offset, importEnd - this.offset); >- methodImportProposal.setTokenRange(importStart - this.offset, importEnd - this.offset); >- methodImportProposal.setRelevance(relevance); >- if(parameterNames != null) methodImportProposal.setParameterNames(parameterNames); >+ } >+ } >+ private void findKeywordsForMember(char[] token, int modifiers) { >+ char[][] keywords = new char[Keywords.COUNT][]; >+ int count = 0; > >- proposal.setRequiredProposals(new CompletionProposal[]{methodImportProposal}); >+ // visibility >+ if((modifiers & ClassFileConstants.AccPrivate) == 0 >+ && (modifiers & ClassFileConstants.AccProtected) == 0 >+ && (modifiers & ClassFileConstants.AccPublic) == 0) { >+ keywords[count++] = Keywords.PROTECTED; >+ keywords[count++] = Keywords.PUBLIC; >+ if((modifiers & ClassFileConstants.AccAbstract) == 0) { >+ keywords[count++] = Keywords.PRIVATE; >+ } >+ } > >- this.requestor.accept(proposal); >- if(DEBUG) { >- this.printDebug(proposal); >- } >- } >+ if((modifiers & ClassFileConstants.AccAbstract) == 0) { >+ // abtract >+ if((modifiers & ~(ExtraCompilerModifiers.AccVisibilityMASK | ClassFileConstants.AccStatic)) == 0) { >+ keywords[count++] = Keywords.ABSTRACT; >+ } >+ >+ // final >+ if((modifiers & ClassFileConstants.AccFinal) == 0) { >+ keywords[count++] = Keywords.FINAL; >+ } >+ >+ // static >+ if((modifiers & ClassFileConstants.AccStatic) == 0) { >+ keywords[count++] = Keywords.STATIC; >+ } >+ >+ boolean canBeField = true; >+ boolean canBeMethod = true; >+ boolean canBeType = true; >+ if((modifiers & ClassFileConstants.AccNative) != 0 >+ || (modifiers & ClassFileConstants.AccStrictfp) != 0 >+ || (modifiers & ClassFileConstants.AccSynchronized) != 0) { >+ canBeField = false; >+ canBeType = false; >+ } >+ >+ if((modifiers & ClassFileConstants.AccTransient) != 0 >+ || (modifiers & ClassFileConstants.AccVolatile) != 0) { >+ canBeMethod = false; >+ canBeType = false; >+ } >+ >+ if(canBeField) { >+ // transient >+ if((modifiers & ClassFileConstants.AccTransient) == 0) { >+ keywords[count++] = Keywords.TRANSIENT; > } > >- this.startPosition = previousStartPosition; >- this.tokenStart = previousTokenStart; >+ // volatile >+ if((modifiers & ClassFileConstants.AccVolatile) == 0) { >+ keywords[count++] = Keywords.VOLATILE; >+ } > } >- } > >- private CompletionProposal createRequiredTypeProposal(Binding binding, int start, int end, int relevance) { >- InternalCompletionProposal proposal = null; >- if (binding instanceof ReferenceBinding) { >- ReferenceBinding typeBinding = (ReferenceBinding) binding; >+ if(canBeMethod) { >+ // native >+ if((modifiers & ClassFileConstants.AccNative) == 0) { >+ keywords[count++] = Keywords.NATIVE; >+ } > >- char[] packageName = typeBinding.qualifiedPackageName(); >- char[] typeName = typeBinding.qualifiedSourceName(); >- char[] fullyQualifiedName = CharOperation.concat(packageName, typeName, '.'); >+ // strictfp >+ if((modifiers & ClassFileConstants.AccStrictfp) == 0) { >+ keywords[count++] = Keywords.STRICTFP; >+ } > >- proposal = createProposal(CompletionProposal.TYPE_REF, this.actualCompletionPosition); >- proposal.nameLookup = this.nameEnvironment.nameLookup; >- proposal.completionEngine = this; >- proposal.setDeclarationSignature(packageName); >- proposal.setSignature(getRequiredTypeSignature(typeBinding)); >- proposal.setPackageName(packageName); >- proposal.setTypeName(typeName); >- proposal.setCompletion(fullyQualifiedName); >- proposal.setFlags(typeBinding.modifiers); >- proposal.setReplaceRange(start - this.offset, end - this.offset); >- proposal.setTokenRange(start - this.offset, end - this.offset); >- proposal.setRelevance(relevance); >- } else if (binding instanceof PackageBinding) { >- PackageBinding packageBinding = (PackageBinding) binding; >+ // synchronized >+ if((modifiers & ClassFileConstants.AccSynchronized) == 0) { >+ keywords[count++] = Keywords.SYNCHRONIZED; >+ } >+ } > >- char[] packageName = CharOperation.concatWith(packageBinding.compoundName, '.'); >+ if(canBeType) { >+ keywords[count++] = Keywords.CLASS; >+ keywords[count++] = Keywords.INTERFACE; > >- proposal = createProposal(CompletionProposal.PACKAGE_REF, this.actualCompletionPosition); >- proposal.setDeclarationSignature(packageName); >- proposal.setPackageName(packageName); >- proposal.setCompletion(packageName); >- proposal.setReplaceRange(start - this.offset, end - this.offset); >- proposal.setTokenRange(start - this.offset, end - this.offset); >- proposal.setRelevance(relevance); >+ if((modifiers & ClassFileConstants.AccFinal) == 0) { >+ keywords[count++] = Keywords.ENUM; >+ } >+ } >+ } else { >+ // class >+ keywords[count++] = Keywords.CLASS; >+ keywords[count++] = Keywords.INTERFACE; > } >- return proposal; >+ System.arraycopy(keywords, 0, keywords = new char[count][], 0, count); >+ >+ findKeywords(token, keywords, false, false); > } >+ private void findLabels(char[] label, char[][] choices) { >+ if(choices == null || choices.length == 0) return; > >- // Helper method for findMethods(char[], TypeBinding[], ReferenceBinding, Scope, ObjectVector, boolean, boolean, boolean) >- private void findLocalMethodsFromStaticImports( >+ int length = label.length; >+ for (int i = 0; i < choices.length; i++) { >+ if (length <= choices[i].length >+ && CharOperation.prefixEquals(label, choices[i], false /* ignore case */ >+ )){ >+ int relevance = computeBaseRelevance(); >+ relevance += computeRelevanceForResolution(); >+ relevance += computeRelevanceForInterestingProposal(); >+ relevance += computeRelevanceForCaseMatching(label, choices[i]); >+ relevance += computeRelevanceForRestrictions(IAccessRule.K_ACCESSIBLE); // no access restriction for keywors >+ >+ this.noProposal = false; >+ if(!this.requestor.isIgnored(CompletionProposal.LABEL_REF)) { >+ InternalCompletionProposal proposal = createProposal(CompletionProposal.LABEL_REF, this.actualCompletionPosition); >+ proposal.setName(choices[i]); >+ proposal.setCompletion(choices[i]); >+ proposal.setReplaceRange(this.startPosition - this.offset, this.endPosition - this.offset); >+ proposal.setTokenRange(this.tokenStart - this.offset, this.tokenEnd - this.offset); >+ proposal.setRelevance(relevance); >+ this.requestor.accept(proposal); >+ if(DEBUG) { >+ this.printDebug(proposal); >+ } >+ } >+ } >+ } >+ } >+ >+ // Helper method for findMethods(char[], MethodBinding[], Scope, ObjectVector, boolean, boolean, boolean, TypeBinding) >+ private void findLocalMethodDeclarations( > char[] methodName, > MethodBinding[] methods, > Scope scope, >- boolean exactMatch, > ObjectVector methodsFound, >- ReferenceBinding receiverType, >- InvocationSite invocationSite) { >+ // boolean noVoidReturnType, how do you know? >+ boolean exactMatch, >+ ReferenceBinding receiverType) { > > ObjectVector newMethodsFound = new ObjectVector(); >- >+ // Inherited methods which are hidden by subclasses are filtered out >+ // No visibility checks can be performed without the scope & invocationSite >+ int methodLength = methodName.length; > next : for (int f = methods.length; --f >= 0;) { >- MethodBinding method = methods[f]; > >- if (method.isSynthetic()) continue next; >+ MethodBinding method = methods[f]; >+ if (method.isSynthetic()) continue next; > >- if (method.isDefaultAbstract()) continue next; >+ if (method.isDefaultAbstract()) continue next; > > if (method.isConstructor()) continue next; > >- if (!method.isStatic()) continue next; >+ if (method.isFinal()) { >+ newMethodsFound.add(method); >+ continue next; >+ } > > if (this.options.checkDeprecation && > method.isViewedAsDeprecated() && > !scope.isDefinedInSameUnit(method.declaringClass)) > continue next; > >- if (this.options.checkVisibility >- && !method.canBeSeenBy(receiverType, invocationSite, scope)) continue next; >+ // if (noVoidReturnType && method.returnType == BaseTypes.VoidBinding) continue next; >+ if(method.isStatic()) continue next; > >- if (!CharOperation.equals(methodName, method.selector, false /* ignore case */) >- && !(this.options.camelCaseMatch && CharOperation.camelCaseMatch(methodName, method.selector))) >- continue next; >+ if (!method.canBeSeenBy(receiverType, FakeInvocationSite , scope)) continue next; >+ >+ if (exactMatch) { >+ if (!CharOperation.equals(methodName, method.selector, false /* ignore case */ >+ )) >+ continue next; >+ >+ } else { >+ >+ if (methodLength > method.selector.length) >+ continue next; >+ >+ if (!CharOperation.prefixEquals(methodName, method.selector, false/* ignore case */) >+ && !(this.options.camelCaseMatch && CharOperation.camelCaseMatch(methodName, method.selector))) >+ continue next; >+ } > > for (int i = methodsFound.size; --i >= 0;) { >- Object[] other = (Object[]) methodsFound.elementAt(i); >- MethodBinding otherMethod = (MethodBinding) other[0]; >- ReferenceBinding otherReceiverType = (ReferenceBinding) other[1]; >- if (method == otherMethod && receiverType == otherReceiverType) >+ MethodBinding otherMethod = (MethodBinding) methodsFound.elementAt(i); >+ if (method == otherMethod) > continue next; > >- if (CharOperation.equals(method.selector, otherMethod.selector, true)) { >- if (this.lookupEnvironment.methodVerifier().isMethodSubsignature(otherMethod, method)) { >- continue next; >- } >+ if (CharOperation.equals(method.selector, otherMethod.selector, true) >+ && this.lookupEnvironment.methodVerifier().isMethodSubsignature(otherMethod, method)) { >+ continue next; > } > } > >- newMethodsFound.add(new Object[]{method, receiverType}); >+ newMethodsFound.add(method); > > int length = method.parameters.length; > char[][] parameterPackageNames = new char[length][]; >- char[][] parameterTypeNames = new char[length][]; >+ char[][] parameterFullTypeNames = new char[length][]; > > for (int i = 0; i < length; i++) { >- TypeBinding type = method.original().parameters[i]; >+ TypeBinding type = method.parameters[i]; > parameterPackageNames[i] = type.qualifiedPackageName(); >- parameterTypeNames[i] = type.qualifiedSourceName(); >+ parameterFullTypeNames[i] = type.qualifiedSourceName(); > } >- char[][] parameterNames = findMethodParameterNames(method,parameterTypeNames); >- >- char[] completion = CharOperation.NO_CHAR; > >- int previousStartPosition = this.startPosition; >- int previousTokenStart = this.tokenStart; >+ char[][] parameterNames = findMethodParameterNames(method, parameterFullTypeNames); > >- if (!exactMatch) { >- if (this.source != null >- && this.source.length > this.endPosition >- && this.source[this.endPosition] == '(') { >- completion = method.selector; >- } else { >- completion = CharOperation.concat(method.selector, new char[] { '(', ')' }); >- } >- } else { >- this.startPosition = this.endPosition; >- this.tokenStart = this.tokenEnd; >+ if(method.typeVariables != null && method.typeVariables.length > 0) { >+ char[][] excludedNames = findEnclosingTypeNames(scope); >+ char[][] substituedParameterNames = substituteMethodTypeParameterNames(method.typeVariables, excludedNames); >+ if(substituedParameterNames != null) { >+ method = new ParameterizedMethodBinding( >+ method.declaringClass, >+ method, >+ substituedParameterNames, >+ scope.environment()); >+ } >+ } >+ >+ StringBuffer completion = new StringBuffer(10); >+ if (!exactMatch) { >+ createMethod(method, parameterPackageNames, parameterFullTypeNames, parameterNames, scope, completion); > } > > int relevance = computeBaseRelevance(); > relevance += computeRelevanceForResolution(); > relevance += computeRelevanceForInterestingProposal(); > relevance += computeRelevanceForCaseMatching(methodName, method.selector); >- relevance += computeRelevanceForExpectingType(method.returnType); >- relevance += computeRelevanceForEnumConstant(method.returnType); >- relevance += computeRelevanceForStatic(true, method.isStatic()); >- relevance += computeRelevanceForQualification(false); >+ relevance += R_METHOD_OVERIDE; >+ if(method.isAbstract()) relevance += R_ABSTRACT_METHOD; > relevance += computeRelevanceForRestrictions(IAccessRule.K_ACCESSIBLE); > > this.noProposal = false; >- if(!this.requestor.isIgnored(CompletionProposal.METHOD_REF)) { >- InternalCompletionProposal proposal = createProposal(CompletionProposal.METHOD_REF, this.actualCompletionPosition); >+ if(!this.requestor.isIgnored(CompletionProposal.METHOD_DECLARATION)) { >+ InternalCompletionProposal proposal = createProposal(CompletionProposal.METHOD_DECLARATION, this.actualCompletionPosition); > proposal.setDeclarationSignature(getSignature(method.declaringClass)); >+ proposal.setDeclarationKey(method.declaringClass.computeUniqueKey()); > proposal.setSignature(getSignature(method)); > MethodBinding original = method.original(); > if(original != method) { > proposal.setOriginalSignature(getSignature(original)); > } >+ proposal.setKey(method.computeUniqueKey()); > proposal.setDeclarationPackageName(method.declaringClass.qualifiedPackageName()); > proposal.setDeclarationTypeName(method.declaringClass.qualifiedSourceName()); > proposal.setParameterPackageNames(parameterPackageNames); >- proposal.setParameterTypeNames(parameterTypeNames); >+ proposal.setParameterTypeNames(parameterFullTypeNames); > proposal.setPackageName(method.returnType.qualifiedPackageName()); > proposal.setTypeName(method.returnType.qualifiedSourceName()); >+ proposal.setCompletion(completion.toString().toCharArray()); > proposal.setName(method.selector); >- proposal.setCompletion(completion); > proposal.setFlags(method.modifiers); > proposal.setReplaceRange(this.startPosition - this.offset, this.endPosition - this.offset); > proposal.setTokenRange(this.tokenStart - this.offset, this.tokenEnd - this.offset); >@@ -6733,3290 +6975,3307 @@ > this.printDebug(proposal); > } > } >- this.startPosition = previousStartPosition; >- this.tokenStart = previousTokenStart; > } >- > methodsFound.addAll(newMethodsFound); > } >- int computeRelevanceForCaseMatching(char[] token, char[] proposalName){ >- if (this.options.camelCaseMatch) { >- if(CharOperation.equals(token, proposalName, true /* do not ignore case */)) { >- return R_CASE + R_EXACT_NAME; >- } else if (CharOperation.prefixEquals(token, proposalName, true /* do not ignore case */)) { >- return R_CASE; >- } else if (CharOperation.camelCaseMatch(token, proposalName)){ >- return R_CAMEL_CASE; >- } else if(CharOperation.equals(token, proposalName, false /* ignore case */)) { >- return R_EXACT_NAME; >- } >- } else if (CharOperation.prefixEquals(token, proposalName, true /* do not ignore case */)) { >- if(CharOperation.equals(token, proposalName, true /* do not ignore case */)) { >- return R_CASE + R_EXACT_NAME; >- } else { >- return R_CASE; >- } >- } else if(CharOperation.equals(token, proposalName, false /* ignore case */)) { >- return R_EXACT_NAME; >- } >- return 0; >- } >- private int computeRelevanceForAnnotation(){ >- if(this.assistNodeIsAnnotation) { >- return R_ANNOTATION; >- } >- return 0; >- } >- private int computeRelevanceForAnnotationTarget(TypeBinding typeBinding){ >- if (this.assistNodeIsAnnotation && >- (this.targetedElement & TagBits.AnnotationTargetMASK) != 0) { >- long target = typeBinding.getAnnotationTagBits() & TagBits.AnnotationTargetMASK; >- if(target == 0 || (target & this.targetedElement) != 0) { >- return R_TARGET; >- } >- } >- return 0; >- } >- private int computeRelevanceForClass(){ >- if(this.assistNodeIsClass) { >- return R_CLASS; >- } >- return 0; >- } >- private int computeRelevanceForEnum(){ >- if(this.assistNodeIsEnum) { >- return R_ENUM; >- } >- return 0; >- } >- private int computeRelevanceForInterface(){ >- if(this.assistNodeIsInterface) { >- return R_INTERFACE; >- } >- return 0; >- } >- private int computeRelevanceForMissingElements(boolean hasProblems) { >- if (!hasProblems) { >- return R_NO_PROBLEMS; >- } >- return 0; >- } >- int computeRelevanceForQualification(boolean prefixRequired) { >- if(!prefixRequired && !this.insideQualifiedReference) { >- return R_UNQUALIFIED; >- } > >- if(prefixRequired && this.insideQualifiedReference) { >- return R_QUALIFIED; >- } >- return 0; >- } >- int computeRelevanceForRestrictions(int accessRuleKind) { >- if(accessRuleKind == IAccessRule.K_ACCESSIBLE) { >- return R_NON_RESTRICTED; >- } >- return 0; >- } >- private int computeRelevanceForStatic(boolean onlyStatic, boolean isStatic) { >- if(this.insideQualifiedReference && !onlyStatic && !isStatic) { >- return R_NON_STATIC; >- } >- return 0; >- } >- private int computeRelevanceForEnumConstant(TypeBinding proposalType){ >- if(this.assistNodeIsEnum && >- proposalType != null && >- this.expectedTypes != null) { >- for (int i = 0; i <= this.expectedTypesPtr; i++) { >- if (proposalType.isEnum() && >- proposalType == this.expectedTypes[i]) { >- return R_ENUM + R_ENUM_CONSTANT; >- } >+ // Helper method for findMethods(char[], TypeBinding[], ReferenceBinding, Scope, ObjectVector, boolean, boolean, boolean) >+ private void findLocalMethods( >+ char[] methodName, >+ TypeBinding[] typeArgTypes, >+ TypeBinding[] argTypes, >+ MethodBinding[] methods, >+ Scope scope, >+ ObjectVector methodsFound, >+ boolean onlyStaticMethods, >+ boolean exactMatch, >+ ReferenceBinding receiverType, >+ InvocationSite invocationSite, >+ Scope invocationScope, >+ boolean implicitCall, >+ boolean superCall, >+ boolean canBePrefixed, >+ Binding[] missingElements, >+ int[] missingElementsStarts, >+ int[] missingElementsEnds, >+ boolean missingElementsHaveProblems, >+ char[] castedReceiver, >+ int receiverStart, >+ int receiverEnd) { > >- } >- } >- return 0; >- } >- private int computeRelevanceForException(){ >- if (this.assistNodeIsException) { >- return R_EXCEPTION; >- } >- return 0; >- } >- private int computeRelevanceForException(char[] proposalName){ >+ ObjectVector newMethodsFound = new ObjectVector(); >+ // Inherited methods which are hidden by subclasses are filtered out >+ // No visibility checks can be performed without the scope & invocationSite > >- if((this.assistNodeIsException || (this.assistNodeInJavadoc & CompletionOnJavadoc.EXCEPTION) != 0 )&& >- (CharOperation.match(EXCEPTION_PATTERN, proposalName, false) || >- CharOperation.match(ERROR_PATTERN, proposalName, false))) { >- return R_EXCEPTION; >- } >- return 0; >- } >- private int computeRelevanceForExpectingType(TypeBinding proposalType){ >- if(this.expectedTypes != null && proposalType != null) { >- int relevance = 0; >- for (int i = 0; i <= this.expectedTypesPtr; i++) { >- if((this.expectedTypesFilter & SUBTYPE) != 0 >- && proposalType.isCompatibleWith(this.expectedTypes[i])) { >+ int methodLength = methodName.length; >+ int minTypeArgLength = typeArgTypes == null ? 0 : typeArgTypes.length; >+ int minArgLength = argTypes == null ? 0 : argTypes.length; > >- if(CharOperation.equals(this.expectedTypes[i].qualifiedPackageName(), proposalType.qualifiedPackageName()) && >- CharOperation.equals(this.expectedTypes[i].qualifiedSourceName(), proposalType.qualifiedSourceName())) { >- return R_EXACT_EXPECTED_TYPE; >- } >+ next : for (int f = methods.length; --f >= 0;) { >+ MethodBinding method = methods[f]; > >- relevance = R_EXPECTED_TYPE; >- } >- if((this.expectedTypesFilter & SUPERTYPE) != 0 >- && this.expectedTypes[i].isCompatibleWith(proposalType)) { >+ if (method.isSynthetic()) continue next; > >- if(CharOperation.equals(this.expectedTypes[i].qualifiedPackageName(), proposalType.qualifiedPackageName()) && >- CharOperation.equals(this.expectedTypes[i].qualifiedSourceName(), proposalType.qualifiedSourceName())) { >- return R_EXACT_EXPECTED_TYPE; >- } >+ if (method.isDefaultAbstract()) continue next; > >- relevance = R_EXPECTED_TYPE; >- } >+ if (method.isConstructor()) continue next; >+ >+ if (this.options.checkDeprecation && >+ method.isViewedAsDeprecated() && >+ !scope.isDefinedInSameUnit(method.declaringClass)) >+ continue next; >+ >+ //TODO (david) perhaps the relevance of a void method must be lesser than other methods >+ //if (expectedTypesPtr > -1 && method.returnType == BaseTypes.VoidBinding) continue next; >+ >+ if (onlyStaticMethods && !method.isStatic()) continue next; >+ >+ if (this.options.checkVisibility >+ && !method.canBeSeenBy(receiverType, invocationSite, scope)) continue next; >+ >+ if(superCall && method.isAbstract()) { >+ methodsFound.add(new Object[]{method, receiverType}); >+ continue next; > } >- return relevance; >- } >- return 0; >- } >- private int computeRelevanceForExpectingType(char[] packageName, char[] typeName){ >- if(this.expectedTypes != null) { >- for (int i = 0; i <= this.expectedTypesPtr; i++) { >- if(CharOperation.equals(this.expectedTypes[i].qualifiedPackageName(), packageName) && >- CharOperation.equals(this.expectedTypes[i].qualifiedSourceName(), typeName)) { >- return R_EXACT_EXPECTED_TYPE; >+ >+ if (exactMatch) { >+ if (!CharOperation.equals(methodName, method.selector, false /* ignore case */)) { >+ continue next; >+ } >+ } else { >+ if (methodLength > method.selector.length) continue next; >+ if (!CharOperation.prefixEquals(methodName, method.selector, false /* ignore case */) >+ && !(this.options.camelCaseMatch && CharOperation.camelCaseMatch(methodName, method.selector))) { >+ continue next; > } > } >- if(this.hasJavaLangObjectAsExpectedType) { >- return R_EXPECTED_TYPE; >+ >+ if (minTypeArgLength != 0 && minTypeArgLength != method.typeVariables.length) >+ continue next; >+ >+ if (minTypeArgLength != 0) { >+ method = scope.environment().createParameterizedGenericMethod(method, typeArgTypes); > } >- } >- return 0; >- } > >- private int computeRelevanceForInheritance(ReferenceBinding receiverType, ReferenceBinding declaringClass) { >- if (receiverType == declaringClass) return R_NON_INHERITED; >- return 0; >- } >+ if (minArgLength > method.parameters.length) >+ continue next; > >- int computeRelevanceForInterestingProposal(){ >- return computeRelevanceForInterestingProposal(null); >- } >- private int computeRelevanceForInterestingProposal(Binding binding){ >- if(this.uninterestingBindings != null) { >- for (int i = 0; i <= this.uninterestingBindingsPtr; i++) { >- if(this.uninterestingBindings[i] == binding) { >- return 0; >- } >- } >- } >- return R_INTERESTING; >- } >- private void computeUninterestingBindings(ASTNode parent, Scope scope){ >- if(parent instanceof LocalDeclaration) { >- addUninterestingBindings(((LocalDeclaration)parent).binding); >- } else if (parent instanceof FieldDeclaration) { >- addUninterestingBindings(((FieldDeclaration)parent).binding); >- } >- } >- >- private void findLabels(char[] label, char[][] choices) { >- if(choices == null || choices.length == 0) return; >- >- int length = label.length; >- for (int i = 0; i < choices.length; i++) { >- if (length <= choices[i].length >- && CharOperation.prefixEquals(label, choices[i], false /* ignore case */ >- )){ >- int relevance = computeBaseRelevance(); >- relevance += computeRelevanceForResolution(); >- relevance += computeRelevanceForInterestingProposal(); >- relevance += computeRelevanceForCaseMatching(label, choices[i]); >- relevance += computeRelevanceForRestrictions(IAccessRule.K_ACCESSIBLE); // no access restriction for keywors >- >- this.noProposal = false; >- if(!this.requestor.isIgnored(CompletionProposal.LABEL_REF)) { >- InternalCompletionProposal proposal = createProposal(CompletionProposal.LABEL_REF, this.actualCompletionPosition); >- proposal.setName(choices[i]); >- proposal.setCompletion(choices[i]); >- proposal.setReplaceRange(this.startPosition - this.offset, this.endPosition - this.offset); >- proposal.setTokenRange(this.tokenStart - this.offset, this.tokenEnd - this.offset); >- proposal.setRelevance(relevance); >- this.requestor.accept(proposal); >- if(DEBUG) { >- this.printDebug(proposal); >+ for (int a = minArgLength; --a >= 0;){ >+ if (argTypes[a] != null) { // can be null if it could not be resolved properly >+ if (!argTypes[a].isCompatibleWith(method.parameters[a])) { >+ continue next; > } > } > } >- } >- } >- >- // Helper method for findMethods(char[], MethodBinding[], Scope, ObjectVector, boolean, boolean, boolean, TypeBinding) >- private void findLocalMethodDeclarations( >- char[] methodName, >- MethodBinding[] methods, >- Scope scope, >- ObjectVector methodsFound, >- // boolean noVoidReturnType, how do you know? >- boolean exactMatch, >- ReferenceBinding receiverType) { >- >- ObjectVector newMethodsFound = new ObjectVector(); >- // Inherited methods which are hidden by subclasses are filtered out >- // No visibility checks can be performed without the scope & invocationSite >- int methodLength = methodName.length; >- next : for (int f = methods.length; --f >= 0;) { >- >- MethodBinding method = methods[f]; >- if (method.isSynthetic()) continue next; >- >- if (method.isDefaultAbstract()) continue next; >- >- if (method.isConstructor()) continue next; >- >- if (method.isFinal()) { >- newMethodsFound.add(method); >- continue next; >- } >- >- if (this.options.checkDeprecation && >- method.isViewedAsDeprecated() && >- !scope.isDefinedInSameUnit(method.declaringClass)) >- continue next; >- >- // if (noVoidReturnType && method.returnType == BaseTypes.VoidBinding) continue next; >- if(method.isStatic()) continue next; > >- if (!method.canBeSeenBy(receiverType, FakeInvocationSite , scope)) continue next; >+ boolean prefixRequired = false; > >- if (exactMatch) { >- if (!CharOperation.equals(methodName, method.selector, false /* ignore case */ >- )) >+ for (int i = methodsFound.size; --i >= 0;) { >+ Object[] other = (Object[]) methodsFound.elementAt(i); >+ MethodBinding otherMethod = (MethodBinding) other[0]; >+ ReferenceBinding otherReceiverType = (ReferenceBinding) other[1]; >+ if (method == otherMethod && receiverType == otherReceiverType) > continue next; > >- } else { >+ if (CharOperation.equals(method.selector, otherMethod.selector, true)) { >+ if (receiverType == otherReceiverType) { >+ if (this.lookupEnvironment.methodVerifier().isMethodSubsignature(otherMethod, method)) { >+ if (!superCall || !otherMethod.declaringClass.isInterface()) { >+ continue next; >+ } >+ } >+ } else { >+ if (this.lookupEnvironment.methodVerifier().isMethodSubsignature(otherMethod, method)) { >+ if(receiverType.isAnonymousType()) continue next; > >- if (methodLength > method.selector.length) >- continue next; >+ if(!superCall) { >+ if(!canBePrefixed) continue next; > >- if (!CharOperation.prefixEquals(methodName, method.selector, false/* ignore case */) >- && !(this.options.camelCaseMatch && CharOperation.camelCaseMatch(methodName, method.selector))) >- continue next; >+ prefixRequired = true; >+ } >+ } >+ } >+ } > } > >- for (int i = methodsFound.size; --i >= 0;) { >- MethodBinding otherMethod = (MethodBinding) methodsFound.elementAt(i); >- if (method == otherMethod) >- continue next; >+ newMethodsFound.add(new Object[]{method, receiverType}); > >- if (CharOperation.equals(method.selector, otherMethod.selector, true) >- && this.lookupEnvironment.methodVerifier().isMethodSubsignature(otherMethod, method)) { >- continue next; >+ ReferenceBinding superTypeWithSameErasure = (ReferenceBinding)receiverType.findSuperTypeOriginatingFrom(method.declaringClass); >+ if (method.declaringClass != superTypeWithSameErasure) { >+ MethodBinding[] otherMethods = superTypeWithSameErasure.getMethods(method.selector); >+ for (int i = 0; i < otherMethods.length; i++) { >+ if(otherMethods[i].original() == method.original()) { >+ method = otherMethods[i]; >+ } > } > } > >- newMethodsFound.add(method); >- > int length = method.parameters.length; > char[][] parameterPackageNames = new char[length][]; >- char[][] parameterFullTypeNames = new char[length][]; >+ char[][] parameterTypeNames = new char[length][]; > > for (int i = 0; i < length; i++) { >- TypeBinding type = method.parameters[i]; >+ TypeBinding type = method.original().parameters[i]; > parameterPackageNames[i] = type.qualifiedPackageName(); >- parameterFullTypeNames[i] = type.qualifiedSourceName(); >+ parameterTypeNames[i] = type.qualifiedSourceName(); > } >+ char[][] parameterNames = findMethodParameterNames(method,parameterTypeNames); > >- char[][] parameterNames = findMethodParameterNames(method, parameterFullTypeNames); >+ char[] completion = CharOperation.NO_CHAR; > >- if(method.typeVariables != null && method.typeVariables.length > 0) { >- char[][] excludedNames = findEnclosingTypeNames(scope); >- char[][] substituedParameterNames = substituteMethodTypeParameterNames(method.typeVariables, excludedNames); >- if(substituedParameterNames != null) { >- method = new ParameterizedMethodBinding( >- method.declaringClass, >- method, >- substituedParameterNames, >- scope.environment()); >+ int previousStartPosition = this.startPosition; >+ int previousTokenStart = this.tokenStart; >+ >+ // Special case for completion in javadoc >+ if (this.assistNodeInJavadoc > 0) { >+ Expression receiver = null; >+ if (invocationSite instanceof CompletionOnJavadocMessageSend) { >+ CompletionOnJavadocMessageSend msg = (CompletionOnJavadocMessageSend) invocationSite; >+ receiver = msg.receiver; >+ } else if (invocationSite instanceof CompletionOnJavadocFieldReference) { >+ CompletionOnJavadocFieldReference fieldRef = (CompletionOnJavadocFieldReference) invocationSite; >+ receiver = fieldRef.receiver; > } >- } >+ if (receiver != null) { >+ StringBuffer javadocCompletion = new StringBuffer(); >+ if (receiver.isThis()) { >+ if ((this.assistNodeInJavadoc & CompletionOnJavadoc.TEXT) != 0) { >+ javadocCompletion.append('#'); >+ } >+ } else if ((this.assistNodeInJavadoc & CompletionOnJavadoc.TEXT) != 0) { >+ if (receiver instanceof JavadocSingleTypeReference) { >+ JavadocSingleTypeReference typeRef = (JavadocSingleTypeReference) receiver; >+ javadocCompletion.append(typeRef.token); >+ javadocCompletion.append('#'); >+ } else if (receiver instanceof JavadocQualifiedTypeReference) { >+ JavadocQualifiedTypeReference typeRef = (JavadocQualifiedTypeReference) receiver; >+ completion = CharOperation.concat(CharOperation.concatWith(typeRef.tokens, '.'), method.selector, '#'); >+ for (int t=0,nt =typeRef.tokens.length; t<nt; t++) { >+ if (t>0) javadocCompletion.append('.'); >+ javadocCompletion.append(typeRef.tokens[t]); >+ } >+ javadocCompletion.append('#'); >+ } >+ } >+ javadocCompletion.append(method.selector); >+ // Append parameters types >+ javadocCompletion.append('('); >+ if (method.parameters != null) { >+ boolean isVarargs = method.isVarargs(); >+ for (int p=0, ln=method.parameters.length; p<ln; p++) { >+ if (p>0) javadocCompletion.append(", "); //$NON-NLS-1$ >+ TypeBinding argTypeBinding = method.parameters[p]; >+ if (isVarargs && p == ln - 1) { >+ createVargsType(argTypeBinding.erasure(), scope, javadocCompletion); >+ } else { >+ createType(argTypeBinding.erasure(), scope,javadocCompletion); >+ } >+ } >+ } >+ javadocCompletion.append(')'); >+ completion = javadocCompletion.toString().toCharArray(); >+ } >+ } else { >+ // nothing to insert - do not want to replace the existing selector & arguments >+ if (!exactMatch) { >+ if (this.source != null >+ && this.source.length > this.endPosition >+ && this.source[this.endPosition] == '(') >+ completion = method.selector; >+ else >+ completion = CharOperation.concat(method.selector, new char[] { '(', ')' }); > >- StringBuffer completion = new StringBuffer(10); >- if (!exactMatch) { >- createMethod(method, parameterPackageNames, parameterFullTypeNames, parameterNames, scope, completion); >+ if (castedReceiver != null) { >+ completion = CharOperation.concat(castedReceiver, completion); >+ } >+ } else { >+ if(prefixRequired && (this.source != null)) { >+ completion = CharOperation.subarray(this.source, this.startPosition, this.endPosition); >+ } else { >+ this.startPosition = this.endPosition; >+ } >+ this.tokenStart = this.tokenEnd; >+ } >+ >+ if(prefixRequired || this.options.forceImplicitQualification){ >+ char[] prefix = computePrefix(scope.enclosingSourceType(), invocationScope.enclosingSourceType(), method.isStatic()); >+ completion = CharOperation.concat(prefix,completion,'.'); >+ } > } > > int relevance = computeBaseRelevance(); > relevance += computeRelevanceForResolution(); > relevance += computeRelevanceForInterestingProposal(); >- relevance += computeRelevanceForCaseMatching(methodName, method.selector); >- relevance += R_METHOD_OVERIDE; >- if(method.isAbstract()) relevance += R_ABSTRACT_METHOD; >+ if (methodName != null) relevance += computeRelevanceForCaseMatching(methodName, method.selector); >+ relevance += computeRelevanceForExpectingType(method.returnType); >+ relevance += computeRelevanceForEnumConstant(method.returnType); >+ relevance += computeRelevanceForStatic(onlyStaticMethods, method.isStatic()); >+ relevance += computeRelevanceForQualification(prefixRequired); > relevance += computeRelevanceForRestrictions(IAccessRule.K_ACCESSIBLE); >+ if (onlyStaticMethods && this.insideQualifiedReference) { >+ relevance += computeRelevanceForInheritance(receiverType, method.declaringClass); >+ } >+ if (missingElements != null) { >+ relevance += computeRelevanceForMissingElements(missingElementsHaveProblems); >+ } > > this.noProposal = false; >- if(!this.requestor.isIgnored(CompletionProposal.METHOD_DECLARATION)) { >- InternalCompletionProposal proposal = createProposal(CompletionProposal.METHOD_DECLARATION, this.actualCompletionPosition); >- proposal.setDeclarationSignature(getSignature(method.declaringClass)); >- proposal.setDeclarationKey(method.declaringClass.computeUniqueKey()); >- proposal.setSignature(getSignature(method)); >- MethodBinding original = method.original(); >- if(original != method) { >- proposal.setOriginalSignature(getSignature(original)); >+ >+ if (castedReceiver == null) { >+ // Standard proposal >+ if(!this.isIgnored(CompletionProposal.METHOD_REF, missingElements != null) && (this.assistNodeInJavadoc & CompletionOnJavadoc.ONLY_INLINE_TAG) == 0) { >+ InternalCompletionProposal proposal = createProposal(CompletionProposal.METHOD_REF, this.actualCompletionPosition); >+ proposal.setDeclarationSignature(getSignature(method.declaringClass)); >+ proposal.setSignature(getSignature(method)); >+ MethodBinding original = method.original(); >+ if(original != method) { >+ proposal.setOriginalSignature(getSignature(original)); >+ } >+ proposal.setDeclarationPackageName(method.declaringClass.qualifiedPackageName()); >+ proposal.setDeclarationTypeName(method.declaringClass.qualifiedSourceName()); >+ proposal.setParameterPackageNames(parameterPackageNames); >+ proposal.setParameterTypeNames(parameterTypeNames); >+ proposal.setPackageName(method.returnType.qualifiedPackageName()); >+ proposal.setTypeName(method.returnType.qualifiedSourceName()); >+ proposal.setName(method.selector); >+ if (missingElements != null) { >+ CompletionProposal[] subProposals = new CompletionProposal[missingElements.length]; >+ for (int i = 0; i < missingElements.length; i++) { >+ subProposals[i] = >+ createRequiredTypeProposal( >+ missingElements[i], >+ missingElementsStarts[i], >+ missingElementsEnds[i], >+ relevance); >+ } >+ proposal.setRequiredProposals(subProposals); >+ } >+ proposal.setCompletion(completion); >+ proposal.setFlags(method.modifiers); >+ proposal.setReplaceRange(this.startPosition - this.offset, this.endPosition - this.offset); >+ proposal.setTokenRange(this.tokenStart - this.offset, this.tokenEnd - this.offset); >+ proposal.setRelevance(relevance); >+ if(parameterNames != null) proposal.setParameterNames(parameterNames); >+ this.requestor.accept(proposal); >+ if(DEBUG) { >+ this.printDebug(proposal); >+ } > } >- proposal.setKey(method.computeUniqueKey()); >- proposal.setDeclarationPackageName(method.declaringClass.qualifiedPackageName()); >- proposal.setDeclarationTypeName(method.declaringClass.qualifiedSourceName()); >- proposal.setParameterPackageNames(parameterPackageNames); >- proposal.setParameterTypeNames(parameterFullTypeNames); >- proposal.setPackageName(method.returnType.qualifiedPackageName()); >- proposal.setTypeName(method.returnType.qualifiedSourceName()); >- proposal.setCompletion(completion.toString().toCharArray()); >- proposal.setName(method.selector); >- proposal.setFlags(method.modifiers); >- proposal.setReplaceRange(this.startPosition - this.offset, this.endPosition - this.offset); >- proposal.setTokenRange(this.tokenStart - this.offset, this.tokenEnd - this.offset); >- proposal.setRelevance(relevance); >- if(parameterNames != null) proposal.setParameterNames(parameterNames); >- this.requestor.accept(proposal); >- if(DEBUG) { >- this.printDebug(proposal); >+ >+ // Javadoc proposal >+ if ((this.assistNodeInJavadoc & CompletionOnJavadoc.TEXT) != 0 && !this.requestor.isIgnored(CompletionProposal.JAVADOC_METHOD_REF)) { >+ char[] javadocCompletion = inlineTagCompletion(completion, JavadocTagConstants.TAG_LINK); >+ InternalCompletionProposal proposal = createProposal(CompletionProposal.JAVADOC_METHOD_REF, this.actualCompletionPosition); >+ proposal.setDeclarationSignature(getSignature(method.declaringClass)); >+ proposal.setSignature(getSignature(method)); >+ MethodBinding original = method.original(); >+ if(original != method) { >+ proposal.setOriginalSignature(getSignature(original)); >+ } >+ proposal.setDeclarationPackageName(method.declaringClass.qualifiedPackageName()); >+ proposal.setDeclarationTypeName(method.declaringClass.qualifiedSourceName()); >+ proposal.setParameterPackageNames(parameterPackageNames); >+ proposal.setParameterTypeNames(parameterTypeNames); >+ proposal.setPackageName(method.returnType.qualifiedPackageName()); >+ proposal.setTypeName(method.returnType.qualifiedSourceName()); >+ proposal.setName(method.selector); >+ proposal.setCompletion(javadocCompletion); >+ proposal.setFlags(method.modifiers); >+ int start = (this.assistNodeInJavadoc & CompletionOnJavadoc.REPLACE_TAG) != 0 ? this.javadocTagPosition : this.startPosition; >+ proposal.setReplaceRange(start - this.offset, this.endPosition - this.offset); >+ proposal.setTokenRange(this.tokenStart - this.offset, this.tokenEnd - this.offset); >+ proposal.setRelevance(relevance+R_INLINE_TAG); >+ if(parameterNames != null) proposal.setParameterNames(parameterNames); >+ this.requestor.accept(proposal); >+ if(DEBUG) { >+ this.printDebug(proposal); >+ } >+ } >+ } else { >+ if(!this.isIgnored(CompletionProposal.METHOD_REF_WITH_CASTED_RECEIVER, missingElements != null)) { >+ InternalCompletionProposal proposal = createProposal(CompletionProposal.METHOD_REF_WITH_CASTED_RECEIVER, this.actualCompletionPosition); >+ proposal.setDeclarationSignature(getSignature(method.declaringClass)); >+ proposal.setSignature(getSignature(method)); >+ MethodBinding original = method.original(); >+ if(original != method) { >+ proposal.setOriginalSignature(getSignature(original)); >+ } >+ proposal.setReceiverSignature(getSignature(receiverType)); >+ proposal.setDeclarationPackageName(method.declaringClass.qualifiedPackageName()); >+ proposal.setDeclarationTypeName(method.declaringClass.qualifiedSourceName()); >+ proposal.setParameterPackageNames(parameterPackageNames); >+ proposal.setParameterTypeNames(parameterTypeNames); >+ proposal.setPackageName(method.returnType.qualifiedPackageName()); >+ proposal.setTypeName(method.returnType.qualifiedSourceName()); >+ proposal.setName(method.selector); >+ if (missingElements != null) { >+ CompletionProposal[] subProposals = new CompletionProposal[missingElements.length]; >+ for (int i = 0; i < missingElements.length; i++) { >+ subProposals[i] = >+ createRequiredTypeProposal( >+ missingElements[i], >+ missingElementsStarts[i], >+ missingElementsEnds[i], >+ relevance); >+ } >+ proposal.setRequiredProposals(subProposals); >+ } >+ proposal.setCompletion(completion); >+ proposal.setFlags(method.modifiers); >+ proposal.setReplaceRange(this.startPosition - this.offset, this.endPosition - this.offset); >+ proposal.setReceiverRange(receiverStart - this.offset, receiverEnd - this.offset); >+ proposal.setTokenRange(this.tokenStart - this.offset, this.tokenEnd - this.offset); >+ proposal.setRelevance(relevance); >+ if(parameterNames != null) proposal.setParameterNames(parameterNames); >+ this.requestor.accept(proposal); >+ if(DEBUG) { >+ this.printDebug(proposal); >+ } > } > } >+ this.startPosition = previousStartPosition; >+ this.tokenStart = previousTokenStart; > } >+ > methodsFound.addAll(newMethodsFound); > } >+ private void findLocalMethodsFromFavorites( >+ char[] methodName, >+ MethodBinding[] methods, >+ Scope scope, >+ ObjectVector methodsFound, >+ ObjectVector methodsFoundFromFavorites, >+ ReferenceBinding receiverType, >+ InvocationSite invocationSite, >+ Scope invocationScope) { > >- private void createTypeVariable(TypeVariableBinding typeVariable, Scope scope, StringBuffer completion) { >- completion.append(typeVariable.sourceName); >+ char[] typeName = CharOperation.concatWith(receiverType.compoundName, '.'); > >- if (typeVariable.superclass != null && typeVariable.firstBound == typeVariable.superclass) { >- completion.append(' '); >- completion.append(EXTENDS); >- completion.append(' '); >- createType(typeVariable.superclass, scope, completion); >- } >- if (typeVariable.superInterfaces != null && typeVariable.superInterfaces != Binding.NO_SUPERINTERFACES) { >- if (typeVariable.firstBound != typeVariable.superclass) { >- completion.append(' '); >- completion.append(EXTENDS); >- completion.append(' '); >- } >- for (int i = 0, length = typeVariable.superInterfaces.length; i < length; i++) { >- if (i > 0 || typeVariable.firstBound == typeVariable.superclass) { >- completion.append(' '); >- completion.append(EXTENDS); >- completion.append(' '); >- } >- createType(typeVariable.superInterfaces[i], scope, completion); >- } >- } >- } >+ int methodLength = methodName.length; > >- private void createType(TypeBinding type, Scope scope, StringBuffer completion) { >- switch (type.kind()) { >- case Binding.BASE_TYPE : >- completion.append(type.sourceName()); >- break; >- case Binding.WILDCARD_TYPE : >- case Binding.INTERSECTION_TYPE : // TODO (david) need to handle intersection type specifically >- WildcardBinding wildcardBinding = (WildcardBinding) type; >- completion.append('?'); >- switch (wildcardBinding.boundKind) { >- case Wildcard.EXTENDS: >- completion.append(' '); >- completion.append(EXTENDS); >- completion.append(' '); >- createType(wildcardBinding.bound, scope, completion); >- if(wildcardBinding.otherBounds != null) { >+ next : for (int f = methods.length; --f >= 0;) { >+ MethodBinding method = methods[f]; > >- int length = wildcardBinding.otherBounds.length; >- for (int i = 0; i < length; i++) { >- completion.append(' '); >- completion.append('&'); >- completion.append(' '); >- createType(wildcardBinding.otherBounds[i], scope, completion); >- } >+ if (method.isSynthetic()) continue next; >+ >+ if (method.isDefaultAbstract()) continue next; >+ >+ if (method.isConstructor()) continue next; >+ >+ if (this.options.checkDeprecation && >+ method.isViewedAsDeprecated() && >+ !scope.isDefinedInSameUnit(method.declaringClass)) >+ continue next; >+ >+ if (!method.isStatic()) continue next; >+ >+ if (this.options.checkVisibility >+ && !method.canBeSeenBy(receiverType, invocationSite, scope)) continue next; >+ >+ if (methodLength > method.selector.length) continue next; >+ >+ if (!CharOperation.prefixEquals(methodName, method.selector, false /* ignore case */) >+ && !(this.options.camelCaseMatch && CharOperation.camelCaseMatch(methodName, method.selector))) { >+ continue next; >+ } >+ >+ for (int i = methodsFoundFromFavorites.size; --i >= 0;) { >+ Object[] other = (Object[]) methodsFoundFromFavorites.elementAt(i); >+ MethodBinding otherMethod = (MethodBinding) other[0]; >+ >+ if (method == otherMethod) continue next; >+ >+ if (CharOperation.equals(method.selector, otherMethod.selector, true)) { >+ if (otherMethod.declaringClass == method.declaringClass && >+ this.lookupEnvironment.methodVerifier().isMethodSubsignature(otherMethod, method)) { >+ continue next; > } >- break; >- case Wildcard.SUPER: >- completion.append(' '); >- completion.append(SUPER); >- completion.append(' '); >- createType(wildcardBinding.bound, scope, completion); >- break; >+ } > } >- break; >- case Binding.ARRAY_TYPE : >- createType(type.leafComponentType(), scope, completion); >- int dim = type.dimensions(); >- for (int i = 0; i < dim; i++) { >- completion.append('['); >- completion.append(']'); >+ >+ for (int i = methodsFound.size; --i >= 0;) { >+ Object[] other = (Object[]) methodsFound.elementAt(i); >+ MethodBinding otherMethod = (MethodBinding) other[0]; >+ >+ if (method == otherMethod) continue next; >+ >+ if (CharOperation.equals(method.selector, otherMethod.selector, true)) { >+ if (this.lookupEnvironment.methodVerifier().isMethodSubsignature(otherMethod, method)) { >+ continue next; >+ } >+ } > } >- break; >- case Binding.PARAMETERIZED_TYPE : >- ParameterizedTypeBinding parameterizedType = (ParameterizedTypeBinding) type; >- if (type.isMemberType()) { >- createType(parameterizedType.enclosingType(), scope, completion); >- completion.append('.'); >- completion.append(parameterizedType.sourceName); >- } else { >- completion.append(CharOperation.concatWith(parameterizedType.genericType().compoundName, '.')); >- } >- if (parameterizedType.arguments != null) { >- completion.append('<'); >- for (int i = 0, length = parameterizedType.arguments.length; i < length; i++) { >- if (i != 0) completion.append(','); >- createType(parameterizedType.arguments[i], scope, completion); >- } >- completion.append('>'); >- } >- break; >- default : >- char[] packageName = type.qualifiedPackageName(); >- char[] typeName = type.qualifiedSourceName(); >- if(mustQualifyType( >- (ReferenceBinding)type, >- packageName, >- scope)) { >- completion.append(CharOperation.concat(packageName, typeName,'.')); >- } else { >- completion.append(type.sourceName()); >- } >- break; >- } >- } >- >- private void createVargsType(TypeBinding type, Scope scope, StringBuffer completion) { >- if (type.isArrayType()) { >- createType(type.leafComponentType(), scope, completion); >- int dim = type.dimensions() - 1; >- for (int i = 0; i < dim; i++) { >- completion.append('['); >- completion.append(']'); >- } >- completion.append(VARARGS); >- } else { >- createType(type, scope, completion); >- } >- } >- private char[] createImportCharArray(char[] importedElement, boolean isStatic, boolean onDemand) { >- char[] result = IMPORT; >- if (isStatic) { >- result = CharOperation.concat(result, STATIC, ' '); >- } >- result = CharOperation.concat(result, importedElement, ' '); >- if (onDemand) { >- result = CharOperation.concat(result, ON_DEMAND); >- } >- return CharOperation.concat(result, IMPORT_END); >- } >- private void createMethod(MethodBinding method, char[][] parameterPackageNames, char[][] parameterTypeNames, char[][] parameterNames, Scope scope, StringBuffer completion) { >- //// Modifiers >- // flush uninteresting modifiers >- int insertedModifiers = method.modifiers & ~(ClassFileConstants.AccNative | ClassFileConstants.AccAbstract); >- if(insertedModifiers != ClassFileConstants.AccDefault){ >- ASTNode.printModifiers(insertedModifiers, completion); >- } > >- //// Type parameters >+ boolean proposeStaticImport = !(this.compilerOptions.complianceLevel < ClassFileConstants.JDK1_5) && >+ this.options.suggestStaticImport; > >- TypeVariableBinding[] typeVariableBindings = method.typeVariables; >- if(typeVariableBindings != null && typeVariableBindings.length != 0) { >- completion.append('<'); >- for (int i = 0; i < typeVariableBindings.length; i++) { >- if(i != 0) { >- completion.append(','); >- completion.append(' '); >+ boolean isAlreadyImported = false; >+ if (!proposeStaticImport) { >+ if(!this.importCachesInitialized) { >+ initializeImportCaches(); >+ } >+ for (int j = 0; j < this.importCacheCount; j++) { >+ char[][] importName = this.importsCache[j]; >+ if(CharOperation.equals(receiverType.sourceName, importName[0])) { >+ if (!CharOperation.equals(typeName, importName[1])) { >+ continue next; >+ } else { >+ isAlreadyImported = true; >+ } >+ } >+ } > } >- createTypeVariable(typeVariableBindings[i], scope, completion); >- } >- completion.append('>'); >- completion.append(' '); >- } > >- //// Return type >- createType(method.returnType, scope, completion); >- completion.append(' '); >+ methodsFoundFromFavorites.add(new Object[]{method, receiverType}); > >- //// Selector >- completion.append(method.selector); >+ ReferenceBinding superTypeWithSameErasure = (ReferenceBinding)receiverType.findSuperTypeOriginatingFrom(method.declaringClass); >+ if (method.declaringClass != superTypeWithSameErasure) { >+ MethodBinding[] otherMethods = superTypeWithSameErasure.getMethods(method.selector); >+ for (int i = 0; i < otherMethods.length; i++) { >+ if(otherMethods[i].original() == method.original()) { >+ method = otherMethods[i]; >+ } >+ } >+ } > >- completion.append('('); >+ int length = method.parameters.length; >+ char[][] parameterPackageNames = new char[length][]; >+ char[][] parameterTypeNames = new char[length][]; > >- ////Parameters >- TypeBinding[] parameterTypes = method.parameters; >- int length = parameterTypes.length; >- for (int i = 0; i < length; i++) { >- if(i != 0) { >- completion.append(','); >- completion.append(' '); >- } >- createType(parameterTypes[i], scope, completion); >- completion.append(' '); >- if(parameterNames != null){ >- completion.append(parameterNames[i]); >- } else { >- completion.append('%'); >- } >- } >+ for (int i = 0; i < length; i++) { >+ TypeBinding type = method.original().parameters[i]; >+ parameterPackageNames[i] = type.qualifiedPackageName(); >+ parameterTypeNames[i] = type.qualifiedSourceName(); >+ } >+ char[][] parameterNames = findMethodParameterNames(method,parameterTypeNames); > >- completion.append(')'); >+ char[] completion = CharOperation.NO_CHAR; > >- //// Exceptions >- ReferenceBinding[] exceptions = method.thrownExceptions; >+ int previousStartPosition = this.startPosition; >+ int previousTokenStart = this.tokenStart; > >- if (exceptions != null && exceptions.length > 0){ >- completion.append(' '); >- completion.append(THROWS); >- completion.append(' '); >- for(int i = 0; i < exceptions.length ; i++){ >- if(i != 0) { >- completion.append(' '); >- completion.append(','); >+ if (this.source != null >+ && this.source.length > this.endPosition >+ && this.source[this.endPosition] == '(') { >+ completion = method.selector; >+ } else { >+ completion = CharOperation.concat(method.selector, new char[] { '(', ')' }); > } >- createType(exceptions[i], scope, completion); >- } >- } >- } > >- private boolean isIgnored(int kind, boolean missingTypes) { >- return this.requestor.isIgnored(kind) || >- (missingTypes && !this.requestor.isAllowingRequiredProposals(kind, CompletionProposal.TYPE_REF)); >- } >+ int relevance = computeBaseRelevance(); >+ relevance += computeRelevanceForResolution(); >+ relevance += computeRelevanceForInterestingProposal(); >+ if (methodName != null) relevance += computeRelevanceForCaseMatching(methodName, method.selector); >+ relevance += computeRelevanceForExpectingType(method.returnType); >+ relevance += computeRelevanceForEnumConstant(method.returnType); >+ relevance += computeRelevanceForStatic(true, method.isStatic()); >+ relevance += computeRelevanceForQualification(true); >+ relevance += computeRelevanceForRestrictions(IAccessRule.K_ACCESSIBLE); > >- private boolean isIgnored(int kind) { >- return this.requestor.isIgnored(kind); >- } >+ CompilationUnitDeclaration cu = this.unitScope.referenceContext; >+ int importStart = cu.types[0].declarationSourceStart; >+ int importEnd = importStart; > >- private boolean isIgnored(int kind, int requiredProposalKind) { >- return this.requestor.isIgnored(kind) || >- !this.requestor.isAllowingRequiredProposals(kind, requiredProposalKind); >- } >+ this.noProposal = false; > >- private void findMethods( >- char[] selector, >- TypeBinding[] typeArgTypes, >- TypeBinding[] argTypes, >- ReferenceBinding receiverType, >- Scope scope, >- ObjectVector methodsFound, >- boolean onlyStaticMethods, >- boolean exactMatch, >- boolean isCompletingDeclaration, >- InvocationSite invocationSite, >- Scope invocationScope, >- boolean implicitCall, >- boolean superCall, >- boolean canBePrefixed, >- Binding[] missingElements, >- int[] missingElementsStarts, >- int[] missingElementsEnds, >- boolean missingElementsHaveProblems, >- char[] castedReceiver, >- int receiverStart, >- int receiverEnd) { >+ if (!proposeStaticImport) { >+ if (isAlreadyImported) { >+ if (!isIgnored(CompletionProposal.METHOD_REF)) { >+ completion = CharOperation.concat(receiverType.sourceName, completion, '.'); > >- boolean notInJavadoc = this.assistNodeInJavadoc == 0; >- if (selector == null && notInJavadoc) { >- return; >- } >+ InternalCompletionProposal proposal = createProposal(CompletionProposal.METHOD_REF, this.actualCompletionPosition); >+ proposal.setDeclarationSignature(getSignature(method.declaringClass)); >+ proposal.setSignature(getSignature(method)); >+ MethodBinding original = method.original(); >+ if(original != method) { >+ proposal.setOriginalSignature(getSignature(original)); >+ } >+ proposal.setDeclarationPackageName(method.declaringClass.qualifiedPackageName()); >+ proposal.setDeclarationTypeName(method.declaringClass.qualifiedSourceName()); >+ proposal.setParameterPackageNames(parameterPackageNames); >+ proposal.setParameterTypeNames(parameterTypeNames); >+ proposal.setPackageName(method.returnType.qualifiedPackageName()); >+ proposal.setTypeName(method.returnType.qualifiedSourceName()); >+ proposal.setName(method.selector); >+ proposal.setCompletion(completion); >+ proposal.setFlags(method.modifiers); >+ proposal.setReplaceRange(this.startPosition - this.offset, this.endPosition - this.offset); >+ proposal.setTokenRange(this.tokenStart - this.offset, this.tokenEnd - this.offset); >+ proposal.setRelevance(relevance); >+ if(parameterNames != null) proposal.setParameterNames(parameterNames); > >- if(isCompletingDeclaration) { >- MethodBinding[] methods = receiverType.availableMethods(); >- if (methods != null){ >- for (int i = 0; i < methods.length; i++) { >- if(!methods[i].isDefaultAbstract()) { >- methodsFound.add(methods[i]); >- } >- } >- } >- } >+ this.requestor.accept(proposal); >+ if(DEBUG) { >+ this.printDebug(proposal); >+ } >+ } >+ } else if (!this.isIgnored(CompletionProposal.METHOD_REF, CompletionProposal.TYPE_IMPORT)) { >+ completion = CharOperation.concat(receiverType.sourceName, completion, '.'); > >- ReferenceBinding currentType = receiverType; >- if (notInJavadoc) { >- if (receiverType.isInterface()) { >- if (isCompletingDeclaration) { >- findInterfacesMethods( >- selector, >- typeArgTypes, >- argTypes, >- receiverType, >- currentType.superInterfaces(), >- scope, >- methodsFound, >- onlyStaticMethods, >- exactMatch, >- isCompletingDeclaration, >- invocationSite, >- invocationScope, >- implicitCall, >- superCall, >- canBePrefixed, >- missingElements, >- missingElementsStarts, >- missingElementsEnds, >- missingElementsHaveProblems, >- castedReceiver, >- receiverStart, >- receiverEnd); >- } else { >- findInterfacesMethods( >- selector, >- typeArgTypes, >- argTypes, >- receiverType, >- new ReferenceBinding[]{currentType}, >- scope, >- methodsFound, >- onlyStaticMethods, >- exactMatch, >- isCompletingDeclaration, >- invocationSite, >- invocationScope, >- implicitCall, >- superCall, >- canBePrefixed, >- missingElements, >- missingElementsStarts, >- missingElementsEnds, >- missingElementsHaveProblems, >- castedReceiver, >- receiverStart, >- receiverEnd); >- } >- >- currentType = scope.getJavaLangObject(); >- } else { >- if (isCompletingDeclaration){ >- findInterfacesMethods( >- selector, >- typeArgTypes, >- argTypes, >- receiverType, >- currentType.superInterfaces(), >- scope, >- methodsFound, >- onlyStaticMethods, >- exactMatch, >- isCompletingDeclaration, >- invocationSite, >- invocationScope, >- implicitCall, >- superCall, >- canBePrefixed, >- missingElements, >- missingElementsStarts, >- missingElementsEnds, >- missingElementsHaveProblems, >- castedReceiver, >- receiverStart, >- receiverEnd); >+ InternalCompletionProposal proposal = createProposal(CompletionProposal.METHOD_REF, this.actualCompletionPosition); >+ proposal.setDeclarationSignature(getSignature(method.declaringClass)); >+ proposal.setSignature(getSignature(method)); >+ MethodBinding original = method.original(); >+ if(original != method) { >+ proposal.setOriginalSignature(getSignature(original)); >+ } >+ proposal.setDeclarationPackageName(method.declaringClass.qualifiedPackageName()); >+ proposal.setDeclarationTypeName(method.declaringClass.qualifiedSourceName()); >+ proposal.setParameterPackageNames(parameterPackageNames); >+ proposal.setParameterTypeNames(parameterTypeNames); >+ proposal.setPackageName(method.returnType.qualifiedPackageName()); >+ proposal.setTypeName(method.returnType.qualifiedSourceName()); >+ proposal.setName(method.selector); >+ proposal.setCompletion(completion); >+ proposal.setFlags(method.modifiers); >+ proposal.setReplaceRange(this.startPosition - this.offset, this.endPosition - this.offset); >+ proposal.setTokenRange(this.tokenStart - this.offset, this.tokenEnd - this.offset); >+ proposal.setRelevance(relevance); >+ if(parameterNames != null) proposal.setParameterNames(parameterNames); > >- currentType = receiverType.superclass(); >- } >- } >- } >- boolean hasPotentialDefaultAbstractMethods = true; >- while (currentType != null) { >+ char[] typeImportCompletion = createImportCharArray(typeName, false, false); > >- MethodBinding[] methods = currentType.availableMethods(); >- if (methods != null) { >- if (isCompletingDeclaration){ >- findLocalMethodDeclarations( >- selector, >- methods, >- scope, >- methodsFound, >- exactMatch, >- receiverType); >- } else{ >- findLocalMethods( >- selector, >- typeArgTypes, >- argTypes, >- methods, >- scope, >- methodsFound, >- onlyStaticMethods, >- exactMatch, >- receiverType, >- invocationSite, >- invocationScope, >- implicitCall, >- superCall, >- canBePrefixed, >- missingElements, >- missingElementsStarts, >- missingElementsEnds, >- missingElementsHaveProblems, >- castedReceiver, >- receiverStart, >- receiverEnd); >- } >- } >+ InternalCompletionProposal typeImportProposal = createProposal(CompletionProposal.TYPE_IMPORT, this.actualCompletionPosition); >+ typeImportProposal.nameLookup = this.nameEnvironment.nameLookup; >+ typeImportProposal.completionEngine = this; >+ char[] packageName = receiverType.qualifiedPackageName(); >+ typeImportProposal.setDeclarationSignature(packageName); >+ typeImportProposal.setSignature(getSignature(receiverType)); >+ typeImportProposal.setPackageName(packageName); >+ typeImportProposal.setTypeName(receiverType.qualifiedSourceName()); >+ typeImportProposal.setCompletion(typeImportCompletion); >+ typeImportProposal.setFlags(receiverType.modifiers); >+ typeImportProposal.setAdditionalFlags(CompletionFlags.Default); >+ typeImportProposal.setReplaceRange(importStart - this.offset, importEnd - this.offset); >+ typeImportProposal.setTokenRange(importStart - this.offset, importEnd - this.offset); >+ typeImportProposal.setRelevance(relevance); > >- if (hasPotentialDefaultAbstractMethods && >- (currentType.isAbstract() || >- currentType.isTypeVariable() || >- currentType.isIntersectionType() || >- currentType.isEnum())){ >+ proposal.setRequiredProposals(new CompletionProposal[]{typeImportProposal}); > >- ReferenceBinding[] superInterfaces = currentType.superInterfaces(); >- if (superInterfaces != null && currentType.isIntersectionType()) { >- for (int i = 0; i < superInterfaces.length; i++) { >- superInterfaces[i] = (ReferenceBinding)superInterfaces[i].capture(invocationScope, invocationSite.sourceEnd()); >+ this.requestor.accept(proposal); >+ if(DEBUG) { >+ this.printDebug(proposal); >+ } > } >- } >- >- findInterfacesMethods( >- selector, >- typeArgTypes, >- argTypes, >- receiverType, >- superInterfaces, >- scope, >- methodsFound, >- onlyStaticMethods, >- exactMatch, >- isCompletingDeclaration, >- invocationSite, >- invocationScope, >- implicitCall, >- superCall, >- canBePrefixed, >- missingElements, >- missingElementsStarts, >- missingElementsEnds, >- missingElementsHaveProblems, >- castedReceiver, >- receiverStart, >- receiverEnd); >- } else { >- hasPotentialDefaultAbstractMethods = false; >- } >- currentType = currentType.superclass(); >- } >- } >- private char[][] findMethodParameterNames(MethodBinding method, char[][] parameterTypeNames){ >- TypeBinding erasure = method.declaringClass.erasure(); >- if(!(erasure instanceof ReferenceBinding)) return null; >- >- char[][] parameterNames = null; >- >- int length = parameterTypeNames.length; >- >- if (length == 0){ >- return CharOperation.NO_CHAR_CHAR; >- } >- // look into the corresponding unit if it is available >- if (erasure instanceof SourceTypeBinding){ >- SourceTypeBinding sourceType = (SourceTypeBinding) erasure; >+ } else { >+ if (!this.isIgnored(CompletionProposal.METHOD_REF, CompletionProposal.METHOD_IMPORT)) { >+ InternalCompletionProposal proposal = createProposal(CompletionProposal.METHOD_REF, this.actualCompletionPosition); >+ proposal.setDeclarationSignature(getSignature(method.declaringClass)); >+ proposal.setSignature(getSignature(method)); >+ MethodBinding original = method.original(); >+ if(original != method) { >+ proposal.setOriginalSignature(getSignature(original)); >+ } >+ proposal.setDeclarationPackageName(method.declaringClass.qualifiedPackageName()); >+ proposal.setDeclarationTypeName(method.declaringClass.qualifiedSourceName()); >+ proposal.setParameterPackageNames(parameterPackageNames); >+ proposal.setParameterTypeNames(parameterTypeNames); >+ proposal.setPackageName(method.returnType.qualifiedPackageName()); >+ proposal.setTypeName(method.returnType.qualifiedSourceName()); >+ proposal.setName(method.selector); >+ proposal.setCompletion(completion); >+ proposal.setFlags(method.modifiers); >+ proposal.setReplaceRange(this.startPosition - this.offset, this.endPosition - this.offset); >+ proposal.setTokenRange(this.tokenStart - this.offset, this.tokenEnd - this.offset); >+ proposal.setRelevance(relevance); >+ if(parameterNames != null) proposal.setParameterNames(parameterNames); > >- if (sourceType.scope != null){ >- TypeDeclaration parsedType; >+ char[] methodImportCompletion = createImportCharArray(CharOperation.concat(typeName, method.selector, '.'), true, false); > >- if ((parsedType = sourceType.scope.referenceContext) != null){ >- AbstractMethodDeclaration methodDecl = parsedType.declarationOf(method.original()); >+ InternalCompletionProposal methodImportProposal = createProposal(CompletionProposal.METHOD_IMPORT, this.actualCompletionPosition); >+ methodImportProposal.setDeclarationSignature(getSignature(method.declaringClass)); >+ methodImportProposal.setSignature(getSignature(method)); >+ if(original != method) { >+ proposal.setOriginalSignature(getSignature(original)); >+ } >+ methodImportProposal.setDeclarationPackageName(method.declaringClass.qualifiedPackageName()); >+ methodImportProposal.setDeclarationTypeName(method.declaringClass.qualifiedSourceName()); >+ methodImportProposal.setParameterPackageNames(parameterPackageNames); >+ methodImportProposal.setParameterTypeNames(parameterTypeNames); >+ methodImportProposal.setPackageName(method.returnType.qualifiedPackageName()); >+ methodImportProposal.setTypeName(method.returnType.qualifiedSourceName()); >+ methodImportProposal.setName(method.selector); >+ methodImportProposal.setCompletion(methodImportCompletion); >+ methodImportProposal.setFlags(method.modifiers); >+ methodImportProposal.setAdditionalFlags(CompletionFlags.StaticImport); >+ methodImportProposal.setReplaceRange(importStart - this.offset, importEnd - this.offset); >+ methodImportProposal.setTokenRange(importStart - this.offset, importEnd - this.offset); >+ methodImportProposal.setRelevance(relevance); >+ if(parameterNames != null) methodImportProposal.setParameterNames(parameterNames); > >- if (methodDecl != null){ >- Argument[] arguments = methodDecl.arguments; >- parameterNames = new char[length][]; >+ proposal.setRequiredProposals(new CompletionProposal[]{methodImportProposal}); > >- for(int i = 0 ; i < length ; i++){ >- parameterNames[i] = arguments[i].name; >+ this.requestor.accept(proposal); >+ if(DEBUG) { >+ this.printDebug(proposal); > } > } > } >+ >+ this.startPosition = previousStartPosition; >+ this.tokenStart = previousTokenStart; > } > } >- // look into the model >- if(parameterNames == null){ > >- ReferenceBinding bindingType = (ReferenceBinding)erasure; >+ // Helper method for findMethods(char[], TypeBinding[], ReferenceBinding, Scope, ObjectVector, boolean, boolean, boolean) >+ private void findLocalMethodsFromStaticImports( >+ char[] methodName, >+ MethodBinding[] methods, >+ Scope scope, >+ boolean exactMatch, >+ ObjectVector methodsFound, >+ ReferenceBinding receiverType, >+ InvocationSite invocationSite) { > >- char[] compoundName = CharOperation.concatWith(bindingType.compoundName, '.'); >- Object type = this.typeCache.get(compoundName); >+ ObjectVector newMethodsFound = new ObjectVector(); > >- ISourceType sourceType = null; >- if(type != null) { >- if(type instanceof ISourceType) { >- sourceType = (ISourceType) type; >- } >- } else { >- NameEnvironmentAnswer answer = this.nameEnvironment.findType(bindingType.compoundName); >- if(answer != null && answer.isSourceType()) { >- sourceType = answer.getSourceTypes()[0]; >- this.typeCache.put(compoundName, sourceType); >- } >- } >- >- if(sourceType != null) { >- IType typeHandle = ((SourceTypeElementInfo) sourceType).getHandle(); >- >- String[] parameterTypeSignatures = new String[length]; >- for (int i = 0; i < length; i++) { >- parameterTypeSignatures[i] = Signature.createTypeSignature(parameterTypeNames[i], false); >- } >- IMethod searchedMethod = typeHandle.getMethod(String.valueOf(method.selector), parameterTypeSignatures); >- IMethod[] foundMethods = typeHandle.findMethods(searchedMethod); >- >- if(foundMethods != null) { >- int len = foundMethods.length; >- if(len == 1) { >- try { >- SourceMethod sourceMethod = (SourceMethod) foundMethods[0]; >- parameterNames = ((SourceMethodElementInfo) sourceMethod.getElementInfo()).getArgumentNames(); >- } catch (JavaModelException e) { >- // method doesn't exist: ignore >- } >- } >- } >- } >- } >- return parameterNames; >- } >- >- private void findNestedTypes( >- char[] typeName, >- SourceTypeBinding currentType, >- Scope scope, >- boolean proposeAllMemberTypes, >- ObjectVector typesFound) { >- if (typeName == null) >- return; >- >- int typeLength = typeName.length; >- >- SourceTypeBinding nextTypeToIgnore = null; >- while (scope != null) { // done when a COMPILATION_UNIT_SCOPE is found >- >- switch (scope.kind) { >- >- case Scope.METHOD_SCOPE : >- case Scope.BLOCK_SCOPE : >- BlockScope blockScope = (BlockScope) scope; >+ next : for (int f = methods.length; --f >= 0;) { >+ MethodBinding method = methods[f]; > >- next : for (int i = 0, length = blockScope.subscopeCount; i < length; i++) { >+ if (method.isSynthetic()) continue next; > >- if (blockScope.subscopes[i] instanceof ClassScope) { >- SourceTypeBinding localType = >- ((ClassScope) blockScope.subscopes[i]).referenceContext.binding; >+ if (method.isDefaultAbstract()) continue next; > >- if (!localType.isAnonymousType()) { >- if (isForbidden(localType)) >- continue next; >+ if (method.isConstructor()) continue next; > >- if (typeLength > localType.sourceName.length) >- continue next; >- if (!CharOperation.prefixEquals(typeName, localType.sourceName, false/* ignore case */) >- && !(this.options.camelCaseMatch && CharOperation.camelCaseMatch(typeName, localType.sourceName))) >- continue next; >+ if (!method.isStatic()) continue next; > >- for (int j = typesFound.size; --j >= 0;) { >- ReferenceBinding otherType = (ReferenceBinding) typesFound.elementAt(j); >+ if (this.options.checkDeprecation && >+ method.isViewedAsDeprecated() && >+ !scope.isDefinedInSameUnit(method.declaringClass)) >+ continue next; > >- if (localType == otherType) >- continue next; >- } >+ if (this.options.checkVisibility >+ && !method.canBeSeenBy(receiverType, invocationSite, scope)) continue next; > >- if(this.assistNodeIsClass) { >- if(!localType.isClass()) continue next; >- } else if(this.assistNodeIsInterface) { >- if(!localType.isInterface() && !localType.isAnnotationType()) continue next; >- } else if (this.assistNodeIsAnnotation) { >- if(!localType.isAnnotationType()) continue next; >- } >+ if (!CharOperation.equals(methodName, method.selector, false /* ignore case */) >+ && !(this.options.camelCaseMatch && CharOperation.camelCaseMatch(methodName, method.selector))) >+ continue next; > >- int relevance = computeBaseRelevance(); >- relevance += computeRelevanceForResolution(); >- relevance += computeRelevanceForInterestingProposal(); >- relevance += computeRelevanceForCaseMatching(typeName, localType.sourceName); >- relevance += computeRelevanceForExpectingType(localType); >- relevance += computeRelevanceForException(localType.sourceName); >- relevance += computeRelevanceForClass(); >- relevance += computeRelevanceForQualification(false); >- relevance += computeRelevanceForRestrictions(IAccessRule.K_ACCESSIBLE); // no access restriction for nested type >- relevance += computeRelevanceForAnnotationTarget(localType); >+ for (int i = methodsFound.size; --i >= 0;) { >+ Object[] other = (Object[]) methodsFound.elementAt(i); >+ MethodBinding otherMethod = (MethodBinding) other[0]; >+ ReferenceBinding otherReceiverType = (ReferenceBinding) other[1]; >+ if (method == otherMethod && receiverType == otherReceiverType) >+ continue next; > >- this.noProposal = false; >- if(!this.requestor.isIgnored(CompletionProposal.TYPE_REF)) { >- createTypeProposal( >- localType, >- localType.sourceName, >- IAccessRule.K_ACCESSIBLE, >- localType.sourceName, >- relevance, >- null, >- null, >- null, >- false); >- } >- } >- } >+ if (CharOperation.equals(method.selector, otherMethod.selector, true)) { >+ if (this.lookupEnvironment.methodVerifier().isMethodSubsignature(otherMethod, method)) { >+ continue next; > } >- break; >- >- case Scope.CLASS_SCOPE : >- SourceTypeBinding enclosingSourceType = scope.enclosingSourceType(); >- findMemberTypes( >- typeName, >- enclosingSourceType, >- scope, >- currentType, >- false, >- false, >- false, >- false, >- proposeAllMemberTypes, >- nextTypeToIgnore, >- typesFound, >- null, >- null, >- null, >- false); >- nextTypeToIgnore = enclosingSourceType; >- if (typeLength == 0) >- return; // do not search outside the class scope if no prefix was provided >- break; >- >- case Scope.COMPILATION_UNIT_SCOPE : >- return; >+ } > } >- scope = scope.parent; >- } >- } > >- private void findPackages(CompletionOnPackageReference packageStatement) { >+ newMethodsFound.add(new Object[]{method, receiverType}); > >- this.completionToken = CharOperation.concatWith(packageStatement.tokens, '.'); >- if (this.completionToken.length == 0) >- return; >+ int length = method.parameters.length; >+ char[][] parameterPackageNames = new char[length][]; >+ char[][] parameterTypeNames = new char[length][]; > >- setSourceRange(packageStatement.sourceStart, packageStatement.sourceEnd); >- long completionPosition = packageStatement.sourcePositions[packageStatement.sourcePositions.length - 1]; >- setTokenRange((int) (completionPosition >>> 32), (int) completionPosition); >- this.nameEnvironment.findPackages(CharOperation.toLowerCase(this.completionToken), this); >- } >+ for (int i = 0; i < length; i++) { >+ TypeBinding type = method.original().parameters[i]; >+ parameterPackageNames[i] = type.qualifiedPackageName(); >+ parameterTypeNames[i] = type.qualifiedSourceName(); >+ } >+ char[][] parameterNames = findMethodParameterNames(method,parameterTypeNames); > >- private void findParameterizedType(TypeReference ref, Scope scope) { >- ReferenceBinding refBinding = (ReferenceBinding) ref.resolvedType; >- if(refBinding != null) { >- if (this.options.checkDeprecation && >- refBinding.isViewedAsDeprecated() && >- !scope.isDefinedInSameUnit(refBinding)) >- return; >+ char[] completion = CharOperation.NO_CHAR; > >- int accessibility = IAccessRule.K_ACCESSIBLE; >- if(refBinding.hasRestrictedAccess()) { >- AccessRestriction accessRestriction = this.lookupEnvironment.getAccessRestriction(refBinding); >- if(accessRestriction != null) { >- switch (accessRestriction.getProblemId()) { >- case IProblem.ForbiddenReference: >- if (this.options.checkForbiddenReference) { >- return; >- } >- accessibility = IAccessRule.K_NON_ACCESSIBLE; >- break; >- case IProblem.DiscouragedReference: >- if (this.options.checkDiscouragedReference) { >- return; >- } >- accessibility = IAccessRule.K_DISCOURAGED; >- break; >- } >+ int previousStartPosition = this.startPosition; >+ int previousTokenStart = this.tokenStart; >+ >+ if (!exactMatch) { >+ if (this.source != null >+ && this.source.length > this.endPosition >+ && this.source[this.endPosition] == '(') { >+ completion = method.selector; >+ } else { >+ completion = CharOperation.concat(method.selector, new char[] { '(', ')' }); > } >+ } else { >+ this.startPosition = this.endPosition; >+ this.tokenStart = this.tokenEnd; > } > > int relevance = computeBaseRelevance(); > relevance += computeRelevanceForResolution(); > relevance += computeRelevanceForInterestingProposal(); >- relevance += computeRelevanceForCaseMatching(refBinding.sourceName, refBinding.sourceName); >- relevance += computeRelevanceForExpectingType(refBinding); >+ relevance += computeRelevanceForCaseMatching(methodName, method.selector); >+ relevance += computeRelevanceForExpectingType(method.returnType); >+ relevance += computeRelevanceForEnumConstant(method.returnType); >+ relevance += computeRelevanceForStatic(true, method.isStatic()); > relevance += computeRelevanceForQualification(false); >- relevance += computeRelevanceForRestrictions(accessibility); // no access restriction for type in the current unit >- >- if(!this.requestor.isIgnored(CompletionProposal.TYPE_REF)) { >- createTypeProposal( >- refBinding, >- refBinding.qualifiedSourceName(), >- IAccessRule.K_ACCESSIBLE, >- CharOperation.NO_CHAR, >- relevance, >- null, >- null, >- null, >- false); >- } >- } >- } >- private void findTypeParameters(char[] token, Scope scope) { >- if (this.compilerOptions.sourceLevel < ClassFileConstants.JDK1_5) return; >+ relevance += computeRelevanceForRestrictions(IAccessRule.K_ACCESSIBLE); > >- TypeParameter[] typeParameters = null; >- while (scope != null) { // done when a COMPILATION_UNIT_SCOPE is found >- typeParameters = null; >- switch (scope.kind) { >- case Scope.METHOD_SCOPE : >- MethodScope methodScope = (MethodScope) scope; >- if(methodScope.referenceContext instanceof MethodDeclaration) { >- MethodDeclaration methodDeclaration = (MethodDeclaration) methodScope.referenceContext; >- typeParameters = methodDeclaration.typeParameters; >- } else if(methodScope.referenceContext instanceof ConstructorDeclaration) { >- ConstructorDeclaration methodDeclaration = (ConstructorDeclaration) methodScope.referenceContext; >- typeParameters = methodDeclaration.typeParameters; >- } >- break; >- case Scope.CLASS_SCOPE : >- ClassScope classScope = (ClassScope) scope; >- typeParameters = classScope.referenceContext.typeParameters; >- break; >- case Scope.COMPILATION_UNIT_SCOPE : >- return; >- } >- if(typeParameters != null) { >- for (int i = 0; i < typeParameters.length; i++) { >- int typeLength = token.length; >- TypeParameter typeParameter = typeParameters[i]; >- >- if(typeParameter.binding == null) continue; >- >- if (typeLength > typeParameter.name.length) continue; >- >- if (!CharOperation.prefixEquals(token, typeParameter.name, false) >- && !(this.options.camelCaseMatch && CharOperation.camelCaseMatch(token, typeParameter.name))) continue; >- >- int relevance = computeBaseRelevance(); >- relevance += computeRelevanceForResolution(); >- relevance += computeRelevanceForInterestingProposal(); >- relevance += computeRelevanceForCaseMatching(token, typeParameter.name); >- relevance += computeRelevanceForExpectingType(typeParameter.type == null ? null :typeParameter.type.resolvedType); >- relevance += computeRelevanceForQualification(false); >- relevance += computeRelevanceForException(typeParameter.name); >- relevance += computeRelevanceForRestrictions(IAccessRule.K_ACCESSIBLE); // no access restriction fot type parameter >- >- this.noProposal = false; >- if(!this.requestor.isIgnored(CompletionProposal.TYPE_REF)) { >- createTypeParameterProposal(typeParameter, relevance); >- } >+ this.noProposal = false; >+ if(!this.requestor.isIgnored(CompletionProposal.METHOD_REF)) { >+ InternalCompletionProposal proposal = createProposal(CompletionProposal.METHOD_REF, this.actualCompletionPosition); >+ proposal.setDeclarationSignature(getSignature(method.declaringClass)); >+ proposal.setSignature(getSignature(method)); >+ MethodBinding original = method.original(); >+ if(original != method) { >+ proposal.setOriginalSignature(getSignature(original)); >+ } >+ proposal.setDeclarationPackageName(method.declaringClass.qualifiedPackageName()); >+ proposal.setDeclarationTypeName(method.declaringClass.qualifiedSourceName()); >+ proposal.setParameterPackageNames(parameterPackageNames); >+ proposal.setParameterTypeNames(parameterTypeNames); >+ proposal.setPackageName(method.returnType.qualifiedPackageName()); >+ proposal.setTypeName(method.returnType.qualifiedSourceName()); >+ proposal.setName(method.selector); >+ proposal.setCompletion(completion); >+ proposal.setFlags(method.modifiers); >+ proposal.setReplaceRange(this.startPosition - this.offset, this.endPosition - this.offset); >+ proposal.setTokenRange(this.tokenStart - this.offset, this.tokenEnd - this.offset); >+ proposal.setRelevance(relevance); >+ if(parameterNames != null) proposal.setParameterNames(parameterNames); >+ this.requestor.accept(proposal); >+ if(DEBUG) { >+ this.printDebug(proposal); > } > } >- scope = scope.parent; >+ this.startPosition = previousStartPosition; >+ this.tokenStart = previousTokenStart; > } >+ >+ methodsFound.addAll(newMethodsFound); > } >- private void findTypesAndPackages(char[] token, Scope scope, boolean proposeBaseTypes, boolean proposeVoidType, ObjectVector typesFound) { > >- if (token == null) >- return; >+ private void findLocalMethodsFromStaticImports( >+ char[] token, >+ Scope scope, >+ InvocationSite invocationSite, >+ Scope invocationScope, >+ boolean exactMatch, >+ ObjectVector methodsFound, >+ boolean proposeMethod) { >+ findFieldsAndMethodsFromStaticImports( >+ token, >+ scope, >+ invocationSite, >+ invocationScope, >+ exactMatch, >+ false, >+ new ObjectVector(), >+ new ObjectVector(), >+ methodsFound, >+ false, >+ proposeMethod); >+ } >+ protected void findMembers( >+ char[] token, >+ ReferenceBinding receiverType, >+ Scope scope, >+ InvocationSite invocationSite, >+ boolean isInsideAnnotationAttribute, >+ Binding[] missingElements, >+ int[] missingElementsStarts, >+ int[] missingElementsEnds, >+ boolean missingElementsHaveProblems) { > >- // do not propose type if completion token is empty >- boolean skip = false; >- if (token.length == 0 && NO_TYPE_COMPLETION_ON_EMPTY_TOKEN) { >- if(!this.assistNodeIsConstructor && (this.assistNodeInJavadoc & CompletionOnJavadoc.EXCEPTION) == 0) { >- return; >- } >- skip = true; >+ if (!this.requestor.isIgnored(CompletionProposal.TYPE_REF)) { >+ findMemberTypes( >+ token, >+ receiverType, >+ scope, >+ scope.enclosingSourceType(), >+ false, >+ true, >+ new ObjectVector(), >+ missingElements, >+ missingElementsStarts, >+ missingElementsEnds, >+ missingElementsHaveProblems); > } >- >- boolean proposeType = >- !this.requestor.isIgnored(CompletionProposal.TYPE_REF) || >- ((this.assistNodeInJavadoc & CompletionOnJavadoc.TEXT) != 0 && !this.requestor.isIgnored(CompletionProposal.JAVADOC_TYPE_REF)); >- >- boolean proposeAllMemberTypes = !this.assistNodeIsConstructor; >- >- if (!skip && proposeType && scope.enclosingSourceType() != null) { >- findNestedTypes(token, scope.enclosingSourceType(), scope, proposeAllMemberTypes, typesFound); >- if(!this.assistNodeIsInterface && >- !this.assistNodeIsConstructor && >- !this.assistNodeIsAnnotation && >- this.assistNodeInJavadoc == 0) { >- // don't propose type parameters if the completion is a constructor ('new |') >- findTypeParameters(token, scope); >- } >+ if (!this.requestor.isIgnored(CompletionProposal.FIELD_REF)) { >+ findClassField( >+ token, >+ receiverType, >+ scope, >+ missingElements, >+ missingElementsStarts, >+ missingElementsEnds, >+ missingElementsHaveProblems); > } > >- boolean isEmptyPrefix = token.length == 0; >- >- if (!skip && proposeType && this.unitScope != null) { >- ReferenceBinding outerInvocationType = scope.enclosingSourceType(); >- if(outerInvocationType != null) { >- ReferenceBinding temp = outerInvocationType.enclosingType(); >- while(temp != null) { >- outerInvocationType = temp; >- temp = temp.enclosingType(); >- } >- } >- >- int typeLength = token.length; >- SourceTypeBinding[] types = this.unitScope.topLevelTypes; >- >- next : for (int i = 0, length = types.length; i < length; i++) { >- SourceTypeBinding sourceType = types[i]; >- >- if(isForbidden(sourceType)) continue next; >- >- if(proposeAllMemberTypes && >- sourceType != outerInvocationType) { >- findSubMemberTypes( >- token, >- sourceType, >- scope, >- scope.enclosingSourceType(), >- false, >- false, >- false, >- typesFound); >- } >- >- if (sourceType.sourceName == CompletionParser.FAKE_TYPE_NAME) continue next; >- if (sourceType.sourceName == TypeConstants.PACKAGE_INFO_NAME) continue next; >- >- if (typeLength > sourceType.sourceName.length) continue next; >- >- if (!CharOperation.prefixEquals(token, sourceType.sourceName, false) >- && !(this.options.camelCaseMatch && CharOperation.camelCaseMatch(token, sourceType.sourceName))) continue; >- >- if (this.assistNodeIsAnnotation && !hasPossibleAnnotationTarget(sourceType, scope)) { >- continue next; >- } >- >- for (int j = typesFound.size; --j >= 0;) { >- ReferenceBinding otherType = (ReferenceBinding) typesFound.elementAt(j); >- >- if (sourceType == otherType) continue next; >- } >- >- this.knownTypes.put(CharOperation.concat(sourceType.qualifiedPackageName(), sourceType.sourceName(), '.'), this); >- >- if(this.assistNodeIsClass) { >- if(!sourceType.isClass()) continue next; >- } else if(this.assistNodeIsInterface) { >- if(!sourceType.isInterface() && !sourceType.isAnnotationType()) continue next; >- } else if (this.assistNodeIsAnnotation) { >- if(!sourceType.isAnnotationType()) continue next; >- } else if (isEmptyPrefix && this.assistNodeIsException) { >- if (sourceType.findSuperTypeOriginatingFrom(TypeIds.T_JavaLangThrowable, true) == null) { >- continue next; >- } >- } >- >+ MethodScope methodScope = null; >+ if (!isInsideAnnotationAttribute && >+ !this.requestor.isIgnored(CompletionProposal.KEYWORD) && >+ ((scope instanceof MethodScope && !((MethodScope)scope).isStatic) >+ || ((methodScope = scope.enclosingMethodScope()) != null && !methodScope.isStatic))) { >+ if (token.length > 0) { >+ findKeywords(token, new char[][]{Keywords.THIS}, false, true); >+ } else { > int relevance = computeBaseRelevance(); > relevance += computeRelevanceForResolution(); > relevance += computeRelevanceForInterestingProposal(); >- relevance += computeRelevanceForCaseMatching(token, sourceType.sourceName); >- relevance += computeRelevanceForExpectingType(sourceType); >- relevance += computeRelevanceForQualification(false); >- relevance += computeRelevanceForRestrictions(IAccessRule.K_ACCESSIBLE); // no access restriction for type in the current unit >+ relevance += computeRelevanceForCaseMatching(this.completionToken, Keywords.THIS); >+ relevance += computeRelevanceForRestrictions(IAccessRule.K_ACCESSIBLE); // no access restriction for keywords >+ relevance += R_NON_INHERITED; > >- if (sourceType.isAnnotationType()) { >- relevance += computeRelevanceForAnnotation(); >- relevance += computeRelevanceForAnnotationTarget(sourceType); >- } else if (sourceType.isInterface()) { >- relevance += computeRelevanceForInterface(); >- } else if(sourceType.isClass()){ >- relevance += computeRelevanceForClass(); >- relevance += computeRelevanceForException(sourceType.sourceName); >- } > this.noProposal = false; >- if(proposeType) { >- char[] typeName = sourceType.sourceName(); >- createTypeProposal( >- sourceType, >- typeName, >- IAccessRule.K_ACCESSIBLE, >- typeName, >- relevance, >- null, >- null, >- null, >- false); >+ if (!this.requestor.isIgnored(CompletionProposal.KEYWORD)) { >+ InternalCompletionProposal proposal = createProposal(CompletionProposal.KEYWORD, this.actualCompletionPosition); >+ proposal.setName(Keywords.THIS); >+ proposal.setCompletion(Keywords.THIS); >+ proposal.setReplaceRange(this.startPosition - this.offset, this.endPosition - this.offset); >+ proposal.setTokenRange(this.tokenStart - this.offset, this.tokenEnd - this.offset); >+ proposal.setRelevance(relevance); >+ this.requestor.accept(proposal); >+ if (DEBUG) { >+ this.printDebug(proposal); >+ } > } > } > } > >- if(!skip && proposeType) { >- findTypesFromStaticImports(token, scope, proposeAllMemberTypes, typesFound); >+ if (!this.requestor.isIgnored(CompletionProposal.FIELD_REF)) { >+ findFields( >+ token, >+ receiverType, >+ scope, >+ new ObjectVector(), >+ new ObjectVector(), >+ true, >+ invocationSite, >+ scope, >+ false, >+ false, >+ missingElements, >+ missingElementsStarts, >+ missingElementsEnds, >+ missingElementsHaveProblems, >+ null, >+ -1, >+ -1); > } > >- if (isEmptyPrefix && !this.assistNodeIsAnnotation) { >- if(proposeType && this.expectedTypesPtr > -1) { >- next : for (int i = 0; i <= this.expectedTypesPtr; i++) { >- if(this.expectedTypes[i] instanceof ReferenceBinding) { >- ReferenceBinding refBinding = (ReferenceBinding)this.expectedTypes[i]; >- >- if(refBinding.isTypeVariable() && this.assistNodeIsConstructor) { >- // don't propose type variable if the completion is a constructor ('new |') >- continue next; >- } >- if (this.options.checkDeprecation && >- refBinding.isViewedAsDeprecated() && >- !scope.isDefinedInSameUnit(refBinding)) >- continue next; >- >- int accessibility = IAccessRule.K_ACCESSIBLE; >- if(refBinding.hasRestrictedAccess()) { >- AccessRestriction accessRestriction = this.lookupEnvironment.getAccessRestriction(refBinding); >- if(accessRestriction != null) { >- switch (accessRestriction.getProblemId()) { >- case IProblem.ForbiddenReference: >- if (this.options.checkForbiddenReference) { >- continue next; >- } >- accessibility = IAccessRule.K_NON_ACCESSIBLE; >- break; >- case IProblem.DiscouragedReference: >- if (this.options.checkDiscouragedReference) { >- continue next; >- } >- accessibility = IAccessRule.K_DISCOURAGED; >- break; >- } >- } >- } >- >- for (int j = 0; j < typesFound.size(); j++) { >- ReferenceBinding typeFound = (ReferenceBinding)typesFound.elementAt(j); >- if (typeFound == refBinding) { >- continue next; >- } >- } >+ if (!isInsideAnnotationAttribute && !this.requestor.isIgnored(CompletionProposal.METHOD_REF)) { >+ findMethods( >+ token, >+ null, >+ null, >+ receiverType, >+ scope, >+ new ObjectVector(), >+ true, >+ false, >+ invocationSite, >+ scope, >+ false, >+ false, >+ false, >+ missingElements, >+ missingElementsStarts, >+ missingElementsEnds, >+ missingElementsHaveProblems, >+ null, >+ -1, >+ -1); >+ } >+ } > >- boolean inSameUnit = this.unitScope.isDefinedInSameUnit(refBinding); >+ private void findMembersFromMissingType( >+ final char[] token, >+ final long pos, >+ TypeBinding resolveType, >+ final Scope scope, >+ final InvocationSite invocationSite, >+ final boolean isInsideAnnotationAttribute) { >+ MissingTypesGuesser missingTypesConverter = new MissingTypesGuesser(this); >+ MissingTypesGuesser.GuessedTypeRequestor substitutionRequestor = >+ new MissingTypesGuesser.GuessedTypeRequestor() { >+ public void accept( >+ TypeBinding guessedType, >+ Binding[] missingElements, >+ int[] missingElementsStarts, >+ int[] missingElementsEnds, >+ boolean hasProblems) { >+ if (guessedType instanceof ReferenceBinding) { >+ findMembers( >+ CompletionEngine.this.completionToken, >+ (ReferenceBinding)guessedType, >+ scope, >+ invocationSite, >+ isInsideAnnotationAttribute, >+ missingElements, >+ missingElementsStarts, >+ missingElementsEnds, >+ hasProblems); >+ } >+ } >+ }; >+ SingleTypeReference typeRef = new SingleTypeReference(token, pos); >+ typeRef.resolvedType = new ProblemReferenceBinding(new char[][]{ token }, null, ProblemReasons.NotFound); >+ missingTypesConverter.guess(typeRef, scope, substitutionRequestor); >+ } > >- // top level types of the current unit are already proposed. >- if(skip || !inSameUnit || (inSameUnit && refBinding.isMemberType())) { >- char[] packageName = refBinding.qualifiedPackageName(); >- char[] typeName = refBinding.sourceName(); >- char[] completionName = typeName; >+ private void findMemberTypes( >+ char[] typeName, >+ ReferenceBinding receiverType, >+ Scope scope, >+ SourceTypeBinding typeInvocation, >+ boolean staticOnly, >+ boolean staticFieldsAndMethodOnly, >+ boolean fromStaticImport, >+ boolean checkQualification, >+ boolean proposeAllMemberTypes, >+ SourceTypeBinding typeToIgnore, >+ ObjectVector typesFound, >+ Binding[] missingElements, >+ int[] missingElementsStarts, >+ int[] missingElementsEnds, >+ boolean missingElementsHaveProblems) { > >- boolean isQualified = false; >- if (!this.insideQualifiedReference && !refBinding.isMemberType()) { >- if (mustQualifyType(packageName, typeName, null, refBinding.modifiers)) { >- if (packageName == null || packageName.length == 0) >- if (this.unitScope != null && this.unitScope.fPackage.compoundName != CharOperation.NO_CHAR_CHAR) >- continue next; // ignore types from the default package from outside it >- completionName = CharOperation.concat(packageName, typeName, '.'); >- isQualified = true; >- } >- } >+ ReferenceBinding currentType = receiverType; >+ if (typeName == null) >+ return; > >- if(this.assistNodeIsClass) { >- if(!refBinding.isClass()) continue next; >- } else if(this.assistNodeIsInterface) { >- if(!refBinding.isInterface() && !refBinding.isAnnotationType()) continue next; >- } else if (this.assistNodeIsAnnotation) { >- if(!refBinding.isAnnotationType()) continue next; >- } >+ if (this.insideQualifiedReference >+ || typeName.length == 0) { // do not search up the hierarchy > >- int relevance = computeBaseRelevance(); >- relevance += computeRelevanceForResolution(); >- relevance += computeRelevanceForInterestingProposal(); >- relevance += computeRelevanceForCaseMatching(token, typeName); >- relevance += computeRelevanceForExpectingType(refBinding); >- relevance += computeRelevanceForQualification(isQualified); >- relevance += computeRelevanceForRestrictions(accessibility); >+ findMemberTypes( >+ typeName, >+ currentType.memberTypes(), >+ typesFound, >+ receiverType, >+ typeInvocation, >+ staticOnly, >+ staticFieldsAndMethodOnly, >+ fromStaticImport, >+ checkQualification, >+ scope, >+ missingElements, >+ missingElementsStarts, >+ missingElementsEnds, >+ missingElementsHaveProblems); >+ return; >+ } > >- if(refBinding.isClass()) { >- relevance += computeRelevanceForClass(); >- relevance += computeRelevanceForException(typeName); >- } else if(refBinding.isEnum()) { >- relevance += computeRelevanceForEnum(); >- } else if(refBinding.isInterface()) { >- relevance += computeRelevanceForInterface(); >- } >+ ReferenceBinding[] interfacesToVisit = null; >+ int nextPosition = 0; > >- this.noProposal = false; >- if(!this.requestor.isIgnored(CompletionProposal.TYPE_REF)) { >- InternalCompletionProposal proposal = createProposal(CompletionProposal.TYPE_REF, this.actualCompletionPosition); >- proposal.setDeclarationSignature(packageName); >- proposal.setSignature(getSignature(refBinding)); >- proposal.setPackageName(packageName); >- proposal.setTypeName(typeName); >- proposal.setCompletion(completionName); >- proposal.setFlags(refBinding.modifiers); >- proposal.setReplaceRange(this.startPosition - this.offset, this.endPosition - this.offset); >- proposal.setTokenRange(this.tokenStart - this.offset, this.tokenEnd - this.offset); >- proposal.setRelevance(relevance); >- proposal.setAccessibility(accessibility); >- this.requestor.accept(proposal); >- if(DEBUG) { >- this.printDebug(proposal); >- } >- } >- } >- } >- } >- } >- } else { >- if(!isEmptyPrefix && !this.requestor.isIgnored(CompletionProposal.KEYWORD)) { >- if (this.assistNodeInJavadoc == 0 || (this.assistNodeInJavadoc & CompletionOnJavadoc.BASE_TYPES) != 0) { >- if (proposeBaseTypes) { >- if (proposeVoidType) { >- findKeywords(token, BASE_TYPE_NAMES, false, false); >- } else { >- findKeywords(token, BASE_TYPE_NAMES_WITHOUT_VOID, false, false); >- } >+ do { >+ ReferenceBinding[] itsInterfaces = currentType.superInterfaces(); >+ if (itsInterfaces != null && itsInterfaces != Binding.NO_SUPERINTERFACES) { >+ if (interfacesToVisit == null) { >+ interfacesToVisit = itsInterfaces; >+ nextPosition = interfacesToVisit.length; >+ } else { >+ int itsLength = itsInterfaces.length; >+ if (nextPosition + itsLength >= interfacesToVisit.length) >+ System.arraycopy(interfacesToVisit, 0, interfacesToVisit = new ReferenceBinding[nextPosition + itsLength + 5], 0, nextPosition); >+ nextInterface : for (int a = 0; a < itsLength; a++) { >+ ReferenceBinding next = itsInterfaces[a]; >+ for (int b = 0; b < nextPosition; b++) >+ if (next == interfacesToVisit[b]) continue nextInterface; >+ interfacesToVisit[nextPosition++] = next; > } > } > } >- if(proposeType) { >- int l = typesFound.size(); >- for (int i = 0; i < l; i++) { >- ReferenceBinding typeFound = (ReferenceBinding) typesFound.elementAt(i); >- char[] fullyQualifiedTypeName = >- CharOperation.concat( >- typeFound.qualifiedPackageName(), >- typeFound.qualifiedSourceName(), >- '.'); >- this.knownTypes.put(fullyQualifiedTypeName, this); >- } >- int searchFor = IJavaSearchConstants.TYPE; >- if(this.assistNodeIsClass) { >- searchFor = IJavaSearchConstants.CLASS; >- } else if(this.assistNodeIsInterface) { >- searchFor = IJavaSearchConstants.INTERFACE_AND_ANNOTATION; >- } else if(this.assistNodeIsEnum) { >- searchFor = IJavaSearchConstants.ENUM; >- } else if(this.assistNodeIsAnnotation) { >- searchFor = IJavaSearchConstants.ANNOTATION_TYPE; >+ >+ findMemberTypes( >+ typeName, >+ currentType.memberTypes(), >+ typesFound, >+ receiverType, >+ typeInvocation, >+ staticOnly, >+ staticFieldsAndMethodOnly, >+ fromStaticImport, >+ checkQualification, >+ scope, >+ missingElements, >+ missingElementsStarts, >+ missingElementsEnds, >+ missingElementsHaveProblems); >+ >+ currentType = currentType.superclass(); >+ } while (currentType != null); >+ >+ if(proposeAllMemberTypes) { >+ ReferenceBinding[] memberTypes = receiverType.memberTypes(); >+ for (int i = 0; i < memberTypes.length; i++) { >+ if(memberTypes[i] != typeToIgnore) { >+ findSubMemberTypes( >+ typeName, >+ memberTypes[i], >+ scope, >+ typeInvocation, >+ staticOnly, >+ staticFieldsAndMethodOnly, >+ fromStaticImport, >+ typesFound); > } >- this.nameEnvironment.findTypes( >- token, >- proposeAllMemberTypes, >- this.options.camelCaseMatch, >- searchFor, >- this); >- acceptTypes(scope); > } >- if(!isEmptyPrefix && !this.requestor.isIgnored(CompletionProposal.PACKAGE_REF)) { >- this.nameEnvironment.findPackages(token, this); >+ } >+ >+ if (interfacesToVisit != null) { >+ for (int i = 0; i < nextPosition; i++) { >+ ReferenceBinding anInterface = interfacesToVisit[i]; >+ findMemberTypes( >+ typeName, >+ anInterface.memberTypes(), >+ typesFound, >+ receiverType, >+ typeInvocation, >+ staticOnly, >+ staticFieldsAndMethodOnly, >+ fromStaticImport, >+ checkQualification, >+ scope, >+ missingElements, >+ missingElementsStarts, >+ missingElementsEnds, >+ missingElementsHaveProblems); >+ >+ ReferenceBinding[] itsInterfaces = anInterface.superInterfaces(); >+ if (itsInterfaces != null && itsInterfaces != Binding.NO_SUPERINTERFACES) { >+ int itsLength = itsInterfaces.length; >+ if (nextPosition + itsLength >= interfacesToVisit.length) >+ System.arraycopy(interfacesToVisit, 0, interfacesToVisit = new ReferenceBinding[nextPosition + itsLength + 5], 0, nextPosition); >+ nextInterface : for (int a = 0; a < itsLength; a++) { >+ ReferenceBinding next = itsInterfaces[a]; >+ for (int b = 0; b < nextPosition; b++) >+ if (next == interfacesToVisit[b]) continue nextInterface; >+ interfacesToVisit[nextPosition++] = next; >+ } >+ } > } > } > } > >- private void findTypesAndSubpackages( >- char[] token, >- PackageBinding packageBinding, >- Scope scope) { >+ protected void findMemberTypes( >+ char[] typeName, >+ ReferenceBinding receiverType, >+ Scope scope, >+ SourceTypeBinding typeInvocation, >+ boolean staticOnly, >+ boolean staticFieldsAndMethodOnly, >+ ObjectVector typesFound, >+ Binding[] missingElements, >+ int[] missingElementsStarts, >+ int[] missingElementsEnds, >+ boolean missingElementsHaveProblems) { >+ findMemberTypes( >+ typeName, >+ receiverType, >+ scope, >+ typeInvocation, >+ staticOnly, >+ staticFieldsAndMethodOnly, >+ false, >+ false, >+ false, >+ null, >+ typesFound, >+ missingElements, >+ missingElementsStarts, >+ missingElementsEnds, >+ missingElementsHaveProblems); >+ } >+ // Helper method for findMemberTypes(char[], ReferenceBinding, Scope) >+ private void findMemberTypes( >+ char[] typeName, >+ ReferenceBinding[] memberTypes, >+ ObjectVector typesFound, >+ ReferenceBinding receiverType, >+ SourceTypeBinding invocationType, >+ boolean staticOnly, >+ boolean staticFieldsAndMethodOnly, >+ boolean fromStaticImport, >+ boolean checkQualification, >+ Scope scope, >+ Binding[] missingElements, >+ int[] missingElementsStarts, >+ int[] missingElementsEnds, >+ boolean missingElementsHaveProblems) { > >- boolean proposeType = >- !this.requestor.isIgnored(CompletionProposal.TYPE_REF) || >- ((this.assistNodeInJavadoc & CompletionOnJavadoc.TEXT) != 0 && !this.requestor.isIgnored(CompletionProposal.JAVADOC_TYPE_REF)); >+ // Inherited member types which are hidden by subclasses are filtered out >+ // No visibility checks can be performed without the scope & invocationSite >+ int typeLength = typeName.length; >+ next : for (int m = memberTypes.length; --m >= 0;) { >+ ReferenceBinding memberType = memberTypes[m]; >+ // if (!wantClasses && memberType.isClass()) continue next; >+ // if (!wantInterfaces && memberType.isInterface()) continue next; > >- char[] qualifiedName = >- CharOperation.concatWith(packageBinding.compoundName, token, '.'); >+ if (staticOnly && !memberType.isStatic()) continue next; > >- if (token == null || token.length == 0) { >- int length = qualifiedName.length; >- System.arraycopy( >- qualifiedName, >- 0, >- qualifiedName = new char[length + 1], >- 0, >- length); >- qualifiedName[length] = '.'; >- } >+ if (isForbidden(memberType)) continue next; > >- this.qualifiedCompletionToken = qualifiedName; >+ if (typeLength > memberType.sourceName.length) >+ continue next; > >- if (proposeType && this.unitScope != null) { >- int typeLength = qualifiedName.length; >- SourceTypeBinding[] types = this.unitScope.topLevelTypes; >+ if (!CharOperation.prefixEquals(typeName, memberType.sourceName, false/* ignore case */) >+ && !(this.options.camelCaseMatch && CharOperation.camelCaseMatch(typeName, memberType.sourceName))) >+ continue next; > >- for (int i = 0, length = types.length; i < length; i++) { >- SourceTypeBinding sourceType = types[i]; >+ if (this.options.checkDeprecation && >+ memberType.isViewedAsDeprecated() && >+ !scope.isDefinedInSameUnit(memberType)) >+ continue next; > >- char[] qualifiedSourceTypeName = CharOperation.concatWith(sourceType.compoundName, '.'); >+ if (this.options.checkVisibility) { >+ if (invocationType != null && !memberType.canBeSeenBy(receiverType, invocationType)) { >+ continue next; >+ } else if(invocationType == null && !memberType.canBeSeenBy(this.unitScope.fPackage)) { >+ continue next; >+ } >+ } > >- if (sourceType.sourceName == CompletionParser.FAKE_TYPE_NAME) continue; >- if (sourceType.sourceName == TypeConstants.PACKAGE_INFO_NAME) continue; >- if (typeLength > qualifiedSourceTypeName.length) continue; >- if (!(packageBinding == sourceType.getPackage())) continue; >+ if (this.insideQualifiedReference && >+ receiverType.isParameterizedType() && >+ memberType.isStatic()) { >+ continue next; >+ } > >- if (!CharOperation.prefixEquals(qualifiedName, qualifiedSourceTypeName, false) >- && !(this.options.camelCaseMatch && CharOperation.camelCaseMatch(token, sourceType.sourceName))) continue; >+ for (int i = typesFound.size; --i >= 0;) { >+ ReferenceBinding otherType = (ReferenceBinding) typesFound.elementAt(i); > >- if (this.options.checkDeprecation && >- sourceType.isViewedAsDeprecated() && >- !scope.isDefinedInSameUnit(sourceType)) >- continue; >+ if (memberType == otherType) >+ continue next; > >- int accessibility = IAccessRule.K_ACCESSIBLE; >- if(sourceType.hasRestrictedAccess()) { >- AccessRestriction accessRestriction = this.lookupEnvironment.getAccessRestriction(sourceType); >- if(accessRestriction != null) { >- switch (accessRestriction.getProblemId()) { >- case IProblem.ForbiddenReference: >- if (this.options.checkForbiddenReference) { >- continue; >- } >- accessibility = IAccessRule.K_NON_ACCESSIBLE; >- break; >- case IProblem.DiscouragedReference: >- if (this.options.checkDiscouragedReference) { >- continue; >- } >- accessibility = IAccessRule.K_DISCOURAGED; >- break; >- } >- } >- } >+ if (CharOperation.equals(memberType.sourceName, otherType.sourceName, true)) { > >- this.knownTypes.put(CharOperation.concat(sourceType.qualifiedPackageName(), sourceType.sourceName(), '.'), this); >+ if (memberType.enclosingType().isSuperclassOf(otherType.enclosingType())) >+ continue next; > >- int relevance = computeBaseRelevance(); >- relevance += computeRelevanceForResolution(); >- relevance += computeRelevanceForInterestingProposal(); >- relevance += computeRelevanceForCaseMatching(qualifiedName, qualifiedSourceTypeName); >- relevance += computeRelevanceForExpectingType(sourceType); >- relevance += computeRelevanceForQualification(false); >- relevance += computeRelevanceForRestrictions(accessibility); >+ if (otherType.enclosingType().isInterface()) >+ if (memberType.enclosingType() >+ .implementsInterface(otherType.enclosingType(), true)) >+ continue next; > >- if (sourceType.isAnnotationType()) { >- relevance += computeRelevanceForAnnotation(); >- } else if (sourceType.isInterface()) { >- relevance += computeRelevanceForInterface(); >- } else if (sourceType.isClass()) { >- relevance += computeRelevanceForClass(); >- relevance += computeRelevanceForException(sourceType.sourceName); >+ if (memberType.enclosingType().isInterface()) >+ if (otherType.enclosingType() >+ .implementsInterface(memberType.enclosingType(), true)) >+ continue next; > } >- this.noProposal = false; >- if(proposeType) { >- char[] typeName = sourceType.sourceName(); >- createTypeProposal( >- sourceType, >- typeName, >- IAccessRule.K_ACCESSIBLE, >- typeName, >- relevance, >- null, >- null, >- null, >- false); >- } >- } >- } >- >- if(proposeType) { >- int searchFor = IJavaSearchConstants.TYPE; >- if(this.assistNodeIsClass) { >- searchFor = IJavaSearchConstants.CLASS; >- } else if(this.assistNodeIsInterface) { >- searchFor = IJavaSearchConstants.INTERFACE_AND_ANNOTATION; >- } else if(this.assistNodeIsEnum) { >- searchFor = IJavaSearchConstants.ENUM; >- } else if(this.assistNodeIsAnnotation) { >- searchFor = IJavaSearchConstants.ANNOTATION_TYPE; > } >- this.nameEnvironment.findTypes( >- qualifiedName, >- false, >- this.options.camelCaseMatch, >- searchFor, >- this); >- acceptTypes(scope); >- } >- if(!this.requestor.isIgnored(CompletionProposal.PACKAGE_REF)) { >- this.nameEnvironment.findPackages(qualifiedName, this); >- } >- } >- >- private void findTypesFromStaticImports(char[] token, Scope scope, boolean proposeAllMemberTypes, ObjectVector typesFound) { >- ImportBinding[] importBindings = scope.compilationUnitScope().imports; >- for (int i = 0; i < importBindings.length; i++) { >- ImportBinding importBinding = importBindings[i]; >- if(importBinding.isValidBinding() && importBinding.isStatic()) { >- Binding binding = importBinding.resolvedImport; >- if(binding != null && binding.isValidBinding()) { >- if(importBinding.onDemand) { >- if((binding.kind() & Binding.TYPE) != 0) { >- this.findMemberTypes( >- token, >- (ReferenceBinding) binding, >- scope, >- scope.enclosingSourceType(), >- true, >- false, >- true, >- true, >- proposeAllMemberTypes, >- null, >- typesFound, >- null, >- null, >- null, >- false); >- } >- } else { >- if ((binding.kind() & Binding.TYPE) != 0) { >- ReferenceBinding typeBinding = (ReferenceBinding) binding; >- int typeLength = token.length; >- >- if (!typeBinding.isStatic()) continue; > >- if (typeLength > typeBinding.sourceName.length) continue; >+ typesFound.add(memberType); > >- if (!CharOperation.prefixEquals(token, typeBinding.sourceName, false) >- && !(this.options.camelCaseMatch && CharOperation.camelCaseMatch(token, typeBinding.sourceName))) continue; >+ if(!this.insideQualifiedReference) { >+ if(this.assistNodeIsClass) { >+ if(!memberType.isClass()) continue next; >+ } else if(this.assistNodeIsInterface) { >+ if(!memberType.isInterface() && !memberType.isAnnotationType()) continue next; >+ } else if (this.assistNodeIsAnnotation) { >+ if(!memberType.isAnnotationType()) continue next; >+ } >+ } > >- if (typesFound.contains(typeBinding)) continue; >+ char[] completionName = memberType.sourceName(); > >- typesFound.add(typeBinding); >+ boolean isQualified = false; >+ if(checkQualification && !fromStaticImport) { >+ char[] memberPackageName = memberType.qualifiedPackageName(); >+ char[] memberTypeName = memberType.sourceName(); >+ char[] memberEnclosingTypeNames = memberType.enclosingType().qualifiedSourceName(); >+ if (mustQualifyType(memberPackageName, memberTypeName, memberEnclosingTypeNames, memberType.modifiers)) { >+ if (memberPackageName == null || memberPackageName.length == 0) >+ if (this.unitScope != null && this.unitScope.fPackage.compoundName != CharOperation.NO_CHAR_CHAR) >+ break next; // ignore types from the default package from outside it >+ isQualified = true; >+ completionName = >+ CharOperation.concat( >+ memberPackageName, >+ CharOperation.concat( >+ memberEnclosingTypeNames, >+ memberTypeName, >+ '.'), >+ '.'); >+ } >+ } > >- if(this.assistNodeIsClass) { >- if(!typeBinding.isClass()) continue; >- } else if(this.assistNodeIsInterface) { >- if(!typeBinding.isInterface() && !typeBinding.isAnnotationType()) continue; >- } else if (this.assistNodeIsAnnotation) { >- if(!typeBinding.isAnnotationType()) continue; >- } >+ int relevance = computeBaseRelevance(); >+ relevance += computeRelevanceForResolution(); >+ relevance += computeRelevanceForInterestingProposal(); >+ relevance += computeRelevanceForCaseMatching(typeName, memberType.sourceName); >+ relevance += computeRelevanceForExpectingType(memberType); >+ relevance += computeRelevanceForRestrictions(IAccessRule.K_ACCESSIBLE); >+ if(!this.insideQualifiedReference) { >+ relevance += computeRelevanceForQualification(isQualified); >+ } >+ if (staticFieldsAndMethodOnly && this.insideQualifiedReference) relevance += R_NON_INHERITED; // This criterion doesn't concern types and is added to be balanced with field and method relevance. > >- int relevance = computeBaseRelevance(); >- relevance += computeRelevanceForResolution(); >- relevance += computeRelevanceForInterestingProposal(); >- relevance += computeRelevanceForCaseMatching(token, typeBinding.sourceName); >- relevance += computeRelevanceForExpectingType(typeBinding); >- relevance += computeRelevanceForQualification(false); >- relevance += computeRelevanceForRestrictions(IAccessRule.K_ACCESSIBLE); >+ if (memberType.isAnnotationType()) { >+ relevance += computeRelevanceForAnnotation(); >+ relevance += computeRelevanceForAnnotationTarget(memberType); >+ } else if (memberType.isClass()) { >+ relevance += computeRelevanceForClass(); >+ relevance += computeRelevanceForException(memberType.sourceName); >+ } else if(memberType.isEnum()) { >+ relevance += computeRelevanceForEnum(); >+ } else if(memberType.isInterface()) { >+ relevance += computeRelevanceForInterface(); >+ } > >- if (typeBinding.isClass()) { >- relevance += computeRelevanceForClass(); >- relevance += computeRelevanceForException(typeBinding.sourceName); >- } else if(typeBinding.isEnum()) { >- relevance += computeRelevanceForEnum(); >- } else if(typeBinding.isInterface()) { >- relevance += computeRelevanceForInterface(); >- } >+ if (missingElements != null) { >+ relevance += computeRelevanceForMissingElements(missingElementsHaveProblems); >+ } > >- this.noProposal = false; >- if(!this.requestor.isIgnored(CompletionProposal.TYPE_REF)) { >- InternalCompletionProposal proposal = createProposal(CompletionProposal.TYPE_REF, this.actualCompletionPosition); >- proposal.setDeclarationSignature(typeBinding.qualifiedPackageName()); >- proposal.setSignature(getSignature(typeBinding)); >- proposal.setPackageName(typeBinding.qualifiedPackageName()); >- proposal.setTypeName(typeBinding.qualifiedSourceName()); >- proposal.setCompletion(typeBinding.sourceName()); >- proposal.setFlags(typeBinding.modifiers); >- proposal.setReplaceRange(this.startPosition - this.offset, this.endPosition - this.offset); >- proposal.setTokenRange(this.tokenStart - this.offset, this.tokenEnd - this.offset); >- proposal.setRelevance(relevance); >- this.requestor.accept(proposal); >- if(DEBUG) { >- this.printDebug(proposal); >- } >- } >- } >+ this.noProposal = false; >+ createTypeProposal( >+ memberType, >+ memberType.qualifiedSourceName(), >+ IAccessRule.K_ACCESSIBLE, >+ completionName, >+ relevance, >+ missingElements, >+ missingElementsStarts, >+ missingElementsEnds, >+ missingElementsHaveProblems); >+ } >+ } >+ private void findMemberTypesFromMissingType( >+ char[] typeName, >+ final long pos, >+ final Scope scope) { >+ MissingTypesGuesser missingTypesConverter = new MissingTypesGuesser(this); >+ MissingTypesGuesser.GuessedTypeRequestor substitutionRequestor = >+ new MissingTypesGuesser.GuessedTypeRequestor() { >+ public void accept( >+ TypeBinding guessedType, >+ Binding[] missingElements, >+ int[] missingElementsStarts, >+ int[] missingElementsEnds, >+ boolean hasProblems) { >+ if (guessedType instanceof ReferenceBinding) { >+ findMemberTypes( >+ CompletionEngine.this.completionToken, >+ (ReferenceBinding)guessedType, >+ scope, >+ scope.enclosingSourceType(), >+ false, >+ false, >+ new ObjectVector(), >+ missingElements, >+ missingElementsStarts, >+ missingElementsEnds, >+ hasProblems); > } > } >- } >- } >+ }; >+ SingleTypeReference typeRef = new SingleTypeReference(typeName, pos); >+ typeRef.resolvedType = new ProblemReferenceBinding(new char[][]{ typeName }, null, ProblemReasons.NotFound); >+ missingTypesConverter.guess(typeRef, scope, substitutionRequestor); > } >- private void findVariablesAndMethods( >- char[] token, >+ >+ private void findMemberTypesFromMissingType( >+ TypeReference typeRef, >+ final long pos, >+ final Scope scope) { >+ MissingTypesGuesser missingTypesConverter = new MissingTypesGuesser(this); >+ MissingTypesGuesser.GuessedTypeRequestor substitutionRequestor = >+ new MissingTypesGuesser.GuessedTypeRequestor() { >+ public void accept( >+ TypeBinding guessedType, >+ Binding[] missingElements, >+ int[] missingElementsStarts, >+ int[] missingElementsEnds, >+ boolean hasProblems) { >+ if (guessedType instanceof ReferenceBinding) { >+ findMemberTypes( >+ CompletionEngine.this.completionToken, >+ (ReferenceBinding)guessedType, >+ scope, >+ scope.enclosingSourceType(), >+ false, >+ false, >+ new ObjectVector(), >+ missingElements, >+ missingElementsStarts, >+ missingElementsEnds, >+ hasProblems); >+ } >+ } >+ }; >+ missingTypesConverter.guess(typeRef, scope, substitutionRequestor); >+ } >+ >+ private void findMethodDeclarations( >+ char[] selector, >+ ReferenceBinding receiverType, > Scope scope, >- InvocationSite invocationSite, >- Scope invocationScope, >- boolean insideTypeAnnotation, >- boolean insideAnnotationAttribute) { >+ ObjectVector methodsFound, >+ Binding[] missingElements, >+ int[] missingElementsStarts, >+ int[] missingElementsEnds, >+ boolean missingElementsHaveProblems) { > >- if (token == null) >+ if (selector == null) { > return; >+ } > >- // Should local variables hide fields from the receiver type or any of its enclosing types? >- // we know its an implicit field/method access... see BlockScope getBinding/getImplicitMethod >- >- boolean staticsOnly = false; >- // need to know if we're in a static context (or inside a constructor) >- int tokenLength = token.length; >- >- ObjectVector localsFound = new ObjectVector(); >- ObjectVector fieldsFound = new ObjectVector(); >- ObjectVector methodsFound = new ObjectVector(); >+ MethodBinding[] receiverTypeMethods = receiverType.availableMethods(); >+ if (receiverTypeMethods != null){ >+ for (int i = 0; i < receiverTypeMethods.length; i++) { >+ if(!receiverTypeMethods[i].isDefaultAbstract()) { >+ methodsFound.add(receiverTypeMethods[i]); >+ } >+ } >+ } > >- Scope currentScope = scope; >+ ReferenceBinding currentType = receiverType; >+ >+ findInterfacesMethodDeclarations( >+ selector, >+ receiverType, >+ currentType.superInterfaces(), >+ scope, >+ methodsFound, >+ missingElements, >+ missingElementsStarts, >+ missingElementsEnds, >+ missingElementsHaveProblems); >+ >+ if (receiverType.isInterface()) { >+ currentType = scope.getJavaLangObject(); >+ } else { >+ currentType = receiverType.superclass(); >+ } >+ >+ boolean hasPotentialDefaultAbstractMethods = true; >+ while (currentType != null) { > >- if (!this.requestor.isIgnored(CompletionProposal.LOCAL_VARIABLE_REF)) { >- done1 : while (true) { // done when a COMPILATION_UNIT_SCOPE is found >+ MethodBinding[] methods = currentType.availableMethods(); >+ if (methods != null) { >+ findLocalMethodDeclarations( >+ selector, >+ methods, >+ scope, >+ methodsFound, >+ false, >+ receiverType); >+ } > >- switch (currentScope.kind) { >+ if (hasPotentialDefaultAbstractMethods && >+ (currentType.isAbstract() || >+ currentType.isTypeVariable() || >+ currentType.isIntersectionType() || >+ currentType.isEnum())){ > >- case Scope.METHOD_SCOPE : >- // handle the error case inside an explicit constructor call (see MethodScope>>findField) >- MethodScope methodScope = (MethodScope) currentScope; >- staticsOnly |= methodScope.isStatic | methodScope.isConstructorCall; >+ ReferenceBinding[] superInterfaces = currentType.superInterfaces(); > >- //$FALL-THROUGH$ >- case Scope.BLOCK_SCOPE : >- BlockScope blockScope = (BlockScope) currentScope; >+ findInterfacesMethodDeclarations( >+ selector, >+ receiverType, >+ superInterfaces, >+ scope, >+ methodsFound, >+ missingElements, >+ missingElementsStarts, >+ missingElementsEnds, >+ missingElementsHaveProblems); >+ } else { >+ hasPotentialDefaultAbstractMethods = false; >+ } >+ currentType = currentType.superclass(); >+ } >+ } >+ >+ private char[][] findMethodParameterNames(MethodBinding method, char[][] parameterTypeNames){ >+ TypeBinding erasure = method.declaringClass.erasure(); >+ if(!(erasure instanceof ReferenceBinding)) return null; > >- next : for (int i = 0, length = blockScope.locals.length; i < length; i++) { >- LocalVariableBinding local = blockScope.locals[i]; >+ char[][] parameterNames = null; > >- if (local == null) >- break next; >+ int length = parameterTypeNames.length; > >- if (tokenLength > local.name.length) >- continue next; >+ if (length == 0){ >+ return CharOperation.NO_CHAR_CHAR; >+ } >+ // look into the corresponding unit if it is available >+ if (erasure instanceof SourceTypeBinding){ >+ SourceTypeBinding sourceType = (SourceTypeBinding) erasure; > >- if (!CharOperation.prefixEquals(token, local.name, false /* ignore case */) >- && !(this.options.camelCaseMatch && CharOperation.camelCaseMatch(token, local.name))) >- continue next; >+ if (sourceType.scope != null){ >+ TypeDeclaration parsedType; > >- if (local.isSecret()) >- continue next; >+ if ((parsedType = sourceType.scope.referenceContext) != null){ >+ AbstractMethodDeclaration methodDecl = parsedType.declarationOf(method.original()); > >- for (int f = 0; f < localsFound.size; f++) { >- LocalVariableBinding otherLocal = >- (LocalVariableBinding) localsFound.elementAt(f); >- if (CharOperation.equals(otherLocal.name, local.name, true)) >- continue next; >- } >- localsFound.add(local); >+ if (methodDecl != null){ >+ Argument[] arguments = methodDecl.arguments; >+ parameterNames = new char[length][]; > >- int relevance = computeBaseRelevance(); >- relevance += computeRelevanceForResolution(); >- relevance += computeRelevanceForInterestingProposal(local); >- relevance += computeRelevanceForCaseMatching(token, local.name); >- relevance += computeRelevanceForExpectingType(local.type); >- relevance += computeRelevanceForEnumConstant(local.type); >- relevance += computeRelevanceForQualification(false); >- relevance += computeRelevanceForRestrictions(IAccessRule.K_ACCESSIBLE); // no access restriction for local variable >- this.noProposal = false; >- if(!this.requestor.isIgnored(CompletionProposal.LOCAL_VARIABLE_REF)) { >- InternalCompletionProposal proposal = createProposal(CompletionProposal.LOCAL_VARIABLE_REF, this.actualCompletionPosition); >- proposal.setSignature( >- local.type == null >- ? createTypeSignature( >- CharOperation.NO_CHAR, >- local.declaration.type.toString().toCharArray()) >- : getSignature(local.type)); >- if(local.type == null) { >- //proposal.setPackageName(null); >- proposal.setTypeName(local.declaration.type.toString().toCharArray()); >- } else { >- proposal.setPackageName(local.type.qualifiedPackageName()); >- proposal.setTypeName(local.type.qualifiedSourceName()); >- } >- proposal.setName(local.name); >- proposal.setCompletion(local.name); >- proposal.setFlags(local.modifiers); >- proposal.setReplaceRange(this.startPosition - this.offset, this.endPosition - this.offset); >- proposal.setTokenRange(this.tokenStart - this.offset, this.tokenEnd - this.offset); >- proposal.setRelevance(relevance); >- this.requestor.accept(proposal); >- if(DEBUG) { >- this.printDebug(proposal); >- } >- } >+ for(int i = 0 ; i < length ; i++){ >+ parameterNames[i] = arguments[i].name; > } >- break; >- >- case Scope.COMPILATION_UNIT_SCOPE : >- break done1; >+ } > } >- currentScope = currentScope.parent; > } > } >+ // look into the model >+ if(parameterNames == null){ > >- boolean proposeField = !this.requestor.isIgnored(CompletionProposal.FIELD_REF); >- boolean proposeMethod = !this.requestor.isIgnored(CompletionProposal.METHOD_REF); >- >- staticsOnly = false; >- currentScope = scope; >- >- if(proposeField || proposeMethod) { >- done2 : while (true) { // done when a COMPILATION_UNIT_SCOPE is found >+ ReferenceBinding bindingType = (ReferenceBinding)erasure; > >- switch (currentScope.kind) { >- case Scope.METHOD_SCOPE : >- // handle the error case inside an explicit constructor call (see MethodScope>>findField) >- MethodScope methodScope = (MethodScope) currentScope; >- staticsOnly |= methodScope.isStatic | methodScope.isConstructorCall; >- break; >- case Scope.CLASS_SCOPE : >- ClassScope classScope = (ClassScope) currentScope; >- SourceTypeBinding enclosingType = classScope.referenceContext.binding; >- /* if (tokenLength == 0) { // only search inside the type itself if no prefix was provided >- findFields(token, enclosingType.fields(), classScope, fieldsFound, staticsOnly); >- findMethods(token, enclosingType.methods(), classScope, methodsFound, staticsOnly, false); >- break done; >- } else { */ >- if(!insideTypeAnnotation) { >- if(proposeField) { >- findFields( >- token, >- enclosingType, >- classScope, >- fieldsFound, >- localsFound, >- staticsOnly, >- invocationSite, >- invocationScope, >- true, >- true, >- null, >- null, >- null, >- false, >- null, >- -1, >- -1); >- } >- if(proposeMethod && !insideAnnotationAttribute) { >- findMethods( >- token, >- null, >- null, >- enclosingType, >- classScope, >- methodsFound, >- staticsOnly, >- false, >- false, >- invocationSite, >- invocationScope, >- true, >- false, >- true, >- null, >- null, >- null, >- false, >- null, >- -1, >- -1); >- } >- } >- staticsOnly |= enclosingType.isStatic(); >- insideTypeAnnotation = false; >- // } >- break; >+ char[] compoundName = CharOperation.concatWith(bindingType.compoundName, '.'); >+ Object type = this.typeCache.get(compoundName); > >- case Scope.COMPILATION_UNIT_SCOPE : >- break done2; >+ ISourceType sourceType = null; >+ if(type != null) { >+ if(type instanceof ISourceType) { >+ sourceType = (ISourceType) type; >+ } >+ } else { >+ NameEnvironmentAnswer answer = this.nameEnvironment.findType(bindingType.compoundName); >+ if(answer != null && answer.isSourceType()) { >+ sourceType = answer.getSourceTypes()[0]; >+ this.typeCache.put(compoundName, sourceType); > } >- currentScope = currentScope.parent; > } > >- findFieldsAndMethodsFromStaticImports( >- token, >- scope, >- invocationSite, >- invocationScope, >- false, >- insideAnnotationAttribute, >- localsFound, >- fieldsFound, >- methodsFound, >- proposeField, >- proposeMethod); >+ if(sourceType != null) { >+ IType typeHandle = ((SourceTypeElementInfo) sourceType).getHandle(); > >- if (this.assistNodeInJavadoc == 0) { >- // search in favorites import >- findFieldsAndMethodsFromFavorites( >- token, >- scope, >- invocationSite, >- invocationScope, >- localsFound, >- fieldsFound, >- methodsFound); >- } >+ String[] parameterTypeSignatures = new String[length]; >+ for (int i = 0; i < length; i++) { >+ parameterTypeSignatures[i] = Signature.createTypeSignature(parameterTypeNames[i], false); >+ } >+ IMethod searchedMethod = typeHandle.getMethod(String.valueOf(method.selector), parameterTypeSignatures); >+ IMethod[] foundMethods = typeHandle.findMethods(searchedMethod); > >- findEnumConstantsFromExpectedTypes( >- token, >- invocationScope, >- fieldsFound); >- } >- } >- >- private void findLocalMethodsFromStaticImports( >- char[] token, >- Scope scope, >- InvocationSite invocationSite, >- Scope invocationScope, >- boolean exactMatch, >- ObjectVector methodsFound, >- boolean proposeMethod) { >- findFieldsAndMethodsFromStaticImports( >- token, >- scope, >- invocationSite, >- invocationScope, >- exactMatch, >- false, >- new ObjectVector(), >- new ObjectVector(), >- methodsFound, >- false, >- proposeMethod); >- } >- >- private void findFieldsAndMethodsFromStaticImports( >- char[] token, >- Scope scope, >- InvocationSite invocationSite, >- Scope invocationScope, >- boolean exactMatch, >- boolean insideAnnotationAttribute, >- ObjectVector localsFound, >- ObjectVector fieldsFound, >- ObjectVector methodsFound, >- boolean proposeField, >- boolean proposeMethod) { >- // search in static import >- ImportBinding[] importBindings = scope.compilationUnitScope().imports; >- for (int i = 0; i < importBindings.length; i++) { >- ImportBinding importBinding = importBindings[i]; >- if(importBinding.isValidBinding() && importBinding.isStatic()) { >- Binding binding = importBinding.resolvedImport; >- if(binding != null && binding.isValidBinding()) { >- if(importBinding.onDemand) { >- if((binding.kind() & Binding.TYPE) != 0) { >- if(proposeField) { >- findFields( >- token, >- (ReferenceBinding)binding, >- scope, >- fieldsFound, >- localsFound, >- true, >- invocationSite, >- invocationScope, >- true, >- false, >- null, >- null, >- null, >- false, >- null, >- -1, >- -1); >- } >- if(proposeMethod && !insideAnnotationAttribute) { >- findMethods( >- token, >- null, >- null, >- (ReferenceBinding)binding, >- scope, >- methodsFound, >- true, >- exactMatch, >- false, >- invocationSite, >- invocationScope, >- true, >- false, >- false, >- null, >- null, >- null, >- false, >- null, >- -1, >- -1); >- } >- } >- } else { >- if ((binding.kind() & Binding.FIELD) != 0) { >- if(proposeField) { >- findFields( >- token, >- new FieldBinding[]{(FieldBinding)binding}, >- scope, >- fieldsFound, >- localsFound, >- true, >- ((FieldBinding)binding).declaringClass, >- invocationSite, >- invocationScope, >- true, >- false, >- null, >- null, >- null, >- false, >- null, >- -1, >- -1); >- } >- } else if ((binding.kind() & Binding.METHOD) != 0) { >- if(proposeMethod && !insideAnnotationAttribute) { >- MethodBinding methodBinding = (MethodBinding)binding; >- if ((exactMatch && CharOperation.equals(token, methodBinding.selector)) || >- !exactMatch && CharOperation.prefixEquals(token, methodBinding.selector)) { >- >- findLocalMethodsFromStaticImports( >- methodBinding.selector, >- methodBinding.declaringClass.methods(), >- scope, >- exactMatch, >- methodsFound, >- methodBinding.declaringClass, >- invocationSite); >- } >- } >+ if(foundMethods != null) { >+ int len = foundMethods.length; >+ if(len == 1) { >+ try { >+ SourceMethod sourceMethod = (SourceMethod) foundMethods[0]; >+ parameterNames = ((SourceMethodElementInfo) sourceMethod.getElementInfo()).getArgumentNames(); >+ } catch (JavaModelException e) { >+ // method doesn't exist: ignore > } > } > } > } > } >+ return parameterNames; > } >- private char[][] findVariableFromUnresolvedReference(LocalDeclaration variable, BlockScope scope, final char[][] discouragedNames) { >- final TypeReference type = variable.type; >- if(type != null && >- type.resolvedType != null && >- type.resolvedType.problemId() == ProblemReasons.NoError){ > >- final ArrayList proposedNames = new ArrayList(); >+ private void findMethods( >+ char[] selector, >+ TypeBinding[] typeArgTypes, >+ TypeBinding[] argTypes, >+ ReferenceBinding receiverType, >+ Scope scope, >+ ObjectVector methodsFound, >+ boolean onlyStaticMethods, >+ boolean exactMatch, >+ InvocationSite invocationSite, >+ Scope invocationScope, >+ boolean implicitCall, >+ boolean superCall, >+ boolean canBePrefixed, >+ Binding[] missingElements, >+ int[] missingElementsStarts, >+ int[] missingElementsEnds, >+ boolean missingElementsHaveProblems, >+ char[] castedReceiver, >+ int receiverStart, >+ int receiverEnd) { > >- UnresolvedReferenceNameFinder.UnresolvedReferenceNameRequestor nameRequestor = >- new UnresolvedReferenceNameFinder.UnresolvedReferenceNameRequestor() { >- public void acceptName(char[] name) { >- int relevance = computeBaseRelevance(); >- relevance += computeRelevanceForInterestingProposal(); >- relevance += computeRelevanceForCaseMatching(CompletionEngine.this.completionToken, name); >- relevance += R_NAME_FIRST_PREFIX; >- relevance += R_NAME_FIRST_SUFFIX; >- relevance += R_NAME_LESS_NEW_CHARACTERS; >- relevance += computeRelevanceForRestrictions(IAccessRule.K_ACCESSIBLE); // no access restriction for variable name >+ boolean notInJavadoc = this.assistNodeInJavadoc == 0; >+ if (selector == null && notInJavadoc) { >+ return; >+ } > >- // accept result >- CompletionEngine.this.noProposal = false; >- if(!CompletionEngine.this.requestor.isIgnored(CompletionProposal.VARIABLE_DECLARATION)) { >- InternalCompletionProposal proposal = CompletionEngine.this.createProposal(CompletionProposal.VARIABLE_DECLARATION, CompletionEngine.this.actualCompletionPosition); >- proposal.setSignature(getSignature(type.resolvedType)); >- proposal.setPackageName(type.resolvedType.qualifiedPackageName()); >- proposal.setTypeName(type.resolvedType.qualifiedSourceName()); >- proposal.setName(name); >- proposal.setCompletion(name); >- //proposal.setFlags(Flags.AccDefault); >- proposal.setReplaceRange(CompletionEngine.this.startPosition - CompletionEngine.this.offset, CompletionEngine.this.endPosition - CompletionEngine.this.offset); >- proposal.setTokenRange(CompletionEngine.this.tokenStart - CompletionEngine.this.offset, CompletionEngine.this.tokenEnd - CompletionEngine.this.offset); >- proposal.setRelevance(relevance); >- CompletionEngine.this.requestor.accept(proposal); >- if(DEBUG) { >- CompletionEngine.this.printDebug(proposal); >- } >- } >- proposedNames.add(name); >- } >- }; >+ ReferenceBinding currentType = receiverType; >+ if (notInJavadoc) { >+ if (receiverType.isInterface()) { >+ findInterfacesMethods( >+ selector, >+ typeArgTypes, >+ argTypes, >+ receiverType, >+ new ReferenceBinding[]{currentType}, >+ scope, >+ methodsFound, >+ onlyStaticMethods, >+ exactMatch, >+ invocationSite, >+ invocationScope, >+ implicitCall, >+ superCall, >+ canBePrefixed, >+ missingElements, >+ missingElementsStarts, >+ missingElementsEnds, >+ missingElementsHaveProblems, >+ castedReceiver, >+ receiverStart, >+ receiverEnd); > >- ReferenceContext referenceContext = scope.referenceContext(); >- if (referenceContext instanceof AbstractMethodDeclaration) { >- AbstractMethodDeclaration md = (AbstractMethodDeclaration)referenceContext; >+ currentType = scope.getJavaLangObject(); >+ } >+ } >+ boolean hasPotentialDefaultAbstractMethods = true; >+ while (currentType != null) { > >- UnresolvedReferenceNameFinder nameFinder = new UnresolvedReferenceNameFinder(this); >- nameFinder.find( >- this.completionToken, >- md, >- variable.declarationSourceEnd + 1, >- discouragedNames, >- nameRequestor); >- } else if (referenceContext instanceof TypeDeclaration) { >- TypeDeclaration typeDeclaration = (TypeDeclaration) referenceContext; >- FieldDeclaration[] fields = typeDeclaration.fields; >- if (fields != null) { >- done : for (int i = 0; i < fields.length; i++) { >- if (fields[i] instanceof Initializer) { >- Initializer initializer = (Initializer) fields[i]; >- if (initializer.bodyStart <= variable.sourceStart && >- variable.sourceStart < initializer.bodyEnd) { >- UnresolvedReferenceNameFinder nameFinder = new UnresolvedReferenceNameFinder(this); >- nameFinder.find( >- this.completionToken, >- initializer, >- typeDeclaration.scope, >- variable.declarationSourceEnd + 1, >- discouragedNames, >- nameRequestor); >- break done; >- } >- } >+ MethodBinding[] methods = currentType.availableMethods(); >+ if (methods != null) { >+ findLocalMethods( >+ selector, >+ typeArgTypes, >+ argTypes, >+ methods, >+ scope, >+ methodsFound, >+ onlyStaticMethods, >+ exactMatch, >+ receiverType, >+ invocationSite, >+ invocationScope, >+ implicitCall, >+ superCall, >+ canBePrefixed, >+ missingElements, >+ missingElementsStarts, >+ missingElementsEnds, >+ missingElementsHaveProblems, >+ castedReceiver, >+ receiverStart, >+ receiverEnd); >+ } >+ >+ if (hasPotentialDefaultAbstractMethods && >+ (currentType.isAbstract() || >+ currentType.isTypeVariable() || >+ currentType.isIntersectionType() || >+ currentType.isEnum())){ >+ >+ ReferenceBinding[] superInterfaces = currentType.superInterfaces(); >+ if (superInterfaces != null && currentType.isIntersectionType()) { >+ for (int i = 0; i < superInterfaces.length; i++) { >+ superInterfaces[i] = (ReferenceBinding)superInterfaces[i].capture(invocationScope, invocationSite.sourceEnd()); > } > } >- } > >- int proposedNamesCount = proposedNames.size(); >- if (proposedNamesCount > 0) { >- return (char[][])proposedNames.toArray(new char[proposedNamesCount][]); >+ findInterfacesMethods( >+ selector, >+ typeArgTypes, >+ argTypes, >+ receiverType, >+ superInterfaces, >+ scope, >+ methodsFound, >+ onlyStaticMethods, >+ exactMatch, >+ invocationSite, >+ invocationScope, >+ implicitCall, >+ superCall, >+ canBePrefixed, >+ missingElements, >+ missingElementsStarts, >+ missingElementsEnds, >+ missingElementsHaveProblems, >+ castedReceiver, >+ receiverStart, >+ receiverEnd); >+ } else { >+ hasPotentialDefaultAbstractMethods = false; > } >+ currentType = currentType.superclass(); > } >- >- return null; > } > >- private char[][] findUnresolvedReferenceAfter(int from, BlockScope scope, final char[][] discouragedNames) { >- final ArrayList proposedNames = new ArrayList(); >- >- UnresolvedReferenceNameFinder.UnresolvedReferenceNameRequestor nameRequestor = >- new UnresolvedReferenceNameFinder.UnresolvedReferenceNameRequestor() { >- public void acceptName(char[] name) { >- CompletionEngine.this.acceptUnresolvedName(name); >- proposedNames.add(name); >- } >- }; >+ private void findNestedTypes( >+ char[] typeName, >+ SourceTypeBinding currentType, >+ Scope scope, >+ boolean proposeAllMemberTypes, >+ ObjectVector typesFound) { >+ >+ if (typeName == null) >+ return; > >- ReferenceContext referenceContext = scope.referenceContext(); >- if (referenceContext instanceof AbstractMethodDeclaration) { >- AbstractMethodDeclaration md = (AbstractMethodDeclaration)referenceContext; >+ int typeLength = typeName.length; > >- UnresolvedReferenceNameFinder nameFinder = new UnresolvedReferenceNameFinder(this); >- nameFinder.findAfter( >- this.completionToken, >- md.scope, >- md.scope.classScope(), >- from, >- md.bodyEnd, >- discouragedNames, >- nameRequestor); >- } else if (referenceContext instanceof TypeDeclaration) { >- TypeDeclaration typeDeclaration = (TypeDeclaration) referenceContext; >- FieldDeclaration[] fields = typeDeclaration.fields; >- if (fields != null) { >- done : for (int i = 0; i < fields.length; i++) { >- if (fields[i] instanceof Initializer) { >- Initializer initializer = (Initializer) fields[i]; >- if (initializer.block.sourceStart <= from && >- from < initializer.bodyEnd) { >- UnresolvedReferenceNameFinder nameFinder = new UnresolvedReferenceNameFinder(this); >- nameFinder.findAfter( >- this.completionToken, >- typeDeclaration.scope, >- typeDeclaration.scope, >- from, >- initializer.bodyEnd, >- discouragedNames, >- nameRequestor); >- break done; >- } >- } >- } >- } >- } >+ SourceTypeBinding nextTypeToIgnore = null; >+ while (scope != null) { // done when a COMPILATION_UNIT_SCOPE is found > >- int proposedNamesCount = proposedNames.size(); >- if (proposedNamesCount > 0) { >- return (char[][])proposedNames.toArray(new char[proposedNamesCount][]); >- } >+ switch (scope.kind) { > >- return null; >- } >+ case Scope.METHOD_SCOPE : >+ case Scope.BLOCK_SCOPE : >+ BlockScope blockScope = (BlockScope) scope; > >- private void findUnresolvedReference(int completedNameStart, int completedNameEnd, BlockScope scope, char[][] discouragedNames) { >- char[][] foundNames = findUnresolvedReferenceBefore(completedNameStart - 1, completedNameEnd, scope, discouragedNames); >- if (foundNames != null && foundNames.length > 1) { >- int discouragedNamesLength = discouragedNames.length; >- int foundNamesLength = foundNames.length; >- int newLength = discouragedNamesLength + foundNamesLength; >- System.arraycopy(discouragedNames, 0, discouragedNames = new char[newLength][], 0, discouragedNamesLength); >- System.arraycopy(foundNames, 0, discouragedNames, discouragedNamesLength, foundNamesLength); >- } >- findUnresolvedReferenceAfter(completedNameEnd + 1, scope, discouragedNames); >- } >+ next : for (int i = 0, length = blockScope.subscopeCount; i < length; i++) { > >- private char[][] findUnresolvedReferenceBefore(int recordTo, int parseTo, BlockScope scope, final char[][] discouragedNames) { >- final ArrayList proposedNames = new ArrayList(); >+ if (blockScope.subscopes[i] instanceof ClassScope) { >+ SourceTypeBinding localType = >+ ((ClassScope) blockScope.subscopes[i]).referenceContext.binding; > >- UnresolvedReferenceNameFinder.UnresolvedReferenceNameRequestor nameRequestor = >- new UnresolvedReferenceNameFinder.UnresolvedReferenceNameRequestor() { >- public void acceptName(char[] name) { >- CompletionEngine.this.acceptUnresolvedName(name); >- proposedNames.add(name); >- } >- }; >+ if (!localType.isAnonymousType()) { >+ if (isForbidden(localType)) >+ continue next; > >- BlockScope upperScope = scope; >- while (upperScope.enclosingMethodScope() != null) { >- upperScope = upperScope.enclosingMethodScope(); >- } >+ if (typeLength > localType.sourceName.length) >+ continue next; >+ if (!CharOperation.prefixEquals(typeName, localType.sourceName, false/* ignore case */) >+ && !(this.options.camelCaseMatch && CharOperation.camelCaseMatch(typeName, localType.sourceName))) >+ continue next; > >- ReferenceContext referenceContext = upperScope.referenceContext(); >- if (referenceContext instanceof AbstractMethodDeclaration) { >- AbstractMethodDeclaration md = (AbstractMethodDeclaration)referenceContext; >+ for (int j = typesFound.size; --j >= 0;) { >+ ReferenceBinding otherType = (ReferenceBinding) typesFound.elementAt(j); > >- UnresolvedReferenceNameFinder nameFinder = new UnresolvedReferenceNameFinder(this); >- nameFinder.findBefore( >- this.completionToken, >- md.scope, >- md.scope.classScope(), >- md.bodyStart, >- recordTo, >- parseTo, >- discouragedNames, >- nameRequestor); >- } else if (referenceContext instanceof TypeDeclaration) { >- TypeDeclaration typeDeclaration = (TypeDeclaration) referenceContext; >+ if (localType == otherType) >+ continue next; >+ } > >+ if(this.assistNodeIsClass) { >+ if(!localType.isClass()) continue next; >+ } else if(this.assistNodeIsInterface) { >+ if(!localType.isInterface() && !localType.isAnnotationType()) continue next; >+ } else if (this.assistNodeIsAnnotation) { >+ if(!localType.isAnnotationType()) continue next; >+ } > >- done : { >- FieldDeclaration[] fields = typeDeclaration.fields; >- if (fields != null) { >- for (int i = 0; i < fields.length; i++) { >- if (fields[i] instanceof Initializer) { >- Initializer initializer = (Initializer) fields[i]; >- if (initializer.block.sourceStart <= recordTo && >- recordTo < initializer.bodyEnd) { >+ int relevance = computeBaseRelevance(); >+ relevance += computeRelevanceForResolution(); >+ relevance += computeRelevanceForInterestingProposal(); >+ relevance += computeRelevanceForCaseMatching(typeName, localType.sourceName); >+ relevance += computeRelevanceForExpectingType(localType); >+ relevance += computeRelevanceForException(localType.sourceName); >+ relevance += computeRelevanceForClass(); >+ relevance += computeRelevanceForQualification(false); >+ relevance += computeRelevanceForRestrictions(IAccessRule.K_ACCESSIBLE); // no access restriction for nested type >+ relevance += computeRelevanceForAnnotationTarget(localType); > >- UnresolvedReferenceNameFinder nameFinder = new UnresolvedReferenceNameFinder(this); >- nameFinder.findBefore( >- this.completionToken, >- typeDeclaration.scope, >- typeDeclaration.scope, >- initializer.block.sourceStart, >- recordTo, >- parseTo, >- discouragedNames, >- nameRequestor); >- break done; >+ this.noProposal = false; >+ if(!this.requestor.isIgnored(CompletionProposal.TYPE_REF)) { >+ createTypeProposal( >+ localType, >+ localType.sourceName, >+ IAccessRule.K_ACCESSIBLE, >+ localType.sourceName, >+ relevance, >+ null, >+ null, >+ null, >+ false); >+ } > } > } > } >- } >- } >- } >- >- int proposedNamesCount = proposedNames.size(); >- if (proposedNamesCount > 0) { >- return (char[][])proposedNames.toArray(new char[proposedNamesCount][]); >- } >+ break; > >- return null; >- } >- // Helper method for private void findVariableNames(char[] name, TypeReference type ) >- private void findVariableName( >- char[] token, >- char[] qualifiedPackageName, >- char[] qualifiedSourceName, >- char[] sourceName, >- final TypeBinding typeBinding, >- char[][] discouragedNames, >- final char[][] forbiddenNames, >- int dim, >- int kind, >- int modifiers){ >- findVariableName( >- token, >- qualifiedPackageName, >- qualifiedSourceName, >- sourceName, >- typeBinding, >- discouragedNames, >- forbiddenNames, >- false, >- dim, >- kind, >- modifiers); >- } >- private void findVariableName( >- char[] token, >- char[] qualifiedPackageName, >- char[] qualifiedSourceName, >- char[] sourceName, >- final TypeBinding typeBinding, >- char[][] discouragedNames, >- final char[][] forbiddenNames, >- boolean forCollection, >- int dim, >- int kind, >- int modifiers){ >- >- if(sourceName == null || sourceName.length == 0) >- return; >+ case Scope.CLASS_SCOPE : >+ SourceTypeBinding enclosingSourceType = scope.enclosingSourceType(); >+ findMemberTypes( >+ typeName, >+ enclosingSourceType, >+ scope, >+ currentType, >+ false, >+ false, >+ false, >+ false, >+ proposeAllMemberTypes, >+ nextTypeToIgnore, >+ typesFound, >+ null, >+ null, >+ null, >+ false); >+ nextTypeToIgnore = enclosingSourceType; >+ if (typeLength == 0) >+ return; // do not search outside the class scope if no prefix was provided >+ break; > >- // compute variable name for non base type >- final char[] displayName; >- if (!forCollection) { >- if (dim > 0){ >- int l = qualifiedSourceName.length; >- displayName = new char[l+(2*dim)]; >- System.arraycopy(qualifiedSourceName, 0, displayName, 0, l); >- for(int i = 0; i < dim; i++){ >- displayName[l+(i*2)] = '['; >- displayName[l+(i*2)+1] = ']'; >- } >- } else { >- displayName = qualifiedSourceName; >+ case Scope.COMPILATION_UNIT_SCOPE : >+ return; > } >- } else { >- displayName = typeBinding.qualifiedSourceName(); >+ scope = scope.parent; > } >+ } > >- final char[] t = token; >- final char[] q = qualifiedPackageName; >- INamingRequestor namingRequestor = new INamingRequestor() { >- public void acceptNameWithPrefixAndSuffix(char[] name, boolean isFirstPrefix, boolean isFirstSuffix, int reusedCharacters) { >- accept( >- name, >- (isFirstPrefix ? R_NAME_FIRST_PREFIX : R_NAME_PREFIX) + (isFirstSuffix ? R_NAME_FIRST_SUFFIX : R_NAME_SUFFIX), >- reusedCharacters); >- } >- >- public void acceptNameWithPrefix(char[] name, boolean isFirstPrefix, int reusedCharacters) { >- accept(name, isFirstPrefix ? R_NAME_FIRST_PREFIX : R_NAME_PREFIX, reusedCharacters); >- } >+ private void findPackages(CompletionOnPackageReference packageStatement) { > >- public void acceptNameWithSuffix(char[] name, boolean isFirstSuffix, int reusedCharacters) { >- accept(name, isFirstSuffix ? R_NAME_FIRST_SUFFIX : R_NAME_SUFFIX, reusedCharacters); >- } >+ this.completionToken = CharOperation.concatWith(packageStatement.tokens, '.'); >+ if (this.completionToken.length == 0) >+ return; > >- public void acceptNameWithoutPrefixAndSuffix(char[] name,int reusedCharacters) { >- accept(name, 0, reusedCharacters); >- } >- void accept(char[] name, int prefixAndSuffixRelevance, int reusedCharacters){ >- int l = forbiddenNames == null ? 0 : forbiddenNames.length; >- for (int i = 0; i < l; i++) { >- if (CharOperation.equals(forbiddenNames[i], name, false)) return; >- } >+ setSourceRange(packageStatement.sourceStart, packageStatement.sourceEnd); >+ long completionPosition = packageStatement.sourcePositions[packageStatement.sourcePositions.length - 1]; >+ setTokenRange((int) (completionPosition >>> 32), (int) completionPosition); >+ this.nameEnvironment.findPackages(CharOperation.toLowerCase(this.completionToken), this); >+ } > >- if (CharOperation.prefixEquals(t, name, false)) { >- int relevance = computeBaseRelevance(); >- relevance += computeRelevanceForInterestingProposal(); >- relevance += computeRelevanceForCaseMatching(t, name); >- relevance += prefixAndSuffixRelevance; >- if(reusedCharacters > 0) relevance += R_NAME_LESS_NEW_CHARACTERS; >- relevance += computeRelevanceForRestrictions(IAccessRule.K_ACCESSIBLE); // no access restriction for variable name >+ private void findParameterizedType(TypeReference ref, Scope scope) { >+ ReferenceBinding refBinding = (ReferenceBinding) ref.resolvedType; >+ if(refBinding != null) { >+ if (this.options.checkDeprecation && >+ refBinding.isViewedAsDeprecated() && >+ !scope.isDefinedInSameUnit(refBinding)) >+ return; > >- // accept result >- CompletionEngine.this.noProposal = false; >- if(!CompletionEngine.this.requestor.isIgnored(CompletionProposal.VARIABLE_DECLARATION)) { >- InternalCompletionProposal proposal = CompletionEngine.this.createProposal(CompletionProposal.VARIABLE_DECLARATION, CompletionEngine.this.actualCompletionPosition); >- proposal.setSignature(getSignature(typeBinding)); >- proposal.setPackageName(q); >- proposal.setTypeName(displayName); >- proposal.setName(name); >- proposal.setCompletion(name); >- //proposal.setFlags(Flags.AccDefault); >- proposal.setReplaceRange(CompletionEngine.this.startPosition - CompletionEngine.this.offset, CompletionEngine.this.endPosition - CompletionEngine.this.offset); >- proposal.setTokenRange(CompletionEngine.this.tokenStart - CompletionEngine.this.offset, CompletionEngine.this.tokenEnd - CompletionEngine.this.offset); >- proposal.setRelevance(relevance); >- CompletionEngine.this.requestor.accept(proposal); >- if(DEBUG) { >- CompletionEngine.this.printDebug(proposal); >- } >+ int accessibility = IAccessRule.K_ACCESSIBLE; >+ if(refBinding.hasRestrictedAccess()) { >+ AccessRestriction accessRestriction = this.lookupEnvironment.getAccessRestriction(refBinding); >+ if(accessRestriction != null) { >+ switch (accessRestriction.getProblemId()) { >+ case IProblem.ForbiddenReference: >+ if (this.options.checkForbiddenReference) { >+ return; >+ } >+ accessibility = IAccessRule.K_NON_ACCESSIBLE; >+ break; >+ case IProblem.DiscouragedReference: >+ if (this.options.checkDiscouragedReference) { >+ return; >+ } >+ accessibility = IAccessRule.K_DISCOURAGED; >+ break; > } > } > } >- }; > >- switch (kind) { >- case FIELD : >- InternalNamingConventions.suggestFieldNames( >- this.javaProject, >- qualifiedPackageName, >- qualifiedSourceName, >- dim, >- modifiers, >- token, >- discouragedNames, >- namingRequestor); >- break; >- case LOCAL : >- InternalNamingConventions.suggestLocalVariableNames( >- this.javaProject, >- qualifiedPackageName, >- qualifiedSourceName, >- dim, >- token, >- discouragedNames, >- namingRequestor); >- break; >- case ARGUMENT : >- InternalNamingConventions.suggestArgumentNames( >- this.javaProject, >- qualifiedPackageName, >- qualifiedSourceName, >- dim, >- token, >- discouragedNames, >- namingRequestor); >- break; >+ int relevance = computeBaseRelevance(); >+ relevance += computeRelevanceForResolution(); >+ relevance += computeRelevanceForInterestingProposal(); >+ relevance += computeRelevanceForCaseMatching(refBinding.sourceName, refBinding.sourceName); >+ relevance += computeRelevanceForExpectingType(refBinding); >+ relevance += computeRelevanceForQualification(false); >+ relevance += computeRelevanceForRestrictions(accessibility); // no access restriction for type in the current unit >+ >+ if(!this.requestor.isIgnored(CompletionProposal.TYPE_REF)) { >+ createTypeProposal( >+ refBinding, >+ refBinding.qualifiedSourceName(), >+ IAccessRule.K_ACCESSIBLE, >+ CharOperation.NO_CHAR, >+ relevance, >+ null, >+ null, >+ null, >+ false); >+ } > } > } >- >- private void findVariableNameForCollection( >- char[] token, >- char[] qualifiedPackageName, >- char[] qualifiedSourceName, >- char[] sourceName, >- final TypeBinding typeBinding, >- char[][] discouragedNames, >- final char[][] forbiddenNames, >- int kind, >- int modifiers){ > >- findVariableName( >- token, >- qualifiedPackageName, >- qualifiedSourceName, >- sourceName, >- typeBinding, >- discouragedNames, >- forbiddenNames, >- false, >- 1, >- kind, >- modifiers); >- } >+ private void findSubMemberTypes( >+ char[] typeName, >+ ReferenceBinding receiverType, >+ Scope scope, >+ SourceTypeBinding typeInvocation, >+ boolean staticOnly, >+ boolean staticFieldsAndMethodOnly, >+ boolean fromStaticImport, >+ ObjectVector typesFound) { > >- private void findVariableNames(char[] name, TypeReference type , char[][] discouragedNames, char[][] forbiddenNames, int kind, int modifiers){ >- if(type != null && >- type.resolvedType != null) { >- TypeBinding tb = type.resolvedType; >+ ReferenceBinding currentType = receiverType; >+ if (typeName == null || typeName.length == 0) >+ return; > >- if (tb.problemId() == ProblemReasons.NoError && >- tb != Scope.getBaseType(VOID)) { >- findVariableName( >- name, >- tb.leafComponentType().qualifiedPackageName(), >- tb.leafComponentType().qualifiedSourceName(), >- tb.leafComponentType().sourceName(), >- tb, >- discouragedNames, >- forbiddenNames, >- type.dimensions(), >- kind, >- modifiers); >- >- if (tb.isParameterizedType() && >- tb.findSuperTypeOriginatingFrom(TypeIds.T_JavaUtilCollection, false) != null) { >- ParameterizedTypeBinding ptb = ((ParameterizedTypeBinding) tb); >- TypeBinding[] arguments = ptb.arguments; >- if (arguments != null && arguments.length == 1) { >- TypeBinding argument = arguments[0]; >- findVariableNameForCollection( >- name, >- argument.leafComponentType().qualifiedPackageName(), >- argument.leafComponentType().qualifiedSourceName(), >- argument.leafComponentType().sourceName(), >- tb, >- discouragedNames, >- forbiddenNames, >- kind, >- modifiers); >- } >+ if (this.assistNodeIsSuperType && !this.insideQualifiedReference && isForbidden(currentType)) return; // we're trying to find a supertype >+ >+ findMemberTypes( >+ typeName, >+ currentType.memberTypes(), >+ typesFound, >+ receiverType, >+ typeInvocation, >+ staticOnly, >+ staticFieldsAndMethodOnly, >+ fromStaticImport, >+ true, >+ scope, >+ null, >+ null, >+ null, >+ false); >+ >+ ReferenceBinding[] memberTypes = receiverType.memberTypes(); >+ next : for (int i = 0; i < memberTypes.length; i++) { >+ if (this.options.checkVisibility) { >+ if (typeInvocation != null && !memberTypes[i].canBeSeenBy(receiverType, typeInvocation)) { >+ continue next; >+ } else if(typeInvocation == null && !memberTypes[i].canBeSeenBy(this.unitScope.fPackage)) { >+ continue next; > } > } >+ findSubMemberTypes( >+ typeName, >+ memberTypes[i], >+ scope, >+ typeInvocation, >+ staticOnly, >+ staticFieldsAndMethodOnly, >+ fromStaticImport, >+ typesFound); > } >- > } > >- private ImportBinding[] getFavoriteReferenceBindings(Scope scope) { >- if (this.favoriteReferenceBindings != null) return this.favoriteReferenceBindings; >+ private void findTrueOrFalseKeywords(char[][] choices) { >+ if(choices == null || choices.length == 0) return; > >- String[] favoriteReferences = this.requestor.getFavoriteReferences(); >+ if(this.expectedTypesPtr != 0 || this.expectedTypes[0] != TypeBinding.BOOLEAN) return; > >- if (favoriteReferences == null || favoriteReferences.length == 0) return null; >+ for (int i = 0; i < choices.length; i++) { >+ if (CharOperation.equals(choices[i], Keywords.TRUE) || >+ CharOperation.equals(choices[i], Keywords.FALSE) >+ ){ >+ int relevance = computeBaseRelevance(); >+ relevance += computeRelevanceForResolution(); >+ relevance += computeRelevanceForInterestingProposal(); >+ relevance += computeRelevanceForCaseMatching(CharOperation.NO_CHAR, choices[i]); >+ relevance += computeRelevanceForRestrictions(IAccessRule.K_ACCESSIBLE); // no access restriction for keywors >+ relevance += computeRelevanceForExpectingType(TypeBinding.BOOLEAN); >+ relevance += computeRelevanceForQualification(false); >+ relevance += R_TRUE_OR_FALSE; > >- ImportBinding[] resolvedImports = new ImportBinding[favoriteReferences.length]; >+ this.noProposal = false; >+ if(!this.requestor.isIgnored(CompletionProposal.KEYWORD)) { >+ InternalCompletionProposal proposal = createProposal(CompletionProposal.KEYWORD, this.actualCompletionPosition); >+ proposal.setName(choices[i]); >+ proposal.setCompletion(choices[i]); >+ proposal.setReplaceRange(this.startPosition - this.offset, this.endPosition - this.offset); >+ proposal.setTokenRange(this.tokenStart - this.offset, this.tokenEnd - this.offset); >+ proposal.setRelevance(relevance); >+ this.requestor.accept(proposal); >+ if(DEBUG) { >+ this.printDebug(proposal); >+ } >+ } >+ } >+ } >+ } > >- int count = 0; >- next : for (int i = 0; i < favoriteReferences.length; i++) { >- String favoriteReference = favoriteReferences[i]; >+ private void findTypeParameters(char[] token, Scope scope) { >+ if (this.compilerOptions.sourceLevel < ClassFileConstants.JDK1_5) return; > >- int length; >- if (favoriteReference == null || (length = favoriteReference.length()) == 0) continue next; >+ TypeParameter[] typeParameters = null; >+ while (scope != null) { // done when a COMPILATION_UNIT_SCOPE is found >+ typeParameters = null; >+ switch (scope.kind) { >+ case Scope.METHOD_SCOPE : >+ MethodScope methodScope = (MethodScope) scope; >+ if(methodScope.referenceContext instanceof MethodDeclaration) { >+ MethodDeclaration methodDeclaration = (MethodDeclaration) methodScope.referenceContext; >+ typeParameters = methodDeclaration.typeParameters; >+ } else if(methodScope.referenceContext instanceof ConstructorDeclaration) { >+ ConstructorDeclaration methodDeclaration = (ConstructorDeclaration) methodScope.referenceContext; >+ typeParameters = methodDeclaration.typeParameters; >+ } >+ break; >+ case Scope.CLASS_SCOPE : >+ ClassScope classScope = (ClassScope) scope; >+ typeParameters = classScope.referenceContext.typeParameters; >+ break; >+ case Scope.COMPILATION_UNIT_SCOPE : >+ return; >+ } >+ if(typeParameters != null) { >+ for (int i = 0; i < typeParameters.length; i++) { >+ int typeLength = token.length; >+ TypeParameter typeParameter = typeParameters[i]; > >- boolean onDemand = favoriteReference.charAt(length - 1) == '*'; >+ if(typeParameter.binding == null) continue; > >- char[][] compoundName = CharOperation.splitOn('.', favoriteReference.toCharArray()); >- if (onDemand) { >- compoundName = CharOperation.subarray(compoundName, 0, compoundName.length - 1); >- } >+ if (typeLength > typeParameter.name.length) continue; > >- // remove duplicate and conflicting >- for (int j = 0; j < count; j++) { >- ImportReference f = resolvedImports[j].reference; >+ if (!CharOperation.prefixEquals(token, typeParameter.name, false) >+ && !(this.options.camelCaseMatch && CharOperation.camelCaseMatch(token, typeParameter.name))) continue; > >- if (CharOperation.equals(f.tokens, compoundName)) continue next; >+ int relevance = computeBaseRelevance(); >+ relevance += computeRelevanceForResolution(); >+ relevance += computeRelevanceForInterestingProposal(); >+ relevance += computeRelevanceForCaseMatching(token, typeParameter.name); >+ relevance += computeRelevanceForExpectingType(typeParameter.type == null ? null :typeParameter.type.resolvedType); >+ relevance += computeRelevanceForQualification(false); >+ relevance += computeRelevanceForException(typeParameter.name); >+ relevance += computeRelevanceForRestrictions(IAccessRule.K_ACCESSIBLE); // no access restriction fot type parameter > >- if (!onDemand && ((f.bits & ASTNode.OnDemand) == 0)) { >- if (CharOperation.equals(f.tokens[f.tokens.length - 1], compoundName[compoundName.length - 1])) >- continue next; >+ this.noProposal = false; >+ if(!this.requestor.isIgnored(CompletionProposal.TYPE_REF)) { >+ createTypeParameterProposal(typeParameter, relevance); >+ } > } > } >+ scope = scope.parent; >+ } >+ } > >- boolean isStatic = true; >- >- ImportReference importReference = >- new ImportReference( >- compoundName, >- new long[compoundName.length], >- onDemand, >- isStatic ? ClassFileConstants.AccStatic : ClassFileConstants.AccDefault); >+ private void findTypesAndPackages(char[] token, Scope scope, boolean proposeBaseTypes, boolean proposeVoidType, ObjectVector typesFound) { > >- Binding importBinding = this.unitScope.findImport(compoundName, isStatic, onDemand); >+ if (token == null) >+ return; > >- if (!importBinding.isValidBinding()) { >- continue next; >+ // do not propose type if completion token is empty >+ boolean skip = false; >+ if (token.length == 0 && NO_TYPE_COMPLETION_ON_EMPTY_TOKEN) { >+ if(!this.assistNodeIsConstructor && (this.assistNodeInJavadoc & CompletionOnJavadoc.EXCEPTION) == 0) { >+ return; > } >+ skip = true; >+ } > >- if (importBinding instanceof PackageBinding) { >- continue next; >- } >+ boolean proposeType = >+ !this.requestor.isIgnored(CompletionProposal.TYPE_REF) || >+ ((this.assistNodeInJavadoc & CompletionOnJavadoc.TEXT) != 0 && !this.requestor.isIgnored(CompletionProposal.JAVADOC_TYPE_REF)); > >- resolvedImports[count++] = >- new ImportBinding(compoundName, onDemand, importBinding, importReference); >+ boolean proposeAllMemberTypes = !this.assistNodeIsConstructor; >+ >+ if (!skip && proposeType && scope.enclosingSourceType() != null) { >+ >+ checkCancel(); >+ >+ findNestedTypes(token, scope.enclosingSourceType(), scope, proposeAllMemberTypes, typesFound); >+ if(!this.assistNodeIsInterface && >+ !this.assistNodeIsConstructor && >+ !this.assistNodeIsAnnotation && >+ this.assistNodeInJavadoc == 0) { >+ >+ checkCancel(); >+ >+ // don't propose type parameters if the completion is a constructor ('new |') >+ findTypeParameters(token, scope); >+ } > } > >- if (resolvedImports.length > count) >- System.arraycopy(resolvedImports, 0, resolvedImports = new ImportBinding[count], 0, count); >+ boolean isEmptyPrefix = token.length == 0; > >- return this.favoriteReferenceBindings = resolvedImports; >- } >+ if (!skip && proposeType && this.unitScope != null) { >+ >+ ReferenceBinding outerInvocationType = scope.enclosingSourceType(); >+ if(outerInvocationType != null) { >+ ReferenceBinding temp = outerInvocationType.enclosingType(); >+ while(temp != null) { >+ outerInvocationType = temp; >+ temp = temp.enclosingType(); >+ } >+ } > >- public AssistParser getParser() { >+ int typeLength = token.length; >+ SourceTypeBinding[] types = this.unitScope.topLevelTypes; > >- return this.parser; >- } >+ next : for (int i = 0, length = types.length; i < length; i++) { >+ >+ checkCancel(); >+ >+ SourceTypeBinding sourceType = types[i]; > >- private char[] getCompletedTypeSignature(ReferenceBinding referenceBinding) { >- char[] result = null; >- StringBuffer sig = new StringBuffer(10); >- if (!referenceBinding.isMemberType()) { >- char[] typeSig = referenceBinding.genericTypeSignature(); >- sig.append(typeSig, 0, typeSig.length); >- } else if (!this.insideQualifiedReference) { >- if (referenceBinding.isStatic()) { >- char[] typeSig = referenceBinding.signature(); >- sig.append(typeSig, 0, typeSig.length-1); // copy all but trailing semicolon >+ if(isForbidden(sourceType)) continue next; > >- TypeVariableBinding[] typeVariables = referenceBinding.typeVariables(); >- if (typeVariables != Binding.NO_TYPE_VARIABLES) { >- sig.append(Signature.C_GENERIC_START); >- for (int i = 0, length = typeVariables.length; i < length; i++) { >- sig.append(typeVariables[i].genericTypeSignature()); >- } >- sig.append(Signature.C_GENERIC_END); >+ if(proposeAllMemberTypes && >+ sourceType != outerInvocationType) { >+ findSubMemberTypes( >+ token, >+ sourceType, >+ scope, >+ scope.enclosingSourceType(), >+ false, >+ false, >+ false, >+ typesFound); > } >- sig.append(Signature.C_SEMICOLON); >- } else { >- char[] typeSig = referenceBinding.genericTypeSignature(); >- sig.append(typeSig, 0, typeSig.length); >- } >- } else { >- ReferenceBinding enclosingType = referenceBinding.enclosingType(); >- if (enclosingType.isParameterizedType()) { >- char[] typeSig = referenceBinding.genericTypeSignature(); >- sig.append(typeSig, 0, typeSig.length-1); >- >- TypeVariableBinding[] typeVariables = referenceBinding.typeVariables(); >- if (typeVariables != Binding.NO_TYPE_VARIABLES) { >- sig.append(Signature.C_GENERIC_START); >- for (int i = 0, length = typeVariables.length; i < length; i++) { >- sig.append(typeVariables[i].genericTypeSignature()); >- } >- sig.append(Signature.C_GENERIC_END); >- } >- } else { >- char[] typeSig = referenceBinding.signature(); >- sig.append(typeSig, 0, typeSig.length-1); // copy all but trailing semicolon >- >- if (referenceBinding.isStatic()) { >- TypeVariableBinding[] typeVariables = referenceBinding.typeVariables(); >- if (typeVariables != Binding.NO_TYPE_VARIABLES) { >- sig.append(Signature.C_GENERIC_START); >- for (int i = 0, length = typeVariables.length; i < length; i++) { >- sig.append(typeVariables[i].genericTypeSignature()); >- } >- sig.append(Signature.C_GENERIC_END); >- } >- } >- } >- sig.append(Signature.C_SEMICOLON); >- } >- int sigLength = sig.length(); >- result = new char[sigLength]; >- sig.getChars(0, sigLength, result, 0); >- result = CharOperation.replaceOnCopy(result, '/', Signature.C_DOT); >- return result; >- } > >- private static char[] getRequiredTypeSignature(TypeBinding typeBinding) { >- char[] result = null; >- StringBuffer sig = new StringBuffer(10); >+ if (sourceType.sourceName == CompletionParser.FAKE_TYPE_NAME) continue next; >+ if (sourceType.sourceName == TypeConstants.PACKAGE_INFO_NAME) continue next; > >- sig.append(typeBinding.signature()); >+ if (typeLength > sourceType.sourceName.length) continue next; > >- int sigLength = sig.length(); >- result = new char[sigLength]; >- sig.getChars(0, sigLength, result, 0); >- result = CharOperation.replaceOnCopy(result, '/', '.'); >- return result; >- } >+ if (!CharOperation.prefixEquals(token, sourceType.sourceName, false) >+ && !(this.options.camelCaseMatch && CharOperation.camelCaseMatch(token, sourceType.sourceName))) continue; > >- protected boolean hasPossibleAnnotationTarget(TypeBinding typeBinding, Scope scope) { >- if (this.targetedElement == TagBits.AnnotationForPackage) { >- long target = typeBinding.getAnnotationTagBits() & TagBits.AnnotationTargetMASK; >- if(target != 0 && (target & TagBits.AnnotationForPackage) == 0) { >- return false; >- } >- } else if ((this.targetedElement & TagBits.AnnotationForType) != 0) { >- if (scope.parent != null && >- scope.parent.parent != null && >- scope.parent.referenceContext() instanceof CompletionOnAnnotationOfType && >- scope.parent.parent instanceof CompilationUnitScope) { >- long target = typeBinding.getAnnotationTagBits() & TagBits.AnnotationTargetMASK; >- if ((this.targetedElement & TagBits.AnnotationForAnnotationType) != 0) { >- if(target != 0 && (target &(TagBits.AnnotationForType | TagBits.AnnotationForAnnotationType)) == 0) { >- return false; >- } >- } else { >- if(target != 0 && (target &(TagBits.AnnotationForType)) == 0) { >- return false; >- } >+ if (this.assistNodeIsAnnotation && !hasPossibleAnnotationTarget(sourceType, scope)) { >+ continue next; > } >- } >- } >- return true; >- } > >- protected void reset() { >+ for (int j = typesFound.size; --j >= 0;) { >+ ReferenceBinding otherType = (ReferenceBinding) typesFound.elementAt(j); > >- super.reset(false); >- this.knownPkgs = new HashtableOfObject(10); >- this.knownTypes = new HashtableOfObject(10); >- } >+ if (sourceType == otherType) continue next; >+ } > >- private void setSourceAndTokenRange(int start, int end) { >- this.setSourceAndTokenRange(start, end, true); >- } >+ this.knownTypes.put(CharOperation.concat(sourceType.qualifiedPackageName(), sourceType.sourceName(), '.'), this); > >- private void setSourceAndTokenRange(int start, int end, boolean emptyTokenAdjstment) { >- this.setSourceRange(start, end, emptyTokenAdjstment); >- this.setTokenRange(start, end, emptyTokenAdjstment); >- } >+ if(this.assistNodeIsClass) { >+ if(!sourceType.isClass()) continue next; >+ } else if(this.assistNodeIsInterface) { >+ if(!sourceType.isInterface() && !sourceType.isAnnotationType()) continue next; >+ } else if (this.assistNodeIsAnnotation) { >+ if(!sourceType.isAnnotationType()) continue next; >+ } else if (isEmptyPrefix && this.assistNodeIsException) { >+ if (sourceType.findSuperTypeOriginatingFrom(TypeIds.T_JavaLangThrowable, true) == null) { >+ continue next; >+ } >+ } > >- private void setSourceRange(int start, int end) { >- this.setSourceRange(start, end, true); >- } >+ int relevance = computeBaseRelevance(); >+ relevance += computeRelevanceForResolution(); >+ relevance += computeRelevanceForInterestingProposal(); >+ relevance += computeRelevanceForCaseMatching(token, sourceType.sourceName); >+ relevance += computeRelevanceForExpectingType(sourceType); >+ relevance += computeRelevanceForQualification(false); >+ relevance += computeRelevanceForRestrictions(IAccessRule.K_ACCESSIBLE); // no access restriction for type in the current unit > >- private void setSourceRange(int start, int end, boolean emptyTokenAdjstment) { >- this.startPosition = start; >- if(emptyTokenAdjstment) { >- int endOfEmptyToken = ((CompletionScanner)this.parser.scanner).endOfEmptyToken; >- this.endPosition = endOfEmptyToken > end ? endOfEmptyToken + 1 : end + 1; >- } else { >- this.endPosition = end + 1; >+ if (sourceType.isAnnotationType()) { >+ relevance += computeRelevanceForAnnotation(); >+ relevance += computeRelevanceForAnnotationTarget(sourceType); >+ } else if (sourceType.isInterface()) { >+ relevance += computeRelevanceForInterface(); >+ } else if(sourceType.isClass()){ >+ relevance += computeRelevanceForClass(); >+ relevance += computeRelevanceForException(sourceType.sourceName); >+ } >+ this.noProposal = false; >+ if(proposeType) { >+ char[] typeName = sourceType.sourceName(); >+ createTypeProposal( >+ sourceType, >+ typeName, >+ IAccessRule.K_ACCESSIBLE, >+ typeName, >+ relevance, >+ null, >+ null, >+ null, >+ false); >+ } >+ } > } >- } > >- private void setTokenRange(int start, int end) { >- this.setTokenRange(start, end, true); >- } >- >- private void setTokenRange(int start, int end, boolean emptyTokenAdjstment) { >- this.tokenStart = start; >- if(emptyTokenAdjstment) { >- int endOfEmptyToken = ((CompletionScanner)this.parser.scanner).endOfEmptyToken; >- this.tokenEnd = endOfEmptyToken > end ? endOfEmptyToken + 1 : end + 1; >- } else { >- this.tokenEnd = end + 1; >+ if(!skip && proposeType) { >+ >+ checkCancel(); >+ >+ findTypesFromStaticImports(token, scope, proposeAllMemberTypes, typesFound); > } >- } > >- private char[][] computeAlreadyDefinedName( >- BlockScope scope, >- InvocationSite invocationSite) { >- ArrayList result = new ArrayList(); >+ if (isEmptyPrefix && !this.assistNodeIsAnnotation) { >+ if(proposeType && this.expectedTypesPtr > -1) { >+ next : for (int i = 0; i <= this.expectedTypesPtr; i++) { >+ >+ checkCancel(); >+ >+ if(this.expectedTypes[i] instanceof ReferenceBinding) { >+ ReferenceBinding refBinding = (ReferenceBinding)this.expectedTypes[i]; > >- boolean staticsOnly = false; >+ if(refBinding.isTypeVariable() && this.assistNodeIsConstructor) { >+ // don't propose type variable if the completion is a constructor ('new |') >+ continue next; >+ } >+ if (this.options.checkDeprecation && >+ refBinding.isViewedAsDeprecated() && >+ !scope.isDefinedInSameUnit(refBinding)) >+ continue next; > >- Scope currentScope = scope; >+ int accessibility = IAccessRule.K_ACCESSIBLE; >+ if(refBinding.hasRestrictedAccess()) { >+ AccessRestriction accessRestriction = this.lookupEnvironment.getAccessRestriction(refBinding); >+ if(accessRestriction != null) { >+ switch (accessRestriction.getProblemId()) { >+ case IProblem.ForbiddenReference: >+ if (this.options.checkForbiddenReference) { >+ continue next; >+ } >+ accessibility = IAccessRule.K_NON_ACCESSIBLE; >+ break; >+ case IProblem.DiscouragedReference: >+ if (this.options.checkDiscouragedReference) { >+ continue next; >+ } >+ accessibility = IAccessRule.K_DISCOURAGED; >+ break; >+ } >+ } >+ } > >- done1 : while (true) { // done when a COMPILATION_UNIT_SCOPE is found >+ for (int j = 0; j < typesFound.size(); j++) { >+ ReferenceBinding typeFound = (ReferenceBinding)typesFound.elementAt(j); >+ if (typeFound == refBinding) { >+ continue next; >+ } >+ } > >- switch (currentScope.kind) { >+ boolean inSameUnit = this.unitScope.isDefinedInSameUnit(refBinding); > >- case Scope.METHOD_SCOPE : >- // handle the error case inside an explicit constructor call (see MethodScope>>findField) >- MethodScope methodScope = (MethodScope) currentScope; >- staticsOnly |= methodScope.isStatic | methodScope.isConstructorCall; >+ // top level types of the current unit are already proposed. >+ if(skip || !inSameUnit || (inSameUnit && refBinding.isMemberType())) { >+ char[] packageName = refBinding.qualifiedPackageName(); >+ char[] typeName = refBinding.sourceName(); >+ char[] completionName = typeName; > >- //$FALL-THROUGH$ >- case Scope.BLOCK_SCOPE : >- BlockScope blockScope = (BlockScope) currentScope; >+ boolean isQualified = false; >+ if (!this.insideQualifiedReference && !refBinding.isMemberType()) { >+ if (mustQualifyType(packageName, typeName, null, refBinding.modifiers)) { >+ if (packageName == null || packageName.length == 0) >+ if (this.unitScope != null && this.unitScope.fPackage.compoundName != CharOperation.NO_CHAR_CHAR) >+ continue next; // ignore types from the default package from outside it >+ completionName = CharOperation.concat(packageName, typeName, '.'); >+ isQualified = true; >+ } >+ } > >- next : for (int i = 0, length = blockScope.locals.length; i < length; i++) { >- LocalVariableBinding local = blockScope.locals[i]; >+ if(this.assistNodeIsClass) { >+ if(!refBinding.isClass()) continue next; >+ } else if(this.assistNodeIsInterface) { >+ if(!refBinding.isInterface() && !refBinding.isAnnotationType()) continue next; >+ } else if (this.assistNodeIsAnnotation) { >+ if(!refBinding.isAnnotationType()) continue next; >+ } > >- if (local == null) >- break next; >+ int relevance = computeBaseRelevance(); >+ relevance += computeRelevanceForResolution(); >+ relevance += computeRelevanceForInterestingProposal(); >+ relevance += computeRelevanceForCaseMatching(token, typeName); >+ relevance += computeRelevanceForExpectingType(refBinding); >+ relevance += computeRelevanceForQualification(isQualified); >+ relevance += computeRelevanceForRestrictions(accessibility); > >- if (local.isSecret()) >- continue next; >+ if(refBinding.isClass()) { >+ relevance += computeRelevanceForClass(); >+ relevance += computeRelevanceForException(typeName); >+ } else if(refBinding.isEnum()) { >+ relevance += computeRelevanceForEnum(); >+ } else if(refBinding.isInterface()) { >+ relevance += computeRelevanceForInterface(); >+ } > >- result.add(local.name); >+ this.noProposal = false; >+ if(!this.requestor.isIgnored(CompletionProposal.TYPE_REF)) { >+ InternalCompletionProposal proposal = createProposal(CompletionProposal.TYPE_REF, this.actualCompletionPosition); >+ proposal.setDeclarationSignature(packageName); >+ proposal.setSignature(getSignature(refBinding)); >+ proposal.setPackageName(packageName); >+ proposal.setTypeName(typeName); >+ proposal.setCompletion(completionName); >+ proposal.setFlags(refBinding.modifiers); >+ proposal.setReplaceRange(this.startPosition - this.offset, this.endPosition - this.offset); >+ proposal.setTokenRange(this.tokenStart - this.offset, this.tokenEnd - this.offset); >+ proposal.setRelevance(relevance); >+ proposal.setAccessibility(accessibility); >+ this.requestor.accept(proposal); >+ if(DEBUG) { >+ this.printDebug(proposal); >+ } >+ } >+ } > } >- break; >- >- case Scope.CLASS_SCOPE : >- ClassScope classScope = (ClassScope) currentScope; >- SourceTypeBinding enclosingType = classScope.referenceContext.binding; >- computeAlreadyDefinedName( >- enclosingType, >- classScope, >- staticsOnly, >- invocationSite, >- result); >- staticsOnly |= enclosingType.isStatic(); >- break; >- >- case Scope.COMPILATION_UNIT_SCOPE : >- break done1; >+ } > } >- currentScope = currentScope.parent; >- } >- >- if (result.size() == 0) return CharOperation.NO_CHAR_CHAR; >- >- return (char[][])result.toArray(new char[result.size()][]); >- } >- >- private void computeAlreadyDefinedName( >- SourceTypeBinding receiverType, >- ClassScope scope, >- boolean onlyStaticFields, >- InvocationSite invocationSite, >- ArrayList result) { >- >- ReferenceBinding currentType = receiverType; >- ReferenceBinding[] interfacesToVisit = null; >- int nextPosition = 0; >- do { >- ReferenceBinding[] itsInterfaces = currentType.superInterfaces(); >- if (itsInterfaces != Binding.NO_SUPERINTERFACES) { >- if (interfacesToVisit == null) { >- interfacesToVisit = itsInterfaces; >- nextPosition = interfacesToVisit.length; >- } else { >- int itsLength = itsInterfaces.length; >- if (nextPosition + itsLength >= interfacesToVisit.length) >- System.arraycopy(interfacesToVisit, 0, interfacesToVisit = new ReferenceBinding[nextPosition + itsLength + 5], 0, nextPosition); >- nextInterface : for (int a = 0; a < itsLength; a++) { >- ReferenceBinding next = itsInterfaces[a]; >- for (int b = 0; b < nextPosition; b++) >- if (next == interfacesToVisit[b]) continue nextInterface; >- interfacesToVisit[nextPosition++] = next; >+ } else { >+ if(!isEmptyPrefix && !this.requestor.isIgnored(CompletionProposal.KEYWORD)) { >+ if (this.assistNodeInJavadoc == 0 || (this.assistNodeInJavadoc & CompletionOnJavadoc.BASE_TYPES) != 0) { >+ if (proposeBaseTypes) { >+ if (proposeVoidType) { >+ findKeywords(token, BASE_TYPE_NAMES, false, false); >+ } else { >+ findKeywords(token, BASE_TYPE_NAMES_WITHOUT_VOID, false, false); >+ } > } > } > } >- >- FieldBinding[] fields = currentType.availableFields(); >- if(fields != null && fields.length > 0) { >- computeAlreadyDefinedName( >- fields, >- scope, >- onlyStaticFields, >- receiverType, >- invocationSite, >- result); >- } >- currentType = currentType.superclass(); >- } while ( currentType != null); >- >- if (interfacesToVisit != null) { >- for (int i = 0; i < nextPosition; i++) { >- ReferenceBinding anInterface = interfacesToVisit[i]; >- FieldBinding[] fields = anInterface.availableFields(); >- if(fields != null) { >- computeAlreadyDefinedName( >- fields, >- scope, >- onlyStaticFields, >- receiverType, >- invocationSite, >- result); >+ if(proposeType) { >+ int l = typesFound.size(); >+ for (int i = 0; i < l; i++) { >+ ReferenceBinding typeFound = (ReferenceBinding) typesFound.elementAt(i); >+ char[] fullyQualifiedTypeName = >+ CharOperation.concat( >+ typeFound.qualifiedPackageName(), >+ typeFound.qualifiedSourceName(), >+ '.'); >+ this.knownTypes.put(fullyQualifiedTypeName, this); > } >- >- ReferenceBinding[] itsInterfaces = anInterface.superInterfaces(); >- if (itsInterfaces != Binding.NO_SUPERINTERFACES) { >- int itsLength = itsInterfaces.length; >- if (nextPosition + itsLength >= interfacesToVisit.length) >- System.arraycopy(interfacesToVisit, 0, interfacesToVisit = new ReferenceBinding[nextPosition + itsLength + 5], 0, nextPosition); >- nextInterface : for (int a = 0; a < itsLength; a++) { >- ReferenceBinding next = itsInterfaces[a]; >- for (int b = 0; b < nextPosition; b++) >- if (next == interfacesToVisit[b]) continue nextInterface; >- interfacesToVisit[nextPosition++] = next; >- } >+ int searchFor = IJavaSearchConstants.TYPE; >+ if(this.assistNodeIsClass) { >+ searchFor = IJavaSearchConstants.CLASS; >+ } else if(this.assistNodeIsInterface) { >+ searchFor = IJavaSearchConstants.INTERFACE_AND_ANNOTATION; >+ } else if(this.assistNodeIsEnum) { >+ searchFor = IJavaSearchConstants.ENUM; >+ } else if(this.assistNodeIsAnnotation) { >+ searchFor = IJavaSearchConstants.ANNOTATION_TYPE; > } >+ >+ checkCancel(); >+ >+ this.foundTypesCount = 0; >+ this.nameEnvironment.findTypes( >+ token, >+ proposeAllMemberTypes, >+ this.options.camelCaseMatch, >+ searchFor, >+ this); >+ acceptTypes(scope); >+ } >+ if(!isEmptyPrefix && !this.requestor.isIgnored(CompletionProposal.PACKAGE_REF)) { >+ >+ checkCancel(); >+ >+ this.nameEnvironment.findPackages(token, this); > } > } > } > >- private void computeAlreadyDefinedName( >- FieldBinding[] fields, >- Scope scope, >- boolean onlyStaticFields, >- ReferenceBinding receiverType, >- InvocationSite invocationSite, >- ArrayList result) { >- >- next : for (int f = fields.length; --f >= 0;) { >- FieldBinding field = fields[f]; >- >- if (field.isSynthetic()) continue next; >+ private void findTypesAndSubpackages( >+ char[] token, >+ PackageBinding packageBinding, >+ Scope scope) { > >- if (onlyStaticFields && !field.isStatic()) continue next; >+ boolean proposeType = >+ !this.requestor.isIgnored(CompletionProposal.TYPE_REF) || >+ ((this.assistNodeInJavadoc & CompletionOnJavadoc.TEXT) != 0 && !this.requestor.isIgnored(CompletionProposal.JAVADOC_TYPE_REF)); > >- if (!field.canBeSeenBy(receiverType, invocationSite, scope)) continue next; >+ char[] qualifiedName = >+ CharOperation.concatWith(packageBinding.compoundName, token, '.'); > >- result.add(field.name); >+ if (token == null || token.length == 0) { >+ int length = qualifiedName.length; >+ System.arraycopy( >+ qualifiedName, >+ 0, >+ qualifiedName = new char[length + 1], >+ 0, >+ length); >+ qualifiedName[length] = '.'; > } >- } > >- int computeBaseRelevance(){ >- return R_DEFAULT; >- } >- int computeRelevanceForResolution(){ >- return computeRelevanceForResolution(true); >- } >- int computeRelevanceForResolution(boolean isResolved){ >- if (isResolved) { >- return R_RESOLVED; >- } >- return 0; >- } >- private void computeExpectedTypes(ASTNode parent, ASTNode node, Scope scope){ >+ this.qualifiedCompletionToken = qualifiedName; > >- // default filter >- this.expectedTypesFilter = SUBTYPE; >- this.hasJavaLangObjectAsExpectedType = false; >+ if (proposeType && this.unitScope != null) { >+ int typeLength = qualifiedName.length; >+ SourceTypeBinding[] types = this.unitScope.topLevelTypes; > >- // find types from parent >- if(parent instanceof AbstractVariableDeclaration) { >- AbstractVariableDeclaration variable = (AbstractVariableDeclaration)parent; >- TypeBinding binding = variable.type.resolvedType; >- if(binding != null) { >- if(!(variable.initialization instanceof ArrayInitializer)) { >- addExpectedType(binding, scope); >- } >- } >- } else if(parent instanceof Assignment) { >- TypeBinding binding = ((Assignment)parent).lhs.resolvedType; >- if(binding != null) { >- addExpectedType(binding, scope); >- } >- } else if(parent instanceof ReturnStatement) { >- if(scope.methodScope().referenceContext instanceof AbstractMethodDeclaration) { >- MethodBinding methodBinding = ((AbstractMethodDeclaration) scope.methodScope().referenceContext).binding; >- TypeBinding binding = methodBinding == null ? null : methodBinding.returnType; >- if(binding != null) { >- addExpectedType(binding, scope); >- } >- } >- } else if(parent instanceof CastExpression) { >- Expression e = ((CastExpression)parent).type; >- TypeBinding binding = e.resolvedType; >- if(binding != null){ >- addExpectedType(binding, scope); >- this.expectedTypesFilter = SUBTYPE | SUPERTYPE; >- } >- } else if(parent instanceof MessageSend) { >- MessageSend messageSend = (MessageSend) parent; >+ for (int i = 0, length = types.length; i < length; i++) { >+ >+ checkCancel(); >+ >+ SourceTypeBinding sourceType = types[i]; > >- if(messageSend.actualReceiverType instanceof ReferenceBinding) { >- ReferenceBinding binding = (ReferenceBinding)messageSend.actualReceiverType; >- boolean isStatic = messageSend.receiver.isTypeReference(); >+ char[] qualifiedSourceTypeName = CharOperation.concatWith(sourceType.compoundName, '.'); > >- while(binding != null) { >- computeExpectedTypesForMessageSend( >- binding, >- messageSend.selector, >- messageSend.arguments, >- (ReferenceBinding)messageSend.actualReceiverType, >- scope, >- messageSend, >- isStatic); >- computeExpectedTypesForMessageSendForInterface( >- binding, >- messageSend.selector, >- messageSend.arguments, >- (ReferenceBinding)messageSend.actualReceiverType, >- scope, >- messageSend, >- isStatic); >- binding = binding.superclass(); >- } >- } >- } else if(parent instanceof AllocationExpression) { >- AllocationExpression allocationExpression = (AllocationExpression) parent; >+ if (sourceType.sourceName == CompletionParser.FAKE_TYPE_NAME) continue; >+ if (sourceType.sourceName == TypeConstants.PACKAGE_INFO_NAME) continue; >+ if (typeLength > qualifiedSourceTypeName.length) continue; >+ if (!(packageBinding == sourceType.getPackage())) continue; > >- ReferenceBinding binding = (ReferenceBinding)allocationExpression.type.resolvedType; >+ if (!CharOperation.prefixEquals(qualifiedName, qualifiedSourceTypeName, false) >+ && !(this.options.camelCaseMatch && CharOperation.camelCaseMatch(token, sourceType.sourceName))) continue; > >- if(binding != null) { >- computeExpectedTypesForAllocationExpression( >- binding, >- allocationExpression.arguments, >- scope, >- allocationExpression); >- } >- } else if(parent instanceof OperatorExpression) { >- int operator = (parent.bits & ASTNode.OperatorMASK) >> ASTNode.OperatorSHIFT; >- if(parent instanceof ConditionalExpression) { >- // for future use >- } else if(parent instanceof InstanceOfExpression) { >- InstanceOfExpression e = (InstanceOfExpression) parent; >- TypeBinding binding = e.expression.resolvedType; >- if(binding != null){ >- addExpectedType(binding, scope); >- this.expectedTypesFilter = SUBTYPE | SUPERTYPE; >- } >- } else if(parent instanceof BinaryExpression) { >- BinaryExpression binaryExpression = (BinaryExpression) parent; >- switch(operator) { >- case OperatorIds.EQUAL_EQUAL : >- // expected type is not relevant in this case >- TypeBinding binding = binaryExpression.left.resolvedType; >- if (binding != null) { >- addExpectedType(binding, scope); >- this.expectedTypesFilter = SUBTYPE | SUPERTYPE; >- } >- break; >- case OperatorIds.PLUS : >- addExpectedType(TypeBinding.SHORT, scope); >- addExpectedType(TypeBinding.INT, scope); >- addExpectedType(TypeBinding.LONG, scope); >- addExpectedType(TypeBinding.FLOAT, scope); >- addExpectedType(TypeBinding.DOUBLE, scope); >- addExpectedType(TypeBinding.CHAR, scope); >- addExpectedType(TypeBinding.BYTE, scope); >- addExpectedType(scope.getJavaLangString(), scope); >- break; >- case OperatorIds.AND_AND : >- case OperatorIds.OR_OR : >- case OperatorIds.XOR : >- addExpectedType(TypeBinding.BOOLEAN, scope); >- break; >- default : >- addExpectedType(TypeBinding.SHORT, scope); >- addExpectedType(TypeBinding.INT, scope); >- addExpectedType(TypeBinding.LONG, scope); >- addExpectedType(TypeBinding.FLOAT, scope); >- addExpectedType(TypeBinding.DOUBLE, scope); >- addExpectedType(TypeBinding.CHAR, scope); >- addExpectedType(TypeBinding.BYTE, scope); >- break; >- } >- if(operator == OperatorIds.LESS) { >- if(binaryExpression.left instanceof SingleNameReference){ >- SingleNameReference name = (SingleNameReference) binaryExpression.left; >- Binding b = scope.getBinding(name.token, Binding.VARIABLE | Binding.TYPE, name, false); >- if(b instanceof ReferenceBinding) { >- TypeVariableBinding[] typeVariableBindings =((ReferenceBinding)b).typeVariables(); >- if(typeVariableBindings != null && typeVariableBindings.length > 0) { >- addExpectedType(typeVariableBindings[0].firstBound, scope); >- } >+ if (this.options.checkDeprecation && >+ sourceType.isViewedAsDeprecated() && >+ !scope.isDefinedInSameUnit(sourceType)) >+ continue; > >+ int accessibility = IAccessRule.K_ACCESSIBLE; >+ if(sourceType.hasRestrictedAccess()) { >+ AccessRestriction accessRestriction = this.lookupEnvironment.getAccessRestriction(sourceType); >+ if(accessRestriction != null) { >+ switch (accessRestriction.getProblemId()) { >+ case IProblem.ForbiddenReference: >+ if (this.options.checkForbiddenReference) { >+ continue; >+ } >+ accessibility = IAccessRule.K_NON_ACCESSIBLE; >+ break; >+ case IProblem.DiscouragedReference: >+ if (this.options.checkDiscouragedReference) { >+ continue; >+ } >+ accessibility = IAccessRule.K_DISCOURAGED; >+ break; > } > } > } >- } else if(parent instanceof UnaryExpression) { >- switch(operator) { >- case OperatorIds.NOT : >- addExpectedType(TypeBinding.BOOLEAN, scope); >- break; >- case OperatorIds.TWIDDLE : >- addExpectedType(TypeBinding.SHORT, scope); >- addExpectedType(TypeBinding.INT, scope); >- addExpectedType(TypeBinding.LONG, scope); >- addExpectedType(TypeBinding.CHAR, scope); >- addExpectedType(TypeBinding.BYTE, scope); >- break; >- case OperatorIds.PLUS : >- case OperatorIds.MINUS : >- case OperatorIds.PLUS_PLUS : >- case OperatorIds.MINUS_MINUS : >- addExpectedType(TypeBinding.SHORT, scope); >- addExpectedType(TypeBinding.INT, scope); >- addExpectedType(TypeBinding.LONG, scope); >- addExpectedType(TypeBinding.FLOAT, scope); >- addExpectedType(TypeBinding.DOUBLE, scope); >- addExpectedType(TypeBinding.CHAR, scope); >- addExpectedType(TypeBinding.BYTE, scope); >- break; >+ >+ this.knownTypes.put(CharOperation.concat(sourceType.qualifiedPackageName(), sourceType.sourceName(), '.'), this); >+ >+ int relevance = computeBaseRelevance(); >+ relevance += computeRelevanceForResolution(); >+ relevance += computeRelevanceForInterestingProposal(); >+ relevance += computeRelevanceForCaseMatching(qualifiedName, qualifiedSourceTypeName); >+ relevance += computeRelevanceForExpectingType(sourceType); >+ relevance += computeRelevanceForQualification(false); >+ relevance += computeRelevanceForRestrictions(accessibility); >+ >+ if (sourceType.isAnnotationType()) { >+ relevance += computeRelevanceForAnnotation(); >+ } else if (sourceType.isInterface()) { >+ relevance += computeRelevanceForInterface(); >+ } else if (sourceType.isClass()) { >+ relevance += computeRelevanceForClass(); >+ relevance += computeRelevanceForException(sourceType.sourceName); >+ } >+ this.noProposal = false; >+ if(proposeType) { >+ char[] typeName = sourceType.sourceName(); >+ createTypeProposal( >+ sourceType, >+ typeName, >+ IAccessRule.K_ACCESSIBLE, >+ typeName, >+ relevance, >+ null, >+ null, >+ null, >+ false); > } > } >- } else if(parent instanceof ArrayReference) { >- addExpectedType(TypeBinding.SHORT, scope); >- addExpectedType(TypeBinding.INT, scope); >- addExpectedType(TypeBinding.LONG, scope); >- } else if(parent instanceof ParameterizedSingleTypeReference) { >- ParameterizedSingleTypeReference ref = (ParameterizedSingleTypeReference) parent; >- TypeVariableBinding[] typeVariables = ((ReferenceBinding)ref.resolvedType).typeVariables(); >- int length = ref.typeArguments == null ? 0 : ref.typeArguments.length; >- if(typeVariables != null && typeVariables.length >= length) { >- int index = length - 1; >- while(index > -1 && ref.typeArguments[index] != node) index--; >+ } > >- TypeBinding bound = typeVariables[index].firstBound; >- addExpectedType(bound == null ? scope.getJavaLangObject() : bound, scope); >+ if(proposeType) { >+ int searchFor = IJavaSearchConstants.TYPE; >+ if(this.assistNodeIsClass) { >+ searchFor = IJavaSearchConstants.CLASS; >+ } else if(this.assistNodeIsInterface) { >+ searchFor = IJavaSearchConstants.INTERFACE_AND_ANNOTATION; >+ } else if(this.assistNodeIsEnum) { >+ searchFor = IJavaSearchConstants.ENUM; >+ } else if(this.assistNodeIsAnnotation) { >+ searchFor = IJavaSearchConstants.ANNOTATION_TYPE; > } >- } else if(parent instanceof ParameterizedQualifiedTypeReference) { >- ParameterizedQualifiedTypeReference ref = (ParameterizedQualifiedTypeReference) parent; >- TypeVariableBinding[] typeVariables = ((ReferenceBinding)ref.resolvedType).typeVariables(); >- TypeReference[][] arguments = ref.typeArguments; >- if(typeVariables != null) { >- int iLength = arguments == null ? 0 : arguments.length; >- done: for (int i = 0; i < iLength; i++) { >- int jLength = arguments[i] == null ? 0 : arguments[i].length; >- for (int j = 0; j < jLength; j++) { >- if(arguments[i][j] == node && typeVariables.length > j) { >- TypeBinding bound = typeVariables[j].firstBound; >- addExpectedType(bound == null ? scope.getJavaLangObject() : bound, scope); >- break done; >+ >+ checkCancel(); >+ >+ this.foundTypesCount = 0; >+ this.nameEnvironment.findTypes( >+ qualifiedName, >+ false, >+ this.options.camelCaseMatch, >+ searchFor, >+ this); >+ acceptTypes(scope); >+ } >+ if(!this.requestor.isIgnored(CompletionProposal.PACKAGE_REF)) { >+ this.nameEnvironment.findPackages(qualifiedName, this); >+ } >+ } >+ >+ private void findTypesFromStaticImports(char[] token, Scope scope, boolean proposeAllMemberTypes, ObjectVector typesFound) { >+ ImportBinding[] importBindings = scope.compilationUnitScope().imports; >+ for (int i = 0; i < importBindings.length; i++) { >+ ImportBinding importBinding = importBindings[i]; >+ if(importBinding.isValidBinding() && importBinding.isStatic()) { >+ Binding binding = importBinding.resolvedImport; >+ if(binding != null && binding.isValidBinding()) { >+ if(importBinding.onDemand) { >+ if((binding.kind() & Binding.TYPE) != 0) { >+ this.findMemberTypes( >+ token, >+ (ReferenceBinding) binding, >+ scope, >+ scope.enclosingSourceType(), >+ true, >+ false, >+ true, >+ true, >+ proposeAllMemberTypes, >+ null, >+ typesFound, >+ null, >+ null, >+ null, >+ false); > } >- } >- } >- } >- } else if(parent instanceof MemberValuePair) { >- MemberValuePair memberValuePair = (MemberValuePair) parent; >- if(memberValuePair.binding != null) { >- addExpectedType(memberValuePair.binding.returnType, scope); >- } >- } else if (parent instanceof NormalAnnotation) { >- NormalAnnotation annotation = (NormalAnnotation) parent; >- MemberValuePair[] memberValuePairs = annotation.memberValuePairs(); >- if(memberValuePairs == null || memberValuePairs.length == 0) { >- if(annotation.resolvedType instanceof ReferenceBinding) { >- MethodBinding[] methodBindings = >- ((ReferenceBinding)annotation.resolvedType).availableMethods(); >- if (methodBindings != null && >- methodBindings.length > 0 && >- CharOperation.equals(methodBindings[0].selector, VALUE)) { >- boolean canBeSingleMemberAnnotation = true; >- done : for (int i = 1; i < methodBindings.length; i++) { >- if((methodBindings[i].modifiers & ClassFileConstants.AccAnnotationDefault) == 0) { >- canBeSingleMemberAnnotation = false; >+ } else { >+ if ((binding.kind() & Binding.TYPE) != 0) { >+ ReferenceBinding typeBinding = (ReferenceBinding) binding; >+ int typeLength = token.length; >+ >+ if (!typeBinding.isStatic()) continue; >+ >+ if (typeLength > typeBinding.sourceName.length) continue; >+ >+ if (!CharOperation.prefixEquals(token, typeBinding.sourceName, false) >+ && !(this.options.camelCaseMatch && CharOperation.camelCaseMatch(token, typeBinding.sourceName))) continue; >+ >+ if (typesFound.contains(typeBinding)) continue; >+ >+ typesFound.add(typeBinding); >+ >+ if(this.assistNodeIsClass) { >+ if(!typeBinding.isClass()) continue; >+ } else if(this.assistNodeIsInterface) { >+ if(!typeBinding.isInterface() && !typeBinding.isAnnotationType()) continue; >+ } else if (this.assistNodeIsAnnotation) { >+ if(!typeBinding.isAnnotationType()) continue; >+ } >+ >+ int relevance = computeBaseRelevance(); >+ relevance += computeRelevanceForResolution(); >+ relevance += computeRelevanceForInterestingProposal(); >+ relevance += computeRelevanceForCaseMatching(token, typeBinding.sourceName); >+ relevance += computeRelevanceForExpectingType(typeBinding); >+ relevance += computeRelevanceForQualification(false); >+ relevance += computeRelevanceForRestrictions(IAccessRule.K_ACCESSIBLE); >+ >+ if (typeBinding.isClass()) { >+ relevance += computeRelevanceForClass(); >+ relevance += computeRelevanceForException(typeBinding.sourceName); >+ } else if(typeBinding.isEnum()) { >+ relevance += computeRelevanceForEnum(); >+ } else if(typeBinding.isInterface()) { >+ relevance += computeRelevanceForInterface(); >+ } >+ >+ this.noProposal = false; >+ if(!this.requestor.isIgnored(CompletionProposal.TYPE_REF)) { >+ InternalCompletionProposal proposal = createProposal(CompletionProposal.TYPE_REF, this.actualCompletionPosition); >+ proposal.setDeclarationSignature(typeBinding.qualifiedPackageName()); >+ proposal.setSignature(getSignature(typeBinding)); >+ proposal.setPackageName(typeBinding.qualifiedPackageName()); >+ proposal.setTypeName(typeBinding.qualifiedSourceName()); >+ proposal.setCompletion(typeBinding.sourceName()); >+ proposal.setFlags(typeBinding.modifiers); >+ proposal.setReplaceRange(this.startPosition - this.offset, this.endPosition - this.offset); >+ proposal.setTokenRange(this.tokenStart - this.offset, this.tokenEnd - this.offset); >+ proposal.setRelevance(relevance); >+ this.requestor.accept(proposal); >+ if(DEBUG) { >+ this.printDebug(proposal); >+ } >+ } >+ } >+ } >+ } >+ } >+ } >+ } >+ >+ private void findUnresolvedReference(int completedNameStart, int completedNameEnd, BlockScope scope, char[][] discouragedNames) { >+ char[][] foundNames = findUnresolvedReferenceBefore(completedNameStart - 1, completedNameEnd, scope, discouragedNames); >+ if (foundNames != null && foundNames.length > 1) { >+ int discouragedNamesLength = discouragedNames.length; >+ int foundNamesLength = foundNames.length; >+ int newLength = discouragedNamesLength + foundNamesLength; >+ System.arraycopy(discouragedNames, 0, discouragedNames = new char[newLength][], 0, discouragedNamesLength); >+ System.arraycopy(foundNames, 0, discouragedNames, discouragedNamesLength, foundNamesLength); >+ } >+ findUnresolvedReferenceAfter(completedNameEnd + 1, scope, discouragedNames); >+ } >+ >+ private char[][] findUnresolvedReferenceAfter(int from, BlockScope scope, final char[][] discouragedNames) { >+ final ArrayList proposedNames = new ArrayList(); >+ >+ UnresolvedReferenceNameFinder.UnresolvedReferenceNameRequestor nameRequestor = >+ new UnresolvedReferenceNameFinder.UnresolvedReferenceNameRequestor() { >+ public void acceptName(char[] name) { >+ CompletionEngine.this.acceptUnresolvedName(name); >+ proposedNames.add(name); >+ } >+ }; >+ >+ ReferenceContext referenceContext = scope.referenceContext(); >+ if (referenceContext instanceof AbstractMethodDeclaration) { >+ AbstractMethodDeclaration md = (AbstractMethodDeclaration)referenceContext; >+ >+ UnresolvedReferenceNameFinder nameFinder = new UnresolvedReferenceNameFinder(this); >+ nameFinder.findAfter( >+ this.completionToken, >+ md.scope, >+ md.scope.classScope(), >+ from, >+ md.bodyEnd, >+ discouragedNames, >+ nameRequestor); >+ } else if (referenceContext instanceof TypeDeclaration) { >+ TypeDeclaration typeDeclaration = (TypeDeclaration) referenceContext; >+ FieldDeclaration[] fields = typeDeclaration.fields; >+ if (fields != null) { >+ done : for (int i = 0; i < fields.length; i++) { >+ if (fields[i] instanceof Initializer) { >+ Initializer initializer = (Initializer) fields[i]; >+ if (initializer.block.sourceStart <= from && >+ from < initializer.bodyEnd) { >+ UnresolvedReferenceNameFinder nameFinder = new UnresolvedReferenceNameFinder(this); >+ nameFinder.findAfter( >+ this.completionToken, >+ typeDeclaration.scope, >+ typeDeclaration.scope, >+ from, >+ initializer.bodyEnd, >+ discouragedNames, >+ nameRequestor); >+ break done; >+ } >+ } >+ } >+ } >+ } >+ >+ int proposedNamesCount = proposedNames.size(); >+ if (proposedNamesCount > 0) { >+ return (char[][])proposedNames.toArray(new char[proposedNamesCount][]); >+ } >+ >+ return null; >+ } >+ >+ private char[][] findUnresolvedReferenceBefore(int recordTo, int parseTo, BlockScope scope, final char[][] discouragedNames) { >+ final ArrayList proposedNames = new ArrayList(); >+ >+ UnresolvedReferenceNameFinder.UnresolvedReferenceNameRequestor nameRequestor = >+ new UnresolvedReferenceNameFinder.UnresolvedReferenceNameRequestor() { >+ public void acceptName(char[] name) { >+ CompletionEngine.this.acceptUnresolvedName(name); >+ proposedNames.add(name); >+ } >+ }; >+ >+ BlockScope upperScope = scope; >+ while (upperScope.enclosingMethodScope() != null) { >+ upperScope = upperScope.enclosingMethodScope(); >+ } >+ >+ ReferenceContext referenceContext = upperScope.referenceContext(); >+ if (referenceContext instanceof AbstractMethodDeclaration) { >+ AbstractMethodDeclaration md = (AbstractMethodDeclaration)referenceContext; >+ >+ UnresolvedReferenceNameFinder nameFinder = new UnresolvedReferenceNameFinder(this); >+ nameFinder.findBefore( >+ this.completionToken, >+ md.scope, >+ md.scope.classScope(), >+ md.bodyStart, >+ recordTo, >+ parseTo, >+ discouragedNames, >+ nameRequestor); >+ } else if (referenceContext instanceof TypeDeclaration) { >+ TypeDeclaration typeDeclaration = (TypeDeclaration) referenceContext; >+ >+ >+ done : { >+ FieldDeclaration[] fields = typeDeclaration.fields; >+ if (fields != null) { >+ for (int i = 0; i < fields.length; i++) { >+ if (fields[i] instanceof Initializer) { >+ Initializer initializer = (Initializer) fields[i]; >+ if (initializer.block.sourceStart <= recordTo && >+ recordTo < initializer.bodyEnd) { >+ >+ UnresolvedReferenceNameFinder nameFinder = new UnresolvedReferenceNameFinder(this); >+ nameFinder.findBefore( >+ this.completionToken, >+ typeDeclaration.scope, >+ typeDeclaration.scope, >+ initializer.block.sourceStart, >+ recordTo, >+ parseTo, >+ discouragedNames, >+ nameRequestor); > break done; > } > } >- if (canBeSingleMemberAnnotation) { >- this.assistNodeCanBeSingleMemberAnnotation = canBeSingleMemberAnnotation; >- addExpectedType(methodBindings[0].returnType, scope); >+ } >+ } >+ } >+ } >+ >+ int proposedNamesCount = proposedNames.size(); >+ if (proposedNamesCount > 0) { >+ return (char[][])proposedNames.toArray(new char[proposedNamesCount][]); >+ } >+ >+ return null; >+ } >+ >+ private char[][] findVariableFromUnresolvedReference(LocalDeclaration variable, BlockScope scope, final char[][] discouragedNames) { >+ final TypeReference type = variable.type; >+ if(type != null && >+ type.resolvedType != null && >+ type.resolvedType.problemId() == ProblemReasons.NoError){ >+ >+ final ArrayList proposedNames = new ArrayList(); >+ >+ UnresolvedReferenceNameFinder.UnresolvedReferenceNameRequestor nameRequestor = >+ new UnresolvedReferenceNameFinder.UnresolvedReferenceNameRequestor() { >+ public void acceptName(char[] name) { >+ int relevance = computeBaseRelevance(); >+ relevance += computeRelevanceForInterestingProposal(); >+ relevance += computeRelevanceForCaseMatching(CompletionEngine.this.completionToken, name); >+ relevance += R_NAME_FIRST_PREFIX; >+ relevance += R_NAME_FIRST_SUFFIX; >+ relevance += R_NAME_LESS_NEW_CHARACTERS; >+ relevance += computeRelevanceForRestrictions(IAccessRule.K_ACCESSIBLE); // no access restriction for variable name >+ >+ // accept result >+ CompletionEngine.this.noProposal = false; >+ if(!CompletionEngine.this.requestor.isIgnored(CompletionProposal.VARIABLE_DECLARATION)) { >+ InternalCompletionProposal proposal = CompletionEngine.this.createProposal(CompletionProposal.VARIABLE_DECLARATION, CompletionEngine.this.actualCompletionPosition); >+ proposal.setSignature(getSignature(type.resolvedType)); >+ proposal.setPackageName(type.resolvedType.qualifiedPackageName()); >+ proposal.setTypeName(type.resolvedType.qualifiedSourceName()); >+ proposal.setName(name); >+ proposal.setCompletion(name); >+ //proposal.setFlags(Flags.AccDefault); >+ proposal.setReplaceRange(CompletionEngine.this.startPosition - CompletionEngine.this.offset, CompletionEngine.this.endPosition - CompletionEngine.this.offset); >+ proposal.setTokenRange(CompletionEngine.this.tokenStart - CompletionEngine.this.offset, CompletionEngine.this.tokenEnd - CompletionEngine.this.offset); >+ proposal.setRelevance(relevance); >+ CompletionEngine.this.requestor.accept(proposal); >+ if(DEBUG) { >+ CompletionEngine.this.printDebug(proposal); >+ } >+ } >+ proposedNames.add(name); >+ } >+ }; >+ >+ ReferenceContext referenceContext = scope.referenceContext(); >+ if (referenceContext instanceof AbstractMethodDeclaration) { >+ AbstractMethodDeclaration md = (AbstractMethodDeclaration)referenceContext; >+ >+ UnresolvedReferenceNameFinder nameFinder = new UnresolvedReferenceNameFinder(this); >+ nameFinder.find( >+ this.completionToken, >+ md, >+ variable.declarationSourceEnd + 1, >+ discouragedNames, >+ nameRequestor); >+ } else if (referenceContext instanceof TypeDeclaration) { >+ TypeDeclaration typeDeclaration = (TypeDeclaration) referenceContext; >+ FieldDeclaration[] fields = typeDeclaration.fields; >+ if (fields != null) { >+ done : for (int i = 0; i < fields.length; i++) { >+ if (fields[i] instanceof Initializer) { >+ Initializer initializer = (Initializer) fields[i]; >+ if (initializer.bodyStart <= variable.sourceStart && >+ variable.sourceStart < initializer.bodyEnd) { >+ UnresolvedReferenceNameFinder nameFinder = new UnresolvedReferenceNameFinder(this); >+ nameFinder.find( >+ this.completionToken, >+ initializer, >+ typeDeclaration.scope, >+ variable.declarationSourceEnd + 1, >+ discouragedNames, >+ nameRequestor); >+ break done; >+ } >+ } >+ } >+ } >+ } >+ >+ int proposedNamesCount = proposedNames.size(); >+ if (proposedNamesCount > 0) { >+ return (char[][])proposedNames.toArray(new char[proposedNamesCount][]); >+ } >+ } >+ >+ return null; >+ } >+ >+ private void findVariableName( >+ char[] token, >+ char[] qualifiedPackageName, >+ char[] qualifiedSourceName, >+ char[] sourceName, >+ final TypeBinding typeBinding, >+ char[][] discouragedNames, >+ final char[][] forbiddenNames, >+ boolean forCollection, >+ int dim, >+ int kind, >+ int modifiers){ >+ >+ if(sourceName == null || sourceName.length == 0) >+ return; >+ >+ // compute variable name for non base type >+ final char[] displayName; >+ if (!forCollection) { >+ if (dim > 0){ >+ int l = qualifiedSourceName.length; >+ displayName = new char[l+(2*dim)]; >+ System.arraycopy(qualifiedSourceName, 0, displayName, 0, l); >+ for(int i = 0; i < dim; i++){ >+ displayName[l+(i*2)] = '['; >+ displayName[l+(i*2)+1] = ']'; >+ } >+ } else { >+ displayName = qualifiedSourceName; >+ } >+ } else { >+ displayName = typeBinding.qualifiedSourceName(); >+ } >+ >+ final char[] t = token; >+ final char[] q = qualifiedPackageName; >+ INamingRequestor namingRequestor = new INamingRequestor() { >+ void accept(char[] name, int prefixAndSuffixRelevance, int reusedCharacters){ >+ int l = forbiddenNames == null ? 0 : forbiddenNames.length; >+ for (int i = 0; i < l; i++) { >+ if (CharOperation.equals(forbiddenNames[i], name, false)) return; >+ } >+ >+ if (CharOperation.prefixEquals(t, name, false)) { >+ int relevance = computeBaseRelevance(); >+ relevance += computeRelevanceForInterestingProposal(); >+ relevance += computeRelevanceForCaseMatching(t, name); >+ relevance += prefixAndSuffixRelevance; >+ if(reusedCharacters > 0) relevance += R_NAME_LESS_NEW_CHARACTERS; >+ relevance += computeRelevanceForRestrictions(IAccessRule.K_ACCESSIBLE); // no access restriction for variable name >+ >+ // accept result >+ CompletionEngine.this.noProposal = false; >+ if(!CompletionEngine.this.requestor.isIgnored(CompletionProposal.VARIABLE_DECLARATION)) { >+ InternalCompletionProposal proposal = CompletionEngine.this.createProposal(CompletionProposal.VARIABLE_DECLARATION, CompletionEngine.this.actualCompletionPosition); >+ proposal.setSignature(getSignature(typeBinding)); >+ proposal.setPackageName(q); >+ proposal.setTypeName(displayName); >+ proposal.setName(name); >+ proposal.setCompletion(name); >+ //proposal.setFlags(Flags.AccDefault); >+ proposal.setReplaceRange(CompletionEngine.this.startPosition - CompletionEngine.this.offset, CompletionEngine.this.endPosition - CompletionEngine.this.offset); >+ proposal.setTokenRange(CompletionEngine.this.tokenStart - CompletionEngine.this.offset, CompletionEngine.this.tokenEnd - CompletionEngine.this.offset); >+ proposal.setRelevance(relevance); >+ CompletionEngine.this.requestor.accept(proposal); >+ if(DEBUG) { >+ CompletionEngine.this.printDebug(proposal); >+ } >+ } >+ } >+ } >+ >+ public void acceptNameWithoutPrefixAndSuffix(char[] name,int reusedCharacters) { >+ accept(name, 0, reusedCharacters); >+ } >+ >+ public void acceptNameWithPrefix(char[] name, boolean isFirstPrefix, int reusedCharacters) { >+ accept(name, isFirstPrefix ? R_NAME_FIRST_PREFIX : R_NAME_PREFIX, reusedCharacters); >+ } >+ >+ public void acceptNameWithPrefixAndSuffix(char[] name, boolean isFirstPrefix, boolean isFirstSuffix, int reusedCharacters) { >+ accept( >+ name, >+ (isFirstPrefix ? R_NAME_FIRST_PREFIX : R_NAME_PREFIX) + (isFirstSuffix ? R_NAME_FIRST_SUFFIX : R_NAME_SUFFIX), >+ reusedCharacters); >+ } >+ public void acceptNameWithSuffix(char[] name, boolean isFirstSuffix, int reusedCharacters) { >+ accept(name, isFirstSuffix ? R_NAME_FIRST_SUFFIX : R_NAME_SUFFIX, reusedCharacters); >+ } >+ }; >+ >+ switch (kind) { >+ case FIELD : >+ InternalNamingConventions.suggestFieldNames( >+ this.javaProject, >+ qualifiedPackageName, >+ qualifiedSourceName, >+ dim, >+ modifiers, >+ token, >+ discouragedNames, >+ namingRequestor); >+ break; >+ case LOCAL : >+ InternalNamingConventions.suggestLocalVariableNames( >+ this.javaProject, >+ qualifiedPackageName, >+ qualifiedSourceName, >+ dim, >+ token, >+ discouragedNames, >+ namingRequestor); >+ break; >+ case ARGUMENT : >+ InternalNamingConventions.suggestArgumentNames( >+ this.javaProject, >+ qualifiedPackageName, >+ qualifiedSourceName, >+ dim, >+ token, >+ discouragedNames, >+ namingRequestor); >+ break; >+ } >+ } >+ >+ // Helper method for private void findVariableNames(char[] name, TypeReference type ) >+ private void findVariableName( >+ char[] token, >+ char[] qualifiedPackageName, >+ char[] qualifiedSourceName, >+ char[] sourceName, >+ final TypeBinding typeBinding, >+ char[][] discouragedNames, >+ final char[][] forbiddenNames, >+ int dim, >+ int kind, >+ int modifiers){ >+ findVariableName( >+ token, >+ qualifiedPackageName, >+ qualifiedSourceName, >+ sourceName, >+ typeBinding, >+ discouragedNames, >+ forbiddenNames, >+ false, >+ dim, >+ kind, >+ modifiers); >+ } >+ private void findVariableNameForCollection( >+ char[] token, >+ char[] qualifiedPackageName, >+ char[] qualifiedSourceName, >+ char[] sourceName, >+ final TypeBinding typeBinding, >+ char[][] discouragedNames, >+ final char[][] forbiddenNames, >+ int kind, >+ int modifiers){ >+ >+ findVariableName( >+ token, >+ qualifiedPackageName, >+ qualifiedSourceName, >+ sourceName, >+ typeBinding, >+ discouragedNames, >+ forbiddenNames, >+ false, >+ 1, >+ kind, >+ modifiers); >+ } >+ private void findVariableNames(char[] name, TypeReference type , char[][] discouragedNames, char[][] forbiddenNames, int kind, int modifiers){ >+ if(type != null && >+ type.resolvedType != null) { >+ TypeBinding tb = type.resolvedType; >+ >+ if (tb.problemId() == ProblemReasons.NoError && >+ tb != Scope.getBaseType(VOID)) { >+ findVariableName( >+ name, >+ tb.leafComponentType().qualifiedPackageName(), >+ tb.leafComponentType().qualifiedSourceName(), >+ tb.leafComponentType().sourceName(), >+ tb, >+ discouragedNames, >+ forbiddenNames, >+ type.dimensions(), >+ kind, >+ modifiers); >+ >+ if (tb.isParameterizedType() && >+ tb.findSuperTypeOriginatingFrom(TypeIds.T_JavaUtilCollection, false) != null) { >+ ParameterizedTypeBinding ptb = ((ParameterizedTypeBinding) tb); >+ TypeBinding[] arguments = ptb.arguments; >+ if (arguments != null && arguments.length == 1) { >+ TypeBinding argument = arguments[0]; >+ findVariableNameForCollection( >+ name, >+ argument.leafComponentType().qualifiedPackageName(), >+ argument.leafComponentType().qualifiedSourceName(), >+ argument.leafComponentType().sourceName(), >+ tb, >+ discouragedNames, >+ forbiddenNames, >+ kind, >+ modifiers); >+ } >+ } >+ } >+ } >+ >+ } >+ private void findVariablesAndMethods( >+ char[] token, >+ Scope scope, >+ InvocationSite invocationSite, >+ Scope invocationScope, >+ boolean insideTypeAnnotation, >+ boolean insideAnnotationAttribute) { >+ >+ if (token == null) >+ return; >+ >+ // Should local variables hide fields from the receiver type or any of its enclosing types? >+ // we know its an implicit field/method access... see BlockScope getBinding/getImplicitMethod >+ >+ boolean staticsOnly = false; >+ // need to know if we're in a static context (or inside a constructor) >+ int tokenLength = token.length; >+ >+ ObjectVector localsFound = new ObjectVector(); >+ ObjectVector fieldsFound = new ObjectVector(); >+ ObjectVector methodsFound = new ObjectVector(); >+ >+ Scope currentScope = scope; >+ >+ if (!this.requestor.isIgnored(CompletionProposal.LOCAL_VARIABLE_REF)) { >+ done1 : while (true) { // done when a COMPILATION_UNIT_SCOPE is found >+ >+ switch (currentScope.kind) { >+ >+ case Scope.METHOD_SCOPE : >+ // handle the error case inside an explicit constructor call (see MethodScope>>findField) >+ MethodScope methodScope = (MethodScope) currentScope; >+ staticsOnly |= methodScope.isStatic | methodScope.isConstructorCall; >+ >+ //$FALL-THROUGH$ >+ case Scope.BLOCK_SCOPE : >+ BlockScope blockScope = (BlockScope) currentScope; >+ >+ next : for (int i = 0, length = blockScope.locals.length; i < length; i++) { >+ LocalVariableBinding local = blockScope.locals[i]; >+ >+ if (local == null) >+ break next; >+ >+ if (tokenLength > local.name.length) >+ continue next; >+ >+ if (!CharOperation.prefixEquals(token, local.name, false /* ignore case */) >+ && !(this.options.camelCaseMatch && CharOperation.camelCaseMatch(token, local.name))) >+ continue next; >+ >+ if (local.isSecret()) >+ continue next; >+ >+ for (int f = 0; f < localsFound.size; f++) { >+ LocalVariableBinding otherLocal = >+ (LocalVariableBinding) localsFound.elementAt(f); >+ if (CharOperation.equals(otherLocal.name, local.name, true)) >+ continue next; >+ } >+ localsFound.add(local); >+ >+ int relevance = computeBaseRelevance(); >+ relevance += computeRelevanceForResolution(); >+ relevance += computeRelevanceForInterestingProposal(local); >+ relevance += computeRelevanceForCaseMatching(token, local.name); >+ relevance += computeRelevanceForExpectingType(local.type); >+ relevance += computeRelevanceForEnumConstant(local.type); >+ relevance += computeRelevanceForQualification(false); >+ relevance += computeRelevanceForRestrictions(IAccessRule.K_ACCESSIBLE); // no access restriction for local variable >+ this.noProposal = false; >+ if(!this.requestor.isIgnored(CompletionProposal.LOCAL_VARIABLE_REF)) { >+ InternalCompletionProposal proposal = createProposal(CompletionProposal.LOCAL_VARIABLE_REF, this.actualCompletionPosition); >+ proposal.setSignature( >+ local.type == null >+ ? createTypeSignature( >+ CharOperation.NO_CHAR, >+ local.declaration.type.toString().toCharArray()) >+ : getSignature(local.type)); >+ if(local.type == null) { >+ //proposal.setPackageName(null); >+ proposal.setTypeName(local.declaration.type.toString().toCharArray()); >+ } else { >+ proposal.setPackageName(local.type.qualifiedPackageName()); >+ proposal.setTypeName(local.type.qualifiedSourceName()); >+ } >+ proposal.setName(local.name); >+ proposal.setCompletion(local.name); >+ proposal.setFlags(local.modifiers); >+ proposal.setReplaceRange(this.startPosition - this.offset, this.endPosition - this.offset); >+ proposal.setTokenRange(this.tokenStart - this.offset, this.tokenEnd - this.offset); >+ proposal.setRelevance(relevance); >+ this.requestor.accept(proposal); >+ if(DEBUG) { >+ this.printDebug(proposal); >+ } >+ } > } >- } >- } >- } >- } else if (parent instanceof TryStatement) { >- boolean isException = false; >- if (node instanceof CompletionOnSingleTypeReference) { >- isException = ((CompletionOnSingleTypeReference)node).isException(); >- } else if (node instanceof CompletionOnQualifiedTypeReference) { >- isException = ((CompletionOnQualifiedTypeReference)node).isException(); >- } else if (node instanceof CompletionOnParameterizedQualifiedTypeReference) { >- isException = ((CompletionOnParameterizedQualifiedTypeReference)node).isException(); >- } >- if (isException) { >- ThrownExceptionFinder thrownExceptionFinder = new ThrownExceptionFinder(); >- ReferenceBinding[] bindings = thrownExceptionFinder.find((TryStatement) parent, (BlockScope)scope); >- if (bindings != null && bindings.length > 0) { >- for (int i = 0; i < bindings.length; i++) { >- addExpectedType(bindings[i], scope); >- } >- this.expectedTypesFilter = SUPERTYPE; >- } >- } >- } else if (parent instanceof SwitchStatement) { >- SwitchStatement switchStatement = (SwitchStatement) parent; >- if (switchStatement.expression != null && >- switchStatement.expression.resolvedType != null) { >- addExpectedType(switchStatement.expression.resolvedType, scope); >- } >+ break; > >- // Expected types for javadoc >- } else if (parent instanceof Javadoc) { >- if (scope.kind == Scope.METHOD_SCOPE) { >- MethodScope methodScope = (MethodScope) scope; >- AbstractMethodDeclaration methodDecl = methodScope.referenceMethod(); >- if (methodDecl != null && methodDecl.binding != null) { >- ReferenceBinding[] exceptions = methodDecl.binding.thrownExceptions; >- if (exceptions != null) { >- for (int i = 0; i < exceptions.length; i++) { >- addExpectedType(exceptions[i], scope); >- } >- } >+ case Scope.COMPILATION_UNIT_SCOPE : >+ break done1; > } >+ currentScope = currentScope.parent; > } > } >+ >+ checkCancel(); > >- if(this.expectedTypesPtr + 1 != this.expectedTypes.length) { >- System.arraycopy(this.expectedTypes, 0, this.expectedTypes = new TypeBinding[this.expectedTypesPtr + 1], 0, this.expectedTypesPtr + 1); >- } >- } >- >- private void computeExpectedTypesForAllocationExpression( >- ReferenceBinding binding, >- Expression[] arguments, >- Scope scope, >- InvocationSite invocationSite) { >- >- MethodBinding[] methods = binding.availableMethods(); >- nextMethod : for (int i = 0; i < methods.length; i++) { >- MethodBinding method = methods[i]; >- >- if (!method.isConstructor()) continue nextMethod; >- >- if (method.isSynthetic()) continue nextMethod; >+ boolean proposeField = !this.requestor.isIgnored(CompletionProposal.FIELD_REF); >+ boolean proposeMethod = !this.requestor.isIgnored(CompletionProposal.METHOD_REF); > >- if (this.options.checkVisibility && !method.canBeSeenBy(invocationSite, scope)) continue nextMethod; >+ staticsOnly = false; >+ currentScope = scope; > >- TypeBinding[] parameters = method.parameters; >- if(parameters.length < arguments.length) >- continue nextMethod; >+ if(proposeField || proposeMethod) { >+ done2 : while (true) { // done when a COMPILATION_UNIT_SCOPE is found > >- int length = arguments.length - 1; >+ switch (currentScope.kind) { >+ case Scope.METHOD_SCOPE : >+ // handle the error case inside an explicit constructor call (see MethodScope>>findField) >+ MethodScope methodScope = (MethodScope) currentScope; >+ staticsOnly |= methodScope.isStatic | methodScope.isConstructorCall; >+ break; >+ case Scope.CLASS_SCOPE : >+ ClassScope classScope = (ClassScope) currentScope; >+ SourceTypeBinding enclosingType = classScope.referenceContext.binding; >+ /* if (tokenLength == 0) { // only search inside the type itself if no prefix was provided >+ findFields(token, enclosingType.fields(), classScope, fieldsFound, staticsOnly); >+ findMethods(token, enclosingType.methods(), classScope, methodsFound, staticsOnly, false); >+ break done; >+ } else { */ >+ if(!insideTypeAnnotation) { >+ if(proposeField) { >+ findFields( >+ token, >+ enclosingType, >+ classScope, >+ fieldsFound, >+ localsFound, >+ staticsOnly, >+ invocationSite, >+ invocationScope, >+ true, >+ true, >+ null, >+ null, >+ null, >+ false, >+ null, >+ -1, >+ -1); >+ } >+ if(proposeMethod && !insideAnnotationAttribute) { >+ findMethods( >+ token, >+ null, >+ null, >+ enclosingType, >+ classScope, >+ methodsFound, >+ staticsOnly, >+ false, >+ invocationSite, >+ invocationScope, >+ true, >+ false, >+ true, >+ null, >+ null, >+ null, >+ false, >+ null, >+ -1, >+ -1); >+ } >+ } >+ staticsOnly |= enclosingType.isStatic(); >+ insideTypeAnnotation = false; >+ // } >+ break; > >- for (int j = 0; j < length; j++) { >- Expression argument = arguments[j]; >- TypeBinding argType = argument.resolvedType; >- if(argType != null && !argType.isCompatibleWith(parameters[j])) >- continue nextMethod; >+ case Scope.COMPILATION_UNIT_SCOPE : >+ break done2; >+ } >+ currentScope = currentScope.parent; > } >+ >+ checkCancel(); >+ >+ findFieldsAndMethodsFromStaticImports( >+ token, >+ scope, >+ invocationSite, >+ invocationScope, >+ false, >+ insideAnnotationAttribute, >+ localsFound, >+ fieldsFound, >+ methodsFound, >+ proposeField, >+ proposeMethod); > >- TypeBinding expectedType = method.parameters[arguments.length - 1]; >- if(expectedType != null) { >- addExpectedType(expectedType, scope); >+ if (this.assistNodeInJavadoc == 0) { >+ >+ checkCancel(); >+ >+ // search in favorites import >+ findFieldsAndMethodsFromFavorites( >+ token, >+ scope, >+ invocationSite, >+ invocationScope, >+ localsFound, >+ fieldsFound, >+ methodsFound); > } >+ >+ checkCancel(); >+ >+ findEnumConstantsFromExpectedTypes( >+ token, >+ invocationScope, >+ fieldsFound); > } > } > >- private void computeExpectedTypesForMessageSendForInterface( >- ReferenceBinding binding, >- char[] selector, >- Expression[] arguments, >- ReferenceBinding receiverType, >- Scope scope, >- InvocationSite invocationSite, >- boolean isStatic) { >+ private char[] getCompletedTypeSignature(ReferenceBinding referenceBinding) { >+ char[] result = null; >+ StringBuffer sig = new StringBuffer(10); >+ if (!referenceBinding.isMemberType()) { >+ char[] typeSig = referenceBinding.genericTypeSignature(); >+ sig.append(typeSig, 0, typeSig.length); >+ } else if (!this.insideQualifiedReference) { >+ if (referenceBinding.isStatic()) { >+ char[] typeSig = referenceBinding.signature(); >+ sig.append(typeSig, 0, typeSig.length-1); // copy all but trailing semicolon > >- ReferenceBinding[] itsInterfaces = binding.superInterfaces(); >- if (itsInterfaces != Binding.NO_SUPERINTERFACES) { >- ReferenceBinding[] interfacesToVisit = itsInterfaces; >- int nextPosition = interfacesToVisit.length; >+ TypeVariableBinding[] typeVariables = referenceBinding.typeVariables(); >+ if (typeVariables != Binding.NO_TYPE_VARIABLES) { >+ sig.append(Signature.C_GENERIC_START); >+ for (int i = 0, length = typeVariables.length; i < length; i++) { >+ sig.append(typeVariables[i].genericTypeSignature()); >+ } >+ sig.append(Signature.C_GENERIC_END); >+ } >+ sig.append(Signature.C_SEMICOLON); >+ } else { >+ char[] typeSig = referenceBinding.genericTypeSignature(); >+ sig.append(typeSig, 0, typeSig.length); >+ } >+ } else { >+ ReferenceBinding enclosingType = referenceBinding.enclosingType(); >+ if (enclosingType.isParameterizedType()) { >+ char[] typeSig = referenceBinding.genericTypeSignature(); >+ sig.append(typeSig, 0, typeSig.length-1); > >- for (int i = 0; i < nextPosition; i++) { >- ReferenceBinding currentType = interfacesToVisit[i]; >- computeExpectedTypesForMessageSend( >- currentType, >- selector, >- arguments, >- receiverType, >- scope, >- invocationSite, >- isStatic); >+ TypeVariableBinding[] typeVariables = referenceBinding.typeVariables(); >+ if (typeVariables != Binding.NO_TYPE_VARIABLES) { >+ sig.append(Signature.C_GENERIC_START); >+ for (int i = 0, length = typeVariables.length; i < length; i++) { >+ sig.append(typeVariables[i].genericTypeSignature()); >+ } >+ sig.append(Signature.C_GENERIC_END); >+ } >+ } else { >+ char[] typeSig = referenceBinding.signature(); >+ sig.append(typeSig, 0, typeSig.length-1); // copy all but trailing semicolon > >- if ((itsInterfaces = currentType.superInterfaces()) != Binding.NO_SUPERINTERFACES) { >- int itsLength = itsInterfaces.length; >- if (nextPosition + itsLength >= interfacesToVisit.length) >- System.arraycopy(interfacesToVisit, 0, interfacesToVisit = new ReferenceBinding[nextPosition + itsLength + 5], 0, nextPosition); >- nextInterface : for (int a = 0; a < itsLength; a++) { >- ReferenceBinding next = itsInterfaces[a]; >- for (int b = 0; b < nextPosition; b++) >- if (next == interfacesToVisit[b]) continue nextInterface; >- interfacesToVisit[nextPosition++] = next; >+ if (referenceBinding.isStatic()) { >+ TypeVariableBinding[] typeVariables = referenceBinding.typeVariables(); >+ if (typeVariables != Binding.NO_TYPE_VARIABLES) { >+ sig.append(Signature.C_GENERIC_START); >+ for (int i = 0, length = typeVariables.length; i < length; i++) { >+ sig.append(typeVariables[i].genericTypeSignature()); >+ } >+ sig.append(Signature.C_GENERIC_END); > } > } > } >+ sig.append(Signature.C_SEMICOLON); > } >+ int sigLength = sig.length(); >+ result = new char[sigLength]; >+ sig.getChars(0, sigLength, result, 0); >+ result = CharOperation.replaceOnCopy(result, '/', Signature.C_DOT); >+ return result; > } > >- private void computeExpectedTypesForMessageSend( >- ReferenceBinding binding, >- char[] selector, >- Expression[] arguments, >- ReferenceBinding receiverType, >- Scope scope, >- InvocationSite invocationSite, >- boolean isStatic) { >+ private ImportBinding[] getFavoriteReferenceBindings(Scope scope) { >+ if (this.favoriteReferenceBindings != null) return this.favoriteReferenceBindings; > >- MethodBinding[] methods = binding.availableMethods(); >- nextMethod : for (int i = 0; i < methods.length; i++) { >- MethodBinding method = methods[i]; >+ String[] favoriteReferences = this.requestor.getFavoriteReferences(); > >- if (method.isSynthetic()) continue nextMethod; >+ if (favoriteReferences == null || favoriteReferences.length == 0) return null; > >- if (method.isDefaultAbstract()) continue nextMethod; >+ ImportBinding[] resolvedImports = new ImportBinding[favoriteReferences.length]; > >- if (method.isConstructor()) continue nextMethod; >+ int count = 0; >+ next : for (int i = 0; i < favoriteReferences.length; i++) { >+ String favoriteReference = favoriteReferences[i]; > >- if (isStatic && !method.isStatic()) continue nextMethod; >+ int length; >+ if (favoriteReference == null || (length = favoriteReference.length()) == 0) continue next; > >- if (this.options.checkVisibility && !method.canBeSeenBy(receiverType, invocationSite, scope)) continue nextMethod; >+ boolean onDemand = favoriteReference.charAt(length - 1) == '*'; > >- if(!CharOperation.equals(method.selector, selector)) continue nextMethod; >+ char[][] compoundName = CharOperation.splitOn('.', favoriteReference.toCharArray()); >+ if (onDemand) { >+ compoundName = CharOperation.subarray(compoundName, 0, compoundName.length - 1); >+ } > >- TypeBinding[] parameters = method.parameters; >- if(parameters.length < arguments.length) >- continue nextMethod; >+ // remove duplicate and conflicting >+ for (int j = 0; j < count; j++) { >+ ImportReference f = resolvedImports[j].reference; > >- int length = arguments.length - 1; >+ if (CharOperation.equals(f.tokens, compoundName)) continue next; > >- for (int j = 0; j < length; j++) { >- Expression argument = arguments[j]; >- TypeBinding argType = argument.resolvedType; >- if(argType != null && !argType.isCompatibleWith(parameters[j])) >- continue nextMethod; >+ if (!onDemand && ((f.bits & ASTNode.OnDemand) == 0)) { >+ if (CharOperation.equals(f.tokens[f.tokens.length - 1], compoundName[compoundName.length - 1])) >+ continue next; >+ } > } > >- TypeBinding expectedType = method.parameters[arguments.length - 1]; >- if(expectedType != null) { >- addExpectedType(expectedType, scope); >+ boolean isStatic = true; >+ >+ ImportReference importReference = >+ new ImportReference( >+ compoundName, >+ new long[compoundName.length], >+ onDemand, >+ isStatic ? ClassFileConstants.AccStatic : ClassFileConstants.AccDefault); >+ >+ Binding importBinding = this.unitScope.findImport(compoundName, isStatic, onDemand); >+ >+ if (!importBinding.isValidBinding()) { >+ continue next; > } >- } >- } >- private void addExpectedType(TypeBinding type, Scope scope){ >- if (type == null || !type.isValidBinding() || type == TypeBinding.NULL) return; > >- // do not add twice the same type >- for (int i = 0; i <= this.expectedTypesPtr; i++) { >- if (this.expectedTypes[i] == type) return; >+ if (importBinding instanceof PackageBinding) { >+ continue next; >+ } >+ >+ resolvedImports[count++] = >+ new ImportBinding(compoundName, onDemand, importBinding, importReference); > } > >- int length = this.expectedTypes.length; >- if (++this.expectedTypesPtr >= length) >- System.arraycopy(this.expectedTypes, 0, this.expectedTypes = new TypeBinding[length * 2], 0, length); >- this.expectedTypes[this.expectedTypesPtr] = type; >+ if (resolvedImports.length > count) >+ System.arraycopy(resolvedImports, 0, resolvedImports = new ImportBinding[count], 0, count); > >- if(type == scope.getJavaLangObject()) { >- this.hasJavaLangObjectAsExpectedType = true; >- } >+ return this.favoriteReferenceBindings = resolvedImports; > } >- private void addForbiddenBindings(Binding binding){ >- if (binding == null) return; > >- int length = this.forbbidenBindings.length; >- if (++this.forbbidenBindingsPtr >= length) >- System.arraycopy(this.forbbidenBindings, 0, this.forbbidenBindings = new Binding[length * 2], 0, length); >- this.forbbidenBindings[this.forbbidenBindingsPtr] = binding; >- } >- private void addUninterestingBindings(Binding binding){ >- if (binding == null) return; >+ public AssistParser getParser() { > >- int length = this.uninterestingBindings.length; >- if (++this.uninterestingBindingsPtr >= length) >- System.arraycopy(this.uninterestingBindings, 0, this.uninterestingBindings = new Binding[length * 2], 0, length); >- this.uninterestingBindings[this.uninterestingBindingsPtr] = binding; >+ return this.parser; > } >- >- private Scope computeForbiddenBindings(ASTNode astNode, ASTNode astNodeParent, Scope scope) { >- this.forbbidenBindingsFilter = NONE; >- if(scope instanceof ClassScope) { >- TypeDeclaration typeDeclaration = ((ClassScope)scope).referenceContext; >- if(typeDeclaration.superclass == astNode) { >- addForbiddenBindings(typeDeclaration.binding); >- return scope.parent; >- } >- TypeReference[] superInterfaces = typeDeclaration.superInterfaces; >- int length = superInterfaces == null ? 0 : superInterfaces.length; >- for (int i = 0; i < length; i++) { >- if(superInterfaces[i] == astNode) { >- addForbiddenBindings(typeDeclaration.binding); >- return scope.parent; >- } >+ protected boolean hasPossibleAnnotationTarget(TypeBinding typeBinding, Scope scope) { >+ if (this.targetedElement == TagBits.AnnotationForPackage) { >+ long target = typeBinding.getAnnotationTagBits() & TagBits.AnnotationTargetMASK; >+ if(target != 0 && (target & TagBits.AnnotationForPackage) == 0) { >+ return false; > } >- } else { >- if (astNodeParent != null && astNodeParent instanceof TryStatement) { >- boolean isException = false; >- if (astNode instanceof CompletionOnSingleTypeReference) { >- isException = ((CompletionOnSingleTypeReference)astNode).isException(); >- } else if (astNode instanceof CompletionOnQualifiedTypeReference) { >- isException = ((CompletionOnQualifiedTypeReference)astNode).isException(); >- } else if (astNode instanceof CompletionOnParameterizedQualifiedTypeReference) { >- isException = ((CompletionOnParameterizedQualifiedTypeReference)astNode).isException(); >- } >- if (isException) { >- Argument[] catchArguments = ((TryStatement) astNodeParent).catchArguments; >- int length = catchArguments == null ? 0 : catchArguments.length; >- for (int i = 0; i < length; i++) { >- TypeBinding caughtException = catchArguments[i].type.resolvedType; >- if (caughtException != null) { >- addForbiddenBindings(caughtException); >- this.knownTypes.put(CharOperation.concat(caughtException.qualifiedPackageName(), caughtException.qualifiedSourceName(), '.'), this); >- } >+ } else if ((this.targetedElement & TagBits.AnnotationForType) != 0) { >+ if (scope.parent != null && >+ scope.parent.parent != null && >+ scope.parent.referenceContext() instanceof CompletionOnAnnotationOfType && >+ scope.parent.parent instanceof CompilationUnitScope) { >+ long target = typeBinding.getAnnotationTagBits() & TagBits.AnnotationTargetMASK; >+ if ((this.targetedElement & TagBits.AnnotationForAnnotationType) != 0) { >+ if(target != 0 && (target &(TagBits.AnnotationForType | TagBits.AnnotationForAnnotationType)) == 0) { >+ return false; >+ } >+ } else { >+ if(target != 0 && (target &(TagBits.AnnotationForType)) == 0) { >+ return false; > } >- this.forbbidenBindingsFilter = SUBTYPE; > } > } > } >-// else if(scope instanceof MethodScope) { >-// MethodScope methodScope = (MethodScope) scope; >-// if(methodScope.insideTypeAnnotation) { >-// return methodScope.parent.parent; >-// } >-// } >- return scope; >- } >- private char[] computePrefix(SourceTypeBinding declarationType, SourceTypeBinding invocationType, boolean isStatic){ >- >- StringBuffer completion = new StringBuffer(10); >- >- if (isStatic) { >- completion.append(declarationType.sourceName()); >- >- } else if (declarationType == invocationType) { >- completion.append(THIS); >- >- } else { >- >- if (!declarationType.isNestedType()) { >- >- completion.append(declarationType.sourceName()); >- completion.append('.'); >- completion.append(THIS); >- >- } else if (!declarationType.isAnonymousType()) { >- >- completion.append(declarationType.sourceName()); >- completion.append('.'); >- completion.append(THIS); >- >- } >- } >- >- return completion.toString().toCharArray(); >+ return true; > } >- >- private void proposeNewMethod(char[] token, ReferenceBinding reference) { >- if(!this.requestor.isIgnored(CompletionProposal.POTENTIAL_METHOD_DECLARATION)) { >- int relevance = computeBaseRelevance(); >- relevance += computeRelevanceForResolution(); >- relevance += computeRelevanceForInterestingProposal(); >- relevance += computeRelevanceForRestrictions(IAccessRule.K_ACCESSIBLE); // no access restriction for new method >- >- InternalCompletionProposal proposal = createProposal(CompletionProposal.POTENTIAL_METHOD_DECLARATION, this.actualCompletionPosition); >- proposal.setDeclarationSignature(getSignature(reference)); >- proposal.setSignature( >- createMethodSignature( >- CharOperation.NO_CHAR_CHAR, >- CharOperation.NO_CHAR_CHAR, >- CharOperation.NO_CHAR, >- VOID)); >- proposal.setDeclarationPackageName(reference.qualifiedPackageName()); >- proposal.setDeclarationTypeName(reference.qualifiedSourceName()); >- >- //proposal.setPackageName(null); >- proposal.setTypeName(VOID); >- proposal.setName(token); >- //proposal.setParameterPackageNames(null); >- //proposal.setParameterTypeNames(null); >- //proposal.setPackageName(null); >- proposal.setCompletion(token); >- proposal.setFlags(Flags.AccPublic); >- proposal.setReplaceRange(this.startPosition - this.offset, this.endPosition - this.offset); >- proposal.setTokenRange(this.tokenStart - this.offset, this.tokenEnd - this.offset); >- proposal.setRelevance(relevance); >- this.requestor.accept(proposal); >- if(DEBUG) { >- this.printDebug(proposal); >- } >- } >+ /** >+ * Returns completion string inserted inside a specified inline tag. >+ * @param completionName >+ * @return char[] Completion text inclunding specified inline tag >+ */ >+ private char[] inlineTagCompletion(char[] completionName, char[] inlineTag) { >+ int tagLength= inlineTag.length; >+ int completionLength = completionName.length; >+ int inlineLength = 2+tagLength+1+completionLength+1; >+ char[] inlineCompletion = new char[inlineLength]; >+ inlineCompletion[0] = '{'; >+ inlineCompletion[1] = '@'; >+ System.arraycopy(inlineTag, 0, inlineCompletion, 2, tagLength); >+ inlineCompletion[tagLength+2] = ' '; >+ System.arraycopy(completionName, 0, inlineCompletion, tagLength+3, completionLength); >+ // do not add space at end of inline tag (see bug https://bugs.eclipse.org/bugs/show_bug.cgi?id=121026) >+ //inlineCompletion[inlineLength-2] = ' '; >+ inlineCompletion[inlineLength-1] = '}'; >+ return inlineCompletion; > } > private boolean isForbidden(Binding binding) { > for (int i = 0; i <= this.forbbidenBindingsPtr; i++) { >@@ -10033,6 +10292,19 @@ > } > return false; > } >+ >+ private boolean isIgnored(int kind) { >+ return this.requestor.isIgnored(kind); >+ } >+ private boolean isIgnored(int kind, boolean missingTypes) { >+ return this.requestor.isIgnored(kind) || >+ (missingTypes && !this.requestor.isAllowingRequiredProposals(kind, CompletionProposal.TYPE_REF)); >+ } >+ >+ private boolean isIgnored(int kind, int requiredProposalKind) { >+ return this.requestor.isIgnored(kind) || >+ !this.requestor.isAllowingRequiredProposals(kind, requiredProposalKind); >+ } > private boolean isValidParent(ASTNode parent, ASTNode node, Scope scope){ > > if(parent instanceof ParameterizedSingleTypeReference) { >@@ -10112,260 +10384,41 @@ > } > return true; > } >- public static char[] createNonGenericTypeSignature(char[] qualifiedPackageName, char[] qualifiedTypeName) { >- return Signature.createCharArrayTypeSignature( >- CharOperation.concat( >- qualifiedPackageName, >- CharOperation.replaceOnCopy(qualifiedTypeName, '.', '$'), '.'), true); >- } >- public static char[] createTypeSignature(char[] qualifiedPackageName, char[] qualifiedTypeName) { >- char[] name = new char[qualifiedTypeName.length]; >- System.arraycopy(qualifiedTypeName, 0, name, 0, qualifiedTypeName.length); >- >- int depth = 0; >- int length = name.length; >- for (int i = length -1; i >= 0; i--) { >- switch (name[i]) { >- case '.': >- if (depth == 0 && name[i - 1] != '>') { >- name[i] = '$'; >- } >- break; >- case '<': >- depth--; >- break; >- case '>': >- depth++; >- break; >- } >- } >- return Signature.createCharArrayTypeSignature( >- CharOperation.concat( >- qualifiedPackageName, >- name, '.'), true); >- } >- >- public static char[] createMethodSignature(char[][] parameterPackageNames, char[][] parameterTypeNames, char[] returnPackagename, char[] returnTypeName) { >- char[] returnTypeSignature = >- returnTypeName == null || returnTypeName.length == 0 >- ? Signature.createCharArrayTypeSignature(VOID, true) >- : Signature.createCharArrayTypeSignature( >- CharOperation.concat( >- returnPackagename, >- CharOperation.replaceOnCopy(returnTypeName, '.', '$'), '.'), true); >- >- return createMethodSignature( >- parameterPackageNames, >- parameterTypeNames, >- returnTypeSignature); >- } >- >- public static char[] createMethodSignature(char[][] parameterPackageNames, char[][] parameterTypeNames, char[] returnTypeSignature) { >- char[][] parameterTypeSignature = new char[parameterTypeNames.length][]; >- for (int i = 0; i < parameterTypeSignature.length; i++) { >- parameterTypeSignature[i] = >- Signature.createCharArrayTypeSignature( >- CharOperation.concat( >- parameterPackageNames[i], >- CharOperation.replaceOnCopy(parameterTypeNames[i], '.', '$'), '.'), true); >- } >- >- return Signature.createMethodSignature( >- parameterTypeSignature, >- returnTypeSignature); >- } >- >- protected InternalCompletionProposal createProposal(int kind, int completionOffset) { >- InternalCompletionProposal proposal = (InternalCompletionProposal) CompletionProposal.create(kind, completionOffset - this.offset); >- proposal.nameLookup = this.nameEnvironment.nameLookup; >- proposal.completionEngine = this; >- return proposal; >- } >- >- /* >- * Create a completion proposal for a type. >- */ >- private void createTypeProposal(char[] packageName, char[] typeName, int modifiers, int accessibility, char[] completionName, int relevance) { >- >- // Create standard type proposal >- if(!this.requestor.isIgnored(CompletionProposal.TYPE_REF) && (this.assistNodeInJavadoc & CompletionOnJavadoc.ONLY_INLINE_TAG) == 0) { >- InternalCompletionProposal proposal = (InternalCompletionProposal) CompletionProposal.create(CompletionProposal.TYPE_REF, this.actualCompletionPosition - this.offset); >- proposal.nameLookup = this.nameEnvironment.nameLookup; >- proposal.completionEngine = this; >- proposal.setDeclarationSignature(packageName); >- proposal.setSignature(createNonGenericTypeSignature(packageName, typeName)); >- proposal.setPackageName(packageName); >- proposal.setTypeName(typeName); >- proposal.setCompletion(completionName); >- proposal.setFlags(modifiers); >- proposal.setReplaceRange(this.startPosition - this.offset, this.endPosition - this.offset); >- proposal.setTokenRange(this.tokenStart - this.offset, this.tokenEnd - this.offset); >- proposal.setRelevance(relevance); >- proposal.setAccessibility(accessibility); >- this.requestor.accept(proposal); >- if(DEBUG) { >- this.printDebug(proposal); >- } >- } >- >- // Create javadoc text proposal if necessary >- if ((this.assistNodeInJavadoc & CompletionOnJavadoc.TEXT) != 0 && !this.requestor.isIgnored(CompletionProposal.JAVADOC_TYPE_REF)) { >- char[] javadocCompletion= inlineTagCompletion(completionName, JavadocTagConstants.TAG_LINK); >- InternalCompletionProposal proposal = (InternalCompletionProposal) CompletionProposal.create(CompletionProposal.JAVADOC_TYPE_REF, this.actualCompletionPosition - this.offset); >- proposal.nameLookup = this.nameEnvironment.nameLookup; >- proposal.completionEngine = this; >- proposal.setDeclarationSignature(packageName); >- proposal.setSignature(createNonGenericTypeSignature(packageName, typeName)); >- proposal.setPackageName(packageName); >- proposal.setTypeName(typeName); >- proposal.setCompletion(javadocCompletion); >- proposal.setFlags(modifiers); >- int start = (this.assistNodeInJavadoc & CompletionOnJavadoc.REPLACE_TAG) != 0 ? this.javadocTagPosition : this.startPosition; >- proposal.setReplaceRange(start - this.offset, this.endPosition - this.offset); >- proposal.setTokenRange(this.tokenStart - this.offset, this.tokenEnd - this.offset); >- proposal.setRelevance(relevance+R_INLINE_TAG); >- proposal.setAccessibility(accessibility); >- this.requestor.accept(proposal); >- if(DEBUG) { >- this.printDebug(proposal); >- } >- } >- } >- >- /* >- * Create a completion proposal for a member type. >- */ >- private void createTypeProposal( >- ReferenceBinding refBinding, >- char[] typeName, >- int accessibility, >- char[] completionName, >- int relevance, >- Binding[] missingElements, >- int[] missingElementsStarts, >- int[] missingElementsEnds, >- boolean missingElementsHaveProblems) { >- >- // Create standard type proposal >- if(!this.isIgnored(CompletionProposal.TYPE_REF, missingElements != null) && (this.assistNodeInJavadoc & CompletionOnJavadoc.ONLY_INLINE_TAG) == 0) { >- InternalCompletionProposal proposal = (InternalCompletionProposal) CompletionProposal.create(CompletionProposal.TYPE_REF, this.actualCompletionPosition - this.offset); >- proposal.nameLookup = this.nameEnvironment.nameLookup; >- proposal.completionEngine = this; >- proposal.setDeclarationSignature(refBinding.qualifiedPackageName()); >- proposal.setSignature(getCompletedTypeSignature(refBinding)); >- proposal.setPackageName(refBinding.qualifiedPackageName()); >- proposal.setTypeName(typeName); >- if (missingElements != null) { >- CompletionProposal[] subProposals = new CompletionProposal[missingElements.length]; >- for (int i = 0; i < missingElements.length; i++) { >- subProposals[i] = >- createRequiredTypeProposal( >- missingElements[i], >- missingElementsStarts[i], >- missingElementsEnds[i], >- relevance); >- } >- proposal.setRequiredProposals(subProposals); >- } >- proposal.setCompletion(completionName); >- proposal.setFlags(refBinding.modifiers); >- proposal.setReplaceRange(this.startPosition - this.offset, this.endPosition - this.offset); >- proposal.setTokenRange(this.tokenStart - this.offset, this.tokenEnd - this.offset); >- proposal.setRelevance(relevance); >- this.requestor.accept(proposal); >- if(DEBUG) { >- this.printDebug(proposal); >- } >+ private Initializer parseSnippeInitializer(char[] snippet, int position, char[][] localVariableTypeNames, char[][] localVariableNames, int[] localVariableModifiers, boolean isStatic){ >+ StringBuffer prefix = new StringBuffer(); >+ prefix.append("public class FakeType {\n "); //$NON-NLS-1$ >+ if(isStatic) { >+ prefix.append("static "); //$NON-NLS-1$ > } >- >- // Create javadoc text proposal if necessary >- if ((this.assistNodeInJavadoc & CompletionOnJavadoc.TEXT) != 0 && !this.requestor.isIgnored(CompletionProposal.JAVADOC_TYPE_REF)) { >- char[] javadocCompletion= inlineTagCompletion(completionName, JavadocTagConstants.TAG_LINK); >- InternalCompletionProposal proposal = (InternalCompletionProposal) CompletionProposal.create(CompletionProposal.JAVADOC_TYPE_REF, this.actualCompletionPosition - this.offset); >- proposal.nameLookup = this.nameEnvironment.nameLookup; >- proposal.completionEngine = this; >- proposal.setDeclarationSignature(refBinding.qualifiedPackageName()); >- proposal.setSignature(getCompletedTypeSignature(refBinding)); >- proposal.setPackageName(refBinding.qualifiedPackageName()); >- proposal.setTypeName(typeName); >- proposal.setCompletion(javadocCompletion); >- proposal.setFlags(refBinding.modifiers); >- int start = (this.assistNodeInJavadoc & CompletionOnJavadoc.REPLACE_TAG) != 0 ? this.javadocTagPosition : this.startPosition; >- proposal.setReplaceRange(start - this.offset, this.endPosition - this.offset); >- proposal.setTokenRange(this.tokenStart - this.offset, this.tokenEnd - this.offset); >- proposal.setRelevance(relevance+R_INLINE_TAG); >- this.requestor.accept(proposal); >- if(DEBUG) { >- this.printDebug(proposal); >- } >+ prefix.append("{\n"); //$NON-NLS-1$ >+ for (int i = 0; i < localVariableTypeNames.length; i++) { >+ ASTNode.printModifiers(localVariableModifiers[i], prefix); >+ prefix.append(' '); >+ prefix.append(localVariableTypeNames[i]); >+ prefix.append(' '); >+ prefix.append(localVariableNames[i]); >+ prefix.append(';'); > } >- } >- >- /* >- * Create a completion proposal for a member type. >- */ >- private void createTypeParameterProposal(TypeParameter typeParameter, int relevance) { >- char[] completionName = typeParameter.name; > >- // Create standard type proposal >- if(!this.requestor.isIgnored(CompletionProposal.TYPE_REF)) { >- InternalCompletionProposal proposal = (InternalCompletionProposal) CompletionProposal.create(CompletionProposal.TYPE_REF, this.actualCompletionPosition - this.offset); >- proposal.nameLookup = this.nameEnvironment.nameLookup; >- proposal.completionEngine = this; >- proposal.setSignature(getSignature(typeParameter.binding)); >- proposal.setTypeName(completionName); >- proposal.setCompletion(completionName); >- proposal.setFlags(typeParameter.modifiers); >- proposal.setReplaceRange(this.startPosition - this.offset, this.endPosition - this.offset); >- proposal.setTokenRange(this.tokenStart - this.offset, this.tokenEnd - this.offset); >- proposal.setRelevance(relevance); >- this.requestor.accept(proposal); >- if(DEBUG) { >- this.printDebug(proposal); >- } >- } >+ char[] fakeSource = CharOperation.concat(prefix.toString().toCharArray(), snippet, "}}".toCharArray());//$NON-NLS-1$ >+ this.offset = prefix.length(); > >- // Create javadoc text proposal if necessary >- if ((this.assistNodeInJavadoc & CompletionOnJavadoc.TEXT) != 0 && !this.requestor.isIgnored(CompletionProposal.JAVADOC_TYPE_REF)) { >- char[] javadocCompletion= inlineTagCompletion(completionName, JavadocTagConstants.TAG_LINK); >- InternalCompletionProposal proposal = (InternalCompletionProposal) CompletionProposal.create(CompletionProposal.JAVADOC_TYPE_REF, this.actualCompletionPosition - this.offset); >- proposal.nameLookup = this.nameEnvironment.nameLookup; >- proposal.completionEngine = this; >- proposal.setSignature(getSignature(typeParameter.binding)); >- proposal.setTypeName(javadocCompletion); >- proposal.setCompletion(javadocCompletion); >- proposal.setFlags(typeParameter.modifiers); >- proposal.setReplaceRange(this.startPosition - this.offset, this.endPosition - this.offset); >- proposal.setTokenRange(this.tokenStart - this.offset, this.tokenEnd - this.offset); >- proposal.setRelevance(relevance+R_INLINE_TAG); >- this.requestor.accept(proposal); >- if(DEBUG) { >- this.printDebug(proposal); >- } >- } >- } >+ String encoding = this.compilerOptions.defaultEncoding; >+ BasicCompilationUnit fakeUnit = new BasicCompilationUnit( >+ fakeSource, >+ null, >+ "FakeType.java", //$NON-NLS-1$ >+ encoding); > >- /** >- * Returns completion string inserted inside a specified inline tag. >- * @param completionName >- * @return char[] Completion text inclunding specified inline tag >- */ >- private char[] inlineTagCompletion(char[] completionName, char[] inlineTag) { >- int tagLength= inlineTag.length; >- int completionLength = completionName.length; >- int inlineLength = 2+tagLength+1+completionLength+1; >- char[] inlineCompletion = new char[inlineLength]; >- inlineCompletion[0] = '{'; >- inlineCompletion[1] = '@'; >- System.arraycopy(inlineTag, 0, inlineCompletion, 2, tagLength); >- inlineCompletion[tagLength+2] = ' '; >- System.arraycopy(completionName, 0, inlineCompletion, tagLength+3, completionLength); >- // do not add space at end of inline tag (see bug https://bugs.eclipse.org/bugs/show_bug.cgi?id=121026) >- //inlineCompletion[inlineLength-2] = ' '; >- inlineCompletion[inlineLength-1] = '}'; >- return inlineCompletion; >- } >+ this.actualCompletionPosition = prefix.length() + position - 1; >+ >+ CompilationResult fakeResult = new CompilationResult(fakeUnit, 1, 1, this.compilerOptions.maxProblemsPerUnit); >+ CompilationUnitDeclaration fakeAST = this.parser.dietParse(fakeUnit, fakeResult, this.actualCompletionPosition); > >+ parseBlockStatements(fakeAST, this.actualCompletionPosition); >+ >+ return (Initializer)fakeAST.types[0].fields[0]; >+ } > protected void printDebug(CategorizedProblem error) { > if(CompletionEngine.DEBUG) { > System.out.print("COMPLETION - completionFailure("); //$NON-NLS-1$ >@@ -10373,18 +10426,12 @@ > System.out.println(")"); //$NON-NLS-1$ > } > } >- >- private void printDebugTab(int tab, StringBuffer buffer) { >- for (int i = 0; i < tab; i++) { >- buffer.append('\t'); >- } >- } >- > protected void printDebug(CompletionProposal proposal){ > StringBuffer buffer = new StringBuffer(); > printDebug(proposal, 0, buffer); > System.out.println(buffer.toString()); > } >+ > private void printDebug(CompletionProposal proposal, int tab, StringBuffer buffer){ > printDebugTab(tab, buffer); > buffer.append("COMPLETION - "); //$NON-NLS-1$ >@@ -10509,42 +10556,169 @@ > buffer.append("}\n");//$NON-NLS-1$ > } > >- private char[][] substituteMethodTypeParameterNames(TypeVariableBinding[] typeVariables, char[][] excludedNames) { >- char[][] substituedParameterNames = new char[typeVariables.length][]; >+ private void printDebugTab(int tab, StringBuffer buffer) { >+ for (int i = 0; i < tab; i++) { >+ buffer.append('\t'); >+ } >+ } > >- for (int i = 0; i < substituedParameterNames.length; i++) { >- substituedParameterNames[i] = typeVariables[i].sourceName; >+ private void proposeNewMethod(char[] token, ReferenceBinding reference) { >+ if(!this.requestor.isIgnored(CompletionProposal.POTENTIAL_METHOD_DECLARATION)) { >+ int relevance = computeBaseRelevance(); >+ relevance += computeRelevanceForResolution(); >+ relevance += computeRelevanceForInterestingProposal(); >+ relevance += computeRelevanceForRestrictions(IAccessRule.K_ACCESSIBLE); // no access restriction for new method >+ >+ InternalCompletionProposal proposal = createProposal(CompletionProposal.POTENTIAL_METHOD_DECLARATION, this.actualCompletionPosition); >+ proposal.setDeclarationSignature(getSignature(reference)); >+ proposal.setSignature( >+ createMethodSignature( >+ CharOperation.NO_CHAR_CHAR, >+ CharOperation.NO_CHAR_CHAR, >+ CharOperation.NO_CHAR, >+ VOID)); >+ proposal.setDeclarationPackageName(reference.qualifiedPackageName()); >+ proposal.setDeclarationTypeName(reference.qualifiedSourceName()); >+ >+ //proposal.setPackageName(null); >+ proposal.setTypeName(VOID); >+ proposal.setName(token); >+ //proposal.setParameterPackageNames(null); >+ //proposal.setParameterTypeNames(null); >+ //proposal.setPackageName(null); >+ proposal.setCompletion(token); >+ proposal.setFlags(Flags.AccPublic); >+ proposal.setReplaceRange(this.startPosition - this.offset, this.endPosition - this.offset); >+ proposal.setTokenRange(this.tokenStart - this.offset, this.tokenEnd - this.offset); >+ proposal.setRelevance(relevance); >+ this.requestor.accept(proposal); >+ if(DEBUG) { >+ this.printDebug(proposal); >+ } > } >+ } > >- boolean foundConflicts = false; >+ private void proposeType( >+ char[] packageName, >+ char[] simpleTypeName, >+ int modifiers, >+ int accessibility, >+ char[] typeName, >+ char[] fullyQualifiedName, >+ boolean isQualified, >+ Scope scope) { >+ char[] completionName = fullyQualifiedName; >+ if(isQualified) { >+ if (packageName == null || packageName.length == 0) >+ if (this.unitScope != null && this.unitScope.fPackage.compoundName != CharOperation.NO_CHAR_CHAR) >+ return; // ignore types from the default package from outside it >+ } else { >+ completionName = simpleTypeName; >+ } > >- nextTypeParameter : for (int i = 0; i < typeVariables.length; i++) { >- TypeVariableBinding typeVariableBinding = typeVariables[i]; >- char[] methodParameterName = typeVariableBinding.sourceName; >+ TypeBinding guessedType = null; >+ if ((modifiers & ClassFileConstants.AccAnnotation) != 0 && >+ this.assistNodeIsAnnotation && >+ (this.targetedElement & TagBits.AnnotationTargetMASK) != 0) { >+ char[][] cn = CharOperation.splitOn('.', fullyQualifiedName); > >- for (int j = 0; j < excludedNames.length; j++) { >- char[] typeParameterName = excludedNames[j]; >- if(CharOperation.equals(typeParameterName, methodParameterName, false)) { >- char[] substitution; >- if(methodParameterName.length == 1) { >- if(ScannerHelper.isUpperCase(methodParameterName[0])) { >- substitution = substituteMethodTypeParameterName(methodParameterName[0], 'A', 'Z', excludedNames, substituedParameterNames); >- } else { >- substitution = substituteMethodTypeParameterName(methodParameterName[0], 'a', 'z', excludedNames, substituedParameterNames); >- } >- } else { >- substitution = substituteMethodTypeParameterName(methodParameterName, excludedNames, substituedParameterNames); >- } >- substituedParameterNames[i] = substitution; >+ TypeReference ref; >+ if (cn.length == 1) { >+ ref = new SingleTypeReference(simpleTypeName, 0); >+ } else { >+ ref = new QualifiedTypeReference(cn,new long[cn.length]); >+ } > >- foundConflicts = true; >- continue nextTypeParameter; >- } >+ switch (scope.kind) { >+ case Scope.METHOD_SCOPE : >+ case Scope.BLOCK_SCOPE : >+ guessedType = ref.resolveType((BlockScope)scope); >+ break; >+ case Scope.CLASS_SCOPE : >+ guessedType = ref.resolveType((ClassScope)scope); >+ break; > } >+ >+ if (guessedType == null || !guessedType.isValidBinding()) return; >+ >+ if (!hasPossibleAnnotationTarget(guessedType, scope)) return; > } > >- if(foundConflicts) return substituedParameterNames; >- return null; >+ int relevance = computeBaseRelevance(); >+ relevance += computeRelevanceForResolution(); >+ relevance += computeRelevanceForInterestingProposal(); >+ relevance += computeRelevanceForRestrictions(accessibility); >+ relevance += computeRelevanceForCaseMatching(this.completionToken, simpleTypeName); >+ relevance += computeRelevanceForExpectingType(packageName, simpleTypeName); >+ relevance += computeRelevanceForQualification(isQualified); >+ >+ int kind = modifiers & (ClassFileConstants.AccInterface | ClassFileConstants.AccEnum | ClassFileConstants.AccAnnotation); >+ switch (kind) { >+ case ClassFileConstants.AccAnnotation: >+ case ClassFileConstants.AccAnnotation | ClassFileConstants.AccInterface: >+ relevance += computeRelevanceForAnnotation(); >+ if (guessedType != null) relevance += computeRelevanceForAnnotationTarget(guessedType); >+ relevance += computeRelevanceForInterface(); >+ break; >+ case ClassFileConstants.AccEnum: >+ relevance += computeRelevanceForEnum(); >+ break; >+ case ClassFileConstants.AccInterface: >+ relevance += computeRelevanceForInterface(); >+ break; >+ default: >+ relevance += computeRelevanceForClass(); >+ relevance += computeRelevanceForException(simpleTypeName); >+ break; >+ } >+ >+ this.noProposal = false; >+ if(!this.requestor.isIgnored(CompletionProposal.TYPE_REF)) { >+ createTypeProposal(packageName, typeName, modifiers, accessibility, completionName, relevance); >+ } >+ } >+ >+ protected void reset() { >+ >+ super.reset(false); >+ this.knownPkgs = new HashtableOfObject(10); >+ this.knownTypes = new HashtableOfObject(10); >+ } >+ >+ private void setSourceAndTokenRange(int start, int end) { >+ this.setSourceAndTokenRange(start, end, true); >+ } >+ >+ private void setSourceAndTokenRange(int start, int end, boolean emptyTokenAdjstment) { >+ this.setSourceRange(start, end, emptyTokenAdjstment); >+ this.setTokenRange(start, end, emptyTokenAdjstment); >+ } >+ >+ private void setSourceRange(int start, int end) { >+ this.setSourceRange(start, end, true); >+ } >+ >+ private void setSourceRange(int start, int end, boolean emptyTokenAdjstment) { >+ this.startPosition = start; >+ if(emptyTokenAdjstment) { >+ int endOfEmptyToken = ((CompletionScanner)this.parser.scanner).endOfEmptyToken; >+ this.endPosition = endOfEmptyToken > end ? endOfEmptyToken + 1 : end + 1; >+ } else { >+ this.endPosition = end + 1; >+ } >+ } >+ >+ private void setTokenRange(int start, int end) { >+ this.setTokenRange(start, end, true); >+ } >+ private void setTokenRange(int start, int end, boolean emptyTokenAdjstment) { >+ this.tokenStart = start; >+ if(emptyTokenAdjstment) { >+ int endOfEmptyToken = ((CompletionScanner)this.parser.scanner).endOfEmptyToken; >+ this.tokenEnd = endOfEmptyToken > end ? endOfEmptyToken + 1 : end + 1; >+ } else { >+ this.tokenEnd = end + 1; >+ } > } > > private char[] substituteMethodTypeParameterName(char firstName, char startChar, char endChar, char[][] excludedNames, char[][] otherParameterNames) { >@@ -10596,4 +10770,42 @@ > } > return name; > } >+ >+ private char[][] substituteMethodTypeParameterNames(TypeVariableBinding[] typeVariables, char[][] excludedNames) { >+ char[][] substituedParameterNames = new char[typeVariables.length][]; >+ >+ for (int i = 0; i < substituedParameterNames.length; i++) { >+ substituedParameterNames[i] = typeVariables[i].sourceName; >+ } >+ >+ boolean foundConflicts = false; >+ >+ nextTypeParameter : for (int i = 0; i < typeVariables.length; i++) { >+ TypeVariableBinding typeVariableBinding = typeVariables[i]; >+ char[] methodParameterName = typeVariableBinding.sourceName; >+ >+ for (int j = 0; j < excludedNames.length; j++) { >+ char[] typeParameterName = excludedNames[j]; >+ if(CharOperation.equals(typeParameterName, methodParameterName, false)) { >+ char[] substitution; >+ if(methodParameterName.length == 1) { >+ if(ScannerHelper.isUpperCase(methodParameterName[0])) { >+ substitution = substituteMethodTypeParameterName(methodParameterName[0], 'A', 'Z', excludedNames, substituedParameterNames); >+ } else { >+ substitution = substituteMethodTypeParameterName(methodParameterName[0], 'a', 'z', excludedNames, substituedParameterNames); >+ } >+ } else { >+ substitution = substituteMethodTypeParameterName(methodParameterName, excludedNames, substituedParameterNames); >+ } >+ substituedParameterNames[i] = substitution; >+ >+ foundConflicts = true; >+ continue nextTypeParameter; >+ } >+ } >+ } >+ >+ if(foundConflicts) return substituedParameterNames; >+ return null; >+ } > } >\ No newline at end of file >Index: model/org/eclipse/jdt/internal/core/util/messages.properties >=================================================================== >RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/messages.properties,v >retrieving revision 1.72 >diff -u -r1.72 messages.properties >--- model/org/eclipse/jdt/internal/core/util/messages.properties 27 May 2008 23:40:19 -0000 1.72 >+++ model/org/eclipse/jdt/internal/core/util/messages.properties 10 Oct 2008 07:19:37 -0000 >@@ -368,3 +368,6 @@ > classfileformat_exceptiontableentry = [pc: {0}, pc: {1}] -> {2} when : {3} > classfileformat_linenumbertableentry = [pc: {0}, line: {1}] > classfileformat_localvariabletableentry = [pc: {0}, pc: {1}] local: {2} index: {3} type: {4} >+ >+### Eclipse Java Core completion messages. >+engine_completing = Computing proposals... >Index: model/org/eclipse/jdt/internal/core/util/Messages.java >=================================================================== >RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/Messages.java,v >retrieving revision 1.23 >diff -u -r1.23 Messages.java >--- model/org/eclipse/jdt/internal/core/util/Messages.java 27 Jun 2008 16:03:56 -0000 1.23 >+++ model/org/eclipse/jdt/internal/core/util/Messages.java 10 Oct 2008 07:19:37 -0000 >@@ -218,6 +218,7 @@ > public static String importRewrite_processDescription; > public static String correction_nullRequestor; > public static String correction_nullUnit; >+ public static String engine_completing; > public static String engine_searching; > public static String engine_searching_indexing; > public static String engine_searching_matching; >Index: model/org/eclipse/jdt/internal/core/eval/EvaluationContextWrapper.java >=================================================================== >RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/eval/EvaluationContextWrapper.java,v >retrieving revision 1.60 >diff -u -r1.60 EvaluationContextWrapper.java >--- model/org/eclipse/jdt/internal/core/eval/EvaluationContextWrapper.java 9 Oct 2008 08:45:46 -0000 1.60 >+++ model/org/eclipse/jdt/internal/core/eval/EvaluationContextWrapper.java 10 Oct 2008 07:19:37 -0000 >@@ -15,13 +15,6 @@ > > import org.eclipse.core.runtime.IProgressMonitor; > import org.eclipse.jdt.core.*; >-import org.eclipse.jdt.core.ICompilationUnit; >-import org.eclipse.jdt.core.IImportDeclaration; >-import org.eclipse.jdt.core.IJavaElement; >-import org.eclipse.jdt.core.IJavaModelStatusConstants; >-import org.eclipse.jdt.core.IJavaProject; >-import org.eclipse.jdt.core.IType; >-import org.eclipse.jdt.core.JavaModelException; > import org.eclipse.jdt.core.compiler.IProblem; > import org.eclipse.jdt.core.eval.ICodeSnippetRequestor; > import org.eclipse.jdt.core.eval.IEvaluationContext; >@@ -30,12 +23,6 @@ > import org.eclipse.jdt.internal.compiler.env.INameEnvironment; > import org.eclipse.jdt.internal.compiler.impl.CompilerOptions; > import org.eclipse.jdt.internal.core.*; >-import org.eclipse.jdt.internal.core.BinaryType; >-import org.eclipse.jdt.internal.core.ClassFile; >-import org.eclipse.jdt.internal.core.JavaModelStatus; >-import org.eclipse.jdt.internal.core.JavaProject; >-import org.eclipse.jdt.internal.core.SelectionRequestor; >-import org.eclipse.jdt.internal.core.SourceMapper; > import org.eclipse.jdt.internal.core.builder.NameEnvironment; > import org.eclipse.jdt.internal.core.builder.ProblemFactory; > import org.eclipse.jdt.internal.eval.EvaluationContext; >@@ -100,9 +87,26 @@ > codeComplete(codeSnippet, position, requestor, DefaultWorkingCopyOwner.PRIMARY); > } > /** >+ * @see org.eclipse.jdt.core.eval.IEvaluationContext#codeComplete(String, int, CompletionRequestor, IProgressMonitor) >+ */ >+public void codeComplete(String codeSnippet, int position, CompletionRequestor requestor, IProgressMonitor monitor) throws JavaModelException { >+ codeComplete(codeSnippet, position, requestor, DefaultWorkingCopyOwner.PRIMARY, null); >+} >+/** > * @see org.eclipse.jdt.core.eval.IEvaluationContext#codeComplete(String, int, CompletionRequestor, WorkingCopyOwner) > */ > public void codeComplete(String codeSnippet, int position, CompletionRequestor requestor, WorkingCopyOwner owner) throws JavaModelException { >+ codeComplete(codeSnippet, position, requestor, owner, null); >+} >+/** >+ * @see org.eclipse.jdt.core.eval.IEvaluationContext#codeComplete(String, int, CompletionRequestor, WorkingCopyOwner, IProgressMonitor) >+ */ >+public void codeComplete( >+ String codeSnippet, >+ int position, >+ CompletionRequestor requestor, >+ WorkingCopyOwner owner, >+ IProgressMonitor monitor) throws JavaModelException { > SearchableEnvironment environment = this.project.newSearchableNameEnvironment(owner); > this.context.complete( > codeSnippet.toCharArray(), >@@ -111,7 +115,8 @@ > requestor, > this.project.getOptions(true), > this.project, >- owner >+ owner, >+ monitor > ); > } > /** >Index: model/org/eclipse/jdt/core/ICodeAssist.java >=================================================================== >RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/model/org/eclipse/jdt/core/ICodeAssist.java,v >retrieving revision 1.35 >diff -u -r1.35 ICodeAssist.java >--- model/org/eclipse/jdt/core/ICodeAssist.java 27 Jun 2008 16:04:01 -0000 1.35 >+++ model/org/eclipse/jdt/core/ICodeAssist.java 10 Oct 2008 07:19:36 -0000 >@@ -10,6 +10,8 @@ > *******************************************************************************/ > package org.eclipse.jdt.core; > >+import org.eclipse.core.runtime.IProgressMonitor; >+ > /** > * Common protocol for Java elements that support source code assist and code > * resolve. >@@ -82,6 +84,29 @@ > */ > void codeComplete(int offset, CompletionRequestor requestor) > throws JavaModelException; >+ >+ /** >+ * Performs code completion at the given offset position in this compilation unit, >+ * reporting results to the given completion requestor. The <code>offset</code> >+ * is the 0-based index of the character, after which code assist is desired. >+ * An <code>offset</code> of -1 indicates to code assist at the beginning of this >+ * compilation unit. >+ * <p> >+ * >+ * @param offset the given offset position >+ * @param requestor the given completion requestor >+ * @param monitor the progress monitor used to report progress >+ * @exception JavaModelException if code assist could not be performed. Reasons include:<ul> >+ * <li>This Java element does not exist (ELEMENT_DOES_NOT_EXIST)</li> >+ * <li> The position specified is < -1 or is greater than this compilation unit's >+ * source length (INDEX_OUT_OF_BOUNDS) >+ * </ul> >+ * >+ * @exception IllegalArgumentException if <code>requestor</code> is <code>null</code> >+ * @since 3.5 >+ */ >+ void codeComplete(int offset, CompletionRequestor requestor, IProgressMonitor monitor) >+ throws JavaModelException; > > /** > * Performs code completion at the given offset position in this compilation unit, >@@ -141,6 +166,36 @@ > */ > void codeComplete(int offset, CompletionRequestor requestor, WorkingCopyOwner owner) > throws JavaModelException; >+ >+ /** >+ * Performs code completion at the given offset position in this compilation unit, >+ * reporting results to the given completion requestor. The <code>offset</code> >+ * is the 0-based index of the character, after which code assist is desired. >+ * An <code>offset</code> of -1 indicates to code assist at the beginning of this >+ * compilation unit. >+ * It considers types in the working copies with the given owner first. In other words, >+ * the owner's working copies will take precedence over their original compilation units >+ * in the workspace. >+ * <p> >+ * Note that if a working copy is empty, it will be as if the original compilation >+ * unit had been deleted. >+ * </p> >+ * >+ * @param offset the given offset position >+ * @param requestor the given completion requestor >+ * @param owner the owner of working copies that take precedence over their original compilation units >+ * @param monitor the progress monitor used to report progress >+ * @exception JavaModelException if code assist could not be performed. Reasons include:<ul> >+ * <li>This Java element does not exist (ELEMENT_DOES_NOT_EXIST)</li> >+ * <li> The position specified is < -1 or is greater than this compilation unit's >+ * source length (INDEX_OUT_OF_BOUNDS) >+ * </ul> >+ * >+ * @exception IllegalArgumentException if <code>requestor</code> is <code>null</code> >+ * @since 3.5 >+ */ >+ void codeComplete(int offset, CompletionRequestor requestor, WorkingCopyOwner owner, IProgressMonitor monitor) >+ throws JavaModelException; > > /** > * Returns the Java elements corresponding to the given selected text in this compilation unit. >Index: model/org/eclipse/jdt/core/IType.java >=================================================================== >RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/model/org/eclipse/jdt/core/IType.java,v >retrieving revision 1.63 >diff -u -r1.63 IType.java >--- model/org/eclipse/jdt/core/IType.java 27 Jun 2008 16:04:01 -0000 1.63 >+++ model/org/eclipse/jdt/core/IType.java 10 Oct 2008 07:19:36 -0000 >@@ -154,6 +154,44 @@ > boolean isStatic, > CompletionRequestor requestor) > throws JavaModelException; >+ >+ /** >+ * 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 against 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 within snippet where the user >+ * is performing code assist. >+ * @param localVariableTypeNames 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 >+ * @param monitor the progress monitor used to report progress >+ * @exception JavaModelException if this element does not exist or if an >+ * exception occurs while accessing its corresponding resource. >+ * @since 3.5 >+ */ >+ void codeComplete( >+ char[] snippet, >+ int insertion, >+ int position, >+ char[][] localVariableTypeNames, >+ char[][] localVariableNames, >+ int[] localVariableModifiers, >+ boolean isStatic, >+ CompletionRequestor requestor, >+ IProgressMonitor monitor) >+ throws JavaModelException; > > /** > * Do code completion inside a code snippet in the context of the current type. >@@ -199,6 +237,53 @@ > CompletionRequestor requestor, > WorkingCopyOwner owner) > throws JavaModelException; >+ >+ /** >+ * Do code completion inside a code snippet in the context of the current type. >+ * It considers types in the working copies with the given owner first. In other words, >+ * the owner's working copies will take precedence over their original compilation units >+ * in the workspace. >+ * <p> >+ * Note that if a working copy is empty, it will be as if the original compilation >+ * unit had been deleted. >+ * </p><p> >+ * If the type can access to his source code and the insertion position is valid, >+ * then completion is performed against source. Otherwise the completion is performed >+ * against type structure and given locals variables. >+ * </p> >+ * >+ * @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 localVariableTypeNames 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 >+ * @param owner the owner of working copies that take precedence over their original compilation units >+ * @param monitor the progress monitor used to report progress >+ * @exception JavaModelException if this element does not exist or if an >+ * exception occurs while accessing its corresponding resource. >+ * @since 3.5 >+ */ >+ void codeComplete( >+ char[] snippet, >+ int insertion, >+ int position, >+ char[][] localVariableTypeNames, >+ char[][] localVariableNames, >+ int[] localVariableModifiers, >+ boolean isStatic, >+ CompletionRequestor requestor, >+ WorkingCopyOwner owner, >+ IProgressMonitor monitor) >+ throws JavaModelException; > > > /** >Index: eval/org/eclipse/jdt/internal/eval/EvaluationContext.java >=================================================================== >RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/eval/org/eclipse/jdt/internal/eval/EvaluationContext.java,v >retrieving revision 1.62 >diff -u -r1.62 EvaluationContext.java >--- eval/org/eclipse/jdt/internal/eval/EvaluationContext.java 9 Oct 2008 08:45:46 -0000 1.62 >+++ eval/org/eclipse/jdt/internal/eval/EvaluationContext.java 10 Oct 2008 07:19:36 -0000 >@@ -13,6 +13,7 @@ > import java.util.Locale; > import java.util.Map; > >+import org.eclipse.core.runtime.IProgressMonitor; > import org.eclipse.jdt.core.CompletionRequestor; > import org.eclipse.jdt.core.IJavaProject; > import org.eclipse.jdt.core.WorkingCopyOwner; >@@ -104,8 +105,19 @@ > * > * @param owner > * the owner of working copies that take precedence over their original compilation units >- */ >-public void complete(char[] codeSnippet, int completionPosition, SearchableEnvironment environment, CompletionRequestor requestor, Map options, final IJavaProject project, WorkingCopyOwner owner) { >+ * >+ * @param monitor >+ * the progress monitor used to report progress >+ */ >+public void complete( >+ char[] codeSnippet, >+ int completionPosition, >+ SearchableEnvironment environment, >+ CompletionRequestor requestor, >+ Map options, >+ final IJavaProject project, >+ WorkingCopyOwner owner, >+ IProgressMonitor monitor) { > try { > IRequestor variableRequestor = new IRequestor() { > public boolean acceptClassFiles(ClassFile[] classFiles, char[] codeSnippetClassName) { >@@ -148,7 +160,7 @@ > } > }; > >- CompletionEngine engine = new CompletionEngine(environment, mapper.getCompletionRequestor(requestor), options, project, owner); >+ CompletionEngine engine = new CompletionEngine(environment, mapper.getCompletionRequestor(requestor), options, project, owner, monitor); > > if (this.installedVars != null) { > IBinaryType binaryType = getRootCodeSnippetBinary(); >Index: codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnBranchStatementLabel.java >=================================================================== >RCS file: codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnBranchStatementLabel.java >diff -N codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnBranchStatementLabel.java >--- /dev/null 1 Jan 1970 00:00:00 -0000 >+++ codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnBranchStatementLabel.java 1 Jan 1970 00:00:00 -0000 >@@ -0,0 +1,52 @@ >+/******************************************************************************* >+ * Copyright (c) 2005, 2006 IBM Corporation and others. >+ * All rights reserved. This program and the accompanying materials >+ * are made available under the terms of the Eclipse Public License v1.0 >+ * which accompanies this distribution, and is available at >+ * http://www.eclipse.org/legal/epl-v10.html >+ * >+ * Contributors: >+ * IBM Corporation - initial API and implementation >+ *******************************************************************************/ >+package org.eclipse.jdt.internal.codeassist.complete; >+ >+import org.eclipse.jdt.internal.compiler.ast.BranchStatement; >+import org.eclipse.jdt.internal.compiler.flow.FlowContext; >+import org.eclipse.jdt.internal.compiler.flow.FlowInfo; >+import org.eclipse.jdt.internal.compiler.lookup.BlockScope; >+ >+public class CompletionOnBranchStatementLabel extends BranchStatement { >+ public static final int BREAK = 1; >+ public static final int CONTINUE = 2; >+ >+ private int kind; >+ public char[][] possibleLabels; >+ >+ public CompletionOnBranchStatementLabel(int kind, char[] l, int s, int e, char[][] possibleLabels) { >+ super(l, s, e); >+ this.kind = kind; >+ this.possibleLabels = possibleLabels; >+ } >+ >+ public FlowInfo analyseCode(BlockScope currentScope, >+ FlowContext flowContext, FlowInfo flowInfo) { >+ // Is never called >+ return null; >+ } >+ >+ public void resolve(BlockScope scope) { >+ throw new CompletionNodeFound(this, scope); >+ } >+ public StringBuffer printStatement(int indent, StringBuffer output) { >+ printIndent(indent, output); >+ if(this.kind == CONTINUE) { >+ output.append("continue "); //$NON-NLS-1$ >+ } else { >+ output.append("break "); //$NON-NLS-1$ >+ } >+ output.append("<CompleteOnLabel:"); //$NON-NLS-1$ >+ output.append(this.label); >+ return output.append(">;"); //$NON-NLS-1$ >+ } >+ >+} >#P org.eclipse.jdt.core.tests.model >Index: src/org/eclipse/jdt/core/tests/model/CompletionTests.java >=================================================================== >RCS file: /cvsroot/eclipse/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/CompletionTests.java,v >retrieving revision 1.188 >diff -u -r1.188 CompletionTests.java >--- src/org/eclipse/jdt/core/tests/model/CompletionTests.java 9 Sep 2008 12:43:37 -0000 1.188 >+++ src/org/eclipse/jdt/core/tests/model/CompletionTests.java 10 Oct 2008 07:19:48 -0000 >@@ -16,6 +16,9 @@ > import junit.framework.Test; > > import org.eclipse.core.runtime.CoreException; >+import org.eclipse.core.runtime.IProgressMonitor; >+import org.eclipse.core.runtime.NullProgressMonitor; >+import org.eclipse.core.runtime.OperationCanceledException; > import org.eclipse.jdt.core.CompletionContext; > import org.eclipse.jdt.core.CompletionProposal; > import org.eclipse.jdt.core.CompletionRequestor; >@@ -55,6 +58,63 @@ > char[] varClassName = ((EvaluationContextWrapper)context).getVarClassName(); > return Signature.createTypeSignature(varClassName, true); > } >+//https://bugs.eclipse.org/bugs/show_bug.cgi?id=247941 >+public void testAbortCompletion1() throws JavaModelException { >+ this.workingCopies = new ICompilationUnit[1]; >+ this.workingCopies[0] = getWorkingCopy( >+ "/Completion/src/AbortCompletion.java", >+ "public class AbortCompletion {\n"+ >+ " void foo() {\n"+ >+ " Objec\n"+ >+ " }\n"+ >+ "}\n"); >+ >+ CompletionTestsRequestor2 requestor = new CompletionTestsRequestor2(); >+ >+ String str = this.workingCopies[0].getSource(); >+ String completeBehind = "Objec"; >+ int cursorLocation = str.lastIndexOf(completeBehind) + completeBehind.length(); >+ IProgressMonitor monitor = new NullProgressMonitor(); >+ try { >+ this.workingCopies[0].codeComplete(cursorLocation, requestor, this.wcOwner, monitor); >+ assertResults( >+ "Object[TYPE_REF]{Object, java.lang, Ljava.lang.Object;, null, " + (R_DEFAULT + R_RESOLVED + R_INTERESTING + R_CASE + R_UNQUALIFIED + R_NON_RESTRICTED) + "}", >+ requestor.getResults()); >+ } catch (OperationCanceledException e) { >+ assertTrue("Should not be cancelled", false); >+ } >+ >+} >+ >+//https://bugs.eclipse.org/bugs/show_bug.cgi?id=247941 >+public void testAbortCompletion2() throws JavaModelException { >+ this.workingCopies = new ICompilationUnit[1]; >+ this.workingCopies[0] = getWorkingCopy( >+ "/Completion/src/AbortCompletion.java", >+ "public class AbortCompletion {\n"+ >+ " void foo() {\n"+ >+ " Objec\n"+ >+ " }\n"+ >+ "}\n"); >+ >+ CompletionTestsRequestor2 requestor = new CompletionTestsRequestor2(); >+ >+ String str = this.workingCopies[0].getSource(); >+ String completeBehind = "Objec"; >+ int cursorLocation = str.lastIndexOf(completeBehind) + completeBehind.length(); >+ >+ try { >+ IProgressMonitor monitor = new NullProgressMonitor(); >+ monitor.setCanceled(true); /*force completion to abort*/ >+ this.workingCopies[0].codeComplete(cursorLocation, requestor, this.wcOwner, monitor); >+ assertTrue("Should not be cancelled", false); >+ } catch (OperationCanceledException e) { >+ assertResults( >+ "", >+ requestor.getResults()); >+ } >+} >+ > //https://bugs.eclipse.org/bugs/show_bug.cgi?id=164311 > public void testBug164311() throws JavaModelException { > this.workingCopies = new ICompilationUnit[1];
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Diff
Attachments on
bug 247941
:
114663
| 114761