From 5b2bb94f4e856769f91104c59130e71acd77f453 Mon Sep 17 00:00:00 2001 From: Stephan Herrmann Date: Tue, 27 Feb 2018 17:39:26 +0100 Subject: update jdt.core to S4_7_3_RC3 --- .../jdt/core/tests/model/CompletionTests9.java | 152 +++++++++++++++++++++ .../jdt/internal/codeassist/CompletionEngine.java | 14 +- .../compiler/lookup/AnnotatableTypeSystem.java | 5 +- .../jdt/internal/compiler/lookup/TypeSystem.java | 96 +++++++++---- .../org/eclipse/jdt/internal/core/NameLookup.java | 3 +- .../jdt/internal/core/SearchableEnvironment.java | 54 +++++++- 6 files changed, 286 insertions(+), 38 deletions(-) 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 187043395..134963008 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 @@ -1214,4 +1214,156 @@ public void testBug528948_002() throws Exception { deleteProject(project2); } } +public void testBug517417_001() throws Exception { + IJavaProject project1 = createJavaProject("Completion9_1", new String[] {"src"}, new String[] {"JCL9_LIB"}, "bin", "9"); + IJavaProject project2 = createJavaProject("Completion9_2", new String[] {"src"}, new String[] {"JCL9_LIB"}, "bin", "9"); + IJavaProject project3 = createJavaProject("Completion9_3", new String[] {"src"}, new String[] {"JCL9_LIB"}, "bin", "9"); + try { + project1.open(null); + createType("/Completion9_1/src/", "pack11", "X11"); + createFile("/Completion9_1/src/module-info.java", + "module first {\n" + + " requires second;\n" + + "}\n"); + String fileContent = + "package pack0;\n" + + "import pac\n" + + "public class Main {\n" + + "}\n"; + String completeBehind = "import pac"; + createFolder("/Completion9_1/src/pack0"); + String filePath = "/Completion9_1/src/pack0/Main.java"; + createFile(filePath, fileContent); + addClasspathEntry(project1, JavaCore.newContainerEntry(new Path("org.eclipse.jdt.MODULE_PATH"))); + + project2.open(null); + createType("/Completion9_2/src/", "pack21", "X21"); + createType("/Completion9_2/src/", "pack2internal", "X22"); + + createFile("/Completion9_2/src/module-info.java", + "module second { \n" + + " requires transitive third;\n" + + " exports pack21 to first;\n" + + " exports pack2internal to my.test.mod;\n" + + "}\n"); + addClasspathEntry(project2, JavaCore.newContainerEntry(new Path("org.eclipse.jdt.MODULE_PATH"))); + + project3.open(null); + createType("/Completion9_3/src/", "pack31", "X31"); + + createFile("/Completion9_3/src/module-info.java", + "module third { " + + " exports pack31;\n" + + "}\n"); + addClasspathEntry(project3, JavaCore.newContainerEntry(new Path("org.eclipse.jdt.MODULE_PATH"))); + + project1.close(); // sync + project2.close(); + project3.close(); + project3.open(null); + project2.open(null); + project1.open(null); + + int cursorLocation = fileContent.lastIndexOf(completeBehind) + completeBehind.length(); + CompletionTestsRequestor2 requestor = new CompletionTestsRequestor2(); + + ICompilationUnit unit = getCompilationUnit(filePath); + unit.codeComplete(cursorLocation, requestor); + + String expected = "pack0[PACKAGE_REF]{pack0.*;, pack0, null, null, 49}\n" + // local + "pack11[PACKAGE_REF]{pack11.*;, pack11, null, null, 49}\n" + // local + "pack21[PACKAGE_REF]{pack21.*;, pack21, null, null, 49}\n" + // exported + "pack31[PACKAGE_REF]{pack31.*;, pack31, null, null, 49}"; // exported in transitively required third + // package pack2internal is exported only to another module + assertResults(expected, requestor.getResults()); + } finally { + deleteProject(project1); + deleteProject(project2); + deleteProject(project3); + } +} + +// testing only packages from transitive requires modules available for completion +public void testBug517417_002() throws Exception { + IJavaProject project1 = createJavaProject("Completion9_1", new String[] {"src"}, new String[] {"JCL9_LIB"}, "bin", "9"); + IJavaProject project2 = createJavaProject("Completion9_2", new String[] {"src"}, new String[] {"JCL9_LIB"}, "bin", "9"); + IJavaProject project3 = createJavaProject("Completion9_3", new String[] {"src"}, new String[] {"JCL9_LIB"}, "bin", "9"); + IJavaProject project4 = createJavaProject("Completion9_4", new String[] {"src"}, new String[] {"JCL9_LIB"}, "bin", "9"); + try { + project1.open(null); + createType("/Completion9_1/src/", "pack11", "X11"); + createFile("/Completion9_1/src/module-info.java", + "module first {\n" + + " requires second;\n" + + "}\n"); + String fileContent = + "package pack0;\n" + + "import pac\n" + + "public class Main {\n" + + "}\n"; + String completeBehind = "import pac"; + createFolder("/Completion9_1/src/pack0"); + String filePath = "/Completion9_1/src/pack0/Main.java"; + createFile(filePath, fileContent); + addClasspathEntry(project1, JavaCore.newContainerEntry(new Path("org.eclipse.jdt.MODULE_PATH"))); + + project2.open(null); + createType("/Completion9_2/src/", "pack21", "X21"); + createType("/Completion9_2/src/", "pack2internal", "X22"); + + createFile("/Completion9_2/src/module-info.java", + "module second { \n" + + " requires transitive third;\n" + + " requires four;\n" + + " exports pack21 to first;\n" + + " exports pack2internal to my.test.mod;\n" + + "}\n"); + addClasspathEntry(project2, JavaCore.newContainerEntry(new Path("org.eclipse.jdt.MODULE_PATH"))); + + project3.open(null); + createType("/Completion9_3/src/", "pack31", "X31"); + + createFile("/Completion9_3/src/module-info.java", + "module third { " + + " exports pack31;\n" + + "}\n"); + addClasspathEntry(project3, JavaCore.newContainerEntry(new Path("org.eclipse.jdt.MODULE_PATH"))); + + project4.open(null); + createType("/Completion9_4/src/", "pack41", "X41"); + + createFile("/Completion9_4/src/module-info.java", + "module four { " + + " exports pack41;\n" + + "}\n"); + addClasspathEntry(project4, JavaCore.newContainerEntry(new Path("org.eclipse.jdt.MODULE_PATH"))); + + project1.close(); // sync + project2.close(); + project3.close(); + project4.close(); + project4.open(null); + project3.open(null); + project2.open(null); + project1.open(null); + + int cursorLocation = fileContent.lastIndexOf(completeBehind) + completeBehind.length(); + CompletionTestsRequestor2 requestor = new CompletionTestsRequestor2(); + + ICompilationUnit unit = getCompilationUnit(filePath); + unit.codeComplete(cursorLocation, requestor); + + String expected = "pack0[PACKAGE_REF]{pack0.*;, pack0, null, null, 49}\n" + // local + "pack11[PACKAGE_REF]{pack11.*;, pack11, null, null, 49}\n" + // local + "pack21[PACKAGE_REF]{pack21.*;, pack21, null, null, 49}\n" + // exported + "pack31[PACKAGE_REF]{pack31.*;, pack31, null, null, 49}"; // exported in transitively required third + // package pack2internal is exported only to another module + assertResults(expected, requestor.getResults()); + } finally { + deleteProject(project1); + deleteProject(project2); + deleteProject(project3); + deleteProject(project4); + } +} } \ 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 5f948cdae..0eb8b8447 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 @@ -8549,7 +8549,11 @@ public final class CompletionEngine setSourceRange( importReference.sourceStart, importReference.declarationSourceEnd); - this.nameEnvironment.findPackages(importName, this); + try { + this.nameEnvironment.findPackages(importName, this, this.javaProject.getAllPackageFragmentRoots(), true); + } catch (JavaModelException e) { + // silent + } setSourceRange( oldStart, oldEnd - 1, @@ -11515,7 +11519,7 @@ public final class CompletionEngine private void findPackagesInCurrentModule() { try { IPackageFragmentRoot[] moduleRoots = SearchableEnvironment.getOwnedPackageFragmentRoots(this.javaProject); - this.nameEnvironment.findPackages(CharOperation.toLowerCase(this.completionToken), this, moduleRoots); + this.nameEnvironment.findPackages(CharOperation.toLowerCase(this.completionToken), this, moduleRoots, false); } catch (JavaModelException e) { // silent } @@ -11527,7 +11531,11 @@ public final class CompletionEngine 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); + try { + this.nameEnvironment.findPackages(CharOperation.toLowerCase(this.completionToken), this, this.javaProject.getAllPackageFragmentRoots(), true); + } catch (JavaModelException e) { + // silent + } } private void findParameterizedType(TypeReference ref, Scope scope) { diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/AnnotatableTypeSystem.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/AnnotatableTypeSystem.java index 3d5efab14..e7215f277 100644 --- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/AnnotatableTypeSystem.java +++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/AnnotatableTypeSystem.java @@ -226,7 +226,8 @@ public class AnnotatableTypeSystem extends TypeSystem { throw new IllegalStateException(); WildcardBinding nakedType = null; - TypeBinding[] derivedTypes = getDerivedTypes(genericType); + boolean useDerivedTypesOfBound = bound instanceof TypeVariableBinding || bound instanceof ParameterizedTypeBinding; + TypeBinding[] derivedTypes = getDerivedTypes(useDerivedTypesOfBound ? bound : genericType); for (int i = 0, length = derivedTypes.length; i < length; i++) { TypeBinding derivedType = derivedTypes[i]; if (derivedType == null) @@ -250,7 +251,7 @@ public class AnnotatableTypeSystem extends TypeSystem { WildcardBinding wildcard = new WildcardBinding(genericType, rank, bound, otherBounds, boundKind, this.environment); wildcard.id = nakedType.id; wildcard.setTypeAnnotations(annotations, this.isAnnotationBasedNullAnalysisEnabled); - return (WildcardBinding) cacheDerivedType(genericType, nakedType, wildcard); + return (WildcardBinding) cacheDerivedType(useDerivedTypesOfBound ? bound : genericType, nakedType, wildcard); } public WildcardBinding getWildcard(ReferenceBinding genericType, int rank, TypeBinding bound, TypeBinding[] otherBounds, int boundKind) { diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/TypeSystem.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/TypeSystem.java index fe3247ace..f221d1ab2 100644 --- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/TypeSystem.java +++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/TypeSystem.java @@ -69,34 +69,62 @@ public class TypeSystem { public final class HashedParameterizedTypes { - private final class InternalParameterizedTypeBinding extends ParameterizedTypeBinding { - + private final class PTBKey extends ReferenceBinding { // extends ReferenceBinding so it can be used as wrapper + protected ReferenceBinding type; // must ensure the type is resolved + public TypeBinding[] arguments; + private ReferenceBinding enclosingType; //{ObjectTeams: announce dependent types as parameterizations, too: ITeamAnchor teamAnchor; int valueParamPosition = -1; - public InternalParameterizedTypeBinding(ReferenceBinding genericType, TypeBinding[] typeArguments, ITeamAnchor teamAnchor, int valueParamPosition, + public PTBKey(ReferenceBinding type, TypeBinding[] arguments, ITeamAnchor teamAnchor, int valueParamPosition, ReferenceBinding enclosingType, LookupEnvironment environment) { -/* orig: - public InternalParameterizedTypeBinding(ReferenceBinding genericType, TypeBinding[] typeArguments, ReferenceBinding enclosingType, LookupEnvironment environment) { - super(genericType, typeArguments, enclosingType, environment); - */ -// :giro - super(genericType, typeArguments, teamAnchor, enclosingType, environment); this.teamAnchor = teamAnchor; this.valueParamPosition = valueParamPosition; +/* orig: + public PTBKey(ReferenceBinding type, TypeBinding[] arguments, ReferenceBinding enclosingType, LookupEnvironment environment) { + :giro */ // SH} + this.type = type; + this.arguments = arguments; + this.enclosingType = enclosingType; + + if(environment != null) { + // only add as wrapper when used in put() + if (type instanceof UnresolvedReferenceBinding) + ((UnresolvedReferenceBinding) type).addWrapper(this, environment); + if (arguments != null) { + for (int i = 0, l = arguments.length; i < l; i++) { + if (arguments[i] instanceof UnresolvedReferenceBinding) + ((UnresolvedReferenceBinding) arguments[i]).addWrapper(this, environment); + if (arguments[i].hasNullTypeAnnotations()) + this.tagBits |= TagBits.HasNullTypeAnnotation; + } + } + } + } + @Override + public void swapUnresolved(UnresolvedReferenceBinding unresolvedType, ReferenceBinding resolvedType, LookupEnvironment env) { + if (this.type == unresolvedType) { //$IDENTITY-COMPARISON$ + this.type = resolvedType; // cannot be raw since being parameterized below + ReferenceBinding enclosing = resolvedType.enclosingType(); + if (enclosing != null) { + this.enclosingType = (ReferenceBinding) env.convertUnresolvedBinaryToRawType(enclosing); // needed when binding unresolved member type + } + } + if (this.arguments != null) { + for (int i = 0, l = this.arguments.length; i < l; i++) { + if (this.arguments[i] == unresolvedType) { //$IDENTITY-COMPARISON$ + this.arguments[i] = env.convertUnresolvedBinaryToRawType(resolvedType); + } + } + } } - public boolean equals(Object other) { - ParameterizedTypeBinding that = (ParameterizedTypeBinding) other; // homogeneous container. + PTBKey that = (PTBKey) other; // homogeneous container. //{ObjectTeams: more checks: - ITeamAnchor thatAnchor = null; - int thatValueParamPos = -1; - if (that instanceof InternalParameterizedTypeBinding) { - thatValueParamPos = ((InternalParameterizedTypeBinding)that).valueParamPosition; - thatAnchor = ((InternalParameterizedTypeBinding)that).teamAnchor; - } + ITeamAnchor thatAnchor = that.teamAnchor; + int thatValueParamPos = that.valueParamPosition; if (this.teamAnchor != thatAnchor) { if (this.teamAnchor == null || thatAnchor == null || !this.teamAnchor.hasSameBestNameAs(thatAnchor)) return false; @@ -105,11 +133,17 @@ public class TypeSystem { // SH} return this.type == that.type && this.enclosingType == that.enclosingType && Util.effectivelyEqual(this.arguments, that.arguments); //$IDENTITY-COMPARISON$ } - + final int hash(TypeBinding b) { + if(b instanceof WildcardBinding || b instanceof TypeVariableBinding) { + return System.identityHashCode(b); + } + return b.hashCode(); + } public int hashCode() { - int hashCode = this.type.hashCode() + 13 * (this.enclosingType != null ? this.enclosingType.hashCode() : 0); + final int prime=31; + int hashCode = 1 + hash(this.type) + (this.enclosingType != null ? hash(this.enclosingType) : 0); for (int i = 0, length = this.arguments == null ? 0 : this.arguments.length; i < length; i++) { - hashCode += (i + 1) * this.arguments[i].hashCode(); + hashCode = hashCode * prime + hash(this.arguments[i]); } //{ObjectTeams: more if (this.teamAnchor != null) @@ -121,7 +155,7 @@ public class TypeSystem { } } - HashMap hashedParameterizedTypes = new HashMap(256); + HashMap hashedParameterizedTypes = new HashMap<>(256); //{ObjectTeams: more args: /* orig: @@ -140,9 +174,9 @@ public class TypeSystem { ReferenceBinding unannotatedEnclosingType = enclosingType == null ? null : (ReferenceBinding) getUnannotatedType(enclosingType); /* - ParameterizedTypeBinding typeParameterization = new InternalParameterizedTypeBinding(unannotatedGenericType, unannotatedTypeArguments, unannotatedEnclosingType, TypeSystem.this.environment); + PTBKey key = new PTBKey(unannotatedGenericType, unannotatedTypeArguments, unannotatedEnclosingType, null); :giro */ - ParameterizedTypeBinding typeParameterization = new InternalParameterizedTypeBinding(unannotatedGenericType, unannotatedTypeArguments, + PTBKey key = new PTBKey(unannotatedGenericType, unannotatedTypeArguments, anchor, valueParamPosition, unannotatedEnclosingType, TypeSystem.this.environment); // SH} ReferenceBinding genericTypeToMatch = unannotatedGenericType, enclosingTypeToMatch = unannotatedEnclosingType; @@ -152,7 +186,7 @@ public class TypeSystem { enclosingTypeToMatch = enclosingType; typeArgumentsToMatch = typeArguments; } - ParameterizedTypeBinding [] parameterizedTypeBindings = this.hashedParameterizedTypes.get(typeParameterization); + ParameterizedTypeBinding [] parameterizedTypeBindings = this.hashedParameterizedTypes.get(key); for (int i = 0, length = parameterizedTypeBindings == null ? 0 : parameterizedTypeBindings.length; i < length; i++) { ParameterizedTypeBinding parameterizedType = parameterizedTypeBindings[i]; if (parameterizedType.actualType() != genericTypeToMatch) { //$IDENTITY-COMPARISON$ @@ -184,12 +218,12 @@ public class TypeSystem { ReferenceBinding unannotatedEnclosingType = enclosingType == null ? null : (ReferenceBinding) getUnannotatedType(enclosingType); /* - ParameterizedTypeBinding typeParameterization = new InternalParameterizedTypeBinding(unannotatedGenericType, unannotatedTypeArguments, unannotatedEnclosingType, TypeSystem.this.environment); + PTBKey key = new PTBKey(unannotatedGenericType, unannotatedTypeArguments, unannotatedEnclosingType, TypeSystem.this.environment); :giro */ - ParameterizedTypeBinding typeParameterization = new InternalParameterizedTypeBinding(unannotatedGenericType, unannotatedTypeArguments, + PTBKey key = new PTBKey(unannotatedGenericType, unannotatedTypeArguments, anchor, valueParamPosition, unannotatedEnclosingType, TypeSystem.this.environment); // SH} - ParameterizedTypeBinding [] parameterizedTypeBindings = this.hashedParameterizedTypes.get(typeParameterization); + ParameterizedTypeBinding [] parameterizedTypeBindings = this.hashedParameterizedTypes.get(key); int slot; if (parameterizedTypeBindings == null) { slot = 0; @@ -199,7 +233,7 @@ public class TypeSystem { System.arraycopy(parameterizedTypeBindings, 0, parameterizedTypeBindings = new ParameterizedTypeBinding[slot + 1], 0, slot); } parameterizedTypeBindings[slot] = parameterizedType; - this.hashedParameterizedTypes.put(typeParameterization, parameterizedTypeBindings); + this.hashedParameterizedTypes.put(key, parameterizedTypeBindings); } } @@ -440,7 +474,9 @@ public class TypeSystem { } TypeBinding unannotatedBound = bound == null ? null : getUnannotatedType(bound); - TypeBinding[] derivedTypes = this.types[unannotatedGenericType.id]; // by construction, cachedInfo != null now. + boolean useDerivedTypesOfBound = unannotatedBound instanceof TypeVariableBinding || unannotatedBound instanceof ParameterizedTypeBinding; + TypeBinding[] derivedTypes = this.types[useDerivedTypesOfBound ? unannotatedBound.id :unannotatedGenericType.id]; // by construction, cachedInfo != null now. + int i, length = derivedTypes.length; for (i = 0; i < length; i++) { TypeBinding derivedType = derivedTypes[i]; @@ -456,7 +492,7 @@ public class TypeSystem { if (i == length) { System.arraycopy(derivedTypes, 0, derivedTypes = new TypeBinding[length * 2], 0, length); - this.types[unannotatedGenericType.id] = derivedTypes; + this.types[useDerivedTypesOfBound ? unannotatedBound.id :unannotatedGenericType.id] = derivedTypes; } TypeBinding wildcard = derivedTypes[i] = new WildcardBinding(unannotatedGenericType, rank, unannotatedBound, unannotatedOtherBounds, boundKind, this.environment); diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/NameLookup.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/NameLookup.java index 9695895d1..734cccbe0 100644 --- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/NameLookup.java +++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/NameLookup.java @@ -1153,9 +1153,10 @@ public class NameLookup implements SuffixConstants { private void seekModuleAwarePartialPackageFragments(String name, IJavaElementRequestor requestor, IPackageFragmentRoot[] moduleContext) { boolean allPrefixMatch = CharOperation.equals(name.toCharArray(), CharOperation.ALL_PREFIX); + String lName = name.toLowerCase(); Arrays.stream(this.packageFragments.keyTable) .filter(k -> k != null) - .filter(k -> allPrefixMatch || Util.concatWith((String[])k, '.').startsWith(name)) + .filter(k -> allPrefixMatch || Util.concatWith((String[])k, '.').toLowerCase().startsWith(lName)) .forEach(k -> { checkModulePackages(requestor, moduleContext, this.packageFragments.getIndex(k)); }); diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SearchableEnvironment.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SearchableEnvironment.java index 2b30b8e7d..37446db8f 100644 --- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SearchableEnvironment.java +++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SearchableEnvironment.java @@ -14,9 +14,10 @@ package org.eclipse.jdt.internal.core; import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; +import java.util.HashSet; import java.util.List; import java.util.Map; - +import java.util.Set; import org.eclipse.core.resources.IProject; import org.eclipse.core.resources.IResource; import org.eclipse.core.runtime.IPath; @@ -31,6 +32,8 @@ import org.eclipse.jdt.internal.compiler.env.AccessRestriction; import org.eclipse.jdt.internal.compiler.env.IBinaryType; import org.eclipse.jdt.internal.compiler.env.ICompilationUnit; import org.eclipse.jdt.internal.compiler.env.IModule; +import org.eclipse.jdt.internal.compiler.env.IModule.IModuleReference; +import org.eclipse.jdt.internal.compiler.env.IModule.IPackageExport; import org.eclipse.jdt.internal.compiler.env.IModuleAwareNameEnvironment; import org.eclipse.jdt.internal.compiler.env.ISourceType; import org.eclipse.jdt.internal.compiler.env.IUpdatableModule; @@ -233,12 +236,59 @@ public class SearchableEnvironment * The packages found are passed to: * ISearchRequestor.acceptPackage(char[][] packageName) */ - public void findPackages(char[] prefix, ISearchRequestor requestor, IPackageFragmentRoot[] moduleContext) { + public void findPackages(char[] prefix, ISearchRequestor requestor, IPackageFragmentRoot[] moduleContext, boolean followRequires) { this.nameLookup.seekPackageFragments( new String(prefix), true, new SearchableEnvironmentRequestor(requestor), moduleContext); + if (followRequires && this.knownModuleLocations != null) { + try { + boolean isMatchAllPrefix = CharOperation.equals(CharOperation.ALL_PREFIX, prefix); + Set modDescs = new HashSet<>(); + for (IPackageFragmentRoot root : moduleContext) { + IModuleDescription desc = root.getJavaProject().getModuleDescription(); + if (desc instanceof AbstractModule) + modDescs.add(desc); + } + for (IModuleDescription md : modDescs) { + IModuleReference[] reqModules = ((AbstractModule) md).getRequiredModules(); + char[] modName = md.getElementName().toCharArray(); + for (IModuleReference moduleReference : reqModules) { + findPackagesFromRequires(prefix, isMatchAllPrefix, requestor, moduleReference, modName); + } + } + } catch (JavaModelException e) { + // silent + } + } +} + +private void findPackagesFromRequires(char[] prefix, boolean isMatchAllPrefix, ISearchRequestor requestor, IModuleReference moduleReference, char[] clientModuleName) { + IPackageFragmentRoot[] fragmentRoots = findModuleContext(moduleReference.name()); + if (fragmentRoots == null) return; + for (IPackageFragmentRoot root : fragmentRoots) { + IJavaProject requiredProject = root.getJavaProject(); + try { + IModuleDescription module = requiredProject.getModuleDescription(); + if (module instanceof AbstractModule) { + AbstractModule requiredModule = (AbstractModule) module; + for (IPackageExport packageExport : requiredModule.getExportedPackages()) { + if (!packageExport.isQualified() || CharOperation.containsEqual(packageExport.targets(), clientModuleName)) { + char[] exportName = packageExport.name(); + if (isMatchAllPrefix || CharOperation.prefixEquals(prefix, exportName)) + requestor.acceptPackage(exportName); + } + } + for (IModuleReference moduleRef2 : requiredModule.getRequiredModules()) { + if (moduleRef2.isTransitive()) + findPackagesFromRequires(prefix, isMatchAllPrefix, requestor, moduleRef2, clientModuleName); + } + } + } catch (JavaModelException e) { + // silent + } } +} /** * Find the top-level types that are defined * in the current environment and whose simple name matches the given name. -- cgit v1.2.3