View | Details | Raw Unified | Return to bug 365992
Collapse All | Expand All

(-)a/org.eclipse.jdt.core.tests.builder/src/org/eclipse/jdt/core/tests/builder/AnnotationDependencyTests.java (+135 lines)
Lines 11-20 Link Here
11
 *******************************************************************************/
11
 *******************************************************************************/
12
package org.eclipse.jdt.core.tests.builder;
12
package org.eclipse.jdt.core.tests.builder;
13
13
14
import java.io.File;
15
import java.io.IOException;
16
14
import junit.framework.Test;
17
import junit.framework.Test;
15
18
16
import org.eclipse.core.resources.IMarker;
19
import org.eclipse.core.resources.IMarker;
20
import org.eclipse.core.runtime.FileLocator;
17
import org.eclipse.core.runtime.IPath;
21
import org.eclipse.core.runtime.IPath;
22
import org.eclipse.core.runtime.Path;
23
import org.eclipse.core.runtime.Platform;
24
import org.eclipse.jdt.core.IClasspathEntry;
25
import org.eclipse.jdt.core.IJavaProject;
26
import org.eclipse.jdt.core.JavaCore;
27
import org.eclipse.jdt.core.JavaModelException;
18
import org.eclipse.jdt.core.compiler.CategorizedProblem;
28
import org.eclipse.jdt.core.compiler.CategorizedProblem;
19
import org.eclipse.jdt.core.tests.util.Util;
29
import org.eclipse.jdt.core.tests.util.Util;
20
30
Lines 127-132 Link Here
127
		env.addClass(this.srcRoot, "p1", "AnnoClass", annoCode);
137
		env.addClass(this.srcRoot, "p1", "AnnoClass", annoCode);
128
	}
138
	}
129
	
139
	
140
	void setupProjectForNullAnnotations() throws IOException, JavaModelException {
141
		// add the org.eclipse.jdt.annotation library (bin/ folder or jar) to the project:
142
		File bundleFile = FileLocator.getBundleFile(Platform.getBundle("org.eclipse.jdt.annotation"));
143
		String annotationsLib = bundleFile.isDirectory() ? bundleFile.getPath()+"/bin" : bundleFile.getPath();
144
		IJavaProject javaProject = env.getJavaProject(this.projectPath);
145
		IClasspathEntry[] rawClasspath = javaProject.getRawClasspath();
146
		int len = rawClasspath.length;
147
		System.arraycopy(rawClasspath, 0, rawClasspath = new IClasspathEntry[len+1], 0, len);
148
		rawClasspath[len] = JavaCore.newLibraryEntry(new Path(annotationsLib), null, null);
149
		javaProject.setRawClasspath(rawClasspath, null);
150
151
		javaProject.setOption(JavaCore.COMPILER_ANNOTATION_NULL_ANALYSIS, JavaCore.ENABLED);
152
	}
