This is an automated email from the ASF dual-hosted git repository.

jlahoda pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/netbeans.git


The following commit(s) were added to refs/heads/master by this push:
     new 1115605  When java.lang is not available, avoid throwing a FatalError, 
but rather try to report an error to the user and continue.
1115605 is described below

commit 11156054b7c12b8e1eaf567010d62d83342ac796
Author: Jan Lahoda <jlah...@netbeans.org>
AuthorDate: Sat Oct 9 07:24:09 2021 +0200

    When java.lang is not available, avoid throwing a FatalError, but rather 
try to report an error to the user and continue.
---
 .../lib/nbjavac/services/NBClassFinder.java        |  59 +++++++++
 .../lib/nbjavac/services/NBClassFinderTest.java    | 139 +++++++++++++++++++++
 2 files changed, 198 insertions(+)

diff --git 
a/java/lib.nbjavac/src/org/netbeans/lib/nbjavac/services/NBClassFinder.java 
b/java/lib.nbjavac/src/org/netbeans/lib/nbjavac/services/NBClassFinder.java
index c43f322..11f67b3 100644
--- a/java/lib.nbjavac/src/org/netbeans/lib/nbjavac/services/NBClassFinder.java
+++ b/java/lib.nbjavac/src/org/netbeans/lib/nbjavac/services/NBClassFinder.java
@@ -19,7 +19,23 @@
 package org.netbeans.lib.nbjavac.services;
 
 import com.sun.tools.javac.code.ClassFinder;
+import com.sun.tools.javac.code.Flags;
+import com.sun.tools.javac.code.Kinds.Kind;
+import com.sun.tools.javac.code.Symbol;
+import com.sun.tools.javac.code.Symbol.Completer;
+import com.sun.tools.javac.code.Symbol.CompletionFailure;
 import com.sun.tools.javac.util.Context;
