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