# HG changeset patch # User Jan Lahoda # Date 1493843843 -7200 # Node ID 7feb751ba76b0c5cfdde14f6cee52857737ffff8 # Parent 57843026e60b721b87594dad3c67f9c4787ddb36# Parent 06b3af1708efde7e8fbf8f750f0a64a26f9c6f62 Merging recent changes to the donation_review branch. diff -r 57843026e60b -r 7feb751ba76b cmdline/tool/nbproject/genfiles.properties --- a/cmdline/tool/nbproject/genfiles.properties Mon Feb 27 22:40:44 2017 +0100 +++ b/cmdline/tool/nbproject/genfiles.properties Wed May 03 22:37:23 2017 +0200 @@ -44,6 +44,6 @@ build.xml.stylesheet.CRC32=a56c6a5b@1.44 # This file is used by a NetBeans-based IDE to track changes in generated files such as build-impl.xml. # Do not edit this file. You may delete it but then the IDE will never regenerate such files for you. -nbproject/build-impl.xml.data.CRC32=c79833a9 +nbproject/build-impl.xml.data.CRC32=8514a197 nbproject/build-impl.xml.script.CRC32=08f1fb11 -nbproject/build-impl.xml.stylesheet.CRC32=238281d1@2.70 +nbproject/build-impl.xml.stylesheet.CRC32=238281d1@2.73 diff -r 57843026e60b -r 7feb751ba76b cmdline/tool/nbproject/project.xml --- a/cmdline/tool/nbproject/project.xml Mon Feb 27 22:40:44 2017 +0100 +++ b/cmdline/tool/nbproject/project.xml Wed May 03 22:37:23 2017 +0200 @@ -148,6 +148,15 @@ + org.netbeans.modules.java.hints.declarative + + + + 1 + + + + org.netbeans.modules.java.hints.ui @@ -387,10 +396,6 @@ - org.netbeans.modules.java.hints.declarative - - - org.netbeans.modules.java.hints.declarative.test diff -r 57843026e60b -r 7feb751ba76b cmdline/tool/src/org/netbeans/modules/jackpot30/cmdline/Main.java --- a/cmdline/tool/src/org/netbeans/modules/jackpot30/cmdline/Main.java Mon Feb 27 22:40:44 2017 +0100 +++ b/cmdline/tool/src/org/netbeans/modules/jackpot30/cmdline/Main.java Wed May 03 22:37:23 2017 +0200 @@ -54,6 +54,7 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; +import java.util.Collections; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; @@ -87,6 +88,10 @@ import org.netbeans.core.startup.MainLookup; import org.netbeans.modules.jackpot30.cmdline.lib.Utils; import org.netbeans.modules.jackpot30.ui.settings.XMLHintPreferences; +import org.netbeans.modules.java.hints.declarative.DeclarativeHintRegistry; +import org.netbeans.modules.java.hints.declarative.test.TestParser; +import org.netbeans.modules.java.hints.declarative.test.TestParser.TestCase; +import org.netbeans.modules.java.hints.declarative.test.TestPerformer; import org.netbeans.modules.java.hints.jackpot.spi.PatternConvertor; import org.netbeans.modules.java.hints.providers.spi.HintDescription; import org.netbeans.modules.java.hints.providers.spi.HintMetadata; @@ -108,6 +113,8 @@ import org.netbeans.modules.parsing.impl.indexing.CacheFolder; import org.netbeans.modules.parsing.impl.indexing.RepositoryUpdater; import org.netbeans.spi.editor.hints.ErrorDescription; +import org.netbeans.spi.editor.hints.ErrorDescriptionFactory; +import org.netbeans.spi.editor.hints.Fix; import org.netbeans.spi.editor.hints.Severity; import org.netbeans.spi.java.classpath.ClassPathProvider; import org.netbeans.spi.java.classpath.support.ClassPathSupport; @@ -133,6 +140,7 @@ private static final String OPTION_APPLY = "apply"; private static final String OPTION_NO_APPLY = "no-apply"; private static final String OPTION_FAIL_ON_WARNINGS = "fail-on-warnings"; + private static final String RUN_TESTS = "run-tests"; private static final String SOURCE_LEVEL_DEFAULT = "1.7"; private static final String ACCEPTABLE_SOURCE_LEVEL_PATTERN = "(1\\.)?[2-9][0-9]*"; @@ -162,6 +170,7 @@ parser.accepts(OPTION_APPLY, "apply changes"); parser.accepts("show-gui", "show configuration dialog"); parser.accepts(OPTION_FAIL_ON_WARNINGS, "fail when warnings are detected"); + parser.accepts(RUN_TESTS, "run tests for declarative rules that were used"); OptionSet parsed; @@ -286,6 +295,7 @@ Preferences hintSettingsPreferences; boolean apply; boolean runDeclarative; + boolean runDeclarativeTests; if (parsed.has(configFile)) { Preferences settingsFromConfigFile; @@ -293,6 +303,7 @@ hintSettingsPreferences = settingsFromConfigFile.node("settings"); apply = settingsFromConfigFile.getBoolean("apply", false); runDeclarative = settingsFromConfigFile.getBoolean("runDeclarative", true); + runDeclarativeTests = settingsFromConfigFile.getBoolean("runDeclarativeTests", false); if (parsed.has(hint)) { System.err.println("cannot specify --hint and --config-file together"); return 1; @@ -304,6 +315,7 @@ hintSettingsPreferences = null; apply = false; runDeclarative = true; + runDeclarativeTests = parsed.has(RUN_TESTS); } if (parsed.has(config) && !parsed.has(hint)) { @@ -320,7 +332,7 @@ GroupResult result = GroupResult.NOTHING_TO_DO; try (Writer outS = parsed.has(out) ? new BufferedWriter(new OutputStreamWriter(new FileOutputStream(parsed.valueOf(out)))) : null) { - GlobalConfiguration globalConfig = new GlobalConfiguration(hintSettingsPreferences, apply, runDeclarative, parsed.valueOf(hint), parsed.valueOf(hintFile), outS, parsed.has(OPTION_FAIL_ON_WARNINGS)); + GlobalConfiguration globalConfig = new GlobalConfiguration(hintSettingsPreferences, apply, runDeclarative, runDeclarativeTests, parsed.valueOf(hint), parsed.valueOf(hintFile), outS, parsed.has(OPTION_FAIL_ON_WARNINGS)); for (RootConfiguration groupConfig : groups) { result = result.join(handleGroup(groupConfig, progress, globalConfig, parsed.valuesOf(config))); @@ -405,6 +417,8 @@ return GroupResult.NOTHING_TO_DO; } + WarningsAndErrors wae = new WarningsAndErrors(); + ProgressHandleWrapper progress = w.startNextPartWithEmbedding(1); Preferences settings = globalConfig.configurationPreferences != null ? globalConfig.configurationPreferences : new MemoryPreferences(); HintsSettings hintSettings = HintsSettings.createPreferencesBasedHintsSettings(settings, false, null); @@ -420,6 +434,46 @@ } } else { hints = readHints(rootConfiguration.sourceCP, rootConfiguration.binaryCP, hintSettings, settings, globalConfig.runDeclarative); + if (globalConfig.runDeclarativeTests) { + Set enabledHints = new HashSet<>(); + for (HintDescription desc : hints) { + enabledHints.add(desc.getMetadata().id); + } + ClassPath combined = ClassPathSupport.createProxyClassPath(rootConfiguration.sourceCP, rootConfiguration.binaryCP); + Map testFiles = new HashMap<>(); + for (FileObject upgrade : combined.findAllResources("META-INF/upgrade")) { + for (FileObject c : upgrade.getChildren()) { + if (c.getExt().equals("test")) { + FileObject hintFile = FileUtil.findBrother(c, "hint"); + + for (HintMetadata hm : DeclarativeHintRegistry.parseHintFile(hintFile).keySet()) { + if (enabledHints.contains(hm.id)) { + testFiles.put(c, hintFile); + break; + } + } + } + } + } + for (Entry e : testFiles.entrySet()) { + TestCase[] testCases = TestParser.parse(e.getKey().asText()); //XXX: encoding + try { + Map> testResult = TestPerformer.performTest(e.getValue(), e.getKey(), testCases, new AtomicBoolean()); + for (TestCase tc : testCases) { + List expected = Arrays.asList(tc.getResults()); + List actual = new ArrayList<>(testResult.get(tc)); + if (!expected.equals(actual)) { + int pos = tc.getTestCaseStart(); + String id = "test-failure"; + ErrorDescription ed = ErrorDescriptionFactory.createErrorDescription(id, Severity.ERROR, "Actual results did not match the expected test results. Actual results: " + expected, null, ErrorDescriptionFactory.lazyListForFixes(Collections.emptyList()), e.getKey(), pos, pos); + print(ed, wae, Collections.singletonMap(id, id)); + } + } + } catch (Exception ex) { + ex.printStackTrace(); + } + } + } } if (config != null && !config.isEmpty()) { @@ -478,10 +532,8 @@ if (globalConfig.apply) { apply(hints, rootConfiguration.rootFolders.toArray(new Folder[0]), progress, hintSettings, globalConfig.out); - return GroupResult.SUCCESS; + return GroupResult.SUCCESS; //TODO: WarningsAndErrors? } else { - WarningsAndErrors wae = new WarningsAndErrors(); - findOccurrences(hints, rootConfiguration.rootFolders.toArray(new Folder[0]), progress, hintSettings, wae); if (wae.errors != 0 || (wae.warnings != 0 && globalConfig.failOnWarnings)) { @@ -870,15 +922,17 @@ private final Preferences configurationPreferences; private final boolean apply; private final boolean runDeclarative; + private final boolean runDeclarativeTests; private final String hint; private final File hintFile; private final Writer out; private final boolean failOnWarnings; - public GlobalConfiguration(Preferences configurationPreferences, boolean apply, boolean runDeclarative, String hint, File hintFile, Writer out, boolean failOnWarnings) { + public GlobalConfiguration(Preferences configurationPreferences, boolean apply, boolean runDeclarative, boolean runDeclarativeTests, String hint, File hintFile, Writer out, boolean failOnWarnings) { this.configurationPreferences = configurationPreferences; this.apply = apply; this.runDeclarative = runDeclarative; + this.runDeclarativeTests = runDeclarativeTests; this.hint = hint; this.hintFile = hintFile; this.out = out; diff -r 57843026e60b -r 7feb751ba76b cmdline/tool/test/unit/src/org/netbeans/modules/jackpot30/cmdline/MainTest.java --- a/cmdline/tool/test/unit/src/org/netbeans/modules/jackpot30/cmdline/MainTest.java Mon Feb 27 22:40:44 2017 +0100 +++ b/cmdline/tool/test/unit/src/org/netbeans/modules/jackpot30/cmdline/MainTest.java Wed May 03 22:37:23 2017 +0200 @@ -536,12 +536,210 @@ "--apply"); } + public void testAutomaticTestRun() throws Exception { + class Config { + private final String commandLineOption; + private final int result; + private final Validator validator; + + public Config(String commandLineOption, int result, Validator validator) { + this.commandLineOption = commandLineOption; + this.result = result; + this.validator = validator; + } + + } + Validator testValidator = + equivalentValidator("${workdir}/src/META-INF/upgrade/test.test:15: error: [test_failure] Actual results did not match the expected test results. Actual results: []\n" + + "%%TestCase pos-neg\n" + + "^\n" + + "${workdir}/src/META-INF/upgrade/test.test:29: error: [test_failure] Actual results did not match the expected test results. Actual results: [package test;\n" + + "public class Test {{\n" + + " private void test(java.util.Collection c) {\n" + + " boolean b1 = c.isEmpty();\n" + + " }\n" + + "}}\n" + + "]\n" + + "%%TestCase neg-neg\n" + + "^\n" + + "${workdir}/src/test/Test.java:4: warning: [test] test\n" + + " boolean b1 = c.size() == 0;\n" + + " ^\n"); + List options = + Arrays.asList(new Config("--run-tests", 1, testValidator), + new Config(IGNORE, 0, equivalentValidator("${workdir}/src/test/Test.java:4: warning: [test] test\n" + + " boolean b1 = c.size() == 0;\n" + + " ^\n"))); + for (Config testConfig : options) { + doRunCompiler(equivalentValidator("package test;\n" + + "public class Test {\n" + + " private void test(java.util.Collection c) {\n" + + " boolean b1 = c.size() == 0;\n" + + " boolean b2 = c.size() != 0;\n" + + " }\n" + + "}\n"), + testConfig.validator, + equivalentValidator(""), + testConfig.result, + "src/META-INF/upgrade/test.hint", + "$coll.size() == 0 :: $coll instanceof java.util.Collection\n" + + "=>\n" + + "$coll.isEmpty()\n" + + ";;", + "src/META-INF/upgrade/test.test", + "%%TestCase pos-pos\n" + + "package test;\n" + + "public class Test {{\n" + + " private void test(java.util.Collection c) {\n" + + " boolean b1 = c.size() == 0;\n" + + " }\n" + + "}}\n" + + "%%=>\n" + + "package test;\n" + + "public class Test {{\n" + + " private void test(java.util.Collection c) {\n" + + " boolean b1 = c.isEmpty();\n" + + " }\n" + + "}}\n" + + "%%TestCase pos-neg\n" + + "package test;\n" + + "public class Test {{\n" + + " private void test(java.util.Collection c) {\n" + + " boolean b1 = c.size() == 0;\n" + + " }\n" + + "}}\n" + + "%%TestCase neg-pos\n" + + "package test;\n" + + "public class Test {{\n" + + " private void test(java.util.Collection c) {\n" + + " boolean b1 = c.size() != 0;\n" + + " }\n" + + "}}\n" + + "%%TestCase neg-neg\n" + + "package test;\n" + + "public class Test {{\n" + + " private void test(java.util.Collection c) {\n" + + " boolean b1 = c.size() != 0;\n" + + " }\n" + + "}}\n" + + "%%=>\n" + + "package test;\n" + + "public class Test {{\n" + + " private void test(java.util.Collection c) {\n" + + " boolean b1 = c.isEmpty();\n" + + " }\n" + + "}}\n", + "src/test/Test.java", + "package test;\n" + + "public class Test {\n" + + " private void test(java.util.Collection c) {\n" + + " boolean b1 = c.size() == 0;\n" + + " boolean b2 = c.size() != 0;\n" + + " }\n" + + "}\n", + null, + testConfig.commandLineOption, + "--sourcepath", "${workdir}/src"); + } + } + + public void testLambda() throws Exception { + doRunCompiler(null, + equivalentValidator("${workdir}/src/test/Test.java:4: warning: [test] test\n" + + " Runnable r = () -> {};\n" + + " ^\n" + + "${workdir}/src/test/Test.java:5: warning: [test] test\n" + + " I1 i1 = (str1, str2) -> {};\n" + + " ^\n" + + "${workdir}/src/test/Test.java:6: warning: [test] test\n" + + " I2 i2 = (str1, str2) -> str1;\n" + + " ^\n" + + "${workdir}/src/test/Test.java:7: warning: [test] test\n" + + " I3 i3 = str -> { return str; };\n" + + " ^\n"), + equivalentValidator(""), + "src/META-INF/upgrade/test.hint", + "($args$) -> $expr" + + ";;", + "src/test/Test.java", + "package test;\n" + + "public class Test {\n" + + " private void test() {\n" + + " Runnable r = () -> {};\n" + + " I1 i1 = (str1, str2) -> {};\n" + + " I2 i2 = (str1, str2) -> str1;\n" + + " I3 i3 = str -> { return str; };\n" + + " }\n" + + " interface I1 {\n" + + " public void test(String str1, String str2);\n" + + " }\n" + + " interface I2 {\n" + + " public String test(String str1, String str2);\n" + + " }\n" + + " interface I3 {\n" + + " public String test(String str);\n" + + " }\n" + + "}\n", + null, + "-source", "8", + "--sourcepath", "${workdir}/src"); + } + + public void testMethodRef() throws Exception { + doRunCompiler(null, + equivalentValidator("${workdir}/src/test/Test.java:8: warning: [test] test\n" + + " I3 i3b = String::new;\n" + + " ^\n" + + "${workdir}/src/test/Test.java:4: warning: [test] test\n" + + " Runnable r = Test::m1;\n" + + " ^\n" + + "${workdir}/src/test/Test.java:5: warning: [test] test\n" + + " I1 i1 = this::m2;\n" + + " ^\n" + + "${workdir}/src/test/Test.java:6: warning: [test] test\n" + + " I2 i2 = String::replace;\n" + + " ^\n" + + "${workdir}/src/test/Test.java:7: warning: [test] test\n" + + " I3 i3a = String::toLowerCase;\n" + + " ^\n"), + equivalentValidator(""), + "src/META-INF/upgrade/test.hint", + "$clazz \\u003a\\u003a $member;;" + + "$clazz \\u003a\\u003a new;;", + "src/test/Test.java", + "package test;\n" + + "public class Test {\n" + + " private void test() {\n" + + " Runnable r = Test::m1;\n" + + " I1 i1 = this::m2;\n" + + " I2 i2 = String::replace;\n" + + " I3 i3a = String::toLowerCase;\n" + + " I3 i3b = String::new;\n" + + " }\n" + + " interface I1 {\n" + + " public void test(String str1, String str2);\n" + + " }\n" + + " interface I2 {\n" + + " public String test(String str1, String str2);\n" + + " }\n" + + " interface I3 {\n" + + " public String test(String str);\n" + + " }\n" + + " private static void m1() { }\n" + + " private void m2(String str1, String str2) { }\n" + + "}\n", + null, + "-source", "8", + "--sourcepath", "${workdir}/src"); + } + public void testGroupsParamEscape() throws Exception { assertEquals(Arrays.asList("a b", "a\\b"), Arrays.asList(Main.splitGroupArg("a\\ b a\\\\b"))); } private static final String DONT_APPEND_PATH = new String("DONT_APPEND_PATH"); + private static final String IGNORE = new String("IGNORE"); private void doRunCompiler(String golden, String stdOut, String stdErr, String... fileContentAndExtraOptions) throws Exception { doRunCompiler(equivalentValidator(golden), equivalentValidator(stdOut), equivalentValidator(stdErr), fileContentAndExtraOptions); @@ -590,6 +788,9 @@ appendPath = false; continue; } + if (extraOption == IGNORE) { + continue; + } options.add(extraOption.replace("${workdir}", wd.getAbsolutePath())); }