You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@netbeans.apache.org by GitBox <gi...@apache.org> on 2018/01/31 17:49:35 UTC

[GitHub] geertjanw closed pull request #358: [NETBEANS-253] Fixing watches with lambdas.

geertjanw closed pull request #358: [NETBEANS-253] Fixing watches with lambdas.
URL: https://github.com/apache/incubator-netbeans/pull/358
 
 
   

This is a PR merged from a forked repository.
As GitHub hides the original diff on merge, it is displayed below for
the sake of provenance:

As this is a foreign pull request (from a fork), the diff is supplied
below (as it won't show otherwise due to GitHub magic):

diff --git a/debugger.jpda.projects/nbproject/project.xml b/debugger.jpda.projects/nbproject/project.xml
index e223d0928..c1c6ce7aa 100644
--- a/debugger.jpda.projects/nbproject/project.xml
+++ b/debugger.jpda.projects/nbproject/project.xml
@@ -177,11 +177,42 @@
                         <code-name-base>org.netbeans.libs.junit4</code-name-base>
                         <compile-dependency/>
                     </test-dependency>
+                    <test-dependency>
+                        <code-name-base>org.netbeans.modules.classfile</code-name-base>
+                        <compile-dependency/>
+                    </test-dependency>
+                    <test-dependency>
+                        <code-name-base>org.netbeans.modules.editor.mimelookup</code-name-base>
+                        <compile-dependency/>
+                        <test/>
+                    </test-dependency>
+                    <test-dependency>
+                        <code-name-base>org.netbeans.modules.java.source</code-name-base>
+                        <compile-dependency/>
+                    </test-dependency>
+                    <test-dependency>
+                        <code-name-base>org.netbeans.modules.java.source.base</code-name-base>
+                        <compile-dependency/>
+                        <test/>
+                    </test-dependency>
                     <test-dependency>
                         <code-name-base>org.netbeans.modules.nbjunit</code-name-base>
                         <recursive/>
                         <compile-dependency/>
                     </test-dependency>
+                    <test-dependency>
+                        <code-name-base>org.netbeans.modules.parsing.indexing</code-name-base>
+                        <compile-dependency/>
+                        <test/>
+                    </test-dependency>
+                    <test-dependency>
+                        <code-name-base>org.netbeans.modules.parsing.nb</code-name-base>
+                        <compile-dependency/>
+                    </test-dependency>
+                    <test-dependency>
+                        <code-name-base>org.netbeans.modules.projectapi.nb</code-name-base>
+                        <compile-dependency/>
+                    </test-dependency>
                 </test-type>
             </test-dependencies>
             <friend-packages>
diff --git a/debugger.jpda.projects/src/org/netbeans/modules/debugger/jpda/projects/ScanLocalVars.java b/debugger.jpda.projects/src/org/netbeans/modules/debugger/jpda/projects/ScanLocalVars.java
index b14bc6a0f..21515639f 100644
--- a/debugger.jpda.projects/src/org/netbeans/modules/debugger/jpda/projects/ScanLocalVars.java
+++ b/debugger.jpda.projects/src/org/netbeans/modules/debugger/jpda/projects/ScanLocalVars.java
@@ -133,9 +133,9 @@ private boolean isMethodCode() {
     public Void visitReturn(ReturnTree node, Void p) {
         if (isMethodCode() /*&& phase == PHASE_INSIDE_SELECTION*/) {
             hasReturns = true;
-            Element retExpElem = info.getTrees().getElement(new TreePath(getCurrentPath(), node.getExpression())); //.asType().toString();
-            if (retExpElem != null) {
-                returnTypes.add(getElementType(retExpElem));
+            TypeMirror type = info.getTrees().getTypeMirror(new TreePath(getCurrentPath(), node.getExpression())); //.asType().toString();
+            if (type != null && type.getKind() != TypeKind.ERROR) {
+                returnTypes.add(type);
             } else {
                 // Unresolved element
                 TypeElement object = info.getElements().getTypeElement("java.lang.Object");
@@ -152,36 +152,15 @@ public Void visitExpressionStatement(ExpressionStatementTree node, Void p) {
         if (node == lastStatement) {
             if (!hasReturns) {
                 ExpressionTree expression = node.getExpression();
-                Element retExpElem = info.getTrees().getElement(new TreePath(getCurrentPath(), expression));
-                if (retExpElem == null) {
-                    TreePath elementPath = null;
-                    if (Tree.Kind.ASSIGNMENT.equals(expression.getKind())) {
-                        elementPath = new TreePath(getCurrentPath(), ((AssignmentTree) expression).getVariable());
-                    } else if (Tree.Kind.VARIABLE.equals(expression.getKind())) {
-                        elementPath = new TreePath(getCurrentPath(), ((VariableTree) expression));
-                    }
-                    if (elementPath != null) {
-                        retExpElem = info.getTrees().getElement(elementPath);
-                    }
-                }
-                if (retExpElem != null && !TypeKind.ERROR.equals(retExpElem.asType().getKind())) {
-                    returnTypes.add(getElementType(retExpElem));
+                TypeMirror type = info.getTrees().getTypeMirror(new TreePath(getCurrentPath(), expression));
+                if (type != null && !TypeKind.ERROR.equals(type.getKind())) {
+                    returnTypes.add(type);
                 }
             }
         }
         return super.visitExpressionStatement(node, p);
     }
     
-    private TypeMirror getElementType(Element element) {
-        switch (element.getKind()) {
-            case METHOD:
-            case CONSTRUCTOR:
-                return ((ExecutableElement) element).getReturnType();
-            default:
-                return element.asType();
-        }
-    }
-
     Set<VariableElement> getReferencedVariables() {
         return referencedVariables;
     }
diff --git a/debugger.jpda.projects/test/unit/src/org/netbeans/modules/debugger/jpda/projects/CodeSnippetCompilerTest.java b/debugger.jpda.projects/test/unit/src/org/netbeans/modules/debugger/jpda/projects/CodeSnippetCompilerTest.java
new file mode 100644
index 000000000..8dd3a8fe7
--- /dev/null
+++ b/debugger.jpda.projects/test/unit/src/org/netbeans/modules/debugger/jpda/projects/CodeSnippetCompilerTest.java
@@ -0,0 +1,107 @@
+/*
+ * 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.modules.debugger.jpda.projects;
+
+import com.sun.source.tree.StatementTree;
+import com.sun.source.util.SourcePositions;
+import com.sun.source.util.TreePath;
+import com.sun.tools.classfile.ClassFile;
+import com.sun.tools.classfile.Method;
+import java.io.ByteArrayInputStream;
+import org.netbeans.api.java.classpath.ClassPath;
+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.api.java.source.TestUtilities;
+import org.netbeans.junit.NbTestCase;
+import org.netbeans.spi.java.classpath.ClassPathProvider;
+import org.netbeans.spi.java.classpath.support.ClassPathSupport;
+import org.openide.filesystems.FileObject;
+import org.openide.filesystems.FileUtil;
+
+/**
+ *
+ * @author lahvac
+ */
+public class CodeSnippetCompilerTest extends NbTestCase {
+
+    public CodeSnippetCompilerTest(String name) {
+        super(name);
+    }
+
+    private FileObject wd;
+    private FileObject root;
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        clearWorkDir();
+        SourceUtilsTestUtil.prepareTest(new String[0], new Object[] {
+            new ClassPathProvider() {
+                @Override
+                public ClassPath findClassPath(FileObject file, String type) {
+                    if (type == ClassPath.SOURCE) {
+                        return ClassPathSupport.createClassPath(root);
+                    }
+                    return null;
+                }
+            }
+        });
+        wd = FileUtil.toFileObject(FileUtil.normalizeFile(getWorkDir()));
+        root = FileUtil.createFolder(wd, "src");    //NOI18N
+    }
+
+    private static FileObject createFile(
+            final FileObject root,
+            final String path,
+            final String content) throws Exception {
+        FileObject file = FileUtil.createData(root, path);
+        TestUtilities.copyStringToFile(file, content);
+        return file;
+    }
+
+    public void testInferResultType() throws Exception {
+        String code = "package test;\n class A { public void test(java.util.List<String> l) { } }";
+        String watch = "l.stream().map(s -> s.length()).collect(java.util.stream.Collectors.toList());";
+        int pos = code.indexOf("{", code.indexOf("{") + 1);
+        FileObject java = createFile(root, "test/A.java", code);    //NOI18N
+        JavaSource.forFileObject(java).runUserActionTask((CompilationController cc) -> {
+            cc.toPhase(Phase.RESOLVED);
+            TreePath posPath = cc.getTreeUtilities().pathFor(pos);
+            StatementTree tree = cc.getTreeUtilities().parseStatement(
+                watch,
+                new SourcePositions[1]
+            );
+            cc.getTreeUtilities().attributeTree(tree, cc.getTrees().getScope(posPath));
+            TreePath tp = new TreePath(posPath, tree);
+            ClassToInvoke cti = CodeSnippetCompiler.compileToClass(cc, watch, 0, cc.getJavaSource(), java, -1, tp, tree, false);
+
+            ClassFile cf = ClassFile.read(new ByteArrayInputStream(cti.bytecode));
+
+            for (Method m : cf.methods) {
+                if (cf.constant_pool.getUTF8Value(m.name_index).equals("invoke")) {
+                    assertEquals("(Ljava/util/List;)Ljava/util/List;", cf.constant_pool.getUTF8Value(m.descriptor.index));
+                }
+            }
+        }, true);
+
+    }
+
+}
diff --git a/java.source.base/src/org/netbeans/modules/java/source/JavaSourceUtilImpl.java b/java.source.base/src/org/netbeans/modules/java/source/JavaSourceUtilImpl.java
index 6c6b060fc..5d0f2035b 100644
--- a/java.source.base/src/org/netbeans/modules/java/source/JavaSourceUtilImpl.java
+++ b/java.source.base/src/org/netbeans/modules/java/source/JavaSourceUtilImpl.java
@@ -143,6 +143,8 @@ protected long createTaggedCompilationController(FileObject file, long currenTag
         final JavaFileObject toCompile = FileObjects.memoryFileObject(
                 ncs[0],
                 ncs[1]+'.'+file.getExt(),
+                file.toURI(),
+                System.currentTimeMillis(),
                 content);
         boolean success = false;
         final TransactionContext ctx = TransactionContext.beginTrans()
diff --git a/java.source.base/src/org/netbeans/modules/java/source/indexing/APTUtils.java b/java.source.base/src/org/netbeans/modules/java/source/indexing/APTUtils.java
index 3f26bccda..68e4a4bd2 100644
--- a/java.source.base/src/org/netbeans/modules/java/source/indexing/APTUtils.java
+++ b/java.source.base/src/org/netbeans/modules/java/source/indexing/APTUtils.java
@@ -269,9 +269,11 @@ public URL sourceOutputDirectory() {
             if (pp == null) {
                 pp = ClassPath.EMPTY;
             }
+            ClassLoader contextCL = Context.class.getClassLoader();
             cl = CachingArchiveClassLoader.forClassPath(
                     pp,
-                    new BypassOpenIDEUtilClassLoader(Context.class.getClassLoader()),
+                    contextCL != null ? new BypassOpenIDEUtilClassLoader(contextCL)
+                                      : ClassLoader.getSystemClassLoader().getParent(),
                     usedRoots);
             classLoaderCache = !DISABLE_CLASSLOADER_CACHE ? new ClassLoaderRef(cl, root, isModule) : null;
         } else {
diff --git a/java.source.base/test/unit/src/org/netbeans/modules/java/source/JavaSourceUtilImplTest.java b/java.source.base/test/unit/src/org/netbeans/modules/java/source/JavaSourceUtilImplTest.java
index 4db230e8e..90e55f951 100644
--- a/java.source.base/test/unit/src/org/netbeans/modules/java/source/JavaSourceUtilImplTest.java
+++ b/java.source.base/test/unit/src/org/netbeans/modules/java/source/JavaSourceUtilImplTest.java
@@ -21,20 +21,35 @@
 import java.io.ByteArrayInputStream;
 import java.io.IOException;
 import java.io.OutputStream;
+import java.net.URL;
 import java.util.Arrays;
+import java.util.Collections;
+import java.util.EnumSet;
 import java.util.HashSet;
 import java.util.Map;
+import java.util.Map.Entry;
 import java.util.Set;
 import java.util.stream.Collectors;
+import javax.swing.event.ChangeListener;
+import javax.tools.DiagnosticListener;
+import javax.tools.JavaFileObject;
 import org.junit.Before;
 import org.junit.Test;
+import org.netbeans.api.java.classpath.ClassPath;
+import org.netbeans.api.java.classpath.JavaClassPathConstants;
+import org.netbeans.api.java.queries.AnnotationProcessingQuery;
 import org.netbeans.api.java.source.TestUtilities;
 import org.netbeans.junit.NbTestCase;
 import org.netbeans.modules.classfile.ClassFile;
 import org.netbeans.modules.java.source.parsing.FileObjects;
+import org.netbeans.spi.java.classpath.ClassPathProvider;
+import org.netbeans.spi.java.classpath.support.ClassPathSupport;
+import org.netbeans.spi.java.queries.AnnotationProcessingQueryImplementation;
+import org.netbeans.spi.java.queries.SourceLevelQueryImplementation;
 import org.openide.filesystems.FileLock;
 import org.openide.filesystems.FileObject;
 import org.openide.filesystems.FileUtil;
+import org.openide.util.test.MockLookup;
 
 /**
  *
@@ -45,6 +60,9 @@
     private FileObject wd;
     private FileObject root;
     private FileObject java;
+    private FileObject cache;
+    private FileObject cacheSrc;
+    private FileObject ap;
     
     public JavaSourceUtilImplTest(String name) {
         super(name);
@@ -58,13 +76,136 @@ public void setUp() throws Exception {
         wd = FileUtil.toFileObject(FileUtil.normalizeFile(getWorkDir()));
         root = FileUtil.createFolder(wd, "src");    //NOI18N
         java = createFile(root, "org/nb/A.java","package nb;\n class A {}");    //NOI18N
+        cache = FileUtil.createFolder(wd, "cache");    //NOI18N
+        cacheSrc = FileUtil.createFolder(wd, "cacheSrc");    //NOI18N
+        ap = createFile(cacheSrc, "test/AP.java","");    //NOI18N
     }
     
     @Test
     public void testGenerate() throws Exception {
+        MockLookup.setInstances(new SourceLevelQueryImplementation() {
+            @Override
+            public String getSourceLevel(FileObject javaFile) {
+                return "1.8";
+            }
+        });
+        assertNotNull(root);
+        assertNotNull(java);
+        DiagnosticListener<JavaFileObject> noErrors = d -> {
+            fail(d.getMessage(null));
+        };
+        final Map<String, byte[]> res = new JavaSourceUtilImpl().generate(root, java, "package nb;\n class A { void foo(){}}", noErrors);   //NOI18N
+        assertNotNull(res);
+        assertEquals(1, res.size());
+        Map.Entry<String,byte[]> e = res.entrySet().iterator().next();
+        assertEquals("nb.A", e.getKey());   //NOI18N
+        final ClassFile cf = new ClassFile(new ByteArrayInputStream(e.getValue()));
+        assertEquals(2, cf.getMethodCount());
+        final Set<String> methods = cf.getMethods().stream()
+                .map((m) -> m.getName())
+                .collect(Collectors.toSet());
+        assertEquals(
+                new HashSet<>(Arrays.asList(new String[]{
+                    "<init>",   //NOI18N
+                    "foo"       //NOI18N
+                })),
+                methods);
+    }
+
+    @Test
+    public void testGenerateWithAP() throws Exception {
+        MockLookup.setInstances(new AnnotationProcessingQueryImplementation() {
+            @Override
+            public AnnotationProcessingQuery.Result getAnnotationProcessingOptions(FileObject file) {
+                if (file != java && file != root) return null;
+                return new AnnotationProcessingQuery.Result() {
+                    @Override
+                    public Set<? extends AnnotationProcessingQuery.Trigger> annotationProcessingEnabled() {
+                        return EnumSet.allOf(AnnotationProcessingQuery.Trigger.class);
+                    }
+
+                    @Override
+                    public Iterable<? extends String> annotationProcessorsToRun() {
+                        return Arrays.asList("test.AP");
+                    }
+
+                    @Override
+                    public URL sourceOutputDirectory() {
+                        return cache.toURL();
+                    }
+
+                    @Override
+                    public Map<? extends String, ? extends String> processorOptions() {
+                        return Collections.emptyMap();
+                    }
+
+                    @Override
+                    public void addChangeListener(ChangeListener l) {
+                    }
+
+                    @Override
+                    public void removeChangeListener(ChangeListener l) {
+                    }
+                };
+            }
+        }, new ClassPathProvider() {
+            @Override
+            public ClassPath findClassPath(FileObject file, String type) {
+                if (file != java && file != root) return null;
+                if (type == JavaClassPathConstants.PROCESSOR_PATH) {
+                    return ClassPathSupport.createClassPath(cache);
+                } else if (type == ClassPath.SOURCE) {
+                    return ClassPathSupport.createClassPath(root);
+                }
+                return null;
+            }
+        }, new SourceLevelQueryImplementation() {
+            @Override
+            public String getSourceLevel(FileObject javaFile) {
+                return "1.8";
+            }
+        });
+
+        String apCode = "package test;\n" +
+                        "\n" +
+                        "import java.io.IOException;\n" +
+                        "import java.io.Writer;\n" +
+                        "import java.util.Set;\n" +
+                        "import javax.annotation.processing.AbstractProcessor;\n" +
+                        "import javax.annotation.processing.RoundEnvironment;\n" +
+                        "import javax.annotation.processing.SupportedAnnotationTypes;\n" +
+                        "import javax.annotation.processing.SupportedSourceVersion;\n" +
+                        "import javax.lang.model.element.TypeElement;\n" +
+                        "import javax.lang.model.SourceVersion;\n" +
+                        "\n" +
+                        "@SupportedAnnotationTypes(\"*\") @SupportedSourceVersion(SourceVersion.RELEASE_8)\n" +
+                        "public class AP extends AbstractProcessor {\n" +
+                        "    int round;\n" +
+                        "    @Override\n" +
+                        "    public boolean process(Set<? extends TypeElement> arg0, RoundEnvironment arg1) {\n" +
+                        "        if (round++ == 0) {\n" +
+                        "            try (Writer w = processingEnv.getFiler().createSourceFile(\"nb.Dep\").openWriter()) {\n" +
+                        "                w.write(\"package nb; class Dep { }\");\n" +
+                        "            } catch (IOException ex) {\n" +
+                        "                ex.printStackTrace();\n" +
+                        "                throw new IllegalStateException(ex);\n" +
+                        "            }\n" +
+                        "        }\n" +
+                        "        return false;\n" +
+                        "    }\n" +
+                        "    \n" +
+                        "}\n";
+        DiagnosticListener<JavaFileObject> noErrors = d -> {
+            fail(d.getMessage(null));
+        };
+        for (Entry<String, byte[]> e : new JavaSourceUtilImpl().generate(cacheSrc, ap, apCode, noErrors).entrySet()) {
+            try (OutputStream out = FileUtil.createData(cache, e.getKey().replace(".", "/") + ".class").getOutputStream()) {
+                out.write(e.getValue());
+            }
+        }
         assertNotNull(root);
         assertNotNull(java);
-        final Map<String, byte[]> res = new JavaSourceUtilImpl().generate(root, java, "package nb;\n class A { void foo(){}}", null);   //NOI18N
+        final Map<String, byte[]> res = new JavaSourceUtilImpl().generate(root, java, "package nb;\n class A { Dep dep; void foo(){}}", noErrors);   //NOI18N
         assertNotNull(res);
         assertEquals(1, res.size());
         Map.Entry<String,byte[]> e = res.entrySet().iterator().next();
@@ -108,4 +249,8 @@ private static void dump(
         }
         System.out.printf("Dumped into: %s%n", FileUtil.getFileDisplayName(wd));
     }
+
+    static {
+        System.setProperty("SourcePath.no.source.filter", "true");
+    }
 }


 

----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on GitHub and use the
URL above to go to the specific comment.
 
For queries about this service, please contact Infrastructure at:
users@infra.apache.org


With regards,
Apache Git Services

---------------------------------------------------------------------
To unsubscribe, e-mail: notifications-unsubscribe@netbeans.apache.org
For additional commands, e-mail: notifications-help@netbeans.apache.org

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