| /******************************************************************************* |
| * Copyright (c) 2000, 2016 IBM Corporation and others. |
| * All rights reserved. This program and the accompanying materials |
| * are made available under the terms of the Eclipse Public License v1.0 |
| * which accompanies this distribution, and is available at |
| * http://www.eclipse.org/legal/epl-v10.html |
| * |
| * This is an implementation of an early-draft specification developed under the Java |
| * Community Process (JCP) and is made available for testing and evaluation purposes |
| * only. The code is not compatible with any specification of the JCP. |
| * |
| * Contributors: |
| * IBM Corporation - initial API and implementation |
| *******************************************************************************/ |
| package org.eclipse.jdt.core.tests.builder; |
| |
| import java.io.File; |
| import java.io.IOException; |
| import java.io.PrintWriter; |
| import java.io.StringWriter; |
| import java.util.Arrays; |
| |
| import junit.framework.Test; |
| |
| import org.eclipse.core.resources.IFile; |
| import org.eclipse.core.resources.IMarker; |
| import org.eclipse.core.resources.IProject; |
| import org.eclipse.core.runtime.CoreException; |
| 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; |
| |
| @SuppressWarnings("rawtypes") |
| public class PackageInfoTest extends BuilderTests { |
| |
| public PackageInfoTest(String name) { |
| super(name); |
| } |
| // Static initializer to specify tests subset using TESTS_* static variables |
| // All specified tests which does not belong to the class are skipped... |
| static { |
| // TESTS_NAMES = new String[] { "testBug374063" }; |
| // TESTS_NUMBERS = new int[] { 3 }; |
| // TESTS_RANGE = new int[] { 21, 50 }; |
| } |
| public static Test suite() { |
| return buildTestSuite(PackageInfoTest.class); |
| } |
| public void test001() throws JavaModelException { |
| IPath projectPath = env.addProject("Project", "1.5"); //$NON-NLS-1$ |
| env.addExternalJars(projectPath, Util.getJavaClassLibs()); |
| fullBuild(projectPath); |
| |
| // remove old package fragment root so that names don't collide |
| env.removePackageFragmentRoot(projectPath, ""); //$NON-NLS-1$ |
| |
| IPath root = env.addPackageFragmentRoot(projectPath, "src"); //$NON-NLS-1$ |
| env.setOutputFolder(projectPath, "bin"); //$NON-NLS-1$ |
| |
| env.addClass(root, "pack", "Annot", //$NON-NLS-1$ //$NON-NLS-2$ |
| "package pack;\n" + //$NON-NLS-1$ |
| "public @interface Annot {}" //$NON-NLS-1$ |
| ); |
| |
| incrementalBuild(projectPath); |
| |
| IPath packageInfoPath = env.addFile(root, "pack/package-info.java", //$NON-NLS-1$ //$NON-NLS-2$ |
| "@Annot package p1" //$NON-NLS-1$ |
| ); |
| |
| incrementalBuild(projectPath); |
| expectingOnlyProblemsFor(packageInfoPath); |
| final Problem[] problems = env.getProblems(); |
| Arrays.sort(problems); |
| assertNotNull(problems); |
| final StringWriter stringWriter = new StringWriter(); |
| final PrintWriter writer = new PrintWriter(stringWriter); |
| final int problemsLength = problems.length; |
| if (problemsLength == 1) { |
| writer.print(problems[0].getMessage()); |
| } else { |
| for (int i = 0; i < problemsLength - 1; i++) |
| writer.println(problems[i].getMessage()); |
| writer.print(problems[problemsLength - 1].getMessage()); |
| } |
| writer.close(); |
| final String expectedOutput = |
| "Syntax error on token \"p1\", ; expected after this token\n" + |
| "The declared package \"p1\" does not match the expected package \"pack\""; |
| assertSourceEquals("Different messages", expectedOutput, stringWriter.toString()); |
| } |
| public void test002() throws JavaModelException { |
| IPath projectPath = env.addProject("Project", "1.5"); //$NON-NLS-1$ |
| env.addExternalJars(projectPath, Util.getJavaClassLibs()); |
| fullBuild(projectPath); |
| |
| // remove old package fragment root so that names don't collide |
| env.removePackageFragmentRoot(projectPath, ""); //$NON-NLS-1$ |
| |
| IPath root = env.addPackageFragmentRoot(projectPath, "src"); //$NON-NLS-1$ |
| env.setOutputFolder(projectPath, "bin"); //$NON-NLS-1$ |
| |
| env.addClass(root, "testcase", "Main", //$NON-NLS-1$ //$NON-NLS-2$ |
| "package testcase;\n" + |
| "\n" + |
| "public class Main {\n" + |
| " public static void main(String[] argv) throws Exception {\n" + |
| " Package pkg = Package.getPackage(\"testcase\");\n" + |
| " System.out.print(pkg.getAnnotation(TestAnnotation.class));\n" + |
| " pkg = Class.forName(\"testcase.package-info\").getPackage();\n" + |
| " System.out.print(pkg.getAnnotation(TestAnnotation.class));\n" + |
| " }\n" + |
| "}" |
| ); |
| |
| env.addClass(root, "testcase", "TestAnnotation", //$NON-NLS-1$ //$NON-NLS-2$ |
| "package testcase;\n" + |
| "\n" + |
| "import static java.lang.annotation.ElementType.PACKAGE;\n" + |
| "import static java.lang.annotation.RetentionPolicy.RUNTIME;\n" + |
| "\n" + |
| "import java.lang.annotation.Retention;\n" + |
| "import java.lang.annotation.Target;\n" + |
| "\n" + |
| "@Target(PACKAGE)\n" + |
| "@Retention(RUNTIME)\n" + |
| "public @interface TestAnnotation {\n" + |
| "}" |
| ); |
| |
| env.addFile(root, "testcase/package-info.java", //$NON-NLS-1$ //$NON-NLS-2$ |
| "@TestAnnotation package testcase;" //$NON-NLS-1$ |
| ); |
| incrementalBuild(projectPath); |
| String javaVersion = System.getProperty("java.version"); |
| if (javaVersion != null && javaVersion.startsWith("9")) { |
| expectingProblemsFor(new Path("/Project/src/testcase/Main.java"), |
| "Problem : The method getPackage(String) from the type Package is deprecated [ resource : </Project/src/testcase/Main.java> range : <125,147> category : <110> severity : <1>]"); |
| } else { |
| expectingNoProblems(); |
| } |
| executeClass(projectPath, "testcase.Main", "@testcase.TestAnnotation()@testcase.TestAnnotation()", ""); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ |
| } |
| public void test003() throws JavaModelException { |
| IPath projectPath = env.addProject("Project", "1.5"); //$NON-NLS-1$ |
| env.addExternalJars(projectPath, Util.getJavaClassLibs()); |
| fullBuild(projectPath); |
| |
| // remove old package fragment root so that names don't collide |
| env.removePackageFragmentRoot(projectPath, ""); //$NON-NLS-1$ |
| |
| IPath root = env.addPackageFragmentRoot(projectPath, "src"); //$NON-NLS-1$ |
| env.setOutputFolder(projectPath, "bin"); //$NON-NLS-1$ |
| |
| env.addPackage(root, "testcase"); |
| IPath packageInfoPath = env.addFile(root, "testcase/package-info.java", //$NON-NLS-1$ //$NON-NLS-2$ |
| "" //$NON-NLS-1$ |
| ); |
| |
| incrementalBuild(projectPath); |
| expectingOnlySpecificProblemFor( |
| packageInfoPath, |
| new Problem("testcase/package-info.java", "The declared package \"\" does not match the expected package \"testcase\"", packageInfoPath, 0, 0, CategorizedProblem.CAT_INTERNAL, IMarker.SEVERITY_ERROR)); //$NON-NLS-1$ //$NON-NLS-2$ |
| } |
| // test for bug https://bugs.eclipse.org/bugs/show_bug.cgi?id=252555 : NPE |
| // on duplicate package-info |
| public void test004() throws JavaModelException { |
| IPath projectPath = env.addProject("Project", "1.5"); //$NON-NLS-1$ |
| env.addExternalJars(projectPath, Util.getJavaClassLibs()); |
| fullBuild(projectPath); |
| |
| // remove old package fragment root so that names don't collide |
| env.removePackageFragmentRoot(projectPath, ""); //$NON-NLS-1$ |
| |
| IPath root = env.addPackageFragmentRoot(projectPath, "src"); //$NON-NLS-1$ |
| env.setOutputFolder(projectPath, "bin"); //$NON-NLS-1$ |
| |
| IPath otherRoot = env.addPackageFragmentRoot(projectPath, "test"); //$NON-NLS-1$ |
| env.setOutputFolder(projectPath, "bin"); //$NON-NLS-1$ |
| |
| env.addPackage(root, "my.foo"); |
| env.addPackage(otherRoot, "my.foo"); |
| |
| env.addFile(root, "my/foo/package-info.java", //$NON-NLS-1$ //$NON-NLS-2$ |
| "/**\n" + |
| "* A demo package for foo.\n" + |
| "*/\n" + |
| "package my.foo;\n" |
| ); |
| |
| IPath otherPackageInfoPath = env.addFile(otherRoot, |
| "my/foo/package-info.java", //$NON-NLS-1$ //$NON-NLS-2$ |
| "/**\n" + |
| "* A demo package for foo.\n" + |
| "*/\n" + |
| "package my.foo;\n" |
| ); |
| |
| incrementalBuild(projectPath); |
| expectingOnlySpecificProblemFor( |
| otherPackageInfoPath, |
| new Problem("my/foo/package-info.java", "The type package-info is already defined", otherPackageInfoPath, 0, 0, CategorizedProblem.CAT_TYPE, IMarker.SEVERITY_ERROR)); //$NON-NLS-1$ //$NON-NLS-2$ |
| } |
| // test for bug https://bugs.eclipse.org/bugs/show_bug.cgi?id=258145 : JME |
| // on duplicate package-info |
| public void test258145() throws JavaModelException { |
| IPath projectPath = env.addProject("Project", "1.5"); //$NON-NLS-1$ |
| env.addExternalJars(projectPath, Util.getJavaClassLibs()); |
| fullBuild(projectPath); |
| |
| // remove old package fragment root so that names don't collide |
| env.removePackageFragmentRoot(projectPath, ""); //$NON-NLS-1$ |
| |
| IPath root = env.addPackageFragmentRoot(projectPath, "src"); //$NON-NLS-1$ |
| env.setOutputFolder(projectPath, "bin"); //$NON-NLS-1$ |
| |
| IPath otherRoot = env.addPackageFragmentRoot(projectPath, "test"); //$NON-NLS-1$ |
| env.setOutputFolder(projectPath, "bin"); //$NON-NLS-1$ |
| |
| env.addPackage(root, "my.foo"); |
| env.addFile(root, "my/foo/package-info.java", //$NON-NLS-1$ //$NON-NLS-2$ |
| "/**\n" + |
| "* A demo package for foo.\n" + |
| "*/\n" + |
| "package my.foo;\n" |
| ); |
| |
| fullBuild(projectPath); |
| |
| env.addPackage(otherRoot, "my.foo"); |
| |
| IPath otherPackageInfoPath = env.addFile(otherRoot, |
| "my/foo/package-info.java", //$NON-NLS-1$ //$NON-NLS-2$ |
| "/**\n" + |
| "* A demo package for foo.\n" + |
| "*/\n" + |
| "package my.foo;\n" |
| ); |
| |
| incrementalBuild(projectPath); |
| expectingOnlySpecificProblemFor( |
| otherPackageInfoPath, |
| new Problem("my/foo/package-info.java", "The type package-info is already defined", otherPackageInfoPath, 0, 0, CategorizedProblem.CAT_TYPE, IMarker.SEVERITY_ERROR)); //$NON-NLS-1$ //$NON-NLS-2$ |
| } |
| // https://bugs.eclipse.org/bugs/show_bug.cgi?id=323785 |
| // (NPE upon creation/deletion of package-info.java in default package) |
| public void test323785 () throws JavaModelException { |
| |
| IPath projectPath = env.addProject("Project", "1.5"); |
| env.addExternalJars(projectPath, Util.getJavaClassLibs()); |
| fullBuild(projectPath); |
| |
| // remove old package fragment root so that names don't collide |
| env.removePackageFragmentRoot(projectPath, ""); |
| |
| IPath root = env.addPackageFragmentRoot(projectPath, "src"); |
| env.setOutputFolder(projectPath, "bin"); |
| |
| fullBuild(projectPath); |
| |
| env.addFile(root, "package-info.java", ""); |
| |
| incrementalBuild(projectPath); |
| expectingNoProblems(); |
| |
| } |
| // https://bugs.eclipse.org/bugs/show_bug.cgi?id=323785 |
| // verify that changes to package info containing secondary types do trigger incremental build. |
| public void test323785a () throws JavaModelException { |
| |
| IPath projectPath = env.addProject("Project", "1.5"); |
| env.addExternalJars(projectPath, Util.getJavaClassLibs()); |
| fullBuild(projectPath); |
| |
| // remove old package fragment root so that names don't collide |
| env.removePackageFragmentRoot(projectPath, ""); |
| |
| IPath root = env.addPackageFragmentRoot(projectPath, "src"); |
| env.setOutputFolder(projectPath, "bin"); |
| |
| IPath xJavaPath = env.addFile(root, "X.java", "class X extends Y {}\n"); |
| fullBuild(projectPath); |
| env.addFile(root, "package-info.java", "class Y {}\n"); |
| incrementalBuild(projectPath); |
| expectingNoProblems(); |
| env.addFile(root, "package-info.java", "final class Y {}\n"); |
| incrementalBuild(projectPath); |
| expectingOnlySpecificProblemFor( |
| xJavaPath, |
| new Problem("X.java", "The type X cannot subclass the final class Y", xJavaPath, 16, 17, CategorizedProblem.CAT_TYPE, IMarker.SEVERITY_ERROR)); |
| |
| } |
| |
| // https://bugs.eclipse.org/bugs/show_bug.cgi?id=372012 |
| // test missing default nullness annotation for a package without package-info |
| // test when the package-info is added with the default annotation, the problem disappears |
| public void testBug372012() throws JavaModelException, IOException { |
| |
| IPath projectPath = env.addProject("Project", "1.5"); |
| env.addExternalJars(projectPath, Util.getJavaClassLibs()); |
| fullBuild(projectPath); |
| |
| // remove old package fragment root so that names don't collide |
| env.removePackageFragmentRoot(projectPath, ""); |
| |
| IPath srcRoot = env.addPackageFragmentRoot(projectPath, "src"); |
| env.setOutputFolder(projectPath, "bin"); |
| // prepare the project: |
| setupProjectForNullAnnotations(projectPath); |
| env.getJavaProject(projectPath).setOption(JavaCore.COMPILER_PB_MISSING_NONNULL_BY_DEFAULT_ANNOTATION, JavaCore.ERROR); |
| env.getJavaProject(projectPath).setOption(JavaCore.COMPILER_PB_REDUNDANT_NULL_ANNOTATION, JavaCore.ERROR); |
| String test1Code = "package p1;\n" + |
| "public class Test1 {\n" + |
| " public void foo() {\n" + |
| " new Test2().bar(\"\");\n" + |
| " }\n" + |
| " class Test1Inner{}\n" + |
| "}"; |
| String test2Code = "package p1;\n" + |
| "@org.eclipse.jdt.annotation.NonNullByDefault\n" + |
| "public class Test2 {\n" + |
| " public void bar(String str) {}\n" + |
| "}"; |
| String test3Code = "package p1;\n" + |
| "public class Test3 {\n" + |
| " public void bar(String str) {}\n" + |
| "}"; |
| |
| IPath test1Path = env.addClass(srcRoot, "p1", "Test1", test1Code); |
| env.addClass(srcRoot, "p1", "Test2", test2Code); |
| env.addClass(srcRoot, "p1", "Test3", test3Code); |
| |
| fullBuild(projectPath); |
| expectingNoProblemsFor(test1Path); |
| // should have only one marker |
| expectingProblemsFor(srcRoot, |
| "Problem : A default nullness annotation has not been specified for the package p1 [ resource : </Project/src/p1> range : <8,10> category : <90> severity : <2>]"); |
| |
| // add package-info.java with default annotation |
| String packageInfoCode = "@org.eclipse.jdt.annotation.NonNullByDefault\n" + |
| "package p1;\n"; |
| env.addClass(srcRoot, "p1", "package-info", packageInfoCode); |
| incrementalBuild(projectPath); |
| expectingProblemsFor(projectPath, |
| "Problem : Nullness default is redundant with a default specified for the enclosing package p1 [ resource : </Project/src/p1/Test2.java> range : <12,56> category : <120> severity : <2>]"); |
| |
| // verify that all package CU's were recompiled |
| expectingUniqueCompiledClasses(new String[] { "p1.Test1", "p1.Test1$Test1Inner", "p1.Test2", "p1.Test3", "p1.package-info" }); |
| } |
| |
| // https://bugs.eclipse.org/bugs/show_bug.cgi?id=372012 |
| // test missing default nullness annotation for a package without package-info |
| // test when the the default annotations are added to all top level types, the problem stays |
| public void testBug372012a() throws JavaModelException, IOException { |
| |
| IPath projectPath = env.addProject("Project", "1.5"); |
| env.addExternalJars(projectPath, Util.getJavaClassLibs()); |
| fullBuild(projectPath); |
| |
| // remove old package fragment root so that names don't collide |
| env.removePackageFragmentRoot(projectPath, ""); |
| |
| IPath srcRoot = env.addPackageFragmentRoot(projectPath, "src"); |
| env.setOutputFolder(projectPath, "bin"); |
| // prepare the project: |
| setupProjectForNullAnnotations(projectPath); |
| env.getJavaProject(projectPath).setOption(JavaCore.COMPILER_PB_MISSING_NONNULL_BY_DEFAULT_ANNOTATION, JavaCore.ERROR); |
| env.getJavaProject(projectPath).setOption(JavaCore.COMPILER_PB_REDUNDANT_NULL_ANNOTATION, JavaCore.ERROR); |
| String test1Code = "package p1;\n" + |
| "public class Test1 {\n" + |
| " public void foo() {\n" + |
| " new Test2().bar(\"\");\n" + |
| " }\n" + |
| " class Test1Inner{}\n" + |
| "}"; |
| String test2Code = "package p1;\n" + |
| "@org.eclipse.jdt.annotation.NonNullByDefault\n" + |
| "public class Test2 {\n" + |
| " public void bar(String str) {}\n" + |
| "}"; |
| |
| IPath test1Path = env.addClass(srcRoot, "p1", "Test1", test1Code); |
| env.addClass(srcRoot, "p1", "Test2", test2Code); |
| |
| fullBuild(projectPath); |
| expectingNoProblemsFor(test1Path); |
| // should have only one marker |
| expectingProblemsFor(srcRoot, |
| "Problem : A default nullness annotation has not been specified for the package p1 [ resource : </Project/src/p1> range : <8,10> category : <90> severity : <2>]"); |
| |
| // add default annotation to Test1 |
| test1Code = "package p1;\n" + |
| "@org.eclipse.jdt.annotation.NonNullByDefault\n" + |
| "public class Test1 {\n" + |
| " public void foo() {\n" + |
| " new Test2().bar(\"\");\n" + |
| " }\n" + |
| " class Test1Inner{}\n" + |
| "}"; |
| env.addClass(srcRoot, "p1", "Test1", test1Code); |
| incrementalBuild(projectPath); |
| // should have only one marker |
| expectingProblemsFor(srcRoot, |
| "Problem : A default nullness annotation has not been specified for the package p1 [ resource : </Project/src/p1> range : <8,10> category : <90> severity : <2>]"); |
| |
| // verify that all package CU's were recompiled |
| expectingUniqueCompiledClasses(new String[] { "p1.Test1", "p1.Test1$Test1Inner"}); |
| } |
| |
| // https://bugs.eclipse.org/bugs/show_bug.cgi?id=372012 |
| // test missing default nullness annotation for a package without package-info |
| // test when the the default annotations is added to only 1 top level type, the problem stays |
| public void testBug372012b() throws JavaModelException, IOException { |
| |
| IPath projectPath = env.addProject("Project", "1.5"); |
| env.addExternalJars(projectPath, Util.getJavaClassLibs()); |
| fullBuild(projectPath); |
| |
| // remove old package fragment root so that names don't collide |
| env.removePackageFragmentRoot(projectPath, ""); |
| |
| IPath srcRoot = env.addPackageFragmentRoot(projectPath, "src"); |
| env.setOutputFolder(projectPath, "bin"); |
| // prepare the project: |
| setupProjectForNullAnnotations(projectPath); |
| env.getJavaProject(projectPath).setOption(JavaCore.COMPILER_PB_MISSING_NONNULL_BY_DEFAULT_ANNOTATION, JavaCore.ERROR); |
| env.getJavaProject(projectPath).setOption(JavaCore.COMPILER_PB_REDUNDANT_NULL_ANNOTATION, JavaCore.ERROR); |
| String test1Code = "package p1;\n" + |
| "public class Test1 {\n" + |
| " public void foo() {\n" + |
| " new Test2().bar(\"\");\n" + |
| " }\n" + |
| " class Test1Inner{}\n" + |
| "}"; |
| String test2Code = "package p1;\n" + |
| "public class Test2 {\n" + |
| " public void bar(String str) {}\n" + |
| "}"; |
| |
| IPath test1Path = env.addClass(srcRoot, "p1", "Test1", test1Code); |
| env.addClass(srcRoot, "p1", "Test2", test2Code); |
| |
| fullBuild(projectPath); |
| expectingNoProblemsFor(test1Path); |
| // should have only one marker |
| expectingProblemsFor(srcRoot, |
| "Problem : A default nullness annotation has not been specified for the package p1 [ resource : </Project/src/p1> range : <8,10> category : <90> severity : <2>]"); |
| |
| // add default annotation to Test1 |
| test1Code = "package p1;\n" + |
| "@org.eclipse.jdt.annotation.NonNullByDefault\n" + |
| "public class Test1 {\n" + |
| " public void foo() {\n" + |
| " new Test2().bar(\"\");\n" + |
| " }\n" + |
| " class Test1Inner{}\n" + |
| "}"; |
| env.addClass(srcRoot, "p1", "Test1", test1Code); |
| incrementalBuild(projectPath); |
| // should have only one marker |
| expectingProblemsFor(srcRoot, |
| "Problem : A default nullness annotation has not been specified for the package p1 [ resource : </Project/src/p1> range : <8,10> category : <90> severity : <2>]"); |
| |
| // verify that only Test1's CU's were recompiled |
| expectingUniqueCompiledClasses(new String[] { "p1.Test1", "p1.Test1$Test1Inner"}); |
| } |
| |
| // https://bugs.eclipse.org/bugs/show_bug.cgi?id=372012 |
| // test missing default nullness annotation for a package with package-info |
| // test when the the default annotation is removed from package-info, the problem comes back |
| public void testBug372012c() throws JavaModelException, IOException { |
| |
| IPath projectPath = env.addProject("Project", "1.5"); |
| env.addExternalJars(projectPath, Util.getJavaClassLibs()); |
| fullBuild(projectPath); |
| |
| // remove old package fragment root so that names don't collide |
| env.removePackageFragmentRoot(projectPath, ""); |
| |
| IPath srcRoot = env.addPackageFragmentRoot(projectPath, "src"); |
| env.setOutputFolder(projectPath, "bin"); |
| // prepare the project: |
| setupProjectForNullAnnotations(projectPath); |
| env.getJavaProject(projectPath).setOption(JavaCore.COMPILER_PB_MISSING_NONNULL_BY_DEFAULT_ANNOTATION, JavaCore.ERROR); |
| env.getJavaProject(projectPath).setOption(JavaCore.COMPILER_PB_REDUNDANT_NULL_ANNOTATION, JavaCore.ERROR); |
| String test1Code = "package p1;\n" + |
| "public class Test1 {\n" + |
| " public void foo() {\n" + |
| " new Test2().bar(\"\");\n" + |
| " }\n" + |
| " class Test1Inner{}\n" + |
| "}"; |
| String test2Code = "package p1;\n" + |
| "public class Test2 {\n" + |
| " public void bar(String str) {}\n" + |
| "}"; |
| // add package-info.java with default annotation |
| String packageInfoCode = "@org.eclipse.jdt.annotation.NonNullByDefault\n" + |
| "package p1;\n"; |
| env.addClass(srcRoot, "p1", "package-info", packageInfoCode); |
| |
| env.addClass(srcRoot, "p1", "Test1", test1Code); |
| env.addClass(srcRoot, "p1", "Test2", test2Code); |
| env.addClass(srcRoot, "p1", "package-info", packageInfoCode); |
| |
| fullBuild(projectPath); |
| // default annotation present, so no problem |
| expectingNoProblemsFor(srcRoot); |
| |
| // add package-info.java with default annotation |
| packageInfoCode = |
| "package p1;\n"; |
| env.addClass(srcRoot, "p1", "package-info", packageInfoCode); |
| incrementalBuild(projectPath); |
| expectingProblemsFor(projectPath, |
| "Problem : A default nullness annotation has not been specified for the package p1 [ resource : </Project/src/p1/package-info.java> range : <8,10> category : <90> severity : <2>]"); |
| |
| // verify that all package CU's were recompiled |
| expectingUniqueCompiledClasses(new String[] { "p1.Test1", "p1.Test1$Test1Inner", "p1.Test2", "p1.package-info" }); |
| } |
| |
| /** |
| * https://bugs.eclipse.org/bugs/show_bug.cgi?id=367836 |
| */ |
| public void testBug367836() throws JavaModelException { |
| IPath projectPath = env.addProject("Project"); //$NON-NLS-1$ |
| env.addExternalJars(projectPath, Util.getJavaClassLibs()); |
| env.removePackageFragmentRoot(projectPath, ""); //$NON-NLS-1$ |
| IPath src = env.addPackageFragmentRoot(projectPath, "src"); //$NON-NLS-1$ |
| env.setOutputFolder(projectPath, "bin"); //$NON-NLS-1$ |
| |
| env.addClass(src, "p", "A", //$NON-NLS-1$ //$NON-NLS-2$ |
| "package p;\n"+ //$NON-NLS-1$ |
| "public class A {}" //$NON-NLS-1$ |
| ); |
| |
| IPath bPath = env.addClass(src, "p", "package-info", //$NON-NLS-1$ //$NON-NLS-2$ |
| "" //$NON-NLS-1$ |
| ); |
| |
| fullBuild(); |
| expectingOnlySpecificProblemFor(bPath, |
| new Problem("", "The declared package \"\" does not match the expected package \"p\"", bPath, 0, 0, CategorizedProblem.CAT_INTERNAL, IMarker.SEVERITY_ERROR)); //$NON-NLS-1$ //$NON-NLS-2$ |
| } |
| // https://bugs.eclipse.org/bugs/show_bug.cgi?id=374063 |
| // verify that markers are created on the correct resource |
| public void testBug374063() throws JavaModelException, IOException { |
| |
| IPath projectPath = env.addProject("Project", "1.5"); |
| env.addExternalJars(projectPath, Util.getJavaClassLibs()); |
| fullBuild(projectPath); |
| |
| // remove old package fragment root so that names don't collide |
| env.removePackageFragmentRoot(projectPath, ""); |
| |
| IPath srcRoot = env.addPackageFragmentRoot(projectPath, "src"); |
| env.setOutputFolder(projectPath, "bin"); |
| // prepare the project: |
| setupProjectForNullAnnotations(projectPath); |
| env.getJavaProject(projectPath).setOption(JavaCore.COMPILER_PB_MISSING_NONNULL_BY_DEFAULT_ANNOTATION, JavaCore.ERROR); |
| env.getJavaProject(projectPath).setOption(JavaCore.COMPILER_PB_REDUNDANT_NULL_ANNOTATION, JavaCore.ERROR); |
| String test1Code = "package p1;\n" + |
| "public class Test1 {\n" + |
| " public String output(List<Integer> integers) {\n" + |
| " return \"\";\n" + |
| " }\n" + |
| " public void output(List<Double> doubles) {}\n" + |
| "}"; |
| |
| env.addClass(srcRoot, "p1", "Test1", test1Code); |
| |
| fullBuild(projectPath); |
| // resource for compile errors should be Test1 and not p1 |
| expectingProblemsFor(projectPath, |
| "Problem : A default nullness annotation has not been specified for the package p1 [ resource : </Project/src/p1> range : <8,10> category : <90> severity : <2>]\n" + |
| "Problem : List cannot be resolved to a type [ resource : </Project/src/p1/Test1.java> range : <130,134> category : <40> severity : <2>]\n" + |
| "Problem : List cannot be resolved to a type [ resource : </Project/src/p1/Test1.java> range : <58,62> category : <40> severity : <2>]"); |
| |
| // add package-info.java with default annotation |
| String packageInfoCode = "@org.eclipse.jdt.annotation.NonNullByDefault\n" + |
| "package p1;\n"; |
| env.addClass(srcRoot, "p1", "package-info", packageInfoCode); |
| incrementalBuild(projectPath); |
| expectingProblemsFor(projectPath, |
| "Problem : List cannot be resolved to a type [ resource : </Project/src/p1/Test1.java> range : <130,134> category : <40> severity : <2>]\n" + |
| "Problem : List cannot be resolved to a type [ resource : </Project/src/p1/Test1.java> range : <58,62> category : <40> severity : <2>]"); |
| |
| // verify that all package CU's were recompiled |
| expectingUniqueCompiledClasses(new String[] { "p1.Test1", "p1.package-info" }); |
| } |
| // 382960 |
| public void testBug382960() throws JavaModelException, IOException, CoreException { |
| IPath projectPath = env.addProject("Project", "1.5"); |
| env.addExternalJars(projectPath, Util.getJavaClassLibs()); |
| fullBuild(projectPath); |
| |
| env.removePackageFragmentRoot(projectPath, ""); |
| IPath srcRoot = env.addPackageFragmentRoot(projectPath, "src"); |
| env.setOutputFolder(projectPath, "bin"); |
| // prepare the project: |
| setupProjectForNullAnnotations(projectPath); |
| env.getJavaProject(projectPath).setOption(JavaCore.COMPILER_PB_MISSING_NONNULL_BY_DEFAULT_ANNOTATION, JavaCore.ERROR); |
| String test1Code = "package p1;\n" + |
| "public class Test1 {\n" + |
| " public String output(List<Integer> integers) {\n" + |
| " return \"\";\n" + |
| " }\n" + |
| " public void output(List<Double> doubles) {}\n" + |
| "}"; |
| |
| env.addClass(srcRoot, "p1", "Test1", test1Code); |
| String packageInfoCode = "package p1;\n"; |
| env.addClass(srcRoot, "p1", "package-info", packageInfoCode); |
| fullBuild(projectPath); |
| expectingProblemsFor(projectPath, |
| "Problem : A default nullness annotation has not been specified for the package p1 [ resource : </Project/src/p1/package-info.java> range : <8,10> category : <90> severity : <2>]\n" + |
| "Problem : List cannot be resolved to a type [ resource : </Project/src/p1/Test1.java> range : <130,134> category : <40> severity : <2>]\n" + |
| "Problem : List cannot be resolved to a type [ resource : </Project/src/p1/Test1.java> range : <58,62> category : <40> severity : <2>]"); |
| |
| packageInfoCode = "@org.eclipse.jdt.annotation.NonNullByDefault\n" + |
| "package p1;\n"; |
| env.addClass(srcRoot, "p1", "package-info", packageInfoCode); |
| incrementalBuild(projectPath); |
| expectingProblemsFor(projectPath, |
| "Problem : List cannot be resolved to a type [ resource : </Project/src/p1/Test1.java> range : <130,134> category : <40> severity : <2>]\n" + |
| "Problem : List cannot be resolved to a type [ resource : </Project/src/p1/Test1.java> range : <58,62> category : <40> severity : <2>]"); |
| expectingUniqueCompiledClasses(new String[] { "p1.Test1", "p1.package-info" }); |
| |
| IProject project = env.getProject(projectPath); |
| IFile packageInfo = project.getFile("/src/p1/package-info.java"); |
| packageInfo.touch(null); |
| |
| incrementalBuild(projectPath); |
| expectingProblemsFor(projectPath, |
| "Problem : List cannot be resolved to a type [ resource : </Project/src/p1/Test1.java> range : <130,134> category : <40> severity : <2>]\n" + |
| "Problem : List cannot be resolved to a type [ resource : </Project/src/p1/Test1.java> range : <58,62> category : <40> severity : <2>]"); |
| |
| // verify that only package-info was recompiled |
| expectingUniqueCompiledClasses(new String[] { "p1.package-info" }); |
| } |
| |
| void setupProjectForNullAnnotations(IPath projectPath) throws IOException, JavaModelException { |
| // add the org.eclipse.jdt.annotation library (bin/ folder or jar) to the project: |
| File bundleFile = FileLocator.getBundleFile(Platform.getBundle("org.eclipse.jdt.annotation")); |
| String annotationsLib = bundleFile.isDirectory() ? bundleFile.getPath()+"/bin" : bundleFile.getPath(); |
| IJavaProject javaProject = env.getJavaProject(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); |
| } |
| |
| protected void assertSourceEquals(String message, String expected, String actual) { |
| if (actual == null) { |
| assertEquals(message, expected, null); |
| return; |
| } |
| actual = org.eclipse.jdt.core.tests.util.Util.convertToIndependantLineDelimiter(actual); |
| if (!actual.equals(expected)) { |
| System.out.print(org.eclipse.jdt.core.tests.util.Util.displayString(actual.toString(), 0)); |
| } |
| assertEquals(message, expected, actual); |
| } |
| public static Class testClass() { |
| return PackageInfoTest.class; |
| } |
| } |