blob: d2dd9852f7b135f2b69d82ac60aa34db7e562847 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2013, 2015 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
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
*******************************************************************************/
package org.eclipse.jdt.core.tests.builder;
import java.io.File;
import java.io.IOException;
import junit.framework.Test;
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.tests.util.AbstractCompilerTest;
import org.eclipse.jdt.core.tests.util.Util;
import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
import org.osgi.framework.Bundle;
public class IncrementalTests18 extends BuilderTests {
static {
// TESTS_NAMES = new String[] { "testBug481276b" };
}
public IncrementalTests18(String name) {
super(name);
}
public static Test suite() {
return AbstractCompilerTest.buildUniqueComplianceTestSuite(IncrementalTests18.class, ClassFileConstants.JDK1_8);
}
private 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","[2.0.0,3.0.0)");
File bundleFile = FileLocator.getBundleFile(bundles[0]);
String annotationsLib = bundleFile.isDirectory() ? bundleFile.getPath()+"/bin" : bundleFile.getPath();
IJavaProject javaProject = env.getJavaProject("Project");
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);
}
// https://bugs.eclipse.org/bugs/show_bug.cgi?id=423122, [1.8] Missing incremental build dependency from lambda expression to functional interface.
public void test423122() throws JavaModelException {
IPath projectPath = env.addProject("Project", "1.8");
env.addExternalJars(projectPath, Util.getJavaClassLibs());
// remove old package fragment root so that names don't collide
env.removePackageFragmentRoot(projectPath, "");
IPath root = env.addPackageFragmentRoot(projectPath, "src");
env.setOutputFolder(projectPath, "bin");
env.addClass(root, "p", "I",
"package p; \n"+
"public interface I { void foo(); } \n"
);
env.addClass(root, "p", "X",
"package p; \n"+
"public class X { I i = () -> {}; } \n"
);
fullBuild(projectPath);
expectingNoProblems();
env.addClass(root, "p", "I",
"package p; \n"+
"public interface I { } \n"
);
incrementalBuild(projectPath);
expectingProblemsFor(
projectPath,
"Problem : The target type of this expression must be a functional interface [ resource : </Project/src/p/X.java> range : <35,40> category : <40> severity : <2>]"
);
}
// https://bugs.eclipse.org/bugs/show_bug.cgi?id=423122, [1.8] Missing incremental build dependency from lambda expression to functional interface.
public void test423122a() throws JavaModelException {
IPath projectPath = env.addProject("Project", "1.8");
env.addExternalJars(projectPath, Util.getJavaClassLibs());
// remove old package fragment root so that names don't collide
env.removePackageFragmentRoot(projectPath, "");
IPath root = env.addPackageFragmentRoot(projectPath, "src");
env.setOutputFolder(projectPath, "bin");
env.addClass(root, "test1", "I",
"package test1;\n" +
"public interface I {\n" +
" int method(int a); // change argument type to Object\n" +
"}\n"
);
env.addClass(root, "test1", "E",
"package test1;\n" +
"public class E {\n" +
" void take(I i) {\n" +
" }\n" +
"}\n"
);
env.addClass(root, "test1", "Ref",
"package test1;\n" +
"public class Ref {\n" +
" void foo(E e) {\n" +
" e.take((x) -> x+2); // not recompiled when I#method changed\n" +
" }\n" +
"}\n"
);
fullBuild(projectPath);
expectingNoProblems();
env.addClass(root, "test1", "I",
"package test1;\n" +
"public interface I {\n" +
" int method(Object a); // change argument type to Object\n" +
"}\n"
);
incrementalBuild(projectPath);
expectingProblemsFor(
projectPath,
"Problem : The operator + is undefined for the argument type(s) Object, int [ resource : </Project/src/test1/Ref.java> range : <76,79> category : <60> severity : <2>]"
);
env.addClass(root, "test1", "I",
"package test1;\n" +
"public interface I {\n" +
" int method(int a); // change argument type back to int\n" +
"}\n"
);
incrementalBuild(projectPath);
expectingNoProblems();
}
// https://bugs.eclipse.org/bugs/show_bug.cgi?id=427105, [1.8][builder] Differences between incremental and full builds in method contract verification in the presence of type annotations
public void test427105() throws JavaModelException {
IPath projectPath = env.addProject("Project", "1.8");
env.addExternalJars(projectPath, Util.getJavaClassLibs());
// remove old package fragment root so that names don't collide
env.removePackageFragmentRoot(projectPath, "");
IPath root = env.addPackageFragmentRoot(projectPath, "src");
env.setOutputFolder(projectPath, "bin");
env.addClass(root, "", "X",
"import java.util.List;\n" +
"public class X implements I {\n" +
" public void f(List x, List<I> ls) { \n" +
" }\n" +
"}\n"
);
env.addClass(root, "", "I",
"import java.util.List;\n" +
"public interface I {\n" +
" void f(@T List x, List<I> ls);\n" +
"}\n"
);
env.addClass(root, "", "T",
"import java.lang.annotation.ElementType;\n" +
"import java.lang.annotation.Target;\n" +
"@Target(ElementType.TYPE_USE)\n" +
"public @interface T {\n" +
"}\n"
);
// force annotation encoding into bindings which is necessary to reproduce.
env.getJavaProject("Project").setOption(JavaCore.COMPILER_ANNOTATION_NULL_ANALYSIS, JavaCore.ENABLED);
fullBuild(projectPath);
expectingProblemsFor(
projectPath,
"Problem : List is a raw type. References to generic type List<E> should be parameterized [ resource : </Project/src/I.java> range : <55,59> category : <130> severity : <1>]\n" +
"Problem : List is a raw type. References to generic type List<E> should be parameterized [ resource : </Project/src/X.java> range : <68,72> category : <130> severity : <1>]"
);
env.addClass(root, "", "X",
"import java.util.List;\n" +
"public class X implements I {\n" +
" public void f(List x, List<I> ls) { \n" +
" }\n" +
"}\n"
);
incrementalBuild(projectPath);
expectingProblemsFor(
projectPath,
"Problem : List is a raw type. References to generic type List<E> should be parameterized [ resource : </Project/src/I.java> range : <55,59> category : <130> severity : <1>]\n" +
"Problem : List is a raw type. References to generic type List<E> should be parameterized [ resource : </Project/src/X.java> range : <68,72> category : <130> severity : <1>]"
);
}
// https://bugs.eclipse.org/bugs/show_bug.cgi?id=427105, [1.8][builder] Differences between incremental and full builds in method contract verification in the presence of type annotations
public void test427105a() throws JavaModelException {
IPath projectPath = env.addProject("Project", "1.8");
env.addExternalJars(projectPath, Util.getJavaClassLibs());
// remove old package fragment root so that names don't collide
env.removePackageFragmentRoot(projectPath, "");
IPath root = env.addPackageFragmentRoot(projectPath, "src");
env.setOutputFolder(projectPath, "bin");
env.addClass(root, "", "X",
"import java.util.List;\n" +
"public class X implements I {\n" +
" public void f(List x, List<I> ls) { \n" +
" }\n" +
"}\n"
);
env.addClass(root, "", "I",
"import java.util.List;\n" +
"public interface I {\n" +
" void f(@T List x, List<I> ls);\n" +
"}\n"
);
env.addClass(root, "", "T",
"import java.lang.annotation.ElementType;\n" +
"import java.lang.annotation.Target;\n" +
"@Target(ElementType.TYPE_USE)\n" +
"public @interface T {\n" +
"}\n"
);
// force annotation encoding into bindings which is necessary to reproduce.
env.getJavaProject("Project").setOption(JavaCore.COMPILER_ANNOTATION_NULL_ANALYSIS, JavaCore.ENABLED);
fullBuild(projectPath);
expectingProblemsFor(
projectPath,
"Problem : List is a raw type. References to generic type List<E> should be parameterized [ resource : </Project/src/I.java> range : <55,59> category : <130> severity : <1>]\n" +
"Problem : List is a raw type. References to generic type List<E> should be parameterized [ resource : </Project/src/X.java> range : <68,72> category : <130> severity : <1>]"
);
env.addClass(root, "", "X",
"import java.util.List;\n" +
"public class X implements I {\n" +
" public void f(@T List x, List<I> ls) { \n" +
" }\n" +
"}\n"
);
incrementalBuild(projectPath);
expectingProblemsFor(
projectPath,
"Problem : List is a raw type. References to generic type List<E> should be parameterized [ resource : </Project/src/I.java> range : <55,59> category : <130> severity : <1>]\n" +
"Problem : List is a raw type. References to generic type List<E> should be parameterized [ resource : </Project/src/X.java> range : <71,75> category : <130> severity : <1>]"
);
}
// https://bugs.eclipse.org/bugs/show_bug.cgi?id=428071, [1.8][compiler] Bogus error about incompatible return type during override
public void test428071() throws JavaModelException {
IPath projectPath = env.addProject("Project", "1.8");
env.addExternalJars(projectPath, Util.getJavaClassLibs());
// remove old package fragment root so that names don't collide
env.removePackageFragmentRoot(projectPath, "");
IPath root = env.addPackageFragmentRoot(projectPath, "src");
env.setOutputFolder(projectPath, "bin");
env.addClass(root, "", "K1",
"import java.util.List;\n" +
"import java.util.Map;\n" +
"interface K1 {\n" +
" public Map<String,List> get();\n" +
"}\n"
);
env.addClass(root, "", "K",
"import java.util.List;\n" +
"import java.util.Map;\n" +
"public class K implements K1 {\n" +
" public Map<String, List> get() {\n" +
" return null;\n" +
" }\n" +
"}\n"
);
env.getJavaProject("Project").setOption(JavaCore.COMPILER_PB_RAW_TYPE_REFERENCE, JavaCore.IGNORE);
fullBuild(projectPath);
expectingNoProblems();
env.addClass(root, "", "K",
"import java.util.List;\n" +
"import java.util.Map;\n" +
"public class K implements K1 {\n" +
" public Map<String, List> get() {\n" +
" return null;\n" +
" }\n" +
"}\n"
);
incrementalBuild(projectPath);
expectingNoProblems();
}
// https://bugs.eclipse.org/bugs/show_bug.cgi?id=430425, [1.8][compiler] Type mismatch: cannot convert from StyleConverter<ParsedValue[],Insets> to StyleConverter<ParsedValue[],Insets>
public void test430425() throws JavaModelException {
IPath projectPath = env.addProject("Project", "1.8");
String jreDirectory = Util.getJREDirectory();
String jfxJar = Util.toNativePath(jreDirectory + "/lib/ext/jfxrt.jar");
File file = new File(jfxJar);
if (file.exists())
env.addExternalJars(projectPath, Util.concatWithClassLibs(jfxJar, false));
else
return;
// remove old package fragment root so that names don't collide
env.removePackageFragmentRoot(projectPath, "");
IPath root = env.addPackageFragmentRoot(projectPath, "src");
env.setOutputFolder(projectPath, "bin");
env.addClass(root, "javafx.css", "StyleConverter",
"package javafx.css;\n" +
"import com.sun.javafx.css.converters.InsetsConverter;\n" +
"import javafx.geometry.Insets;\n" +
"public class StyleConverter<F, T> {\n" +
" public static StyleConverter<ParsedValue[], Insets> getInsetsConverter() {\n" +
" return InsetsConverter.getInstance();\n" +
" }\n" +
" void fred5555() {\n" +
" }\n" +
"}\n"
);
env.addClass(root, "com.sun.javafx.css.converters", "InsetsConverter",
"package com.sun.javafx.css.converters;\n" +
"import com.sun.javafx.css.StyleConverterImpl;\n" +
"import javafx.css.ParsedValue;\n" +
"import javafx.css.StyleConverter;\n" +
"import javafx.geometry.Insets;\n" +
"public final class InsetsConverter extends StyleConverterImpl<ParsedValue[], Insets> {\n" +
" public static StyleConverter<ParsedValue[], Insets> getInstance() {\n" +
" return null;\n" +
" }\n" +
"}\n"
);
env.addClass(root, "javafx.css", "ParsedValue",
"package javafx.css;\n" +
"public class ParsedValue<V, T> {\n" +
"}\n"
);
env.getJavaProject("Project").setOption(JavaCore.COMPILER_PB_RAW_TYPE_REFERENCE, JavaCore.IGNORE);
fullBuild(projectPath);
expectingNoProblems();
env.addClass(root, "javafx.css", "StyleConverter",
"package javafx.css;\n" +
"import com.sun.javafx.css.converters.InsetsConverter;\n" +
"import javafx.geometry.Insets;\n" +
"public class StyleConverter<F, T> {\n" +
" public static StyleConverter<ParsedValue[], Insets> getInsetsConverter() {\n" +
" return InsetsConverter.getInstance();\n" +
" }\n" +
" void fred555() {\n" +
" }\n" +
"}\n"
);
incrementalBuild(projectPath);
expectingNoProblems();
}
// https://bugs.eclipse.org/bugs/show_bug.cgi?id=435544, [compiler][null] Enum constants not recognised as being NonNull (take2)
public void test435544() throws JavaModelException, IOException {
IPath projectPath = env.addProject("Project", "1.8");
env.addExternalJars(projectPath, Util.getJavaClassLibs());
// remove old package fragment root so that names don't collide
env.removePackageFragmentRoot(projectPath, "");
IPath root = env.addPackageFragmentRoot(projectPath, "src");
env.setOutputFolder(projectPath, "bin");
setupProjectForNullAnnotations();
env.addClass(root, "p", "Y",
"package p; \n" +
"public enum Y {\n" +
" A,\n" +
" B\n" +
"}\n" +
"\n"
);
fullBuild(projectPath);
expectingNoProblems();
env.addClass(root, "p", "X",
"package p; \n" +
"import org.eclipse.jdt.annotation.NonNull;\n" +
"public class X {\n" +
" @NonNull\n" +
" public Y y = Y.A; // warning without fix\n" +
" void foo(@NonNull Y y) {}\n" +
" void bar() {\n" +
" foo(Y.A); // warning without fix\n" +
" }\n" +
"}\n"
);
incrementalBuild(projectPath);
expectingNoProblems();
}
// https://bugs.eclipse.org/bugs/show_bug.cgi?id=442452, [compiler][regression] Bogus error: The interface Comparable cannot be implemented more than once with different arguments
public void testBug442452() throws JavaModelException {
IPath projectPath = env.addProject("Project", "1.8");
env.addExternalJars(projectPath, Util.getJavaClassLibs());
env.setOutputFolder(projectPath, "bin"); //$NON-NLS-1$
env.addClass(projectPath, "", "Entity", //$NON-NLS-1$ //$NON-NLS-2$
"public class Entity implements IEntity<Entity> {\n" +
" public int compareTo(IBasicItem o) {\n" +
" return 0;\n" +
" }\n" +
"}\n"); //$NON-NLS-1$
env.addClass(projectPath, "", "IEntity", //$NON-NLS-1$ //$NON-NLS-2$
"public interface IEntity<T extends IEntity<T>> extends IBasicItem {\n" +
"}\n"); //$NON-NLS-1$
env.addClass(projectPath, "", "IBasicItem", //$NON-NLS-1$ //$NON-NLS-2$
"public interface IBasicItem extends Comparable<IBasicItem> {\n" +
"}\n"); //$NON-NLS-1$
env.addClass(projectPath, "", "IAdvancedItem", //$NON-NLS-1$ //$NON-NLS-2$
"public interface IAdvancedItem extends Comparable<IBasicItem> {\n" +
"}\n"); //$NON-NLS-1$
fullBuild(projectPath);
expectingNoProblems();
env.addClass(projectPath, "", "Entity", //$NON-NLS-1$ //$NON-NLS-2$
"public class Entity implements IEntity<Entity>, IAdvancedItem {\n" +
" public int compareTo(IBasicItem o) {\n" +
" return 0;\n" +
" }\n" +
"}\n"); //$NON-NLS-1$
incrementalBuild(projectPath);
expectingNoProblems();
}
// https://bugs.eclipse.org/bugs/show_bug.cgi?id=442755,
// [compiler] NPE at ProblemHandler.handle
public void testBug442755() throws JavaModelException {
IPath projectPath = env.addProject("Project", "1.8");
env.addExternalJars(projectPath, Util.getJavaClassLibs());
env.setOutputFolder(projectPath, "bin");
env.addClass(projectPath, "", "Z",
"public interface Z <X1 extends X, Y1 extends Y> {}\n");
fullBuild(projectPath);
expectingProblemsFor(
projectPath,
"Problem : X cannot be resolved to a type [ resource : </Project/Z.java>" +
" range : <31,32> category : <40> severity : <2>]\n" +
"Problem : Y cannot be resolved to a type [ resource : </Project/Z.java>" +
" range : <45,46> category : <40> severity : <2>]");
env.addClass(projectPath, "", "Unmarshaller", //$NON-NLS-1$ //$NON-NLS-2$
"public abstract class Unmarshaller<CONTEXT extends Context, DESCRIPTOR extends Z> {\n" +
" public CONTEXT getContext() {\n" +
" return null;\n" +
" }\n" +
"}\n");
incrementalBuild(projectPath);
expectingProblemsFor(
projectPath,
"Problem : The project was not built since its build path is incomplete." +
" Cannot find the class file for Y. Fix the build path then try building" +
" this project [ resource : </Project> range : <-1,-1> category : <10> severity : <2>]\n" +
"Problem : The type Y cannot be resolved. It is indirectly referenced from" +
" required .class files [ resource : </Project/Unmarshaller.java> range : <0,1> category : <10> severity : <2>]");
}
// https://bugs.eclipse.org/bugs/show_bug.cgi?id=442755,
// [compiler] NPE at ProblemHandler.handle
// Simplified test case.
public void testBug442755a() throws JavaModelException {
IPath projectPath = env.addProject("Project", "1.8");
env.addExternalJars(projectPath, Util.getJavaClassLibs());
env.setOutputFolder(projectPath, "bin");
env.addClass(projectPath, "", "Z",
"public class Z <Y2 extends Y> {}\n");
fullBuild(projectPath);
expectingProblemsFor(
projectPath,
"Problem : Y cannot be resolved to a type [ resource : " +
"</Project/Z.java> range : <27,28> category : <40> severity : <2>]");
env.addClass(projectPath, "", "X", //$NON-NLS-1$ //$NON-NLS-2$
"public class X <Z> {}\n");
incrementalBuild(projectPath);
expectingProblemsFor(
projectPath,
"Problem : The project was not built since its build path is incomplete." +
" Cannot find the class file for Y. Fix the build path then try building" +
" this project [ resource : </Project> range : <-1,-1> category : <10> severity : <2>]\n" +
"Problem : The type Y cannot be resolved. It is indirectly referenced from" +
" required .class files [ resource : </Project/X.java> range : <0,1> category : <10> severity : <2>]");
}
// https://bugs.eclipse.org/bugs/show_bug.cgi?id=445049,
// [compiler] java.lang.ClassCastException: org.eclipse.jdt.internal.compiler.lookup.BinaryTypeBinding
// cannot be cast to org.eclipse.jdt.internal.compiler.lookup.SourceTypeBinding
public void test445049() throws JavaModelException, IOException {
IPath projectPath = env.addProject("Project", "1.8");
env.addExternalJars(projectPath, Util.getJavaClassLibs());
// remove old package fragment root so that names don't collide
env.removePackageFragmentRoot(projectPath, "");
IPath root = env.addPackageFragmentRoot(projectPath, "src");
env.setOutputFolder(projectPath, "bin");
setupProjectForNullAnnotations();
env.addClass(root, "", "I",
"public interface I { int f = 0;}");
fullBuild(projectPath);
expectingNoProblems();
env.addClass(root, "", "X", "class X implements I { int i = I.super.f;}");
incrementalBuild(projectPath);
expectingProblemsFor(
projectPath,
"Problem : No enclosing instance of the type I is accessible in scope [" +
" resource : </Project/src/X.java> range : <31,38> category : <40> severity : <2>]");
}
public void testBug481276a() throws Exception {
IPath projectPath = env.addProject("Project", "1.8");
env.addExternalJars(projectPath, Util.getJavaClassLibs());
// remove old package fragment root so that names don't collide
env.removePackageFragmentRoot(projectPath, "");
IPath root = env.addPackageFragmentRoot(projectPath, "src");
env.setOutputFolder(projectPath, "bin");
setupProjectForNullAnnotations();
// clean status from https://bugs.eclipse.org/bugs/attachment.cgi?id=257687
env.addClass(root, "testNullAnnotations", "package-info",
"@org.eclipse.jdt.annotation.NonNullByDefault\n" +
"package testNullAnnotations;\n");
env.addClass(root, "testNullAnnotations", "NonNullUtils",
"package testNullAnnotations;\n" +
"\n" +
"import org.eclipse.jdt.annotation.Nullable;\n" +
"\n" +
"public final class NonNullUtils {\n" +
"\n" +
" public static <T> T[] checkNotNull(T @Nullable [] array) {\n" +
" if (array == null) {\n" +
" throw new NullPointerException();\n" +
" }\n" +
" return array;\n" +
" }\n" +
"}\n");
env.addClass(root, "testNullAnnotations", "Snippet",
"package testNullAnnotations;\n" +
"\n" +
"import static testNullAnnotations.NonNullUtils.checkNotNull;\n" +
"\n" +
"import org.eclipse.jdt.annotation.*;\n" +
"\n" +
"public class Snippet {\n" +
" @SuppressWarnings(\"unused\")\n" +
" public void foo() {\n" +
" @NonNull Object @Nullable [] objects = null;\n" +
" @NonNull Object @NonNull [] checked3 = checkNotNull(objects); \n" +
" }\n" +
"}\n");
fullBuild(projectPath);
expectingNoProblems();
// add an error by removing the necessary @Nullable annotation:
env.addClass(root, "testNullAnnotations", "NonNullUtils",
"package testNullAnnotations;\n" +
"\n" +
"public final class NonNullUtils {\n" +
"\n" +
" public static <T> T[] checkNotNull(T [] array) {\n" +
" if (array == null) {\n" +
" throw new NullPointerException();\n" +
" }\n" +
" return array;\n" +
" }\n" +
"}\n");
incrementalBuild(projectPath);
expectingProblemsFor(
projectPath,
"Problem : Dead code [" +
" resource : </Project/src/testNullAnnotations/NonNullUtils.java> range : <145,202> category : <90> severity : <1>]\n" +
"Problem : Null type mismatch (type annotations): required '@NonNull Object @NonNull[]' but this expression has type '@NonNull Object @Nullable[]' [" +
" resource : </Project/src/testNullAnnotations/Snippet.java> range : <316,323> category : <90> severity : <2>]");
}
public void testBug481276b() throws Exception {
IPath projectPath = env.addProject("Project", "1.8");
env.addExternalJars(projectPath, Util.getJavaClassLibs());
// remove old package fragment root so that names don't collide
env.removePackageFragmentRoot(projectPath, "");
IPath root = env.addPackageFragmentRoot(projectPath, "src");
env.setOutputFolder(projectPath, "bin");
setupProjectForNullAnnotations();
// clean status:
env.addClass(root, "testNullAnnotations", "package-info",
"@org.eclipse.jdt.annotation.NonNullByDefault\n" +
"package testNullAnnotations;\n");
env.addClass(root, "testNullAnnotations", "NonNullUtils",
"package testNullAnnotations;\n" +
"\n" +
"import org.eclipse.jdt.annotation.Nullable;\n" +
"\n" +
"public final class NonNullUtils {\n" +
"\n" +
" public static <@Nullable T> T[] checkNotNull(T @Nullable[] array) {\n" +
" if (array == null) {\n" +
" throw new NullPointerException();\n" +
" }\n" +
" return array;\n" +
" }\n" +
"}\n");
env.addClass(root, "testNullAnnotations", "Snippet",
"package testNullAnnotations;\n" +
"\n" +
"import static testNullAnnotations.NonNullUtils.checkNotNull;\n" +
"\n" +
"import org.eclipse.jdt.annotation.*;\n" +
"\n" +
"public class Snippet {\n" +
" @SuppressWarnings(\"unused\")\n" +
" public void foo() {\n" +
" @NonNull Object @Nullable [] objects = new @NonNull Object[0];\n" +
" @NonNull Object @NonNull [] checked3 = checkNotNull(objects); \n" +
" }\n" +
"}\n");
fullBuild(projectPath);
expectingProblemsFor(
projectPath,
"Problem : Null type mismatch (type annotations): required \'@NonNull Object @NonNull[]\' but this expression has type \'@Nullable Object @NonNull[]\' [" +
" resource : </Project/src/testNullAnnotations/Snippet.java> range : <321,342> category : <90> severity : <2>]\n" +
"Problem : Null type mismatch (type annotations): required \'@Nullable Object @Nullable[]\' but this expression has type \'@NonNull Object @Nullable[]\' [" +
" resource : </Project/src/testNullAnnotations/Snippet.java> range : <334,341> category : <90> severity : <2>]");
// fix error according to https://bugs.eclipse.org/bugs/show_bug.cgi?id=481276#c4
env.addClass(root, "testNullAnnotations", "NonNullUtils",
"package testNullAnnotations;\n" +
"\n" +
"import org.eclipse.jdt.annotation.Nullable;\n" +
"\n" +
"public final class NonNullUtils {\n" +
"\n" +
" public static <T> T[] checkNotNull(T @Nullable[] array) {\n" +
" if (array == null) {\n" +
" throw new NullPointerException();\n" +
" }\n" +
" return array;\n" +
" }\n" +
"}\n");
incrementalBuild(projectPath);
expectingNoProblems();
}
public void testBug481276c() throws Exception {
IPath projectPath = env.addProject("Project", "1.8");
env.addExternalJars(projectPath, Util.getJavaClassLibs());
// remove old package fragment root so that names don't collide
env.removePackageFragmentRoot(projectPath, "");
IPath root = env.addPackageFragmentRoot(projectPath, "src");
env.setOutputFolder(projectPath, "bin");
setupProjectForNullAnnotations();
// clean status from https://bugs.eclipse.org/bugs/attachment.cgi?id=257687
env.addClass(root, "testNullAnnotations", "package-info",
"@org.eclipse.jdt.annotation.NonNullByDefault\n" +
"package testNullAnnotations;\n");
env.addClass(root, "testNullAnnotations", "NonNullUtils",
"package testNullAnnotations;\n" +
"\n" +
"import org.eclipse.jdt.annotation.Nullable;\n" +
"\n" +
"public final class NonNullUtils {\n" +
"\n" +
" public static <T> T[] checkNotNull(T @Nullable [] array) {\n" +
" if (array == null) {\n" +
" throw new NullPointerException();\n" +
" }\n" +
" return array;\n" +
" }\n" +
"}\n");
env.addClass(root, "testNullAnnotations", "Snippet",
"package testNullAnnotations;\n" +
"\n" +
"import static testNullAnnotations.NonNullUtils.checkNotNull;\n" +
"\n" +
"import org.eclipse.jdt.annotation.*;\n" +
"\n" +
"public class Snippet {\n" +
" @SuppressWarnings(\"unused\")\n" +
" public void foo() {\n" +
" @NonNull Object @Nullable [] objects = null;\n" +
" @NonNull Object @NonNull [] checked3 = checkNotNull(objects); \n" +
" }\n" +
"}\n");
fullBuild(projectPath);
expectingNoProblems();
// add a warning by making @NNBD ineffective:
env.addClass(root, "testNullAnnotations", "package-info",
"@org.eclipse.jdt.annotation.NonNullByDefault({})\n" +
"package testNullAnnotations;\n");
incrementalBuild(projectPath);
expectingProblemsFor(
projectPath,
"Problem : Null type safety (type annotations): The expression of type \'@NonNull Object []\' needs unchecked conversion to conform to \'@NonNull Object @NonNull[]\' [" +
" resource : </Project/src/testNullAnnotations/Snippet.java> range : <303,324> category : <90> severity : <1>]");
}
public void testBug483744_remove() throws JavaModelException, IOException {
IPath projectPath = env.addProject("Project", "1.8");
env.addExternalJars(projectPath, Util.getJavaClassLibs());
env.removePackageFragmentRoot(projectPath, "");
IPath root = env.addPackageFragmentRoot(projectPath, "src");
env.setOutputFolder(projectPath, "bin");
setupProjectForNullAnnotations();
env.addClass(root, "testNullAnnotations", "package-info",
"@org.eclipse.jdt.annotation.NonNullByDefault\n" +
"package testNullAnnotations;\n");
env.addClass(root, "testNullAnnotations", "NonNullUtils",
"package testNullAnnotations;\n" +
"\n" +
"import java.util.*;\n" +
"import org.eclipse.jdt.annotation.*;\n" +
"\n" +
"public final class NonNullUtils {\n" +
"\n" +
" public static <T> List<@NonNull T> checkNotNullContents(List<@Nullable T> list, List<@NonNull T> nList) {\n" +
" return nList;\n" +
" }\n" +
"}\n");
env.addClass(root, "testNullAnnotations", "Snippet",
"package testNullAnnotations;\n" +
"\n" +
"import java.util.*;\n" +
"import org.eclipse.jdt.annotation.*;\n" +
"\n" +
"import static testNullAnnotations.NonNullUtils.checkNotNullContents;\n" +
"\n" +
"public class Snippet {\n" +
" public List<@NonNull String> foo(List<@Nullable String> inList, List<@NonNull String> nList) {\n" +
" return checkNotNullContents(inList, nList); \n" +
" }\n" +
"}\n");
fullBuild(projectPath);
expectingNoProblems();
// remove @Nullable (second type annotation):
env.addClass(root, "testNullAnnotations", "NonNullUtils",
"package testNullAnnotations;\n" +
"\n" +
"import java.util.*;\n" +
"import org.eclipse.jdt.annotation.*;\n" +
"\n" +
"public final class NonNullUtils {\n" +
"\n" +
" public static <T> List<@NonNull T> checkNotNullContents(List<T> list, List<@NonNull T> nList) {\n" +
" return nList;\n" +
" }\n" +
"}\n");
incrementalBuild(projectPath); // was throwing NPE
expectingNoProblems();
// and add it again:
env.addClass(root, "testNullAnnotations", "NonNullUtils",
"package testNullAnnotations;\n" +
"\n" +
"import java.util.*;\n" +
"import org.eclipse.jdt.annotation.*;\n" +
"\n" +
"public final class NonNullUtils {\n" +
"\n" +
" public static <T> List<@NonNull T> checkNotNullContents(List<@Nullable T> list, List<@NonNull T> nList) {\n" +
" return nList;\n" +
" }\n" +
"}\n");
incrementalBuild(projectPath); // was throwing NPE
expectingNoProblems();
}
}