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

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


The following commit(s) were added to refs/heads/master by this push:
     new 41da26b  [NETBEANS-253] Fixing watches with lambdas. (#358)
41da26b is described below

commit 41da26b7de7506c86dee891b88b50f3c6f37b5bb
Author: Jan Lahoda <[email protected]>
AuthorDate: Wed Jan 31 18:49:31 2018 +0100

    [NETBEANS-253] Fixing watches with lambdas. (#358)
    
    -passing an URI to the created (memory) FileObject when compiling a class 
using JavaSourceUtilImpl to prevent exceptions
    -improving type detection for watches (don't using 
Trees.getElement(...).getReturnType() and alike, but rather 
Trees.getTypeMirror(...), as the latter has generics instantiated, etc.)
---
 debugger.jpda.projects/nbproject/project.xml       |  31 +++++
 .../debugger/jpda/projects/ScanLocalVars.java      |  33 +----
 .../jpda/projects/CodeSnippetCompilerTest.java     | 107 +++++++++++++++
 .../modules/java/source/JavaSourceUtilImpl.java    |   2 +
 .../modules/java/source/indexing/APTUtils.java     |   4 +-
 .../java/source/JavaSourceUtilImplTest.java        | 147 ++++++++++++++++++++-
 6 files changed, 295 insertions(+), 29 deletions(-)

diff --git a/debugger.jpda.projects/nbproject/project.xml 
b/debugger.jpda.projects/nbproject/project.xml
index e223d09..c1c6ce7 100644
--- a/debugger.jpda.projects/nbproject/project.xml
+++ b/debugger.jpda.projects/nbproject/project.xml
@@ -178,10 +178,41 @@
                         <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 b14bc6a..2151563 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 @@ final class ScanLocalVars extends 
ErrorAwareTreePathScanner<Void, Void> {
     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 @@ final class ScanLocalVars extends 
ErrorAwareTreePathScanner<Void, Void> {
         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 0000000..8dd3a8f
--- /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 6c6b060..5d0f203 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 @@ public final class JavaSourceUtilImpl extends 
org.netbeans.modules.java.preproce
         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 3f26bcc..68e4a4b 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 class APTUtils implements ChangeListener, 
PropertyChangeListener {
             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 4db230e..90e55f9 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 @@ package org.netbeans.modules.java.source;
 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 @@ public class JavaSourceUtilImplTest extends NbTestCase {
     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 class JavaSourceUtilImplTest extends NbTestCase {
         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 @@ public class JavaSourceUtilImplTest extends NbTestCase {
         }
         System.out.printf("Dumped into: %s%n", 
FileUtil.getFileDisplayName(wd));
     }
+
+    static {
+        System.setProperty("SourcePath.no.source.filter", "true");
+    }
 }

-- 
To stop receiving notification emails like this one, please contact
[email protected].

---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

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

Reply via email to