153
130
	/**
154
	/**
131
	 * This test makes sure that changing an annotation on type A causes type B
155
	 * This test makes sure that changing an annotation on type A causes type B
132
	 * to be recompiled, if B references A.  See http://bugs.eclipse.org/149768
156
	 * to be recompiled, if B references A.  See http://bugs.eclipse.org/149768
Lines 1371-1374 Link Here
1371
		// verify that B was recompiled
1395
		// verify that B was recompiled
1372
		expectingUniqueCompiledClasses(new String[] { "p1.A", "p1.B" });
1396
		expectingUniqueCompiledClasses(new String[] { "p1.A", "p1.B" });
1373
	}
1397
	}
1398
1399
	// Bug 365992 - [builder] [null] Change of nullness for a parameter doesn't trigger a build for the files that call the method
1400
	public void testParameterAnnotationDependency01() throws JavaModelException, IOException {
1401
		// prepare the project:
1402
		setupProjectForNullAnnotations();
1403
1404
		String test1Code = "package p1;\n"	+
1405
			"public class Test1 {\n" +
1406
			"    public void foo() {\n" +
1407
			"        new Test2().bar(null);\n" +
1408
			"    }\n" +
1409
			"}";
1410
		String test2Code = "package p1;\n" +
1411
			"public class Test2 {\n" +
1412
			"    public void bar(String str) {}\n" +
1413
			"}";
1414
1415
		IPath test1Path = env.addClass( this.srcRoot, "p1", "Test1", test1Code );
1416
		env.addClass( this.srcRoot, "p1", "Test2", test2Code );
1417
1418
		fullBuild( this.projectPath );
1419
		expectingNoProblems();
1420
1421
		// edit Test2 to add @NonNull annotation (changes number of annotations)
1422
		String test2CodeB = "package p1;\n" +
1423
			"import org.eclipse.jdt.annotation.NonNull;\n" +
1424
			"public class Test2 {\n" +
1425
			"    public void bar(@NonNull String str) {}\n" +
1426
			"}";
1427
		env.addClass( this.srcRoot, "p1", "Test2", test2CodeB );
1428
		incrementalBuild( this.projectPath );
1429
		expectingProblemsFor(test1Path, 
1430
				"Problem : Type mismatch: required \'@NonNull String\' but the provided value is null [ resource : </Project/src/p1/Test1.java> range : <81,85> category : <90> severity : <2>]");
1431
1432
		// verify that Test1 was recompiled
1433
		expectingUniqueCompiledClasses(new String[] { "p1.Test1", "p1.Test2" });
1434
1435
		// fix error by changing to @Nullable (change is only in an annotation name)
1436
		String test2CodeC = "package p1;\n" +
1437
			"import org.eclipse.jdt.annotation.Nullable;\n" +
1438
			"public class Test2 {\n" +
1439
			"    public void bar(@Nullable String str) {}\n" +
1440
			"}";
1441
		env.addClass( this.srcRoot, "p1", "Test2", test2CodeC );
1442
		incrementalBuild( this.projectPath );
1443
		expectingNoProblems();
1444
1445
		// verify that Test1 was recompiled
1446
		expectingUniqueCompiledClasses(new String[] { "p1.Test1", "p1.Test2" });
1447
	}
1448
1449
	// Bug 365992 - [builder] [null] Change of nullness for a parameter doesn't trigger a build for the files that call the method
1450
	// Bug 366341 - Incremental compiler fails to detect right scope for annotation related code changes
1451
	public void testReturnAnnotationDependency01() throws JavaModelException, IOException {
1452
		// prepare the project:
1453
		setupProjectForNullAnnotations();
1454
1455
		String test1Code = "package p1;\n" +
1456
			"import org.eclipse.jdt.annotation.NonNull;\n" +
1457
			"public class Test1 {\n" +
1458
			"    public @NonNull Object foo() {\n" +
1459
			"        return new Test2().bar();\n" +
1460
			"    }\n" +
1461
			"}";
1462
		String test2Code = "package p1;\n" +
1463
			"import org.eclipse.jdt.annotation.NonNull;\n" +
1464
			"public class Test2 {\n" +
1465
			"    public @NonNull Object bar() { return this; }\n" +
1466
			"}";
1467
1468
		IPath test1Path = env.addClass( this.srcRoot, "p1", "Test1", test1Code );
1469
		env.addClass( this.srcRoot, "p1", "Test2", test2Code );
1470
1471
		fullBuild( this.projectPath );
1472
		expectingNoProblems();
1473
1474
		// edit Test2 to replace annotation
1475
		String test2CodeB = "package p1;\n" +
1476
			"import org.eclipse.jdt.annotation.Nullable;\n" +
1477
			"public class Test2 {\n" +
1478
			"    public @Nullable Object bar() { return null; }\n" +
1479
			"}";
1480
		env.addClass( this.srcRoot, "p1", "Test2", test2CodeB );
1481
		incrementalBuild( this.projectPath );
1482
		expectingProblemsFor(test1Path, 
1483
			"Problem : Type mismatch: required \'@NonNull Object\' but the provided value can be null [ resource : </Project/src/p1/Test1.java> range : <126,143> category : <90> severity : <2>]");
1484
1485
		// verify that Test1 was recompiled
1486
		expectingUniqueCompiledClasses(new String[] { "p1.Test1", "p1.Test2" });
1487
1488
		// remove annotation, error changes from can be null to unknown nullness
1489
		String test2CodeC = "package p1;\n" +
1490
			"public class Test2 {\n" +
1491
			"    public Object bar() { return null; }\n" +
1492
			"}";
1493
		env.addClass( this.srcRoot, "p1", "Test2", test2CodeC );
1494
		incrementalBuild( this.projectPath );
1495
		expectingProblemsFor(test1Path, 
1496
			"Problem : Potential type mismatch: required \'@NonNull Object\' but nullness of the provided value is unknown [ resource : </Project/src/p1/Test1.java> range : <126,143> category : <90> severity : <1>]");
1497
1498
		// verify that Test1 was recompiled
1499
		expectingUniqueCompiledClasses(new String[] { "p1.Test1", "p1.Test2" });
1500
1501
		// back to initial OK version (re-add @NonNull annotation)
1502
		env.addClass( this.srcRoot, "p1", "Test2", test2Code );
1503
		incrementalBuild( this.projectPath );
1504
		expectingNoProblems();
1505
1506
		// verify that Test1 was recompiled
1507
		expectingUniqueCompiledClasses(new String[] { "p1.Test1", "p1.Test2" });
1508
	}
1374
}
1509
}
(-)a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/classfmt/ClassFileReader.java (+10 lines)
Lines 1070-1075 Link Here
1070
		return true;
1070
		return true;
1071
	if (hasStructuralAnnotationChanges(currentMethodInfo.getAnnotations(), otherMethodInfo.getAnnotations()))
1071
	if (hasStructuralAnnotationChanges(currentMethodInfo.getAnnotations(), otherMethodInfo.getAnnotations()))
1072
		return true;
1072
		return true;
1073
	// parameter annotations:
1074
	int currentAnnotatedParamsCount = currentMethodInfo.getAnnotatedParametersCount();
1075
	int otherAnnotatedParamsCount = otherMethodInfo.getAnnotatedParametersCount();
1076
	if (currentAnnotatedParamsCount != otherAnnotatedParamsCount)
1077
		return true;
1078
	for (int i=0; i<currentAnnotatedParamsCount; i++) {
1079
		if (hasStructuralAnnotationChanges(currentMethodInfo.getParameterAnnotations(i), otherMethodInfo.getParameterAnnotations(i)))
1080
			return true;
1081
	}
1082
1073
	if (!CharOperation.equals(currentMethodInfo.getSelector(), otherMethodInfo.getSelector()))
1083
	if (!CharOperation.equals(currentMethodInfo.getSelector(), otherMethodInfo.getSelector()))
1074
		return true;
1084
		return true;
1075
	if (!CharOperation.equals(currentMethodInfo.getMethodDescriptor(), otherMethodInfo.getMethodDescriptor()))
1085
	if (!CharOperation.equals(currentMethodInfo.getMethodDescriptor(), otherMethodInfo.getMethodDescriptor()))
(-)a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/classfmt/MethodInfo.java (-1 / +1 lines)
Lines 271-277 Link Here
271
public IBinaryAnnotation[] getParameterAnnotations(int index) {
271
public IBinaryAnnotation[] getParameterAnnotations(int index) {
272
	return null;
272
	return null;
273
}
273
}
274
public int getNumParameterAnnotations() {
274
public int getAnnotatedParametersCount() {
275
	return 0;
275
	return 0;
276
}
276
}
277
/**
277
/**
(-)a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/classfmt/MethodInfoWithParameterAnnotations.java (-1 / +1 lines)
Lines 37-43 Link Here
37
public IBinaryAnnotation[] getParameterAnnotations(int index) {
37
public IBinaryAnnotation[] getParameterAnnotations(int index) {
38
	return this.parameterAnnotations[index];
38
	return this.parameterAnnotations[index];
39
}
39
}
40
public int getNumParameterAnnotations() {
40
public int getAnnotatedParametersCount() {
41
	return this.parameterAnnotations == null ? 0 : this.parameterAnnotations.length;
41
	return this.parameterAnnotations == null ? 0 : this.parameterAnnotations.length;
42
}
42
}
43
protected void initialize() {
43
protected void initialize() {
(-)a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/env/IBinaryMethod.java (-1 / +1 lines)
Lines 71-77 Link Here
71
 * using {@link #getParameterAnnotations(int)}.
71
 * using {@link #getParameterAnnotations(int)}.
72
 * @return one beyond the highest legal argument to {@link #getParameterAnnotations(int)}.
72
 * @return one beyond the highest legal argument to {@link #getParameterAnnotations(int)}.
73
 */
