Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorStephan Herrmann2019-06-07 14:58:30 +0000
committerStephan Herrmann2019-07-02 14:25:31 +0000
commit1fbf13c28311e9090a4ae402b14adbc440f874ec (patch)
tree9a25525de352e1b137729d7186177b0a19878a8b
parent5d58390bf2fb018a53c69e075d1416a113301107 (diff)
downloadeclipse.jdt.core-1fbf13c28311e9090a4ae402b14adbc440f874ec.tar.gz
eclipse.jdt.core-1fbf13c28311e9090a4ae402b14adbc440f874ec.tar.xz
eclipse.jdt.core-1fbf13c28311e9090a4ae402b14adbc440f874ec.zip
Bug 547181 - [9][impl] Reconsider representation and lookup of packages
(SplitPackageBinding) - early creation of plain PB into MB.declaredPackages: - from CUS.buildTypeBindins() -> PVS.resolvePackageReference() - includes early application of add-exports - later add all (plain) packages with CUs associated to this module - avoid passing elements of MD.declaredPackages to clients - let MD.analyseReferencedPackages be responsible for error reporting - unify severity determination after bug 521497 - sketch of package scanning for auto modules (may be incomplete) - add a search for inaccessible package/type for better error reporting - when limit-modules present distinguish inaccessible vs. unobservable - improve package scan in ClasspathMultiDirectory - refactoring to avoid some "instanceof SplitPackageBinding" - apply add-reads early, too - throw ISE if reentrance still happens in package lookup (TESTING) - throw ISE if add-reads is applied when packages already exist - remove MB.isPackageLookupActive and related code Refactoring: introduce PlainPackageBinding for more precise typechecking Change-Id: I5f96bc7a487adfff75737a66096598e1c638c4d9
-rw-r--r--org.eclipse.jdt.compiler.apt/src/org/eclipse/jdt/internal/compiler/apt/model/Factory.java5
-rw-r--r--org.eclipse.jdt.compiler.apt/src/org/eclipse/jdt/internal/compiler/apt/model/ModuleElementImpl.java14
-rw-r--r--org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/InMemoryNameEnvironment9.java9
-rw-r--r--org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/ModuleCompilationTests.java54
-rw-r--r--org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/PackageBindingTest.java5
-rw-r--r--org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/ModuleBuilderTests.java78
-rw-r--r--org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/ReconcilerTests9.java93
-rw-r--r--org.eclipse.jdt.core/batch/org/eclipse/jdt/internal/compiler/batch/ClasspathDirectory.java28
-rw-r--r--org.eclipse.jdt.core/batch/org/eclipse/jdt/internal/compiler/batch/ClasspathJar.java13
-rw-r--r--org.eclipse.jdt.core/batch/org/eclipse/jdt/internal/compiler/batch/FileSystem.java36
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ModuleDeclaration.java35
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/OpensStatement.java10
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/PackageVisibilityStatement.java22
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/QualifiedNameReference.java7
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/QualifiedTypeReference.java2
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/env/IModuleAwareNameEnvironment.java17
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/env/IModulePathEntry.java8
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/env/IUpdatableModule.java1
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/impl/ITypeRequestor.java11
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/BinaryModuleBinding.java79
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/Binding.java3
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ClassScope.java12
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/CompilationUnitScope.java24
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/LookupEnvironment.java100
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ModuleBinding.java230
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/PackageBinding.java52
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/PlainPackageBinding.java47
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ProblemPackageBinding.java17
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/SourceModuleBinding.java4
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/SplitPackageBinding.java86
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/problem/ProblemReporter.java12
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/util/HashtableOfPackage.java27
-rw-r--r--org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SearchableEnvironment.java37
-rw-r--r--org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/ClasspathDirectory.java20
-rw-r--r--org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/ClasspathJar.java33
-rw-r--r--org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/ClasspathLocation.java4
-rw-r--r--org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/ClasspathMultiDirectory.java31
-rw-r--r--org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/ModulePathEntry.java12
-rw-r--r--org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/NameEnvironment.java18
-rw-r--r--org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/BindingKeyResolver.java6
-rw-r--r--org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/JavaSearchNameEnvironment.java20
41 files changed, 920 insertions, 402 deletions
diff --git a/org.eclipse.jdt.compiler.apt/src/org/eclipse/jdt/internal/compiler/apt/model/Factory.java b/org.eclipse.jdt.compiler.apt/src/org/eclipse/jdt/internal/compiler/apt/model/Factory.java
index c865529a65..8ea41f0242 100644
--- a/org.eclipse.jdt.compiler.apt/src/org/eclipse/jdt/internal/compiler/apt/model/Factory.java
+++ b/org.eclipse.jdt.compiler.apt/src/org/eclipse/jdt/internal/compiler/apt/model/Factory.java
@@ -52,7 +52,6 @@ import org.eclipse.jdt.internal.compiler.lookup.ModuleBinding;
import org.eclipse.jdt.internal.compiler.lookup.PackageBinding;
import org.eclipse.jdt.internal.compiler.lookup.ParameterizedTypeBinding;
import org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding;
-import org.eclipse.jdt.internal.compiler.lookup.SplitPackageBinding;
import org.eclipse.jdt.internal.compiler.lookup.TagBits;
import org.eclipse.jdt.internal.compiler.lookup.TypeBinding;
import org.eclipse.jdt.internal.compiler.lookup.TypeConstants;
@@ -392,8 +391,8 @@ public class Factory {
*/
public PackageElement newPackageElement(PackageBinding binding)
{
- if (binding instanceof SplitPackageBinding && binding.enclosingModule != null) {
- binding = ((SplitPackageBinding) binding).getIncarnation(binding.enclosingModule);
+ if (binding != null && binding.enclosingModule != null) {
+ binding = binding.getIncarnation(binding.enclosingModule);
}
if (binding == null) {
return null;
diff --git a/org.eclipse.jdt.compiler.apt/src/org/eclipse/jdt/internal/compiler/apt/model/ModuleElementImpl.java b/org.eclipse.jdt.compiler.apt/src/org/eclipse/jdt/internal/compiler/apt/model/ModuleElementImpl.java
index 86183925d5..62e8caedee 100644
--- a/org.eclipse.jdt.compiler.apt/src/org/eclipse/jdt/internal/compiler/apt/model/ModuleElementImpl.java
+++ b/org.eclipse.jdt.compiler.apt/src/org/eclipse/jdt/internal/compiler/apt/model/ModuleElementImpl.java
@@ -55,10 +55,7 @@ public class ModuleElementImpl extends ElementImpl implements ModuleElement {
}
private PackageBinding getModulesPackageBinding(PackageBinding binding) {
- if (binding instanceof SplitPackageBinding) {
- return ((SplitPackageBinding) binding).getIncarnation(this.binding);
- }
- return binding;
+ return binding.getIncarnation(this.binding);
}
@Override
@@ -85,9 +82,8 @@ public class ModuleElementImpl extends ElementImpl implements ModuleElement {
@Override
public List<? extends Element> getEnclosedElements() {
ModuleBinding module = this.binding;
- PackageBinding[] packs = module.declaredPackages.valueTable;
Set<PackageBinding> unique = new HashSet<>();
- for (PackageBinding p : packs) {
+ for (PackageBinding p : module.declaredPackages.values()) {
if (p == null)
continue;
if (p instanceof SplitPackageBinding) {
@@ -111,12 +107,10 @@ public class ModuleElementImpl extends ElementImpl implements ModuleElement {
unique.add(def);
}
} else {
- packs = this.binding.getExports();
- for (PackageBinding pBinding : packs) {
+ for (PackageBinding pBinding : this.binding.getExports()) {
unique.add(getModulesPackageBinding(pBinding));
}
- packs = this.binding.getOpens();
- for (PackageBinding pBinding : packs) {
+ for (PackageBinding pBinding : this.binding.getOpens()) {
unique.add(getModulesPackageBinding(pBinding));
}
}
diff --git a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/InMemoryNameEnvironment9.java b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/InMemoryNameEnvironment9.java
index c329fba5f7..8464c36880 100644
--- a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/InMemoryNameEnvironment9.java
+++ b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/InMemoryNameEnvironment9.java
@@ -71,8 +71,13 @@ public class InMemoryNameEnvironment9 extends InMemoryNameEnvironment implements
}
@Override
- public char[][] getModulesDeclaringPackage(char[][] parentPackageName, char[] name, char[] moduleName) {
- return collect(env -> env.getModulesDeclaringPackage(parentPackageName, name, moduleName), char[][]::new);
+ public char[][] getModulesDeclaringPackage(char[][] packageName, char[] moduleName) {
+ return collect(env -> env.getModulesDeclaringPackage(packageName, moduleName), char[][]::new);
+ }
+
+ @Override
+ public char[][] listPackages(char[] moduleName) {
+ return collect(env -> env.listPackages(moduleName), char[][]::new);
}
@Override
diff --git a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/ModuleCompilationTests.java b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/ModuleCompilationTests.java
index cddbcf6388..b69c75b599 100644
--- a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/ModuleCompilationTests.java
+++ b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/ModuleCompilationTests.java
@@ -1086,8 +1086,8 @@ public class ModuleCompilationTests extends AbstractBatchCompilerTest {
"----------\n" +
"1. ERROR in ---OUTPUT_DIR_PLACEHOLDER---/src/mod.two/q/Y.java (at line 3)\n" +
" java.sql.Connection con = p.X.getConnection();\n" +
- " ^\n" +
- "p cannot be resolved\n" +
+ " ^^^\n" +
+ "The type p.X is not accessible\n" +
"----------\n" +
"1 problem (1 error)\n",
false,
@@ -5393,4 +5393,54 @@ public void testBug521362_emptyFile() {
runConformModuleTest(files, buffer, "Could not invoke method java.lang.module.ModuleDescriptor.Version.parse(), cannot validate module version.\n", "", false);
}
}
+ public void testPackageTypeConflict2() {
+ File outputDirectory = new File(OUTPUT_DIR);
+ Util.flushDirectoryContent(outputDirectory);
+ String out = "bin";
+ String directory = OUTPUT_DIR + File.separator + "src";
+
+ String moduleLoc = directory + File.separator + "mod.one";
+ List<String> files = new ArrayList<>();
+ writeFileCollecting(files, moduleLoc, "module-info.java",
+ "module mod.one { \n" +
+ " exports p1.p2;\n" +
+ "}");
+ writeFileCollecting(files, moduleLoc + File.separator + "p1" + File.separator + "p2", "t3.java",
+ "package p1.p2;\n" +
+ "public class t3 {\n" +
+ "}\n");
+
+ moduleLoc = directory + File.separator + "mod.two";
+ writeFileCollecting(files, moduleLoc, "module-info.java",
+ "module mod.two { \n" +
+ " exports p1.p2.t3;\n" +
+ " requires mod.one;\n" +
+ "}");
+ writeFileCollecting(files, moduleLoc + File.separator + "p1" + File.separator + "p2" + File.separator + "t3", "t4.java",
+ "package p1.p2.t3;\n" +
+ "public class t4 {\n" +
+ "}\n");
+
+ StringBuffer buffer = new StringBuffer();
+ buffer.append("-d " + OUTPUT_DIR + File.separator + out )
+ .append(" -9 ")
+ .append(" -classpath \"")
+ .append(Util.getJavaClassLibsAsString())
+ .append("\" ")
+ .append(" --module-source-path " + "\"" + directory + "\"");
+
+ runNegativeModuleTest(
+ files,
+ buffer,
+ "",
+ "----------\n" +
+ "1. ERROR in ---OUTPUT_DIR_PLACEHOLDER---/src/mod.two/p1/p2/t3/t4.java (at line 1)\n" +
+ " package p1.p2.t3;\n" +
+ " ^^^^^^^^\n" +
+ "The package p1.p2.t3 collides with a type\n" +
+ "----------\n" +
+ "1 problem (1 error)\n",
+ false,
+ "package p1.p2.t3 clashes with class of same name");
+ }
}
diff --git a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/PackageBindingTest.java b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/PackageBindingTest.java
index b8e7a88340..61a6e061d9 100644
--- a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/PackageBindingTest.java
+++ b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/PackageBindingTest.java
@@ -20,6 +20,7 @@ import org.eclipse.jdt.internal.compiler.impl.CompilerOptions;
import org.eclipse.jdt.internal.compiler.lookup.Binding;
import org.eclipse.jdt.internal.compiler.lookup.LookupEnvironment;
import org.eclipse.jdt.internal.compiler.lookup.PackageBinding;
+import org.eclipse.jdt.internal.compiler.lookup.PlainPackageBinding;
import org.eclipse.jdt.internal.core.INameEnvironmentWithProgress;
public class PackageBindingTest extends AbstractCompilerTest
@@ -36,7 +37,7 @@ public class PackageBindingTest extends AbstractCompilerTest
public void _test01() {
NameEnvironmentDummy nameEnv = new NameEnvironmentDummy(true);
- PackageBinding packageBinding = new PackageBinding(new LookupEnvironment(null, new CompilerOptions(), null, nameEnv));
+ PlainPackageBinding packageBinding = new PlainPackageBinding(new LookupEnvironment(null, new CompilerOptions(), null, nameEnv));
Binding resultBinding = packageBinding.getTypeOrPackage("java.lang".toCharArray(), null, false);
assertNotNull(resultBinding);
@@ -53,7 +54,7 @@ public class PackageBindingTest extends AbstractCompilerTest
NameEnvironmentDummy nameEnv = new NameEnvironmentDummy(false);
LookupEnvironment environment = new LookupEnvironment(null, new CompilerOptions(), null, nameEnv);
- PackageBinding packageBinding = new PackageBinding(environment);
+ PlainPackageBinding packageBinding = new PlainPackageBinding(environment);
Binding resultBinding = packageBinding.getTypeOrPackage("java.lang.String".toCharArray(), environment.module, false);
assertNull(resultBinding); // (not implemented)
diff --git a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/ModuleBuilderTests.java b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/ModuleBuilderTests.java
index 5b8459fd96..897233965f 100644
--- a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/ModuleBuilderTests.java
+++ b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/ModuleBuilderTests.java
@@ -4238,8 +4238,8 @@ public class ModuleBuilderTests extends ModifyingResourceTests {
getWorkspace().build(IncrementalProjectBuilder.FULL_BUILD, null);
IMarker[] markers = p3.getProject().findMarkers(null, true, IResource.DEPTH_INFINITE);
assertMarkers("Unexpected markers",
- "The project was not built since its build path is incomplete. Cannot find the class file for org.astro.World. Fix the build path then try building this project\n" +
- "The type org.astro.World cannot be resolved. It is indirectly referenced from required .class files",
+ "Name of automatic module \'test\' is unstable, it is derived from the module\'s file name.\n" +
+ "The type org.astro.World is not accessible",
markers);
} finally {
this.deleteProject("test");
@@ -8704,6 +8704,80 @@ public class ModuleBuilderTests extends ModifyingResourceTests {
deleteProject(prjB);
}
}
+ public void testBug547181() throws CoreException {
+ IJavaProject prjA = createJava9Project("A");
+ IJavaProject prjB = createJava9Project("B");
+ IJavaProject prjC = createJava9Project("C");
+ IJavaProject prjD = createJava9Project("D");
+ try {
+ createFile("A/src/module-info.java",
+ "module A {\n" +
+ " exports p1.p2;\n" +
+ "}\n");
+ createFolder("A/src/p1/p2");
+ createFile("A/src/p1/p2/X.java",
+ "package p1.p2;\n" +
+ "public class X {\n" +
+ "}\n");
+
+ addModularProjectEntry(prjB, prjA);
+ addModularProjectEntry(prjD, prjA);
+ addModularProjectEntry(prjD, prjB);
+ addModularProjectEntry(prjD, prjC);
+
+ createFile("B/src/module-info.java",
+ "module B {\n" +
+ " requires A;\n" +
+ " exports p1;\n" +
+ "}\n");
+ createFolder("B/src/p1");
+ createFile("B/src/p1/Y.java",
+ "package p1;\n" +
+ "import p1.p2.X;\n" +
+ "public class Y {\n" +
+ " private void f(X x) {}\n" +
+ "}\n");
+
+ createFile("C/src/module-info.java",
+ "module C {\n" +
+ " exports p1.p2;\n" +
+ "}\n");
+ createFolder("C/src/p1/p2");
+ createFile("C/src/p1/p2/X.java",
+ "package p1.p2;\n" +
+ "public class X {\n" +
+ "}\n");
+
+ createFile("D/src/module-info.java",
+ "module D {\n" +
+ " requires B;\n" +
+ " requires C;\n" +
+ "}\n");
+
+ createFolder("D/src/usage");
+ createFile("D/src/usage/AAA.java",
+ "package usage;\n" +
+ "import p1.Y;\n" +
+ "public class AAA {\n" +
+ " Y y;\n" +
+ "}\n");
+ createFile("D/src/usage/Usage.java",
+ "package usage;\n" +
+ "import p1.p2.X;\n" +
+ "public class Usage {\n" +
+ " X x;\n" +
+ "}\n");
+
+ getWorkspace().build(IncrementalProjectBuilder.FULL_BUILD, null);
+ assertNoErrors();
+
+ } finally {
+ deleteProject(prjA);
+ deleteProject(prjB);
+ deleteProject(prjC);
+ deleteProject(prjD);
+ }
+ }
protected void assertNoErrors() throws CoreException {
for (IProject p : getWorkspace().getRoot().getProjects()) {
int maxSeverity = p.findMaxProblemSeverity(null, true, IResource.DEPTH_INFINITE);
diff --git a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/ReconcilerTests9.java b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/ReconcilerTests9.java
index 2a2db521a0..25fff8343f 100644
--- a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/ReconcilerTests9.java
+++ b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/ReconcilerTests9.java
@@ -851,4 +851,97 @@ public void testBug544306() throws Exception {
deleteProject(p2);
}
}
+public void testBug547113() throws CoreException {
+ IJavaProject unnamed = createJava9Project("unnamed");
+ IJavaProject a = createJava9Project("a");
+ IJavaProject b = createJava9Project("b");
+ IJavaProject c = createJava9Project("c");
+ try {
+ createFolder("a/src/com/example/a");
+ createFile("a/src/com/example/Base.java",
+ "package com.example;\n" +
+ "\n" +
+ "public class Base {}\n");
+ createFile("a/src/com/example/a/A.java",
+ "package com.example.a;\n" +
+ "\n" +
+ "public class A {}\n");
+ createFile("a/src/module-info.java",
+ "open module com.example.a {\n" +
+ " exports com.example;\n" +
+ " exports com.example.a;\n" +
+ " \n" +
+ " requires unnamed;\n" +
+ "}\n");
+ addModularProjectEntry(a, unnamed);
+
+ createFolder("b/src/com/example/b");
+ createFile("b/src/com/example/b/B.java",
+ "package com.example.b;\n" +
+ "\n" +
+ "import com.example.Base;\n" +
+ "import com.example.a.A;\n" +
+ "\n" +
+ "public class B {\n" +
+ "\n" +
+ " public void a(A a) {\n" +
+ " System.out.println(a);\n" +
+ " }\n" +
+ "\n" +
+ " public void base(Base base) {\n" +
+ " System.out.println(base);\n" +
+ " }\n" +
+ "\n" +
+ "}\n");
+ createFile("b/src/module-info.java",
+ "open module com.example.b {\n" +
+ " exports com.example.b;\n" +
+ " requires transitive com.example.a;\n" +
+ "}\n");
+ addModularProjectEntry(b, a);
+ addModularProjectEntry(b, unnamed);
+
+ createFolder("c/src/com/example/c");
+ String cSource = "package com.example.c;\n" +
+ "\n" +
+ "import com.example.Base;\n" +
+ "import com.example.a.A;\n" +
+ "import com.example.b.B;\n" +
+ "\n" +
+ "public class C {\n" +
+ "\n" +
+ " public static void main(String[] args) {\n" +
+ " new B().a(new A());\n" +
+ " new B().base(new Base());\n" +
+ " System.out.println(\"done.\");\n" +
+ " }\n" +
+ "}\n";
+ createFile("c/src/com/example/c/C.java", cSource);
+ createFile("c/src/module-info.java",
+ "open module com.example.c {\n" +
+ " exports com.example.c;\n" +
+ " requires com.example.b;\n" +
+ "}\n");
+ addModularProjectEntry(c, a);
+ addModularProjectEntry(c, b);
+ addModularProjectEntry(c, unnamed);
+
+ waitForAutoBuild();
+
+ this.workingCopy.discardWorkingCopy();
+ this.problemRequestor.initialize(cSource.toCharArray());
+ this.workingCopy = getCompilationUnit("c/src/com/example/c/C.java").getWorkingCopy(this.wcOwner, null);
+ this.problemRequestor.initialize(this.workingCopy.getSource().toCharArray());
+ this.workingCopy.reconcile(AST_INTERNAL_JLS11, true, this.wcOwner, null);
+ assertProblems("Expecting no problems",
+ "----------\n" +
+ "----------\n",
+ this.problemRequestor);
+ } finally {
+ deleteProject(unnamed);
+ deleteProject(a);
+ deleteProject(b);
+ deleteProject(c);
+ }
+}
}
diff --git a/org.eclipse.jdt.core/batch/org/eclipse/jdt/internal/compiler/batch/ClasspathDirectory.java b/org.eclipse.jdt.core/batch/org/eclipse/jdt/internal/compiler/batch/ClasspathDirectory.java
index afeb890b2e..0d14e13c06 100644
--- a/org.eclipse.jdt.core/batch/org/eclipse/jdt/internal/compiler/batch/ClasspathDirectory.java
+++ b/org.eclipse.jdt.core/batch/org/eclipse/jdt/internal/compiler/batch/ClasspathDirectory.java
@@ -39,6 +39,13 @@ import org.eclipse.jdt.internal.compiler.util.Util;
import java.io.File;
import java.io.FilenameFilter;
import java.io.IOException;
+import java.nio.file.FileSystems;
+import java.nio.file.FileVisitResult;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.SimpleFileVisitor;
+import java.nio.file.attribute.BasicFileAttributes;
+import java.util.HashSet;
import java.util.Hashtable;
import java.util.List;
import java.util.Map;
@@ -329,6 +336,27 @@ public boolean hasCUDeclaringPackage(String qualifiedPackageName, Function<Compi
return hasDeclaration;
});
}
+
+@Override
+public char[][] listPackages() {
+ Set<String> packageNames = new HashSet<>();
+ try {
+ Path basePath = FileSystems.getDefault().getPath(this.path);
+ Files.walkFileTree(basePath, new SimpleFileVisitor<Path>() {
+ @Override
+ public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) {
+ if (file.toString().toLowerCase().endsWith(SUFFIX_STRING_class)) {
+ packageNames.add(file.getParent().relativize(basePath).toString().replace('/', '.'));
+ }
+ return FileVisitResult.CONTINUE;
+ }
+ });
+ } catch (IOException e) {
+ // treat as if files are missing
+ }
+ return packageNames.stream().map(String::toCharArray).toArray(char[][]::new);
+}
+
@Override
public void reset() {
super.reset();
diff --git a/org.eclipse.jdt.core/batch/org/eclipse/jdt/internal/compiler/batch/ClasspathJar.java b/org.eclipse.jdt.core/batch/org/eclipse/jdt/internal/compiler/batch/ClasspathJar.java
index cb607ad7d5..93d48e6ff4 100644
--- a/org.eclipse.jdt.core/batch/org/eclipse/jdt/internal/compiler/batch/ClasspathJar.java
+++ b/org.eclipse.jdt.core/batch/org/eclipse/jdt/internal/compiler/batch/ClasspathJar.java
@@ -260,6 +260,19 @@ public boolean hasCompilationUnit(String qualifiedPackageName, String moduleName
}
return false;
}
+
+@Override
+public char[][] listPackages() {
+ Set<String> packageNames = new HashSet<>();
+ for (Enumeration<? extends ZipEntry> e = this.zipFile.entries(); e.hasMoreElements(); ) {
+ String fileName = e.nextElement().getName();
+ int lastSlash = fileName.lastIndexOf('/');
+ if (lastSlash != -1 && fileName.toLowerCase().endsWith(SUFFIX_STRING_class))
+ packageNames.add(fileName.substring(0, lastSlash).replace('/', '.'));
+ }
+ return packageNames.stream().map(String::toCharArray).toArray(char[][]::new);
+}
+
@Override
public void reset() {
super.reset();
diff --git a/org.eclipse.jdt.core/batch/org/eclipse/jdt/internal/compiler/batch/FileSystem.java b/org.eclipse.jdt.core/batch/org/eclipse/jdt/internal/compiler/batch/FileSystem.java
index 7a08126d5b..7828c82a9c 100644
--- a/org.eclipse.jdt.core/batch/org/eclipse/jdt/internal/compiler/batch/FileSystem.java
+++ b/org.eclipse.jdt.core/batch/org/eclipse/jdt/internal/compiler/batch/FileSystem.java
@@ -19,6 +19,7 @@ import java.io.File;
import java.io.IOException;
import java.nio.file.InvalidPathException;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
@@ -168,6 +169,9 @@ public class FileSystem implements IModuleAwareNameEnvironment, SuffixConstants
/** Tasks resulting from --add-reads or --add-exports command line options. */
Map<String,UpdatesByKind> moduleUpdates = new HashMap<>();
+
+ private boolean hasLimitModules = false;
+
static final boolean isJRE12Plus;
static {
isJRE12Plus = CompilerOptions.VERSION_12.equals(System.getProperty("java.specification.version")); //$NON-NLS-1$
@@ -184,6 +188,7 @@ protected FileSystem(String[] classpathNames, String[] initialFileNames, String
final int classpathSize = classpathNames.length;
this.classpaths = new Classpath[classpathSize];
int counter = 0;
+ this.hasLimitModules = limitModules != null && !limitModules.isEmpty();
for (int i = 0; i < classpathSize; i++) {
Classpath classpath = getClasspath(classpathNames[i], encoding, null, null, null);
try {
@@ -204,6 +209,7 @@ protected FileSystem(Classpath[] paths, String[] initialFileNames, boolean annot
final int length = paths.length;
int counter = 0;
this.classpaths = new FileSystem.Classpath[length];
+ this.hasLimitModules = limitedModules != null && !limitedModules.isEmpty();
for (int i = 0; i < length; i++) {
final Classpath classpath = paths[i];
try {
@@ -558,8 +564,8 @@ public NameEnvironmentAnswer findType(char[] typeName, char[][] packageName, cha
}
@Override
-public char[][] getModulesDeclaringPackage(char[][] parentPackageName, char[] packageName, char[] moduleName) {
- String qualifiedPackageName = new String(CharOperation.concatWith(parentPackageName, packageName, '/'));
+public char[][] getModulesDeclaringPackage(char[][] packageName, char[] moduleName) {
+ String qualifiedPackageName = new String(CharOperation.concatWith(packageName, '/'));
String moduleNameString = String.valueOf(moduleName);
LookupStrategy strategy = LookupStrategy.get(moduleName);
@@ -576,6 +582,7 @@ public char[][] getModulesDeclaringPackage(char[][] parentPackageName, char[] pa
}
// search the entire environment and answer which modules declare that package:
char[][] allNames = null;
+ boolean hasUnobserable = false;
for (Classpath cp : this.classpaths) {
if (strategy.matches(cp, Classpath::hasModule)) {
if (strategy == LookupStrategy.Unnamed) {
@@ -585,6 +592,10 @@ public char[][] getModulesDeclaringPackage(char[][] parentPackageName, char[] pa
} else {
char[][] declaringModules = cp.getModulesDeclaringPackage(qualifiedPackageName, null);
if (declaringModules != null) {
+ if (cp instanceof ClasspathJrt && this.hasLimitModules) {
+ declaringModules = filterModules(declaringModules);
+ hasUnobserable |= declaringModules == null;
+ }
if (allNames == null)
allNames = declaringModules;
else
@@ -593,8 +604,16 @@ public char[][] getModulesDeclaringPackage(char[][] parentPackageName, char[] pa
}
}
}
+ if (allNames == null && hasUnobserable)
+ return new char[][] { ModuleBinding.UNOBSERVABLE };
return allNames;
}
+private char[][] filterModules(char[][] declaringModules) {
+ char[][] filtered = Arrays.stream(declaringModules).filter(m -> this.moduleLocations.containsKey(new String(m))).toArray(char[][]::new);
+ if (filtered.length == 0)
+ return null;
+ return filtered;
+}
private Parser getParser() {
Map<String,String> opts = new HashMap<String, String>();
opts.put(CompilerOptions.OPTION_Source, CompilerOptions.VERSION_9);
@@ -676,6 +695,19 @@ public char[][] getAllAutomaticModules() {
return set.toArray(new char[set.size()][]);
}
+@Override
+public char[][] listPackages(char[] moduleName) {
+ switch (LookupStrategy.get(moduleName)) {
+ case Named:
+ Classpath classpath = this.moduleLocations.get(new String(moduleName));
+ if (classpath != null)
+ return classpath.listPackages();
+ return CharOperation.NO_CHAR_CHAR;
+ default:
+ throw new UnsupportedOperationException("can list packages only of a named module"); //$NON-NLS-1$
+ }
+}
+
void addModuleUpdate(String moduleName, Consumer<IUpdatableModule> update, UpdateKind kind) {
UpdatesByKind updates = this.moduleUpdates.get(moduleName);
if (updates == null) {
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ModuleDeclaration.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ModuleDeclaration.java
index 0b189519c1..ff81ca577f 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ModuleDeclaration.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ModuleDeclaration.java
@@ -37,10 +37,9 @@ import org.eclipse.jdt.internal.compiler.lookup.ExtraCompilerModifiers;
import org.eclipse.jdt.internal.compiler.lookup.LookupEnvironment;
import org.eclipse.jdt.internal.compiler.lookup.MethodScope;
import org.eclipse.jdt.internal.compiler.lookup.ModuleBinding;
-import org.eclipse.jdt.internal.compiler.lookup.PackageBinding;
+import org.eclipse.jdt.internal.compiler.lookup.PlainPackageBinding;
import org.eclipse.jdt.internal.compiler.lookup.Scope;
import org.eclipse.jdt.internal.compiler.lookup.SourceModuleBinding;
-import org.eclipse.jdt.internal.compiler.lookup.SplitPackageBinding;
import org.eclipse.jdt.internal.compiler.lookup.TypeBinding;
import org.eclipse.jdt.internal.compiler.problem.AbortCompilation;
import org.eclipse.jdt.internal.compiler.problem.AbortCompilationUnit;
@@ -195,7 +194,7 @@ public class ModuleDeclaration extends ASTNode implements ReferenceContext {
this.hasResolvedPackageDirectives = true;
- Set<PackageBinding> exportedPkgs = new HashSet<>();
+ Set<PlainPackageBinding> exportedPkgs = new HashSet<>();
for (int i = 0; i < this.exportsCount; i++) {
ExportsStatement ref = this.exports[i];
if (ref != null && ref.resolve(cuScope)) {
@@ -283,16 +282,21 @@ public class ModuleDeclaration extends ASTNode implements ReferenceContext {
private void analyseReferencedPackages(CompilationUnitScope skope) {
if (this.exports != null) {
- for (ExportsStatement export : this.exports) {
- PackageBinding pb = export.resolvedPackage;
- if (pb == null)
- continue;
- if (pb instanceof SplitPackageBinding)
- pb = ((SplitPackageBinding) pb).getIncarnation(this.binding);
- if (pb.hasCompilationUnit(true))
- continue;
- skope.problemReporter().invalidPackageReference(IProblem.PackageDoesNotExistOrIsEmpty, export);
- }
+ analyseSomeReferencedPackages(this.exports, skope);
+ }
+ if (this.opens != null) {
+ analyseSomeReferencedPackages(this.opens, skope);
+ }
+ }
+
+ private void analyseSomeReferencedPackages(PackageVisibilityStatement[] stats, CompilationUnitScope skope) {
+ for (PackageVisibilityStatement stat : stats) {
+ PlainPackageBinding pb = stat.resolvedPackage;
+ if (pb == null)
+ continue;
+ if (pb.hasCompilationUnit(true))
+ continue;
+ skope.problemReporter().invalidPackageReference(IProblem.PackageDoesNotExistOrIsEmpty, stat);
}
}
@@ -301,8 +305,7 @@ public class ModuleDeclaration extends ASTNode implements ReferenceContext {
// collect transitively:
Map<String, Set<ModuleBinding>> pack2mods = new HashMap<>();
for (ModuleBinding requiredModule : this.binding.getAllRequiredModules()) {
- for (PackageBinding exportedPackage : requiredModule.getExports()) {
- exportedPackage = exportedPackage.getVisibleFor(requiredModule, true);
+ for (PlainPackageBinding exportedPackage : requiredModule.getExports()) {
if (this.binding.canAccess(exportedPackage)) {
String packName = String.valueOf(exportedPackage.readableName());
Set<ModuleBinding> mods = pack2mods.get(packName);
@@ -331,7 +334,7 @@ public class ModuleDeclaration extends ASTNode implements ReferenceContext {
private void analyseOneDependency(RequiresStatement requiresStat, ModuleBinding requiredModule, CompilationUnitScope skope,
Map<String, Set<ModuleBinding>> pack2mods)
{
- for (PackageBinding pack : requiredModule.getExports()) {
+ for (PlainPackageBinding pack : requiredModule.getExports()) {
Set<ModuleBinding> mods = pack2mods.get(String.valueOf(pack.readableName()));
if (mods != null && mods.size() > 1) {
CompilerOptions compilerOptions = skope.compilerOptions();
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/OpensStatement.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/OpensStatement.java
index 0565524a34..e1da2b772b 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/OpensStatement.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/OpensStatement.java
@@ -13,6 +13,7 @@
*******************************************************************************/
package org.eclipse.jdt.internal.compiler.ast;
+import org.eclipse.jdt.core.compiler.IProblem;
import org.eclipse.jdt.internal.compiler.problem.ProblemSeverities;
public class OpensStatement extends PackageVisibilityStatement {
@@ -24,8 +25,13 @@ public class OpensStatement extends PackageVisibilityStatement {
super(pkgRef, targets);
}
@Override
- protected int computeSeverity(int problemId) {
- return ProblemSeverities.Warning;
+ public int computeSeverity(int problemId) {
+ switch (problemId) {
+ case IProblem.PackageDoesNotExistOrIsEmpty:
+ return ProblemSeverities.Warning;
+ default:
+ return ProblemSeverities.Error;
+ }
}
@Override
public StringBuffer print(int indent, StringBuffer output) {
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/PackageVisibilityStatement.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/PackageVisibilityStatement.java
index f5e7470035..b4bdbf8364 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/PackageVisibilityStatement.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/PackageVisibilityStatement.java
@@ -17,7 +17,7 @@ package org.eclipse.jdt.internal.compiler.ast;
import org.eclipse.jdt.core.compiler.CharOperation;
import org.eclipse.jdt.core.compiler.IProblem;
import org.eclipse.jdt.internal.compiler.lookup.ModuleBinding;
-import org.eclipse.jdt.internal.compiler.lookup.PackageBinding;
+import org.eclipse.jdt.internal.compiler.lookup.PlainPackageBinding;
import org.eclipse.jdt.internal.compiler.lookup.Scope;
import org.eclipse.jdt.internal.compiler.problem.ProblemSeverities;
import org.eclipse.jdt.internal.compiler.util.HashtableOfObject;
@@ -26,7 +26,7 @@ public abstract class PackageVisibilityStatement extends ModuleStatement {
public ImportReference pkgRef;
public ModuleReference[] targets;
public char[] pkgName;
- public PackageBinding resolvedPackage;
+ public PlainPackageBinding resolvedPackage;
public PackageVisibilityStatement(ImportReference pkgRef, ModuleReference[] targets) {
this.pkgRef = pkgRef;
@@ -58,27 +58,15 @@ public abstract class PackageVisibilityStatement extends ModuleStatement {
}
return !errorsExist;
}
- protected int computeSeverity(int problemId) {
+ public int computeSeverity(int problemId) {
return ProblemSeverities.Error;
}
- protected PackageBinding resolvePackageReference(Scope scope) {
+ protected PlainPackageBinding resolvePackageReference(Scope scope) {
if (this.resolvedPackage != null)
return this.resolvedPackage;
ModuleDeclaration exportingModule = scope.compilationUnitScope().referenceContext.moduleDeclaration;
ModuleBinding src = exportingModule.binding;
- this.resolvedPackage = src != null ? src.getVisiblePackage(this.pkgRef.tokens) : null;
- int problemId = IProblem.PackageDoesNotExistOrIsEmpty;
- if (this.resolvedPackage == null) {
- // TODO: need a check for empty package as well
- scope.problemReporter().invalidPackageReference(problemId, this, computeSeverity(problemId));
- } else {
- if (!this.resolvedPackage.isDeclaredIn(src)) {
- this.resolvedPackage = null;
- // TODO(SHMOD): specific error?
- scope.problemReporter().invalidPackageReference(problemId, this, computeSeverity(problemId));
- }
- }
-
+ this.resolvedPackage = src != null ? src.getOrCreateDeclaredPackage(this.pkgRef.tokens) : null;
return this.resolvedPackage;
}
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/QualifiedNameReference.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/QualifiedNameReference.java
index e9d9103f26..cec0657f7c 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/QualifiedNameReference.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/QualifiedNameReference.java
@@ -1000,7 +1000,12 @@ public StringBuffer printExpression(int indent, StringBuffer output) {
* Normal field binding did not work, try to bind to a field of the delegate receiver.
*/
public TypeBinding reportError(BlockScope scope) {
- if (this.binding instanceof ProblemFieldBinding) {
+ Binding inaccessible = scope.environment().getInaccessibleBinding(this.tokens, scope.module());
+ if (inaccessible instanceof TypeBinding) {
+ this.indexOfFirstFieldBinding = -1;
+ this.binding = inaccessible;
+ scope.problemReporter().invalidType(this, (TypeBinding) this.binding);
+ } else if (this.binding instanceof ProblemFieldBinding) {
scope.problemReporter().invalidField(this, (FieldBinding) this.binding);
} else if (this.binding instanceof ProblemReferenceBinding || this.binding instanceof MissingTypeBinding) {
scope.problemReporter().invalidType(this, (TypeBinding) this.binding);
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/QualifiedTypeReference.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/QualifiedTypeReference.java
index 8178dec1f9..8a6cb02b57 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/QualifiedTypeReference.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/QualifiedTypeReference.java
@@ -124,7 +124,7 @@ public class QualifiedTypeReference extends TypeReference {
int typeStart = packageBinding == null ? 0 : packageBinding.compoundName.length;
if (packageBinding != null) {
- PackageBinding uniquePackage = packageBinding.getVisibleFor(scope.module(), false);
+ PackageBinding uniquePackage = packageBinding.getVisibleFor(scope.module(), false, false);
if (uniquePackage instanceof SplitPackageBinding) {
CompilerOptions compilerOptions = scope.compilerOptions();
boolean inJdtDebugCompileMode = compilerOptions.enableJdtDebugCompileMode;
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/env/IModuleAwareNameEnvironment.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/env/IModuleAwareNameEnvironment.java
index b7b81f466a..539caaba7c 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/env/IModuleAwareNameEnvironment.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/env/IModuleAwareNameEnvironment.java
@@ -15,6 +15,7 @@ package org.eclipse.jdt.internal.compiler.env;
import java.util.function.Predicate;
+import org.eclipse.jdt.core.compiler.CharOperation;
import org.eclipse.jdt.internal.compiler.lookup.ModuleBinding;
import org.eclipse.jdt.internal.compiler.util.SimpleSetOfCharArray;
@@ -101,15 +102,15 @@ public interface IModuleAwareNameEnvironment extends INameEnvironment {
}
@Override
default boolean isPackage(char[][] parentPackageName, char[] packageName) {
- return getModulesDeclaringPackage(parentPackageName, packageName, ModuleBinding.ANY) != null;
+ return getModulesDeclaringPackage(CharOperation.arrayConcat(parentPackageName, packageName), ModuleBinding.ANY) != null;
}
NameEnvironmentAnswer findType(char[][] compoundName, char[] moduleName);
/** Answer a type identified by the given names. moduleName may be one of the special names from ModuleBinding (ANY, ANY_NAMED, UNNAMED). */
NameEnvironmentAnswer findType(char[] typeName, char[][] packageName, char[] moduleName);
- char[][] getModulesDeclaringPackage(char[][] parentPackageName, char[] name, char[] moduleName);
- default char[][] getUniqueModulesDeclaringPackage(char[][] parentPackageName, char[] name, char[] moduleName) {
- char[][] allNames = getModulesDeclaringPackage(parentPackageName, name, moduleName);
+ char[][] getModulesDeclaringPackage(char[][] packageName, char[] moduleName);
+ default char[][] getUniqueModulesDeclaringPackage(char[][] packageName, char[] moduleName) {
+ char[][] allNames = getModulesDeclaringPackage(packageName, moduleName);
if (allNames != null && allNames.length > 1) {
SimpleSetOfCharArray set = new SimpleSetOfCharArray(allNames.length);
for (char[] oneName : allNames)
@@ -139,4 +140,12 @@ public interface IModuleAwareNameEnvironment extends INameEnvironment {
* @param kind selects what kind of updates should be performed
*/
default void applyModuleUpdates(IUpdatableModule module, IUpdatableModule.UpdateKind kind) { /* default: do nothing */ }
+
+ /**
+ * Lists all packages in the module identified by the given, real module name
+ * (i.e., this method is implemented only for {@link LookupStrategy#Named}).
+ * @param moduleName
+ * @return array of flat, dot-separated package names
+ */
+ char[][] listPackages(char[] moduleName);
}
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/env/IModulePathEntry.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/env/IModulePathEntry.java
index 562c1aef79..86f24f73a0 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/env/IModulePathEntry.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/env/IModulePathEntry.java
@@ -75,6 +75,14 @@ public interface IModulePathEntry {
boolean hasCompilationUnit(String qualifiedPackageName, String moduleName);
/**
+ * Lists all packages in this modulepath entry.
+ * @return array of flat, dot-separated package names
+ */
+ default char[][] listPackages() {
+ return CharOperation.NO_CHAR_CHAR;
+ }
+
+ /**
* Specifies whether this entry represents an automatic module.
*
* @return true if this is an automatic module, false otherwise
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/env/IUpdatableModule.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/env/IUpdatableModule.java
index 4082b28482..0704eefe9f 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/env/IUpdatableModule.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/env/IUpdatableModule.java
@@ -43,7 +43,6 @@ public interface IUpdatableModule {
}
@Override
public void accept(IUpdatableModule t) {
- // TODO Auto-generated method stub
t.addExports(this.name, this.targets);
}
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/impl/ITypeRequestor.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/impl/ITypeRequestor.java
index 248e0afd76..2ad85cd4c2 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/impl/ITypeRequestor.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/impl/ITypeRequestor.java
@@ -23,7 +23,6 @@ import org.eclipse.jdt.internal.compiler.env.ISourceType;
import org.eclipse.jdt.internal.compiler.lookup.BinaryModuleBinding;
import org.eclipse.jdt.internal.compiler.lookup.LookupEnvironment;
import org.eclipse.jdt.internal.compiler.lookup.PackageBinding;
-import org.eclipse.jdt.internal.compiler.problem.AbortCompilation;
public interface ITypeRequestor {
@@ -57,13 +56,9 @@ public interface ITypeRequestor {
*/
default void accept(IModule module, LookupEnvironment environment) {
if (module instanceof ISourceModule) {
- try {
- ICompilationUnit compilationUnit = ((ISourceModule) module).getCompilationUnit();
- if (compilationUnit != null) {
- accept(compilationUnit, null);
- }
- } catch (AbortCompilation abort) {
- // silent
+ ICompilationUnit compilationUnit = ((ISourceModule) module).getCompilationUnit();
+ if (compilationUnit != null) {
+ accept(compilationUnit, null);
}
} else {
// handles IBinaryModule and IModule.AutoModule:
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/BinaryModuleBinding.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/BinaryModuleBinding.java
index 080b8f8a89..5102e9ca15 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/BinaryModuleBinding.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/BinaryModuleBinding.java
@@ -32,6 +32,7 @@ public class BinaryModuleBinding extends ModuleBinding {
private static class AutomaticModuleBinding extends ModuleBinding {
boolean autoNameFromManifest;
+ boolean hasScannedPackages;
public AutomaticModuleBinding(IModule module, LookupEnvironment existingEnvironment) {
super(module.name(), existingEnvironment);
@@ -40,7 +41,8 @@ public class BinaryModuleBinding extends ModuleBinding {
this.autoNameFromManifest = module.isAutoNameFromManifest();
this.requires = Binding.NO_MODULES;
this.requiresTransitive = Binding.NO_MODULES;
- this.exportedPackages = Binding.NO_PACKAGES;
+ this.exportedPackages = Binding.NO_PLAIN_PACKAGES;
+ this.hasScannedPackages = false;
}
@Override
public boolean hasUnstableAutoName() {
@@ -58,6 +60,17 @@ public class BinaryModuleBinding extends ModuleBinding {
return this.requiresTransitive;
}
@Override
+ PlainPackageBinding getDeclaredPackage(char[] flatName) {
+ if (!this.hasScannedPackages) {
+ for (char[] packageName : (((IModuleAwareNameEnvironment)this.environment.nameEnvironment).listPackages(nameForCUCheck()))) {
+ getOrCreateDeclaredPackage(CharOperation.splitOn('.', packageName));
+ }
+ this.hasScannedPackages = true;
+ }
+ return this.declaredPackages.get(flatName);
+ }
+
+ @Override
public char[] nameForLookup() {
return ANY_NAMED;
}
@@ -155,73 +168,51 @@ public class BinaryModuleBinding extends ModuleBinding {
}
@Override
- public PackageBinding[] getExports() {
+ public PlainPackageBinding[] getExports() {
if (this.exportedPackages == null && this.unresolvedExports != null)
resolvePackages();
return super.getExports();
}
@Override
- public PackageBinding[] getOpens() {
+ public PlainPackageBinding[] getOpens() {
if (this.openedPackages == null && this.unresolvedOpens != null)
resolvePackages();
return super.getOpens();
}
private void resolvePackages() {
- this.exportedPackages = new PackageBinding[this.unresolvedExports.length];
+ this.exportedPackages = new PlainPackageBinding[this.unresolvedExports.length];
int count = 0;
for (int i = 0; i < this.unresolvedExports.length; i++) {
IPackageExport export = this.unresolvedExports[i];
- PackageBinding declaredPackage = forcedGetExportedPackage(CharOperation.splitOn('.', export.name()));
- if (declaredPackage != null) {
- this.exportedPackages[count++] = declaredPackage;
- if (declaredPackage instanceof SplitPackageBinding)
- declaredPackage = ((SplitPackageBinding) declaredPackage).getIncarnation(this);
- if (declaredPackage != null) {
- declaredPackage.isExported = Boolean.TRUE;
- recordExportRestrictions(declaredPackage, export.targets());
- }
- }
+ // when resolving "exports" in a binary module we simply assume the package must exist,
+ // since this has been checked already when compiling that module.
+ PlainPackageBinding declaredPackage = getOrCreateDeclaredPackage(CharOperation.splitOn('.', export.name()));
+ this.exportedPackages[count++] = declaredPackage;
+ declaredPackage.isExported = Boolean.TRUE;
+ recordExportRestrictions(declaredPackage, export.targets());
}
if (count < this.exportedPackages.length)
- System.arraycopy(this.exportedPackages, 0, this.exportedPackages = new PackageBinding[count], 0, count);
+ System.arraycopy(this.exportedPackages, 0, this.exportedPackages = new PlainPackageBinding[count], 0, count);
- this.openedPackages = new PackageBinding[this.unresolvedOpens.length];
+ this.openedPackages = new PlainPackageBinding[this.unresolvedOpens.length];
count = 0;
for (int i = 0; i < this.unresolvedOpens.length; i++) {
IPackageExport opens = this.unresolvedOpens[i];
- PackageBinding declaredPackage = getVisiblePackage(CharOperation.splitOn('.', opens.name()));
- if (declaredPackage != null) {
- this.openedPackages[count++] = declaredPackage;
- if (declaredPackage instanceof SplitPackageBinding)
- declaredPackage = ((SplitPackageBinding) declaredPackage).getIncarnation(this);
- if (declaredPackage != null) {
- recordOpensRestrictions(declaredPackage, opens.targets());
- }
- } else {
- // TODO(SHMOD): report incomplete module path?
- }
+ PlainPackageBinding declaredPackage = getOrCreateDeclaredPackage(CharOperation.splitOn('.', opens.name()));
+ this.openedPackages[count++] = declaredPackage;
+ recordOpensRestrictions(declaredPackage, opens.targets());
}
if (count < this.openedPackages.length)
- System.arraycopy(this.openedPackages, 0, this.openedPackages = new PackageBinding[count], 0, count);
+ System.arraycopy(this.openedPackages, 0, this.openedPackages = new PlainPackageBinding[count], 0, count);
}
-
- PackageBinding forcedGetExportedPackage(char[][] compoundName) {
- // when resolving "exports" in a binary module we simply assume the package must exist,
- // since this has been checked already when compiling that module.
- PackageBinding binding = getVisiblePackage(compoundName);
- if (binding != null)
- return binding;
- if (compoundName.length > 1) {
- PackageBinding parent = forcedGetExportedPackage(CharOperation.subarray(compoundName, 0, compoundName.length-1));
- binding = new PackageBinding(compoundName, parent, this.environment, this);
- parent.addPackage(binding, this);
- return binding;
- }
- binding = new PackageBinding(compoundName[0], this.environment, this);
- addPackage(binding, true);
- return binding;
+
+ @Override
+ PlainPackageBinding getDeclaredPackage(char[] flatName) {
+ getExports(); // triggers initialization of exported packages into declaredPackages
+ completeIfNeeded(UpdateKind.PACKAGE);
+ return super.getDeclaredPackage(flatName);
}
@Override
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/Binding.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/Binding.java
index 01703e059b..72394d2962 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/Binding.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/Binding.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2017 IBM Corporation and others.
+ * Copyright (c) 2000, 2010 IBM Corporation and others.
*
* This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
@@ -50,6 +50,7 @@ public abstract class Binding {
// Shared binding collections
public static final ModuleBinding[] NO_MODULES = new ModuleBinding[0];
public static final PackageBinding[] NO_PACKAGES = new PackageBinding[0];
+ public static final PlainPackageBinding[] NO_PLAIN_PACKAGES = new PlainPackageBinding[0];
public static final TypeBinding[] NO_TYPES = new TypeBinding[0];
public static final ReferenceBinding[] NO_REFERENCE_TYPES = new ReferenceBinding[0];
public static final TypeBinding[] NO_PARAMETERS = new TypeBinding[0];
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ClassScope.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ClassScope.java
index cdd7675932..7c579d457a 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ClassScope.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ClassScope.java
@@ -410,15 +410,9 @@ public class ClassScope extends Scope {
char[][] className = CharOperation.deepCopy(enclosingType.compoundName);
className[className.length - 1] =
CharOperation.concat(className[className.length - 1], this.referenceContext.name, '$');
- ReferenceBinding existingType = packageBinding.getType0(className[className.length - 1]);
- if (existingType != null) {
- if (existingType instanceof UnresolvedReferenceBinding) {
- // its possible that a BinaryType referenced the member type before its enclosing source type was built
- // so just replace the unresolved type with a new member type
- } else {
- // report the error against the parent - its still safe to answer the member type
- this.parent.problemReporter().duplicateNestedType(this.referenceContext);
- }
+ if (packageBinding.hasType0Any(className[className.length - 1])) {
+ // report the error against the parent - its still safe to answer the member type
+ this.parent.problemReporter().duplicateNestedType(this.referenceContext);
}
this.referenceContext.binding = new MemberTypeBinding(className, this, enclosingType);
}
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/CompilationUnitScope.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/CompilationUnitScope.java
index b42355e16d..e2bf18d278 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/CompilationUnitScope.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/CompilationUnitScope.java
@@ -30,6 +30,7 @@ import org.eclipse.jdt.core.compiler.CharOperation;
import org.eclipse.jdt.internal.compiler.ast.*;
import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
import org.eclipse.jdt.internal.compiler.env.AccessRestriction;
+import org.eclipse.jdt.internal.compiler.env.IUpdatableModule;
import org.eclipse.jdt.internal.compiler.impl.CompilerOptions;
import org.eclipse.jdt.internal.compiler.problem.ProblemReporter;
import org.eclipse.jdt.internal.compiler.util.*;
@@ -162,11 +163,8 @@ void buildTypeBindings(AccessRestriction accessRestriction) {
TypeDeclaration typeDecl = types[i];
if (this.environment.root.isProcessingAnnotations && this.environment.isMissingType(typeDecl.name))
throw new SourceTypeCollisionException(); // resolved a type ref before APT generated the type
- ReferenceBinding typeBinding = this.fPackage.getType0(typeDecl.name);
- if (Binding.isValid(typeBinding) && this.fPackage instanceof SplitPackageBinding && !this.environment.module.canAccess(typeBinding.fPackage))
- typeBinding = null;
recordSimpleReference(typeDecl.name); // needed to detect collision cases
- if (Binding.isValid(typeBinding) && !(typeBinding instanceof UnresolvedReferenceBinding)) {
+ if (this.fPackage.hasType0Any(typeDecl.name)) {
// if its an unresolved binding - its fixed up whenever its needed, see UnresolvedReferenceBinding.resolve()
if (this.environment.root.isProcessingAnnotations)
throw new SourceTypeCollisionException(); // resolved a type ref before APT generated the type
@@ -197,6 +195,12 @@ void buildTypeBindings(AccessRestriction accessRestriction) {
// shrink topLevelTypes... only happens if an error was reported
if (count != this.topLevelTypes.length)
System.arraycopy(this.topLevelTypes, 0, this.topLevelTypes = new SourceTypeBinding[count], 0, count);
+
+ if (this.referenceContext.moduleDeclaration != null) {
+ this.module().completeIfNeeded(IUpdatableModule.UpdateKind.MODULE);
+ this.referenceContext.moduleDeclaration.resolvePackageDirectives(this);
+ this.module().completeIfNeeded(IUpdatableModule.UpdateKind.PACKAGE);
+ }
}
void checkAndSetImports() {
// TODO(SHMOD): verify: this block moved here from buildTypeBindings.
@@ -428,7 +432,7 @@ void faultInImports() {
continue nextImport;
}
if (importBinding instanceof PackageBinding) {
- PackageBinding uniquePackage = ((PackageBinding)importBinding).getVisibleFor(module(), false);
+ PackageBinding uniquePackage = ((PackageBinding)importBinding).getVisibleFor(module(), false, false);
if (uniquePackage instanceof SplitPackageBinding && !inJdtDebugCompileMode) {
SplitPackageBinding splitPackage = (SplitPackageBinding) uniquePackage;
problemReporter().conflictingPackagesFromModules(splitPackage, module(), importReference.sourceStart, importReference.sourceEnd);
@@ -472,7 +476,7 @@ void faultInImports() {
// re-get to find a possible split package:
importedPackage = (PackageBinding) findImport(importedPackage.compoundName, false, true);
if (importedPackage != null)
- importedPackage = importedPackage.getVisibleFor(module(), true);
+ importedPackage = importedPackage.getVisibleFor(module(), true, false);
if (importedPackage instanceof SplitPackageBinding && !inJdtDebugCompileMode) {
SplitPackageBinding splitPackage = (SplitPackageBinding) importedPackage;
int sourceEnd = (int) importReference.sourcePositions[splitPackage.compoundName.length-1];
@@ -516,7 +520,6 @@ void faultInImports() {
public void faultInTypes() {
faultInImports();
if (this.referenceContext.moduleDeclaration != null) {
- this.referenceContext.moduleDeclaration.resolvePackageDirectives(this);
this.referenceContext.moduleDeclaration.resolveTypeDirectives(this);
} else if (this.referenceContext.currentPackage != null) {
this.referenceContext.currentPackage.checkPackageConflict(this);
@@ -554,7 +557,7 @@ private Binding findImport(char[][] compoundName, int length) {
break foundNothingOrType;
}
if (!(binding instanceof PackageBinding)) {
- PackageBinding visibleFor = packageBinding.getVisibleFor(module, false); // filter out empty parent-packages
+ PackageBinding visibleFor = packageBinding.getVisibleFor(module, false, false); // filter out empty parent-packages
if (visibleFor instanceof SplitPackageBinding)
return visibleFor;
break foundNothingOrType;
@@ -569,6 +572,11 @@ private Binding findImport(char[][] compoundName, int length) {
ReferenceBinding type;
if (binding == null) {
+ if (!module.isUnnamed()) {
+ Binding inaccessible = this.environment.getInaccessibleBinding(compoundName, module);
+ if (inaccessible != null)
+ return inaccessible;
+ }
if (compilerOptions().complianceLevel >= ClassFileConstants.JDK1_4)
return problemType(compoundName, i, null);
type = findType(compoundName[0], this.environment.defaultPackage, this.environment.defaultPackage);
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/LookupEnvironment.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/LookupEnvironment.java
index 426e30218c..46aba9e14c 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/LookupEnvironment.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/LookupEnvironment.java
@@ -162,7 +162,7 @@ public LookupEnvironment(ITypeRequestor typeRequestor, CompilerOptions globalOpt
this.typeRequestor = typeRequestor;
this.globalOptions = globalOptions;
this.problemReporter = problemReporter;
- this.defaultPackage = new PackageBinding(this); // assume the default package always exists
+ this.defaultPackage = new PlainPackageBinding(this); // assume the default package always exists
this.defaultImports = null;
this.nameEnvironment = nameEnvironment;
this.knownPackages = new HashtableOfPackage();
@@ -187,7 +187,7 @@ LookupEnvironment(LookupEnvironment rootEnv, ModuleBinding module) {
this.typeRequestor = rootEnv.typeRequestor;
this.globalOptions = rootEnv.globalOptions;
this.problemReporter = rootEnv.problemReporter;
- this.defaultPackage = new PackageBinding(this); // assume the default package always exists
+ this.defaultPackage = new PlainPackageBinding(this); // assume the default package always exists
this.defaultImports = null;
this.nameEnvironment = rootEnv.nameEnvironment;
this.knownPackages = new HashtableOfPackage();
@@ -316,8 +316,7 @@ ReferenceBinding askForType(PackageBinding packageBinding, char[] name, ModuleBi
if (answerModule != null) {
if (!answerPackage.isDeclaredIn(answerModule))
continue; // this answer is not reachable via the packageBinding
- if (answerPackage instanceof SplitPackageBinding)
- answerPackage = ((SplitPackageBinding) answerPackage).getIncarnation(answerModule);
+ answerPackage = answerPackage.getIncarnation(answerModule);
}
if (answer.isResolvedBinding()) {
candidate = combine(candidate, answer.getResolvedBinding(), clientModule);
@@ -741,7 +740,7 @@ private PackageBinding computePackageFrom(char[][] constantPoolName, boolean isM
if (packageBinding == null || packageBinding == TheNotFoundPackage) {
if (this.useModuleSystem) {
if (this.module.isUnnamed()) {
- char[][] declaringModules = ((IModuleAwareNameEnvironment) this.nameEnvironment).getUniqueModulesDeclaringPackage(null, constantPoolName[0], ModuleBinding.ANY);
+ char[][] declaringModules = ((IModuleAwareNameEnvironment) this.nameEnvironment).getUniqueModulesDeclaringPackage(new char[][] {constantPoolName[0]}, ModuleBinding.ANY);
if (declaringModules != null) {
for (char[] mod : declaringModules) {
ModuleBinding declaringModule = this.root.getModule(mod);
@@ -754,7 +753,7 @@ private PackageBinding computePackageFrom(char[][] constantPoolName, boolean isM
}
}
if (packageBinding == null || packageBinding == TheNotFoundPackage) {
- packageBinding = new PackageBinding(constantPoolName[0], this, this.module);
+ packageBinding = new PlainPackageBinding(constantPoolName[0], this, this.module);
}
if (isMissing) packageBinding.tagBits |= TagBits.HasMissingType;
this.knownPackages.put(constantPoolName[0], packageBinding); // TODO: split?
@@ -765,7 +764,8 @@ private PackageBinding computePackageFrom(char[][] constantPoolName, boolean isM
if ((packageBinding = parent.getPackage0(constantPoolName[i])) == null || packageBinding == TheNotFoundPackage) {
if (this.useModuleSystem) {
if (this.module.isUnnamed()) {
- char[][] declaringModules = ((IModuleAwareNameEnvironment) this.nameEnvironment).getModulesDeclaringPackage(parent.compoundName, constantPoolName[i], ModuleBinding.ANY);
+ char[][] declaringModules = ((IModuleAwareNameEnvironment) this.nameEnvironment).getModulesDeclaringPackage(
+ CharOperation.arrayConcat(parent.compoundName, constantPoolName[i]), ModuleBinding.ANY);
if (declaringModules != null) {
for (char[] mod : declaringModules) {
ModuleBinding declaringModule = this.root.getModule(mod);
@@ -778,7 +778,7 @@ private PackageBinding computePackageFrom(char[][] constantPoolName, boolean isM
}
}
if (packageBinding == null || packageBinding == TheNotFoundPackage) {
- packageBinding = new PackageBinding(CharOperation.subarray(constantPoolName, 0, i + 1), parent, this, this.module);
+ packageBinding = new PlainPackageBinding(CharOperation.subarray(constantPoolName, 0, i + 1), parent, this, this.module);
}
if (isMissing) {
packageBinding.tagBits |= TagBits.HasMissingType;
@@ -1086,13 +1086,19 @@ public MissingTypeBinding createMissingType(PackageBinding packageBinding, char[
* 3. Create the method bindings
*/
public PackageBinding createPackage(char[][] compoundName) {
- PackageBinding packageBinding = getPackage0(compoundName[0]);
- if (packageBinding == null || packageBinding == TheNotFoundPackage) {
- packageBinding = new PackageBinding(compoundName[0], this, this.module);
- this.knownPackages.put(compoundName[0], packageBinding);
- if (this.module != null) {
- packageBinding = this.module.addPackage(packageBinding, true);
- this.knownPackages.put(compoundName[0], packageBinding); // update in case of split package
+ PackageBinding packageBinding = this.module.getDeclaredPackage(CharOperation.concatWith(compoundName, '.'));
+ if (packageBinding != null && packageBinding.isValidBinding()) {
+ // restart from the toplevel package to proceed with clash analysis below
+ packageBinding = this.getTopLevelPackage(compoundName[0]);
+ } else {
+ packageBinding = getPackage0(compoundName[0]);
+ if (packageBinding == null || packageBinding == TheNotFoundPackage) {
+ packageBinding = new PlainPackageBinding(compoundName[0], this, this.module);
+ this.knownPackages.put(compoundName[0], packageBinding);
+ if (this.module != null) {
+ packageBinding = this.module.addPackage(packageBinding, true);
+ this.knownPackages.put(compoundName[0], packageBinding); // update in case of split package
+ }
}
}
@@ -1103,8 +1109,7 @@ public PackageBinding createPackage(char[][] compoundName) {
// unless its an unresolved type which is referenced from an inconsistent class file
// NOTE: empty packages are not packages according to changes in JLS v2, 7.4.3
// so not all types cause collision errors when they're created even though the package did exist
- ReferenceBinding type = packageBinding.getType0(compoundName[i]);
- if (type != null && type != TheNotFoundType && !(type instanceof UnresolvedReferenceBinding))
+ if (packageBinding.hasType0Any(compoundName[i]))
return null;
PackageBinding parent = packageBinding;
@@ -1125,21 +1130,18 @@ public PackageBinding createPackage(char[][] compoundName) {
return null;
}
}
- if (parent instanceof SplitPackageBinding) {
+ PackageBinding singleParent = parent.getIncarnation(this.module);
+ if (singleParent != parent && singleParent != null) {
// parent.getPackage0() may have been too shy, so drill into the split:
- PackageBinding singleParent = ((SplitPackageBinding) parent).getIncarnation(this.module);
- if (singleParent != null)
- packageBinding = singleParent.getPackage0(compoundName[i]);
+ packageBinding = singleParent.getPackage0(compoundName[i]);
}
if (packageBinding == null) {
- packageBinding = new PackageBinding(CharOperation.subarray(compoundName, 0, i + 1), parent, this, this.module);
+ packageBinding = new PlainPackageBinding(CharOperation.subarray(compoundName, 0, i + 1), parent, this, this.module);
packageBinding = parent.addPackage(packageBinding, this.module);
}
}
}
- if (packageBinding instanceof SplitPackageBinding)
- packageBinding = ((SplitPackageBinding) packageBinding).getIncarnation(this.module);
- return packageBinding;
+ return packageBinding.getIncarnation(this.module);
}
public ParameterizedGenericMethodBinding createParameterizedGenericMethod(MethodBinding genericMethod, RawTypeBinding rawType) {
@@ -1474,6 +1476,10 @@ public ReferenceBinding getCachedType0(char[][] compoundName) {
PackageBinding packageBinding = getPackage0(compoundName[0]);
if (packageBinding == null || packageBinding == TheNotFoundPackage)
return null;
+ // we should be asking via the correct LE, so peel any SPB at the root:
+ packageBinding = packageBinding.getIncarnation(this.module);
+ if (packageBinding == null || packageBinding == TheNotFoundPackage)
+ return null;
for (int i = 1, packageLength = compoundName.length - 1; i < packageLength; i++)
if ((packageBinding = packageBinding.getPackage0Any(compoundName[i])) == null || packageBinding == TheNotFoundPackage)
@@ -1645,7 +1651,7 @@ PackageBinding getTopLevelPackage(char[] name) {
packageBinding = this.module.getTopLevelPackage(name);
} else {
if (this.nameEnvironment.isPackage(null, name)) {
- this.knownPackages.put(name, packageBinding = new PackageBinding(name, this, this.module));
+ this.knownPackages.put(name, packageBinding = new PlainPackageBinding(name, this, this.module));
}
}
if (packageBinding != null) {
@@ -2130,7 +2136,7 @@ public void reset() {
this.module = this.UnNamedModule;
this.JavaBaseModule = null;
- this.defaultPackage = new PackageBinding(this); // assume the default package always exists
+ this.defaultPackage = new PlainPackageBinding(this); // assume the default package always exists
this.defaultImports = null;
this.knownPackages = new HashtableOfPackage();
this.accessRestrictions = new HashMap(3);
@@ -2241,4 +2247,44 @@ public boolean containsNullTypeAnnotation(AnnotationBinding[] typeAnnotations) {
}
return false;
}
+
+public Binding getInaccessibleBinding(char[][] compoundName, ModuleBinding clientModule) {
+ if (this.root != this)
+ return this.root.getInaccessibleBinding(compoundName, clientModule);
+ if (this.nameEnvironment instanceof IModuleAwareNameEnvironment) {
+ IModuleAwareNameEnvironment moduleEnv = (IModuleAwareNameEnvironment) this.nameEnvironment;
+ int length = compoundName.length;
+ for (int j=length; j>0; j--) {
+ char[][] candidateName = CharOperation.subarray(compoundName, 0, j);
+ char[][] moduleNames = moduleEnv.getModulesDeclaringPackage(candidateName, ModuleBinding.ANY);
+ if (moduleNames != null) {
+ // in some module a package named candidateName exists, verify observability & inaccessibility:
+ PackageBinding inaccessiblePackage = null;
+ for (char[] moduleName : moduleNames) {
+ if (moduleName == ModuleBinding.UNOBSERVABLE)
+ continue;
+ ModuleBinding mod = getModule(moduleName);
+ if (mod != null) {
+ PackageBinding pack = mod.getVisiblePackage(candidateName);
+ if (pack != null && pack.isValidBinding()) {
+ if (clientModule.canAccess(pack))
+ return null;
+ inaccessiblePackage = pack;
+ }
+ }
+ }
+ if (inaccessiblePackage == null)
+ return null;
+ if (j < length) {
+ // does the package even contain a type of the next name segment?
+ TypeBinding type = inaccessiblePackage.getType(compoundName[j], inaccessiblePackage.enclosingModule);
+ if (type instanceof ReferenceBinding && type.isValidBinding())
+ return new ProblemReferenceBinding(compoundName, (ReferenceBinding) type, ProblemReasons.NotAccessible);
+ }
+ return new ProblemPackageBinding(candidateName, ProblemReasons.NotAccessible, this);
+ }
+ }
+ }
+ return null;
+}
}
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ModuleBinding.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ModuleBinding.java
index 642fe17b1a..a32ae2d34f 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ModuleBinding.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ModuleBinding.java
@@ -58,6 +58,8 @@ public class ModuleBinding extends Binding implements IUpdatableModule {
public static final char[] ANY = "".toCharArray(); //$NON-NLS-1$
/** Module name for package/type lookup that should look into all named modules. */
public static final char[] ANY_NAMED = "".toCharArray(); //$NON-NLS-1$
+ /** Module name for an unobservable module */
+ public static final char[] UNOBSERVABLE = "".toCharArray(); //$NON-NLS-1$
public static class UnNamedModule extends ModuleBinding {
@@ -93,6 +95,20 @@ public class ModuleBinding extends Binding implements IUpdatableModule {
return pkg.isDeclaredIn(this) && pkg.hasCompilationUnit(false);
}
@Override
+ PlainPackageBinding getDeclaredPackage(char[] flatName) {
+ PlainPackageBinding declaredPackage = super.getDeclaredPackage(flatName);
+ if (declaredPackage == null && this.environment.useModuleSystem) {
+ IModuleAwareNameEnvironment moduleEnv = (IModuleAwareNameEnvironment) this.environment.nameEnvironment;
+ char[][] compoundName = CharOperation.splitOn('.', flatName);
+ char[][] declaringModuleNames = moduleEnv.getUniqueModulesDeclaringPackage(compoundName, nameForLookup());
+ if (declaringModuleNames != null && CharOperation.containsEqual(declaringModuleNames, this.moduleName)) {
+ declaredPackage = getOrCreateDeclaredPackage(compoundName);
+ this.declaredPackages.put(flatName, declaredPackage);
+ }
+ }
+ return declaredPackage;
+ }
+ @Override
public boolean isUnnamed() {
return true;
}
@@ -116,10 +132,10 @@ public class ModuleBinding extends Binding implements IUpdatableModule {
public char[] moduleName;
protected ModuleBinding[] requires;
protected ModuleBinding[] requiresTransitive;
- protected PackageBinding[] exportedPackages;
- private Map<PackageBinding,SimpleSetOfCharArray> exportRestrictions; // RHS is unresolved names, because unresolvable names are legal in this position
- protected PackageBinding[] openedPackages;
- private Map<PackageBinding,SimpleSetOfCharArray> openRestrictions; // RHS is unresolved names, because unresolvable names are legal in this position
+ protected PlainPackageBinding[] exportedPackages;
+ private Map<PlainPackageBinding,SimpleSetOfCharArray> exportRestrictions; // RHS is unresolved names, because unresolvable names are legal in this position
+ protected PlainPackageBinding[] openedPackages;
+ private Map<PlainPackageBinding,SimpleSetOfCharArray> openRestrictions; // RHS is unresolved names, because unresolvable names are legal in this position
protected TypeBinding[] uses;
protected TypeBinding[] services;
public Map<TypeBinding,TypeBinding[]> implementations;
@@ -133,7 +149,6 @@ public class ModuleBinding extends Binding implements IUpdatableModule {
boolean isAuto = false;
private boolean[] isComplete = new boolean[UpdateKind.values().length];
private Set<ModuleBinding> transitiveRequires;
- boolean isPackageLookupActive = false; // to prevent cyclic lookup caused by synthetic reads edges on behalf of auto-modules.
SimpleLookupTable storedAnnotations = null;
/**
@@ -141,8 +156,16 @@ public class ModuleBinding extends Binding implements IUpdatableModule {
* We consider a package as declared in a module,
* if a compilation unit associated with the module
* declares the package or a subpackage thereof.
+ * <p>
+ * A package in this structures is always represented by a {@link PlainPackageBinding},
+ * as opposed to {@link SplitPackageBinding}, which are only maintained in the trees
+ * below {@link LookupEnvironment#knownPackages}.
+ * <p>
+ * This structure is populated early during compilation with all packages that
+ * are referenced in exports and opens directives, plus their parent packages.
+ * </p>
*/
- public HashtableOfPackage declaredPackages;
+ public HashtableOfPackage<PlainPackageBinding> declaredPackages;
/** Constructor for the unnamed module. */
private ModuleBinding(LookupEnvironment env) {
@@ -150,9 +173,9 @@ public class ModuleBinding extends Binding implements IUpdatableModule {
this.environment = env;
this.requires = Binding.NO_MODULES;
this.requiresTransitive = Binding.NO_MODULES;
- this.exportedPackages = Binding.NO_PACKAGES;
- this.openedPackages = Binding.NO_PACKAGES;
- this.declaredPackages = new HashtableOfPackage(0);
+ this.exportedPackages = Binding.NO_PLAIN_PACKAGES;
+ this.openedPackages = Binding.NO_PLAIN_PACKAGES;
+ this.declaredPackages = new HashtableOfPackage<PlainPackageBinding>();
Arrays.fill(this.isComplete, true);
}
/* For error binding and sub class SourceModuleBinding. */
@@ -160,11 +183,11 @@ public class ModuleBinding extends Binding implements IUpdatableModule {
this.moduleName = moduleName;
this.requires = Binding.NO_MODULES;
this.requiresTransitive = Binding.NO_MODULES;
- this.exportedPackages = Binding.NO_PACKAGES;
- this.openedPackages = Binding.NO_PACKAGES;
+ this.exportedPackages = Binding.NO_PLAIN_PACKAGES;
+ this.openedPackages = Binding.NO_PLAIN_PACKAGES;
this.uses = Binding.NO_TYPES;
this.services = Binding.NO_TYPES;
- this.declaredPackages = new HashtableOfPackage(5);
+ this.declaredPackages = new HashtableOfPackage<PlainPackageBinding>(5);
}
/* For sub class BinaryModuleBinding */
@@ -173,10 +196,10 @@ public class ModuleBinding extends Binding implements IUpdatableModule {
this.requires = Binding.NO_MODULES;
this.requiresTransitive = Binding.NO_MODULES;
this.environment = new LookupEnvironment(existingEnvironment.root, this);
- this.declaredPackages = new HashtableOfPackage(5);
+ this.declaredPackages = new HashtableOfPackage<PlainPackageBinding>(5);
}
- public PackageBinding[] getExports() {
+ public PlainPackageBinding[] getExports() {
completeIfNeeded(UpdateKind.PACKAGE);
return this.exportedPackages;
}
@@ -192,7 +215,7 @@ public class ModuleBinding extends Binding implements IUpdatableModule {
}
return CharOperation.NO_STRINGS;
}
- public PackageBinding[] getOpens() {
+ public PlainPackageBinding[] getOpens() {
completeIfNeeded(UpdateKind.PACKAGE);
return this.openedPackages;
}
@@ -231,7 +254,7 @@ public class ModuleBinding extends Binding implements IUpdatableModule {
return this.services;
}
- private void completeIfNeeded(IUpdatableModule.UpdateKind kind) {
+ void completeIfNeeded(IUpdatableModule.UpdateKind kind) {
if (!this.isComplete[kind.ordinal()]) {
this.isComplete[kind.ordinal()] = true;
if (this.environment.nameEnvironment instanceof IModuleAwareNameEnvironment) {
@@ -257,23 +280,10 @@ public class ModuleBinding extends Binding implements IUpdatableModule {
this.environment.problemReporter.missingModuleAddReads(requiredModuleName);
return;
}
- // update known packages:
- HashtableOfPackage knownPackages = this.environment.knownPackages;
- for (int i = 0; i < knownPackages.valueTable.length; i++) {
- PackageBinding packageBinding = knownPackages.valueTable[i];
- if (packageBinding == null) continue;
- PackageBinding newBinding = requiredModule.getVisiblePackage(packageBinding.compoundName);
- newBinding = SplitPackageBinding.combine(newBinding, packageBinding, this);
- if (packageBinding != newBinding) {
- knownPackages.valueTable[i] = newBinding;
- if (this.declaredPackages.containsKey(newBinding.readableName()))
- this.declaredPackages.put(newBinding.readableName(), newBinding);
- }
- }
}
@Override
public void addExports(char[] packageName, char[][] targetModules) {
- PackageBinding declaredPackage = getVisiblePackage(CharOperation.splitOn('.', packageName));
+ PlainPackageBinding declaredPackage = getOrCreateDeclaredPackage(CharOperation.splitOn('.', packageName));
if (declaredPackage != null && declaredPackage.isValidBinding())
addResolvedExport(declaredPackage, targetModules);
}
@@ -293,9 +303,9 @@ public class ModuleBinding extends Binding implements IUpdatableModule {
public char[][] getPackageNamesForClassFile() {
if (this.packageNames == null)
return null;
- for (PackageBinding packageBinding : this.exportedPackages)
+ for (PlainPackageBinding packageBinding : this.exportedPackages)
this.packageNames.add(packageBinding.readableName());
- for (PackageBinding packageBinding : this.openedPackages)
+ for (PlainPackageBinding packageBinding : this.openedPackages)
this.packageNames.add(packageBinding.readableName());
if (this.implementations != null)
for (TypeBinding[] types : this.implementations.values())
@@ -306,38 +316,57 @@ public class ModuleBinding extends Binding implements IUpdatableModule {
// ---
- public void addResolvedExport(PackageBinding declaredPackage, char[][] targetModules) {
- int len = this.exportedPackages.length;
+ public PlainPackageBinding getOrCreateDeclaredPackage(char[][] compoundName) {
+ char[] flatName = CharOperation.concatWith(compoundName, '.');
+ PlainPackageBinding pkgBinding = this.declaredPackages.get(flatName);
+ if (pkgBinding != null)
+ return pkgBinding;
+ if (compoundName.length > 1) {
+ PlainPackageBinding parent = getOrCreateDeclaredPackage(CharOperation.subarray(compoundName, 0, compoundName.length-1));
+ pkgBinding = new PlainPackageBinding(compoundName, parent, this.environment, this);
+ parent.addPackage(pkgBinding, this);
+ } else {
+ pkgBinding = new PlainPackageBinding(compoundName[0], this.environment, this);
+ PackageBinding problemPackage = this.environment.getPackage0(compoundName[0]);
+ if (problemPackage == LookupEnvironment.TheNotFoundPackage)
+ this.environment.knownPackages.put(compoundName[0], null); // forget TheNotFoundPackage if package was detected late (e.g. with APT in the loop)
+ }
+ this.declaredPackages.put(flatName, pkgBinding);
+ return pkgBinding;
+ }
+
+ public void addResolvedExport(PlainPackageBinding declaredPackage, char[][] targetModules) {
if (declaredPackage == null || !declaredPackage.isValidBinding()) {
// TODO(SHMOD) use a problem binding (if needed by DOM clients)? See https://bugs.eclipse.org/518794#c13
return;
}
- if (len == 0) {
- this.exportedPackages = new PackageBinding[] { declaredPackage };
+ if (this.exportedPackages == null || this.exportedPackages.length == 0) {
+ this.exportedPackages = new PlainPackageBinding[] { declaredPackage };
} else {
- System.arraycopy(this.exportedPackages, 0, this.exportedPackages = new PackageBinding[len+1], 0, len);
+ int len = this.exportedPackages.length;
+ System.arraycopy(this.exportedPackages, 0, this.exportedPackages = new PlainPackageBinding[len+1], 0, len);
this.exportedPackages[len] = declaredPackage;
}
declaredPackage.isExported = Boolean.TRUE;
recordExportRestrictions(declaredPackage, targetModules);
}
- public void addResolvedOpens(PackageBinding declaredPackage, char[][] targetModules) {
+ public void addResolvedOpens(PlainPackageBinding declaredPackage, char[][] targetModules) {
int len = this.openedPackages.length;
if (declaredPackage == null || !declaredPackage.isValidBinding()) {
// TODO(SHMOD) use a problem binding (if needed by DOM clients)? See https://bugs.eclipse.org/518794#c13
return;
}
if (len == 0) {
- this.openedPackages = new PackageBinding[] { declaredPackage };
+ this.openedPackages = new PlainPackageBinding[] { declaredPackage };
} else {
- System.arraycopy(this.openedPackages, 0, this.openedPackages = new PackageBinding[len+1], 0, len);
+ System.arraycopy(this.openedPackages, 0, this.openedPackages = new PlainPackageBinding[len+1], 0, len);
this.openedPackages[len] = declaredPackage;
}
recordOpensRestrictions(declaredPackage, targetModules);
}
- protected void recordExportRestrictions(PackageBinding exportedPackage, char[][] targetModules) {
+ protected void recordExportRestrictions(PlainPackageBinding exportedPackage, char[][] targetModules) {
if (targetModules != null && targetModules.length > 0) {
SimpleSetOfCharArray targetModuleSet = null;
if (this.exportRestrictions != null) {
@@ -355,7 +384,7 @@ public class ModuleBinding extends Binding implements IUpdatableModule {
}
}
- protected void recordOpensRestrictions(PackageBinding openedPackage, char[][] targetModules) {
+ protected void recordOpensRestrictions(PlainPackageBinding openedPackage, char[][] targetModules) {
if (targetModules != null && targetModules.length > 0) {
SimpleSetOfCharArray targetModuleSet = null;
if (this.openRestrictions != null) {
@@ -472,12 +501,7 @@ public class ModuleBinding extends Binding implements IUpdatableModule {
*/
public boolean isPackageExportedTo(PackageBinding pkg, ModuleBinding client) {
// TODO(SHMOD): cache the result?
- PackageBinding resolved = null;
- if (pkg instanceof SplitPackageBinding) {
- resolved = ((SplitPackageBinding) pkg).getIncarnation(this);
- } else if (pkg.enclosingModule == this) {
- resolved = pkg;
- }
+ PackageBinding resolved = pkg.getIncarnation(this);
if (resolved != null) {
if (this.isAuto) { // all packages are exported by an automatic module
return pkg.enclosingModule == this; // no transitive export
@@ -515,11 +539,8 @@ public class ModuleBinding extends Binding implements IUpdatableModule {
* </p>
*/
public PackageBinding getTopLevelPackage(char[] name) {
- // check caches:
- PackageBinding binding = this.declaredPackages.get(name);
- if (binding != null)
- return binding;
- binding = this.environment.getPackage0(name);
+ // check cache:
+ PackageBinding binding = this.environment.getPackage0(name);
if (binding != null)
return binding;
binding = getVisiblePackage(null, name, true);
@@ -533,31 +554,14 @@ public class ModuleBinding extends Binding implements IUpdatableModule {
return binding;
}
- PackageBinding getDeclaredPackage(char[][] parentName, char[] name) {
- // check caches:
- char[][] subPkgCompoundName = CharOperation.arrayConcat(parentName, name);
- char[] fullFlatName = CharOperation.concatWith(subPkgCompoundName, '.');
- PackageBinding pkg = this.declaredPackages.get(fullFlatName);
- if (pkg != null)
- return pkg;
- PackageBinding parent = parentName.length == 0 ? null : getVisiblePackage(parentName);
- PackageBinding binding = new PackageBinding(subPkgCompoundName, parent, this.environment, this);
- // remember
- this.declaredPackages.put(fullFlatName, binding);
- if (parent == null) {
- this.environment.knownPackages.put(name, binding);
- }
- return binding;
+ PlainPackageBinding getDeclaredPackage(char[] flatName) {
+ return this.declaredPackages.get(flatName);
}
+
// Given parent is visible in this module, see if there is sub package named name visible in this module
PackageBinding getVisiblePackage(PackageBinding parent, char[] name, boolean considerRequiredModules) {
- // check caches:
- char[][] parentName = parent == null ? CharOperation.NO_CHAR_CHAR : parent.compoundName;
- char[][] subPkgCompoundName = CharOperation.arrayConcat(parentName, name);
- char[] fullFlatName = CharOperation.concatWith(subPkgCompoundName, '.');
- PackageBinding pkg = this.declaredPackages.get(fullFlatName);
- if (pkg != null)
- return pkg;
+ // check caches in PackageBinding/LookupEnvironment, which contain the full SplitPackageBinding if appropriate:
+ PackageBinding pkg;
if (parent != null)
pkg = parent.getPackage0(name);
else
@@ -569,33 +573,37 @@ public class ModuleBinding extends Binding implements IUpdatableModule {
return addPackage(pkg, false);
}
- PackageBinding binding = null;
+ // check cached plain PackageBinding in declaredPackages (which may need combining with siblings):
+ char[][] parentName = parent == null ? CharOperation.NO_CHAR_CHAR : parent.compoundName;
+ char[][] subPkgCompoundName = CharOperation.arrayConcat(parentName, name);
+ char[] fullFlatName = CharOperation.concatWith(subPkgCompoundName, '.');
+ PackageBinding binding = this.declaredPackages.get(fullFlatName);
+
char[][] declaringModuleNames = null;
boolean packageMayBeIncomplete = !considerRequiredModules;
if (this.environment.useModuleSystem) {
IModuleAwareNameEnvironment moduleEnv = (IModuleAwareNameEnvironment) this.environment.nameEnvironment;
- declaringModuleNames = moduleEnv.getUniqueModulesDeclaringPackage(parentName, name, nameForLookup());
- if (declaringModuleNames != null) {
- if (CharOperation.containsEqual(declaringModuleNames, this.moduleName)) {
- if (parent instanceof SplitPackageBinding) {
- // parent.getPackage0() may have been too shy, so drill into the split:
- PackageBinding singleParent = ((SplitPackageBinding) parent).getIncarnation(this);
- if (singleParent != null)
- binding = singleParent.getPackage0(name);
- }
- if (binding == null) {
- // declared here, not yet known, so create it now:
- binding = new PackageBinding(subPkgCompoundName, parent, this.environment, this);
- }
- } else if (considerRequiredModules) {
- // visible but foreign (when current is unnamed or auto):
- for (char[] declaringModuleName : declaringModuleNames) {
- ModuleBinding declaringModule = this.environment.root.getModule(declaringModuleName);
- if (declaringModule != null) {
- if (declaringModule.isPackageLookupActive) {
- packageMayBeIncomplete = true;
- } else {
- PackageBinding declaredPackage = declaringModule.getDeclaredPackage(parentName, name);
+ declaringModuleNames = moduleEnv.getUniqueModulesDeclaringPackage(subPkgCompoundName, nameForLookup());
+ if (binding == null) {
+ if (declaringModuleNames != null) {
+ if (CharOperation.containsEqual(declaringModuleNames, this.moduleName)) {
+ if (parent != null) {
+ PackageBinding singleParent = parent.getIncarnation(this);
+ if (singleParent != null && singleParent != parent) {
+ // parent.getPackage0() may have been too shy, so drill into the split:
+ binding = singleParent.getPackage0(name);
+ }
+ }
+ if (binding == null) {
+ // declared here, not yet known, so create it now:
+ binding = new PlainPackageBinding(subPkgCompoundName, parent, this.environment, this);
+ }
+ } else if (considerRequiredModules) {
+ // visible but foreign (when current is unnamed or auto):
+ for (char[] declaringModuleName : declaringModuleNames) {
+ ModuleBinding declaringModule = this.environment.root.getModule(declaringModuleName);
+ if (declaringModule != null) {
+ PlainPackageBinding declaredPackage = declaringModule.getDeclaredPackage(fullFlatName);
if (declaredPackage != null) {
// don't add foreign package to 'parent' (below), but to its own parent:
if (declaredPackage.parent != null)
@@ -611,7 +619,7 @@ public class ModuleBinding extends Binding implements IUpdatableModule {
}
} else {
if (this.environment.nameEnvironment.isPackage(parentName, name))
- binding = new PackageBinding(subPkgCompoundName, parent, this.environment, this);
+ binding = new PlainPackageBinding(subPkgCompoundName, parent, this.environment, this);
}
// enrich with split-siblings from visible modules:
@@ -716,11 +724,11 @@ public class ModuleBinding extends Binding implements IUpdatableModule {
char[][] declaringModuleNames = null;
if (isUnnamed()) {
IModuleAwareNameEnvironment moduleEnv = (IModuleAwareNameEnvironment) this.environment.nameEnvironment;
- declaringModuleNames = moduleEnv.getUniqueModulesDeclaringPackage(null, packageName, ANY);
+ declaringModuleNames = moduleEnv.getUniqueModulesDeclaringPackage(new char[][] {packageName}, ANY);
}
packageBinding = combineWithPackagesFromOtherRelevantModules(packageBinding, packageBinding.compoundName, declaringModuleNames);
}
- this.declaredPackages.put(packageName, packageBinding);
+ this.declaredPackages.put(packageName, packageBinding.getIncarnation(this));
if (packageBinding.parent == null) {
this.environment.knownPackages.put(packageName, packageBinding);
}
@@ -729,23 +737,11 @@ public class ModuleBinding extends Binding implements IUpdatableModule {
}
private PackageBinding combineWithPackagesFromOtherRelevantModules(PackageBinding currentBinding, char[][] compoundName, char[][] declaringModuleNames) {
- boolean save = this.isPackageLookupActive;
- this.isPackageLookupActive = true;
- try {
- char[] singleName = compoundName[compoundName.length-1];
- PackageBinding parent = currentBinding != null ? currentBinding.parent : null;
- for (ModuleBinding moduleBinding : otherRelevantModules(declaringModuleNames)) {
- if (!moduleBinding.isPackageLookupActive) {
- PackageBinding nextBinding = parent != null
- ? moduleBinding.getVisiblePackage(parent, singleName, false)
- : moduleBinding.getVisiblePackage(compoundName, false);
- currentBinding = SplitPackageBinding.combine(nextBinding, currentBinding, this);
- }
- }
- return currentBinding;
- } finally {
- this.isPackageLookupActive = save;
+ for (ModuleBinding moduleBinding : otherRelevantModules(declaringModuleNames)) {
+ PlainPackageBinding nextBinding = moduleBinding.getDeclaredPackage(CharOperation.concatWith(compoundName, '.'));
+ currentBinding = SplitPackageBinding.combine(nextBinding, currentBinding, this);
}
+ return currentBinding;
}
List<ModuleBinding> otherRelevantModules(char[][] declaringModuleNames) {
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/PackageBinding.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/PackageBinding.java
index 0bd0e50cbb..de338d86be 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/PackageBinding.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/PackageBinding.java
@@ -25,7 +25,7 @@ import org.eclipse.jdt.internal.compiler.env.IModuleAwareNameEnvironment;
import org.eclipse.jdt.internal.compiler.util.HashtableOfPackage;
import org.eclipse.jdt.internal.compiler.util.HashtableOfType;
-public class PackageBinding extends Binding implements TypeConstants {
+public abstract class PackageBinding extends Binding implements TypeConstants {
public long tagBits = 0; // See values in the interface TagBits below
public char[][] compoundName;
@@ -35,7 +35,7 @@ public class PackageBinding extends Binding implements TypeConstants {
/** Types in this map are either uniquely visible in the current module or ProblemReferenceBindings. */
public HashtableOfType knownTypes;
/** All visible member packages, i.e. observable packages associated with modules read by the current module. */
- HashtableOfPackage knownPackages;
+ HashtableOfPackage<PackageBinding> knownPackages;
// code representing the default that has been defined for this package (using @NonNullByDefault)
// one of Binding.{NO_NULL_DEFAULT,NULL_UNSPECIFIED_BY_DEFAULT,NONNULL_BY_DEFAULT}
@@ -46,12 +46,12 @@ public class PackageBinding extends Binding implements TypeConstants {
/** Is this package exported from its module? NB: to query this property use {@link #isExported()} to ensure initialization. */
Boolean isExported;
-protected PackageBinding() {
+protected PackageBinding(char[][] compoundName, LookupEnvironment environment) {
// for creating problem package
+ this.compoundName = compoundName;
+ this.environment = environment;
}
-public PackageBinding(char[] topLevelPackageName, LookupEnvironment environment, ModuleBinding enclosingModule) {
- this(new char[][] {topLevelPackageName}, null, environment, enclosingModule);
-}
+
/* Create a normal package.
*/
public PackageBinding(char[][] compoundName, PackageBinding parent, LookupEnvironment environment, ModuleBinding enclosingModule) {
@@ -59,7 +59,7 @@ public PackageBinding(char[][] compoundName, PackageBinding parent, LookupEnviro
this.parent = parent;
this.environment = environment;
this.knownTypes = null; // initialized if used... class counts can be very large 300-600
- this.knownPackages = new HashtableOfPackage(3); // sub-package counts are typically 0-3
+ this.knownPackages = new HashtableOfPackage<PackageBinding>(3); // sub-package counts are typically 0-3
if (compoundName != CharOperation.NO_CHAR_CHAR)
checkIfNullAnnotationPackage();
@@ -73,9 +73,6 @@ public PackageBinding(char[][] compoundName, PackageBinding parent, LookupEnviro
throw new IllegalStateException("Package should have an enclosing module"); //$NON-NLS-1$
}
-public PackageBinding(LookupEnvironment environment) {
- this(CharOperation.NO_CHAR_CHAR, null, environment, environment.module);
-}
protected void addNotFoundPackage(char[] simpleName) {
if (!this.environment.suppressImportErrors)
this.knownPackages.put(simpleName, LookupEnvironment.TheNotFoundPackage);
@@ -226,6 +223,17 @@ ReferenceBinding getType0(char[] name) {
return null;
return this.knownTypes.get(name);
}
+
+/**
+ * Test if this package (or any of its incarnations in case of a SplitPackageBinding) has recorded
+ * an actual, resolved type of the given name (based on answers from getType0()).
+ * Useful for clash detection.
+ */
+boolean hasType0Any(char[] name) {
+ ReferenceBinding type0 = getType0(name);
+ return type0 != null && type0 != LookupEnvironment.TheNotFoundType && !(type0 instanceof UnresolvedReferenceBinding);
+}
+
/* Answer the package or type named name; ask the oracle if it is not in the cache.
* Answer null if it could not be resolved.
*
@@ -258,8 +266,8 @@ public Binding getTypeOrPackage(char[] name, ModuleBinding mod, boolean splitPac
PackageBinding packageBinding = getPackage0(name);
if (packageBinding != null && packageBinding != LookupEnvironment.TheNotFoundPackage) {
- if (!splitPackageAllowed && packageBinding instanceof SplitPackageBinding) {
- return ((SplitPackageBinding) packageBinding).getVisibleFor(mod, false);
+ if (!splitPackageAllowed) {
+ return packageBinding.getVisibleFor(mod, false, false);
}
return packageBinding;
}
@@ -284,8 +292,8 @@ public Binding getTypeOrPackage(char[] name, ModuleBinding mod, boolean splitPac
if (packageBinding == null) { // have not looked for it before
if ((packageBinding = findPackage(name, mod)) != null) {
- if (!splitPackageAllowed && packageBinding instanceof SplitPackageBinding) {
- return ((SplitPackageBinding) packageBinding).getVisibleFor(mod, false);
+ if (!splitPackageAllowed) {
+ return packageBinding.getVisibleFor(mod, false, false);
}
return packageBinding;
}
@@ -433,15 +441,23 @@ public boolean isExported() {
}
/**
* If this package is uniquely visible to 'module' return a plain PackageBinding.
- * In case of a conflict between a local package and foreign package
- * the plain local package is returned, because this conflict will more
- * appropriately be reported against the package declaration, not its references.
+ * In case of a conflict between a local package and foreign package flag <b>preferLocal</b>
+ * will select the behavior:
+ * <ul>
+ * <li>if {@code true} the plain local package is returned, because this conflict will more
+ * appropriately be reported against the package declaration, not its references.</li>
+ * <li>if {@code false} a conflict local vs. foreign will be treated just like any other conflict,
+ * see next.</li>
+ * </ul>
* In case of multiple accessible foreign packages a SplitPackageBinding is returned
* to indicate a conflict.
*/
-public PackageBinding getVisibleFor(ModuleBinding module, boolean preferLocal) {
+public PackageBinding getVisibleFor(ModuleBinding module, boolean preferLocal, boolean skipCUcheck) {
return this;
}
+
+public abstract PlainPackageBinding getIncarnation(ModuleBinding moduleBinding);
+
public boolean hasCompilationUnit(boolean checkCUs) {
if (this.knownTypes != null) {
for (ReferenceBinding knownType : this.knownTypes.valueTable) {
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/PlainPackageBinding.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/PlainPackageBinding.java
new file mode 100644
index 0000000000..97ea1a2bef
--- /dev/null
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/PlainPackageBinding.java
@@ -0,0 +1,47 @@
+/*******************************************************************************
+ * Copyright (c) 2019 GK Software SE, and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ * Stephan Herrmann - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jdt.internal.compiler.lookup;
+
+import org.eclipse.jdt.core.compiler.CharOperation;
+
+/** A package binding that is known not to be a {@link SplitPackageBinding}. */
+public class PlainPackageBinding extends PackageBinding {
+
+ /** Create a toplevel package. */
+ public PlainPackageBinding(char[] topLevelPackageName, LookupEnvironment environment, ModuleBinding enclosingModule) {
+ super(new char[][] {topLevelPackageName}, null, environment, enclosingModule);
+ }
+
+ /** Create a default package. */
+ public PlainPackageBinding(LookupEnvironment environment) {
+ super(CharOperation.NO_CHAR_CHAR, null, environment, environment.module);
+ }
+
+ /** Create a normal package. */
+ public PlainPackageBinding(char[][] compoundName, PackageBinding parent, LookupEnvironment environment, ModuleBinding enclosingModule) {
+ super(compoundName, parent, environment, enclosingModule);
+ }
+
+ protected PlainPackageBinding(char[][] compoundName, LookupEnvironment environment) {
+ // for problem bindings
+ super(compoundName, environment);
+ }
+
+ @Override
+ public PlainPackageBinding getIncarnation(ModuleBinding moduleBinding) {
+ if (this.enclosingModule == moduleBinding)
+ return this;
+ return null;
+ }
+}
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ProblemPackageBinding.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ProblemPackageBinding.java
index d531a62baa..efe9f8b301 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ProblemPackageBinding.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ProblemPackageBinding.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2009 IBM Corporation and others.
+ * Copyright (c) 2000, 2019 IBM Corporation and others.
*
* This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
@@ -13,23 +13,22 @@
*******************************************************************************/
package org.eclipse.jdt.internal.compiler.lookup;
-public class ProblemPackageBinding extends PackageBinding {
+public class ProblemPackageBinding extends PlainPackageBinding {
private int problemId;
// NOTE: must only answer the subset of the name related to the problem
ProblemPackageBinding(char[][] compoundName, int problemId, LookupEnvironment environment) {
- this.compoundName = compoundName;
+ super(compoundName, environment);
this.problemId = problemId;
- this.environment = environment;
}
ProblemPackageBinding(char[] name, int problemId, LookupEnvironment environment) {
this(new char[][] {name}, problemId, environment);
}
-/* API
-* Answer the problem id associated with the receiver.
-* NoError if the receiver is a valid binding.
-*/
-
+/**
+ * API
+ * Answer the problem id associated with the receiver.
+ * NoError if the receiver is a valid binding.
+ */
@Override
public final int problemId() {
return this.problemId;
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/SourceModuleBinding.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/SourceModuleBinding.java
index ee5fd9a20e..76d92b2830 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/SourceModuleBinding.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/SourceModuleBinding.java
@@ -119,14 +119,14 @@ public class SourceModuleBinding extends ModuleBinding {
}
@Override
- public PackageBinding[] getExports() {
+ public PlainPackageBinding[] getExports() {
// don't rely on "if (this.exportedPackages == Binding.NO_PACKAGES)" - could have been modified by completeIfNeeded()
this.scope.referenceContext.moduleDeclaration.resolvePackageDirectives(this.scope);
return super.getExports();
}
@Override
- public PackageBinding[] getOpens() {
+ public PlainPackageBinding[] getOpens() {
// don't rely on "if (this.openedPackages == Binding.NO_PACKAGES)" - could have been modified by completeIfNeeded()
this.scope.referenceContext.moduleDeclaration.resolvePackageDirectives(this.scope);
return super.getOpens();
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/SplitPackageBinding.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/SplitPackageBinding.java
index 8bb5266322..44bab26bc9 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/SplitPackageBinding.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/SplitPackageBinding.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2017 GK Software SE, and others.
+ * Copyright (c) 2017, 2019 GK Software SE, and others.
*
* This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
@@ -21,7 +21,7 @@ import org.eclipse.jdt.core.compiler.CharOperation;
public class SplitPackageBinding extends PackageBinding {
Set<ModuleBinding> declaringModules;
- public Set<PackageBinding> incarnations;
+ public Set<PlainPackageBinding> incarnations;
/**
* Combine two potential package bindings, answering either the better of those if the other has a problem,
@@ -71,14 +71,14 @@ public class SplitPackageBinding extends PackageBinding {
if (packageBinding instanceof SplitPackageBinding) {
SplitPackageBinding split = (SplitPackageBinding) packageBinding;
this.declaringModules.addAll(split.declaringModules);
- for(PackageBinding incarnation: split.incarnations) {
+ for(PlainPackageBinding incarnation: split.incarnations) {
if(this.incarnations.add(incarnation)) {
incarnation.addWrappingSplitPackageBinding(this);
}
}
- } else {
+ } else if (packageBinding instanceof PlainPackageBinding) {
this.declaringModules.add(packageBinding.enclosingModule);
- if(this.incarnations.add(packageBinding)) {
+ if(this.incarnations.add((PlainPackageBinding) packageBinding)) {
packageBinding.addWrappingSplitPackageBinding(this);
}
}
@@ -92,31 +92,32 @@ public class SplitPackageBinding extends PackageBinding {
PackageBinding visible = this.knownPackages.get(simpleName);
visible = SplitPackageBinding.combine(element, visible, this.enclosingModule);
this.knownPackages.put(simpleName, visible);
- PackageBinding incarnation = getIncarnation(element.enclosingModule);
- if (incarnation != null)
- incarnation.addPackage(element, module);
+
+ // also record the PPB's as parent-child:
+ PlainPackageBinding incarnation = getIncarnation(element.enclosingModule);
+ if (incarnation != null) {
+ // avoid adding an SPB as a child of a PPB:
+ PlainPackageBinding elementIncarnation = element.getIncarnation(element.enclosingModule);
+ if (elementIncarnation != null)
+ incarnation.addPackage(elementIncarnation, module);
+ }
return element;
}
PackageBinding combineWithSiblings(PackageBinding childPackage, char[] name, ModuleBinding module) {
- ModuleBinding primaryModule = childPackage != null ? childPackage.enclosingModule : this.enclosingModule;
+ ModuleBinding primaryModule = childPackage.enclosingModule;
// see if other incarnations contribute to the child package, too:
- boolean activeSave = primaryModule.isPackageLookupActive;
- primaryModule.isPackageLookupActive = true;
- try {
- for (PackageBinding incarnation : this.incarnations) {
- ModuleBinding moduleBinding = incarnation.enclosingModule;
- if (moduleBinding == module)
- continue;
- if (childPackage.isDeclaredIn(moduleBinding))
- continue;
- PackageBinding next = moduleBinding.getVisiblePackage(incarnation, name, false);
- childPackage = combine(next, childPackage, primaryModule);
- }
- return childPackage;
- } finally {
- primaryModule.isPackageLookupActive = activeSave;
+ char[] flatName = CharOperation.concatWith(childPackage.compoundName, '.');
+ for (PackageBinding incarnation : this.incarnations) {
+ ModuleBinding moduleBinding = incarnation.enclosingModule;
+ if (moduleBinding == module)
+ continue;
+ if (childPackage.isDeclaredIn(moduleBinding))
+ continue;
+ PlainPackageBinding next = moduleBinding.getDeclaredPackage(flatName);
+ childPackage = combine(next, childPackage, primaryModule);
}
+ return childPackage;
}
@Override
@@ -190,8 +191,9 @@ public class SplitPackageBinding extends PackageBinding {
return result;
}
- public PackageBinding getIncarnation(ModuleBinding requestedModule) {
- for (PackageBinding incarnation : this.incarnations) {
+ @Override
+ public PlainPackageBinding getIncarnation(ModuleBinding requestedModule) {
+ for (PlainPackageBinding incarnation : this.incarnations) {
if (incarnation.enclosingModule == requestedModule)
return incarnation;
}
@@ -209,27 +211,15 @@ public class SplitPackageBinding extends PackageBinding {
}
@Override
- ReferenceBinding getType0(char[] name) {
- ReferenceBinding knownType = super.getType0(name);
- if (knownType != null && !(knownType instanceof UnresolvedReferenceBinding))
- return knownType;
+ boolean hasType0Any(char[] name) {
+ if (super.hasType0Any(name))
+ return true;
- ReferenceBinding candidate = null;
for (PackageBinding incarnation : this.incarnations) {
- ReferenceBinding next = incarnation.getType0(name);
- if (next != null) {
- if (next.isValidBinding() && !(knownType instanceof UnresolvedReferenceBinding)) {
- if (candidate != null)
- return null; // unable to disambiguate without a module context
- candidate = next;
- }
- }
- }
- if (candidate != null) {
- addType(candidate);
+ if (incarnation.hasType0Any(name))
+ return true;
}
-
- return candidate;
+ return false;
}
/** Similar to getType0() but now we have a module and can ask the specific incarnation! */
@@ -266,11 +256,11 @@ public class SplitPackageBinding extends PackageBinding {
}
@Override
- public PackageBinding getVisibleFor(ModuleBinding clientModule, boolean preferLocal) {
+ public PackageBinding getVisibleFor(ModuleBinding clientModule, boolean preferLocal, boolean skipCUcheck) {
int visibleCount = 0;
- PackageBinding unique = null;
- for (PackageBinding incarnation : this.incarnations) {
- if (incarnation.hasCompilationUnit(false)) {
+ PlainPackageBinding unique = null;
+ for (PlainPackageBinding incarnation : this.incarnations) {
+ if (skipCUcheck || incarnation.hasCompilationUnit(false)) {
if (preferLocal && incarnation.enclosingModule == clientModule) {
return incarnation;
} else {
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/problem/ProblemReporter.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/problem/ProblemReporter.java
index 56cdae73b7..ab054e000d 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/problem/ProblemReporter.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/problem/ProblemReporter.java
@@ -10954,12 +10954,12 @@ public void invalidOpensStatement(OpensStatement statement, ModuleDeclaration mo
statement.declarationSourceStart, statement.declarationSourceEnd);
}
public void invalidPackageReference(int problem, PackageVisibilityStatement ref) {
- invalidPackageReference(problem, ref, ProblemSeverities.Error);
-}
-public void invalidPackageReference(int problem, PackageVisibilityStatement ref, int severity) {
- this.handle(problem, NoArgument, 0, new String[] { CharOperation.charToString(ref.pkgName) }, severity,
- ref.pkgRef.sourceStart, ref.pkgRef.sourceEnd, this.referenceContext,
- this.referenceContext == null ? null : this.referenceContext.compilationResult());
+ this.handle(problem,
+ NoArgument,
+ new String[] { CharOperation.charToString(ref.pkgName) },
+ ref.computeSeverity(problem),
+ ref.pkgRef.sourceStart,
+ ref.pkgRef.sourceEnd);
}
public void duplicateModuleReference(int problem, ModuleReference ref) {
this.handle(problem,
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/util/HashtableOfPackage.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/util/HashtableOfPackage.java
index c504b70791..abdfce15b5 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/util/HashtableOfPackage.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/util/HashtableOfPackage.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2009 IBM Corporation and others.
+ * Copyright (c) 2000, 2019 IBM Corporation and others.
*
* This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
@@ -13,13 +13,17 @@
*******************************************************************************/
package org.eclipse.jdt.internal.compiler.util;
+import java.util.Arrays;
+import java.util.Objects;
+import java.util.stream.Collectors;
+
import org.eclipse.jdt.core.compiler.CharOperation;
import org.eclipse.jdt.internal.compiler.lookup.PackageBinding;
-public final class HashtableOfPackage {
+public final class HashtableOfPackage<P extends PackageBinding> {
// to avoid using Enumerations, walk the individual tables skipping nulls
public char[] keyTable[];
- public PackageBinding valueTable[];
+ private PackageBinding valueTable[];
public int elementSize; // number of elements in the table
int threshold;
@@ -35,6 +39,12 @@ public HashtableOfPackage(int size) {
this.keyTable = new char[extraRoom][];
this.valueTable = new PackageBinding[extraRoom];
}
+public Iterable<P> values() {
+ return Arrays.stream(this.valueTable)
+ .filter(Objects::nonNull)
+ .map(p -> { @SuppressWarnings("unchecked") P theP = (P)p; return theP; })
+ .collect(Collectors.toList());
+}
public boolean containsKey(char[] key) {
int length = this.keyTable.length,
index = CharOperation.hashCode(key) % length;
@@ -49,14 +59,17 @@ public boolean containsKey(char[] key) {
}
return false;
}
-public PackageBinding get(char[] key) {
+public P get(char[] key) {
int length = this.keyTable.length,
index = CharOperation.hashCode(key) % length;
int keyLength = key.length;
char[] currentKey;
while ((currentKey = this.keyTable[index]) != null) {
- if (currentKey.length == keyLength && CharOperation.equals(currentKey, key))
- return this.valueTable[index];
+ if (currentKey.length == keyLength && CharOperation.equals(currentKey, key)) {
+ @SuppressWarnings("unchecked")
+ P p = (P) this.valueTable[index];
+ return p;
+ }
if (++index == length) {
index = 0;
}
@@ -84,7 +97,7 @@ public PackageBinding put(char[] key, PackageBinding value) {
return value;
}
private void rehash() {
- HashtableOfPackage newHashtable = new HashtableOfPackage(this.elementSize * 2); // double the number of expected elements
+ HashtableOfPackage<P> newHashtable = new HashtableOfPackage<P>(this.elementSize * 2); // double the number of expected elements
char[] currentKey;
for (int i = this.keyTable.length; --i >= 0;)
if ((currentKey = this.keyTable[i]) != null)
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 5595856759..ec2e0476d2 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
@@ -887,20 +887,11 @@ private void findPackagesFromRequires(char[] prefix, boolean isMatchAllPrefix, I
}
/**
- * @see org.eclipse.jdt.internal.compiler.env.IModuleAwareNameEnvironment#getModulesDeclaringPackage(char[][], char[], char[])
+ * @see org.eclipse.jdt.internal.compiler.env.IModuleAwareNameEnvironment#getModulesDeclaringPackage(char[][], char[])
*/
@Override
- public char[][] getModulesDeclaringPackage(char[][] parentPackageName, char[] name, char[] moduleName) {
- String[] pkgName;
- if (parentPackageName == null)
- pkgName = new String[] {new String(name)};
- else {
- int length = parentPackageName.length;
- pkgName = new String[length+1];
- for (int i = 0; i < length; i++)
- pkgName[i] = new String(parentPackageName[i]);
- pkgName[length] = new String(name);
- }
+ public char[][] getModulesDeclaringPackage(char[][] packageName, char[] moduleName) {
+ String[] pkgName = Arrays.stream(packageName).map(String::new).toArray(String[]::new);
LookupStrategy strategy = LookupStrategy.get(moduleName);
switch (strategy) {
case Named:
@@ -1145,4 +1136,26 @@ private void findPackagesFromRequires(char[] prefix, boolean isMatchAllPrefix, I
return Arrays.copyOf(sourceRoots, count);
return sourceRoots;
}
+
+ @Override
+ public char[][] listPackages(char[] moduleName) {
+ switch (LookupStrategy.get(moduleName)) {
+ case Named:
+ IPackageFragmentRoot[] packageRoots = findModuleContext(moduleName);
+ Set<String> packages = new HashSet<>();
+ for (IPackageFragmentRoot packageRoot : packageRoots) {
+ try {
+ for (IJavaElement javaElement : packageRoot.getChildren()) {
+ if (javaElement instanceof IPackageFragment && !((IPackageFragment) javaElement).isDefaultPackage())
+ packages.add(javaElement.getElementName());
+ }
+ } catch (JavaModelException e) {
+ Util.log(e, "Failed to retrieve packages from " + packageRoot); //$NON-NLS-1$
+ }
+ }
+ return packages.stream().map(String::toCharArray).toArray(char[][]::new);
+ default:
+ throw new UnsupportedOperationException("can list packages only of a named module"); //$NON-NLS-1$
+ }
+ }
}
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/ClasspathDirectory.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/ClasspathDirectory.java
index 3e01d29d8a..bffce17c78 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/ClasspathDirectory.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/ClasspathDirectory.java
@@ -14,10 +14,13 @@
package org.eclipse.jdt.internal.core.builder;
import java.io.IOException;
+import java.util.HashSet;
+import java.util.Set;
import java.util.function.Predicate;
import java.util.zip.ZipFile;
import org.eclipse.core.resources.IContainer;
+import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
@@ -254,4 +257,21 @@ public NameEnvironmentAnswer findClass(String typeName, String qualifiedPackageN
return findClass(typeName, qualifiedPackageName, moduleName, qualifiedBinaryFileName, false, null);
}
+@Override
+public char[][] listPackages() {
+ Set<String> packageNames = new HashSet<>();
+ IPath basePath = this.binaryFolder.getFullPath();
+ try {
+ this.binaryFolder.accept(r -> {
+ if (r instanceof IFile && SuffixConstants.EXTENSION_class.equals(r.getFileExtension().toLowerCase())) {
+ packageNames.add(r.getParent().getFullPath().makeRelativeTo(basePath).toString().replace('/', '.'));
+ }
+ return true;
+ });
+ } catch (CoreException e) {
+ Util.log(e, "Failed to scan packages of "+this.binaryFolder); //$NON-NLS-1$
+ }
+ return packageNames.stream().map(String::toCharArray).toArray(char[][]::new);
+}
+
}
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/ClasspathJar.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/ClasspathJar.java
index 27c8f298b1..c03f8a1ffe 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/ClasspathJar.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/ClasspathJar.java
@@ -18,6 +18,7 @@ package org.eclipse.jdt.internal.core.builder;
import java.io.File;
import java.io.IOException;
+import java.util.Arrays;
import java.util.Date;
import java.util.Enumeration;
import java.util.function.Predicate;
@@ -323,13 +324,15 @@ public boolean isPackage(String qualifiedPackageName, String moduleName) {
}
@Override
public boolean hasCompilationUnit(String pkgName, String moduleName) {
- for (Enumeration<? extends ZipEntry> e = this.zipFile.entries(); e.hasMoreElements(); ) {
- String fileName = e.nextElement().getName();
- if (fileName.startsWith(pkgName)
- && fileName.toLowerCase().endsWith(SuffixConstants.SUFFIX_STRING_class)
- && fileName.indexOf('/', pkgName.length()+1) == -1)
- return true;
- }
+ if (scanContent()) {
+ for (Enumeration<? extends ZipEntry> e = this.zipFile.entries(); e.hasMoreElements(); ) {
+ String fileName = e.nextElement().getName();
+ if (fileName.startsWith(pkgName)
+ && fileName.toLowerCase().endsWith(SuffixConstants.SUFFIX_STRING_class)
+ && fileName.indexOf('/', pkgName.length()+1) == -1)
+ return true;
+ }
+ }
return false;
}
@@ -399,4 +402,20 @@ public Manifest getManifest() {
}
return null;
}
+@Override
+public char[][] listPackages() {
+ if (!scanContent()) // ensure zipFile is initialized
+ return null;
+ char[][] result = new char[this.knownPackageNames.elementSize][];
+ int count = 0;
+ for (int i=0; i<this.knownPackageNames.values.length; i++) {
+ String string = (String) this.knownPackageNames.values[i];
+ if (string != null &&!string.isEmpty()) {
+ result[count++] = string.replace('/', '.').toCharArray();
+ }
+ }
+ if (count < result.length)
+ return Arrays.copyOf(result, count);
+ return result;
+}
}
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/ClasspathLocation.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/ClasspathLocation.java
index 52cd7e0c31..891aedec64 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/ClasspathLocation.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/ClasspathLocation.java
@@ -25,6 +25,7 @@ import org.eclipse.core.resources.IContainer;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
+import org.eclipse.jdt.core.compiler.CharOperation;
import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
import org.eclipse.jdt.internal.compiler.env.AccessRuleSet;
import org.eclipse.jdt.internal.compiler.env.IModule;
@@ -186,4 +187,7 @@ public char[][] singletonModuleNameIf(boolean condition) {
return new char[][] { this.module.name() };
return new char[][] { ModuleBinding.UNNAMED };
}
+public char[][] listPackages() {
+ return CharOperation.NO_CHAR_CHAR;
+}
}
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/ClasspathMultiDirectory.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/ClasspathMultiDirectory.java
index 8137e61ea8..9c6865e4a6 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/ClasspathMultiDirectory.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/ClasspathMultiDirectory.java
@@ -82,12 +82,31 @@ String[] directoryList(String qualifiedPackageName) {
IResource[] members = ((IContainer) container).members();
dirList = new String[members.length];
int index = 0;
- for (int i = 0, l = members.length; i < l; i++) {
- IResource m = members[i];
- String name = m.getName();
- if (m.getType() == IResource.FILE && org.eclipse.jdt.internal.compiler.util.Util.isClassFileName(name)) {
- // add exclusion pattern check here if we want to hide .class files
- dirList[index++] = name;
+ if (members.length > 0) {
+ for (int i = 0, l = members.length; i < l; i++) {
+ IResource m = members[i];
+ String name = m.getName();
+ if (m.getType() == IResource.FILE && org.eclipse.jdt.internal.compiler.util.Util.isClassFileName(name)) {
+ // add exclusion pattern check here if we want to hide .class files
+ dirList[index++] = name;
+ }
+ }
+ } else {
+ container = this.sourceFolder.findMember(qualifiedPackageName);
+ if (container instanceof IContainer) {
+ members = ((IContainer) container).members();
+ if (members.length > 0) {
+ dirList = new String[members.length];
+ index = 0;
+ for (int i = 0, l = members.length; i < l; i++) {
+ IResource m = members[i];
+ String name = m.getName();
+ if (m.getType() == IResource.FILE && org.eclipse.jdt.internal.compiler.util.Util.isJavaFileName(name)) {
+ // FIXME: check if .java file has any declarations?
+ dirList[index++] = name;
+ }
+ }
+ }
}
}
if (index < dirList.length)
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/ModulePathEntry.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/ModulePathEntry.java
index 61161cc2ea..f3332ed0b8 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/ModulePathEntry.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/ModulePathEntry.java
@@ -121,6 +121,18 @@ public class ModulePathEntry implements IModulePathEntry {
return false;
}
+ @Override
+ public char[][] listPackages() {
+ char[][] packages = CharOperation.NO_CHAR_CHAR;
+ if (this.isAutomaticModule) {
+ for (ClasspathLocation cp : this.locations) {
+ packages = CharOperation.arrayConcat(packages, cp.listPackages());
+ }
+ return packages;
+ }
+ return packages;
+ }
+
/**
* Combines an IMultiModuleEntry with further locations in order to support patch-module.
* Implemented by adding IMultiModuleEntry functionality to ModulePathEntry.
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/NameEnvironment.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/NameEnvironment.java
index ba00f5f45c..d94b9ac094 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/NameEnvironment.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/NameEnvironment.java
@@ -561,8 +561,8 @@ public NameEnvironmentAnswer findType(char[] typeName, char[][] packageName, cha
}
@Override
-public char[][] getModulesDeclaringPackage(char[][] parentPackageName, char[] name, char[] moduleName) {
- String pkgName = new String(CharOperation.concatWith(parentPackageName, name, '/'));
+public char[][] getModulesDeclaringPackage(char[][] packageName, char[] moduleName) {
+ String pkgName = new String(CharOperation.concatWith(packageName, '/'));
String modName = new String(moduleName);
LookupStrategy strategy = LookupStrategy.get(moduleName);
switch (strategy) {
@@ -685,7 +685,19 @@ public boolean isPackage(String qualifiedPackageName, char[] moduleName) {
}
return false;
}
-
+@Override
+public char[][] listPackages(char[] moduleName) {
+ LookupStrategy strategy = LookupStrategy.get(moduleName);
+ switch (strategy) {
+ case Named:
+ IModulePathEntry entry = this.modulePathEntries.get(String.valueOf(moduleName));
+ if (entry == null)
+ return CharOperation.NO_CHAR_CHAR;
+ return entry.listPackages();
+ default:
+ throw new UnsupportedOperationException("can list packages only of a named module"); //$NON-NLS-1$
+ }
+}
void setNames(String[] typeNames, SourceFile[] additionalFiles) {
// convert the initial typeNames to a set
if (typeNames == null) {
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/BindingKeyResolver.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/BindingKeyResolver.java
index 8d5a4c6045..722ce5b7f2 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/BindingKeyResolver.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/BindingKeyResolver.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2005, 2017 IBM Corporation and others.
+ * Copyright (c) 2005, 2019 IBM Corporation and others.
*
* This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
@@ -45,8 +45,8 @@ import org.eclipse.jdt.internal.compiler.lookup.LocalTypeBinding;
import org.eclipse.jdt.internal.compiler.lookup.LocalVariableBinding;
import org.eclipse.jdt.internal.compiler.lookup.LookupEnvironment;
import org.eclipse.jdt.internal.compiler.lookup.MethodBinding;
-import org.eclipse.jdt.internal.compiler.lookup.PackageBinding;
import org.eclipse.jdt.internal.compiler.lookup.ParameterizedTypeBinding;
+import org.eclipse.jdt.internal.compiler.lookup.PlainPackageBinding;
import org.eclipse.jdt.internal.compiler.lookup.PolymorphicMethodBinding;
import org.eclipse.jdt.internal.compiler.lookup.RawTypeBinding;
import org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding;
@@ -500,7 +500,7 @@ public class BindingKeyResolver extends BindingKeyParser {
@Override
public void consumePackage(char[] pkgName) {
this.compoundName = CharOperation.splitOn('/', pkgName);
- this.compilerBinding = new PackageBinding(this.compoundName, null, this.environment, this.environment.module); //TODO(SHMOD) enclosingModule
+ this.compilerBinding = new PlainPackageBinding(this.compoundName, null, this.environment, this.environment.module); //TODO(SHMOD) enclosingModule
}
@Override
diff --git a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/JavaSearchNameEnvironment.java b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/JavaSearchNameEnvironment.java
index db613ca5a3..083fbc04f5 100644
--- a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/JavaSearchNameEnvironment.java
+++ b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/JavaSearchNameEnvironment.java
@@ -328,8 +328,8 @@ public NameEnvironmentAnswer findType(char[][] compoundName, char[] moduleName)
}
@Override
-public char[][] getModulesDeclaringPackage(char[][] parentPackageName, char[] packageName, char[] moduleName) {
- String qualifiedPackageName = String.valueOf(CharOperation.concatWith(parentPackageName, packageName, '/'));
+public char[][] getModulesDeclaringPackage(char[][] packageName, char[] moduleName) {
+ String qualifiedPackageName = String.valueOf(CharOperation.concatWith(packageName, '/'));
LookupStrategy strategy = LookupStrategy.get(moduleName);
if (strategy == LookupStrategy.Named) {
if (this.moduleToClassPathLocations != null) {
@@ -359,6 +359,22 @@ public char[][] getModulesDeclaringPackage(char[][] parentPackageName, char[] pa
}
@Override
+public char[][] listPackages(char[] moduleName) { LookupStrategy strategy = LookupStrategy.get(moduleName);
+ switch (strategy) {
+ case Named:
+ if (this.moduleLocations != null) {
+ ClasspathLocation location = this.moduleLocations.get(String.valueOf(moduleName));
+ if (location == null)
+ return CharOperation.NO_CHAR_CHAR;
+ return location.listPackages();
+ }
+ return CharOperation.NO_CHAR_CHAR;
+ default:
+ throw new UnsupportedOperationException("can list packages only of a named module"); //$NON-NLS-1$
+ }
+}
+
+@Override
public boolean hasCompilationUnit(char[][] qualifiedPackageName, char[] moduleName, boolean checkCUs) {
String qualifiedPackageNameString = String.valueOf(CharOperation.concatWith(qualifiedPackageName, '/'));
LookupStrategy strategy = LookupStrategy.get(moduleName);

Back to the top