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 <jlah...@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-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