Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorStephan Herrmann2016-02-25 23:22:21 +0000
committerStephan Herrmann2016-02-28 16:24:55 +0000
commitc96202cbcb2ef06c10430e9d0f011fe30e627a82 (patch)
treecf91dd0d069e7c3777d45b63fe687e874a359d67
parenta620430067d64a8c379ef9bfad63016ee0485c9e (diff)
downloadeclipse.jdt.core-c96202cbcb2ef06c10430e9d0f011fe30e627a82.tar.gz
eclipse.jdt.core-c96202cbcb2ef06c10430e9d0f011fe30e627a82.tar.xz
eclipse.jdt.core-c96202cbcb2ef06c10430e9d0f011fe30e627a82.zip
Bug 488494: [null] external annotations should apply to project
dependencies, too Change-Id: I130fd707e7eaf20779518d118702e9fd3873ae09
-rw-r--r--org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/ExternalAnnotations18Test.java133
-rw-r--r--org.eclipse.jdt.core.tests.model/workspace/ExternalAnnotations18/Lib/.classpath6
-rw-r--r--org.eclipse.jdt.core.tests.model/workspace/ExternalAnnotations18/Lib/.project17
-rw-r--r--org.eclipse.jdt.core.tests.model/workspace/ExternalAnnotations18/Lib/src/libs/Arrays.java6
-rw-r--r--org.eclipse.jdt.core.tests.model/workspace/ExternalAnnotations18/Lib/src/libs/MyFunction.java10
-rw-r--r--org.eclipse.jdt.core.tests.model/workspace/ExternalAnnotations18/Lib/src/libs/MyMap.java6
-rw-r--r--org.eclipse.jdt.core.tests.model/workspace/ExternalAnnotations18/Test3b/.classpath6
-rw-r--r--org.eclipse.jdt.core.tests.model/workspace/ExternalAnnotations18/Test3b/.project17
-rw-r--r--org.eclipse.jdt.core.tests.model/workspace/ExternalAnnotations18/Test3b/src/test1/Reconcile2.java24
-rw-r--r--org.eclipse.jdt.core.tests.model/workspace/ExternalAnnotations18/Test3b/src/test1/Reconcile3.java19
-rw-r--r--org.eclipse.jdt.core/batch/org/eclipse/jdt/internal/compiler/batch/ClasspathDirectory.java4
-rw-r--r--org.eclipse.jdt.core/batch/org/eclipse/jdt/internal/compiler/batch/ClasspathJar.java4
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/classfmt/ExternalAnnotationProvider.java26
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/classfmt/NonNullDefaultAwareTypeAnnotationWalker.java4
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/env/NameEnvironmentAnswer.java10
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ExternalAnnotationSuperimposer.java269
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/LookupEnvironment.java8
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/SourceTypeBinding.java9
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/TypeBindingVisitor.java6
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/messages.properties3
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/util/Messages.java3
-rw-r--r--org.eclipse.jdt.core/model/org/eclipse/jdt/core/util/ExternalAnnotationUtil.java4
-rw-r--r--org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ExternalAnnotationTracker.java6
-rw-r--r--org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/NameLookup.java36
-rw-r--r--org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SearchableEnvironment.java14
-rw-r--r--org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/ClasspathDirectory.java25
-rw-r--r--org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/ClasspathLocation.java6
-rw-r--r--org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/ClasspathMultiDirectory.java4
-rw-r--r--org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/NameEnvironment.java6
-rw-r--r--org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/State.java7
-rw-r--r--org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/JavaSearchNameEnvironment.java15
31 files changed, 650 insertions, 63 deletions
diff --git a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/ExternalAnnotations18Test.java b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/ExternalAnnotations18Test.java
index 19c83637fe..0b4fd0544e 100644
--- a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/ExternalAnnotations18Test.java
+++ b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/ExternalAnnotations18Test.java
@@ -249,6 +249,22 @@ public class ExternalAnnotations18Test extends ModifyingResourceTests {
addClasspathEntry(this.project, entry);
}
+ protected void addProjectDependencyWithExternalAnnotations(
+ IJavaProject javaProject,
+ String referencedProjectName,
+ String externalAnnotationPath,
+ Map options) throws CoreException, IOException
+ {
+ IClasspathAttribute[] extraAttributes = new IClasspathAttribute[] { new ClasspathAttribute(IClasspathAttribute.EXTERNAL_ANNOTATION_PATH, externalAnnotationPath) };
+ IClasspathEntry entry = JavaCore.newProjectEntry(
+ new Path(referencedProjectName),
+ null/*access rules*/,
+ false/*combine access rules*/,
+ extraAttributes,
+ false/*exported*/);
+ addClasspathEntry(this.project, entry);
+ }
+
protected void createFileInProject(String projectRelativeFolder, String fileName, String content) throws CoreException {
String folderPath = this.project.getProject().getName()+'/'+projectRelativeFolder;
createFolder(folderPath);
@@ -1419,4 +1435,121 @@ public class ExternalAnnotations18Test extends ModifyingResourceTests {
Platform.removeLogListener(listener);
}
}
+
+ /** Lib exists as workspace project. Perform full build. */
+ public void testProjectDependencyFullBuild() throws Exception {
+ try {
+ setupJavaProject("Lib");
+ this.project.getProject().build(IncrementalProjectBuilder.FULL_BUILD, null);
+
+ setupJavaProject("Test1");
+ addProjectDependencyWithExternalAnnotations(this.project, "/Lib", "annots", null);
+ this.project.getProject().build(IncrementalProjectBuilder.FULL_BUILD, null);
+ IMarker[] markers = this.project.getProject().findMarkers(IJavaModelMarker.JAVA_MODEL_PROBLEM_MARKER, false, IResource.DEPTH_INFINITE);
+ assertNoMarkers(markers);
+ } finally {
+ deleteProject("Lib");
+ }
+ }
+
+ /** Lib exists as workspace project. Reconcile an individual CU. */
+ public void testProjectDependencyReconcile1() throws Exception {
+ try {
+ setupJavaProject("Lib");
+ this.project.getProject().build(IncrementalProjectBuilder.FULL_BUILD, null);
+ this.root = null; // prepare to get the root from project Test1
+
+ setupJavaProject("Test1");
+ addProjectDependencyWithExternalAnnotations(this.project, "/Lib", "annots", null);
+ IPackageFragment fragment = this.root.getPackageFragment("test1");
+ ICompilationUnit unit = fragment.getCompilationUnit("Test1.java").getWorkingCopy(new NullProgressMonitor());
+ CompilationUnit reconciled = unit.reconcile(AST.JLS8, true, null, new NullProgressMonitor());
+ IProblem[] problems = reconciled.getProblems();
+ assertNoProblems(problems);
+ } finally {
+ deleteProject("Lib");
+ }
+ }
+
+ /** Lib exists as workspace project. Type-Annotations in zip file. Reconcile an individual CU. */
+ public void testProjectDependencyReconcile2() throws Exception {
+ try {
+ setupJavaProject("Lib");
+ this.project.getProject().build(IncrementalProjectBuilder.FULL_BUILD, null);
+ this.root = null; // prepare to get the root from project Test1
+
+ setupJavaProject("Test3b");
+ Util.createSourceZip(
+ new String[] {
+ "libs/MyFunction.eea",
+ "class libs/MyFunction\n" +
+ " <T:R:>\n" +
+ "\n" +
+ "compose\n" +
+ " <V:Ljava/lang/Object;>(Llibs/MyFunction<-TV;+TT;>;)Llibs/MyFunction<TV;TR;>;\n" +
+ " <V:Ljava/lang/Object;>(Llibs/MyFunction<-TV;+T0T;>;)Llibs/MyFunction<TV;TR;>;\n" +
+ "\n",
+ "libs/Arrays.eea",
+ "class libs/Arrays\n" +
+ "\n" +
+ "array\n" +
+ " [Ljava/lang/String;\n" +
+ " [1L0java/lang/String;\n" +
+ "\n" +
+ "getArray\n" +
+ " ()[[Ljava/lang/String;\n" +
+ " ()[0[1L0java/lang/String;\n"
+ },
+ this.project.getProject().getLocation().toString()+"/annots.zip");
+ this.project.getProject().refreshLocal(1, new NullProgressMonitor());
+
+ addProjectDependencyWithExternalAnnotations(this.project, "/Lib", "annots.zip", null);
+ IPackageFragment fragment = this.root.getPackageFragment("test1");
+ ICompilationUnit unit = fragment.getCompilationUnit("Reconcile2.java").getWorkingCopy(new NullProgressMonitor());
+ CompilationUnit reconciled = unit.reconcile(AST.JLS8, true, null, new NullProgressMonitor());
+ IProblem[] problems = reconciled.getProblems();
+ assertNoProblems(problems);
+ } finally {
+ deleteProject("Lib");
+ }
+ }
+
+ /** Lib exists as workspace project. Invocations conflict with type parameter constraints. Reconcile an individual CU. */
+ public void testProjectDependencyReconcile3() throws Exception {
+ try {
+ setupJavaProject("Lib");
+ this.project.getProject().build(IncrementalProjectBuilder.FULL_BUILD, null);
+ this.root = null; // prepare to get the root from project Test1
+
+ setupJavaProject("Test3b");
+ Util.createSourceZip(
+ new String[] {
+ "libs/MyFunction.eea",
+ "class libs/MyFunction\n" +
+ " <T:R:>\n" +
+ " <T:1R:>\n" +
+ "\n" +
+ "compose\n" +
+ " <V:Ljava/lang/Object;>(Llibs/MyFunction<-TV;+TT;>;)Llibs/MyFunction<TV;TR;>;\n" +
+ " <1V:Ljava/lang/Object;>(Llibs/MyFunction<-TV;+TT;>;)Llibs/MyFunction<TV;TR;>;\n" +
+ "\n",
+ },
+ this.project.getProject().getLocation().toString()+"/annots.zip");
+ this.project.getProject().refreshLocal(1, new NullProgressMonitor());
+
+ addProjectDependencyWithExternalAnnotations(this.project, "/Lib", "annots.zip", null);
+ IPackageFragment fragment = this.root.getPackageFragment("test1");
+ ICompilationUnit unit = fragment.getCompilationUnit("Reconcile3.java").getWorkingCopy(new NullProgressMonitor());
+ CompilationUnit reconciled = unit.reconcile(AST.JLS8, true, null, new NullProgressMonitor());
+ for (IProblem iProblem : reconciled.getProblems()) {
+ System.out.println(iProblem);
+ }
+ assertProblems(reconciled.getProblems(), new String[] {
+ "Pb(964) Null constraint mismatch: The type '@Nullable B' is not a valid substitute for the type parameter '@NonNull R'",
+ "Pb(964) Null constraint mismatch: The type '@Nullable String' is not a valid substitute for the type parameter '@NonNull V'",
+ }, new int[] { 12, 17 });
+ } finally {
+ deleteProject("Lib");
+ }
+ }
}
diff --git a/org.eclipse.jdt.core.tests.model/workspace/ExternalAnnotations18/Lib/.classpath b/org.eclipse.jdt.core.tests.model/workspace/ExternalAnnotations18/Lib/.classpath
new file mode 100644
index 0000000000..f8a6de7d3b
--- /dev/null
+++ b/org.eclipse.jdt.core.tests.model/workspace/ExternalAnnotations18/Lib/.classpath
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+ <classpathentry kind="src" path="src"/>
+ <classpathentry kind="var" path="JCL18_LIB"/>
+ <classpathentry kind="output" path="bin"/>
+</classpath>
diff --git a/org.eclipse.jdt.core.tests.model/workspace/ExternalAnnotations18/Lib/.project b/org.eclipse.jdt.core.tests.model/workspace/ExternalAnnotations18/Lib/.project
new file mode 100644
index 0000000000..b68234a6fe
--- /dev/null
+++ b/org.eclipse.jdt.core.tests.model/workspace/ExternalAnnotations18/Lib/.project
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+ <name>Lib</name>
+ <comment></comment>
+ <projects>
+ </projects>
+ <buildSpec>
+ <buildCommand>
+ <name>org.eclipse.jdt.core.javabuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ </buildSpec>
+ <natures>
+ <nature>org.eclipse.jdt.core.javanature</nature>
+ </natures>
+</projectDescription>
diff --git a/org.eclipse.jdt.core.tests.model/workspace/ExternalAnnotations18/Lib/src/libs/Arrays.java b/org.eclipse.jdt.core.tests.model/workspace/ExternalAnnotations18/Lib/src/libs/Arrays.java
new file mode 100644
index 0000000000..29b7e159b8
--- /dev/null
+++ b/org.eclipse.jdt.core.tests.model/workspace/ExternalAnnotations18/Lib/src/libs/Arrays.java
@@ -0,0 +1,6 @@
+package libs;
+
+public class Arrays {
+ public String[][] getArray() { return null; }
+ public static final String[] array = new String[1] { null }
+} \ No newline at end of file
diff --git a/org.eclipse.jdt.core.tests.model/workspace/ExternalAnnotations18/Lib/src/libs/MyFunction.java b/org.eclipse.jdt.core.tests.model/workspace/ExternalAnnotations18/Lib/src/libs/MyFunction.java
new file mode 100644
index 0000000000..6f7bff6437
--- /dev/null
+++ b/org.eclipse.jdt.core.tests.model/workspace/ExternalAnnotations18/Lib/src/libs/MyFunction.java
@@ -0,0 +1,10 @@
+package libs;
+
+public interface MyFunction<T,R> {
+
+ R apply(T t);
+
+ default <V> MyFunction<V, R> compose(MyFunction<? super V, ? extends T> before) {
+ return (V v) -> apply(before.apply(v));
+ }
+} \ No newline at end of file
diff --git a/org.eclipse.jdt.core.tests.model/workspace/ExternalAnnotations18/Lib/src/libs/MyMap.java b/org.eclipse.jdt.core.tests.model/workspace/ExternalAnnotations18/Lib/src/libs/MyMap.java
new file mode 100644
index 0000000000..ad51f8d971
--- /dev/null
+++ b/org.eclipse.jdt.core.tests.model/workspace/ExternalAnnotations18/Lib/src/libs/MyMap.java
@@ -0,0 +1,6 @@
+package libs;
+public interface MyMap<K,V> {
+ V get(Object key);
+ V put(K key, V val);
+ V remove(Object key);
+}
diff --git a/org.eclipse.jdt.core.tests.model/workspace/ExternalAnnotations18/Test3b/.classpath b/org.eclipse.jdt.core.tests.model/workspace/ExternalAnnotations18/Test3b/.classpath
new file mode 100644
index 0000000000..1574d24895
--- /dev/null
+++ b/org.eclipse.jdt.core.tests.model/workspace/ExternalAnnotations18/Test3b/.classpath
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+ <classpathentry kind="src" path="src"/>
+ <classpathentry kind="con" path="org.eclipse.jdt.core.tests.model.TEST_CONTAINER"/>
+ <classpathentry kind="output" path="bin"/>
+</classpath>
diff --git a/org.eclipse.jdt.core.tests.model/workspace/ExternalAnnotations18/Test3b/.project b/org.eclipse.jdt.core.tests.model/workspace/ExternalAnnotations18/Test3b/.project
new file mode 100644
index 0000000000..ea7fde1523
--- /dev/null
+++ b/org.eclipse.jdt.core.tests.model/workspace/ExternalAnnotations18/Test3b/.project
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+ <name>Test3</name>
+ <comment></comment>
+ <projects>
+ </projects>
+ <buildSpec>
+ <buildCommand>
+ <name>org.eclipse.jdt.core.javabuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ </buildSpec>
+ <natures>
+ <nature>org.eclipse.jdt.core.javanature</nature>
+ </natures>
+</projectDescription>
diff --git a/org.eclipse.jdt.core.tests.model/workspace/ExternalAnnotations18/Test3b/src/test1/Reconcile2.java b/org.eclipse.jdt.core.tests.model/workspace/ExternalAnnotations18/Test3b/src/test1/Reconcile2.java
new file mode 100644
index 0000000000..385d7cb4c9
--- /dev/null
+++ b/org.eclipse.jdt.core.tests.model/workspace/ExternalAnnotations18/Test3b/src/test1/Reconcile2.java
@@ -0,0 +1,24 @@
+package test1;
+
+import org.eclipse.jdt.annotation.*;
+import libs.*;
+
+
+class A {}
+class B {}
+class C {}
+
+@NonNullByDefault
+public class Reconcile2 {
+ C test(MyFunction<A,@Nullable B> f1, MyFunction<B,C> f2, A a) {
+ return f2.compose(f1).apply(a); // actually incompatible, but we tweak compose to pretend it's compatible
+ }
+
+ void test2(Arrays lib) {
+ @Nullable String[]@NonNull[] arr = lib.getArray();
+ if (arr == null)
+ throw new NullPointerException(); // not dead code
+ @Nullable String @NonNull[] arr2 = Arrays.array;
+ Arrays.array[1] = null;
+ }
+} \ No newline at end of file
diff --git a/org.eclipse.jdt.core.tests.model/workspace/ExternalAnnotations18/Test3b/src/test1/Reconcile3.java b/org.eclipse.jdt.core.tests.model/workspace/ExternalAnnotations18/Test3b/src/test1/Reconcile3.java
new file mode 100644
index 0000000000..7a777c0d85
--- /dev/null
+++ b/org.eclipse.jdt.core.tests.model/workspace/ExternalAnnotations18/Test3b/src/test1/Reconcile3.java
@@ -0,0 +1,19 @@
+package test1;
+
+import org.eclipse.jdt.annotation.*;
+import libs.*;
+
+class A {}
+class B {}
+class C {}
+
+@NonNullByDefault
+public class Reconcile3 {
+ void test1(MyFunction<A,@Nullable B> f1) {
+ // nothing
+ }
+
+ void test2(MyFunction<A,@NonNull B> f2a, MyFunction<@Nullable String,@NonNull A> f2b) {
+ f2a.<@Nullable String>compose(f2b);
+ }
+} \ No newline at end of file
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 e94ec90857..c44d210567 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
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2015 IBM Corporation and others.
+ * Copyright (c) 2000, 2016 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -160,7 +160,7 @@ public NameEnvironmentAnswer findSecondaryInClass(char[] typeName, String qualif
public boolean hasAnnotationFileFor(String qualifiedTypeName) {
int pos = qualifiedTypeName.lastIndexOf('/');
if (pos != -1 && (pos + 1 < qualifiedTypeName.length())) {
- String fileName = qualifiedTypeName.substring(pos + 1) + '.' + ExternalAnnotationProvider.ANNOTION_FILE_EXTENSION;
+ String fileName = qualifiedTypeName.substring(pos + 1) + ExternalAnnotationProvider.ANNOTATION_FILE_SUFFIX;
return doesFileExist(fileName, qualifiedTypeName.substring(0, pos));
}
return false;
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 8d56c0a91b..77ad9037c3 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
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2015 IBM Corporation and others.
+ * Copyright (c) 2000, 2016 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -127,7 +127,7 @@ public NameEnvironmentAnswer findClass(char[] typeName, String qualifiedPackageN
}
@Override
public boolean hasAnnotationFileFor(String qualifiedTypeName) {
- return this.zipFile.getEntry(qualifiedTypeName+'.'+ExternalAnnotationProvider.ANNOTION_FILE_EXTENSION) != null;
+ return this.zipFile.getEntry(qualifiedTypeName+ExternalAnnotationProvider.ANNOTATION_FILE_SUFFIX) != null;
}
public char[][][] findTypeNames(String qualifiedPackageName) {
if (!isPackage(qualifiedPackageName))
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/classfmt/ExternalAnnotationProvider.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/classfmt/ExternalAnnotationProvider.java
index cbb2bc1cab..f58c49c5c4 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/classfmt/ExternalAnnotationProvider.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/classfmt/ExternalAnnotationProvider.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2014, 2015 GK Software AG.
+ * Copyright (c) 2014, 2016 GK Software AG.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -30,7 +30,7 @@ import org.eclipse.jdt.internal.compiler.util.Util;
public class ExternalAnnotationProvider {
- public static final String ANNOTION_FILE_EXTENSION= "eea"; //$NON-NLS-1$
+ public static final String ANNOTATION_FILE_EXTENSION= "eea"; //$NON-NLS-1$
public static final String CLASS_PREFIX = "class "; //$NON-NLS-1$
public static final String SUPER_PREFIX = "super "; //$NON-NLS-1$
@@ -46,7 +46,7 @@ public class ExternalAnnotationProvider {
*/
public static final char NO_ANNOTATION = '@';
- static final String ANNOTATION_FILE_SUFFIX = ".eea"; //$NON-NLS-1$
+ public static final String ANNOTATION_FILE_SUFFIX = ".eea"; //$NON-NLS-1$
private static final String TYPE_PARAMETER_PREFIX = " <"; //$NON-NLS-1$
@@ -69,8 +69,7 @@ public class ExternalAnnotationProvider {
}
private void initialize(InputStream input) throws IOException {
- LineNumberReader reader = new LineNumberReader(new InputStreamReader(input));
- try {
+ try (LineNumberReader reader = new LineNumberReader(new InputStreamReader(input))) {
assertClassHeader(reader.readLine(), this.typeName);
String line;
@@ -137,8 +136,6 @@ public class ExternalAnnotationProvider {
this.fieldAnnotationSources.put(selector+':'+rawSig, annotSig);
}
} while (((line = pendingLine) != null) || (line = reader.readLine()) != null);
- } finally {
- reader.close();
}
}
@@ -402,7 +399,7 @@ public class ExternalAnnotationProvider {
}
}
}
- return null;
+ return NO_ANNOTATIONS;
}
}
@@ -441,6 +438,19 @@ public class ExternalAnnotationProvider {
if ((depth == 0) && (i +1 < length) && (this.source[i+1] != Util.C_COLON))
pendingVariable = true;
break;
+ case Util.C_COLON :
+ if (depth == 0)
+ pendingVariable = true; // end of variable name
+ // skip optional bound ReferenceTypeSignature
+ i++; // peek next
+ while (i < length && this.source[i] == Util.C_ARRAY)
+ i++;
+ if (i < length && this.source[i] == Util.C_RESOLVED) {
+ while (i < length && this.source[i] != Util.C_NAME_END)
+ i++;
+ }
+ i--; // unget
+ break;
default:
if (pendingVariable) {
pendingVariable = false;
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/classfmt/NonNullDefaultAwareTypeAnnotationWalker.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/classfmt/NonNullDefaultAwareTypeAnnotationWalker.java
index 9fa7cbf580..f6092ac9cd 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/classfmt/NonNullDefaultAwareTypeAnnotationWalker.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/classfmt/NonNullDefaultAwareTypeAnnotationWalker.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2014 GK Software AG.
+ * Copyright (c) 2014, 2016 GK Software AG.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -176,7 +176,7 @@ public class NonNullDefaultAwareTypeAnnotationWalker extends TypeAnnotationWalke
@Override
public IBinaryAnnotation[] getAnnotationsAtCursor(int currentTypeId) {
- IBinaryAnnotation[] normalAnnotations = this.isEmpty ? null : super.getAnnotationsAtCursor(currentTypeId);
+ IBinaryAnnotation[] normalAnnotations = this.isEmpty ? NO_ANNOTATIONS : super.getAnnotationsAtCursor(currentTypeId);
if (this.atDefaultLocation &&
!(currentTypeId == -1) && // never apply default on type variable use or wildcard
!(this.atTypeBound && currentTypeId == TypeIds.T_JavaLangObject)) // for CLIMB-to-top consider a j.l.Object type bound as no explicit type bound
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/env/NameEnvironmentAnswer.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/env/NameEnvironmentAnswer.java
index f43f037784..bc79c2f51f 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/env/NameEnvironmentAnswer.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/env/NameEnvironmentAnswer.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2009 IBM Corporation and others.
+ * Copyright (c) 2000, 2016 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -17,6 +17,7 @@ public class NameEnvironmentAnswer {
ICompilationUnit compilationUnit;
ISourceType[] sourceTypes;
AccessRestriction accessRestriction;
+ String externalAnnotationPath; // should be an absolute file system path
public NameEnvironmentAnswer(IBinaryType binaryType, AccessRestriction accessRestriction) {
this.binaryType = binaryType;
@@ -28,9 +29,10 @@ public class NameEnvironmentAnswer {
this.accessRestriction = accessRestriction;
}
- public NameEnvironmentAnswer(ISourceType[] sourceTypes, AccessRestriction accessRestriction) {
+ public NameEnvironmentAnswer(ISourceType[] sourceTypes, AccessRestriction accessRestriction, String externalAnnotationPath) {
this.sourceTypes = sourceTypes;
this.accessRestriction = accessRestriction;
+ this.externalAnnotationPath = externalAnnotationPath;
}
/**
* Returns the associated access restriction, or null if none.
@@ -54,6 +56,10 @@ public class NameEnvironmentAnswer {
return this.compilationUnit;
}
+ public String getExternalAnnotationPath() {
+ return this.externalAnnotationPath;
+ }
+
/**
* Answer the unresolved source forms for the type or null if the
* receiver represents a compilation unit or binary type.
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ExternalAnnotationSuperimposer.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ExternalAnnotationSuperimposer.java
new file mode 100644
index 0000000000..781a451a89
--- /dev/null
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ExternalAnnotationSuperimposer.java
@@ -0,0 +1,269 @@
+/*******************************************************************************
+ * Copyright (c) 2016 GK Software AG.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Stephan Herrmann - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jdt.internal.compiler.lookup;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipFile;
+
+import org.eclipse.jdt.internal.compiler.classfmt.ExternalAnnotationProvider;
+import org.eclipse.jdt.internal.compiler.env.IBinaryAnnotation;
+import org.eclipse.jdt.internal.compiler.env.ITypeAnnotationWalker;
+import org.eclipse.jdt.internal.compiler.util.Messages;
+
+/**
+ * Used for superimposing external annotations (served by an {@link ITypeAnnotationWalker})
+ * over signatures of a {@link SourceTypeBinding}.
+ */
+class ExternalAnnotationSuperimposer extends TypeBindingVisitor {
+
+ public static void apply(SourceTypeBinding typeBinding, String externalAnnotationPath) {
+ ZipFile zipFile = null;
+ try {
+ File annotationBase = new File(externalAnnotationPath);
+ if (annotationBase.exists()) {
+ String binaryTypeName = String.valueOf(typeBinding.constantPoolName());
+ String relativeFileName = binaryTypeName.replace('.', '/')+ExternalAnnotationProvider.ANNOTATION_FILE_SUFFIX;
+
+ InputStream input;
+ if (annotationBase.isDirectory()) {
+ input = new FileInputStream(externalAnnotationPath+'/'+relativeFileName);
+ } else {
+ zipFile = new ZipFile(externalAnnotationPath);
+ ZipEntry zipEntry = zipFile.getEntry(relativeFileName);
+ if (zipEntry == null)
+ return;
+ input = zipFile.getInputStream(zipEntry);
+ }
+ annotateType(typeBinding, new ExternalAnnotationProvider(input, binaryTypeName), typeBinding.environment);
+ }
+ } catch (FileNotFoundException e) {
+ // file not found is expected
+ } catch (IOException e) {
+ typeBinding.scope.problemReporter().abortDueToInternalError(Messages.bind(Messages.abort_externaAnnotationFile,
+ new String[] {String.valueOf(typeBinding.readableName()), externalAnnotationPath, e.getMessage()}));
+ } finally {
+ if (zipFile != null)
+ try {
+ zipFile.close();
+ } catch (IOException e) {
+ // nothing
+ }
+ }
+ }
+
+ static void annotateType(SourceTypeBinding binding, ExternalAnnotationProvider provider, LookupEnvironment environment) {
+ ITypeAnnotationWalker typeWalker = provider.forTypeHeader(environment);
+ if (typeWalker != null && typeWalker != ITypeAnnotationWalker.EMPTY_ANNOTATION_WALKER) {
+ ExternalAnnotationSuperimposer visitor = new ExternalAnnotationSuperimposer(environment);
+ TypeVariableBinding[] typeParameters = binding.typeVariables();
+ for (int i = 0; i < typeParameters.length; i++) {
+ if (visitor.go(typeWalker.toTypeParameter(true, i)))
+ typeParameters[i] = visitor.superimpose(typeParameters[i], TypeVariableBinding.class);
+ }
+ }
+ binding.externalAnnotationProvider = provider; // for superimposing method signatures
+ }
+
+ public static void annotateFieldBinding(FieldBinding field, ExternalAnnotationProvider provider, LookupEnvironment environment) {
+ char[] fieldSignature = field.genericSignature();
+ if (fieldSignature == null && field.type != null)
+ fieldSignature = field.type.signature();
+ ITypeAnnotationWalker walker = provider.forField(field.name, fieldSignature, environment);
+ ExternalAnnotationSuperimposer visitor = new ExternalAnnotationSuperimposer(environment);
+ if (visitor.go(walker))
+ field.type = visitor.superimpose(field.type, TypeBinding.class);
+ }
+
+ public static void annotateMethodBinding(MethodBinding method, ExternalAnnotationProvider provider, LookupEnvironment environment) {
+ char[] methodSignature = method.genericSignature();
+ if (methodSignature == null)
+ methodSignature = method.signature();
+ ITypeAnnotationWalker walker = provider.forMethod(method.selector, methodSignature, environment);
+ if (walker != null && walker != ITypeAnnotationWalker.EMPTY_ANNOTATION_WALKER) {
+ ExternalAnnotationSuperimposer visitor = new ExternalAnnotationSuperimposer(environment);
+ TypeVariableBinding[] typeParams = method.typeVariables;
+ for (short i = 0; i < typeParams.length; i++) {
+ if (visitor.go(walker.toTypeParameter(false, i)))
+ typeParams[i] = visitor.superimpose(typeParams[i], TypeVariableBinding.class);
+ }
+ if (!method.isConstructor()) {
+ if (visitor.go(walker.toMethodReturn()))
+ method.returnType = visitor.superimpose(method.returnType, TypeBinding.class);
+ }
+ TypeBinding[] parameters = method.parameters;
+ for (short i = 0; i < parameters.length; i++) {
+ if (visitor.go(walker.toMethodParameter(i)))
+ parameters[i] = visitor.superimpose(parameters[i], TypeBinding.class);
+ }
+ }
+ }
+
+ private ITypeAnnotationWalker currentWalker;
+ private TypeBinding typeReplacement;
+ private LookupEnvironment environment;
+ private boolean isReplacing;
+
+ ExternalAnnotationSuperimposer(LookupEnvironment environment) {
+ this.environment = environment;
+ }
+
+ /** for constructing a memento of the superimposer's current state. */
+ private ExternalAnnotationSuperimposer(TypeBinding typeReplacement, boolean isReplacing, ITypeAnnotationWalker walker) {
+ this.typeReplacement = typeReplacement;
+ this.isReplacing = isReplacing;
+ this.currentWalker = walker;
+ }
+ private ExternalAnnotationSuperimposer snapshot() {
+ ExternalAnnotationSuperimposer memento = new ExternalAnnotationSuperimposer(this.typeReplacement, this.isReplacing, this.currentWalker);
+ // soft reset:
+ this.typeReplacement = null;
+ this.isReplacing = false;
+ return memento;
+ }
+ private void restore(ExternalAnnotationSuperimposer memento) {
+ this.isReplacing = memento.isReplacing;
+ this.currentWalker = memento.currentWalker;
+ }
+
+ boolean go(ITypeAnnotationWalker walker) {
+ // hard reset:
+ reset();
+ this.typeReplacement = null;
+ this.isReplacing = false;
+ // and start anew:
+ this.currentWalker = walker;
+ return walker != ITypeAnnotationWalker.EMPTY_ANNOTATION_WALKER;
+ }
+
+ <T extends TypeBinding> T superimpose(T type, Class<? extends T> cl) {
+ TypeBindingVisitor.visit(this, type);
+ if (cl.isInstance(this.typeReplacement))
+ return cl.cast(this.typeReplacement);
+ return type;
+ }
+
+ private TypeBinding goAndSuperimpose(ITypeAnnotationWalker walker, TypeBinding type) {
+ // no reset here
+ if (walker == ITypeAnnotationWalker.EMPTY_ANNOTATION_WALKER)
+ return type;
+ this.currentWalker = walker;
+
+ TypeBindingVisitor.visit(this, type);
+
+ if (this.typeReplacement == null)
+ return type;
+ this.isReplacing = true;
+ TypeBinding answer = this.typeReplacement;
+ this.typeReplacement = null;
+ return answer;
+ }
+
+ @Override
+ public boolean visit(ArrayBinding arrayBinding) {
+ ExternalAnnotationSuperimposer memento = snapshot();
+ try {
+ int dims = arrayBinding.dimensions;
+ AnnotationBinding[][] annotsOnDims = new AnnotationBinding[dims][];
+ ITypeAnnotationWalker walker = this.currentWalker;
+ for (int i = 0; i < dims; i++) {
+ IBinaryAnnotation[] binaryAnnotations = walker.getAnnotationsAtCursor(arrayBinding.id);
+ if (binaryAnnotations != ITypeAnnotationWalker.NO_ANNOTATIONS) {
+ annotsOnDims[i] = BinaryTypeBinding.createAnnotations(binaryAnnotations, this.environment, null);
+ this.isReplacing = true;
+ } else {
+ annotsOnDims[i] = Binding.NO_ANNOTATIONS;
+ }
+ walker = walker.toNextArrayDimension();
+ }
+ TypeBinding leafComponentType = goAndSuperimpose(walker, arrayBinding.leafComponentType());
+ if (this.isReplacing) {
+ this.typeReplacement = this.environment.createArrayType(leafComponentType, dims, AnnotatableTypeSystem.flattenedAnnotations(annotsOnDims));
+ }
+ } finally {
+ restore(memento);
+ }
+ return false;
+ }
+ @Override
+ public boolean visit(BaseTypeBinding baseTypeBinding) {
+ return false; // no null annotations
+ }
+ @Override
+ public boolean visit(IntersectionTypeBinding18 intersectionTypeBinding18) {
+ return false; // shouldn't occur in declarations
+ }
+ @Override
+ public boolean visit(ParameterizedTypeBinding parameterizedTypeBinding) {
+ ExternalAnnotationSuperimposer memento = snapshot();
+ try {
+ IBinaryAnnotation[] binaryAnnotations = this.currentWalker.getAnnotationsAtCursor(parameterizedTypeBinding.id);
+ AnnotationBinding[] annotations = Binding.NO_ANNOTATIONS;
+ if (binaryAnnotations != ITypeAnnotationWalker.NO_ANNOTATIONS) {
+ annotations = BinaryTypeBinding.createAnnotations(binaryAnnotations, this.environment, null);
+ this.isReplacing = true;
+ }
+
+ TypeBinding[] typeArguments = parameterizedTypeBinding.typeArguments();
+ TypeBinding[] newArguments = new TypeBinding[typeArguments.length];
+ for (int i = 0; i < typeArguments.length; i++) {
+ newArguments[i] = goAndSuperimpose(memento.currentWalker.toTypeArgument(i), typeArguments[i]);
+ }
+ if (this.isReplacing)
+ this.typeReplacement = this.environment.createParameterizedType(parameterizedTypeBinding.genericType(), newArguments, parameterizedTypeBinding.enclosingType(), annotations);
+ return false;
+ } finally {
+ restore(memento);
+ }
+ }
+ @Override
+ public boolean visit(RawTypeBinding rawTypeBinding) {
+ return visit((ReferenceBinding)rawTypeBinding);
+ }
+ @Override
+ public boolean visit(ReferenceBinding referenceBinding) {
+ IBinaryAnnotation[] binaryAnnotations = this.currentWalker.getAnnotationsAtCursor(referenceBinding.id);
+ if (binaryAnnotations != ITypeAnnotationWalker.NO_ANNOTATIONS)
+ this.typeReplacement = this.environment.createAnnotatedType(referenceBinding, BinaryTypeBinding.createAnnotations(binaryAnnotations, this.environment, null));
+ return false;
+ }
+ @Override
+ public boolean visit(TypeVariableBinding typeVariable) {
+ return visit((ReferenceBinding) typeVariable);
+ }
+ @Override
+ public boolean visit(WildcardBinding wildcardBinding) {
+ TypeBinding bound = wildcardBinding.bound;
+ ExternalAnnotationSuperimposer memento = snapshot();
+ try {
+ if (bound != null) {
+ bound = goAndSuperimpose(memento.currentWalker.toWildcardBound(), bound);
+ }
+ IBinaryAnnotation[] binaryAnnotations = memento.currentWalker.getAnnotationsAtCursor(-1);
+ if (this.isReplacing || binaryAnnotations != ITypeAnnotationWalker.NO_ANNOTATIONS) {
+ TypeBinding[] otherBounds = wildcardBinding.otherBounds;
+ if (binaryAnnotations != ITypeAnnotationWalker.NO_ANNOTATIONS) {
+ AnnotationBinding[] annotations = BinaryTypeBinding.createAnnotations(binaryAnnotations, this.environment, null);
+ this.typeReplacement = this.environment.createWildcard(wildcardBinding.genericType, wildcardBinding.rank, bound, otherBounds, wildcardBinding.boundKind, annotations);
+ } else {
+ this.typeReplacement = this.environment.createWildcard(wildcardBinding.genericType, wildcardBinding.rank, bound, otherBounds, wildcardBinding.boundKind);
+ }
+ }
+ } finally {
+ restore(memento);
+ }
+ return false;
+ }
+}
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 15c5aac3d6..b233099fc5 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
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2015 IBM Corporation and others.
+ * Copyright (c) 2000, 2016 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -190,6 +190,12 @@ ReferenceBinding askForType(PackageBinding packageBinding, char[] name) {
} else if (answer.isSourceType()) {
// the type was found as a source model
this.typeRequestor.accept(answer.getSourceTypes(), packageBinding, answer.getAccessRestriction());
+ ReferenceBinding binding = packageBinding.getType0(name);
+ String externalAnnotationPath = answer.getExternalAnnotationPath();
+ if (externalAnnotationPath != null && this.globalOptions.isAnnotationBasedNullAnalysisEnabled && binding instanceof SourceTypeBinding) {
+ ExternalAnnotationSuperimposer.apply((SourceTypeBinding) binding, externalAnnotationPath);
+ }
+ return binding;
}
return packageBinding.getType0(name);
}
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/SourceTypeBinding.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/SourceTypeBinding.java
index c4a5e723fe..7ae4663504 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/SourceTypeBinding.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/SourceTypeBinding.java
@@ -65,6 +65,7 @@ import org.eclipse.jdt.internal.compiler.ast.TypeParameter;
import org.eclipse.jdt.internal.compiler.ast.TypeReference;
import org.eclipse.jdt.internal.compiler.ast.TypeReference.AnnotationPosition;
import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
+import org.eclipse.jdt.internal.compiler.classfmt.ExternalAnnotationProvider;
import org.eclipse.jdt.internal.compiler.impl.CompilerOptions;
import org.eclipse.jdt.internal.compiler.impl.Constant;
import org.eclipse.jdt.internal.compiler.problem.ProblemSeverities;
@@ -101,6 +102,8 @@ public class SourceTypeBinding extends ReferenceBinding {
private int nullnessDefaultInitialized = 0; // 0: nothing; 1: type; 2: package
private int lambdaOrdinal = 0;
private ReferenceBinding containerAnnotationType = null;
+
+ public ExternalAnnotationProvider externalAnnotationProvider;
public SourceTypeBinding(char[][] compoundName, PackageBinding fPackage, ClassScope scope) {
this.compoundName = compoundName;
@@ -1773,6 +1776,9 @@ public FieldBinding resolveTypeFor(FieldBinding field) {
} finally {
initializationScope.initializedField = previousField;
}
+ if (this.externalAnnotationProvider != null) {
+ ExternalAnnotationSuperimposer.annotateFieldBinding(field, this.externalAnnotationProvider, this.environment);
+ }
return field;
}
return null; // should never reach this point
@@ -1995,6 +2001,9 @@ public MethodBinding resolveTypesFor(MethodBinding method) {
return method; // but its still unresolved with a null return type & is still connected to its method declaration
method.modifiers &= ~ExtraCompilerModifiers.AccUnresolved;
+ if (this.externalAnnotationProvider != null) {
+ ExternalAnnotationSuperimposer.annotateMethodBinding(method, this.externalAnnotationProvider, this.environment);
+ }
return method;
}
// https://bugs.eclipse.org/bugs/show_bug.cgi?id=391108
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/TypeBindingVisitor.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/TypeBindingVisitor.java
index a77994e178..ad71838602 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/TypeBindingVisitor.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/TypeBindingVisitor.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2013 IBM Corporation and others.
+ * Copyright (c) 2013, 2016 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -18,6 +18,10 @@ public class TypeBindingVisitor {
private SimpleLookupTable visitedCache;
+ public void reset() {
+ this.visitedCache = null;
+ }
+
public boolean visit(BaseTypeBinding baseTypeBinding) {
return true; // continue traversal.
}
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/messages.properties b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/messages.properties
index 614d5acbce..1d1a5bbb80 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/messages.properties
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/messages.properties
@@ -1,5 +1,5 @@
###############################################################################
-# Copyright (c) 2000, 2009 IBM Corporation and others.
+# Copyright (c) 2000, 2016 IBM Corporation and others.
# All rights reserved. This program and the accompanying materials
# are made available under the terms of the Eclipse Public License v1.0
# which accompanies this distribution, and is available at
@@ -39,6 +39,7 @@ abort_invalidExceptionAttribute = SANITY CHECK: Invalid attribute for exception
abort_missingCode = Missing code implementation in the compiler
abort_againstSourceModel = Cannot compile against source model {0} issued from {1}
abort_invalidOpcode = SANITY CHECK: Invalid opcode {0} at pc {1} for stackmap table attribute for method {2}
+abort_externaAnnotationFile = Failed to read external annotations for {0} from {1} due to an exception: {2}
### accept
accept_cannot = Cannot accept the compilation unit:
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/util/Messages.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/util/Messages.java
index 5eded19ddc..317d830ece 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/util/Messages.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/util/Messages.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2013 IBM Corporation and others.
+ * Copyright (c) 2000, 2016 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -100,6 +100,7 @@ public final class Messages {
public static String abort_invalidOpcode;
public static String abort_missingCode;
public static String abort_againstSourceModel;
+ public static String abort_externaAnnotationFile;
public static String accept_cannot;
public static String parser_incorrectPath;
public static String parser_moveFiles;
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/util/ExternalAnnotationUtil.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/util/ExternalAnnotationUtil.java
index 2ecd344e75..6d15fb2556 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/util/ExternalAnnotationUtil.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/util/ExternalAnnotationUtil.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2015 GK Software AG.
+ * Copyright (c) 2015, 2016 GK Software AG.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -185,7 +185,7 @@ public final class ExternalAnnotationUtil {
return null;
}
- annotationPath = annotationPath.append(binaryTypeName).addFileExtension(ExternalAnnotationProvider.ANNOTION_FILE_EXTENSION);
+ annotationPath = annotationPath.append(binaryTypeName).addFileExtension(ExternalAnnotationProvider.ANNOTATION_FILE_EXTENSION);
return workspaceRoot.getFile(annotationPath);
}
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ExternalAnnotationTracker.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ExternalAnnotationTracker.java
index 19c4747ef0..cc5d4f1880 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ExternalAnnotationTracker.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ExternalAnnotationTracker.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2015 GK Software AG.
+ * Copyright (c) 2015, 2016 GK Software AG.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -149,7 +149,7 @@ public class ExternalAnnotationTracker implements IResourceChangeListener {
if (baseDepth == 0) {
Util.log(new IllegalArgumentException("annotationBase cannot be empty")); //$NON-NLS-1$
} else {
- relativeAnnotationPath = relativeAnnotationPath.addFileExtension(ExternalAnnotationProvider.ANNOTION_FILE_EXTENSION);
+ relativeAnnotationPath = relativeAnnotationPath.addFileExtension(ExternalAnnotationProvider.ANNOTATION_FILE_EXTENSION);
DirectoryNode base = singleton.getAnnotationBase(singleton.tree, annotationBase, baseDepth, 1);
base.registerClassFile(relativeAnnotationPath, classFile);
}
@@ -166,7 +166,7 @@ public class ExternalAnnotationTracker implements IResourceChangeListener {
if (baseDepth == 0) {
Util.log(new IllegalArgumentException("annotationBase cannot be empty")); //$NON-NLS-1$
} else {
- relativeAnnotationPath = relativeAnnotationPath.addFileExtension(ExternalAnnotationProvider.ANNOTION_FILE_EXTENSION);
+ relativeAnnotationPath = relativeAnnotationPath.addFileExtension(ExternalAnnotationProvider.ANNOTATION_FILE_EXTENSION);
DirectoryNode base = singleton.getAnnotationBase(singleton.tree, annotationBase, baseDepth, 1);
base.unregisterClassFile(relativeAnnotationPath);
}
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/NameLookup.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/NameLookup.java
index 517b19bc18..58ea8fe8d7 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/NameLookup.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/NameLookup.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2014 IBM Corporation and others.
+ * Copyright (c) 2000, 2016 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -61,9 +61,11 @@ public class NameLookup implements SuffixConstants {
public static class Answer {
public IType type;
AccessRestriction restriction;
- Answer(IType type, AccessRestriction restriction) {
+ IClasspathEntry entry;
+ Answer(IType type, AccessRestriction restriction, IClasspathEntry entry) {
this.type = type;
this.restriction = restriction;
+ this.entry = entry;
}
public boolean ignoreIfBetter() {
return this.restriction != null && this.restriction.ignoreIfBetter();
@@ -663,10 +665,14 @@ public class NameLookup implements SuffixConstants {
type = findType(typeName, packages[i], partialMatch, acceptFlags, waitForIndexes, considerSecondaryTypes);
if (type != null) {
AccessRestriction accessRestriction = null;
- if (checkRestrictions) {
- accessRestriction = getViolatedRestriction(typeName, packageName, type, accessRestriction);
+ PackageFragmentRoot root = (PackageFragmentRoot) type.getAncestor(IJavaElement.PACKAGE_FRAGMENT_ROOT);
+ ClasspathEntry entry = (ClasspathEntry) this.rootToResolvedEntries.get(root);
+ if (entry != null) { // reverse map always contains resolved CP entry
+ if (checkRestrictions) {
+ accessRestriction = getViolatedRestriction(typeName, packageName, entry, accessRestriction);
+ }
}
- Answer answer = new Answer(type, accessRestriction);
+ Answer answer = new Answer(type, accessRestriction, entry);
if (!answer.ignoreIfBetter()) {
if (answer.isBetter(suggestedAnswer))
return answer;
@@ -722,20 +728,16 @@ public class NameLookup implements SuffixConstants {
if (!typeFound) type = null;
}
}
- return type == null ? null : new Answer(type, null);
+ return type == null ? null : new Answer(type, null, null);
}
- private AccessRestriction getViolatedRestriction(String typeName, String packageName, IType type, AccessRestriction accessRestriction) {
- PackageFragmentRoot root = (PackageFragmentRoot) type.getAncestor(IJavaElement.PACKAGE_FRAGMENT_ROOT);
- ClasspathEntry entry = (ClasspathEntry) this.rootToResolvedEntries.get(root);
- if (entry != null) { // reverse map always contains resolved CP entry
- AccessRuleSet accessRuleSet = entry.getAccessRuleSet();
- if (accessRuleSet != null) {
- // TODO (philippe) improve char[] <-> String conversions to avoid performing them on the fly
- char[][] packageChars = CharOperation.splitOn('.', packageName.toCharArray());
- char[] typeChars = typeName.toCharArray();
- accessRestriction = accessRuleSet.getViolatedRestriction(CharOperation.concatWith(packageChars, typeChars, '/'));
- }
+ private AccessRestriction getViolatedRestriction(String typeName, String packageName, ClasspathEntry entry, AccessRestriction accessRestriction) {
+ AccessRuleSet accessRuleSet = entry.getAccessRuleSet();
+ if (accessRuleSet != null) {
+ // TODO (philippe) improve char[] <-> String conversions to avoid performing them on the fly
+ char[][] packageChars = CharOperation.splitOn('.', packageName.toCharArray());
+ char[] typeChars = typeName.toCharArray();
+ accessRestriction = accessRuleSet.getViolatedRestriction(CharOperation.concatWith(packageChars, typeChars, '/'));
}
return accessRestriction;
}
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 8dc74b2600..c44cba3422 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
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2015 IBM Corporation and others.
+ * Copyright (c) 2000, 2016 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -11,6 +11,7 @@
*******************************************************************************/
package org.eclipse.jdt.internal.core;
+import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.OperationCanceledException;
import org.eclipse.jdt.core.*;
@@ -136,7 +137,7 @@ public class SearchableEnvironment
if (!otherType.equals(topLevelType) && index < length) // check that the index is in bounds (see https://bugs.eclipse.org/bugs/show_bug.cgi?id=62861)
sourceTypes[index++] = otherType;
}
- return new NameEnvironmentAnswer(sourceTypes, answer.restriction);
+ return new NameEnvironmentAnswer(sourceTypes, answer.restriction, getExternalAnnotationPath(answer.entry));
} catch (JavaModelException jme) {
if (jme.isDoesNotExist() && String.valueOf(TypeConstants.PACKAGE_INFO_NAME).equals(typeName)) {
// in case of package-info.java the type doesn't exist in the model,
@@ -150,6 +151,15 @@ public class SearchableEnvironment
return null;
}
+ private String getExternalAnnotationPath(IClasspathEntry entry) {
+ if (entry == null)
+ return null;
+ IPath path = ClasspathEntry.getExternalAnnotationPath(entry, this.project.getProject(), true);
+ if (path == null)
+ return null;
+ return path.toOSString();
+ }
+
/**
* Find the packages that start with the given prefix.
* A valid prefix is a qualified name separated by periods
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 63c8de7c5e..72917d5716 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
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2009 IBM Corporation and others.
+ * Copyright (c) 2000, 2016 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -11,6 +11,7 @@
package org.eclipse.jdt.internal.core.builder;
import java.io.IOException;
+import java.util.zip.ZipFile;
import org.eclipse.core.resources.*;
import org.eclipse.core.runtime.*;
@@ -30,15 +31,26 @@ boolean isOutputFolder;
SimpleLookupTable directoryCache;
String[] missingPackageHolder = new String[1];
AccessRuleSet accessRuleSet;
+ZipFile annotationZipFile;
+String externalAnnotationPath;
-ClasspathDirectory(IContainer binaryFolder, boolean isOutputFolder, AccessRuleSet accessRuleSet) {
+ClasspathDirectory(IContainer binaryFolder, boolean isOutputFolder, AccessRuleSet accessRuleSet, IPath externalAnnotationPath) {
this.binaryFolder = binaryFolder;
this.isOutputFolder = isOutputFolder || binaryFolder.getProjectRelativePath().isEmpty(); // if binaryFolder == project, then treat it as an outputFolder
this.directoryCache = new SimpleLookupTable(5);
this.accessRuleSet = accessRuleSet;
+ if (externalAnnotationPath != null)
+ this.externalAnnotationPath = externalAnnotationPath.toOSString();
}
public void cleanup() {
+ if (this.annotationZipFile != null) {
+ try {
+ this.annotationZipFile.close();
+ } catch(IOException e) { // ignore it
+ }
+ this.annotationZipFile = null;
+ }
this.directoryCache = null;
}
@@ -106,9 +118,16 @@ public NameEnvironmentAnswer findClass(String binaryFileName, String qualifiedPa
return null;
}
if (reader != null) {
+ String fileNameWithoutExtension = qualifiedBinaryFileName.substring(0, qualifiedBinaryFileName.length() - SuffixConstants.SUFFIX_CLASS.length);
+ if (this.externalAnnotationPath != null) {
+ try {
+ this.annotationZipFile = reader.setExternalAnnotationProvider(this.externalAnnotationPath, fileNameWithoutExtension, this.annotationZipFile, null);
+ } catch (IOException e) {
+ // don't let error on annotations fail class reading
+ }
+ }
if (this.accessRuleSet == null)
return new NameEnvironmentAnswer(reader, null);
- String fileNameWithoutExtension = qualifiedBinaryFileName.substring(0, qualifiedBinaryFileName.length() - SuffixConstants.SUFFIX_CLASS.length);
return new NameEnvironmentAnswer(reader, this.accessRuleSet.getViolatedRestriction(fileNameWithoutExtension.toCharArray()));
}
return null;
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 343abc086f..8758a86628 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
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2015 IBM Corporation and others.
+ * Copyright (c) 2000, 2016 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -24,8 +24,8 @@ static ClasspathLocation forSourceFolder(IContainer sourceFolder, IContainer out
return new ClasspathMultiDirectory(sourceFolder, outputFolder, inclusionPatterns, exclusionPatterns, ignoreOptionalProblems);
}
-public static ClasspathLocation forBinaryFolder(IContainer binaryFolder, boolean isOutputFolder, AccessRuleSet accessRuleSet) {
- return new ClasspathDirectory(binaryFolder, isOutputFolder, accessRuleSet);
+public static ClasspathLocation forBinaryFolder(IContainer binaryFolder, boolean isOutputFolder, AccessRuleSet accessRuleSet, IPath externalAnnotationPath) {
+ return new ClasspathDirectory(binaryFolder, isOutputFolder, accessRuleSet, externalAnnotationPath);
}
static ClasspathLocation forLibrary(String libraryPathname, long lastModified, AccessRuleSet accessRuleSet, IPath annotationsPath) {
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 3d41e087a9..991e98ec68 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
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2012 IBM Corporation and others.
+ * Copyright (c) 2000, 2016 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -24,7 +24,7 @@ boolean hasIndependentOutputFolder; // if output folder is not equal to any of t
public boolean ignoreOptionalProblems;
ClasspathMultiDirectory(IContainer sourceFolder, IContainer binaryFolder, char[][] inclusionPatterns, char[][] exclusionPatterns, boolean ignoreOptionalProblems) {
- super(binaryFolder, true, null);
+ super(binaryFolder, true, null, null);
this.sourceFolder = sourceFolder;
this.inclusionPatterns = inclusionPatterns;
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 060bb205a9..c1509e1804 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
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2015 IBM Corporation and others.
+ * Copyright (c) 2000, 2016 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -146,7 +146,7 @@ private void computeClasspathLocations(
: (IContainer) root.getFolder(prereqOutputPath);
if (binaryFolder.exists() && !seen.contains(binaryFolder)) {
seen.add(binaryFolder);
- ClasspathLocation bLocation = ClasspathLocation.forBinaryFolder(binaryFolder, true, entry.getAccessRuleSet());
+ ClasspathLocation bLocation = ClasspathLocation.forBinaryFolder(binaryFolder, true, entry.getAccessRuleSet(), externalAnnotationPath);
bLocations.add(bLocation);
if (binaryLocationsPerProject != null) { // normal builder mode
ClasspathLocation[] existingLocations = (ClasspathLocation[]) binaryLocationsPerProject.get(prereqProject);
@@ -181,7 +181,7 @@ private void computeClasspathLocations(
&& JavaCore.IGNORE.equals(javaProject.getOption(JavaCore.COMPILER_PB_DISCOURAGED_REFERENCE, true)))
? null
: entry.getAccessRuleSet();
- bLocation = ClasspathLocation.forBinaryFolder((IContainer) target, false, accessRuleSet); // is library folder not output folder
+ bLocation = ClasspathLocation.forBinaryFolder((IContainer) target, false, accessRuleSet, externalAnnotationPath); // is library folder not output folder
}
bLocations.add(bLocation);
if (binaryLocationsPerProject != null) { // normal builder mode
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/State.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/State.java
index 72f0d233cc..c28e5c3de3 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/State.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/State.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2014 IBM Corporation and others.
+ * Copyright (c) 2000, 2016 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -47,7 +47,7 @@ private long previousStructuralBuildTime;
private StringSet structurallyChangedTypes;
public static int MaxStructurallyChangedTypes = 100; // keep track of ? structurally changed types, otherwise consider all to be changed
-public static final byte VERSION = 0x001C;
+public static final byte VERSION = 0x001D;
static final byte SOURCE_FOLDER = 1;
static final byte BINARY_FOLDER = 2;
@@ -268,7 +268,7 @@ static State read(IProject project, DataInputStream in) throws IOException {
IContainer outputFolder = path.segmentCount() == 1
? (IContainer) root.getProject(path.toString())
: (IContainer) root.getFolder(path);
- newState.binaryLocations[i] = ClasspathLocation.forBinaryFolder(outputFolder, in.readBoolean(), readRestriction(in));
+ newState.binaryLocations[i] = ClasspathLocation.forBinaryFolder(outputFolder, in.readBoolean(), readRestriction(in), new Path(in.readUTF()));
break;
case EXTERNAL_JAR :
newState.binaryLocations[i] = ClasspathLocation.forLibrary(in.readUTF(), in.readLong(), readRestriction(in), new Path(in.readUTF()));
@@ -454,6 +454,7 @@ void write(DataOutputStream out) throws IOException {
out.writeUTF(cd.binaryFolder.getFullPath().toString());
out.writeBoolean(cd.isOutputFolder);
writeRestriction(cd.accessRuleSet, out);
+ out.writeUTF(cd.externalAnnotationPath != null ? cd.externalAnnotationPath : ""); //$NON-NLS-1$
} else {
ClasspathJar jar = (ClasspathJar) c;
if (jar.resource == null) {
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 2126a1ce01..636863b000 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
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2015 IBM Corporation and others.
+ * Copyright (c) 2000, 2016 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -104,10 +104,15 @@ private ClasspathLocation mapToClassPathLocation( JavaModelManager manager, Pack
cp = new ClasspathJar(manager.getZipFile(path), rawClasspathEntry.getAccessRuleSet(), ClasspathEntry.getExternalAnnotationPath(rawClasspathEntry, ((IJavaProject)root.getParent()).getProject(), true));
} else {
Object target = JavaModel.getTarget(path, true);
- if (target != null)
- cp = root.getKind() == IPackageFragmentRoot.K_SOURCE ?
- new ClasspathSourceDirectory((IContainer)target, root.fullExclusionPatternChars(), root.fullInclusionPatternChars()) :
- ClasspathLocation.forBinaryFolder((IContainer) target, false, ((ClasspathEntry) root.getRawClasspathEntry()).getAccessRuleSet());
+ if (target != null) {
+ if (root.getKind() == IPackageFragmentRoot.K_SOURCE) {
+ cp = new ClasspathSourceDirectory((IContainer)target, root.fullExclusionPatternChars(), root.fullInclusionPatternChars());
+ } else {
+ ClasspathEntry rawClasspathEntry = (ClasspathEntry) root.getRawClasspathEntry();
+ cp = ClasspathLocation.forBinaryFolder((IContainer) target, false, rawClasspathEntry.getAccessRuleSet(),
+ ClasspathEntry.getExternalAnnotationPath(rawClasspathEntry, ((IJavaProject)root.getParent()).getProject(), true));
+ }
+ }
}
} catch (CoreException e1) {
// problem opening zip file or getting root kind

Back to the top