blob: 21dcf7b03b845e1a24daef3d0137b3b2ef4e9af4 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2009, 2014 Walter Harley 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
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Walter Harley (eclipse@cafewalter.com) - initial implementation
* IBM Corporation - initial API and implementation
* Stephan Herrmann - Contributions for
* bug 365992 - [builder] [null] Change of nullness for a parameter doesn't trigger a build for the files that call the method
* Bug 392099 - [1.8][compiler][null] Apply null annotation on types for null analysis
*******************************************************************************/
package org.eclipse.jdt.core.tests.builder;
import java.io.File;
import java.io.IOException;
import junit.framework.Test;
import org.eclipse.core.resources.IMarker;
import org.eclipse.core.runtime.FileLocator;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.Path;
import org.eclipse.core.runtime.Platform;
import org.eclipse.jdt.core.IClasspathEntry;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jdt.core.JavaCore;
import org.eclipse.jdt.core.JavaModelException;
import org.eclipse.jdt.core.compiler.CategorizedProblem;
import org.eclipse.jdt.core.tests.util.Util;
import org.osgi.framework.Bundle;
/**
* Tests to verify that annotation changes cause recompilation of dependent types.
* See http://bugs.eclipse.org/149768
*/
public class AnnotationDependencyTests extends BuilderTests {
private IPath srcRoot = null;
private IPath projectPath = null;
public AnnotationDependencyTests(String name) {
super(name);
}
public static Test suite() {
return buildTestSuite(AnnotationDependencyTests.class);
}
public void setUp() throws Exception {
super.setUp();
this.projectPath = env.addProject("Project", "1.5"); //$NON-NLS-1$
env.addExternalJars(this.projectPath, Util.getJavaClassLibs());
// remove old package fragment root so that names don't collide
env.removePackageFragmentRoot(this.projectPath,""); //$NON-NLS-1$
this.srcRoot = env.addPackageFragmentRoot(this.projectPath, "src"); //$NON-NLS-1$
env.setOutputFolder(this.projectPath, "bin"); //$NON-NLS-1$
}
protected void tearDown() throws Exception {
this.projectPath = null;
this.srcRoot = null;
super.tearDown();
}
private void addAnnotationType() {
String annoCode = "package p1;\n"
+ "@interface Anno {\n"
+ "String value();\n"
+ "}\n";
env.addClass(this.srcRoot, "p1", "Anno", annoCode);
annoCode = "package p1;\n"
+ "@interface AnnoInt {\n"
+ "int value();\n"
+ "}\n";
env.addClass(this.srcRoot, "p1", "AnnoInt", annoCode);
annoCode = "package p1;\n"
+ "@interface AnnoBoolean {\n"
+ "boolean value();\n"
+ "}\n";
env.addClass(this.srcRoot, "p1", "AnnoBoolean", annoCode);
annoCode = "package p1;\n"
+ "@interface AnnoByte {\n"
+ "byte value();\n"
+ "}\n";
env.addClass(this.srcRoot, "p1", "AnnoByte", annoCode);
annoCode = "package p1;\n"
+ "@interface AnnoChar {\n"
+ "char value();\n"
+ "}\n";
env.addClass(this.srcRoot, "p1", "AnnoChar", annoCode);
annoCode = "package p1;\n"
+ "@interface AnnoShort {\n"
+ "short value();\n"
+ "}\n";
env.addClass(this.srcRoot, "p1", "AnnoShort", annoCode);
annoCode = "package p1;\n"
+ "@interface AnnoDouble {\n"
+ "double value();\n"
+ "}\n";
env.addClass(this.srcRoot, "p1", "AnnoDouble", annoCode);
annoCode = "package p1;\n"
+ "@interface AnnoFloat {\n"
+ "float value();\n"
+ "}\n";
env.addClass(this.srcRoot, "p1", "AnnoFloat", annoCode);
annoCode = "package p1;\n"
+ "@interface AnnoLong {\n"
+ "long value();\n"
+ "}\n";
env.addClass(this.srcRoot, "p1", "AnnoLong", annoCode);
annoCode = "package p1;\n"
+ "@interface AnnoStringArray {\n"
+ "String[] value();\n"
+ "}\n";
env.addClass(this.srcRoot, "p1", "AnnoStringArray", annoCode);
annoCode = "package p1;\n"
+ "@interface AnnoAnnotation {\n"
+ "AnnoLong value();\n"
+ "}\n";
env.addClass(this.srcRoot, "p1", "AnnoAnnotation", annoCode);
annoCode = "package p1;\n"
+ "enum E {\n"
+ "A, B, C\n"
+ "}\n";
env.addClass(this.srcRoot, "p1", "E", annoCode);
annoCode = "package p1;\n"
+ "@interface AnnoEnum {\n"
+ "E value();\n"
+ "}\n";
env.addClass(this.srcRoot, "p1", "AnnoEnum", annoCode);
annoCode = "package p1;\n"
+ "@interface AnnoClass {\n"
+ "Class<?> value();\n"
+ "}\n";
env.addClass(this.srcRoot, "p1", "AnnoClass", annoCode);
}
void setupProjectForNullAnnotations() throws IOException, JavaModelException {
// add the org.eclipse.jdt.annotation library (bin/ folder or jar) to the project:
Bundle[] bundles = Platform.getBundles("org.eclipse.jdt.annotation","[1.1.0,2.0.0)");
File bundleFile = FileLocator.getBundleFile(bundles[0]);
String annotationsLib = bundleFile.isDirectory() ? bundleFile.getPath()+"/bin" : bundleFile.getPath();
IJavaProject javaProject = env.getJavaProject(this.projectPath);
IClasspathEntry[] rawClasspath = javaProject.getRawClasspath();
int len = rawClasspath.length;
System.arraycopy(rawClasspath, 0, rawClasspath = new IClasspathEntry[len+1], 0, len);
rawClasspath[len] = JavaCore.newLibraryEntry(new Path(annotationsLib), null, null);
javaProject.setRawClasspath(rawClasspath, null);
javaProject.setOption(JavaCore.COMPILER_ANNOTATION_NULL_ANALYSIS, JavaCore.ENABLED);
}
/**
* This test makes sure that changing an annotation on type A causes type B
* to be recompiled, if B references A. See http://bugs.eclipse.org/149768
*/
public void testTypeAnnotationDependency() throws Exception
{
String a1Code = "package p1; " + "\n"
+ "@Anno(\"A1\")" + "\n"
+ "public class A {}";
String a2Code = "package p1; " + "\n"
+ "@Anno(\"A2\")" + "\n"
+ "public class A {}";
String bCode = "package p1; " + "\n"
+ "public class B {" + "\n"
+ " public A a;" + "\n"
+ "}";
env.addClass( this.srcRoot, "p1", "A", a1Code );
env.addClass( this.srcRoot, "p1", "B", bCode );
addAnnotationType();
fullBuild( this.projectPath );
expectingNoProblems();
// edit annotation in A
env.addClass( this.srcRoot, "p1", "A", a2Code );
incrementalBuild( this.projectPath );
expectingNoProblems();
// verify that B was recompiled
expectingUniqueCompiledClasses(new String[] { "p1.A", "p1.B" });
}
/**
* This test makes sure that changing an annotation on a field within type A
* causes type B to be recompiled, if B references A.
* See http://bugs.eclipse.org/149768
*/
public void testFieldAnnotationDependency() throws Exception
{
String a1Code = "package p1; " + "\n"
+ "public class A {" + "\n"
+ " @Anno(\"A1\")" + "\n"
+ " protected int f;" + "\n"
+ "}";
String a2Code = "package p1; " + "\n"
+ "public class A {" + "\n"
+ " @Anno(\"A2\")" + "\n"
+ " protected int f;" + "\n"
+ "}";
String bCode = "package p1; " + "\n"
+ "public class B {" + "\n"
+ " public A a;" + "\n"
+ "}";
env.addClass( this.srcRoot, "p1", "A", a1Code );
env.addClass( this.srcRoot, "p1", "B", bCode );
addAnnotationType();
fullBuild( this.projectPath );
expectingNoProblems();
// edit annotation in A
env.addClass( this.srcRoot, "p1", "A", a2Code );
incrementalBuild( this.projectPath );
expectingNoProblems();
// verify that B was recompiled
expectingUniqueCompiledClasses(new String[] { "p1.A", "p1.B" });
}
/**
* This test makes sure that changing an annotation on a method within type A
* causes type B to be recompiled, if B references A.
* See http://bugs.eclipse.org/149768
*/
public void testMethodAnnotationDependency() throws Exception
{
String a1Code = "package p1; " + "\n"
+ "public class A {" + "\n"
+ " @Anno(\"A1\")" + "\n"
+ " protected int f() { return 0; }" + "\n"
+ "}";
String a2Code = "package p1; " + "\n"
+ "public class A {" + "\n"
+ " @Anno(\"A2\")" + "\n"
+ " protected int f() { return 0; }" + "\n"
+ "}";
String bCode = "package p1; " + "\n"
+ "public class B {" + "\n"
+ " public A a;" + "\n"
+ "}";
env.addClass( this.srcRoot, "p1", "A", a1Code );
env.addClass( this.srcRoot, "p1", "B", bCode );
addAnnotationType();
fullBuild( this.projectPath );
expectingNoProblems();
// edit annotation in A
env.addClass( this.srcRoot, "p1", "A", a2Code );
incrementalBuild( this.projectPath );
expectingNoProblems();
// verify that B was recompiled
expectingUniqueCompiledClasses(new String[] { "p1.A", "p1.B" });
}
/**
* This test makes sure that changing an annotation on an inner type X within type A
* causes type B to be recompiled, if B references A.
* Note that B does not directly reference A.X, only A.
* See http://bugs.eclipse.org/149768
*/
public void testInnerTypeAnnotationDependency() throws Exception
{
String a1Code = "package p1; " + "\n"
+ "public class A {" + "\n"
+ " @Anno(\"A1\")" + "\n"
+ " public class X { }" + "\n"
+ "}";
String a2Code = "package p1; " + "\n"
+ "public class A {" + "\n"
+ " @Anno(\"A2\")" + "\n"
+ " public class X { }" + "\n"
+ "}";
String bCode = "package p1; " + "\n"
+ "public class B {" + "\n"
+ " public A a;" + "\n"
+ "}";
env.addClass( this.srcRoot, "p1", "A", a1Code );
env.addClass( this.srcRoot, "p1", "B", bCode );
addAnnotationType();
fullBuild( this.projectPath );
expectingNoProblems();
// edit annotation in A
env.addClass( this.srcRoot, "p1", "A", a2Code );
incrementalBuild( this.projectPath );
expectingNoProblems();
// verify that B was recompiled
expectingUniqueCompiledClasses(new String[] { "p1.A", "p1.A$X", "p1.B" });
}
/**
* This test makes sure that changing an annotation on a type A
* does not cause type B to be recompiled, if B does not reference A.
* See http://bugs.eclipse.org/149768
*/
public void testUnrelatedTypeAnnotationDependency() throws Exception
{
String a1Code = "package p1; " + "\n"
+ "@Anno(\"A1\")" + "\n"
+ "public class A {}";
String a2Code = "package p1; " + "\n"
+ "@Anno(\"A2\")" + "\n"
+ "public class A {}";
String bCode = "package p1; " + "\n"
+ "public class B {" + "\n"
+ "}";
env.addClass( this.srcRoot, "p1", "A", a1Code );
env.addClass( this.srcRoot, "p1", "B", bCode );
addAnnotationType();
fullBuild( this.projectPath );
expectingNoProblems();
// edit annotation in A
env.addClass( this.srcRoot, "p1", "A", a2Code );
incrementalBuild( this.projectPath );
expectingNoProblems();
// verify that B was not recompiled
expectingUniqueCompiledClasses(new String[] { "p1.A" });
}
// https://bugs.eclipse.org/bugs/show_bug.cgi?id=214948
public void testPackageInfoDependency() throws Exception {
String notypes = "@question.SimpleAnnotation(\"foo\") package notypes;";
String question = "package question;";
String deprecatedQuestion = "@Deprecated package question;";
String SimpleAnnotation = "package question; " + "\n"
+ "public @interface SimpleAnnotation { String value(); }";
IPath notypesPath = env.addClass( this.srcRoot, "notypes", "package-info", notypes );
env.addClass( this.srcRoot, "question", "package-info", question );
env.addClass( this.srcRoot, "question", "SimpleAnnotation", SimpleAnnotation );
fullBuild( this.projectPath );
expectingNoProblems();
env.addClass( this.srcRoot, "question", "package-info", deprecatedQuestion );
incrementalBuild( this.projectPath );
expectingOnlySpecificProblemFor(notypesPath, new Problem("", "The type SimpleAnnotation is deprecated", notypesPath, 10, 26, CategorizedProblem.CAT_DEPRECATION, IMarker.SEVERITY_WARNING)); //$NON-NLS-1$
env.addClass( this.srcRoot, "question", "package-info", question );
incrementalBuild( this.projectPath );
expectingNoProblems();
}
/**
* https://bugs.eclipse.org/bugs/show_bug.cgi?id=317841
*/
public void testTypeAnnotationDependency2() throws Exception
{
String a1Code = "package p1; " + "\n"
+ "@Anno(\"A1\")" + "\n"
+ "public class A {\n"
+ " public void foo() {\n"
+ " System.out.println(\"test\");"
+ " }"
+ "}";
String a2Code = "package p1; " + "\n"
+ "@Anno(\"A1\")" + "\n"
+ "public class A {\n"
+ "\n"
+ " public void foo() {\n"
+ " System.out.println(\"test\");"
+ " }"
+ "}";
String bCode = "package p1; " + "\n"
+ "public class B {" + "\n"
+ " public A a;" + "\n"
+ "}";
env.addClass( this.srcRoot, "p1", "A", a1Code );
env.addClass( this.srcRoot, "p1", "B", bCode );
addAnnotationType();
fullBuild( this.projectPath );
expectingNoProblems();
// edit annotation in A
env.addClass( this.srcRoot, "p1", "A", a2Code );
incrementalBuild( this.projectPath );
expectingNoProblems();
// verify that B was NOT recompiled
expectingUniqueCompiledClasses(new String[] { "p1.A" });
}
/**
* https://bugs.eclipse.org/bugs/show_bug.cgi?id=317841
*/
public void testTypeAnnotationDependency3() throws Exception
{
String a1Code = "package p1; " + "\n"
+ "@AnnoInt(24)" + "\n"
+ "public class A {\n"
+ " public void foo() {\n"
+ " System.out.println(\"test\");"
+ " }"
+ "}";
String a2Code = "package p1; " + "\n"
+ "@AnnoInt(24)" + "\n"
+ "public class A {\n"
+ "\n"
+ " public void foo() {\n"
+ " System.out.println(\"test\");"
+ " }"
+ "}";
String bCode = "package p1; " + "\n"
+ "public class B {" + "\n"
+ " public A a;" + "\n"
+ "}";
env.addClass( this.srcRoot, "p1", "A", a1Code );
env.addClass( this.srcRoot, "p1", "B", bCode );
addAnnotationType();
fullBuild( this.projectPath );
expectingNoProblems();
// edit annotation in A
env.addClass( this.srcRoot, "p1", "A", a2Code );
incrementalBuild( this.projectPath );
expectingNoProblems();
// verify that B was NOT recompiled
expectingUniqueCompiledClasses(new String[] { "p1.A" });
}
/**
* https://bugs.eclipse.org/bugs/show_bug.cgi?id=317841
*/
public void testTypeAnnotationDependency4() throws Exception
{
String a1Code = "package p1; " + "\n"
+ "@AnnoByte(3)" + "\n"
+ "public class A {\n"
+ " public void foo() {\n"
+ " System.out.println(\"test\");"
+ " }"
+ "}";
String a2Code = "package p1; " + "\n"
+ "@AnnoByte(3)" + "\n"
+ "public class A {\n"
+ "\n"
+ " public void foo() {\n"
+ " System.out.println(\"test\");"
+ " }"
+ "}";
String bCode = "package p1; " + "\n"
+ "public class B {" + "\n"
+ " public A a;" + "\n"
+ "}";
env.addClass( this.srcRoot, "p1", "A", a1Code );
env.addClass( this.srcRoot, "p1", "B", bCode );
addAnnotationType();
fullBuild( this.projectPath );
expectingNoProblems();
// edit annotation in A
env.addClass( this.srcRoot, "p1", "A", a2Code );
incrementalBuild( this.projectPath );
expectingNoProblems();
// verify that B was NOT recompiled
expectingUniqueCompiledClasses(new String[] { "p1.A" });
}
/**
* https://bugs.eclipse.org/bugs/show_bug.cgi?id=317841
*/
public void testTypeAnnotationDependency5() throws Exception
{
String a1Code = "package p1; " + "\n"
+ "@AnnoBoolean(true)" + "\n"
+ "public class A {\n"
+ " public void foo() {\n"
+ " System.out.println(\"test\");"
+ " }"
+ "}";
String a2Code = "package p1; " + "\n"
+ "@AnnoBoolean(true)" + "\n"
+ "public class A {\n"
+ "\n"
+ " public void foo() {\n"
+ " System.out.println(\"test\");"
+ " }"
+ "}";
String bCode = "package p1; " + "\n"
+ "public class B {" + "\n"
+ " public A a;" + "\n"
+ "}";
env.addClass( this.srcRoot, "p1", "A", a1Code );
env.addClass( this.srcRoot, "p1", "B", bCode );
addAnnotationType();
fullBuild( this.projectPath );
expectingNoProblems();
// edit annotation in A
env.addClass( this.srcRoot, "p1", "A", a2Code );
incrementalBuild( this.projectPath );
expectingNoProblems();
// verify that B was NOT recompiled
expectingUniqueCompiledClasses(new String[] { "p1.A" });
}
/**
* https://bugs.eclipse.org/bugs/show_bug.cgi?id=317841
*/
public void testTypeAnnotationDependency6() throws Exception
{
String a1Code = "package p1; " + "\n"
+ "@AnnoChar('c')" + "\n"
+ "public class A {\n"
+ " public void foo() {\n"
+ " System.out.println(\"test\");"
+ " }"
+ "}";
String a2Code = "package p1; " + "\n"
+ "@AnnoChar('c')" + "\n"
+ "public class A {\n"
+ "\n"
+ " public void foo() {\n"
+ " System.out.println(\"test\");"
+ " }"
+ "}";
String bCode = "package p1; " + "\n"
+ "public class B {" + "\n"
+ " public A a;" + "\n"
+ "}";
env.addClass( this.srcRoot, "p1", "A", a1Code );
env.addClass( this.srcRoot, "p1", "B", bCode );
addAnnotationType();
fullBuild( this.projectPath );
expectingNoProblems();
// edit annotation in A
env.addClass( this.srcRoot, "p1", "A", a2Code );
incrementalBuild( this.projectPath );
expectingNoProblems();
// verify that B was NOT recompiled
expectingUniqueCompiledClasses(new String[] { "p1.A" });
}
/**
* https://bugs.eclipse.org/bugs/show_bug.cgi?id=317841
*/
public void testTypeAnnotationDependency7() throws Exception
{
String a1Code = "package p1; " + "\n"
+ "@AnnoDouble(1.0)" + "\n"
+ "public class A {\n"
+ " public void foo() {\n"
+ " System.out.println(\"test\");"
+ " }"
+ "}";
String a2Code = "package p1; " + "\n"
+ "@AnnoDouble(1.0)" + "\n"
+ "public class A {\n"
+ "\n"
+ " public void foo() {\n"
+ " System.out.println(\"test\");"
+ " }"
+ "}";
String bCode = "package p1; " + "\n"
+ "public class B {" + "\n"
+ " public A a;" + "\n"
+ "}";
env.addClass( this.srcRoot, "p1", "A", a1Code );
env.addClass( this.srcRoot, "p1", "B", bCode );
addAnnotationType();
fullBuild( this.projectPath );
expectingNoProblems();
// edit annotation in A
env.addClass( this.srcRoot, "p1", "A", a2Code );
incrementalBuild( this.projectPath );
expectingNoProblems();
// verify that B was NOT recompiled
expectingUniqueCompiledClasses(new String[] { "p1.A" });
}
/**
* https://bugs.eclipse.org/bugs/show_bug.cgi?id=317841
*/
public void testTypeAnnotationDependency8() throws Exception
{
String a1Code = "package p1; " + "\n"
+ "@AnnoFloat(1.0f)" + "\n"
+ "public class A {\n"
+ " public void foo() {\n"
+ " System.out.println(\"test\");"
+ " }"
+ "}";
String a2Code = "package p1; " + "\n"
+ "@AnnoFloat(1.0f)" + "\n"
+ "public class A {\n"
+ "\n"
+ " public void foo() {\n"
+ " System.out.println(\"test\");"
+ " }"
+ "}";
String bCode = "package p1; " + "\n"
+ "public class B {" + "\n"
+ " public A a;" + "\n"
+ "}";
env.addClass( this.srcRoot, "p1", "A", a1Code );
env.addClass( this.srcRoot, "p1", "B", bCode );
addAnnotationType();
fullBuild( this.projectPath );
expectingNoProblems();
// edit annotation in A
env.addClass( this.srcRoot, "p1", "A", a2Code );
incrementalBuild( this.projectPath );
expectingNoProblems();
// verify that B was NOT recompiled
expectingUniqueCompiledClasses(new String[] { "p1.A" });
}
/**
* https://bugs.eclipse.org/bugs/show_bug.cgi?id=317841
*/
public void testTypeAnnotationDependency9() throws Exception
{
String a1Code = "package p1; " + "\n"
+ "@AnnoLong(1L)" + "\n"
+ "public class A {\n"
+ " public void foo() {\n"
+ " System.out.println(\"test\");"
+ " }"
+ "}";
String a2Code = "package p1; " + "\n"
+ "@AnnoLong(1L)" + "\n"
+ "public class A {\n"
+ "\n"
+ " public void foo() {\n"
+ " System.out.println(\"test\");"
+ " }"
+ "}";
String bCode = "package p1; " + "\n"
+ "public class B {" + "\n"
+ " public A a;" + "\n"
+ "}";
env.addClass( this.srcRoot, "p1", "A", a1Code );
env.addClass( this.srcRoot, "p1", "B", bCode );
addAnnotationType();
fullBuild( this.projectPath );
expectingNoProblems();
// edit annotation in A
env.addClass( this.srcRoot, "p1", "A", a2Code );
incrementalBuild( this.projectPath );
expectingNoProblems();
// verify that B was NOT recompiled
expectingUniqueCompiledClasses(new String[] { "p1.A" });
}
/**
* https://bugs.eclipse.org/bugs/show_bug.cgi?id=317841
*/
public void testTypeAnnotationDependency10() throws Exception
{
String a1Code = "package p1; " + "\n"
+ "@AnnoShort(3)" + "\n"
+ "public class A {\n"
+ " public void foo() {\n"
+ " System.out.println(\"test\");"
+ " }"
+ "}";
String a2Code = "package p1; " + "\n"
+ "@AnnoShort(3)" + "\n"
+ "public class A {\n"
+ "\n"
+ " public void foo() {\n"
+ " System.out.println(\"test\");"
+ " }"
+ "}";
String bCode = "package p1; " + "\n"
+ "public class B {" + "\n"
+ " public A a;" + "\n"
+ "}";
env.addClass( this.srcRoot, "p1", "A", a1Code );
env.addClass( this.srcRoot, "p1", "B", bCode );
addAnnotationType();
fullBuild( this.projectPath );
expectingNoProblems();
// edit annotation in A
env.addClass( this.srcRoot, "p1", "A", a2Code );
incrementalBuild( this.projectPath );
expectingNoProblems();
// verify that B was NOT recompiled
expectingUniqueCompiledClasses(new String[] { "p1.A" });
}
/**
* https://bugs.eclipse.org/bugs/show_bug.cgi?id=317841
*/
public void testTypeAnnotationDependency11() throws Exception
{
String a1Code = "package p1; " + "\n"
+ "@AnnoStringArray({\"A1\",\"A2\"})" + "\n"
+ "public class A {\n"
+ " public void foo() {\n"
+ " System.out.println(\"test\");"
+ " }"
+ "}";
String a2Code = "package p1; " + "\n"
+ "@AnnoStringArray({\"A1\",\"A2\"})" + "\n"
+ "public class A {\n"
+ "\n"
+ " public void foo() {\n"
+ " System.out.println(\"test\");"
+ " }"
+ "}";
String bCode = "package p1; " + "\n"
+ "public class B {" + "\n"
+ " public A a;" + "\n"
+ "}";
env.addClass( this.srcRoot, "p1", "A", a1Code );
env.addClass( this.srcRoot, "p1", "B", bCode );
addAnnotationType();
fullBuild( this.projectPath );
expectingNoProblems();
// edit annotation in A
env.addClass( this.srcRoot, "p1", "A", a2Code );
incrementalBuild( this.projectPath );
expectingNoProblems();
// verify that B was NOT recompiled
expectingUniqueCompiledClasses(new String[] { "p1.A" });
}
/**
* https://bugs.eclipse.org/bugs/show_bug.cgi?id=317841
*/
public void testTypeAnnotationDependency12() throws Exception
{
String a1Code = "package p1; " + "\n"
+ "@AnnoAnnotation(@AnnoLong(3))" + "\n"
+ "public class A {\n"
+ " public void foo() {\n"
+ " System.out.println(\"test\");"
+ " }"
+ "}";
String a2Code = "package p1; " + "\n"
+ "@AnnoAnnotation(@AnnoLong(3))" + "\n"
+ "public class A {\n"
+ "\n"
+ " public void foo() {\n"
+ " System.out.println(\"test\");"
+ " }"
+ "}";
String bCode = "package p1; " + "\n"
+ "public class B {" + "\n"
+ " public A a;" + "\n"
+ "}";
env.addClass( this.srcRoot, "p1", "A", a1Code );
env.addClass( this.srcRoot, "p1", "B", bCode );
addAnnotationType();
fullBuild( this.projectPath );
expectingNoProblems();
// edit annotation in A
env.addClass( this.srcRoot, "p1", "A", a2Code );
incrementalBuild( this.projectPath );
expectingNoProblems();
// verify that B was NOT recompiled
expectingUniqueCompiledClasses(new String[] { "p1.A" });
}
/**
* https://bugs.eclipse.org/bugs/show_bug.cgi?id=317841
*/
public void testTypeAnnotationDependency13() throws Exception
{
String a1Code = "package p1; " + "\n"
+ "@AnnoEnum(E.A)\n"
+ "public class A {\n"
+ " public void foo() {\n"
+ " System.out.println(\"test\");"
+ " }"
+ "}";
String a2Code = "package p1; " + "\n"
+ "@AnnoEnum(E.A)\n"
+ "public class A {\n"
+ "\n"
+ " public void foo() {\n"
+ " System.out.println(\"test\");"
+ " }"
+ "}";
String bCode = "package p1; " + "\n"
+ "public class B {" + "\n"
+ " public A a;" + "\n"
+ "}";
env.addClass( this.srcRoot, "p1", "A", a1Code );
env.addClass( this.srcRoot, "p1", "B", bCode );
addAnnotationType();
fullBuild( this.projectPath );
expectingNoProblems();
// edit annotation in A
env.addClass( this.srcRoot, "p1", "A", a2Code );
incrementalBuild( this.projectPath );
expectingNoProblems();
// verify that B was NOT recompiled
expectingUniqueCompiledClasses(new String[] { "p1.A" });
}
/**
* https://bugs.eclipse.org/bugs/show_bug.cgi?id=317841
*/
public void testTypeAnnotationDependency14() throws Exception
{
String a1Code = "package p1; " + "\n"
+ "@AnnoClass(Object.class)\n"
+ "public class A {\n"
+ " public void foo() {\n"
+ " System.out.println(\"test\");"
+ " }"
+ "}";
String a2Code = "package p1; " + "\n"
+ "@AnnoClass(Object.class)\n"
+ "public class A {\n"
+ "\n"
+ " public void foo() {\n"
+ " System.out.println(\"test\");"
+ " }"
+ "}";
String bCode = "package p1; " + "\n"
+ "public class B {" + "\n"
+ " public A a;" + "\n"
+ "}";
env.addClass( this.srcRoot, "p1", "A", a1Code );
env.addClass( this.srcRoot, "p1", "B", bCode );
addAnnotationType();
fullBuild( this.projectPath );
expectingNoProblems();
// edit annotation in A
env.addClass( this.srcRoot, "p1", "A", a2Code );
incrementalBuild( this.projectPath );
expectingNoProblems();
// verify that B was NOT recompiled
expectingUniqueCompiledClasses(new String[] { "p1.A" });
}
/**
* https://bugs.eclipse.org/bugs/show_bug.cgi?id=317841
*/
public void testTypeAnnotationDependency15() throws Exception
{
String a1Code = "package p1; " + "\n"
+ "@Anno(\"A1\")" + "\n"
+ "public class A {\n"
+ " public void foo() {\n"
+ " System.out.println(\"test\");"
+ " }"
+ "}";
String a2Code = "package p1; " + "\n"
+ "@Anno(\"A2\")" + "\n"
+ "public class A {\n"
+ "\n"
+ " public void foo() {\n"
+ " System.out.println(\"test\");"
+ " }"
+ "}";
String bCode = "package p1; " + "\n"
+ "public class B {" + "\n"
+ " public A a;" + "\n"
+ "}";
env.addClass( this.srcRoot, "p1", "A", a1Code );
env.addClass( this.srcRoot, "p1", "B", bCode );
addAnnotationType();
fullBuild( this.projectPath );
expectingNoProblems();
// edit annotation in A
env.addClass( this.srcRoot, "p1", "A", a2Code );
incrementalBuild( this.projectPath );
expectingNoProblems();
// verify that B was recompiled
expectingUniqueCompiledClasses(new String[] { "p1.A", "p1.B" });
}
/**
* https://bugs.eclipse.org/bugs/show_bug.cgi?id=317841
*/
public void testTypeAnnotationDependency16() throws Exception
{
String a1Code = "package p1; " + "\n"
+ "@AnnoInt(3)" + "\n"
+ "public class A {\n"
+ " public void foo() {\n"
+ " System.out.println(\"test\");"
+ " }"
+ "}";
String a2Code = "package p1; " + "\n"
+ "@AnnoInt(4)" + "\n"
+ "public class A {\n"
+ "\n"
+ " public void foo() {\n"
+ " System.out.println(\"test\");"
+ " }"
+ "}";
String bCode = "package p1; " + "\n"
+ "public class B {" + "\n"
+ " public A a;" + "\n"
+ "}";
env.addClass( this.srcRoot, "p1", "A", a1Code );
env.addClass( this.srcRoot, "p1", "B", bCode );
addAnnotationType();
fullBuild( this.projectPath );
expectingNoProblems();
// edit annotation in A
env.addClass( this.srcRoot, "p1", "A", a2Code );
incrementalBuild( this.projectPath );
expectingNoProblems();
// verify that B was recompiled
expectingUniqueCompiledClasses(new String[] { "p1.A", "p1.B" });
}
/**
* https://bugs.eclipse.org/bugs/show_bug.cgi?id=317841
*/
public void testTypeAnnotationDependency17() throws Exception
{
String a1Code = "package p1; " + "\n"
+ "@AnnoByte(3)" + "\n"
+ "public class A {\n"
+ " public void foo() {\n"
+ " System.out.println(\"test\");"
+ " }"
+ "}";
String a2Code = "package p1; " + "\n"
+ "@AnnoByte(4)" + "\n"
+ "public class A {\n"
+ "\n"
+ " public void foo() {\n"
+ " System.out.println(\"test\");"
+ " }"
+ "}";
String bCode = "package p1; " + "\n"
+ "public class B {" + "\n"
+ " public A a;" + "\n"
+ "}";
env.addClass( this.srcRoot, "p1", "A", a1Code );
env.addClass( this.srcRoot, "p1", "B", bCode );
addAnnotationType();
fullBuild( this.projectPath );
expectingNoProblems();
// edit annotation in A
env.addClass( this.srcRoot, "p1", "A", a2Code );
incrementalBuild( this.projectPath );
expectingNoProblems();
// verify that B was recompiled
expectingUniqueCompiledClasses(new String[] { "p1.A", "p1.B"});
}
/**
* https://bugs.eclipse.org/bugs/show_bug.cgi?id=317841
*/
public void testTypeAnnotationDependency18() throws Exception
{
String a1Code = "package p1; " + "\n"
+ "@AnnoBoolean(true)" + "\n"
+ "public class A {\n"
+ " public void foo() {\n"
+ " System.out.println(\"test\");"
+ " }"
+ "}";
String a2Code = "package p1; " + "\n"
+ "@AnnoBoolean(false)" + "\n"
+ "public class A {\n"
+ "\n"
+ " public void foo() {\n"
+ " System.out.println(\"test\");"
+ " }"
+ "}";
String bCode = "package p1; " + "\n"
+ "public class B {" + "\n"
+ " public A a;" + "\n"
+ "}";
env.addClass( this.srcRoot, "p1", "A", a1Code );
env.addClass( this.srcRoot, "p1", "B", bCode );
addAnnotationType();
fullBuild( this.projectPath );
expectingNoProblems();
// edit annotation in A
env.addClass( this.srcRoot, "p1", "A", a2Code );
incrementalBuild( this.projectPath );
expectingNoProblems();
// verify that B was recompiled
expectingUniqueCompiledClasses(new String[] { "p1.A", "p1.B" });
}
/**
* https://bugs.eclipse.org/bugs/show_bug.cgi?id=317841
*/
public void testTypeAnnotationDependency19() throws Exception
{
String a1Code = "package p1; " + "\n"
+ "@AnnoChar('c')" + "\n"
+ "public class A {\n"
+ " public void foo() {\n"
+ " System.out.println(\"test\");"
+ " }"
+ "}";
String a2Code = "package p1; " + "\n"
+ "@AnnoChar('d')" + "\n"
+ "public class A {\n"
+ "\n"
+ " public void foo() {\n"
+ " System.out.println(\"test\");"
+ " }"
+ "}";
String bCode = "package p1; " + "\n"
+ "public class B {" + "\n"
+ " public A a;" + "\n"
+ "}";
env.addClass( this.srcRoot, "p1", "A", a1Code );
env.addClass( this.srcRoot, "p1", "B", bCode );
addAnnotationType();
fullBuild( this.projectPath );
expectingNoProblems();
// edit annotation in A
env.addClass( this.srcRoot, "p1", "A", a2Code );
incrementalBuild( this.projectPath );
expectingNoProblems();
// verify that B was recompiled
expectingUniqueCompiledClasses(new String[] { "p1.A", "p1.B" });
}
/**
* https://bugs.eclipse.org/bugs/show_bug.cgi?id=317841
*/
public void testTypeAnnotationDependency20() throws Exception
{
String a1Code = "package p1; " + "\n"
+ "@AnnoDouble(1.0)" + "\n"
+ "public class A {\n"
+ " public void foo() {\n"
+ " System.out.println(\"test\");"
+ " }"
+ "}";
String a2Code = "package p1; " + "\n"
+ "@AnnoDouble(2.0)" + "\n"
+ "public class A {\n"
+ "\n"
+ " public void foo() {\n"
+ " System.out.println(\"test\");"
+ " }"
+ "}";
String bCode = "package p1; " + "\n"
+ "public class B {" + "\n"
+ " public A a;" + "\n"
+ "}";
env.addClass( this.srcRoot, "p1", "A", a1Code );
env.addClass( this.srcRoot, "p1", "B", bCode );
addAnnotationType();
fullBuild( this.projectPath );
expectingNoProblems();
// edit annotation in A
env.addClass( this.srcRoot, "p1", "A", a2Code );
incrementalBuild( this.projectPath );
expectingNoProblems();
// verify that B was recompiled
expectingUniqueCompiledClasses(new String[] { "p1.A", "p1.B" });
}
/**
* https://bugs.eclipse.org/bugs/show_bug.cgi?id=317841
*/
public void testTypeAnnotationDependency21() throws Exception
{
String a1Code = "package p1; " + "\n"
+ "@AnnoFloat(1.0f)" + "\n"
+ "public class A {\n"
+ " public void foo() {\n"
+ " System.out.println(\"test\");"
+ " }"
+ "}";
String a2Code = "package p1; " + "\n"
+ "@AnnoFloat(2.0f)" + "\n"
+ "public class A {\n"
+ "\n"
+ " public void foo() {\n"
+ " System.out.println(\"test\");"
+ " }"
+ "}";
String bCode = "package p1; " + "\n"
+ "public class B {" + "\n"
+ " public A a;" + "\n"
+ "}";
env.addClass( this.srcRoot, "p1", "A", a1Code );
env.addClass( this.srcRoot, "p1", "B", bCode );
addAnnotationType();
fullBuild( this.projectPath );
expectingNoProblems();
// edit annotation in A
env.addClass( this.srcRoot, "p1", "A", a2Code );
incrementalBuild( this.projectPath );
expectingNoProblems();
// verify that B was recompiled
expectingUniqueCompiledClasses(new String[] { "p1.A", "p1.B" });
}
/**
* https://bugs.eclipse.org/bugs/show_bug.cgi?id=317841
*/
public void testTypeAnnotationDependency22() throws Exception
{
String a1Code = "package p1; " + "\n"
+ "@AnnoLong(1L)" + "\n"
+ "public class A {\n"
+ " public void foo() {\n"
+ " System.out.println(\"test\");"
+ " }"
+ "}";
String a2Code = "package p1; " + "\n"
+ "@AnnoLong(2L)" + "\n"
+ "public class A {\n"
+ "\n"
+ " public void foo() {\n"
+ " System.out.println(\"test\");"
+ " }"
+ "}";
String bCode = "package p1; " + "\n"
+ "public class B {" + "\n"
+ " public A a;" + "\n"
+ "}";
env.addClass( this.srcRoot, "p1", "A", a1Code );
env.addClass( this.srcRoot, "p1", "B", bCode );
addAnnotationType();
fullBuild( this.projectPath );
expectingNoProblems();
// edit annotation in A
env.addClass( this.srcRoot, "p1", "A", a2Code );
incrementalBuild( this.projectPath );
expectingNoProblems();
// verify that B was recompiled
expectingUniqueCompiledClasses(new String[] { "p1.A", "p1.B" });
}
/**
* https://bugs.eclipse.org/bugs/show_bug.cgi?id=317841
*/
public void testTypeAnnotationDependency23() throws Exception
{
String a1Code = "package p1; " + "\n"
+ "@AnnoShort(3)" + "\n"
+ "public class A {\n"
+ " public void foo() {\n"
+ " System.out.println(\"test\");"
+ " }"
+ "}";
String a2Code = "package p1; " + "\n"
+ "@AnnoShort(5)" + "\n"
+ "public class A {\n"
+ "\n"
+ " public void foo() {\n"
+ " System.out.println(\"test\");"
+ " }"
+ "}";
String bCode = "package p1; " + "\n"
+ "public class B {" + "\n"
+ " public A a;" + "\n"
+ "}";
env.addClass( this.srcRoot, "p1", "A", a1Code );
env.addClass( this.srcRoot, "p1", "B", bCode );
addAnnotationType();
fullBuild( this.projectPath );
expectingNoProblems();
// edit annotation in A
env.addClass( this.srcRoot, "p1", "A", a2Code );
incrementalBuild( this.projectPath );
expectingNoProblems();
// verify that B was recompiled
expectingUniqueCompiledClasses(new String[] { "p1.A", "p1.B" });
}
/**
* https://bugs.eclipse.org/bugs/show_bug.cgi?id=317841
*/
public void testTypeAnnotationDependency24() throws Exception
{
String a1Code = "package p1; " + "\n"
+ "@AnnoStringArray({\"A1\",\"A2\"})" + "\n"
+ "public class A {\n"
+ " public void foo() {\n"
+ " System.out.println(\"test\");"
+ " }"
+ "}";
String a2Code = "package p1; " + "\n"
+ "@AnnoStringArray({\"A2\",\"A1\"})" + "\n"
+ "public class A {\n"
+ "\n"
+ " public void foo() {\n"
+ " System.out.println(\"test\");"
+ " }"
+ "}";
String bCode = "package p1; " + "\n"
+ "public class B {" + "\n"
+ " public A a;" + "\n"
+ "}";
env.addClass( this.srcRoot, "p1", "A", a1Code );
env.addClass( this.srcRoot, "p1", "B", bCode );
addAnnotationType();
fullBuild( this.projectPath );
expectingNoProblems();
// edit annotation in A
env.addClass( this.srcRoot, "p1", "A", a2Code );
incrementalBuild( this.projectPath );
expectingNoProblems();
// verify that B was recompiled
expectingUniqueCompiledClasses(new String[] { "p1.A", "p1.B" });
}
/**
* https://bugs.eclipse.org/bugs/show_bug.cgi?id=317841
*/
public void testTypeAnnotationDependency25() throws Exception
{
String a1Code = "package p1; " + "\n"
+ "@AnnoAnnotation(@AnnoLong(3))" + "\n"
+ "public class A {\n"
+ " public void foo() {\n"
+ " System.out.println(\"test\");"
+ " }"
+ "}";
String a2Code = "package p1; " + "\n"
+ "@AnnoAnnotation(@AnnoLong(4))" + "\n"
+ "public class A {\n"
+ "\n"
+ " public void foo() {\n"
+ " System.out.println(\"test\");"
+ " }"
+ "}";
String bCode = "package p1; " + "\n"
+ "public class B {" + "\n"
+ " public A a;" + "\n"
+ "}";
env.addClass( this.srcRoot, "p1", "A", a1Code );
env.addClass( this.srcRoot, "p1", "B", bCode );
addAnnotationType();
fullBuild( this.projectPath );
expectingNoProblems();
// edit annotation in A
env.addClass( this.srcRoot, "p1", "A", a2Code );
incrementalBuild( this.projectPath );
expectingNoProblems();
// verify that B was recompiled
expectingUniqueCompiledClasses(new String[] { "p1.A", "p1.B" });
}
/**
* https://bugs.eclipse.org/bugs/show_bug.cgi?id=317841
*/
public void testTypeAnnotationDependency26() throws Exception
{
String a1Code = "package p1; " + "\n"
+ "@AnnoEnum(E.A)\n"
+ "public class A {\n"
+ " public void foo() {\n"
+ " System.out.println(\"test\");"
+ " }"
+ "}";
String a2Code = "package p1; " + "\n"
+ "@AnnoEnum(E.C)\n"
+ "public class A {\n"
+ "\n"
+ " public void foo() {\n"
+ " System.out.println(\"test\");"
+ " }"
+ "}";
String bCode = "package p1; " + "\n"
+ "public class B {" + "\n"
+ " public A a;" + "\n"
+ "}";
env.addClass( this.srcRoot, "p1", "A", a1Code );
env.addClass( this.srcRoot, "p1", "B", bCode );
addAnnotationType();
fullBuild( this.projectPath );
expectingNoProblems();
// edit annotation in A
env.addClass( this.srcRoot, "p1", "A", a2Code );
incrementalBuild( this.projectPath );
expectingNoProblems();
// verify that B was recompiled
expectingUniqueCompiledClasses(new String[] { "p1.A", "p1.B" });
}
/**
* https://bugs.eclipse.org/bugs/show_bug.cgi?id=317841
*/
public void testTypeAnnotationDependency27() throws Exception
{
String a1Code = "package p1; " + "\n"
+ "@AnnoClass(Object.class)\n"
+ "public class A {\n"
+ " public void foo() {\n"
+ " System.out.println(\"test\");"
+ " }"
+ "}";
String a2Code = "package p1; " + "\n"
+ "@AnnoClass(String.class)\n"
+ "public class A {\n"
+ "\n"
+ " public void foo() {\n"
+ " System.out.println(\"test\");"
+ " }"
+ "}";
String bCode = "package p1; " + "\n"
+ "public class B {" + "\n"
+ " public A a;" + "\n"
+ "}";
env.addClass( this.srcRoot, "p1", "A", a1Code );
env.addClass( this.srcRoot, "p1", "B", bCode );
addAnnotationType();
fullBuild( this.projectPath );
expectingNoProblems();
// edit annotation in A
env.addClass( this.srcRoot, "p1", "A", a2Code );
incrementalBuild( this.projectPath );
expectingNoProblems();
// verify that B was recompiled
expectingUniqueCompiledClasses(new String[] { "p1.A", "p1.B" });
}
// Bug 365992 - [builder] [null] Change of nullness for a parameter doesn't trigger a build for the files that call the method
public void testParameterAnnotationDependency01() throws JavaModelException, IOException {
// prepare the project:
setupProjectForNullAnnotations();
String test1Code = "package p1;\n" +
"public class Test1 {\n" +
" public void foo() {\n" +
" new Test2().bar(null);\n" +
" }\n" +
"}";
String test2Code = "package p1;\n" +
"public class Test2 {\n" +
" public void bar(String str) {}\n" +
"}";
IPath test1Path = env.addClass( this.srcRoot, "p1", "Test1", test1Code );
env.addClass( this.srcRoot, "p1", "Test2", test2Code );
fullBuild( this.projectPath );
expectingNoProblems();
// edit Test2 to add @NonNull annotation (changes number of annotations)
String test2CodeB = "package p1;\n" +
"import org.eclipse.jdt.annotation.NonNull;\n" +
"public class Test2 {\n" +
" public void bar(@NonNull String str) {}\n" +
"}";
env.addClass( this.srcRoot, "p1", "Test2", test2CodeB );
incrementalBuild( this.projectPath );
expectingProblemsFor(test1Path,
"Problem : Null type mismatch: required \'@NonNull String\' but the provided value is null [ resource : </Project/src/p1/Test1.java> range : <81,85> category : <90> severity : <2>]");
// verify that Test1 was recompiled
expectingUniqueCompiledClasses(new String[] { "p1.Test1", "p1.Test2" });
// fix error by changing to @Nullable (change is only in an annotation name)
String test2CodeC = "package p1;\n" +
"import org.eclipse.jdt.annotation.Nullable;\n" +
"public class Test2 {\n" +
" public void bar(@Nullable String str) {}\n" +
"}";
env.addClass( this.srcRoot, "p1", "Test2", test2CodeC );
incrementalBuild( this.projectPath );
expectingNoProblems();
// verify that Test1 was recompiled
expectingUniqueCompiledClasses(new String[] { "p1.Test1", "p1.Test2" });
}
// Bug 365992 - [builder] [null] Change of nullness for a parameter doesn't trigger a build for the files that call the method
// Bug 366341 - Incremental compiler fails to detect right scope for annotation related code changes
public void testReturnAnnotationDependency01() throws JavaModelException, IOException {
// prepare the project:
setupProjectForNullAnnotations();
String test1Code = "package p1;\n" +
"import org.eclipse.jdt.annotation.NonNull;\n" +
"public class Test1 {\n" +
" public @NonNull Object foo() {\n" +
" return new Test2().bar();\n" +
" }\n" +
"}";
String test2Code = "package p1;\n" +
"import org.eclipse.jdt.annotation.NonNull;\n" +
"public class Test2 {\n" +
" public @NonNull Object bar() { return this; }\n" +
"}";
IPath test1Path = env.addClass( this.srcRoot, "p1", "Test1", test1Code );
env.addClass( this.srcRoot, "p1", "Test2", test2Code );
fullBuild( this.projectPath );
expectingNoProblems();
// edit Test2 to replace annotation
String test2CodeB = "package p1;\n" +
"import org.eclipse.jdt.annotation.Nullable;\n" +
"public class Test2 {\n" +
" public @Nullable Object bar() { return null; }\n" +
"}";
env.addClass( this.srcRoot, "p1", "Test2", test2CodeB );
incrementalBuild( this.projectPath );
expectingProblemsFor(test1Path,
"Problem : Null type mismatch: required \'@NonNull Object\' but the provided value is specified as @Nullable [ resource : </Project/src/p1/Test1.java> range : <126,143> category : <90> severity : <2>]");
// verify that Test1 was recompiled
expectingUniqueCompiledClasses(new String[] { "p1.Test1", "p1.Test2" });
// remove annotation, error changes from can be null to unknown nullness
String test2CodeC = "package p1;\n" +
"public class Test2 {\n" +
" public Object bar() { return null; }\n" +
"}";
env.addClass( this.srcRoot, "p1", "Test2", test2CodeC );
incrementalBuild( this.projectPath );
expectingProblemsFor(test1Path,
"Problem : Null type safety: The expression of type 'Object' needs unchecked conversion to conform to \'@NonNull Object\' [ resource : </Project/src/p1/Test1.java> range : <126,143> category : <90> severity : <1>]");
// verify that Test1 was recompiled
expectingUniqueCompiledClasses(new String[] { "p1.Test1", "p1.Test2" });
// back to initial OK version (re-add @NonNull annotation)
env.addClass( this.srcRoot, "p1", "Test2", test2Code );
incrementalBuild( this.projectPath );
expectingNoProblems();
// verify that Test1 was recompiled
expectingUniqueCompiledClasses(new String[] { "p1.Test1", "p1.Test2" });
}
// https://bugs.eclipse.org/bugs/show_bug.cgi?id=373571
// incremental build that uses binary type for Test1 should not report spurious null errors.
public void testReturnAnnotationDependency02() throws JavaModelException, IOException {
// prepare the project:
setupProjectForNullAnnotations();
String test1Code = "package p1;\n" +
"import org.eclipse.jdt.annotation.NonNullByDefault;\n" +
"@NonNullByDefault\n" +
"public class Test1 {\n" +
" public void doStuff(int i) {\n" +
" }\n" +
"}";
env.addClass( this.srcRoot, "p1", "Test1", test1Code );
fullBuild( this.projectPath );
expectingNoProblems();
// add Test2
String test2Code = "package p1;\n" +
"import org.eclipse.jdt.annotation.NonNullByDefault;\n" +
"@NonNullByDefault\n" +
"public class Test2 extends Test1{\n" +
" @Override\n" +
" public void doStuff(int i) {\n" +
" super.doStuff(i);\n" +
" }\n" +
"}";
env.addClass( this.srcRoot, "p1", "Test2", test2Code );
incrementalBuild( this.projectPath );
expectingNoProblems();
// verify that Test2 only was recompiled
expectingUniqueCompiledClasses(new String[] { "p1.Test2" });
// edit Test2 to delete annotation
test2Code = "package p1;\n" +
"public class Test2 extends Test1{\n" +
" @Override\n" +
" public void doStuff(int i) {\n" +
" super.doStuff(i);\n" +
" }\n" +
"}";
env.addClass( this.srcRoot, "p1", "Test2", test2Code );
incrementalBuild( this.projectPath );
expectingNoProblems();
// verify that Test2 only was recompiled
expectingUniqueCompiledClasses(new String[] { "p1.Test2" });
}
//https://bugs.eclipse.org/bugs/show_bug.cgi?id=411771
//[compiler][null] Enum constants not recognized as being NonNull.
//This test case exposes the bug mentioned in the defect. The enum
//definition comes from a file different from where it is accessed.
public void test411771a() throws IOException, JavaModelException {
setupProjectForNullAnnotations();
String testEnumCode = "package p1;\n" +
"enum TestEnum {FOO };\n";
env.addClass( this.srcRoot, "p1", "TestEnum", testEnumCode );
fullBuild( this.projectPath );
expectingNoProblems();
String nullTestCode = "package p1;\n" +
"import org.eclipse.jdt.annotation.NonNull;\n" +
"public class NullTest {\n" +
" public static TestEnum bla() {\n" +
" @NonNull final TestEnum t = TestEnum.FOO;\n" +
" return t;\n" +
" }\n" +
"}";
env.addClass( this.srcRoot, "p1", "NullTest", nullTestCode );
incrementalBuild( this.projectPath );
expectingNoProblems();
expectingUniqueCompiledClasses(new String[] { "p1.NullTest" });
}
//https://bugs.eclipse.org/bugs/show_bug.cgi?id=411771
//[compiler][null] Enum constants not recognized as being NonNull.
//Distinguish between enum constant and enum type. The enum type should not
//be marked as NonNull.
public void test411771b() throws IOException, JavaModelException {
setupProjectForNullAnnotations();
String testEnumCode = "package p1;\n" +
"enum TestEnum { FOO };\n";
env.addClass( this.srcRoot, "p1", "TestEnum", testEnumCode );
fullBuild( this.projectPath );
expectingNoProblems();
String testClass = "package p1;\n" +
"public class X { TestEnum f; };\n";
env.addClass( this.srcRoot, "p1", "X", testClass );
incrementalBuild( this.projectPath );
expectingNoProblems();
String nullTestCode = "package p1;\n" +
"import org.eclipse.jdt.annotation.NonNull;\n" +
"public class NullTest {\n" +
" public static TestEnum bla(X x) {\n" +
" @NonNull final TestEnum t = x.f;\n" +
" return t;\n" +
" }\n" +
"}\n";
IPath test1Path = env.addClass( this.srcRoot, "p1", "NullTest", nullTestCode );
incrementalBuild( this.projectPath );
expectingProblemsFor(test1Path,
"Problem : Null type safety: The expression of type 'TestEnum' needs unchecked conversion to conform to " +
"'@NonNull TestEnum' [ resource : </Project/src/p1/NullTest.java> range : <144,147> category : <90> severity : <1>]");
expectingUniqueCompiledClasses(new String[] { "p1.NullTest" });
}
//https://bugs.eclipse.org/bugs/show_bug.cgi?id=411771
//[compiler][null] Enum constants not recognized as being NonNull.
//A enum may contain fields other than predefined constants. We
//should not tag them as NonNull.
public void test411771c() throws IOException, JavaModelException {
setupProjectForNullAnnotations();
String testClass = "package p1;\n" +
"public class A {}";
env.addClass( this.srcRoot, "p1", "A", testClass );
fullBuild( this.projectPath );
expectingNoProblems();
String testEnumCode = "package p1;\n" +
"enum TestEnum {\n" +
" FOO;\n" +
" public static A a;" +
"};\n";
env.addClass( this.srcRoot, "p1", "TestEnum", testEnumCode );
incrementalBuild( this.projectPath );
expectingNoProblems();
String nullTestCode = "package p1;\n" +
"import org.eclipse.jdt.annotation.NonNull;\n" +
"public class NullTest {\n" +
" public static TestEnum bla() {\n" +
" @NonNull final TestEnum t = TestEnum.FOO;\n" +
" return t;\n" +
" }\n" +
" public A testint() {\n" +
" @NonNull A a = TestEnum.a;\n" +
" return a;\n" +
" }\n" +
"}";
IPath test1Path = env.addClass( this.srcRoot, "p1", "NullTest", nullTestCode );
incrementalBuild( this.projectPath );
expectingProblemsFor(test1Path,
"Problem : Null type safety: The expression of type 'A' needs unchecked conversion to conform to " +
"'@NonNull A' [ resource : </Project/src/p1/NullTest.java> range : <208,218> category : <90> severity : <1>]");
expectingUniqueCompiledClasses(new String[] { "p1.NullTest" });
}
}