Fix for Bug 522613: [9][content assist] No proposal after
provides...with
Change-Id: I84fbf81c7232bb9068f54eb073fdc201207e31da
diff --git a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/CompletionTests9.java b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/CompletionTests9.java
index 5f908f9..fa5c7df 100644
--- a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/CompletionTests9.java
+++ b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/CompletionTests9.java
@@ -791,4 +791,34 @@
deleteProject(project1);
}
}
+public void test522613_001() throws Exception {
+ IJavaProject project1 = createJavaProject("Completion9_1", new String[] {"src"}, new String[] {"JCL18_LIB"}, "bin", "9");
+ try {
+ project1.open(null);
+ createTypePlus("/Completion9_1/src/", "pack11", "Driver", "", false /* isClass */, true /* createFolder */);
+ createTypePlus("/Completion9_1/src/", "pack11", "CCC", "implements pack11.Driver", true /* isClass */, false /* createFolder */);
+ String filePath1 = "/Completion9_1/src/module-info.java";
+ String completeBehind = "with C";
+ String fileContent1 = "module first {\n"
+ + "provides pack11.Driver " + completeBehind
+ + "}\n";
+ createFile(filePath1, fileContent1);
+ addClasspathEntry(project1, JavaCore.newContainerEntry(new Path("org.eclipse.jdt.MODULE_PATH")));
+
+ project1.close(); // sync
+ project1.open(null);
+
+ int cursorLocation = fileContent1.lastIndexOf(completeBehind) + completeBehind.length();
+ CompletionTestsRequestor2 requestor = new CompletionTestsRequestor2();
+
+ ICompilationUnit unit = getCompilationUnit(filePath1);
+ unit.codeComplete(cursorLocation, requestor);
+
+ String expected = "CCC[TYPE_REF]{pack11.CCC, pack11, Lpack11.CCC;, null, 49}"
+ ;
+ assertResults(expected, requestor.getResults());
+ } finally {
+ deleteProject(project1);
+ }
+}
}
\ No newline at end of file
diff --git a/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/CompletionEngine.java b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/CompletionEngine.java
index af5186d..1875040 100644
--- a/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/CompletionEngine.java
+++ b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/CompletionEngine.java
@@ -1392,9 +1392,10 @@
if (this.options.checkVisibility) {
if((modifiers & ClassFileConstants.AccPublic) == 0) {
if((modifiers & ClassFileConstants.AccPrivate) != 0) return;
-
- char[] currentPackage = CharOperation.concatWith(this.unitScope.fPackage.compoundName, '.');
- if(!CharOperation.equals(packageName, currentPackage)) return;
+ if (this.moduleDeclaration == null) {
+ char[] currentPackage = CharOperation.concatWith(this.unitScope.fPackage.compoundName, '.');
+ if(!CharOperation.equals(packageName, currentPackage)) return;
+ }
}
}
@@ -2074,57 +2075,66 @@
}
}
}
- UsesStatement[] uses = this.moduleDeclaration.uses;
- if (uses != null) {
- for (int i = 0, l = uses.length; i < l; ++i) {
- TypeReference usesReference = uses[i].serviceInterface;
- if (usesReference instanceof CompletionOnUsesSingleTypeReference ||
- usesReference instanceof CompletionOnUsesQualifiedTypeReference) {
- this.lookupEnvironment.buildTypeBindings(parsedUnit, null);
- if ((this.unitScope = parsedUnit.scope) != null) {
- contextAccepted = true;
- buildContext(usesReference, null, parsedUnit, null, null);
- findTypeReferences(usesReference, true);
- debugPrintf();
+ try {
+ UsesStatement[] uses = this.moduleDeclaration.uses;
+ if (uses != null) {
+ for (int i = 0, l = uses.length; i < l; ++i) {
+ UsesStatement usesStatement = uses[i];
+ this.parser.enclosingNode = usesStatement;
+ TypeReference usesReference = usesStatement.serviceInterface;
+ if (usesReference instanceof CompletionOnUsesSingleTypeReference ||
+ usesReference instanceof CompletionOnUsesQualifiedTypeReference) {
+ contextAccepted = checkForCNF(usesReference, parsedUnit, true);
return;
}
}
}
- }
- ProvidesStatement[] providesStmts = this.moduleDeclaration.services;
- for (int i = 0, l = providesStmts != null ? providesStmts.length : 0; i < l; ++i) {
- ProvidesStatement providesStmt = providesStmts[i];
- TypeReference pInterface = providesStmt.serviceInterface;
- if (pInterface instanceof CompletionOnProvidesInterfacesSingleTypeReference ||
- pInterface instanceof CompletionOnProvidesInterfacesQualifiedTypeReference) {
- this.lookupEnvironment.buildTypeBindings(parsedUnit, null);
- if ((this.unitScope = parsedUnit.scope) != null) {
- contextAccepted = true;
- buildContext(pInterface, null, parsedUnit, null, null);
- findTypeReferences(pInterface, true);
- debugPrintf();
+ ProvidesStatement[] providesStmts = this.moduleDeclaration.services;
+ for (int i = 0, l = providesStmts != null ? providesStmts.length : 0; i < l; ++i) {
+ ProvidesStatement providesStmt = providesStmts[i];
+ this.parser.enclosingNode = providesStmt;
+ TypeReference pInterface = providesStmt.serviceInterface;
+ if (pInterface instanceof CompletionOnProvidesInterfacesSingleTypeReference ||
+ pInterface instanceof CompletionOnProvidesInterfacesQualifiedTypeReference) {
+ contextAccepted = checkForCNF(pInterface, parsedUnit, true);
return;
}
- }
- TypeReference[] implementations = providesStmt.implementations;
- for (int j = 0, k = implementations.length; j < k; ++j) {
- TypeReference implementation = implementations[i];
-
- if (implementation instanceof CompletionOnProvidesImplementationsSingleTypeReference ||
- implementation instanceof CompletionOnProvidesImplementationsQualifiedTypeReference) {
- this.lookupEnvironment.buildTypeBindings(parsedUnit, null);
- if ((this.unitScope = parsedUnit.scope) != null) {
- contextAccepted = true;
- buildContext(implementation, null, parsedUnit, null, null);
- findImplementations(providesStmt, i/* stmtIndex */, j/* implIndex */);
- debugPrintf();
+ TypeReference[] implementations = providesStmt.implementations;
+ for (int j = 0, k = implementations.length; j < k; ++j) {
+ TypeReference implementation = implementations[j];
+ if (implementation instanceof CompletionOnProvidesImplementationsSingleTypeReference ||
+ implementation instanceof CompletionOnProvidesImplementationsQualifiedTypeReference) {
+ contextAccepted = checkForCNF(implementation, parsedUnit, false);
return;
+ } else if (implementation instanceof CompletionOnKeyword) {
+ contextAccepted = true;
+ processModuleKeywordCompletion(parsedUnit, implementation, (CompletionOnKeyword) implementation);
}
- } else if (implementation instanceof CompletionOnKeyword) {
- contextAccepted = true;
- processModuleKeywordCompletion(parsedUnit, implementation, (CompletionOnKeyword) implementation);
}
}
+ } 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);
+ }
}
}
// scan the package & import statements first
@@ -2303,6 +2313,26 @@
}
}
+ private boolean checkForCNF(TypeReference ref, CompilationUnitDeclaration parsedUnit, boolean showAll) {
+ this.lookupEnvironment.buildTypeBindings(parsedUnit, null);
+ this.lookupEnvironment.completeTypeBindings(parsedUnit, true);
+ parsedUnit.resolve();
+ if ((this.unitScope = parsedUnit.scope) != null) {
+ if (showAll) {
+ char[][] tokens = ref.getTypeName();
+ char[] typeName = CharOperation.concatWithAll(tokens, '.');
+ if (typeName.length == 0) {
+ buildContext(ref, null, parsedUnit, null, null);
+ this.completionToken = new char[] {'*'};
+ findTypesAndPackages(this.completionToken, this.unitScope, true, true, new ObjectVector());
+ return true;
+ }
+ }
+ parsedUnit.scope.faultInTypes();
+ }
+ return false; // should not come here - will throw exception
+ }
+
private boolean completeOnPackageVisibilityStatements(boolean contextAccepted,
CompilationUnitDeclaration parsedUnit, PackageVisibilityStatement[] pvsStmts) {
for (int i = 0, l = pvsStmts.length; i < l; ++i) {
@@ -3617,8 +3647,7 @@
}
private void completionOnProvidesImplementationsQualifiedTypeReference(ASTNode astNode, ASTNode astNodeParent, Binding qualifiedBinding, Scope scope) {
- // TODO: Filter the results wrt accessibility and add relevance to the results.
- completionOnQualifiedTypeReference(astNode, astNodeParent, qualifiedBinding, scope);
+ findImplementations((ProvidesStatement) this.parser.enclosingNode, (TypeReference) astNode);
}
private void completionOnSingleNameReference(ASTNode astNode, ASTNode astNodeParent, Scope scope,
@@ -3755,12 +3784,11 @@
}
private void completionOnProvidesInterfacesSingleTypeReference(ASTNode astNode, ASTNode astNodeParent, Binding qualifiedBinding, Scope scope) {
- // TODO : filter the results.
completionOnSingleTypeReference(astNode, astNodeParent, qualifiedBinding, scope);
}
private void completionOnProvidesImplementationsSingleTypeReference(ASTNode astNode, ASTNode astNodeParent, Binding qualifiedBinding, Scope scope) {
- // TODO : filter the results.
- completionOnSingleTypeReference(astNode, astNodeParent, qualifiedBinding, scope);
+ findImplementations((ProvidesStatement) this.parser.enclosingNode, (TypeReference) astNode);
+ // TODO : filter the results - remove packs without a type in impl.
}
private char[][] computeAlreadyDefinedName(
@@ -11850,30 +11878,7 @@
return null;
}
- private void findTypeReferences(TypeReference reference, boolean findMembers) {
- char[][] tokens = reference.getTypeName();
-
- char[] typeName = CharOperation.concatWithAll(tokens, '.');
-
- if (typeName.length == 0) {
- this.completionToken = new char[] {'*'};
- } else if (reference instanceof CompletionOnUsesQualifiedTypeReference ||
- reference instanceof CompletionOnProvidesInterfacesQualifiedTypeReference) {
- CompletionOnQualifiedTypeReference qReference = (CompletionOnQualifiedTypeReference) reference;
- if (qReference.completionIdentifier != null) {
- this.completionToken = CharOperation.concatAll(typeName, qReference.completionIdentifier, '.');
- }
- } else {
- char[] lastToken = tokens[tokens.length - 1];
- this.completionToken = lastToken != null && lastToken.length == 0 ?
- CharOperation.concat(typeName, new char[]{'.'}) :lastToken;
- }
- setSourceRange(reference.sourceStart, reference.sourceEnd);
- findTypesAndPackages(this.completionToken, this.unitScope, true, true, new ObjectVector());
- }
-
- private void findImplementations(ProvidesStatement providesStmt, int stmtIndex, int implIndex) {
- TypeReference reference = providesStmt.implementations[implIndex];
+ private void findImplementations(ProvidesStatement providesStmt, TypeReference reference ) {
char[][] tokens = reference.getTypeName();
char[] typeName = CharOperation.concatWithAll(tokens, '.');
@@ -11890,15 +11895,19 @@
CharOperation.concat(typeName, new char[]{'.'}) :lastToken;
}
setSourceRange(reference.sourceStart, reference.sourceEnd);
- findImplementations(this.completionToken, this.unitScope, providesStmt, stmtIndex);
+ findImplementations(this.completionToken, this.unitScope, providesStmt, -1);
}
private void findImplementations(char[] token, Scope scope, ProvidesStatement providesStmt, int stmtIndex) {
-
TypeReference theInterface = providesStmt.serviceInterface;
-
if (token == null) return;
- char[][] theInterfaceType = theInterface.getTypeName();
+ char[][] theInterfaceType = null;
+ if (theInterface.resolvedType != null && theInterface.resolvedType.isValidBinding()) {
+ char[] readableName = theInterface.resolvedType.readableName();
+ if (readableName != null)
+ theInterfaceType = CharOperation.splitOn('.', readableName);
+ }
+ theInterfaceType = theInterfaceType == null ? theInterface.getTypeName() : theInterfaceType;
if (theInterfaceType == null) return;
SearchPattern pattern = null;
NameEnvironmentAnswer answer = this.nameEnvironment.findTypeInModules(theInterfaceType, scope.module());
@@ -11925,7 +11934,7 @@
}
@Override
public void acceptSearchMatch(SearchMatch match) throws CoreException {
- checkCancel();
+ // checkCancel();
IJavaElement element = ((IJavaElement) match.getElement());
if (element.getElementType() == IJavaElement.TYPE) {
IType type = (IType) element;
@@ -11936,7 +11945,9 @@
} else {
fullTypeName = type.getElementName();
}
- if (!fullTypeName.startsWith(this.prefix) || this.filter.contains(fullTypeName)) return;
+ if (this.filter.contains(fullTypeName)) return;
+ if (!(fullTypeName.startsWith(this.prefix) || type.getElementName().startsWith(this.prefix)))
+ return;
}
this.types.add(type);
}