73
 */
74
int getNumParameterAnnotations();
74
int getAnnotatedParametersCount();
75
75
76
/**
76
/**
77
 * Answer the name of the method.
77
 * Answer the name of the method.
(-)a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/BinaryTypeBinding.java (-1 / +1 lines)
Lines 1181-1187 Link Here
1181
	// parameters:
1181
	// parameters:
1182
	TypeBinding[] parameters = methodBinding.parameters;
1182
	TypeBinding[] parameters = methodBinding.parameters;
1183
	int numVisibleParams = parameters.length;
1183
	int numVisibleParams = parameters.length;
1184
	int numParamAnnotations = method.getNumParameterAnnotations();
1184
	int numParamAnnotations = method.getAnnotatedParametersCount();
1185
	if (numParamAnnotations > 0) {
1185
	if (numParamAnnotations > 0) {
1186
		int startIndex = numParamAnnotations - numVisibleParams;
1186
		int startIndex = numParamAnnotations - numVisibleParams;
1187
		for (int j = 0; j < numVisibleParams; j++) {
1187
		for (int j = 0; j < numVisibleParams; j++) {
(-)a/org.eclipse.jdt.core/eval/org/eclipse/jdt/internal/eval/CodeSnippetSkeleton.java (-1 / +1 lines)
Lines 65-71 Link Here
65
		public IBinaryAnnotation[] getParameterAnnotations(int index) {
65
		public IBinaryAnnotation[] getParameterAnnotations(int index) {
66
			return null;
66
			return null;
67
		}
67
		}
68
		public int getNumParameterAnnotations() {
68
		public int getAnnotatedParametersCount() {
69
			return 0;
69
			return 0;
70
		}
70
		}
71
		public char[] getSelector() {
71
		public char[] getSelector() {

Return to bug 365992