You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@netbeans.apache.org by lk...@apache.org on 2020/10/23 01:10:50 UTC
[netbeans] 03/18: Annotation processors may generate class files:
-that have a name different from any source file in the source roots -even
while running in the editor
This is an automated email from the ASF dual-hosted git repository.
lkishalmi pushed a commit to branch release122
in repository https://gitbox.apache.org/repos/asf/netbeans.git
commit 5c2f2f275c0e0192449d31955d7db4ada705fd6d
Author: Jan Lahoda <jl...@netbeans.org>
AuthorDate: Sun Oct 18 10:06:55 2020 +0200
Annotation processors may generate class files:
-that have a name different from any source file in the source roots
-even while running in the editor
But neither of these seems to be working - fixing.
---
.../java/source/parsing/OutputFileManager.java | 48 ++--
.../parsing/WriteArbitraryClassFileAPTest.java | 269 +++++++++++++++++++++
2 files changed, 288 insertions(+), 29 deletions(-)
diff --git a/java/java.source.base/src/org/netbeans/modules/java/source/parsing/OutputFileManager.java b/java/java.source.base/src/org/netbeans/modules/java/source/parsing/OutputFileManager.java
index 65bf36e..146ead0 100644
--- a/java/java.source.base/src/org/netbeans/modules/java/source/parsing/OutputFileManager.java
+++ b/java/java.source.base/src/org/netbeans/modules/java/source/parsing/OutputFileManager.java
@@ -21,14 +21,12 @@ package org.netbeans.modules.java.source.parsing;
import java.io.File;
import java.io.IOException;
-import java.net.MalformedURLException;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
-import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
@@ -116,22 +114,28 @@ public class OutputFileManager extends CachingFileManager {
File activeRoot = getClassFolderForSource(l, sibling, baseName);
if (activeRoot == null) {
activeRoot = getClassFolderForApt(l, sibling, baseName);
+ }
+ if (activeRoot == null && siblings.hasSibling()) {
+ URL siblingURL = siblings.getSibling();
+ activeRoot = getClassFolderForSourceImpl(siblingURL);
if (activeRoot == null) {
- //Deleted project
- if (this.scp.getRoots().length > 0) {
- LOG.log(
- Level.WARNING,
- "No output for class: {0} sibling: {1} srcRoots: {2}", //NOI18N
- new Object[]{
- className,
- sibling,
- this.scp
- });
- }
- throw new InvalidSourcePath ();
+ activeRoot = getClassFolderForApt(siblingURL);
}
}
- assertValidRoot(activeRoot, l);
+ if (activeRoot == null) {
+ //Deleted project
+ if (this.scp.getRoots().length > 0) {
+ LOG.log(
+ Level.WARNING,
+ "No output for class: {0} sibling: {1} srcRoots: {2}", //NOI18N
+ new Object[]{
+ className,
+ sibling,
+ this.scp
+ });
+ }
+ throw new InvalidSourcePath ();
+ }
baseName = className.replace('.', File.separatorChar); //NOI18N
String nameStr = baseName + '.' + FileObjects.SIG;
final File f = new File (activeRoot, nameStr);
@@ -166,7 +170,6 @@ public class OutputFileManager extends CachingFileManager {
throw new InvalidSourcePath ();
}
}
- assertValidRoot(activeRoot, l);
final String path = FileObjects.resolveRelativePath(pkgName, relativeName);
final File file = FileUtil.normalizeFile(new File (activeRoot,path.replace(FileObjects.NBFS_SEPARATOR_CHAR, File.separatorChar)));
return tx.createFileObject(l, file, activeRoot,null,null);
@@ -461,17 +464,4 @@ public class OutputFileManager extends CachingFileManager {
return ModuleLocation.cast(l).getModuleRoots();
}
}
-
- private void assertValidRoot(
- final File activeRoot,
- final Location l) throws IOException {
- final Collection<? extends URL> roots = getLocationRoots(l);
- if (!roots.contains(BaseUtilities.toURI(activeRoot).toURL())) {
- throw new IOException(String.format(
- "Wrong cache folder: %s, allowed: %s, location: %s", //NOI18N
- activeRoot,
- roots,
- l));
- }
- }
}
diff --git a/java/java.source.base/test/unit/src/org/netbeans/modules/java/source/parsing/WriteArbitraryClassFileAPTest.java b/java/java.source.base/test/unit/src/org/netbeans/modules/java/source/parsing/WriteArbitraryClassFileAPTest.java
new file mode 100644
index 0000000..586c925
--- /dev/null
+++ b/java/java.source.base/test/unit/src/org/netbeans/modules/java/source/parsing/WriteArbitraryClassFileAPTest.java
@@ -0,0 +1,269 @@
+/*
+ * 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.java.source.parsing;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.OutputStreamWriter;
+import java.io.PrintWriter;
+import java.net.URL;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.EnumSet;
+import java.util.List;
+import junit.framework.*;
+import java.util.Map;
+import java.util.Set;
+import java.util.stream.Collectors;
+import javax.annotation.processing.AbstractProcessor;
+import javax.annotation.processing.RoundEnvironment;
+import javax.annotation.processing.SupportedAnnotationTypes;
+import javax.lang.model.element.TypeElement;
+import javax.swing.event.ChangeListener;
+import javax.tools.StandardLocation;
+import org.netbeans.api.annotations.common.CheckForNull;
+import org.netbeans.api.annotations.common.NonNull;
+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.queries.AnnotationProcessingQuery.Result;
+import org.netbeans.api.java.queries.AnnotationProcessingQuery.Trigger;
+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.Task;
+import org.netbeans.junit.NbTestCase;
+import org.netbeans.modules.java.source.TestUtil;
+import org.netbeans.modules.java.source.usages.IndexUtil;
+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.Lookup;
+import org.openide.util.lookup.Lookups;
+import org.openide.util.lookup.ProxyLookup;
+
+public class WriteArbitraryClassFileAPTest extends NbTestCase {
+
+ private FileObject src1;
+ private FileObject src2;
+ private FileObject data;
+
+ static {
+ WriteArbitraryClassFileAPTest.class.getClassLoader().setDefaultAssertionStatus(true);
+ System.setProperty("org.openide.util.Lookup", WriteArbitraryClassFileAPTest.Lkp.class.getName());
+ Assert.assertEquals(WriteArbitraryClassFileAPTest.Lkp.class, Lookup.getDefault().getClass());
+ }
+
+ public static class Lkp extends ProxyLookup {
+
+ private static Lkp DEFAULT;
+
+ public Lkp () {
+ Assert.assertNull(DEFAULT);
+ DEFAULT = this;
+ ClassLoader l = Lkp.class.getClassLoader();
+ this.setLookups(
+ new Lookup [] {
+ Lookups.metaInfServices(l),
+ Lookups.singleton(l),
+ Lookups.singleton(ClassPathProviderImpl.getDefault()),
+ Lookups.singleton(SourceLevelQueryImpl.getDefault()),
+ Lookups.singleton(new APQImpl()),
+ });
+ }
+
+ }
+
+
+ public WriteArbitraryClassFileAPTest(String testName) {
+ super(testName);
+ }
+
+ protected void setUp() throws Exception {
+ clearWorkDir();
+ File workDir = getWorkDir();
+ File cacheFolder = new File (workDir, "cache"); //NOI18N
+ cacheFolder.mkdirs();
+ IndexUtil.setCacheFolder(cacheFolder);
+ FileObject wd = FileUtil.toFileObject(this.getWorkDir());
+ assertNotNull(wd);
+ this.src1 = wd.createFolder("src1");
+ this.data = src1.createData("Test","java");
+ this.src2 = wd.createFolder("src2");
+ FileLock lock = data.lock();
+ try {
+ PrintWriter out = new PrintWriter ( new OutputStreamWriter (data.getOutputStream(lock)));
+ try {
+ out.println ("public class Test {}");
+ } finally {
+ out.close ();
+ }
+ } finally {
+ lock.releaseLock();
+ }
+ ClassPathProviderImpl.getDefault().setClassPaths(TestUtil.getBootClassPath(),
+ ClassPathSupport.createClassPath(new URL[0]),
+ ClassPathSupport.createClassPath(new FileObject[]{this.src1, this.src2}),
+ ClassPathSupport.createClassPath(System.getProperty("java.class.path")));
+ }
+
+ public void testWriteArbitraryClassFile() throws Exception {
+ final JavaSource js = JavaSource.forFileObject(data);
+ assertNotNull(js);
+
+ js.runUserActionTask(new Task<CompilationController>() {
+ public void run(CompilationController parameter) throws IOException {
+ parameter.toPhase(Phase.RESOLVED);
+ List<String> messages = parameter.getDiagnostics()
+ .stream()
+ .map(d -> d.getMessage(null))
+ .map(m -> firstLine(m))
+ .collect(Collectors.toList());
+ assertEquals(Collections.emptyList(), messages);
+ }
+ },true);
+ }
+
+ private String firstLine(String m) {
+ int newLine = m.indexOf('\n');
+ if (newLine == (-1)) return m;
+ return m.substring(0, newLine);
+ }
+
+ private static class ClassPathProviderImpl implements ClassPathProvider {
+
+ private static ClassPathProviderImpl instance;
+
+ private ClassPath compile;
+ private ClassPath boot;
+ private ClassPath src;
+ private ClassPath processorPath;
+
+ private ClassPathProviderImpl () {
+
+ }
+
+ public synchronized ClassPath findClassPath(FileObject file, String type) {
+ if (ClassPath.COMPILE.equals(type)) {
+ return compile;
+ }
+ else if (ClassPath.BOOT.equals(type)) {
+ return boot;
+ }
+ else if (ClassPath.SOURCE.equals(type)) {
+ return src;
+ }
+ else if (JavaClassPathConstants.PROCESSOR_PATH.equals(type)) {
+ return processorPath;
+ }
+ else {
+ return null;
+ }
+ }
+
+ public synchronized void setClassPaths (ClassPath boot, ClassPath compile, ClassPath src, ClassPath processorPath) {
+ this.boot = boot;
+ this.compile = compile;
+ this.src = src;
+ this.processorPath = processorPath;
+ }
+
+ public static synchronized ClassPathProviderImpl getDefault () {
+ if (instance == null) {
+ instance = new ClassPathProviderImpl ();
+ }
+ return instance;
+ }
+ }
+
+ private static class SourceLevelQueryImpl implements SourceLevelQueryImplementation {
+
+ private static SourceLevelQueryImpl instance;
+
+ private SourceLevelQueryImpl() {}
+
+ @Override
+ public String getSourceLevel(FileObject javaFile) {
+ return "8";
+ }
+
+ public static synchronized SourceLevelQueryImpl getDefault () {
+ if (instance == null) {
+ instance = new SourceLevelQueryImpl();
+ }
+ return instance;
+ }
+ }
+
+ private static class APQImpl implements AnnotationProcessingQueryImplementation {
+
+ private final Result result = new Result() {
+ public @NonNull Set<? extends Trigger> annotationProcessingEnabled() {
+ return EnumSet.allOf(Trigger.class);
+ }
+
+ public @CheckForNull Iterable<? extends String> annotationProcessorsToRun() {
+ return Arrays.asList(TestAP.class.getName());
+ }
+
+ public @CheckForNull URL sourceOutputDirectory() {
+ return null;
+ }
+
+ public @NonNull Map<? extends String, ? extends String> processorOptions() {
+ return Collections.emptyMap();
+ }
+
+ public void addChangeListener(@NonNull ChangeListener l) {}
+
+ public void removeChangeListener(@NonNull ChangeListener l) {}
+ };
+ @Override
+ public AnnotationProcessingQuery.Result getAnnotationProcessingOptions(FileObject file) {
+ return result;
+ }
+
+ }
+
+ @SupportedAnnotationTypes("*")
+ public static class TestAP extends AbstractProcessor {
+ int round = 0;
+ @Override
+ public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
+ if (round++ == 0) {
+ try {
+ processingEnv.getFiler().createClassFile("any.Name");
+ processingEnv.getFiler().createResource(StandardLocation.CLASS_OUTPUT, "any", "Name.class");
+ } catch (IOException ex) {
+ throw new AssertionError(ex);
+ }
+ }
+ return false;
+ }
+ }
+
+ static {
+ System.setProperty("SourcePath.no.source.filter", "true");
+ }
+}
---------------------------------------------------------------------
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