| /******************************************************************************* |
| * 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.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.buildMinimalComplianceTestSuite(IncrementalTests18.class, AbstractCompilerTest.F_1_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(); |
| } |
| } |