diff options
author | Sasikanth Bharadwaj | 2018-02-08 11:27:50 +0000 |
---|---|---|
committer | Sasikanth Bharadwaj | 2018-02-08 11:47:26 +0000 |
commit | 08ef05d15d2dde1c1f715dc44bb0e9d2464636c4 (patch) | |
tree | 893d7bb91a48b87c3455b75290521376d313fbe5 | |
parent | b8996fefb00a5675c331e99e16920397a404b111 (diff) | |
parent | bf3881160a8c2cad0003a22cceb7074496967f3b (diff) | |
download | eclipse.jdt.core-08ef05d15d2dde1c1f715dc44bb0e9d2464636c4.tar.gz eclipse.jdt.core-08ef05d15d2dde1c1f715dc44bb0e9d2464636c4.tar.xz eclipse.jdt.core-08ef05d15d2dde1c1f715dc44bb0e9d2464636c4.zip |
Merge remote-tracking branch 'origin/R4_7_maintenance' into
BETA_JAVA_18_3
Conflicts:
org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/CompilerInvocationTests.java
Change-Id: I467262b246fc275a6a667156278b07a7a6f99e86
55 files changed, 2151 insertions, 259 deletions
diff --git a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/AbstractRegressionTest.java b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/AbstractRegressionTest.java index 9f7908765e..3d1fa6c333 100644 --- a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/AbstractRegressionTest.java +++ b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/AbstractRegressionTest.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2017 IBM Corporation and others. + * Copyright (c) 2000, 2018 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 @@ -96,6 +96,111 @@ import org.osgi.framework.Bundle; @SuppressWarnings({ "unchecked", "rawtypes" }) public abstract class AbstractRegressionTest extends AbstractCompilerTest implements StopableTestCase { + static final String[] env = System.getenv().entrySet().stream() + .filter(e -> !"JAVA_TOOL_OPTIONS".equals(e.getKey())) + .map(e -> e.getKey() + "=" + e.getValue()) + .toArray(String[]::new); + + protected class Runner { + boolean shouldFlushOutputDirectory = true; + // input: + String[] testFiles; + String[] dependantFiles; + String[] classLibraries; + // control compilation: + Map<String,String> customOptions; + boolean performStatementsRecovery; + boolean generateOutput; + ICompilerRequestor customRequestor; + // compiler result: + String expectedCompilerLog; + String[] alternateCompilerLogs; + boolean showCategory; + boolean showWarningToken; + // javac: + boolean skipJavac; + JavacTestOptions javacTestOptions; + // execution: + boolean forceExecution; + String[] vmArguments; + String expectedOutputString; + String expectedErrorString; + + ASTVisitor visitor; + + @SuppressWarnings("synthetic-access") + protected void runConformTest() { + runTest(this.shouldFlushOutputDirectory, + this.testFiles, + this.dependantFiles != null ? this.dependantFiles : new String[] {}, + this.classLibraries, + this.customOptions, + this.performStatementsRecovery, + new Requestor( + this.generateOutput, + this.customRequestor, + this.showCategory, + this.showWarningToken), + false, + this.expectedCompilerLog, + this.alternateCompilerLogs, + this.forceExecution, + this.vmArguments, + this.expectedOutputString, + this.expectedErrorString, + this.visitor, + this.skipJavac ? JavacTestOptions.SKIP : this.javacTestOptions); + } + + @SuppressWarnings("synthetic-access") + protected void runNegativeTest() { + runTest(this.shouldFlushOutputDirectory, + this.testFiles, + this.dependantFiles != null ? this.dependantFiles : new String[] {}, + this.classLibraries, + this.customOptions, + this.performStatementsRecovery, + new Requestor( + this.generateOutput, + this.customRequestor, + this.showCategory, + this.showWarningToken), + true, + this.expectedCompilerLog, + this.alternateCompilerLogs, + this.forceExecution, + this.vmArguments, + this.expectedOutputString, + this.expectedErrorString, + this.visitor, + this.skipJavac ? JavacTestOptions.SKIP : this.javacTestOptions); + } + + @SuppressWarnings("synthetic-access") + protected void runWarningTest() { + runTest(this.shouldFlushOutputDirectory, + this.testFiles, + this.dependantFiles != null ? this.dependantFiles : new String[] {}, + this.classLibraries, + this.customOptions, + this.performStatementsRecovery, + new Requestor( + this.generateOutput, + this.customRequestor, + this.showCategory, + this.showWarningToken), + false, + this.expectedCompilerLog, + this.alternateCompilerLogs, + this.forceExecution, + this.vmArguments, + this.expectedOutputString, + this.expectedErrorString, + this.visitor, + this.skipJavac ? JavacTestOptions.SKIP : this.javacTestOptions); + } + } + // javac comparison related types, fields and methods - see runJavac for // details static class JavacCompiler { @@ -146,7 +251,7 @@ static class JavacCompiler { static String getVersion(String javacPathName) throws IOException, InterruptedException { Process fetchVersionProcess = null; try { - fetchVersionProcess = Runtime.getRuntime().exec(javacPathName + " -version", null, null); + fetchVersionProcess = Runtime.getRuntime().exec(javacPathName + " -version", env, null); Logger versionStdErrLogger = new Logger(fetchVersionProcess.getErrorStream(), ""); // for javac <= 1.8 Logger versionStdOutLogger = new Logger(fetchVersionProcess.getInputStream(), ""); // for javac >= 9 versionStdErrLogger.start(); @@ -254,7 +359,7 @@ static class JavacCompiler { } else { cmdLineAsString = cmdLine.toString(); } - compileProcess = Runtime.getRuntime().exec(cmdLineAsString, null, directory); + compileProcess = Runtime.getRuntime().exec(cmdLineAsString, env, directory); Logger errorLogger = new Logger(compileProcess.getErrorStream(), "ERROR", log == null ? new StringBuffer() : log); errorLogger.start(); @@ -306,7 +411,7 @@ static class JavaRuntime { cmdLine.append(options); cmdLine.append(' '); cmdLine.append(className); - executionProcess = Runtime.getRuntime().exec(cmdLine.toString(), null, directory); + executionProcess = Runtime.getRuntime().exec(cmdLine.toString(), env, directory); Logger outputLogger = new Logger(executionProcess.getInputStream(), "RUNTIME OUTPUT", stdout == null ? new StringBuffer() : stdout); outputLogger.start(); @@ -1648,7 +1753,7 @@ protected static class JavacTestOptions { // Launch process compileProcess = Runtime.getRuntime().exec( - cmdLine.toString(), null, this.outputTestDirectory); + cmdLine.toString(), env, this.outputTestDirectory); // Log errors Logger errorLogger = new Logger(compileProcess.getErrorStream(), "ERROR"); @@ -1713,7 +1818,7 @@ protected static class JavacTestOptions { javaCmdLine.append(cp); javaCmdLine.append(' ').append(testFiles[0].substring(0, testFiles[0].indexOf('.'))); // assume executable class is name of first test file - PREMATURE check if this is also the case in other test fwk classes - execProcess = Runtime.getRuntime().exec(javaCmdLine.toString(), null, this.outputTestDirectory); + execProcess = Runtime.getRuntime().exec(javaCmdLine.toString(), env, this.outputTestDirectory); Logger logger = new Logger(execProcess.getInputStream(), ""); // PREMATURE implement consistent error policy logger.start(); @@ -1802,7 +1907,7 @@ protected static class JavacTestOptions { // Launch process File currentDirectory = new File(currentDirectoryPath); compileProcess = Runtime.getRuntime().exec( - cmdLine.toString(), null, currentDirectory); + cmdLine.toString(), env, currentDirectory); // Log errors Logger errorLogger = new Logger(compileProcess.getErrorStream(), "ERROR"); @@ -3277,6 +3382,10 @@ protected void runNegativeTest( if (outputDir.exists()) { Util.flushDirectoryContent(outputDir); } + File libDir = new File(LIB_DIR); + if (libDir.exists()) { + Util.flushDirectoryContent(libDir); + } super.tearDown(); if (RUN_JAVAC) { if (JAVAC_OUTPUT_DIR.exists()) { diff --git a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/AutomaticModuleNamingTest.java b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/AutomaticModuleNamingTest.java index 4f7bf13b4d..4693025d97 100644 --- a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/AutomaticModuleNamingTest.java +++ b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/AutomaticModuleNamingTest.java @@ -114,4 +114,9 @@ public class AutomaticModuleNamingTest extends AbstractRegressionTest { new String(determineAutomaticModuleNameFromFileName("CLASSES12.ZIP", true, true))); } + public void testBug529680() throws Exception { + assertEquals("hibernate.jpa", new String( + determineAutomaticModuleNameFromFileName("hibernate-jpa-2.1-api-1.0.0.Final.jar", true, true))); + } + } diff --git a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/CompilerInvocationTests.java b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/CompilerInvocationTests.java index 9b7480babe..ae3e920e33 100644 --- a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/CompilerInvocationTests.java +++ b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/CompilerInvocationTests.java @@ -914,7 +914,9 @@ public void test011_problem_categories() { expectedProblemAttributes.put("OuterLocalMustBeEffectivelyFinal", new ProblemAttributes(CategorizedProblem.CAT_INTERNAL)); expectedProblemAttributes.put("OuterLocalMustBeFinal", new ProblemAttributes(CategorizedProblem.CAT_INTERNAL)); expectedProblemAttributes.put("OverridingDeprecatedMethod", new ProblemAttributes(CategorizedProblem.CAT_DEPRECATION)); + expectedProblemAttributes.put("OverridingDeprecatedSinceVersionMethod", new ProblemAttributes(CategorizedProblem.CAT_DEPRECATION)); expectedProblemAttributes.put("OverridingTerminallyDeprecatedMethod", new ProblemAttributes(CategorizedProblem.CAT_DEPRECATION)); + expectedProblemAttributes.put("OverridingTerminallyDeprecatedSinceVersionMethod", new ProblemAttributes(CategorizedProblem.CAT_DEPRECATION)); expectedProblemAttributes.put("OverridingMethodWithoutSuperInvocation", new ProblemAttributes(CategorizedProblem.CAT_POTENTIAL_PROGRAMMING_PROBLEM)); expectedProblemAttributes.put("OverridingNonVisibleMethod", new ProblemAttributes(CategorizedProblem.CAT_NAME_SHADOWING_CONFLICT)); expectedProblemAttributes.put("PackageCollidesWithType", new ProblemAttributes(CategorizedProblem.CAT_TYPE)); @@ -1131,10 +1133,18 @@ public void test011_problem_categories() { expectedProblemAttributes.put("UsingDeprecatedField", new ProblemAttributes(CategorizedProblem.CAT_DEPRECATION)); expectedProblemAttributes.put("UsingDeprecatedMethod", new ProblemAttributes(CategorizedProblem.CAT_DEPRECATION)); expectedProblemAttributes.put("UsingDeprecatedType", new ProblemAttributes(CategorizedProblem.CAT_DEPRECATION)); + expectedProblemAttributes.put("UsingDeprecatedSinceVersionConstructor", new ProblemAttributes(CategorizedProblem.CAT_DEPRECATION)); + expectedProblemAttributes.put("UsingDeprecatedSinceVersionField", new ProblemAttributes(CategorizedProblem.CAT_DEPRECATION)); + expectedProblemAttributes.put("UsingDeprecatedSinceVersionMethod", new ProblemAttributes(CategorizedProblem.CAT_DEPRECATION)); + expectedProblemAttributes.put("UsingDeprecatedSinceVersionType", new ProblemAttributes(CategorizedProblem.CAT_DEPRECATION)); expectedProblemAttributes.put("UsingTerminallyDeprecatedConstructor", new ProblemAttributes(CategorizedProblem.CAT_DEPRECATION)); expectedProblemAttributes.put("UsingTerminallyDeprecatedField", new ProblemAttributes(CategorizedProblem.CAT_DEPRECATION)); expectedProblemAttributes.put("UsingTerminallyDeprecatedMethod", new ProblemAttributes(CategorizedProblem.CAT_DEPRECATION)); expectedProblemAttributes.put("UsingTerminallyDeprecatedType", new ProblemAttributes(CategorizedProblem.CAT_DEPRECATION)); + expectedProblemAttributes.put("UsingTerminallyDeprecatedSinceVersionConstructor", new ProblemAttributes(CategorizedProblem.CAT_DEPRECATION)); + expectedProblemAttributes.put("UsingTerminallyDeprecatedSinceVersionField", new ProblemAttributes(CategorizedProblem.CAT_DEPRECATION)); + expectedProblemAttributes.put("UsingTerminallyDeprecatedSinceVersionMethod", new ProblemAttributes(CategorizedProblem.CAT_DEPRECATION)); + expectedProblemAttributes.put("UsingTerminallyDeprecatedSinceVersionType", new ProblemAttributes(CategorizedProblem.CAT_DEPRECATION)); expectedProblemAttributes.put("VarIsNotAllowedHere", new ProblemAttributes(CategorizedProblem.CAT_SYNTAX)); expectedProblemAttributes.put("VarIsReserved", new ProblemAttributes(CategorizedProblem.CAT_SYNTAX)); expectedProblemAttributes.put("VarIsReservedInFuture", new ProblemAttributes(CategorizedProblem.CAT_SYNTAX)); @@ -1811,7 +1821,9 @@ public void test012_compiler_problems_tuning() { expectedProblemAttributes.put("OuterLocalMustBeEffectivelyFinal", SKIP); expectedProblemAttributes.put("OuterLocalMustBeFinal", SKIP); expectedProblemAttributes.put("OverridingDeprecatedMethod", new ProblemAttributes(JavaCore.COMPILER_PB_DEPRECATION)); + expectedProblemAttributes.put("OverridingDeprecatedSinceVersionMethod", new ProblemAttributes(JavaCore.COMPILER_PB_DEPRECATION)); expectedProblemAttributes.put("OverridingTerminallyDeprecatedMethod", new ProblemAttributes(JavaCore.COMPILER_PB_TERMINAL_DEPRECATION)); + expectedProblemAttributes.put("OverridingTerminallyDeprecatedSinceVersionMethod", new ProblemAttributes(JavaCore.COMPILER_PB_TERMINAL_DEPRECATION)); expectedProblemAttributes.put("OverridingMethodWithoutSuperInvocation", new ProblemAttributes(JavaCore.COMPILER_PB_OVERRIDING_METHOD_WITHOUT_SUPER_INVOCATION)); expectedProblemAttributes.put("OverridingNonVisibleMethod", new ProblemAttributes(JavaCore.COMPILER_PB_OVERRIDING_PACKAGE_DEFAULT_METHOD)); expectedProblemAttributes.put("PackageCollidesWithType", SKIP); @@ -2028,10 +2040,18 @@ public void test012_compiler_problems_tuning() { expectedProblemAttributes.put("UsingDeprecatedField", new ProblemAttributes(JavaCore.COMPILER_PB_DEPRECATION)); expectedProblemAttributes.put("UsingDeprecatedMethod", new ProblemAttributes(JavaCore.COMPILER_PB_DEPRECATION)); expectedProblemAttributes.put("UsingDeprecatedType", new ProblemAttributes(JavaCore.COMPILER_PB_DEPRECATION)); + expectedProblemAttributes.put("UsingDeprecatedSinceVersionConstructor", new ProblemAttributes(JavaCore.COMPILER_PB_DEPRECATION)); + expectedProblemAttributes.put("UsingDeprecatedSinceVersionField", new ProblemAttributes(JavaCore.COMPILER_PB_DEPRECATION)); + expectedProblemAttributes.put("UsingDeprecatedSinceVersionMethod", new ProblemAttributes(JavaCore.COMPILER_PB_DEPRECATION)); + expectedProblemAttributes.put("UsingDeprecatedSinceVersionType", new ProblemAttributes(JavaCore.COMPILER_PB_DEPRECATION)); expectedProblemAttributes.put("UsingTerminallyDeprecatedConstructor", new ProblemAttributes(JavaCore.COMPILER_PB_TERMINAL_DEPRECATION)); expectedProblemAttributes.put("UsingTerminallyDeprecatedField", new ProblemAttributes(JavaCore.COMPILER_PB_TERMINAL_DEPRECATION)); expectedProblemAttributes.put("UsingTerminallyDeprecatedMethod", new ProblemAttributes(JavaCore.COMPILER_PB_TERMINAL_DEPRECATION)); expectedProblemAttributes.put("UsingTerminallyDeprecatedType", new ProblemAttributes(JavaCore.COMPILER_PB_TERMINAL_DEPRECATION)); + expectedProblemAttributes.put("UsingTerminallyDeprecatedSinceVersionConstructor", new ProblemAttributes(JavaCore.COMPILER_PB_TERMINAL_DEPRECATION)); + expectedProblemAttributes.put("UsingTerminallyDeprecatedSinceVersionField", new ProblemAttributes(JavaCore.COMPILER_PB_TERMINAL_DEPRECATION)); + expectedProblemAttributes.put("UsingTerminallyDeprecatedSinceVersionMethod", new ProblemAttributes(JavaCore.COMPILER_PB_TERMINAL_DEPRECATION)); + expectedProblemAttributes.put("UsingTerminallyDeprecatedSinceVersionType", new ProblemAttributes(JavaCore.COMPILER_PB_TERMINAL_DEPRECATION)); expectedProblemAttributes.put("VarargsConflict", SKIP); expectedProblemAttributes.put("VarargsElementTypeNotVisible", SKIP); expectedProblemAttributes.put("VarargsElementTypeNotVisibleForConstructor", SKIP); diff --git a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/Deprecated9Test.java b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/Deprecated9Test.java index 027b98ee1e..0b10539f45 100644 --- a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/Deprecated9Test.java +++ b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/Deprecated9Test.java @@ -64,7 +64,7 @@ public class Deprecated9Test extends AbstractRegressionTest { "1. ERROR in p\\M1.java (at line 4)\n" + " a.N1.N2.N3 m = null;\n" + " ^^\n" + - "The type N1.N2 has been deprecated and marked for removal\n" + + "The type N1.N2 has been deprecated since version 1.2 and marked for removal\n" + "----------\n" + "2. ERROR in p\\M1.java (at line 4)\n" + " a.N1.N2.N3 m = null;\n" + @@ -78,6 +78,61 @@ public class Deprecated9Test extends AbstractRegressionTest { "----------\n", JavacTestOptions.Excuse.EclipseWarningConfiguredAsError); } + public void test002binary() { + Runner runner = new Runner(); + runner.customOptions = new HashMap<>(); + runner.customOptions.put(JavaCore.COMPILER_PB_DEPRECATION, CompilerOptions.WARNING); + runner.customOptions.put(JavaCore.COMPILER_PB_TERMINAL_DEPRECATION, CompilerOptions.ERROR); + runner.customOptions.put(CompilerOptions.OPTION_ReportNullReference, CompilerOptions.IGNORE); + runner.testFiles = + new String[] { + "a/N1.java", + "package a;\n" + + "public class N1 {\n" + + " @Deprecated(since=\"1.2\",forRemoval=true)\n" + + " public class N2 {" + + " public void foo() {}" + + " public class N3 {" + + " public void foo() {}" + + " }" + + " }" + + "}\n" + }; + runner.runConformTest(); + + runner.shouldFlushOutputDirectory = false; + runner.testFiles = + new String[] { + "p/M1.java", + "package p;\n" + + "public class M1 {\n" + + " void bar() {\n" + + " a.N1.N2.N3 m = null;\n" + + " m.foo();\n" + + " }\n" + + "}\n" + }; + runner.expectedCompilerLog = + "----------\n" + + "1. ERROR in p\\M1.java (at line 4)\n" + + " a.N1.N2.N3 m = null;\n" + + " ^^\n" + + "The type N1.N2 has been deprecated since version 1.2 and marked for removal\n" + + "----------\n" + + "2. ERROR in p\\M1.java (at line 4)\n" + + " a.N1.N2.N3 m = null;\n" + + " ^^\n" + + "The type N1.N2.N3 has been deprecated and marked for removal\n" + + "----------\n" + + "3. ERROR in p\\M1.java (at line 5)\n" + + " m.foo();\n" + + " ^^^^^\n" + + "The method foo() from the type N1.N2.N3 has been deprecated and marked for removal\n" + + "----------\n"; + runner.javacTestOptions = + JavacTestOptions.Excuse.EclipseWarningConfiguredAsError; + runner.runNegativeTest(); + } //https://bugs.eclipse.org/bugs/show_bug.cgi?id=191909 public void test004() { Map<String, String> customOptions = new HashMap<>(); @@ -106,12 +161,12 @@ public class Deprecated9Test extends AbstractRegressionTest { "1. ERROR in test1\\E02.java (at line 4)\n" + " System.out.println(E01.x);\n" + " ^\n" + - "The field E01.x has been deprecated and marked for removal\n" + + "The field E01.x has been deprecated since version 3 and marked for removal\n" + "----------\n" + "2. ERROR in test1\\E02.java (at line 5)\n" + " System.out.println(E01.y);\n" + " ^\n" + - "The field E01.y has been deprecated and marked for removal\n" + + "The field E01.y has been deprecated since version 3 and marked for removal\n" + "----------\n", JavacTestOptions.Excuse.EclipseWarningConfiguredAsError); } @@ -160,8 +215,6 @@ public class Deprecated9Test extends AbstractRegressionTest { "----------\n", JavacTestOptions.Excuse.EclipseWarningConfiguredAsError); } - // Bug 354536 - compiling package-info.java still depends on the order of compilation units - // - option is disabled public void test005b() { Map<String, String> customOptions = new HashMap<>(); customOptions.put(CompilerOptions.OPTION_ReportDeprecation, CompilerOptions.WARNING); @@ -188,14 +241,12 @@ public class Deprecated9Test extends AbstractRegressionTest { }, customOptions); } - // Bug 354536 - compiling package-info.java still depends on the order of compilation units - // some warnings suppressed public void test005c() { - Map<String, String> customOptions = new HashMap<>(); - customOptions.put(CompilerOptions.OPTION_ReportDeprecation, CompilerOptions.WARNING); - customOptions.put(CompilerOptions.OPTION_ReportTerminalDeprecation, CompilerOptions.WARNING); - this.runNegativeTest( - true, + Runner runner = new Runner(); + runner.customOptions = new HashMap<>(); + runner.customOptions.put(CompilerOptions.OPTION_ReportDeprecation, CompilerOptions.WARNING); + runner.customOptions.put(CompilerOptions.OPTION_ReportTerminalDeprecation, CompilerOptions.WARNING); + runner.testFiles = new String[] { "p1/X.java", "package p1;\n" + @@ -216,24 +267,22 @@ public class Deprecated9Test extends AbstractRegressionTest { " a.foo();\n" + " }\n" + "}\n", - }, - null, customOptions, + }; + runner.expectedCompilerLog = "----------\n" + "1. WARNING in p2\\C.java (at line 5)\n" + " a.foo();\n" + " ^^^^^\n" + "The method foo() from the type X.Inner has been deprecated and marked for removal\n" + - "----------\n", - JavacTestOptions.Excuse.EclipseWarningConfiguredAsError); + "----------\n"; + runner.runWarningTest(); } - // https://bugs.eclipse.org/384870 - [compiler] @Deprecated annotation not detected if preceded by other annotation - // old-style deprecation public void test006() { - Map<String, String> customOptions = new HashMap<>(); - customOptions.put(CompilerOptions.OPTION_ReportDeprecation, CompilerOptions.WARNING); - customOptions.put(CompilerOptions.OPTION_ReportTerminalDeprecation, CompilerOptions.ERROR); - this.runNegativeTest( - true, + Runner runner = new Runner(); + runner.customOptions = new HashMap<>(); + runner.customOptions.put(CompilerOptions.OPTION_ReportDeprecation, CompilerOptions.WARNING); + runner.customOptions.put(CompilerOptions.OPTION_ReportTerminalDeprecation, CompilerOptions.ERROR); + runner.testFiles = new String[] { "test1/E02.java", "package test1;\n" + @@ -248,15 +297,15 @@ public class Deprecated9Test extends AbstractRegressionTest { "public class E01 {\n" + " public static int x = 5;\n" + "}" - }, - null, customOptions, + }; + runner.expectedCompilerLog = "----------\n" + "1. WARNING in test1\\E02.java (at line 3)\n" + " public void foo(E01 arg) {\n" + " ^^^\n" + - "The type E01 is deprecated\n" + - "----------\n", - JavacTestOptions.Excuse.EclipseWarningConfiguredAsError); + "The type E01 is deprecated since version 4\n" + + "----------\n"; + runner.runWarningTest(); } // method overriding public void test007() { @@ -297,7 +346,239 @@ public class Deprecated9Test extends AbstractRegressionTest { "----------\n", JavacTestOptions.Excuse.EclipseWarningConfiguredAsError); } + public void testSinceSource() { + Runner runner = new Runner(); + runner.customOptions = new HashMap<>(); + runner.customOptions.put(JavaCore.COMPILER_PB_DEPRECATION, CompilerOptions.WARNING); + runner.customOptions.put(JavaCore.COMPILER_PB_DEPRECATION_WHEN_OVERRIDING_DEPRECATED_METHOD, CompilerOptions.ENABLED); + runner.customOptions.put(JavaCore.COMPILER_PB_TERMINAL_DEPRECATION, CompilerOptions.ERROR); + runner.testFiles = + new String[] { + "test1/E01.java", + "package test1;\n" + + "public class E01 {\n" + + " @Deprecated(since=\"1.0\") protected static class Old {}\n" + + " @Deprecated(since=\"2\") public static int x = 5, y= 10;\n" + + " @Deprecated(since=\"3.0.0\") public E01() {}\n" + + " @Deprecated(since=\"4-SNAPSHOT\") protected void old() {}\n" + + "}", + "test1/E02.java", + "package test1;\n" + + "public class E02 {\n" + + " public void foo() {\n" + + " System.out.println(new E01.Old());\n" + + " E01 e = new E01();\n" + + " e.old();\n" + + " System.out.println(E01.x);\n" + + " System.out.println(E01.y);\n" + + " }\n" + + " class E03 extends E01 {\n" + + " protected void old() {}\n" + + " }\n" + + "}" + }; + runner.expectedCompilerLog = + "----------\n" + + "1. WARNING in test1\\E02.java (at line 4)\n" + + " System.out.println(new E01.Old());\n" + + " ^^^^^^^^^\n" + + "The constructor E01.Old() is deprecated since version 1.0\n" + + "----------\n" + + "2. WARNING in test1\\E02.java (at line 4)\n" + + " System.out.println(new E01.Old());\n" + + " ^^^\n" + + "The type E01.Old is deprecated since version 1.0\n" + + "----------\n" + + "3. WARNING in test1\\E02.java (at line 5)\n" + + " E01 e = new E01();\n" + + " ^^^^^\n" + + "The constructor E01() is deprecated since version 3.0.0\n" + + "----------\n" + + "4. WARNING in test1\\E02.java (at line 6)\n" + + " e.old();\n" + + " ^^^^^\n" + + "The method old() from the type E01 is deprecated since version 4-SNAPSHOT\n" + + "----------\n" + + "5. WARNING in test1\\E02.java (at line 7)\n" + + " System.out.println(E01.x);\n" + + " ^\n" + + "The field E01.x is deprecated since version 2\n" + + "----------\n" + + "6. WARNING in test1\\E02.java (at line 8)\n" + + " System.out.println(E01.y);\n" + + " ^\n" + + "The field E01.y is deprecated since version 2\n" + + "----------\n" + + "7. WARNING in test1\\E02.java (at line 10)\n" + + " class E03 extends E01 {\n" + + " ^^^\n" + + "The constructor E01() is deprecated since version 3.0.0\n" + + "----------\n" + + "8. WARNING in test1\\E02.java (at line 11)\n" + + " protected void old() {}\n" + + " ^^^^^\n" + + "The method E02.E03.old() overrides a method from E01 that is deprecated since version 4-SNAPSHOT\n" + + "----------\n"; + runner.runWarningTest(); + } + public void testSinceBinary() { + Runner runner = new Runner(); + runner.customOptions = new HashMap<>(); + runner.customOptions.put(JavaCore.COMPILER_PB_DEPRECATION, CompilerOptions.WARNING); + runner.customOptions.put(JavaCore.COMPILER_PB_DEPRECATION_WHEN_OVERRIDING_DEPRECATED_METHOD, CompilerOptions.ENABLED); + runner.customOptions.put(JavaCore.COMPILER_PB_TERMINAL_DEPRECATION, CompilerOptions.ERROR); + runner.testFiles = + new String[] { + "test1/E01.java", + "package test1;\n" + + "public class E01 {\n" + + " @Deprecated(since=\"1.0\") protected static class Old {}\n" + + " @Deprecated(since=\"2\") public static int x = 5, y= 10;\n" + + " @Deprecated(since=\"3.0.0\") public E01() {}\n" + + " @Deprecated(since=\"4-SNAPSHOT\") protected void old() {}\n" + + "}" + }; + runner.runConformTest(); + runner.shouldFlushOutputDirectory = false; + runner.testFiles = + new String[] { + "test1/E02.java", + "package test1;\n" + + "public class E02 {\n" + + " public void foo() {\n" + + " System.out.println(new E01.Old());\n" + + " E01 e = new E01();\n" + + " e.old();\n" + + " System.out.println(E01.x);\n" + + " System.out.println(E01.y);\n" + + " }\n" + + " class E03 extends E01 {\n" + + " protected void old() {}\n" + + " }\n" + + "}" + }; + runner.expectedCompilerLog = + "----------\n" + + "1. WARNING in test1\\E02.java (at line 4)\n" + + " System.out.println(new E01.Old());\n" + + " ^^^^^^^^^\n" + + "The constructor E01.Old() is deprecated since version 1.0\n" + + "----------\n" + + "2. WARNING in test1\\E02.java (at line 4)\n" + + " System.out.println(new E01.Old());\n" + + " ^^^\n" + + "The type E01.Old is deprecated since version 1.0\n" + + "----------\n" + + "3. WARNING in test1\\E02.java (at line 5)\n" + + " E01 e = new E01();\n" + + " ^^^^^\n" + + "The constructor E01() is deprecated since version 3.0.0\n" + + "----------\n" + + "4. WARNING in test1\\E02.java (at line 6)\n" + + " e.old();\n" + + " ^^^^^\n" + + "The method old() from the type E01 is deprecated since version 4-SNAPSHOT\n" + + "----------\n" + + "5. WARNING in test1\\E02.java (at line 7)\n" + + " System.out.println(E01.x);\n" + + " ^\n" + + "The field E01.x is deprecated since version 2\n" + + "----------\n" + + "6. WARNING in test1\\E02.java (at line 8)\n" + + " System.out.println(E01.y);\n" + + " ^\n" + + "The field E01.y is deprecated since version 2\n" + + "----------\n" + + "7. WARNING in test1\\E02.java (at line 10)\n" + + " class E03 extends E01 {\n" + + " ^^^\n" + + "The constructor E01() is deprecated since version 3.0.0\n" + + "----------\n" + + "8. WARNING in test1\\E02.java (at line 11)\n" + + " protected void old() {}\n" + + " ^^^^^\n" + + "The method E02.E03.old() overrides a method from E01 that is deprecated since version 4-SNAPSHOT\n" + + "----------\n"; + runner.runWarningTest(); + } + public void testSinceTerminally() { + Runner runner = new Runner(); + runner.customOptions = new HashMap<>(); + runner.customOptions.put(JavaCore.COMPILER_PB_DEPRECATION, CompilerOptions.WARNING); + runner.customOptions.put(JavaCore.COMPILER_PB_DEPRECATION_WHEN_OVERRIDING_DEPRECATED_METHOD, CompilerOptions.ENABLED); + runner.customOptions.put(JavaCore.COMPILER_PB_TERMINAL_DEPRECATION, CompilerOptions.ERROR); + runner.testFiles = + new String[] { + "test1/E01.java", + "package test1;\n" + + "public class E01 {\n" + + " @Deprecated(since=\"1.0\", forRemoval=true) protected static class Old {}\n" + + " @Deprecated(since=\"2\", forRemoval=true) public static int x = 5, y= 10;\n" + + " @Deprecated(since=\"3.0.0\", forRemoval=true) public E01() {}\n" + + " @Deprecated(since=\"4-SNAPSHOT\", forRemoval=true) protected void old() {}\n" + + "}", + "test1/E02.java", + "package test1;\n" + + "public class E02 {\n" + + " public void foo() {\n" + + " System.out.println(new E01.Old());\n" + + " E01 e = new E01();\n" + + " e.old();\n" + + " System.out.println(E01.x);\n" + + " System.out.println(E01.y);\n" + + " }\n" + + " class E03 extends E01 {\n" + + " protected void old() {}\n" + + " }\n" + + "}" + }; + runner.expectedCompilerLog = + "----------\n" + + "1. ERROR in test1\\E02.java (at line 4)\n" + + " System.out.println(new E01.Old());\n" + + " ^^^^^^^^^\n" + + "The constructor E01.Old() has been deprecated since version 1.0 and marked for removal\n" + + "----------\n" + + "2. ERROR in test1\\E02.java (at line 4)\n" + + " System.out.println(new E01.Old());\n" + + " ^^^\n" + + "The type E01.Old has been deprecated since version 1.0 and marked for removal\n" + + "----------\n" + + "3. ERROR in test1\\E02.java (at line 5)\n" + + " E01 e = new E01();\n" + + " ^^^^^\n" + + "The constructor E01() has been deprecated since version 3.0.0 and marked for removal\n" + + "----------\n" + + "4. ERROR in test1\\E02.java (at line 6)\n" + + " e.old();\n" + + " ^^^^^\n" + + "The method old() from the type E01 has been deprecated since version 4-SNAPSHOT and marked for removal\n" + + "----------\n" + + "5. ERROR in test1\\E02.java (at line 7)\n" + + " System.out.println(E01.x);\n" + + " ^\n" + + "The field E01.x has been deprecated since version 2 and marked for removal\n" + + "----------\n" + + "6. ERROR in test1\\E02.java (at line 8)\n" + + " System.out.println(E01.y);\n" + + " ^\n" + + "The field E01.y has been deprecated since version 2 and marked for removal\n" + + "----------\n" + + "7. ERROR in test1\\E02.java (at line 10)\n" + + " class E03 extends E01 {\n" + + " ^^^\n" + + "The constructor E01() has been deprecated since version 3.0.0 and marked for removal\n" + + "----------\n" + + "8. ERROR in test1\\E02.java (at line 11)\n" + + " protected void old() {}\n" + + " ^^^^^\n" + + "The method E02.E03.old() overrides a method from E01 that has been deprecated since version 4-SNAPSHOT and marked for removal\n" + + "----------\n"; + runner.javacTestOptions = + JavacTestOptions.Excuse.EclipseWarningConfiguredAsError; + runner.runNegativeTest(); + } public static Class<?> testClass() { return Deprecated9Test.class; } diff --git a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/DeprecatedTest.java b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/DeprecatedTest.java index f59d3c316b..c75a8b5178 100644 --- a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/DeprecatedTest.java +++ b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/DeprecatedTest.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2016 IBM Corporation and others. + * Copyright (c) 2000, 2018 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 @@ -10,22 +10,70 @@ *******************************************************************************/ package org.eclipse.jdt.core.tests.compiler.regression; +import java.io.File; +import java.io.IOException; +import java.util.Arrays; import java.util.HashMap; import java.util.Map; +import org.eclipse.jdt.core.compiler.CharOperation; +import org.eclipse.jdt.core.tests.util.Util; import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants; +import org.eclipse.jdt.internal.compiler.env.INameEnvironment; +import org.eclipse.jdt.internal.compiler.env.NameEnvironmentAnswer; import org.eclipse.jdt.internal.compiler.impl.CompilerOptions; +import org.eclipse.jdt.internal.compiler.lookup.TypeConstants; import junit.framework.Test; @SuppressWarnings({ "unchecked", "rawtypes" }) public class DeprecatedTest extends AbstractRegressionTest { + +static { +// TESTS_NAMES = new String[] { "test008a" }; +} + +protected char[][] invisibleType; + public DeprecatedTest(String name) { super(name); } public static Test suite() { return buildAllCompliancesTestSuite(testClass()); } + +@Override +protected void tearDown() throws Exception { + this.invisibleType = null; + super.tearDown(); +} + +@Override +protected INameEnvironment getNameEnvironment(final String[] testFiles, String[] classPaths) { + // constructs a name environment that is able to hide a type of name 'this.invisibleType': + this.classpaths = classPaths == null ? getDefaultClassPaths() : classPaths; + return new InMemoryNameEnvironment(testFiles, getClassLibs(classPaths == null)) { + @Override + public NameEnvironmentAnswer findType(char[][] compoundTypeName) { + if (DeprecatedTest.this.invisibleType != null && CharOperation.equals(DeprecatedTest.this.invisibleType, compoundTypeName)) + return null; + return super.findType(compoundTypeName); + } + @Override + public NameEnvironmentAnswer findType(char[] typeName, char[][] packageName) { + if (DeprecatedTest.this.invisibleType != null && DeprecatedTest.this.invisibleType.length == packageName.length+1) { + char[][] packName = CharOperation.subarray(DeprecatedTest.this.invisibleType, 0, DeprecatedTest.this.invisibleType.length-1); + if (CharOperation.equals(packageName, packName)) { + char[] simpleName = DeprecatedTest.this.invisibleType[DeprecatedTest.this.invisibleType.length-1]; + if (CharOperation.equals(simpleName, typeName)) + return null; + } + } + return super.findType(typeName, packageName); + } + }; +} + public void test001() { this.runNegativeTest(new String[] { "p/B.java", @@ -316,6 +364,47 @@ public void test008() { false, // flush previous output dir content null); // custom options } +// variation of test008 on behalf of Bug 526335 - [9][hovering] Deprecation warning should show the new 'since' deprecation value +// verify that we don't attempt to access java.lang.Deprecated in a 1.4 based compilation. +public void test008a() throws IOException { + String jarPath = LIB_DIR+File.separator+"p008"+File.separator+"x.jar"; + Util.createJar(new String[] { + "X.java", + "package p008;\n" + + "@Deprecated\n" + + "public class X {\n" + + "}\n", + }, + jarPath, + "1.5"); + + Runner runner = new Runner(); + runner.testFiles = + new String[] { + "Y.java", + "public class Y {\n" + + " void foo() {\n" + + " p008.X x;\n" + + " }\n" + + "}\n", + }; + String[] libs = getDefaultClassPaths(); + libs = Arrays.copyOf(libs, libs.length+1); + libs[libs.length-1] = jarPath; + runner.classLibraries = libs; + runner.expectedCompilerLog = + "----------\n" + + "1. WARNING in Y.java (at line 3)\n" + + " p008.X x;\n" + + " ^\n" + + "The type X is deprecated\n" + + "----------\n"; + if (this.complianceLevel < ClassFileConstants.JDK1_5) { + // simulate we were running on a JRE without java.lang.Deprecated + this.invisibleType = TypeConstants.JAVA_LANG_DEPRECATED; + } + runner.runWarningTest(); +} //https://bugs.eclipse.org/bugs/show_bug.cgi?id=88124 - variation public void test009() { this.runNegativeTest( diff --git a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/GenericTypeTest.java b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/GenericTypeTest.java index 59ae3694e0..89fa5fcbdd 100644 --- a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/GenericTypeTest.java +++ b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/GenericTypeTest.java @@ -39798,24 +39798,11 @@ public void test1142() { "}\n", // ================= }, // compiler results - this.complianceLevel < ClassFileConstants.JDK1_8 ? "----------\n" + /* expected compiler log */ "1. ERROR in X.java (at line 5)\n" + " return compound(asList(a, b));\n" + " ^^^^^^^^\n" + "The method compound(Iterable<? extends Comparator<? super T>>) in the type X is not applicable for the arguments (List<Comparator<? extends Object>>)\n" + - "----------\n" - // 1.8+ ATM, we generate an extra error due to inner poly expression evaluation. - :"----------\n" + - "1. ERROR in X.java (at line 5)\n" + - " return compound(asList(a, b));\n" + - " ^^^^^^^^\n" + - "The method compound(Iterable<? extends Comparator<? super T>>) in the type X is not applicable for the arguments (List<Comparator<? extends Object>>)\n" + - "----------\n" + - "2. ERROR in X.java (at line 5)\n" + - " return compound(asList(a, b));\n" + - " ^^^^^^^^^^^^\n" + - "Type mismatch: cannot convert from List<Comparator<? extends Object>> to Iterable<? extends Comparator<? super T>>\n" + "----------\n", // javac options JavacTestOptions.JavacHasABug.JavacBug6573446 /* javac test options */); diff --git a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/GenericsRegressionTest_1_8.java b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/GenericsRegressionTest_1_8.java index 9b05540e41..d6409a544e 100644 --- a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/GenericsRegressionTest_1_8.java +++ b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/GenericsRegressionTest_1_8.java @@ -1235,12 +1235,7 @@ public void testBug425493() { " ^^^^^^^^^^^^\n" + "The method addAttribute(Test.Attribute<T>, T) in the type Test is not applicable for the arguments (Test.Attribute<capture#1-of ?>, capture#2-of ?)\n" + "----------\n" + - "2. ERROR in Test.java (at line 3)\n" + - " addAttribute(java.util.Objects.requireNonNull(attribute, \"\"),\n" + - " ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n" + - "Type mismatch: cannot convert from Test.Attribute<capture#1-of ?> to Test.Attribute<T>\n" + - "----------\n" + - "3. ERROR in Test.java (at line 5)\n" + + "2. ERROR in Test.java (at line 5)\n" + " addAttribute(attribute, attribute.getDefault());\n" + " ^^^^^^^^^^^^\n" + "The method addAttribute(Test.Attribute<T>, T) in the type Test is not applicable for the arguments (Test.Attribute<capture#3-of ?>, capture#4-of ?)\n" + @@ -7011,11 +7006,6 @@ public void testBug502350() { " Stuff.func(Comparator.naturalOrder());\n" + " ^^^^\n" + "The method func(Comparator<T>) in the type Stuff is not applicable for the arguments (Comparator<Comparable<Comparable<B>>>)\n" + - "----------\n" + - "2. ERROR in makeCompilerFreeze\\EclipseJava8Bug.java (at line 20)\n" + - " Stuff.func(Comparator.naturalOrder());\n" + - " ^^^^^^^^^^^^^^^^^^^^^^^^^\n" + - "Type mismatch: cannot convert from Comparator<Comparable<Comparable<B>>> to Comparator<T>\n" + "----------\n" ); } @@ -8540,4 +8530,40 @@ public void testBug508834_comment0() { "Type safety: The expression of type Action[] needs unchecked conversion to conform to Action<S2>[]\n" + "----------\n"); } + public void testBug519147() { + runConformTest( + new String[] { + "Main.java", + "import java.util.HashMap;\n" + + "import java.util.HashSet;\n" + + "import java.util.Set;\n" + + "\n" + + "public class Main<MyKey, MyValue> {\n" + + "\n" + + " static class MyMap<K, V> extends HashMap<K, V> {\n" + + " public MyMap<K, V> putAllReturning(MyMap<K, V> c) { putAll(c); return this; }\n" + + " public MyMap<K, V> putReturning(K key, V value) { put(key, value); return this; }\n" + + " }\n" + + "\n" + + " public Main() {\n" + + " Set<MyValue> values = new HashSet<>(); // actually something better\n" + + " final MyMap<MyKey, MyValue> myMap =\n" + + " values.stream()\n" + + " .reduce(\n" + + " new MyMap<MyKey, MyValue>(),\n" + + " (map, value) -> {\n" + + " Set<MyKey> keys = new HashSet<>(); // actually something better\n" + + "\n" + + " return keys.stream()\n" + + " .reduce(\n" + + " map, // this would work syntactically: new MyMap<MyKey, MyValue>(),\n" + + " (map2, key) -> map2.putReturning(key, value),\n" + + " MyMap::putAllReturning);\n" + + " },\n" + + " MyMap::putAllReturning\n" + + " );\n" + + " }\n" + + "}\n" + }); + } } diff --git a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/InnerClass15Test.java b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/InnerClass15Test.java index da87c14a37..c1d45d1132 100644 --- a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/InnerClass15Test.java +++ b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/InnerClass15Test.java @@ -708,6 +708,54 @@ public void testBug520874i() { "Cycle detected: a cycle exists in the type hierarchy between A and C\n" + "----------\n"); } +public void testBug526681() { + runNegativeTest( + new String[] { + "p/A.java", + "package p;\n" + + "import p.B;\n" + + "public class A extends B {\n" + + " public static abstract class C {}\n" + + "}\n", + "p/B.java", + "package p;\n" + + "import p.A.C;\n" + + "public abstract class B extends C {}" + }, + "----------\n" + + "1. ERROR in p\\A.java (at line 3)\n" + + " public class A extends B {\n" + + " ^\n" + + "The hierarchy of the type A is inconsistent\n" + + "----------\n" + + "----------\n" + + "1. ERROR in p\\B.java (at line 3)\n" + + " public abstract class B extends C {}\n" + + " ^\n" + + "Cycle detected: a cycle exists in the type hierarchy between B and A\n" + + "----------\n"); +} +public void testBug527731() { + if (this.complianceLevel < ClassFileConstants.JDK1_8) return; // uses diamond, 1.7-inference fails, only 1.8 is good + runConformTest( + new String[] { + "OuterClass.java", + "import java.util.ArrayList;\n" + + "\n" + + "public class OuterClass<T> extends ArrayList<OuterClass.InnerTypedClass<T>> {\n" + + " \n" + + " public static interface InnerInterface {}\n" + + " \n" + + " public static class InnerTypedClass<T> implements InnerInterface {}\n" + + " \n" + + " public static void main(String[] args) {\n" + + " OuterClass<String> outerClass = new OuterClass<>();\n" + + " outerClass.add(new InnerTypedClass<>());\n" + + " System.out.println(outerClass);\n" + + " }\n" + + "}\n" + }); +} public static Class<InnerClass15Test> testClass() { return InnerClass15Test.class; } diff --git a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/NullTypeAnnotationTest.java b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/NullTypeAnnotationTest.java index 31de7671b0..a3948b4e09 100644 --- a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/NullTypeAnnotationTest.java +++ b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/NullTypeAnnotationTest.java @@ -6905,8 +6905,8 @@ public void test443467() throws Exception { "----------\n" + "1. ERROR in BuildIdeMain.java (at line 9)\n" + " filter2.map(p -> new SimpleEntry<>(updateToFile.get(p), p->ideFiles.get(p)));\n" + - " ^^^^^^^^^^^^^^^^^^\n" + - "The target type of this expression must be a functional interface\n" + + " ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n" + + "Cannot infer type arguments for SimpleEntry<>\n" + "----------\n"); } public void testBug445227() { diff --git a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/runtime/LocalVMLauncher.java b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/runtime/LocalVMLauncher.java index 4595280614..484c911236 100644 --- a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/runtime/LocalVMLauncher.java +++ b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/runtime/LocalVMLauncher.java @@ -30,6 +30,11 @@ import org.eclipse.jdt.core.tests.util.Util; @SuppressWarnings({ "unchecked", "rawtypes" }) public abstract class LocalVMLauncher implements RuntimeConstants { + static final String[] env = System.getenv().entrySet().stream() + .filter(e -> !"JAVA_TOOL_OPTIONS".equals(e.getKey())) + .map(e -> e.getKey() + "=" + e.getValue()) + .toArray(String[]::new); + /** * Whether the target has a file system and thus whether it supports writing * class files to disk. See org.eclipse.jdt.core.tests.eval.target.CodeSnippetRunner for more @@ -130,7 +135,7 @@ protected Process execCommandLine() throws TargetException { // Use Runtime.exec(String[]) with tokens because Runtime.exec(String) with commandLineString // does not properly handle spaces in arguments on Unix/Linux platforms. String[] commandLine = getCommandLine(); - vmProcess= Runtime.getRuntime().exec(commandLine); + vmProcess= Runtime.getRuntime().exec(commandLine, env); } catch (IOException e) { throw new TargetException("Error launching VM at " + this.vmPath); } diff --git a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/RunAllJava9Tests.java b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/RunAllJava9Tests.java index 15566b271c..56e6a51dc2 100644 --- a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/RunAllJava9Tests.java +++ b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/RunAllJava9Tests.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2016, 2017 IBM Corporation and others. + * Copyright (c) 2016, 2018 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 @@ -20,6 +20,7 @@ import org.eclipse.jdt.core.tests.model.Java9ElementTests; import org.eclipse.jdt.core.tests.model.JavaConventionTests; import org.eclipse.jdt.core.tests.model.JavaSearchBugs9Tests; import org.eclipse.jdt.core.tests.model.ModuleBuilderTests; +import org.eclipse.jdt.core.tests.model.ModuleOptionsTests; import org.eclipse.jdt.core.tests.model.ResolveTests9; import org.eclipse.jdt.core.tests.util.AbstractCompilerTest; @@ -36,6 +37,7 @@ public class RunAllJava9Tests extends TestCase { public static Class[] getAllTestClasses() { return new Class[] { ModuleBuilderTests.class, + ModuleOptionsTests.class, Java9ElementTests.class, JavaSearchBugs9Tests.class, CompletionTests9.class, diff --git a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/AbstractJavaModelTests.java b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/AbstractJavaModelTests.java index 57c65edec6..ff5c1bda53 100644 --- a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/AbstractJavaModelTests.java +++ b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/AbstractJavaModelTests.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2017 IBM Corporation and others. + * Copyright (c) 2000, 2018 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 @@ -3258,6 +3258,10 @@ public abstract class AbstractJavaModelTests extends SuiteOfTestCases { new CompilerOptions(options).toString()); } + protected IPath getJRE9Path() { + return new Path(System.getProperty("java.home") + "/lib/jrt-fs.jar"); + } + /** * Wait for autobuild notification to occur */ diff --git a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/AllJavaModelTests.java b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/AllJavaModelTests.java index 4c19df1418..c2ff7ff072 100644 --- a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/AllJavaModelTests.java +++ b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/AllJavaModelTests.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2017 IBM Corporation and others. + * Copyright (c) 2000, 2018 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 @@ -47,6 +47,7 @@ private static Class[] getAllTestClasses() { JavaProjectTests.class, // Modularity tests (Java 9) ModuleBuilderTests.class, + ModuleOptionsTests.class, // Compilation unit tests CompilationUnitTests.class, diff --git a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/JavaProjectTests.java b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/JavaProjectTests.java index 0f868ee6fb..4e29db6d52 100644 --- a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/JavaProjectTests.java +++ b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/JavaProjectTests.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2017 IBM Corporation and others. + * Copyright (c) 2000, 2018 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 diff --git a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/ModuleBuilderTests.java b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/ModuleBuilderTests.java index 65ffee313b..1070abe3af 100644 --- a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/ModuleBuilderTests.java +++ b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/ModuleBuilderTests.java @@ -5916,6 +5916,105 @@ public class ModuleBuilderTests extends ModifyingResourceTests { } } + public void testBug522670() throws Exception { + if (!isJRE9) return; + Hashtable<String, String> javaCoreOptions = JavaCore.getOptions(); + try { + Hashtable<String, String> newOptions=new Hashtable<>(javaCoreOptions); + newOptions.put(CompilerOptions.OPTION_Store_Annotations, JavaCore.ENABLED); + JavaCore.setOptions(newOptions); + IJavaProject p1 = setupModuleProject("util", + new String[] { + "src/module-info.java", + "module util {\n" + + " exports my.util;\n" + + "}\n" + + "", + "src/my/util/Data.java", + "package my.util;\n" + + "public class Data {\n" + + "}\n" + + "", + "src/my/util/AnnotatedInModule.java", + "package my.util;\n" + + "import static java.lang.annotation.ElementType.TYPE_USE;\n" + + "import java.lang.annotation.Target;\n" + + "@Target(TYPE_USE)\n" + + "@interface Y {\n" + + "}\n" + + "public abstract class AnnotatedInModule {\n" + + " abstract public @Y Data getTime();\n" + + "}\n" + + "", + }); + IJavaProject p2 = setupModuleProject("util2", + new String[] { + "src/module-info.java", + "module util2 {\n" + + " exports my.util.nested;\n" + + "}\n" + + "", + "src/my/util/nested/Unrelated.java", + "package my.util.nested;\n" + + "class Unrelated {\n" + + "}\n" + + "", + }); + String[] sources3 = { + "src/a/other/AnnotatedInOtherNonModule.java", + "package a.other;\n" + + "import static java.lang.annotation.ElementType.TYPE_USE;\n" + + "import java.lang.annotation.Target;\n" + + "import my.util.Data;\n" + + "@Target(TYPE_USE)\n" + + "@interface X {\n" + + "}\n" + + "public class AnnotatedInOtherNonModule {\n" + + " @X\n" + + " Data generationDate;\n" + + "}\n" + + "", + }; + IClasspathAttribute[] attr = { JavaCore.newClasspathAttribute(IClasspathAttribute.MODULE, "true") }; + // modulepath + IClasspathEntry[] deps3 = { JavaCore.newProjectEntry(p1.getPath(), null, false, attr, false) }; + IJavaProject p3 = setupModuleProject("other", sources3, deps3); + + String[] sources4 = { + "src/test/Test.java", + "package test;\n" + + "\n" + + "import a.other.AnnotatedInOtherNonModule;\n" + + "import my.util.AnnotatedInModule;\n" + + "import my.util.Data;\n" + + "\n" + + "public class Test extends AnnotatedInOtherNonModule {\n" + + " public Data f(AnnotatedInModule calendar) {\n" + + " return calendar.getTime();\n" + + " }\n" + + "}\n" + + "", + }; + IClasspathEntry[] deps4 = { // + // modulepath (with split package my.util) + JavaCore.newProjectEntry(p1.getPath(), null, false, attr, false), // + JavaCore.newProjectEntry(p2.getPath(), null, false, attr, false), // + // classpath + JavaCore.newProjectEntry(p3.getPath()) // + }; + IJavaProject p4 = setupModuleProject("test", sources4, deps4); + p4.getProject().getWorkspace().build(IncrementalProjectBuilder.FULL_BUILD, null); + + assertNoErrors(); + } finally { + JavaCore.setOptions(javaCoreOptions); + deleteProject("util"); + deleteProject("util2"); + deleteProject("other"); + deleteProject("test"); + } + } + public void testBug525522() throws Exception { if (!isJRE9) return; String save = System.getProperty("modules.to.load"); diff --git a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/ModuleOptionsTests.java b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/ModuleOptionsTests.java new file mode 100644 index 0000000000..543dcc7a62 --- /dev/null +++ b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/ModuleOptionsTests.java @@ -0,0 +1,706 @@ +/******************************************************************************* + * Copyright (c) 2018 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.model; + +import java.io.File; +import java.io.IOException; +import java.util.Arrays; + +import org.eclipse.core.resources.IMarker; +import org.eclipse.core.resources.IResource; +import org.eclipse.core.resources.IncrementalProjectBuilder; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.Path; +import org.eclipse.jdt.core.IClasspathAttribute; +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.Util; +import org.eclipse.jdt.internal.compiler.util.JRTUtil; +import org.eclipse.jdt.internal.core.ClasspathAttribute; +import org.eclipse.jdt.internal.core.builder.ClasspathJrt; + +import junit.framework.Test; + +public class ModuleOptionsTests extends ModifyingResourceTests { + + public ModuleOptionsTests(String name) { + super(name); + } + + static { +// TESTS_NAMES = new String[] { "testAddReads" }; + } + + private String savedModulesOption = null; + public static Test suite() { + return buildModelTestSuite(ModuleOptionsTests.class, BYTECODE_DECLARATION_ORDER); + } + public void setUpSuite() throws Exception { + super.setUpSuite(); + this.savedModulesOption = System.getProperty("modules.to.load", ""); + System.setProperty("modules.to.load", ""); + JRTUtil.reset(); + ClasspathJrt.resetCaches(); + } + public void tearDownSuite() throws Exception { + System.setProperty("modules.to.load", this.savedModulesOption); + super.tearDownSuite(); + } + // testing auto rebuild after change of limit-modules + public void testLimitModules3() throws CoreException, IOException { + if (!isJRE9) return; + try { + IClasspathAttribute[] attributes = { + JavaCore.newClasspathAttribute(IClasspathAttribute.MODULE, "true"), + JavaCore.newClasspathAttribute(IClasspathAttribute.LIMIT_MODULES, "java.se") // test transitive closure + }; + IJavaProject project = createJava9ProjectWithJREAttributes("org.astro", new String[]{"src", "src2"}, attributes); + + String[] sources = { + "src/module-info.java", + "module org.astro {\n" + + " requires java.base;\n" + + " requires java.desktop;\n" + + " requires java.datatransfer;\n" + + " requires java.sql;\n" + + "}\n", + "src/org/astro/Test2.java", + "package org.astro;\n" + + "class Test2 {\n" + + " java.awt.Window window;\n" + + "}\n", + "src2/org/astro/Test3.java", + "package org.astro;\n" + + "class Test3 {\n" + + " java.awt.datatransfer.Clipboard clippy;\n" + + "}\n" + }; + createSourceFiles(project, sources); + + getWorkspace().build(IncrementalProjectBuilder.FULL_BUILD, null); + IMarker[] markers = project.getProject().findMarkers(null, true, IResource.DEPTH_INFINITE); + assertMarkers("Unexpected markers", + "", + markers); + + IClasspathAttribute[] newLimits = { + JavaCore.newClasspathAttribute(IClasspathAttribute.MODULE, "true"), + JavaCore.newClasspathAttribute(IClasspathAttribute.LIMIT_MODULES, "java.base,java.sql") // no more awt etc + }; + setJRECPAttributes(project, newLimits); + + getWorkspace().build(IncrementalProjectBuilder.AUTO_BUILD, null); + + markers = project.getProject().findMarkers(null, true, IResource.DEPTH_INFINITE); + Arrays.sort(markers, (a,b) -> a.getAttribute(IMarker.CHAR_START, 0) - b.getAttribute(IMarker.CHAR_START, 0)); + assertMarkers("Unexpected markers", + "java.awt cannot be resolved to a type\n" + + "java.awt cannot be resolved to a type\n" + + "java.desktop cannot be resolved to a module\n" + + "java.datatransfer cannot be resolved to a module", + markers); + } finally { + this.deleteProject("org.astro"); + } + } + public void testAddExports() throws CoreException, IOException { + if (!isJRE9) return; + try { + String[] sources = { + "src/module-info.java", + "module org.astro {\n" + + " requires java.base;\n" + + " requires java.desktop;\n" + + " requires java.datatransfer;\n" + + " requires java.sql;\n" + + "}\n", + "src/org/astro/Test2.java", + "package org.astro;\n" + + "public class Test2 {\n" + + " java.awt.Window window;\n" + + "}\n", + "src2/org/astro/Test3.java", + "package org.astro;\n" + + "class Test3 {\n" + + " java.awt.datatransfer.Clipboard clippy;\n" + + "}\n" + }; + IJavaProject project = setupModuleProject("org.astro", new String[] {"src", "src2"}, sources, null); + + sources = new String[] { + "src/module-info.java", + "module test {\n" + + " requires org.astro;\n" + + "}\n", + "src/test/Test.java", + "package test;\n" + + "class Test {\n" + + " org.astro.Test2 t;\n" + + "}\n" + }; + IClasspathAttribute[] attributes = { + JavaCore.newClasspathAttribute(IClasspathAttribute.MODULE, "true"), + JavaCore.newClasspathAttribute(IClasspathAttribute.ADD_EXPORTS, "org.astro/org.astro=test") + }; + IClasspathEntry cp = JavaCore.newProjectEntry(project.getPath(), null, false, attributes, false); + IJavaProject p2 = setupModuleProject("test", sources, new IClasspathEntry[] {cp}); + getWorkspace().build(IncrementalProjectBuilder.FULL_BUILD, null); + IMarker[] markers = p2.getProject().findMarkers(null, true, IResource.DEPTH_INFINITE); + assertMarkers("Unexpected markers", + "", + markers); + + IClasspathAttribute[] newAttrs = { + JavaCore.newClasspathAttribute(IClasspathAttribute.MODULE, "true") + }; + setCPAttributes(p2, newAttrs, cp); + + getWorkspace().build(IncrementalProjectBuilder.AUTO_BUILD, null); + + markers = p2.getProject().findMarkers(null, true, IResource.DEPTH_INFINITE); + assertMarkers("Unexpected markers", + "The type org.astro.Test2 is not accessible", + markers); + } finally { + this.deleteProject("org.astro"); + this.deleteProject("test"); + } + } + + public void testAddExports_JRE() throws CoreException, IOException { + if (!isJRE9) return; + try { + String[] sources = { + "src/module-info.java", + "module org.astro {\n" + + " requires java.base;\n" + + " requires java.desktop;\n" + + " requires java.datatransfer;\n" + + " requires java.sql;\n" + + "}\n", + "src/org/astro/Test2.java", + "package org.astro;\n" + + "public class Test2 {\n" + + " int test(jdk.internal.misc.Unsafe unsafe) {\n" + + " return unsafe.addressSize();\n" + + " }" + + "}\n", + }; + IClasspathAttribute[] attrs = new IClasspathAttribute[] { + JavaCore.newClasspathAttribute(IClasspathAttribute.MODULE, "true"), + JavaCore.newClasspathAttribute(IClasspathAttribute.ADD_EXPORTS, "java.base/jdk.internal.misc=org.astro") + }; + IJavaProject project = createJava9ProjectWithJREAttributes("org.astro", new String[] {"src"}, attrs); + createSourceFiles(project, sources); + getWorkspace().build(IncrementalProjectBuilder.FULL_BUILD, null); + IMarker[] markers = project.getProject().findMarkers(null, true, IResource.DEPTH_INFINITE); + assertMarkers("Unexpected markers", + "", + markers); + + IClasspathAttribute[] newAttrs = { + JavaCore.newClasspathAttribute(IClasspathAttribute.MODULE, "true") + }; + setJRECPAttributes(project, newAttrs); + + getWorkspace().build(IncrementalProjectBuilder.AUTO_BUILD, null); + + markers = project.getProject().findMarkers(null, true, IResource.DEPTH_INFINITE); + assertMarkers("Unexpected markers", + "The type jdk.internal.misc.Unsafe is not accessible", + markers); + } finally { + this.deleteProject("org.astro"); + } + } + public void testAddExports_multi() throws CoreException, IOException { + if (!isJRE9) return; + try { + String[] sources = { + "src/module-info.java", + "module org.astro {\n" + + " requires java.base;\n" + + " requires java.desktop;\n" + + " requires java.datatransfer;\n" + + " requires java.sql;\n" + + "}\n", + "src/org/astro/Test2.java", + "package org.astro;\n" + + "public class Test2 {\n" + + " java.awt.Window window;\n" + + "}\n", + "src2/org/astro/sub/Test3.java", + "package org.astro.sub;\n" + + "public class Test3 {\n" + + " java.awt.datatransfer.Clipboard clippy;\n" + + "}\n" + }; + IJavaProject project = setupModuleProject("org.astro", new String[] {"src", "src2"}, sources, null); + + sources = new String[] { + "src/module-info.java", + "module test {\n" + + " requires org.astro;\n" + + "}\n", + "src/test/Test.java", + "package test;\n" + + "class Test {\n" + + " org.astro.Test2 t;\n" + + " org.astro.sub.Test3 t3;\n" + + "}\n" + }; + IClasspathAttribute[] attributes = { + JavaCore.newClasspathAttribute(IClasspathAttribute.MODULE, "true"), + JavaCore.newClasspathAttribute(IClasspathAttribute.ADD_EXPORTS, "org.astro/org.astro=test") + }; + IClasspathEntry cp = JavaCore.newProjectEntry(project.getPath(), null, false, attributes, false); + IJavaProject p2 = setupModuleProject("test", sources, new IClasspathEntry[] {cp}); + getWorkspace().build(IncrementalProjectBuilder.FULL_BUILD, null); + IMarker[] markers = p2.getProject().findMarkers(null, true, IResource.DEPTH_INFINITE); + assertMarkers("Unexpected markers", + "The type org.astro.sub.Test3 is not accessible", + markers); + + IClasspathAttribute[] newAttrs = { + JavaCore.newClasspathAttribute(IClasspathAttribute.MODULE, "true"), + JavaCore.newClasspathAttribute(IClasspathAttribute.ADD_EXPORTS, "org.astro/org.astro=test:org.astro/org.astro.sub=test") + }; + setCPAttributes(p2, newAttrs, cp); + + getWorkspace().build(IncrementalProjectBuilder.AUTO_BUILD, null); + + markers = p2.getProject().findMarkers(null, true, IResource.DEPTH_INFINITE); + assertMarkers("Unexpected markers", + "", + markers); + } finally { + this.deleteProject("org.astro"); + this.deleteProject("test"); + } + } + public void testAddExports_classFolder() throws CoreException, IOException { + if (!isJRE9) return; + try { + String[] sources = { + "src/module-info.java", + "module org.astro {\n" + + " requires java.base;\n" + + " requires java.desktop;\n" + + " requires java.datatransfer;\n" + + " requires java.sql;\n" + + "}\n", + "src/org/astro/Test2.java", + "package org.astro;\n" + + "public class Test2 {\n" + + " java.awt.Window window;\n" + + "}\n", + "src2/org/astro/sub/Test3.java", + "package org.astro.sub;\n" + + "public class Test3 {\n" + + " java.awt.datatransfer.Clipboard clippy;\n" + + "}\n" + }; + IJavaProject project = setupModuleProject("org.astro", new String[] {"src", "src2"}, sources, null); + + sources = new String[] { + "src/module-info.java", + "module test {\n" + + " requires org.astro;\n" + + "}\n", + "src/test/Test.java", + "package test;\n" + + "class Test {\n" + + " org.astro.Test2 t;\n" + + " org.astro.sub.Test3 t3;\n" + + "}\n" + }; + IClasspathAttribute[] attributes = { + JavaCore.newClasspathAttribute(IClasspathAttribute.MODULE, "true"), + JavaCore.newClasspathAttribute(IClasspathAttribute.ADD_EXPORTS, "org.astro/org.astro=test") + }; + IClasspathEntry cp = JavaCore.newLibraryEntry(project.getProject().findMember("bin").getFullPath(), null, + null, null, attributes, false); + IJavaProject p2 = setupModuleProject("test", sources, new IClasspathEntry[] {cp}); + getWorkspace().build(IncrementalProjectBuilder.FULL_BUILD, null); + IMarker[] markers = p2.getProject().findMarkers(null, true, IResource.DEPTH_INFINITE); + assertMarkers("Unexpected markers", + "The type org.astro.sub.Test3 is not accessible", + markers); + + IClasspathAttribute[] newAttrs = { + JavaCore.newClasspathAttribute(IClasspathAttribute.MODULE, "true"), + JavaCore.newClasspathAttribute(IClasspathAttribute.ADD_EXPORTS, "org.astro/org.astro=test:org.astro/org.astro.sub=test") + }; + setCPAttributes(p2, newAttrs, cp); + + getWorkspace().build(IncrementalProjectBuilder.AUTO_BUILD, null); + + markers = p2.getProject().findMarkers(null, true, IResource.DEPTH_INFINITE); + assertMarkers("Unexpected markers", + "", + markers); + } finally { + this.deleteProject("org.astro"); + this.deleteProject("test"); + } + } + public void testAddReads() throws CoreException, IOException { + if (!isJRE9) return; + String libPath = "externalLib/mod.one.jar"; + try { + String[] sources = new String[] { + "src/module-info.java", + "module org.astro {\n" + + " exports org.astro;\n" + + "}", + "src/org/astro/World.java", + "package org.astro;\n" + + "public interface World {\n" + + " public String name();\n" + + "}" + }; + IJavaProject p = setupModuleProject("org.astro", sources); + + String[] src1 = new String[] { + "src/module-info.java", + "module mod.one {\n" + + " exports one.p;\n" + + "}\n", + "src/org/astro/World.java", + "package org.astro;\n" + + "public interface World { public String name(); }\n", + "src/one/p/C.java", + "package one.p;\n" + + "public class C implements org.astro.World {\n" + + " public String name() {\n" + + " return \"C\";\n" + + " }\n" + + "}\n" + }; + IJavaProject p1 = setupModuleProject("mod.one", src1); + getWorkspace().build(IncrementalProjectBuilder.FULL_BUILD, null); + // jar-up without the required class, should be supplied by the other module + deleteFile("/mod.one/src/org/astro/World.java"); + deleteFile("/mod.one/bin/org/astro/World.class"); + File rootDir = new File(p1.getProject().findMember("bin").getLocation().toString()); + Util.zip(rootDir, getExternalResourcePath(libPath)); + + String[] src2 = new String[] { + "src/module-info.java", + "module com.greetings {\n" + + " requires mod.one;\n" + + "}", + "src/com/greetings/MyTest.java", + "package com.greetings;\n" + + "public class MyTest extends one.p.C {}" + }; + IClasspathEntry dep1 = JavaCore.newProjectEntry(p.getPath(), null, false, + new IClasspathAttribute[] {new ClasspathAttribute("module", "true")}, + false/*not exported*/); + IClasspathEntry dep2 = JavaCore.newLibraryEntry(new Path(getExternalResourcePath(libPath)), null, null, null, + new IClasspathAttribute[] { + new ClasspathAttribute("module", "true"), + new ClasspathAttribute(IClasspathAttribute.ADD_READS, "mod.one=org.astro") + }, + false/*not exported*/); + IJavaProject p2 = setupModuleProject("com.greetings", src2, new IClasspathEntry[] { dep1, dep2 }); + getWorkspace().build(IncrementalProjectBuilder.FULL_BUILD, null); + IMarker[] markers = p2.getProject().findMarkers(null, true, IResource.DEPTH_INFINITE); + assertMarkers("Unexpected markers", "", markers); + IClasspathAttribute[] attrs = new IClasspathAttribute[] { + JavaCore.newClasspathAttribute(IClasspathAttribute.MODULE, "true") + }; + setCPAttributes(p2, attrs, dep2); + getWorkspace().build(IncrementalProjectBuilder.AUTO_BUILD, null); + markers = p2.getProject().findMarkers(null, true, IResource.DEPTH_INFINITE); + assertMarkers("Unexpected markers", + "The project was not built since its build path is incomplete. Cannot find the class file for org.astro.World. Fix the build path then try building this project\n" + + "The type org.astro.World cannot be resolved. It is indirectly referenced from required .class files", + markers); + } finally { + deleteExternalResource(libPath); + deleteProject("mod.one"); + deleteProject("org.astro"); + deleteProject("com.greetings"); + } + } + public void testAddReads2() throws CoreException, IOException { + if (!isJRE9) return; + String libPath = "externalLib/mod.one.jar"; + try { + String[] sources = new String[] { + "src/module-info.java", + "module org.astro {\n" + + " exports org.astro;\n" + + "}", + "src/org/astro/World.java", + "package org.astro;\n" + + "public interface World {\n" + + " public String name();\n" + + "}" + }; + IJavaProject p = setupModuleProject("org.astro", sources); + + String[] src1 = new String[] { + "src/module-info.java", + "module mod.one {\n" + + " exports one.p;\n" + + "}\n", + "src/org/astro/World.java", + "package org.astro;\n" + + "public interface World { public String name(); }\n", + "src/one/p/C.java", + "package one.p;\n" + + "public class C implements org.astro.World {\n" + + " public String name() {\n" + + " return \"C\";\n" + + " }\n" + + "}\n" + }; + IJavaProject p1 = setupModuleProject("mod.one", src1); + getWorkspace().build(IncrementalProjectBuilder.FULL_BUILD, null); + // jar-up without the required class, should be supplied by the other module + deleteFile("/mod.one/src/org/astro/World.java"); + deleteFile("/mod.one/bin/org/astro/World.class"); + File rootDir = new File(p1.getProject().findMember("bin").getLocation().toString()); + Util.zip(rootDir, getExternalResourcePath(libPath)); + + String[] src2 = new String[] { + "src/module-info.java", + "module com.greetings {\n" + + " requires mod.one;\n" + + "}", + "src/com/greetings/MyTest.java", + "package com.greetings;\n" + + "public class MyTest extends one.p.C {}" + }; + IClasspathEntry dep1 = JavaCore.newProjectEntry(p.getPath(), null, false, + new IClasspathAttribute[] {new ClasspathAttribute("module", "true")}, + false/*not exported*/); + IClasspathEntry dep2 = JavaCore.newLibraryEntry(new Path(getExternalResourcePath(libPath)), null, null, null, + new IClasspathAttribute[] { + new ClasspathAttribute("module", "true"), + }, + false/*not exported*/); + IJavaProject p2 = setupModuleProject("com.greetings", src2, new IClasspathEntry[] { dep1, dep2 }); + getWorkspace().build(IncrementalProjectBuilder.FULL_BUILD, null); + IMarker[] markers = p2.getProject().findMarkers(null, true, IResource.DEPTH_INFINITE); + assertMarkers("Unexpected markers", + "The project was not built since its build path is incomplete. Cannot find the class file for org.astro.World. Fix the build path then try building this project\n" + + "The type org.astro.World cannot be resolved. It is indirectly referenced from required .class files", + markers); + IClasspathAttribute[] attrs = new IClasspathAttribute[] { + JavaCore.newClasspathAttribute(IClasspathAttribute.MODULE, "true"), + JavaCore.newClasspathAttribute(IClasspathAttribute.ADD_READS, "mod.one=org.astro") + }; + setCPAttributes(p2, attrs, dep2); + getWorkspace().build(IncrementalProjectBuilder.AUTO_BUILD, null); + markers = p2.getProject().findMarkers(null, true, IResource.DEPTH_INFINITE); + assertMarkers("Unexpected markers", "", markers); + } finally { + deleteExternalResource(libPath); + deleteProject("mod.one"); + deleteProject("org.astro"); + deleteProject("com.greetings"); + } + } + public void _testPatchModule() throws CoreException, IOException { + if (!isJRE9) return; + try { + String[] sources = { + "src/module-info.java", + "module org.astro {\n" + + " requires java.base;\n" + + " requires java.desktop;\n" + + " requires java.datatransfer;\n" + + " requires java.sql;\n" + + " exports org.astro;\n" + + "}\n", + "src/org/astro/Test2.java", + "package org.astro;\n" + + "public class Test2 {\n" + + " java.awt.Window window;\n" + + "}\n" + }; + IJavaProject project = setupModuleProject("org.astro", sources); + + sources = new String[] { + "src/code/Code.java", + "package code;\n" + + "class Code {\n" + + "}\n", + "src2/org/astro/Galaxy.java", + "package org.astro;\n" + + "public class Galaxy { }\n" + }; + IClasspathAttribute[] attributes = { + JavaCore.newClasspathAttribute(IClasspathAttribute.MODULE, "true"), + }; + IClasspathEntry cp = JavaCore.newProjectEntry(project.getPath(), null, false, attributes, false); + IJavaProject p2 = setupModuleProject("patch", new String[] {"src", "src2"}, sources, null); + attributes = new IClasspathAttribute[] { + JavaCore.newClasspathAttribute(IClasspathAttribute.MODULE, "true"), + JavaCore.newClasspathAttribute(IClasspathAttribute.PATCH_MODULE, "org.astro") + }; + IClasspathEntry cp2 = JavaCore.newProjectEntry(p2.getPath(), null, false, attributes, false); + sources = new String[] { + "src/module-info.java", + "module test {\n" + + " requires org.astro;\n" + + "}\n", + "src/test/Test.java", + "package test;\n" + + "class Test {\n" + + " org.astro.World w = null;\n" + + " org.astro.Galaxy g = null;\n" + + "}\n", + }; + IJavaProject p3 = setupModuleProject("test", sources, new IClasspathEntry[] {cp, cp2}); + getWorkspace().build(IncrementalProjectBuilder.FULL_BUILD, null); + IMarker[] markers = p3.getProject().findMarkers(null, true, IResource.DEPTH_INFINITE); + assertMarkers("Unexpected markers", + "", + markers); + } finally { + this.deleteProject("org.astro"); + this.deleteProject("patch"); + this.deleteProject("test"); + } + + } + public void testPatchModule() throws CoreException, IOException { + if (!isJRE9) return; + try { + IClasspathAttribute[] attributes = { + JavaCore.newClasspathAttribute(IClasspathAttribute.MODULE, "true") + }; + IJavaProject patchProject = createJava9ProjectWithJREAttributes("org.astro.patch", new String[]{"src", "src2"}, attributes); + + String[] patchSources = { + "src/org/astro/Test2.java", + "package org.astro;\n" + + "class Test2 {\n" + + " int test(jdk.internal.misc.Unsafe unsafe) {\n" + + " return unsafe.addressSize();\n" + + " }\n" + + "}\n", + "src2/jdk/internal/misc/Test3.java", + "package jdk.internal.misc;\n" + + "class Test3 {\n" + + " Signal.NativeHandler handler;\n" + // package access + "}\n" + }; + createSourceFiles(patchProject, patchSources); + + getWorkspace().build(IncrementalProjectBuilder.FULL_BUILD, null); + IMarker[] markers = patchProject.getProject().findMarkers(null, true, IResource.DEPTH_INFINITE); + assertMarkers("Unexpected markers", + "The type jdk.internal.misc.Unsafe is not accessible\n" + + "Signal cannot be resolved to a type", + markers); + + attributes = new IClasspathAttribute[] { + JavaCore.newClasspathAttribute(IClasspathAttribute.MODULE, "true"), + JavaCore.newClasspathAttribute(IClasspathAttribute.PATCH_MODULE, "java.base") + }; + setJRECPAttributes(patchProject, attributes); + + getWorkspace().build(IncrementalProjectBuilder.AUTO_BUILD, null); + + markers = patchProject.getProject().findMarkers(null, true, IResource.DEPTH_INFINITE); + assertMarkers("Unexpected markers", + "", + markers); + } finally { + this.deleteProject("org.astro.patch"); + } + } + public void testPatchModule2() throws CoreException, IOException { + if (!isJRE9) return; + try { + IClasspathAttribute[] attributes = { + JavaCore.newClasspathAttribute(IClasspathAttribute.MODULE, "true"), + JavaCore.newClasspathAttribute(IClasspathAttribute.PATCH_MODULE, "java.base") + }; + IJavaProject patchProject = createJava9ProjectWithJREAttributes("org.astro.patch", new String[]{"src", "src2"}, attributes); + + String[] patchSources = { + "src/org/astro/Test2.java", + "package org.astro;\n" + + "class Test2 {\n" + + " int test(jdk.internal.misc.Unsafe unsafe) {\n" + + " return unsafe.addressSize();\n" + + " }\n" + + "}\n", + "src2/jdk/internal/misc/Test3.java", + "package jdk.internal.misc;\n" + + "class Test3 {\n" + + " Signal.NativeHandler handler;\n" + // package access + "}\n" + }; + createSourceFiles(patchProject, patchSources); + + getWorkspace().build(IncrementalProjectBuilder.FULL_BUILD, null); + + attributes = new IClasspathAttribute[] { + JavaCore.newClasspathAttribute(IClasspathAttribute.MODULE, "true"), + }; + setJRECPAttributes(patchProject, attributes); + + getWorkspace().build(IncrementalProjectBuilder.AUTO_BUILD, null); + + IMarker[] markers = patchProject.getProject().findMarkers(null, true, IResource.DEPTH_INFINITE); + assertMarkers("Unexpected markers", + "The type jdk.internal.misc.Unsafe is not accessible\n" + + "Signal cannot be resolved to a type", + markers); + } finally { + this.deleteProject("org.astro.patch"); + } + } + private void setCPAttributes(IJavaProject javaProject, IClasspathAttribute[] attributes, IClasspathEntry entryToReplace) throws JavaModelException { + IClasspathEntry[] oldClasspath= javaProject.getRawClasspath(); + int nEntries= oldClasspath.length; + IClasspathEntry[] newEntries= Arrays.copyOf(oldClasspath, nEntries); + for (int i = 0; i < newEntries.length; i++) { + if (newEntries[i].getPath().equals(entryToReplace.getPath())) { + switch(entryToReplace.getEntryKind()) { + case IClasspathEntry.CPE_PROJECT: + newEntries[i] = JavaCore.newProjectEntry(entryToReplace.getPath(), entryToReplace.getAccessRules(), entryToReplace.combineAccessRules(), attributes, entryToReplace.isExported()); + break; + case IClasspathEntry.CPE_LIBRARY: + newEntries[i] = JavaCore.newLibraryEntry(entryToReplace.getPath(), newEntries[i].getSourceAttachmentPath(), null, null, attributes, false); + break; + default: + // not supported + break; + } + break; + } + } + javaProject.setRawClasspath(newEntries, null); + } + private void setJRECPAttributes(IJavaProject javaProject, IClasspathAttribute[] attributes) throws JavaModelException { + IClasspathEntry[] oldClasspath= javaProject.getRawClasspath(); + int nEntries= oldClasspath.length; + IClasspathEntry[] newEntries= Arrays.copyOf(oldClasspath, nEntries); + for (int i = 0; i < newEntries.length; i++) { + if (newEntries[i].getPath().equals(getJRE9Path())) { + newEntries[i] = JavaCore.newLibraryEntry(getJRE9Path(), newEntries[i].getSourceAttachmentPath(), null, null, attributes, false); + break; + } + } + javaProject.setRawClasspath(newEntries, null); + } +} diff --git a/org.eclipse.jdt.core/.settings/.api_filters b/org.eclipse.jdt.core/.settings/.api_filters index f93f3d7d24..1c71707816 100644 --- a/org.eclipse.jdt.core/.settings/.api_filters +++ b/org.eclipse.jdt.core/.settings/.api_filters @@ -13,6 +13,12 @@ <message_argument value="3.13.0"/> </message_arguments> </filter> + <filter comment="new API was backported" id="924844039"> + <message_arguments> + <message_argument value="3.13.101"/> + <message_argument value="3.13.100"/> + </message_arguments> + </filter> <filter id="924844039"> <message_arguments> <message_argument value="3.13.50"/> diff --git a/org.eclipse.jdt.core/META-INF/MANIFEST.MF b/org.eclipse.jdt.core/META-INF/MANIFEST.MF index 63c1167678..89f6742582 100644 --- a/org.eclipse.jdt.core/META-INF/MANIFEST.MF +++ b/org.eclipse.jdt.core/META-INF/MANIFEST.MF @@ -3,7 +3,7 @@ Main-Class: org.eclipse.jdt.internal.compiler.batch.Main Bundle-ManifestVersion: 2 Bundle-Name: %pluginName Bundle-SymbolicName: org.eclipse.jdt.core; singleton:=true -Bundle-Version: 3.15.0.qualifier +Bundle-Version: 3.13.102.qualifier Bundle-Activator: org.eclipse.jdt.core.JavaCore Bundle-Vendor: %providerName Bundle-Localization: plugin diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/core/compiler/IProblem.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/core/compiler/IProblem.java index 3fa98766c5..dc3bee8a22 100644 --- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/core/compiler/IProblem.java +++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/core/compiler/IProblem.java @@ -1950,6 +1950,7 @@ void setSourceStart(int sourceStart); /** @since 3.14 */ int DuplicateResource = Internal + 1251; + // terminally /** @since 3.14 */ int UsingTerminallyDeprecatedType = TypeRelated + 1400; /** @since 3.14 */ @@ -1960,7 +1961,30 @@ void setSourceStart(int sourceStart); int UsingTerminallyDeprecatedField = FieldRelated + 1403; /** @since 3.14 */ int OverridingTerminallyDeprecatedMethod = MethodRelated + 1404; + // with since + /** @since 3.13 */ + int UsingDeprecatedSinceVersionType = TypeRelated + 1405; + /** @since 3.13 */ + int UsingDeprecatedSinceVersionMethod = MethodRelated + 1406; + /** @since 3.13 */ + int UsingDeprecatedSinceVersionConstructor = MethodRelated + 1407; + /** @since 3.13 */ + int UsingDeprecatedSinceVersionField = FieldRelated + 1408; + /** @since 3.13 */ + int OverridingDeprecatedSinceVersionMethod = MethodRelated + 1409; + // terminally with since + /** @since 3.13 */ + int UsingTerminallyDeprecatedSinceVersionType = TypeRelated + 1410; + /** @since 3.13 */ + int UsingTerminallyDeprecatedSinceVersionMethod = MethodRelated + 1411; + /** @since 3.13 */ + int UsingTerminallyDeprecatedSinceVersionConstructor = MethodRelated + 1412; + /** @since 3.13 */ + int UsingTerminallyDeprecatedSinceVersionField = FieldRelated + 1413; + /** @since 3.13 */ + int OverridingTerminallyDeprecatedSinceVersionMethod = MethodRelated + 1414; + /** @since 3.14 */ int NotAccessibleType = TypeRelated + 1450; /** @since 3.14 */ @@ -2005,29 +2029,29 @@ void setSourceStart(int sourceStart); int UnlikelyEqualsArgumentType = 1201; /* Local-Variable Type Inference */ - /** @since 3.15 */ + /** @since 3.13 */ int VarLocalMultipleDeclarators = Syntax + 1500; // ''var'' is not allowed in a compound declaration - /** @since 3.15 */ + /** @since 3.13 */ int VarLocalCannotBeArray = Syntax + 1501; // ''var'' is not allowed as an element type of an array - /** @since 3.15 */ + /** @since 3.13 */ int VarLocalReferencesItself = Syntax + 1502; // Declaration using ''var'' may not contin references to itself - /** @since 3.15 */ + /** @since 3.13 */ int VarLocalWithoutInitizalier = Syntax + 1503; // Cannot use ''var'' on variable without initializer - /** @since 3.15 */ + /** @since 3.13 */ int VarLocalInitializedToNull = TypeRelated + 1504; // Variable initialized to ''null'' needs an explicit target-type - /** @since 3.15 */ + /** @since 3.13 */ int VarLocalInitializedToVoid = TypeRelated + 1505; // Variable initializer is ''void'' -- cannot infer variable type - /** @since 3.15 */ + /** @since 3.13 */ int VarLocalCannotBeArrayInitalizers = TypeRelated + 1506; // Array initializer needs an explicit target-type - /** @since 3.15 */ + /** @since 3.13 */ int VarLocalCannotBeLambda = TypeRelated + 1507; // Lambda expression needs an explicit target-type - /** @since 3.15 */ + /** @since 3.13 */ int VarLocalCannotBeMethodReference = TypeRelated + 1508; // Method reference needs an explicit target-type - /** @since 3.15 */ + /** @since 3.13 */ int VarIsReserved = Syntax + 1509; // ''var'' is not a valid type name - /** @since 3.15 */ + /** @since 3.13 */ int VarIsReservedInFuture = Syntax + 1510; // ''var'' should not be used as an type name, since it is a reserved word from source level 10 on - /** @since 3.15 */ + /** @since 3.13 */ int VarIsNotAllowedHere = Syntax + 1511; // ''var'' is not allowed here } diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ASTNode.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ASTNode.java index ad9daa3b07..aa6e653af9 100644 --- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ASTNode.java +++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ASTNode.java @@ -745,7 +745,7 @@ public abstract class ASTNode implements TypeConstants, TypeIds { type.tagBits |= (TagBits.AnnotationResolved | TagBits.DeprecatedAnnotationResolved); if (length > 0) { annotations = new AnnotationBinding[length]; - type.setAnnotations(annotations); + type.setAnnotations(annotations, false); } break; case Binding.METHOD : @@ -754,7 +754,7 @@ public abstract class ASTNode implements TypeConstants, TypeIds { method.tagBits |= (TagBits.AnnotationResolved | TagBits.DeprecatedAnnotationResolved); if (length > 0) { annotations = new AnnotationBinding[length]; - method.setAnnotations(annotations); + method.setAnnotations(annotations, false); } break; case Binding.FIELD : @@ -763,7 +763,7 @@ public abstract class ASTNode implements TypeConstants, TypeIds { field.tagBits |= (TagBits.AnnotationResolved | TagBits.DeprecatedAnnotationResolved); if (length > 0) { annotations = new AnnotationBinding[length]; - field.setAnnotations(annotations); + field.setAnnotations(annotations, false); } break; case Binding.LOCAL : @@ -772,7 +772,7 @@ public abstract class ASTNode implements TypeConstants, TypeIds { local.tagBits |= (TagBits.AnnotationResolved | TagBits.DeprecatedAnnotationResolved); if (length > 0) { annotations = new AnnotationBinding[length]; - local.setAnnotations(annotations, scope); + local.setAnnotations(annotations, scope, false); } break; case Binding.TYPE_PARAMETER : @@ -786,7 +786,7 @@ public abstract class ASTNode implements TypeConstants, TypeIds { module.tagBits |= (TagBits.AnnotationResolved | TagBits.DeprecatedAnnotationResolved); if (length > 0) { annotations = new AnnotationBinding[length]; - module.setAnnotations(annotations, scope); + module.setAnnotations(annotations, scope, false); } break; default : @@ -1092,7 +1092,7 @@ public abstract class ASTNode implements TypeConstants, TypeIds { } if (newLength != length) { System.arraycopy(recipientAnnotations, 0, recipientAnnotations = new AnnotationBinding[newLength], 0, newLength); - recipient.setAnnotations(recipientAnnotations, scope); + recipient.setAnnotations(recipientAnnotations, scope, false); } } } diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Annotation.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Annotation.java index dcb04acf14..164559faac 100644 --- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Annotation.java +++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Annotation.java @@ -888,12 +888,15 @@ public abstract class Annotation extends Expression { pairs[i].resolveTypeExpecting(scope, null); // resilient } } -// if (scope.compilerOptions().storeAnnotations) this.compilerAnnotation = scope.environment().createAnnotation((ReferenceBinding) this.resolvedType, computeElementValuePairs()); // recognize standard annotations ? long tagBits = detectStandardAnnotation(scope, annotationType, valueAttribute); int defaultNullness = (int)(tagBits & Binding.NullnessDefaultMASK); tagBits &= ~Binding.NullnessDefaultMASK; + CompilerOptions compilerOptions = scope.compilerOptions(); + if ((tagBits & TagBits.AnnotationDeprecated) != 0 && compilerOptions.complianceLevel >= ClassFileConstants.JDK9 && !compilerOptions.storeAnnotations) { + this.recipient.setAnnotations(new AnnotationBinding[] {this.compilerAnnotation}, true); // force storing enhanced deprecation + } // record annotation positions in the compilation result scope.referenceCompilationUnit().recordSuppressWarnings(IrritantSet.NLS, null, this.sourceStart, this.declarationSourceEnd, scope.referenceContext()); @@ -918,7 +921,7 @@ public abstract class Annotation extends Expression { } else { start = typeDeclaration.declarationSourceStart; } - recordSuppressWarnings(scope, start, typeDeclaration.declarationSourceEnd, scope.compilerOptions().suppressWarnings); + recordSuppressWarnings(scope, start, typeDeclaration.declarationSourceEnd, compilerOptions.suppressWarnings); } sourceType.defaultNullness |= defaultNullness; break; @@ -928,7 +931,7 @@ public abstract class Annotation extends Expression { if ((tagBits & TagBits.AnnotationSuppressWarnings) != 0) { sourceType = (SourceTypeBinding) sourceMethod.declaringClass; AbstractMethodDeclaration methodDeclaration = sourceType.scope.referenceContext.declarationOf(sourceMethod); - recordSuppressWarnings(scope, methodDeclaration.declarationSourceStart, methodDeclaration.declarationSourceEnd, scope.compilerOptions().suppressWarnings); + recordSuppressWarnings(scope, methodDeclaration.declarationSourceStart, methodDeclaration.declarationSourceEnd, compilerOptions.suppressWarnings); } long nullBits = sourceMethod.tagBits & TagBits.AnnotationNullMASK; if (nullBits == TagBits.AnnotationNullMASK) { @@ -936,7 +939,7 @@ public abstract class Annotation extends Expression { sourceMethod.tagBits &= ~TagBits.AnnotationNullMASK; // avoid secondary problems } if (nullBits != 0 && sourceMethod.isConstructor()) { - if (scope.compilerOptions().sourceLevel >= ClassFileConstants.JDK1_8) + if (compilerOptions.sourceLevel >= ClassFileConstants.JDK1_8) scope.problemReporter().nullAnnotationUnsupportedLocation(this); // for declaration annotations the inapplicability will be reported below sourceMethod.tagBits &= ~TagBits.AnnotationNullMASK; @@ -949,7 +952,7 @@ public abstract class Annotation extends Expression { if ((tagBits & TagBits.AnnotationSuppressWarnings) != 0) { sourceType = (SourceTypeBinding) sourceField.declaringClass; FieldDeclaration fieldDeclaration = sourceType.scope.referenceContext.declarationOf(sourceField); - recordSuppressWarnings(scope, fieldDeclaration.declarationSourceStart, fieldDeclaration.declarationSourceEnd, scope.compilerOptions().suppressWarnings); + recordSuppressWarnings(scope, fieldDeclaration.declarationSourceStart, fieldDeclaration.declarationSourceEnd, compilerOptions.suppressWarnings); } if (defaultNullness != 0) { sourceType = (SourceTypeBinding) sourceField.declaringClass; @@ -976,7 +979,7 @@ public abstract class Annotation extends Expression { } if ((tagBits & TagBits.AnnotationSuppressWarnings) != 0) { LocalDeclaration localDeclaration = variable.declaration; - recordSuppressWarnings(scope, localDeclaration.declarationSourceStart, localDeclaration.declarationSourceEnd, scope.compilerOptions().suppressWarnings); + recordSuppressWarnings(scope, localDeclaration.declarationSourceStart, localDeclaration.declarationSourceEnd, compilerOptions.suppressWarnings); } // note: defaultNullness for local declarations has been already been handled earlier by handleNonNullByDefault() break; diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/TypeReference.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/TypeReference.java index 4aafc6db9b..d3b6e0c6b4 100644 --- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/TypeReference.java +++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/TypeReference.java @@ -624,8 +624,8 @@ public TypeBinding resolveTypeArgument(ClassScope classScope, ReferenceBinding g boolean pauseHierarchyCheck = false; try { if (ref.isHierarchyBeingConnected()) { + pauseHierarchyCheck = (ref.tagBits & TagBits.PauseHierarchyCheck) == 0; ref.tagBits |= TagBits.PauseHierarchyCheck; - pauseHierarchyCheck = true; } return resolveType(classScope, Binding.DefaultLocationTypeArgument); } finally { diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/classfmt/AnnotationInfo.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/classfmt/AnnotationInfo.java index fd258d4ce5..1b053c0f26 100644 --- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/classfmt/AnnotationInfo.java +++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/classfmt/AnnotationInfo.java @@ -163,6 +163,10 @@ public IBinaryElementValuePair[] getElementValuePairs() { public char[] getTypeName() { return this.typename; } +@Override +public boolean isDeprecatedAnnotation() { + return (this.standardAnnotationTagBits & (TagBits.AnnotationDeprecated | TagBits.AnnotationTerminallyDeprecated)) != 0; +} void initialize() { if (this.pairs == null) decodeAnnotation(); diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/classfmt/AnnotationMethodInfo.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/classfmt/AnnotationMethodInfo.java index bba584ca6e..de19990f49 100644 --- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/classfmt/AnnotationMethodInfo.java +++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/classfmt/AnnotationMethodInfo.java @@ -16,8 +16,8 @@ import org.eclipse.jdt.internal.compiler.codegen.AttributeNamesConstants; public class AnnotationMethodInfo extends MethodInfo { protected Object defaultValue = null; -public static MethodInfo createAnnotationMethod(byte classFileBytes[], int offsets[], int offset) { - MethodInfo methodInfo = new MethodInfo(classFileBytes, offsets, offset); +public static MethodInfo createAnnotationMethod(byte classFileBytes[], int offsets[], int offset, long version) { + MethodInfo methodInfo = new MethodInfo(classFileBytes, offsets, offset, version); int attributesCount = methodInfo.u2At(6); int readOffset = 8; AnnotationInfo[] annotations = null; @@ -98,7 +98,7 @@ public static MethodInfo createAnnotationMethod(byte classFileBytes[], int offse } AnnotationMethodInfo(MethodInfo methodInfo, Object defaultValue) { - super(methodInfo.reference, methodInfo.constantPoolOffsets, methodInfo.structOffset); + super(methodInfo.reference, methodInfo.constantPoolOffsets, methodInfo.structOffset, methodInfo.version); this.defaultValue = defaultValue; this.accessFlags = methodInfo.accessFlags; diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/classfmt/ClassFileReader.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/classfmt/ClassFileReader.java index 8f81410b7c..d625594ddf 100644 --- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/classfmt/ClassFileReader.java +++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/classfmt/ClassFileReader.java @@ -312,7 +312,7 @@ public ClassFileReader(byte[] classFileBytes, char[] fileName, boolean fullyInit FieldInfo field; this.fields = new FieldInfo[this.fieldsCount]; for (int i = 0; i < this.fieldsCount; i++) { - field = FieldInfo.createField(this.reference, this.constantPoolOffsets, readOffset); + field = FieldInfo.createField(this.reference, this.constantPoolOffsets, readOffset, this.version); this.fields[i] = field; readOffset += field.sizeInBytes(); } @@ -325,8 +325,8 @@ public ClassFileReader(byte[] classFileBytes, char[] fileName, boolean fullyInit boolean isAnnotationType = (this.accessFlags & ClassFileConstants.AccAnnotation) != 0; for (int i = 0; i < this.methodsCount; i++) { this.methods[i] = isAnnotationType - ? AnnotationMethodInfo.createAnnotationMethod(this.reference, this.constantPoolOffsets, readOffset) - : MethodInfo.createMethod(this.reference, this.constantPoolOffsets, readOffset); + ? AnnotationMethodInfo.createAnnotationMethod(this.reference, this.constantPoolOffsets, readOffset, this.version) + : MethodInfo.createMethod(this.reference, this.constantPoolOffsets, readOffset, this.version); readOffset += this.methods[i].sizeInBytes(); } } @@ -486,11 +486,12 @@ private void decodeAnnotations(int offset, boolean runtimeVisible) { long standardTagBits = newInfo.standardAnnotationTagBits; if (standardTagBits != 0) { this.tagBits |= standardTagBits; - } else { - if (newInfos == null) - newInfos = new AnnotationInfo[numberOfAnnotations - i]; - newInfos[newInfoCount++] = newInfo; + if (this.version < ClassFileConstants.JDK9 || (standardTagBits & TagBits.AnnotationDeprecated) == 0) + continue; } + if (newInfos == null) + newInfos = new AnnotationInfo[numberOfAnnotations - i]; + newInfos[newInfoCount++] = newInfo; } if (newInfos == null) return; // nothing to record in this.annotations diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/classfmt/FieldInfo.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/classfmt/FieldInfo.java index 039f3a454b..462c00fe54 100644 --- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/classfmt/FieldInfo.java +++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/classfmt/FieldInfo.java @@ -18,6 +18,7 @@ import org.eclipse.jdt.internal.compiler.env.IBinaryAnnotation; import org.eclipse.jdt.internal.compiler.env.IBinaryField; import org.eclipse.jdt.internal.compiler.env.IBinaryTypeAnnotation; import org.eclipse.jdt.internal.compiler.impl.*; +import org.eclipse.jdt.internal.compiler.lookup.TagBits; import org.eclipse.jdt.internal.compiler.lookup.TypeIds; import org.eclipse.jdt.internal.compiler.util.Util; @@ -32,9 +33,10 @@ public class FieldInfo extends ClassFileStruct implements IBinaryField, Comparab protected int signatureUtf8Offset; protected long tagBits; protected Object wrappedConstantValue; + protected long version; -public static FieldInfo createField(byte classFileBytes[], int offsets[], int offset) { - FieldInfo fieldInfo = new FieldInfo(classFileBytes, offsets, offset); +public static FieldInfo createField(byte classFileBytes[], int offsets[], int offset, long version) { + FieldInfo fieldInfo = new FieldInfo(classFileBytes, offsets, offset, version); int attributesCount = fieldInfo.u2At(6); int readOffset = 8; @@ -100,11 +102,13 @@ public static FieldInfo createField(byte classFileBytes[], int offsets[], int of * @param classFileBytes byte[] * @param offsets int[] * @param offset int + * @param version class file version */ -protected FieldInfo (byte classFileBytes[], int offsets[], int offset) { +protected FieldInfo (byte classFileBytes[], int offsets[], int offset, long version) { super(classFileBytes, offsets, offset); this.accessFlags = -1; this.signatureUtf8Offset = -1; + this.version = version; } private AnnotationInfo[] decodeAnnotations(int offset, boolean runtimeVisible) { int numberOfAnnotations = u2At(offset + 6); @@ -120,11 +124,12 @@ private AnnotationInfo[] decodeAnnotations(int offset, boolean runtimeVisible) { long standardTagBits = newInfo.standardAnnotationTagBits; if (standardTagBits != 0) { this.tagBits |= standardTagBits; - } else { - if (newInfos == null) - newInfos = new AnnotationInfo[numberOfAnnotations - i]; - newInfos[newInfoCount++] = newInfo; + if (this.version < ClassFileConstants.JDK9 || (standardTagBits & TagBits.AnnotationDeprecated) == 0) + continue; } + if (newInfos == null) + newInfos = new AnnotationInfo[numberOfAnnotations - i]; + newInfos[newInfoCount++] = newInfo; } if (newInfos != null) { if (newInfoCount != newInfos.length) diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/classfmt/FieldInfoWithAnnotation.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/classfmt/FieldInfoWithAnnotation.java index c2190cdafb..c5470baf27 100644 --- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/classfmt/FieldInfoWithAnnotation.java +++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/classfmt/FieldInfoWithAnnotation.java @@ -16,7 +16,7 @@ public class FieldInfoWithAnnotation extends FieldInfo { private AnnotationInfo[] annotations; FieldInfoWithAnnotation(FieldInfo info, AnnotationInfo[] annos) { - super(info.reference, info.constantPoolOffsets, info.structOffset); + super(info.reference, info.constantPoolOffsets, info.structOffset, info.version); this.accessFlags = info.accessFlags; this.attributeBytes = info.attributeBytes; this.constant = info.constant; diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/classfmt/MethodInfo.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/classfmt/MethodInfo.java index bb0ad5424a..d08093247d 100644 --- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/classfmt/MethodInfo.java +++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/classfmt/MethodInfo.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2016 IBM Corporation and others. + * Copyright (c) 2000, 2018 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 @@ -20,6 +20,7 @@ import org.eclipse.jdt.internal.compiler.codegen.ConstantPool; import org.eclipse.jdt.internal.compiler.env.IBinaryAnnotation; import org.eclipse.jdt.internal.compiler.env.IBinaryMethod; import org.eclipse.jdt.internal.compiler.env.IBinaryTypeAnnotation; +import org.eclipse.jdt.internal.compiler.lookup.TagBits; @SuppressWarnings("rawtypes") public class MethodInfo extends ClassFileStruct implements IBinaryMethod, Comparable { @@ -35,9 +36,10 @@ public class MethodInfo extends ClassFileStruct implements IBinaryMethod, Compar protected int signatureUtf8Offset; protected long tagBits; protected char[][] argumentNames; + protected long version; -public static MethodInfo createMethod(byte classFileBytes[], int offsets[], int offset) { - MethodInfo methodInfo = new MethodInfo(classFileBytes, offsets, offset); +public static MethodInfo createMethod(byte classFileBytes[], int offsets[], int offset, long version) { + MethodInfo methodInfo = new MethodInfo(classFileBytes, offsets, offset, version); int attributesCount = methodInfo.u2At(6); int readOffset = 8; AnnotationInfo[] annotations = null; @@ -146,22 +148,25 @@ static AnnotationInfo[] decodeMethodAnnotations(int offset, boolean runtimeVisib if (numberOfAnnotations > 0) { AnnotationInfo[] annos = decodeAnnotations(offset + 8, runtimeVisible, numberOfAnnotations, methodInfo); if (runtimeVisible){ - int numStandardAnnotations = 0; + int numRetainedAnnotations = 0; for( int i=0; i<numberOfAnnotations; i++ ){ long standardAnnoTagBits = annos[i].standardAnnotationTagBits; methodInfo.tagBits |= standardAnnoTagBits; if(standardAnnoTagBits != 0){ - annos[i] = null; - numStandardAnnotations ++; + if (methodInfo.version < ClassFileConstants.JDK9 || (standardAnnoTagBits & TagBits.AnnotationDeprecated) == 0) { // must retain enhanced deprecation + annos[i] = null; + continue; + } } + numRetainedAnnotations++; } - if( numStandardAnnotations != 0 ){ - if( numStandardAnnotations == numberOfAnnotations ) + if(numRetainedAnnotations != numberOfAnnotations){ + if(numRetainedAnnotations == 0) return null; // need to resize - AnnotationInfo[] temp = new AnnotationInfo[numberOfAnnotations - numStandardAnnotations ]; + AnnotationInfo[] temp = new AnnotationInfo[numRetainedAnnotations]; int tmpIndex = 0; for (int i = 0; i < numberOfAnnotations; i++) if (annos[i] != null) @@ -213,11 +218,13 @@ static AnnotationInfo[][] decodeParamAnnotations(int offset, boolean runtimeVisi * @param classFileBytes byte[] * @param offsets int[] * @param offset int + * @param version class file version */ -protected MethodInfo (byte classFileBytes[], int offsets[], int offset) { +protected MethodInfo (byte classFileBytes[], int offsets[], int offset, long version) { super(classFileBytes, offsets, offset); this.accessFlags = -1; this.signatureUtf8Offset = -1; + this.version = version; } public int compareTo(Object o) { MethodInfo otherMethod = (MethodInfo) o; diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/classfmt/MethodInfoWithAnnotations.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/classfmt/MethodInfoWithAnnotations.java index c2621f470c..3e166a2a7b 100644 --- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/classfmt/MethodInfoWithAnnotations.java +++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/classfmt/MethodInfoWithAnnotations.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2005, 2016 BEA Systems, Inc. + * Copyright (c) 2005, 2018 BEA Systems, Inc 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 @@ -16,7 +16,7 @@ public class MethodInfoWithAnnotations extends MethodInfo { protected AnnotationInfo[] annotations; MethodInfoWithAnnotations(MethodInfo methodInfo, AnnotationInfo[] annotations) { - super(methodInfo.reference, methodInfo.constantPoolOffsets, methodInfo.structOffset); + super(methodInfo.reference, methodInfo.constantPoolOffsets, methodInfo.structOffset, methodInfo.version); this.annotations = annotations; this.accessFlags = methodInfo.accessFlags; diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/env/AutomaticModuleNaming.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/env/AutomaticModuleNaming.java index 765c0a149e..bb1c9d1a32 100644 --- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/env/AutomaticModuleNaming.java +++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/env/AutomaticModuleNaming.java @@ -95,7 +95,7 @@ public class AutomaticModuleNaming { dashLoop: for (index = start; index < end - 1; index++) { if (name.charAt(index) == '-' && name.charAt(index + 1) >= '0' && name.charAt(index + 1) <= '9') { for (int index2 = index + 2; index2 < end; index2++) { - final char c = name.charAt(index2 + 1); + final char c = name.charAt(index2); if (c == '.') { break; } diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/env/IBinaryAnnotation.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/env/IBinaryAnnotation.java index 36b1a17638..eae58956bc 100644 --- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/env/IBinaryAnnotation.java +++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/env/IBinaryAnnotation.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2005, 2007 BEA Systems, Inc. + * Copyright (c) 2005, 2018 BEA Systems, Inc 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 @@ -31,5 +31,12 @@ IBinaryElementValuePair[] getElementValuePairs(); default boolean isExternalAnnotation() { return false; } + +/** + * @return true, if this is a @Deprecated annotation. + */ +default boolean isDeprecatedAnnotation() { + return false; +} } diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/env/IUpdatableModule.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/env/IUpdatableModule.java index 1a2d237a37..f851a342cf 100644 --- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/env/IUpdatableModule.java +++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/env/IUpdatableModule.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2017 GK Software AG, and others. + * Copyright (c) 2017, 2018 GK Software AG, 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 @@ -15,6 +15,7 @@ import java.util.Collections; import java.util.List; import java.util.function.Consumer; +import org.eclipse.jdt.core.compiler.CharOperation; import org.eclipse.jdt.internal.compiler.util.SimpleSetOfCharArray; /** @@ -29,6 +30,88 @@ public interface IUpdatableModule { */ enum UpdateKind { MODULE, PACKAGE } + class AddExports implements Consumer<IUpdatableModule> { + + char[] name; + char[][] targets; + public AddExports(char[] pkgName, char[][] targets) { + this.name = pkgName; + this.targets = targets; + } + @Override + public void accept(IUpdatableModule t) { + // TODO Auto-generated method stub + t.addExports(this.name, this.targets); + } + + public char[] getName() { + return this.name; + } + + public char[][] getTargetModules() { + return this.targets; + } + + public UpdateKind getKind() { + return UpdateKind.PACKAGE; + } + @Override + public boolean equals(Object other) { + if (this == other) return true; + if (!(other instanceof AddExports)) return false; + AddExports pu = (AddExports) other; + + if (!CharOperation.equals(this.name, pu.name)) + return false; + if (!CharOperation.equals(this.targets, pu.targets)) + return false; + return true; + } + @Override + public int hashCode() { + int hash = CharOperation.hashCode(this.name); + if (this.targets != null) { + for (int i = 0; i < this.targets.length; i++) { + hash += 17 * CharOperation.hashCode(this.targets[i]); + } + } + return hash; + } + } + + class AddReads implements Consumer<IUpdatableModule> { + + char[] targetModule; + + public AddReads(char[] target) { + this.targetModule = target; + } + @Override + public void accept(IUpdatableModule t) { + // TODO Auto-generated method stub + t.addReads(this.targetModule); + } + + public char[] getTarget() { + return this.targetModule; + } + + public UpdateKind getKind() { + return UpdateKind.MODULE; + } + + @Override + public boolean equals(Object other) { + if (this == other) return true; + if (!(other instanceof AddReads)) return false; + AddReads mu = (AddReads) other; + return CharOperation.equals(this.targetModule, mu.targetModule); + } + @Override + public int hashCode() { + return CharOperation.hashCode(this.targetModule); + } + } /** Structure for update operations, sorted by {@link UpdateKind}. */ class UpdatesByKind { List<Consumer<IUpdatableModule>> moduleUpdates = Collections.emptyList(); diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/BinaryTypeBinding.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/BinaryTypeBinding.java index fccd20643c..d9c4ec3347 100644 --- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/BinaryTypeBinding.java +++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/BinaryTypeBinding.java @@ -48,10 +48,12 @@ import org.eclipse.jdt.core.compiler.CharOperation; import org.eclipse.jdt.internal.compiler.ast.Annotation; import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants; import org.eclipse.jdt.internal.compiler.classfmt.ExternalAnnotationProvider.IMethodAnnotationWalker; +import org.eclipse.jdt.internal.compiler.classfmt.MethodInfoWithAnnotations; import org.eclipse.jdt.internal.compiler.classfmt.NonNullDefaultAwareTypeAnnotationWalker; import org.eclipse.jdt.internal.compiler.classfmt.TypeAnnotationWalker; import org.eclipse.jdt.internal.compiler.codegen.ConstantPool; import org.eclipse.jdt.internal.compiler.env.*; +import org.eclipse.jdt.internal.compiler.impl.BooleanConstant; import org.eclipse.jdt.internal.compiler.impl.CompilerOptions; import org.eclipse.jdt.internal.compiler.impl.Constant; import org.eclipse.jdt.internal.compiler.problem.AbortCompilation; @@ -565,8 +567,27 @@ void cachePartsFrom(IBinaryType binaryType, boolean needFieldsAndMethods) { } } } - if (this.environment.globalOptions.storeAnnotations) - setAnnotations(createAnnotations(binaryType.getAnnotations(), this.environment, missingTypeNames)); + if (this.environment.globalOptions.storeAnnotations) { + setAnnotations(createAnnotations(binaryType.getAnnotations(), this.environment, missingTypeNames), false); + } else if (sourceLevel >= ClassFileConstants.JDK9 && isDeprecated() && binaryType.getAnnotations() != null) { + // prior to Java 9 all standard annotations were marker annotations, not needing to be stored, + // but since Java 9 we need more information from the @Deprecated annotation: + for (IBinaryAnnotation annotation : binaryType.getAnnotations()) { + if (annotation.isDeprecatedAnnotation()) { + AnnotationBinding[] annotationBindings = createAnnotations(new IBinaryAnnotation[] { annotation }, this.environment, missingTypeNames); + setAnnotations(annotationBindings, true); // force storing + for (ElementValuePair elementValuePair : annotationBindings[0].getElementValuePairs()) { + if (CharOperation.equals(elementValuePair.name, TypeConstants.FOR_REMOVAL)) { + if (elementValuePair.value instanceof BooleanConstant && ((BooleanConstant) elementValuePair.value).booleanValue()) { + this.tagBits |= TagBits.AnnotationTerminallyDeprecated; + markImplicitTerminalDeprecation(this); + } + } + } + break; + } + } + } if (this.isAnnotationType()) scanTypeForContainerAnnotation(binaryType, missingTypeNames); } finally { @@ -577,6 +598,21 @@ void cachePartsFrom(IBinaryType binaryType, boolean needFieldsAndMethods) { this.methods = Binding.NO_METHODS; } } +void markImplicitTerminalDeprecation(ReferenceBinding type) { + for (ReferenceBinding member : type.memberTypes()) { + member.tagBits |= TagBits.AnnotationTerminallyDeprecated; + markImplicitTerminalDeprecation(member); + } + MethodBinding[] methodsOfType = type.unResolvedMethods(); + if (methodsOfType != null) + for (MethodBinding methodBinding : methodsOfType) + methodBinding.tagBits |= TagBits.AnnotationTerminallyDeprecated; + + FieldBinding[] fieldsOfType = type.unResolvedFields(); + if (fieldsOfType != null) + for (FieldBinding fieldBinding : fieldsOfType) + fieldBinding.tagBits |= TagBits.AnnotationTerminallyDeprecated; +} /* When creating a method we need to pass in any default 'nullness' from a @NNBD immediately on this method. */ private ITypeAnnotationWalker getTypeAnnotationWalker(IBinaryTypeAnnotation[] annotations, int nullness) { @@ -638,10 +674,16 @@ private void createFields(IBinaryField[] iFields, IBinaryType binaryType, long s binaryField.getModifiers() | ExtraCompilerModifiers.AccUnresolved, this, binaryField.getConstant()); + boolean forceStoreAnnotations = !this.environment.globalOptions.storeAnnotations + && (this.environment.globalOptions.sourceLevel >= ClassFileConstants.JDK9 + && binaryField.getAnnotations() != null + && (binaryField.getTagBits() & TagBits.AnnotationDeprecated) != 0); if (firstAnnotatedFieldIndex < 0 - && this.environment.globalOptions.storeAnnotations + && (this.environment.globalOptions.storeAnnotations || forceStoreAnnotations) && binaryField.getAnnotations() != null) { firstAnnotatedFieldIndex = i; + if (forceStoreAnnotations) + storedAnnotations(true, true); // for Java 9 @Deprecated we need to force storing annotations } field.id = i; // ordinal if (use15specifics) @@ -657,7 +699,7 @@ private void createFields(IBinaryField[] iFields, IBinaryType binaryType, long s if (firstAnnotatedFieldIndex >= 0) { for (int i = firstAnnotatedFieldIndex; i <size; i++) { IBinaryField binaryField = iFields[i]; - this.fields[i].setAnnotations(createAnnotations(binaryField.getAnnotations(), this.environment, missingTypeNames)); + this.fields[i].setAnnotations(createAnnotations(binaryField.getAnnotations(), this.environment, missingTypeNames), false); } } } @@ -842,7 +884,13 @@ private MethodBinding createMethod(IBinaryMethod method, IBinaryType binaryType, result.receiver = this.environment.createAnnotatedType(this, createAnnotations(receiverAnnotations, this.environment, missingTypeNames)); } - if (this.environment.globalOptions.storeAnnotations) { + boolean forceStoreAnnotations = !this.environment.globalOptions.storeAnnotations + && (this.environment.globalOptions.sourceLevel >= ClassFileConstants.JDK9 + && method instanceof MethodInfoWithAnnotations + && (method.getTagBits() & TagBits.AnnotationDeprecated) != 0); + if (this.environment.globalOptions.storeAnnotations || forceStoreAnnotations) { + if (forceStoreAnnotations) + storedAnnotations(true, true); // for Java 9 @Deprecated we need to force storing annotations IBinaryAnnotation[] annotations = method.getAnnotations(); if (method.isConstructor()) { IBinaryAnnotation[] tAnnotations = walker.toMethodReturn().getAnnotationsAtCursor(this.id, false); @@ -1549,13 +1597,13 @@ public void tagAsHavingDefectiveContainerType() { this.containerAnnotationType = new ProblemReferenceBinding(this.containerAnnotationType.compoundName, this.containerAnnotationType, ProblemReasons.DefectiveContainerAnnotationType); } -SimpleLookupTable storedAnnotations(boolean forceInitialize) { +SimpleLookupTable storedAnnotations(boolean forceInitialize, boolean forceStore) { if (!isPrototype()) - return this.prototype.storedAnnotations(forceInitialize); + return this.prototype.storedAnnotations(forceInitialize, forceStore); if (forceInitialize && this.storedAnnotations == null) { - if (!this.environment.globalOptions.storeAnnotations) + if (!this.environment.globalOptions.storeAnnotations && !forceStore) return null; // not supported during this compile this.storedAnnotations = new SimpleLookupTable(3); } diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/Binding.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/Binding.java index cbb24760e6..48e95fcfab 100644 --- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/Binding.java +++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/Binding.java @@ -191,10 +191,10 @@ public abstract class Binding { public AnnotationBinding[] getAnnotations() { return Binding.NO_ANNOTATIONS; } - public void setAnnotations(AnnotationBinding[] annotations, Scope scope) { - setAnnotations(annotations); + public void setAnnotations(AnnotationBinding[] annotations, Scope scope, boolean forceStore) { + setAnnotations(annotations, forceStore); } - public void setAnnotations(AnnotationBinding[] annotations) { + public void setAnnotations(AnnotationBinding[] annotations, boolean forceStore) { // Left to subtypes. } } diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/FieldBinding.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/FieldBinding.java index 7c6d065b6f..1396fa991b 100644 --- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/FieldBinding.java +++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/FieldBinding.java @@ -46,7 +46,7 @@ public FieldBinding(FieldBinding initialFieldBinding, ReferenceBinding declaring super(initialFieldBinding.name, initialFieldBinding.type, initialFieldBinding.modifiers, initialFieldBinding.constant()); this.declaringClass = declaringClass; this.id = initialFieldBinding.id; - setAnnotations(initialFieldBinding.getAnnotations()); + setAnnotations(initialFieldBinding.getAnnotations(), false); } /* API * Answer the receiver's binding type from Binding.BindingID. @@ -411,8 +411,8 @@ public final int kind() { public FieldBinding original() { return this; } -public void setAnnotations(AnnotationBinding[] annotations) { - this.declaringClass.storeAnnotations(this, annotations); +public void setAnnotations(AnnotationBinding[] annotations, boolean forceStore) { + this.declaringClass.storeAnnotations(this, annotations, forceStore); } public FieldDeclaration sourceField() { SourceTypeBinding sourceType; diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/InferenceContext18.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/InferenceContext18.java index e7411e1b74..6b4e58513a 100644 --- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/InferenceContext18.java +++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/InferenceContext18.java @@ -1648,9 +1648,12 @@ public class InferenceContext18 { * unless the given candidate is tolerable to be compatible with buggy javac. */ public MethodBinding getReturnProblemMethodIfNeeded(TypeBinding expectedType, MethodBinding method) { - if (InferenceContext18.SIMULATE_BUG_JDK_8026527 && expectedType != null + if (InferenceContext18.SIMULATE_BUG_JDK_8026527 && expectedType != null + && !(method.original() instanceof SyntheticFactoryMethodBinding) && (method.returnType instanceof ReferenceBinding || method.returnType instanceof ArrayBinding)) { - if (method.returnType.erasure().isCompatibleWith(expectedType)) + if (!expectedType.isProperType(true)) + return null; // not ready + if (this.environment.convertToRawType(method.returnType.erasure(), false).isCompatibleWith(expectedType)) return method; // don't count as problem. } /* We used to check if expected type is null and if so return method, but that is wrong - it injects an incompatible method into overload resolution. diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/LocalVariableBinding.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/LocalVariableBinding.java index 62f2e19a71..82bb67e6d5 100644 --- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/LocalVariableBinding.java +++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/LocalVariableBinding.java @@ -252,14 +252,14 @@ public class LocalVariableBinding extends VariableBinding { this.initializationCount++; } - public void setAnnotations(AnnotationBinding[] annotations, Scope scope) { + public void setAnnotations(AnnotationBinding[] annotations, Scope scope, boolean forceStore) { // note: we don's use this.declaringScope because we might be called before Scope.addLocalVariable(this) // which is where this.declaringScope is set. if (scope == null) return; SourceTypeBinding sourceType = scope.enclosingSourceType(); if (sourceType != null) - sourceType.storeAnnotations(this, annotations); + sourceType.storeAnnotations(this, annotations, forceStore); } public void resetInitializations() { diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/MethodBinding.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/MethodBinding.java index ba7af95b23..a41546022f 100644 --- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/MethodBinding.java +++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/MethodBinding.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2017 IBM Corporation and others. + * Copyright (c) 2000, 2018 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 @@ -981,8 +981,8 @@ final public AnnotationBinding[] getTypeAnnotations() { public void setTypeAnnotations(AnnotationBinding[] annotations) { this.typeAnnotations = annotations; } -public void setAnnotations(AnnotationBinding[] annotations) { - this.declaringClass.storeAnnotations(this, annotations); +public void setAnnotations(AnnotationBinding[] annotations, boolean forceStore) { + this.declaringClass.storeAnnotations(this, annotations, forceStore); } public void setAnnotations(AnnotationBinding[] annotations, AnnotationBinding[][] parameterAnnotations, Object defaultValue, LookupEnvironment optionalEnv) { this.declaringClass.storeAnnotationHolder(this, AnnotationHolder.storeAnnotations(annotations, parameterAnnotations, defaultValue, optionalEnv)); diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ReferenceBinding.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ReferenceBinding.java index d71be819cb..6ab74ba2ad 100644 --- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ReferenceBinding.java +++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ReferenceBinding.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2017 IBM Corporation and others. + * Copyright (c) 2000, 2018 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 @@ -1702,7 +1702,7 @@ protected void appendNullAnnotation(StringBuffer nameBuffer, CompilerOptions opt } public AnnotationHolder retrieveAnnotationHolder(Binding binding, boolean forceInitialization) { - SimpleLookupTable store = storedAnnotations(forceInitialization); + SimpleLookupTable store = storedAnnotations(forceInitialization, false); return store == null ? null : (AnnotationHolder) store.get(binding); } @@ -1711,8 +1711,8 @@ AnnotationBinding[] retrieveAnnotations(Binding binding) { return holder == null ? Binding.NO_ANNOTATIONS : holder.getAnnotations(); } -public void setAnnotations(AnnotationBinding[] annotations) { - storeAnnotations(this, annotations); +public void setAnnotations(AnnotationBinding[] annotations, boolean forceStore) { + storeAnnotations(this, annotations, forceStore); } public void setContainerAnnotationType(ReferenceBinding value) { // Leave this to subclasses @@ -1839,25 +1839,25 @@ public char[] sourceName() { void storeAnnotationHolder(Binding binding, AnnotationHolder holder) { if (holder == null) { - SimpleLookupTable store = storedAnnotations(false); + SimpleLookupTable store = storedAnnotations(false, false); if (store != null) store.removeKey(binding); } else { - SimpleLookupTable store = storedAnnotations(true); + SimpleLookupTable store = storedAnnotations(true, false); if (store != null) store.put(binding, holder); } } -void storeAnnotations(Binding binding, AnnotationBinding[] annotations) { +void storeAnnotations(Binding binding, AnnotationBinding[] annotations, boolean forceStore) { AnnotationHolder holder = null; if (annotations == null || annotations.length == 0) { - SimpleLookupTable store = storedAnnotations(false); + SimpleLookupTable store = storedAnnotations(false, forceStore); if (store != null) holder = (AnnotationHolder) store.get(binding); if (holder == null) return; // nothing to delete } else { - SimpleLookupTable store = storedAnnotations(true); + SimpleLookupTable store = storedAnnotations(true, forceStore); if (store == null) return; // not supported holder = (AnnotationHolder) store.get(binding); if (holder == null) @@ -1866,7 +1866,7 @@ void storeAnnotations(Binding binding, AnnotationBinding[] annotations) { storeAnnotationHolder(binding, holder.setAnnotations(annotations)); } -SimpleLookupTable storedAnnotations(boolean forceInitialize) { +SimpleLookupTable storedAnnotations(boolean forceInitialize, boolean forceStore) { return null; // overrride if interested in storing annotations for the receiver, its fields and methods } diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/SourceModuleBinding.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/SourceModuleBinding.java index 6074fe80dd..5f12684d93 100644 --- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/SourceModuleBinding.java +++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/SourceModuleBinding.java @@ -110,7 +110,7 @@ public class SourceModuleBinding extends ModuleBinding { return retrieveAnnotations(this); } public AnnotationHolder retrieveAnnotationHolder(Binding binding, boolean forceInitialization) { - SimpleLookupTable store = storedAnnotations(forceInitialization); + SimpleLookupTable store = storedAnnotations(forceInitialization, false); return store == null ? null : (AnnotationHolder) store.get(binding); } @@ -119,30 +119,30 @@ public class SourceModuleBinding extends ModuleBinding { return holder == null ? Binding.NO_ANNOTATIONS : holder.getAnnotations(); } - public void setAnnotations(AnnotationBinding[] annotations) { - storeAnnotations(this, annotations); + public void setAnnotations(AnnotationBinding[] annotations, boolean forceStore) { + storeAnnotations(this, annotations, forceStore); } void storeAnnotationHolder(Binding binding, AnnotationHolder holder) { if (holder == null) { - SimpleLookupTable store = storedAnnotations(false); + SimpleLookupTable store = storedAnnotations(false, false); if (store != null) store.removeKey(binding); } else { - SimpleLookupTable store = storedAnnotations(true); + SimpleLookupTable store = storedAnnotations(true, false); if (store != null) store.put(binding, holder); } } - void storeAnnotations(Binding binding, AnnotationBinding[] annotations) { + void storeAnnotations(Binding binding, AnnotationBinding[] annotations, boolean forceStore) { AnnotationHolder holder = null; if (annotations == null || annotations.length == 0) { - SimpleLookupTable store = storedAnnotations(false); + SimpleLookupTable store = storedAnnotations(false, forceStore); if (store != null) holder = (AnnotationHolder) store.get(binding); if (holder == null) return; // nothing to delete } else { - SimpleLookupTable store = storedAnnotations(true); + SimpleLookupTable store = storedAnnotations(true, forceStore); if (store == null) return; // not supported holder = (AnnotationHolder) store.get(binding); if (holder == null) @@ -151,11 +151,11 @@ public class SourceModuleBinding extends ModuleBinding { storeAnnotationHolder(binding, holder.setAnnotations(annotations)); } - SimpleLookupTable storedAnnotations(boolean forceInitialize) { + SimpleLookupTable storedAnnotations(boolean forceInitialize, boolean forceStore) { if (forceInitialize && this.storedAnnotations == null && this.scope != null) { // scope null when no annotation cached, and type got processed fully (159631) this.scope.referenceCompilationUnit().compilationResult.hasAnnotations = true; final CompilerOptions globalOptions = this.scope.environment().globalOptions; - if (!globalOptions.storeAnnotations) + if (!globalOptions.storeAnnotations && !forceStore) return null; // not supported during this compile this.storedAnnotations = new SimpleLookupTable(3); } diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/SourceTypeBinding.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/SourceTypeBinding.java index e6199faca6..426b6f45cc 100644 --- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/SourceTypeBinding.java +++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/SourceTypeBinding.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2017 IBM Corporation and others. + * Copyright (c) 2000, 2018 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 @@ -2457,14 +2457,14 @@ public final int sourceStart() { return this.scope.referenceContext.sourceStart; } -SimpleLookupTable storedAnnotations(boolean forceInitialize) { +SimpleLookupTable storedAnnotations(boolean forceInitialize, boolean forceStore) { if (!isPrototype()) - return this.prototype.storedAnnotations(forceInitialize); + return this.prototype.storedAnnotations(forceInitialize, forceStore); if (forceInitialize && this.storedAnnotations == null && this.scope != null) { // scope null when no annotation cached, and type got processed fully (159631) this.scope.referenceCompilationUnit().compilationResult.hasAnnotations = true; final CompilerOptions globalOptions = this.scope.environment().globalOptions; - if (!globalOptions.storeAnnotations) + if (!globalOptions.storeAnnotations && !forceStore) return null; // not supported during this compile this.storedAnnotations = new SimpleLookupTable(3); } diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/TypeConstants.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/TypeConstants.java index 166a8abbad..87417224f7 100644 --- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/TypeConstants.java +++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/TypeConstants.java @@ -175,6 +175,7 @@ public interface TypeConstants { char[][] JAVA_UTIL_LIST = {JAVA, UTIL, "List".toCharArray()}; //$NON-NLS-1$ char[][] JAVA_LANG_DEPRECATED = {JAVA, LANG, "Deprecated".toCharArray()}; //$NON-NLS-1$ char[] FOR_REMOVAL = "forRemoval".toCharArray(); //$NON-NLS-1$ + char[] SINCE = "since".toCharArray(); //$NON-NLS-1$ char[][] JAVA_LANG_ANNOTATION_DOCUMENTED = {JAVA, LANG, ANNOTATION, "Documented".toCharArray()}; //$NON-NLS-1$ char[][] JAVA_LANG_ANNOTATION_INHERITED = {JAVA, LANG, ANNOTATION, "Inherited".toCharArray()}; //$NON-NLS-1$ char[][] JAVA_LANG_ANNOTATION_REPEATABLE = {JAVA, LANG, ANNOTATION, "Repeatable".toCharArray()}; //$NON-NLS-1$ diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/TypeSystem.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/TypeSystem.java index e01b439ea5..a50f0206c0 100644 --- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/TypeSystem.java +++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/TypeSystem.java @@ -503,6 +503,9 @@ public class TypeSystem { public void updateCaches(UnresolvedReferenceBinding unresolvedType, ReferenceBinding resolvedType) { final int unresolvedTypeId = unresolvedType.id; + if (resolvedType.id != TypeIds.NoId) { + unresolvedType.id = resolvedType.id; + } if (unresolvedTypeId != TypeIds.NoId) { // https://bugs.eclipse.org/bugs/show_bug.cgi?id=432977 TypeBinding[] derivedTypes = this.types[unresolvedTypeId]; @@ -510,7 +513,8 @@ public class TypeSystem { if (derivedTypes[i] == null) break; if (derivedTypes[i] == unresolvedType) { //$IDENTITY-COMPARISON$ - resolvedType.id = unresolvedTypeId; + if(resolvedType.id == TypeIds.NoId) + resolvedType.id = unresolvedTypeId; derivedTypes[i] = resolvedType; } } diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/UnresolvedReferenceBinding.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/UnresolvedReferenceBinding.java index b80272adf3..6cb7126e02 100644 --- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/UnresolvedReferenceBinding.java +++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/UnresolvedReferenceBinding.java @@ -119,9 +119,6 @@ ReferenceBinding resolve(LookupEnvironment environment, boolean convertGenericTo // create a proxy for the missing BinaryType targetType = environment.createMissingType(null, this.compoundName); } - if (targetType.id != TypeIds.NoId) { - this.id = targetType.id; - } setResolvedType(targetType, environment); } if (convertGenericToRawType) { @@ -147,7 +144,7 @@ public void swapUnresolved(UnresolvedReferenceBinding unresolvedType, ReferenceB ReferenceBinding annotatedType = (ReferenceBinding) unannotatedType.clone(null); this.resolvedType = annotatedType; annotatedType.setTypeAnnotations(getTypeAnnotations(), environment.globalOptions.isAnnotationBasedNullAnalysisEnabled); - annotatedType.id = unannotatedType.id = this.id; + environment.updateCaches(this, annotatedType); if (this.wrappers != null) for (int i = 0, l = this.wrappers.length; i < l; i++) diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/problem/ProblemReporter.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/problem/ProblemReporter.java index 47aae1544c..0ae933de9e 100644 --- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/problem/ProblemReporter.java +++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/problem/ProblemReporter.java @@ -85,6 +85,7 @@ import java.io.StringWriter; import java.util.Iterator; import java.util.List; import java.util.Set; +import java.util.function.Supplier; import java.util.stream.Collectors; import org.eclipse.jdt.core.compiler.CategorizedProblem; @@ -167,9 +168,12 @@ import org.eclipse.jdt.internal.compiler.env.ICompilationUnit; import org.eclipse.jdt.internal.compiler.flow.FlowInfo; import org.eclipse.jdt.internal.compiler.impl.CompilerOptions; import org.eclipse.jdt.internal.compiler.impl.ReferenceContext; +import org.eclipse.jdt.internal.compiler.impl.StringConstant; +import org.eclipse.jdt.internal.compiler.lookup.AnnotationBinding; import org.eclipse.jdt.internal.compiler.lookup.ArrayBinding; import org.eclipse.jdt.internal.compiler.lookup.Binding; import org.eclipse.jdt.internal.compiler.lookup.CaptureBinding; +import org.eclipse.jdt.internal.compiler.lookup.ElementValuePair; import org.eclipse.jdt.internal.compiler.lookup.ExtraCompilerModifiers; import org.eclipse.jdt.internal.compiler.lookup.FieldBinding; import org.eclipse.jdt.internal.compiler.lookup.InvocationSite; @@ -247,6 +251,11 @@ public static int getIrritant(int problemID) { case IProblem.UsingDeprecatedMethod : case IProblem.UsingDeprecatedConstructor : case IProblem.UsingDeprecatedField : + case IProblem.OverridingDeprecatedSinceVersionMethod : + case IProblem.UsingDeprecatedSinceVersionType : + case IProblem.UsingDeprecatedSinceVersionMethod : + case IProblem.UsingDeprecatedSinceVersionConstructor : + case IProblem.UsingDeprecatedSinceVersionField : return CompilerOptions.UsingDeprecatedAPI; case IProblem.OverridingTerminallyDeprecatedMethod : @@ -254,6 +263,11 @@ public static int getIrritant(int problemID) { case IProblem.UsingTerminallyDeprecatedMethod : case IProblem.UsingTerminallyDeprecatedConstructor : case IProblem.UsingTerminallyDeprecatedField : + case IProblem.OverridingTerminallyDeprecatedSinceVersionMethod : + case IProblem.UsingTerminallyDeprecatedSinceVersionType : + case IProblem.UsingTerminallyDeprecatedSinceVersionMethod : + case IProblem.UsingTerminallyDeprecatedSinceVersionConstructor : + case IProblem.UsingTerminallyDeprecatedSinceVersionField : return CompilerOptions.UsingTerminallyDeprecatedAPI; case IProblem.LocalVariableIsNeverUsed : @@ -1708,20 +1722,37 @@ public void defaultModifierIllegallySpecified(int sourceStart, int sourceEnd) { sourceStart, sourceEnd); } -public void deprecatedField(FieldBinding field, ASTNode location) { - this.handle( - (field.tagBits & TagBits.AnnotationTerminallyDeprecated) == 0 ? IProblem.UsingDeprecatedField : IProblem.UsingTerminallyDeprecatedField, - new String[] {new String(field.declaringClass.readableName()), new String(field.name)}, - new String[] {new String(field.declaringClass.shortReadableName()), new String(field.name)}, - nodeSourceStart(field, location), - nodeSourceEnd(field, location)); +public void deprecatedField(final FieldBinding field, ASTNode location) { + String fieldName = new String(field.name); + int sourceStart = nodeSourceStart(field, location); + int sourceEnd = nodeSourceEnd(field, location); + String sinceValue = deprecatedSinceValue(() -> field.getAnnotations()); + if (sinceValue != null) { + this.handle( + (field.tagBits & TagBits.AnnotationTerminallyDeprecated) == 0 ? IProblem.UsingDeprecatedSinceVersionField : IProblem.UsingTerminallyDeprecatedSinceVersionField, + new String[] {new String(field.declaringClass.readableName()), fieldName, sinceValue}, + new String[] {new String(field.declaringClass.shortReadableName()), fieldName, sinceValue}, + sourceStart, sourceEnd); + } else { + this.handle( + (field.tagBits & TagBits.AnnotationTerminallyDeprecated) == 0 ? IProblem.UsingDeprecatedField : IProblem.UsingTerminallyDeprecatedField, + new String[] {new String(field.declaringClass.readableName()), fieldName}, + new String[] {new String(field.declaringClass.shortReadableName()), fieldName}, + sourceStart, sourceEnd); + } } -public void deprecatedMethod(MethodBinding method, ASTNode location) { +public void deprecatedMethod(final MethodBinding method, ASTNode location) { + // common arguments: + String readableClassName = new String(method.declaringClass.readableName()); + String shortReadableClassName = new String(method.declaringClass.shortReadableName()); + String selector = new String(method.selector); + String signature = typesAsString(method, false); + String shortSignature = typesAsString(method, true); + boolean isConstructor = method.isConstructor(); - boolean terminally = (method.tagBits & TagBits.AnnotationTerminallyDeprecated) != 0; + int start = -1; if (isConstructor) { - int start = -1; if(location instanceof AllocationExpression) { // omit the new keyword from the warning marker // https://bugs.eclipse.org/bugs/show_bug.cgi?id=300031 @@ -1731,25 +1762,50 @@ public void deprecatedMethod(MethodBinding method, ASTNode location) { } start = allocationExpression.type.sourceStart; } - this.handle( - terminally ? IProblem.UsingTerminallyDeprecatedConstructor : IProblem.UsingDeprecatedConstructor, - new String[] {new String(method.declaringClass.readableName()), typesAsString(method, false)}, - new String[] {new String(method.declaringClass.shortReadableName()), typesAsString(method, true)}, - (start == -1) ? location.sourceStart : start, - location.sourceEnd); } else { - int start = -1; if (location instanceof MessageSend) { // start the warning marker from the location where the name of the method starts // https://bugs.eclipse.org/bugs/show_bug.cgi?id=300031 start = (int) (((MessageSend)location).nameSourcePosition >>> 32); } - this.handle( - terminally ? IProblem.UsingTerminallyDeprecatedMethod : IProblem.UsingDeprecatedMethod, - new String[] {new String(method.declaringClass.readableName()), new String(method.selector), typesAsString(method, false)}, - new String[] {new String(method.declaringClass.shortReadableName()), new String(method.selector), typesAsString(method, true)}, - (start == -1) ? location.sourceStart : start, - location.sourceEnd); + } + int sourceStart = (start == -1) ? location.sourceStart : start; + int sourceEnd = location.sourceEnd; + + // discriminate: + boolean terminally = (method.tagBits & TagBits.AnnotationTerminallyDeprecated) != 0; + String sinceValue = deprecatedSinceValue(() -> method.getAnnotations()); + if (sinceValue == null && method.isConstructor()) { + sinceValue = deprecatedSinceValue(() -> method.declaringClass.getAnnotations()); // for default ctor + } + if (sinceValue != null) { + if (isConstructor) { + this.handle( + terminally ? IProblem.UsingTerminallyDeprecatedSinceVersionConstructor : IProblem.UsingDeprecatedSinceVersionConstructor, + new String[] {readableClassName, signature, sinceValue}, + new String[] {shortReadableClassName, shortSignature, sinceValue}, + sourceStart, sourceEnd); + } else { + this.handle( + terminally ? IProblem.UsingTerminallyDeprecatedSinceVersionMethod : IProblem.UsingDeprecatedSinceVersionMethod, + new String[] {readableClassName, selector, signature, sinceValue}, + new String[] {shortReadableClassName, selector, shortSignature, sinceValue}, + sourceStart, sourceEnd); + } + } else { + if (isConstructor) { + this.handle( + terminally ? IProblem.UsingTerminallyDeprecatedConstructor : IProblem.UsingDeprecatedConstructor, + new String[] {readableClassName, signature}, + new String[] {shortReadableClassName, shortSignature}, + sourceStart, sourceEnd); + } else { + this.handle( + terminally ? IProblem.UsingTerminallyDeprecatedMethod : IProblem.UsingDeprecatedMethod, + new String[] {readableClassName, selector, signature}, + new String[] {shortReadableClassName, selector, shortSignature}, + sourceStart, sourceEnd); + } } } public void deprecatedType(TypeBinding type, ASTNode location) { @@ -1759,7 +1815,7 @@ public void deprecatedType(TypeBinding type, ASTNode location) { // a deprecated type in a qualified reference (see bug 292510) public void deprecatedType(TypeBinding type, ASTNode location, int index) { if (location == null) return; // 1G828DN - no type ref for synthetic arguments - type = type.leafComponentType(); + final TypeBinding leafType = type.leafComponentType(); int sourceStart = -1; if (location instanceof QualifiedTypeReference) { // https://bugs.eclipse.org/bugs/show_bug.cgi?id=300031 QualifiedTypeReference ref = (QualifiedTypeReference) location; @@ -1767,12 +1823,36 @@ public void deprecatedType(TypeBinding type, ASTNode location, int index) { sourceStart = (int) (ref.sourcePositions[index] >> 32); } } - this.handle( - ((type.tagBits & TagBits.AnnotationTerminallyDeprecated) == 0) ? IProblem.UsingDeprecatedType : IProblem.UsingTerminallyDeprecatedType, - new String[] {new String(type.readableName())}, - new String[] {new String(type.shortReadableName())}, - (sourceStart == -1) ? location.sourceStart : sourceStart, - nodeSourceEnd(null, location, index)); + String sinceValue = deprecatedSinceValue(() -> leafType.getAnnotations()); + if (sinceValue != null) { + this.handle( + ((leafType.tagBits & TagBits.AnnotationTerminallyDeprecated) == 0) ? IProblem.UsingDeprecatedSinceVersionType : IProblem.UsingTerminallyDeprecatedSinceVersionType, + new String[] {new String(leafType.readableName()), sinceValue}, + new String[] {new String(leafType.shortReadableName()), sinceValue}, + (sourceStart == -1) ? location.sourceStart : sourceStart, + nodeSourceEnd(null, location, index)); + } else { + this.handle( + ((leafType.tagBits & TagBits.AnnotationTerminallyDeprecated) == 0) ? IProblem.UsingDeprecatedType : IProblem.UsingTerminallyDeprecatedType, + new String[] {new String(leafType.readableName())}, + new String[] {new String(leafType.shortReadableName())}, + (sourceStart == -1) ? location.sourceStart : sourceStart, + nodeSourceEnd(null, location, index)); + } +} +String deprecatedSinceValue(Supplier<AnnotationBinding[]> annotations) { + if (this.options != null && this.options.complianceLevel >= ClassFileConstants.JDK9) { + for (AnnotationBinding annotationBinding : annotations.get()) { + if (annotationBinding.getAnnotationType().id == TypeIds.T_JavaLangDeprecated) { + for (ElementValuePair elementValuePair : annotationBinding.getElementValuePairs()) { + if (CharOperation.equals(elementValuePair.getName(), TypeConstants.SINCE) && elementValuePair.value instanceof StringConstant) + return ((StringConstant) elementValuePair.value).stringValue(); + } + break; + } + } + } + return null; } public void disallowedTargetForAnnotation(Annotation annotation) { this.handle( @@ -6962,25 +7042,45 @@ public void operatorOnlyValidOnNumericType(CompoundAssignment assignment, TypeB assignment.sourceEnd); } public void overridesDeprecatedMethod(MethodBinding localMethod, MethodBinding inheritedMethod) { - this.handle( - (inheritedMethod.tagBits & TagBits.AnnotationTerminallyDeprecated) != 0 + String localMethodName = new String( + CharOperation.concat( + localMethod.declaringClass.readableName(), + localMethod.readableName(), + '.')); + String localMethodShortName = new String( + CharOperation.concat( + localMethod.declaringClass.shortReadableName(), + localMethod.shortReadableName(), + '.')); + String sinceValue = deprecatedSinceValue(() -> inheritedMethod.getAnnotations()); + if (sinceValue != null) { + this.handle( + (inheritedMethod.tagBits & TagBits.AnnotationTerminallyDeprecated) != 0 + ? IProblem.OverridingTerminallyDeprecatedSinceVersionMethod : IProblem.OverridingDeprecatedSinceVersionMethod, + new String[] { + localMethodName, + new String(inheritedMethod.declaringClass.readableName()), + sinceValue}, + new String[] { + localMethodShortName, + new String(inheritedMethod.declaringClass.shortReadableName()), + sinceValue}, + localMethod.sourceStart(), + localMethod.sourceEnd()); + + } else { + this.handle( + (inheritedMethod.tagBits & TagBits.AnnotationTerminallyDeprecated) != 0 ? IProblem.OverridingTerminallyDeprecatedMethod : IProblem.OverridingDeprecatedMethod, - new String[] { - new String( - CharOperation.concat( - localMethod.declaringClass.readableName(), - localMethod.readableName(), - '.')), - new String(inheritedMethod.declaringClass.readableName())}, - new String[] { - new String( - CharOperation.concat( - localMethod.declaringClass.shortReadableName(), - localMethod.shortReadableName(), - '.')), - new String(inheritedMethod.declaringClass.shortReadableName())}, - localMethod.sourceStart(), - localMethod.sourceEnd()); + new String[] { + localMethodName, + new String(inheritedMethod.declaringClass.readableName())}, + new String[] { + localMethodShortName, + new String(inheritedMethod.declaringClass.shortReadableName())}, + localMethod.sourceStart(), + localMethod.sourceEnd()); + } } public void overridesMethodWithoutSuperInvocation(MethodBinding localMethod) { this.handle( diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/problem/messages.properties b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/problem/messages.properties index db0f4378bb..7f3e65c519 100644 --- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/problem/messages.properties +++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/problem/messages.properties @@ -915,6 +915,18 @@ 1403 = The field {0}.{1} has been deprecated and marked for removal 1404 = The method {0} overrides a method from {1} that has been deprecated and marked for removal +1405 = The type {0} is deprecated since version {1} +1406 = The method {1}({2}) from the type {0} is deprecated since version {3} +1407 = The constructor {0}({1}) is deprecated since version {2} +1408 = The field {0}.{1} is deprecated since version {2} +1409 = The method {0} overrides a method from {1} that is deprecated since version {2} + +1410 = The type {0} has been deprecated since version {1} and marked for removal +1411 = The method {1}({2}) from the type {0} has been deprecated since version {3} and marked for removal +1412 = The constructor {0}({1}) has been deprecated since version {2} and marked for removal +1413 = The field {0}.{1} has been deprecated since version {2} and marked for removal +1414 = The method {0} overrides a method from {1} that has been deprecated since version {2} and marked for removal + 1450 = The type {0} is not accessible 1451 = The field {1}.{0} is not accessible 1452 = The method {1}({2}) from the type {0} is not accessible diff --git a/org.eclipse.jdt.core/formatter/org/eclipse/jdt/internal/formatter/DefaultCodeFormatter.java b/org.eclipse.jdt.core/formatter/org/eclipse/jdt/internal/formatter/DefaultCodeFormatter.java index 683d70d384..93c0e01e0f 100644 --- a/org.eclipse.jdt.core/formatter/org/eclipse/jdt/internal/formatter/DefaultCodeFormatter.java +++ b/org.eclipse.jdt.core/formatter/org/eclipse/jdt/internal/formatter/DefaultCodeFormatter.java @@ -17,23 +17,23 @@ *******************************************************************************/ package org.eclipse.jdt.internal.formatter; -import static org.eclipse.jdt.internal.compiler.parser.TerminalTokens.TokenNameEOF; -import static org.eclipse.jdt.internal.compiler.parser.TerminalTokens.TokenNameNotAToken; -import static org.eclipse.jdt.internal.compiler.parser.TerminalTokens.TokenNameCOMMENT_JAVADOC; import static org.eclipse.jdt.internal.compiler.parser.TerminalTokens.TokenNameCOMMENT_BLOCK; +import static org.eclipse.jdt.internal.compiler.parser.TerminalTokens.TokenNameCOMMENT_JAVADOC; import static org.eclipse.jdt.internal.compiler.parser.TerminalTokens.TokenNameCOMMENT_LINE; +import static org.eclipse.jdt.internal.compiler.parser.TerminalTokens.TokenNameEOF; +import static org.eclipse.jdt.internal.compiler.parser.TerminalTokens.TokenNameNotAToken; import java.util.ArrayList; -import java.util.HashMap; import java.util.Arrays; +import java.util.HashMap; import java.util.List; import java.util.Map; -import org.eclipse.core.resources.IFile; -import org.eclipse.core.resources.ResourcesPlugin; -import org.eclipse.core.runtime.Path; import org.eclipse.jdt.core.ICompilationUnit; +import org.eclipse.jdt.core.IJavaProject; +import org.eclipse.jdt.core.IModuleDescription; import org.eclipse.jdt.core.JavaCore; +import org.eclipse.jdt.core.JavaModelException; import org.eclipse.jdt.core.compiler.IProblem; import org.eclipse.jdt.core.compiler.InvalidInputException; import org.eclipse.jdt.core.dom.AST; @@ -49,7 +49,8 @@ import org.eclipse.jdt.internal.compiler.impl.CompilerOptions; import org.eclipse.jdt.internal.compiler.lookup.TypeConstants; import org.eclipse.jdt.internal.compiler.parser.Scanner; import org.eclipse.jdt.internal.compiler.util.Util; -import org.eclipse.jdt.internal.core.PackageFragment; +import org.eclipse.jdt.internal.core.JavaProject; +import org.eclipse.jdt.internal.core.SourceModule; import org.eclipse.jdt.internal.formatter.linewrap.CommentWrapExecutor; import org.eclipse.jdt.internal.formatter.linewrap.WrapPreparator; import org.eclipse.jface.text.IRegion; @@ -328,16 +329,7 @@ public class DefaultCodeFormatter extends CodeFormatter { ASTParser parser = ASTParser.newParser(AST.JLS9); if (kind == K_MODULE_INFO) { - Path fakeModuleInfoPath = new Path("project/" + TypeConstants.MODULE_INFO_FILE_NAME_STRING); //$NON-NLS-1$ - IFile file = ResourcesPlugin.getWorkspace().getRoot().getFile(fakeModuleInfoPath); - ICompilationUnit unit = JavaCore.createCompilationUnitFrom(file); - parser.setSource(new org.eclipse.jdt.internal.core.CompilationUnit((PackageFragment) unit.getParent(), - unit.getElementName(), unit.getOwner()) { - @Override - public char[] getContents() { - return DefaultCodeFormatter.this.sourceArray; - } - }); + parser.setSource(createDummyModuleInfoCompilationUnit()); } else { parser.setSource(this.sourceArray); } @@ -350,6 +342,32 @@ public class DefaultCodeFormatter extends CodeFormatter { return parser; } + private ICompilationUnit createDummyModuleInfoCompilationUnit() { + IJavaProject dummyProject = new JavaProject() { + @Override + public Map<String, String> getOptions(boolean inheritJavaCoreOptions) { + return new HashMap<>(); + } + + @Override + public IModuleDescription getModuleDescription() throws JavaModelException { + return new SourceModule(this, ""); //$NON-NLS-1$ + } + }; + return new org.eclipse.jdt.internal.core.CompilationUnit(null, TypeConstants.MODULE_INFO_FILE_NAME_STRING, + null) { + @Override + public char[] getContents() { + return DefaultCodeFormatter.this.sourceArray; + } + + @Override + public IJavaProject getJavaProject() { + return dummyProject; + } + }; + } + private boolean hasErrors(ASTNode astNode) { CompilationUnit root = (CompilationUnit) astNode.getRoot(); for (IProblem problem : root.getProblems()) { diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ModuleUpdater.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ModuleUpdater.java index 16947f99d1..c9696d1da1 100644 --- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ModuleUpdater.java +++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ModuleUpdater.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2017 GK Software AG, and others. + * Copyright (c) 2017, 2018 GK Software AG, 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 @@ -62,7 +62,7 @@ public class ModuleUpdater { String modName = value.substring(0, slash); char[] packName = value.substring(slash+1, equals).toCharArray(); char[][] targets = CharOperation.splitOn(',', value.substring(equals+1).toCharArray()); - addModuleUpdate(modName, m -> m.addExports(packName, targets), UpdateKind.PACKAGE); + addModuleUpdate(modName, new IUpdatableModule.AddExports(packName, targets), UpdateKind.PACKAGE); } else { Util.log(IStatus.WARNING, "Invalid argument to add-exports: "+value); //$NON-NLS-1$ } @@ -73,7 +73,7 @@ public class ModuleUpdater { if (equals != -1) { String srcMod = value.substring(0, equals); char[] targetMod = value.substring(equals+1).toCharArray(); - addModuleUpdate(srcMod, m -> m.addReads(targetMod), UpdateKind.MODULE); + addModuleUpdate(srcMod, new IUpdatableModule.AddReads(targetMod), UpdateKind.MODULE); } else { Util.log(IStatus.WARNING, "Invalid argument to add-reads: "+value); //$NON-NLS-1$ } @@ -108,4 +108,7 @@ public class ModuleUpdater { } } } + public UpdatesByKind getUpdates(String moduleName) { + return this.moduleUpdates.get(moduleName); + } } diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/ClasspathDirectory.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/ClasspathDirectory.java index 74f3332b74..a0ea9eb5b0 100644 --- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/ClasspathDirectory.java +++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/ClasspathDirectory.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2017 IBM Corporation and others. + * Copyright (c) 2000, 2018 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 @@ -136,10 +136,10 @@ public boolean equals(Object o) { if (this.accessRuleSet != dir.accessRuleSet) if (this.accessRuleSet == null || !this.accessRuleSet.equals(dir.accessRuleSet)) return false; - if (this.module != dir.module) - if (this.module == null || !this.module.equals(dir.module)) - return false; - return this.binaryFolder.equals(dir.binaryFolder); + if (this.isOnModulePath != dir.isOnModulePath) + return false; + + return this.binaryFolder.equals(dir.binaryFolder) && areAllModuleOptionsEqual(dir); } public NameEnvironmentAnswer findClass(String binaryFileName, String qualifiedPackageName, String moduleName, String qualifiedBinaryFileName, boolean asBinaryOnly) { if (!doesFileExist(binaryFileName, qualifiedPackageName, qualifiedBinaryFileName)) return null; // most common case diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/ClasspathJar.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/ClasspathJar.java index 210c43ce41..b433fc0804 100644 --- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/ClasspathJar.java +++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/ClasspathJar.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2017 IBM Corporation and others. + * Copyright (c) 2000, 2018 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 @@ -207,7 +207,8 @@ public boolean equals(Object o) { return false; return this.zipFilename.equals(jar.zipFilename) && lastModified() == jar.lastModified() - && this.isOnModulePath == jar.isOnModulePath; + && this.isOnModulePath == jar.isOnModulePath + && areAllModuleOptionsEqual(jar); } public NameEnvironmentAnswer findClass(String binaryFileName, String qualifiedPackageName, String moduleName, String qualifiedBinaryFileName, boolean asBinaryOnly) { diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/ClasspathJrt.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/ClasspathJrt.java index 855525db79..e40883856d 100644 --- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/ClasspathJrt.java +++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/ClasspathJrt.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2016, 2017 IBM Corporation and others. + * Copyright (c) 2016, 2018 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 @@ -181,7 +181,8 @@ public boolean equals(Object o) { if (this == o) return true; if (!(o instanceof ClasspathJrt)) return false; ClasspathJrt jar = (ClasspathJrt) o; - return this.zipFilename.endsWith(jar.zipFilename); + + return this.zipFilename.endsWith(jar.zipFilename) && areAllModuleOptionsEqual(jar); } @Override diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/ClasspathLocation.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/ClasspathLocation.java index 938151fd31..bdbe6e5056 100644 --- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/ClasspathLocation.java +++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/ClasspathLocation.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2017 IBM Corporation and others. + * Copyright (c) 2000, 2018 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 @@ -12,12 +12,18 @@ *******************************************************************************/ package org.eclipse.jdt.internal.core.builder; +import java.util.List; +import java.util.Set; +import java.util.function.Consumer; + import org.eclipse.core.resources.IContainer; import org.eclipse.core.resources.IFile; import org.eclipse.core.runtime.IPath; import org.eclipse.jdt.internal.compiler.env.AccessRuleSet; import org.eclipse.jdt.internal.compiler.env.IModule; +import org.eclipse.jdt.internal.compiler.env.IUpdatableModule; import org.eclipse.jdt.internal.compiler.env.NameEnvironmentAnswer; +import org.eclipse.jdt.internal.compiler.env.IUpdatableModule.UpdateKind; import org.eclipse.jdt.internal.compiler.lookup.ModuleBinding; import org.eclipse.jdt.internal.compiler.util.Util; @@ -25,6 +31,9 @@ public abstract class ClasspathLocation { protected boolean isOnModulePath; protected IModule module; + protected IUpdatableModule.UpdatesByKind updates; + protected Set<String> limitModuleNames = null; + protected String patchModuleName = null; // In the following signatures, passing a null moduleName signals "don't care": abstract public NameEnvironmentAnswer findClass(String typeName, String qualifiedPackageName, String moduleName, String qualifiedBinaryFileName); abstract public NameEnvironmentAnswer findClass(String typeName, String qualifiedPackageName, String moduleName, String qualifiedBinaryFileName, boolean asBinaryOnly); @@ -45,6 +54,62 @@ public abstract class ClasspathLocation { public IModule getModule() { return this.module; } + protected boolean areAllModuleOptionsEqual(ClasspathLocation other) { + if (this.patchModuleName != null) { + if (other.patchModuleName == null) + return false; + if (!this.patchModuleName.equals(other.patchModuleName)) + return false; + } else { + if (other.patchModuleName != null) + return false; + } + if (this.limitModuleNames != null) { + if (other.limitModuleNames == null) + return false; + if (other.limitModuleNames.size() != this.limitModuleNames.size()) + return false; + if (!this.limitModuleNames.containsAll(other.limitModuleNames)) + return false; + } else { + if (other.limitModuleNames != null) + return false; + } + if (this.updates != null) { + if (other.updates == null) + return false; + List<Consumer<IUpdatableModule>> packageUpdates = this.updates.getList(UpdateKind.PACKAGE, false); + List<Consumer<IUpdatableModule>> otherPackageUpdates = other.updates.getList(UpdateKind.PACKAGE, false); + if (packageUpdates != null) { + if (otherPackageUpdates == null) + return false; + if (packageUpdates.size() != otherPackageUpdates.size()) + return false; + if (!packageUpdates.containsAll(otherPackageUpdates)) + return false; + } else { + if (otherPackageUpdates != null) + return false; + } + List<Consumer<IUpdatableModule>> moduleUpdates = this.updates.getList(UpdateKind.MODULE, false); + List<Consumer<IUpdatableModule>> otherModuleUpdates = other.updates.getList(UpdateKind.MODULE, false); + if (moduleUpdates != null) { + if (otherModuleUpdates == null) + return false; + if (moduleUpdates.size() != otherModuleUpdates.size()) + return false; + if (!moduleUpdates.containsAll(otherModuleUpdates)) + return false; + } else { + if (otherModuleUpdates != null) + return false; + } + } else { + if (other.updates != null) + return false; + } + return true; + } static ClasspathLocation forSourceFolder(IContainer sourceFolder, IContainer outputFolder, char[][] inclusionPatterns, char[][] exclusionPatterns, boolean ignoreOptionalProblems) { return new ClasspathMultiDirectory(sourceFolder, outputFolder, inclusionPatterns, exclusionPatterns, diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/NameEnvironment.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/NameEnvironment.java index bcf5f72c6c..054b11c4bb 100644 --- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/NameEnvironment.java +++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/NameEnvironment.java @@ -23,6 +23,7 @@ import org.eclipse.jdt.core.*; import org.eclipse.jdt.core.compiler.CharOperation; import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants; import org.eclipse.jdt.internal.compiler.env.*; +import org.eclipse.jdt.internal.compiler.env.IUpdatableModule.UpdateKind; import org.eclipse.jdt.internal.compiler.impl.CompilerOptions; import org.eclipse.jdt.internal.compiler.problem.AbortCompilation; import org.eclipse.jdt.internal.compiler.util.SimpleLookupTable; @@ -33,6 +34,7 @@ import org.eclipse.jdt.internal.core.*; import java.io.*; import java.util.*; +import java.util.function.Consumer; import java.util.stream.Collectors; @SuppressWarnings({"rawtypes", "unchecked"}) @@ -162,6 +164,7 @@ private void computeClasspathLocations( entry.ignoreOptionalProblems()); if (patchedModule != null) { ModuleEntryProcessor.combinePatchIntoModuleEntry(sourceLocation, patchedModule, moduleEntries); + sourceLocation.patchModuleName = patchedModuleName; } sLocations.add(sourceLocation); continue nextEntry; @@ -221,6 +224,12 @@ private void computeClasspathLocations( ModulePathEntry projectEntry = new ModulePathEntry(prereqJavaProject.getPath(), info, projectLocations.toArray(new ClasspathLocation[projectLocations.size()])); String moduleName = String.valueOf(info.name()); + IUpdatableModule.UpdatesByKind updates = this.moduleUpdater.getUpdates(moduleName); + for (ClasspathLocation loc : projectLocations) { + loc.limitModuleNames = limitModules; + loc.updates = updates; + loc.patchModuleName = patchedModuleName; + } if (limitModules == null || limitModules.contains(moduleName)) { moduleEntries.put(moduleName, projectEntry); if (moduleName.equals(patchedModuleName)) @@ -339,8 +348,28 @@ IModule collectModuleEntries(ClasspathLocation bLocation, IPath path, boolean is String patchedModuleName, IModule patchedModule, Map<String, IModulePathEntry> moduleEntries) { if (bLocation instanceof IMultiModuleEntry) { IMultiModuleEntry binaryModulePathEntry = (IMultiModuleEntry) bLocation; + bLocation.limitModuleNames = limitModules; + bLocation.patchModuleName = patchedModuleName; + IUpdatableModule.UpdatesByKind updates = null;//new IUpdatableModule.UpdatesByKind(); + IUpdatableModule.UpdatesByKind finalUpdates = new IUpdatableModule.UpdatesByKind(); + List<Consumer<IUpdatableModule>> packageUpdates = null; + List<Consumer<IUpdatableModule>> moduleUpdates = null; for (String moduleName : binaryModulePathEntry.getModuleNames(limitModules)) { moduleEntries.put(moduleName, binaryModulePathEntry); + updates = this.moduleUpdater.getUpdates(moduleName); + if (updates != null) { + List<Consumer<IUpdatableModule>> pu = updates.getList(UpdateKind.PACKAGE, false); + if (pu != null) { + (packageUpdates = finalUpdates.getList(UpdateKind.PACKAGE, true)).addAll(pu); + } + List<Consumer<IUpdatableModule>> mu = updates.getList(UpdateKind.MODULE, false); + if (mu != null) { + (moduleUpdates = finalUpdates.getList(UpdateKind.MODULE, true)).addAll(mu); + } + } + } + if (packageUpdates != null || moduleUpdates != null) { + bLocation.updates = finalUpdates; } if (patchedModuleName != null) { IModule module = binaryModulePathEntry.getModule(patchedModuleName.toCharArray()); @@ -353,6 +382,9 @@ IModule collectModuleEntries(ClasspathLocation bLocation, IPath path, boolean is IModule module = binaryModulePathEntry.getModule(); if (module != null) { String moduleName = String.valueOf(module.name()); + bLocation.updates = this.moduleUpdater.getUpdates(moduleName); + bLocation.limitModuleNames = limitModules; + bLocation.patchModuleName = patchedModuleName; if (limitModules == null || limitModules == ClasspathJrt.NO_LIMIT_MODULES || limitModules.contains(moduleName)) { moduleEntries.put(moduleName, binaryModulePathEntry); if (patchedModuleName != null) { diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/State.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/State.java index a6d5695a59..2ea610af87 100644 --- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/State.java +++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/State.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2016 IBM Corporation and others. + * Copyright (c) 2000, 2018 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 @@ -17,6 +17,8 @@ import org.eclipse.core.runtime.*; import org.eclipse.jdt.core.compiler.CharOperation; import org.eclipse.jdt.internal.compiler.env.AccessRuleSet; +import org.eclipse.jdt.internal.compiler.env.IUpdatableModule; +import org.eclipse.jdt.internal.compiler.env.IUpdatableModule.*; import org.eclipse.jdt.internal.compiler.env.AccessRule; import org.eclipse.jdt.internal.compiler.util.SimpleLookupTable; import org.eclipse.jdt.internal.compiler.util.Util; @@ -25,6 +27,8 @@ import org.eclipse.jdt.internal.core.JavaModelManager; import java.io.*; import java.util.*; +import java.util.function.Consumer; +import java.util.stream.Collectors; @SuppressWarnings({"rawtypes", "unchecked"}) public class State { @@ -281,6 +285,38 @@ static State read(IProject project, DataInputStream in) throws IOException { newState.binaryLocations[i] = ClasspathLocation.forLibrary(root.getFile(new Path(in.readUTF())), readRestriction(in), new Path(in.readUTF()), in.readBoolean()); } + ClasspathLocation loc = newState.binaryLocations[i]; + char[] patchName = readName(in); + loc.patchModuleName = patchName.length > 0 ? new String(patchName) : null; + int limitSize = in.readInt(); + if (limitSize != 0) { + loc.limitModuleNames = new HashSet<>(limitSize); + for (int j = 0; j < limitSize; j++) { + loc.limitModuleNames.add(in.readUTF()); + } + } else { + loc.limitModuleNames = null; + } + IUpdatableModule.UpdatesByKind updates = new IUpdatableModule.UpdatesByKind(); + List<Consumer<IUpdatableModule>> packageUpdates = null; + int packageUpdatesSize = in.readInt(); + if (packageUpdatesSize != 0) { + packageUpdates = updates.getList(UpdateKind.PACKAGE, true); + for (int j = 0; j < packageUpdatesSize; j++) { + char[] pkgName = readName(in); + char[][] targets = readNames(in); + packageUpdates.add(new AddExports(pkgName, targets)); + } + } + List<Consumer<IUpdatableModule>> moduleUpdates = null; + int moduleUpdatesSize = in.readInt(); + if (moduleUpdatesSize != 0) { + moduleUpdates = updates.getList(UpdateKind.MODULE, true); + char[] modName = readName(in); + moduleUpdates.add(new AddReads(modName)); + } + if (packageUpdates != null || moduleUpdates != null) + loc.updates = updates; } newState.structuralBuildTimes = new SimpleLookupTable(length = in.readInt()); @@ -443,14 +479,14 @@ void write(DataOutputStream out) throws IOException { * String path(s) */ out.writeInt(length = this.binaryLocations.length); - next : for (int i = 0; i < length; i++) { + for (int i = 0; i < length; i++) { ClasspathLocation c = this.binaryLocations[i]; if (c instanceof ClasspathMultiDirectory) { out.writeByte(SOURCE_FOLDER); for (int j = 0, m = this.sourceLocations.length; j < m; j++) { if (this.sourceLocations[j] == c) { out.writeInt(j); - continue next; + //continue next; } } } else if (c instanceof ClasspathDirectory) { @@ -482,6 +518,55 @@ void write(DataOutputStream out) throws IOException { writeRestriction(null, out); out.writeUTF(""); //$NON-NLS-1$ } + char[] patchName = c.patchModuleName == null ? CharOperation.NO_CHAR : c.patchModuleName.toCharArray(); + writeName(patchName, out); + if (c.limitModuleNames != null) { + out.writeInt(c.limitModuleNames.size()); + for (String name : c.limitModuleNames) { + out.writeUTF(name); + } + } else { + out.writeInt(0); + } + if (c.updates != null) { + List<Consumer<IUpdatableModule>> pu = c.updates.getList(UpdateKind.PACKAGE, false); + if (pu != null) { + Map<String, List<Consumer<IUpdatableModule>>> map = pu.stream(). + collect(Collectors.groupingBy( + update -> CharOperation.charToString(((IUpdatableModule.AddExports)update).getName()))); + out.writeInt(map.size()); + map.entrySet().stream().forEach(entry -> { + String pkgName = entry.getKey(); + try { + writeName(pkgName.toCharArray(), out); + char[][] targetModules = entry.getValue().stream() + .map(consumer -> ((IUpdatableModule.AddExports) consumer).getTargetModules()) + .filter(targets -> targets != null) + .reduce((f,s) -> CharOperation.arrayConcat(f,s)) + .orElse(null); + writeNames(targetModules, out); + } catch (IOException e) { + // ignore + } + + }); + } else { + out.writeInt(0); + } + List<Consumer<IUpdatableModule>> mu = c.updates.getList(UpdateKind.MODULE, false); + if (mu != null) { + out.writeInt(mu.size()); + for (Consumer<IUpdatableModule> cons : mu) { + AddReads m = (AddReads) cons; + writeName(m.getTarget(), out); + } + } else { + out.writeInt(0); + } + } else { + out.writeInt(0); + out.writeInt(0); + } } /* diff --git a/org.eclipse.jdt.core/pom.xml b/org.eclipse.jdt.core/pom.xml index 8a4777051e..64897acb5f 100644 --- a/org.eclipse.jdt.core/pom.xml +++ b/org.eclipse.jdt.core/pom.xml @@ -18,7 +18,7 @@ </parent> <groupId>org.eclipse.jdt</groupId> <artifactId>org.eclipse.jdt.core</artifactId> - <version>3.15.0-SNAPSHOT</version> + <version>3.13.102-SNAPSHOT</version> <packaging>eclipse-plugin</packaging> <properties> |