+import com.sun.tools.javac.util.JCDiagnostic;
+import com.sun.tools.javac.util.JCDiagnostic.DiagnosticInfo;
+import com.sun.tools.javac.util.JCDiagnostic.DiagnosticType;
+import com.sun.tools.javac.util.JCDiagnostic.SimpleDiagnosticPosition;
+import com.sun.tools.javac.util.Log;
+import com.sun.tools.javac.util.Names;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.InvocationTargetException;
+import java.util.function.Supplier;
+import java.util.logging.Level;
+import java.util.logging.Logger;
 import javax.tools.JavaFileObject;
 
 /**
@@ -36,8 +52,17 @@ public class NBClassFinder extends ClassFinder {
         });
     }
 
+    private final Context context;
+    private final Names names;
+    private final JCDiagnostic.Factory diagFactory;
+    private final Log log;
+
     public NBClassFinder(Context context) {
         super(context);
+        this.context = context;
+        this.names = Names.instance(context);
+        this.diagFactory = JCDiagnostic.Factory.instance(context);
+        this.log = Log.instance(context);
     }
 
     @Override
@@ -55,4 +80,38 @@ public class NBClassFinder extends ClassFinder {
         return super.preferredFileObject(a, b);
     }
 
+    private Completer completer;
+
+    @Override
+    public Completer getCompleter() {
+        if (completer == null) {
+            try {
+                Class.forName("com.sun.tools.javac.model.LazyTreeLoader");
+                //patched nb-javac, handles missing java.lang itself:
+                completer = super.getCompleter();
+            } catch (ClassNotFoundException e) {
+                Completer delegate = super.getCompleter();
+                completer = sym -> {
+                    delegate.complete(sym);
+                    if (sym.kind == Kind.PCK &&
+                        sym.flatName() == names.java_lang &&
+                        sym.members().isEmpty()) {
+                        sym.flags_field |= Flags.EXISTS;
+                        try {
+                            Class<?> dcfhClass = 
Class.forName("com.sun.tools.javac.code.DeferredCompletionFailureHandler");
+                            Constructor<CompletionFailure> constr = 
CompletionFailure.class.getDeclaredConstructor(Symbol.class, Supplier.class, 
dcfhClass);
+                            Object dcfh = 
dcfhClass.getDeclaredMethod("instance", Context.class).invoke(null, context);
+                            throw constr.newInstance(sym, 
(Supplier<JCDiagnostic>) () -> {
+                                return diagFactory.create(log.currentSource(), 
new SimpleDiagnosticPosition(0), DiagnosticInfo.of(DiagnosticType.ERROR, 
"compiler", "cant.resolve", "package", "java.lang"));
+                            }, dcfh);
+                        } catch (ClassNotFoundException | 
NoSuchMethodException | SecurityException | IllegalAccessException | 
IllegalArgumentException | InvocationTargetException | InstantiationException 
ex) {
+                            
Logger.getLogger(NBClassFinder.class.getName()).log(Level.FINE, null, ex);
+                        }
+                    }
+                };
+            }
+        }
+        return completer;
+    }
+
 }
diff --git 
a/java/lib.nbjavac/test/unit/src/org/netbeans/lib/nbjavac/services/NBClassFinderTest.java
 
b/java/lib.nbjavac/test/unit/src/org/netbeans/lib/nbjavac/services/NBClassFinderTest.java
new file mode 100644
index 0000000..8280dc0
--- /dev/null
+++ 
b/java/lib.nbjavac/test/unit/src/org/netbeans/lib/nbjavac/services/NBClassFinderTest.java
@@ -0,0 +1,139 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.netbeans.lib.nbjavac.services;
+
+import com.sun.source.util.JavacTask;
+import com.sun.tools.javac.api.JavacTool;
+import com.sun.tools.javac.util.Context;
+import java.io.File;
+import java.io.StringWriter;
+import java.net.URI;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+import javax.tools.JavaCompiler;
+import javax.tools.JavaFileObject;
+import javax.tools.SimpleJavaFileObject;
+import javax.tools.StandardJavaFileManager;
+import javax.tools.StandardLocation;
+import javax.tools.ToolProvider;
+import org.netbeans.junit.NbTestCase;
+
+/**
+ *
+ * @author lahvac
+ */
+public class NBClassFinderTest extends NbTestCase {
+
+    public NBClassFinderTest(String testName) {
+        super(testName);
+    }
+
+    public void testEmptyClassPath() throws Exception {
+        String code = "package test; public class Test { void t(String s) { 
Integer i = s; } }";
+        if (hasPatchedNbJavac()) {
+            List<String> expectedErrors;
+            expectedErrors =
+                    Arrays.asList(
+                        "Test.java:1:1: compiler.err.cant.access: java.lang, 
(compiler.misc.fatal.err.no.java.lang)",
+                        "Test.java:1:42: compiler.err.cant.resolve.location: 
kindname.class, String, , , (compiler.misc.location: kindname.class, test.Test, 
null)"
+                    );
+            List<String> actualErrors;
+            actualErrors = compile(code, "-bootclasspath", "", "--system", 
"none", "-XDrawDiagnostics", "-source", "8", "-XDide");
+            assertEquals(expectedErrors, actualErrors);
+            actualErrors = compile(code, "-bootclasspath", "", "--system", 
"none", "-XDrawDiagnostics", "-XDide");
+            assertEquals(expectedErrors, actualErrors);
+            expectedErrors = Arrays.asList("Fatal Error: Unable to find 
package java.lang in classpath or bootclasspath");
+            actualErrors = compile(code, "-bootclasspath", "", "--system", 
"none", "-XDrawDiagnostics", "-source", "8", "-XDide", 
"-XDbackgroundCompilation");
+            assertEquals(expectedErrors, actualErrors);
+            actualErrors = compile(code, "-bootclasspath", "", "--system", 
"none", "-XDrawDiagnostics", "-XDide", "-XDbackgroundCompilation");
+            assertEquals(expectedErrors, actualErrors);
+        } else {
+            List<String> expectedErrors;
+            expectedErrors =
+                    Arrays.asList(
+                        "Test.java:1:22: compiler.err.cant.access: java.lang, 
(compiler.err.cant.resolve: package, java.lang)",
+                        "Test.java:1:42: compiler.err.cant.resolve.location: 
kindname.class, String, , , (compiler.misc.location: kindname.class, test.Test, 
null)"
+                    );
+            List<String> actualErrors;
+            actualErrors = compile(code, "-bootclasspath", "", "--system", 
"none", "-XDrawDiagnostics", "-source", "8", "-XDide");
+            assertEquals(expectedErrors, actualErrors);
+            actualErrors = compile(code, "-bootclasspath", "", "--system", 
"none", "-XDrawDiagnostics", "-XDide");
+            assertEquals(expectedErrors, actualErrors);
+            expectedErrors =
+                    Arrays.asList(
+                        "Test.java:1:22: compiler.err.cant.access: java.lang, 
(compiler.err.cant.resolve: package, java.lang)",
+                        "Test.java:1:42: compiler.err.cant.resolve.location: 
kindname.class, String, , , (compiler.misc.location: kindname.class, test.Test, 
null)"
+                    );
+            actualErrors = compile(code, "-bootclasspath", "", "--system", 
"none", "-XDrawDiagnostics", "-source", "8", "-XDide", 
"-XDbackgroundCompilation");
+            assertEquals(expectedErrors, actualErrors);
+            actualErrors = compile(code, "-bootclasspath", "", "--system", 
"none", "-XDrawDiagnostics", "-XDide", "-XDbackgroundCompilation");
+            assertEquals(expectedErrors, actualErrors);
+        }
+    }
+
+    private static class MyFileObject extends SimpleJavaFileObject {
+        private String text;
+
+        public MyFileObject(String text) {
+            super(URI.create("myfo:/Test.java"), JavaFileObject.Kind.SOURCE);
+            this.text = text;
+        }
+
+        @Override
+        public CharSequence getCharContent(boolean ignoreEncodingErrors) {
+            return text;
+        }
+    }
+
+    private File workingDir;
+
+    @Override
+    protected void setUp() throws Exception {
+        workingDir = getWorkDir();
+    }
+
+    private List<String> compile(String code, String... options) throws 
Exception {
+        final JavaCompiler tool = ToolProvider.getSystemJavaCompiler();
+        assert tool != null;
+
+        StandardJavaFileManager std = tool.getStandardFileManager(null, null, 
null);
+
+        std.setLocation(StandardLocation.CLASS_OUTPUT, 
Collections.singleton(workingDir));
+
+        Context context = new Context();
+        NBClassFinder.preRegister(context);
+        StringWriter sw = new StringWriter();
+        List<String> optionsList = Arrays.asList(options);
+        final JavacTask ct = ((JavacTool)tool).getTask(sw, std, null, 
optionsList, null, Arrays.asList(new MyFileObject(code)), context);
+
+        ct.analyze();
+
+        return Arrays.asList(sw.toString().split("\\R"));
+    }
+
+    private static boolean hasPatchedNbJavac() {
+        try {
+            Class.forName("com.sun.tools.javac.model.LazyTreeLoader");
+            return true;
+        } catch (ClassNotFoundException ex) {
+            return false;
+        }
+    }
+}

---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscr...@netbeans.apache.org
For additional commands, e-mail: commits-h...@netbeans.apache.org

For further information about the NetBeans mailing lists, visit:
https://cwiki.apache.org/confluence/display/NETBEANS/Mailing+lists

Reply via email to