You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@netbeans.apache.org by ne...@apache.org on 2023/01/30 12:06:10 UTC
[netbeans] branch delivery updated: [NETBEANS-4054] Ensuring progress when javac crashes while batch evaluating hints.
This is an automated email from the ASF dual-hosted git repository.
neilcsmith pushed a commit to branch delivery
in repository https://gitbox.apache.org/repos/asf/netbeans.git
The following commit(s) were added to refs/heads/delivery by this push:
new b82df809031 [NETBEANS-4054] Ensuring progress when javac crashes while batch evaluating hints.
new 3e4dd33594d Merge pull request #5384 from jlahoda/NETBEANS-4054
b82df809031 is described below
commit b82df809031696fd24a53bcef309a2b0e8473757
Author: Jan Lahoda <jl...@netbeans.org>
AuthorDate: Sun Jan 29 13:43:33 2023 +0100
[NETBEANS-4054] Ensuring progress when javac crashes while batch evaluating hints.
---
.../org/netbeans/lib/nbjavac/services/NBAttr.java | 12 ++
.../java/hints/spiimpl/batch/BatchSearch.java | 12 +-
.../java/hints/spiimpl/batch/BatchSearchTest.java | 196 +++++++++++++++++----
3 files changed, 181 insertions(+), 39 deletions(-)
diff --git a/java/lib.nbjavac/src/org/netbeans/lib/nbjavac/services/NBAttr.java b/java/lib.nbjavac/src/org/netbeans/lib/nbjavac/services/NBAttr.java
index bca9eb351e6..4c64615a2b7 100644
--- a/java/lib.nbjavac/src/org/netbeans/lib/nbjavac/services/NBAttr.java
+++ b/java/lib.nbjavac/src/org/netbeans/lib/nbjavac/services/NBAttr.java
@@ -43,6 +43,8 @@ import java.lang.invoke.MethodType;
*/
public class NBAttr extends Attr {
+ public static boolean TEST_DO_SINGLE_FAIL;
+
public static void preRegister(Context context) {
context.put(attrKey, new Context.Factory<Attr>() {
public Attr make(Context c) {
@@ -60,6 +62,16 @@ public class NBAttr extends Attr {
tm = TreeMaker.instance(context);
}
+ @Override
+ public void attribClass(DiagnosticPosition pos, ClassSymbol c) {
+ cancelService.abortIfCanceled();
+ if (TEST_DO_SINGLE_FAIL) {
+ TEST_DO_SINGLE_FAIL = false;
+ throw new AssertionError("Test requested failure");
+ }
+ super.attribClass(pos, c);
+ }
+
@Override
public void visitClassDef(JCClassDecl tree) {
cancelService.abortIfCanceled();
diff --git a/java/spi.java.hints/src/org/netbeans/modules/java/hints/spiimpl/batch/BatchSearch.java b/java/spi.java.hints/src/org/netbeans/modules/java/hints/spiimpl/batch/BatchSearch.java
index f01480dfa64..b5abcb3f142 100644
--- a/java/spi.java.hints/src/org/netbeans/modules/java/hints/spiimpl/batch/BatchSearch.java
+++ b/java/spi.java.hints/src/org/netbeans/modules/java/hints/spiimpl/batch/BatchSearch.java
@@ -234,8 +234,9 @@ public class BatchSearch {
if (cancel.get())
return;
final AtomicBoolean stop = new AtomicBoolean();
+ List<FileObject> currentInputList = toProcess.subList(currentPointer.get(), toProcess.size());
// JavaSource js = JavaSource.create(e.getKey(), f);
- JavaSource js = JavaSource.create(e.getKey(), toProcess.subList(currentPointer.get(), toProcess.size()));
+ JavaSource js = JavaSource.create(e.getKey(), currentInputList);
js.runUserActionTask(new Task<CompilationController>() {
@Override
@@ -246,8 +247,15 @@ public class BatchSearch {
boolean cont = true;
try {
- if (parameter.toPhase(Phase.RESOLVED).compareTo(Phase.RESOLVED) < 0)
+ if (parameter.toPhase(Phase.RESOLVED).compareTo(Phase.RESOLVED) < 0) {
+ if (currentInputList.size() == 1) {
+ //the javac crashed while processing the (single) file, we must ensure progress, otherwise infinite loop in processing would happen:
+ problems.add(new MessageImpl(MessageKind.WARNING, "An error occurred while processing file: " + FileUtil.getFileDisplayName(parameter.getFileObject()) + ", please see the IDE log for more information."));
+ currentPointer.incrementAndGet();
+ }
+
return ;
+ }
progress.setMessage("processing: " + FileUtil.getFileDisplayName(parameter.getFileObject()));
Resource r = file2Resource.get(parameter.getFileObject());
diff --git a/java/spi.java.hints/test/unit/src/org/netbeans/modules/java/hints/spiimpl/batch/BatchSearchTest.java b/java/spi.java.hints/test/unit/src/org/netbeans/modules/java/hints/spiimpl/batch/BatchSearchTest.java
index a03e88ebee1..511b4e31145 100644
--- a/java/spi.java.hints/test/unit/src/org/netbeans/modules/java/hints/spiimpl/batch/BatchSearchTest.java
+++ b/java/spi.java.hints/test/unit/src/org/netbeans/modules/java/hints/spiimpl/batch/BatchSearchTest.java
@@ -22,7 +22,6 @@ import org.netbeans.modules.java.hints.spiimpl.batch.TestUtils.File;
import org.netbeans.modules.java.hints.spiimpl.MessageImpl;
import org.netbeans.modules.java.hints.providers.spi.HintDescription;
import java.net.URL;
-import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
@@ -35,24 +34,32 @@ import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.concurrent.atomic.AtomicBoolean;
-import java.util.regex.Pattern;
+import java.util.function.Consumer;
+import java.util.function.Function;
import junit.framework.TestSuite;
import org.netbeans.api.java.classpath.ClassPath;
import org.netbeans.api.java.classpath.GlobalPathRegistry;
import org.netbeans.api.java.classpath.GlobalPathRegistryEvent;
import org.netbeans.api.java.classpath.GlobalPathRegistryListener;
+import org.netbeans.api.java.source.ClasspathInfo;
import org.netbeans.api.java.source.CompilationController;
+import org.netbeans.api.java.source.JavaSource;
+import org.netbeans.api.java.source.JavaSource.Phase;
import org.netbeans.api.java.source.SourceUtilsTestUtil;
import org.netbeans.core.startup.Main;
import org.netbeans.junit.NbTestCase;
import org.netbeans.junit.NbTestSuite;
import org.netbeans.junit.RandomlyFails;
+import org.netbeans.lib.nbjavac.services.NBAttr;
import org.netbeans.modules.java.hints.spiimpl.batch.BatchSearch.BatchResult;
import org.netbeans.modules.java.hints.spiimpl.batch.BatchSearch.Folder;
import org.netbeans.modules.java.hints.spiimpl.batch.BatchSearch.Resource;
+import org.netbeans.modules.java.hints.spiimpl.batch.BatchSearch.VerifiedSpansCallBack;
+import org.netbeans.modules.java.source.BootClassPathUtil;
import org.netbeans.modules.parsing.impl.indexing.CacheFolder;
import org.netbeans.modules.parsing.impl.indexing.MimeTypes;
import org.netbeans.modules.parsing.impl.indexing.RepositoryUpdater;
+import org.netbeans.modules.parsing.lucene.support.LowMemoryWatcherAccessor;
import org.netbeans.spi.editor.hints.ErrorDescription;
import org.netbeans.spi.java.classpath.ClassPathProvider;
import org.netbeans.spi.java.classpath.support.ClassPathSupport;
@@ -293,6 +300,147 @@ public class BatchSearchTest extends NbTestCase {
assertEquals(golden, output);
}
+ public void testBatchSearchOutOfMemory() throws Exception {
+ FileObject data = FileUtil.createFolder(workdir, "data");
+ FileObject dataSrc1 = FileUtil.createFolder(data, "src1");
+ writeFilesAndWaitForScan(dataSrc1,
+ new File("test/Test1.java", "package test; public class Test1 { private void test() { java.io.File f = null; f.isDirectory(); } }"),
+ new File("test/Test2.java", "package test; public class Test2 { private void test() { java.io.File f = null; f.isDirectory(); } }"),
+ new File("test/Test3.java", "package test; public class Test3 { private void test() { java.io.File f = null; f.isDirectory(); } }"));
+
+ ClassPathProviderImpl.setSourceRoots(Arrays.asList(dataSrc1));
+
+ Iterable<? extends HintDescription> hints = prepareHints("$1.isDirectory()", "$1", "java.io.File");
+ BatchResult result = BatchSearch.findOccurrences(hints, Scopes.specifiedFoldersScope(Folder.convert(data)));
+ Map<String, Iterable<String>> output = new HashMap<String, Iterable<String>>();
+
+ for (Entry<FileObject, Collection<? extends Resource>> e : result.getResourcesWithRoots().entrySet()) {
+ Collection<String> resourcesRepr = new HashSet<String>();
+
+ for (Resource r : e.getValue()) {
+ resourcesRepr.add(r.getRelativePath());
+ }
+
+ output.put(e.getKey().toURL().toExternalForm(), resourcesRepr);
+ }
+
+ Map<String, Iterable<String>> golden = new HashMap<String, Iterable<String>>();
+
+ golden.put(data.toURL().toExternalForm(), new HashSet<String>(Arrays.asList("src1/test/Test1.java", "src1/test/Test2.java", "src1/test/Test3.java")));
+
+ assertEquals(golden, output);
+
+ //check verification:
+ Map<String, Map<String, Iterable<String>>> verifiedOutput = verifiedSpans(result, false, c -> new VerifiedSpansCallBack() {
+ int callbacks;
+ @Override
+ public void groupStarted() {
+ c.groupStarted();
+ }
+ @Override
+ public boolean spansVerified(CompilationController wc, Resource r, Collection<? extends ErrorDescription> hints) throws Exception {
+ if (++callbacks == 1) {
+ LowMemoryWatcherAccessor.setLowMemory(true);
+ }
+ return c.spansVerified(wc, r, hints);
+ }
+
+ @Override
+ public void groupFinished() {
+ c.groupFinished();
+ }
+
+ @Override
+ public void cannotVerifySpan(Resource r) {
+ c.cannotVerifySpan(r);
+ }
+ }, errors -> assertEquals(0, errors.size()));
+ Map<String, Map<String, Iterable<String>>> verifiedGolden = new HashMap<String, Map<String, Iterable<String>>>();
+
+ Map<String, Iterable<String>> verifiedGoldenPart = new HashMap<String, Iterable<String>>();
+
+ verifiedGoldenPart.put("src1/test/Test1.java", Arrays.<String>asList("0:82-0:93:verifier:"));
+ verifiedGoldenPart.put("src1/test/Test2.java", Arrays.<String>asList("0:82-0:93:verifier:"));
+ verifiedGoldenPart.put("src1/test/Test3.java", Arrays.<String>asList("0:82-0:93:verifier:"));
+
+ verifiedGolden.put(data.toURL().toExternalForm(), verifiedGoldenPart);
+
+ assertEquals(verifiedGolden, verifiedOutput);
+ }
+
+ public void testBatchSearchParserCrashProgressEnsured() throws Exception {
+ writeFilesAndWaitForScan(src1,
+ new File("test/Test1.java", "package test; public class Test1 { private void test() { java.io.File f = null; f.isDirectory(); } }"));
+
+ Iterable<? extends HintDescription> hints = prepareHints("$1.isDirectory()", "$1", "java.io.File");
+ BatchResult result = BatchSearch.findOccurrences(hints, Scopes.allOpenedProjectsScope());
+ Map<String, Iterable<String>> output = new HashMap<String, Iterable<String>>();
+
+ for (Entry<FileObject, Collection<? extends Resource>> e : result.getResourcesWithRoots().entrySet()) {
+ Collection<String> resourcesRepr = new HashSet<String>();
+
+ for (Resource r : e.getValue()) {
+ resourcesRepr.add(r.getRelativePath());
+ }
+
+ output.put(e.getKey().toURL().toExternalForm(), resourcesRepr);
+ }
+
+ Map<String, Iterable<String>> golden = new HashMap<String, Iterable<String>>();
+
+ golden.put(src1.toURL().toExternalForm(), new HashSet<String>(Arrays.asList("test/Test1.java")));
+
+ assertEquals(golden, output);
+
+ //check verification:
+ Entry<ClasspathInfo, Collection<FileObject>> cpAndFile = BatchUtilities.sortFiles(Arrays.asList(src1.getFileObject("test/Test1.java"))).entrySet().iterator().next();
+ JavaSource js = JavaSource.create(cpAndFile.getKey(), cpAndFile.getValue());
+
+ try {
+ js.runUserActionTask(cc -> {
+ NBAttr.TEST_DO_SINGLE_FAIL = true; //the upcoming attribution will fail
+ cc.toPhase(Phase.RESOLVED);
+ }, true);
+ fail("Expected exception not thrown!");
+ } catch (IllegalStateException ex) {
+ //OK
+ }
+
+ Map<String, Map<String, Iterable<String>>> verifiedOutput = verifiedSpans(result, false, c -> new VerifiedSpansCallBack() {
+ @Override
+ public void groupStarted() {
+ c.groupStarted();
+ NBAttr.TEST_DO_SINGLE_FAIL = true; //the upcoming attribution will fail
+ }
+ @Override
+ public boolean spansVerified(CompilationController wc, Resource r, Collection<? extends ErrorDescription> hints) throws Exception {
+ return c.spansVerified(wc, r, hints);
+ }
+
+ @Override
+ public void groupFinished() {
+ c.groupFinished();
+ }
+
+ @Override
+ public void cannotVerifySpan(Resource r) {
+ c.cannotVerifySpan(r);
+ }
+ }, errors -> {
+ assertEquals(1, errors.size());
+ assertTrue(errors.get(0).text.contains("IDE log"));
+ });
+
+ Map<String, Map<String, Iterable<String>>> verifiedGolden = new HashMap<String, Map<String, Iterable<String>>>();
+
+ assertEquals(verifiedGolden, verifiedOutput);
+
+ //prevent GC:
+ js.runUserActionTask(cc -> {
+ assertTrue(true);
+ }, true);
+ }
+
private FileObject workdir;
private FileObject src1;
private FileObject src2;
@@ -332,9 +480,13 @@ public class BatchSearchTest extends NbTestCase {
}
private Map<String, Map<String, Iterable<String>>> verifiedSpans(BatchResult candidates, boolean doNotRegisterClassPath) throws Exception {
+ return verifiedSpans(candidates, doNotRegisterClassPath, c -> c, errors -> assertEquals(0, errors.size()));
+ }
+
+ private Map<String, Map<String, Iterable<String>>> verifiedSpans(BatchResult candidates, boolean doNotRegisterClassPath, Function<VerifiedSpansCallBack, VerifiedSpansCallBack> wrapper, Consumer<List<MessageImpl>> validateErrors) throws Exception {
final Map<String, Map<String, Iterable<String>>> result = new HashMap<String, Map<String, Iterable<String>>>();
List<MessageImpl> errors = new LinkedList<MessageImpl>();
- BatchSearch.getVerifiedSpans(candidates, new ProgressHandleWrapper(1), new BatchSearch.VerifiedSpansCallBack() {
+ BatchSearch.getVerifiedSpans(candidates, new ProgressHandleWrapper(1), wrapper.apply(new VerifiedSpansCallBack() {
@Override
public void groupStarted() {}
@Override
@@ -361,7 +513,9 @@ public class BatchSearchTest extends NbTestCase {
public void cannotVerifySpan(Resource r) {
fail("Cannot verify: " +r.getRelativePath());
}
- }, doNotRegisterClassPath, errors, new AtomicBoolean());
+ }), doNotRegisterClassPath, errors, new AtomicBoolean());
+
+ validateErrors.accept(errors);
return result;
}
@@ -382,7 +536,7 @@ public class BatchSearchTest extends NbTestCase {
@Override
public synchronized ClassPath findClassPath(FileObject file, String type) {
if (ClassPath.BOOT.equals(type)) {
- return ClassPathSupport.createClassPath(getBootClassPath().toArray(new URL[0]));
+ return BootClassPathUtil.getBootClassPath();
}
if (ClassPath.COMPILE.equals(type)) {
@@ -402,36 +556,4 @@ public class BatchSearchTest extends NbTestCase {
}
- //TODO: copied from SourceUtilsTestUtil:
- private static List<URL> bootClassPath;
-
- public static synchronized List<URL> getBootClassPath() {
- if (bootClassPath == null) {
- String cp = System.getProperty("sun.boot.class.path");
- List<URL> urls = new ArrayList<URL>();
- String[] paths = cp.split(Pattern.quote(System.getProperty("path.separator")));
-
- for (String path : paths) {
- java.io.File f = new java.io.File(path);
-
- if (!f.canRead())
- continue;
-
- FileObject fo = FileUtil.toFileObject(f);
-
- if (FileUtil.isArchiveFile(fo)) {
- fo = FileUtil.getArchiveRoot(fo);
- }
-
- if (fo != null) {
- urls.add(fo.toURL());
- }
- }
-
- bootClassPath = urls;
- }
-
- return bootClassPath;
- }
-
}
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@netbeans.apache.org
For additional commands, e-mail: commits-help@netbeans.apache.org
For further information about the NetBeans mailing lists, visit:
https://cwiki.apache.org/confluence/display/NETBEANS/Mailing+lists