diff --git a/ide/lsp.client/src/org/netbeans/modules/lsp/client/bindings/CustomIndexerImpl.java b/ide/lsp.client/src/org/netbeans/modules/lsp/client/bindings/CustomIndexerImpl.java
index c46c3d4095c0..9e97e8c736d0 100644
--- a/ide/lsp.client/src/org/netbeans/modules/lsp/client/bindings/CustomIndexerImpl.java
+++ b/ide/lsp.client/src/org/netbeans/modules/lsp/client/bindings/CustomIndexerImpl.java
@@ -51,8 +51,13 @@ public class CustomIndexerImpl extends CustomIndexer {
@Override
protected void index(Iterable extends Indexable> files, Context context) {
+ FileObject root = context.getRoot();
+
+ if (root == null) {
+ return ; //ignore
+ }
+
handleStoredFiles(context, props -> {
- FileObject root = context.getRoot();
for (Indexable i : files) {
FileObject file = root.getFileObject(i.getRelativePath());
if (file != null) {
diff --git a/java/java.file.launcher/nbproject/project.xml b/java/java.file.launcher/nbproject/project.xml
index d5520075de76..195981d25ec1 100644
--- a/java/java.file.launcher/nbproject/project.xml
+++ b/java/java.file.launcher/nbproject/project.xml
@@ -140,6 +140,15 @@
1.84
+
+ org.netbeans.modules.parsing.api
+
+
+
+ 1
+ 9.30
+
+
org.netbeans.modules.parsing.indexing
@@ -166,6 +175,15 @@
1.63
+
+ org.netbeans.spi.editor.hints
+
+
+
+ 0
+ 1.65
+
+
org.openide.filesystems
diff --git a/java/java.file.launcher/src/org/netbeans/modules/java/file/launcher/AttributeBasedSingleFileOptions.java b/java/java.file.launcher/src/org/netbeans/modules/java/file/launcher/AttributeBasedSingleFileOptions.java
index 586415f3c414..cfa6c4d209aa 100644
--- a/java/java.file.launcher/src/org/netbeans/modules/java/file/launcher/AttributeBasedSingleFileOptions.java
+++ b/java/java.file.launcher/src/org/netbeans/modules/java/file/launcher/AttributeBasedSingleFileOptions.java
@@ -19,8 +19,6 @@
package org.netbeans.modules.java.file.launcher;
import javax.swing.event.ChangeListener;
-import org.netbeans.api.project.FileOwnerQuery;
-import org.netbeans.api.project.Project;
import org.netbeans.modules.java.file.launcher.queries.MultiSourceRootProvider;
import org.netbeans.modules.java.file.launcher.spi.SingleFileOptionsQueryImplementation;
import org.openide.filesystems.FileAttributeEvent;
@@ -38,9 +36,7 @@ public class AttributeBasedSingleFileOptions implements SingleFileOptionsQueryIm
@Override
public Result optionsFor(FileObject file) {
- Project p = FileOwnerQuery.getOwner(file);
-
- if (p != null) {
+ if (!SingleSourceFileUtil.isSupportedFile(file)) {
return null;
}
diff --git a/java/java.file.launcher/src/org/netbeans/modules/java/file/launcher/SharedRootData.java b/java/java.file.launcher/src/org/netbeans/modules/java/file/launcher/SharedRootData.java
index 3c9d9099224a..98530378dd60 100644
--- a/java/java.file.launcher/src/org/netbeans/modules/java/file/launcher/SharedRootData.java
+++ b/java/java.file.launcher/src/org/netbeans/modules/java/file/launcher/SharedRootData.java
@@ -18,16 +18,13 @@
*/
package org.netbeans.modules.java.file.launcher;
-import java.io.File;
import java.io.IOException;
import java.util.Enumeration;
import java.util.HashMap;
-import java.util.List;
import java.util.Map;
import java.util.TreeMap;
import java.util.logging.Level;
import java.util.logging.Logger;
-import java.util.stream.Collectors;
import org.netbeans.api.annotations.common.CheckForNull;
import org.netbeans.modules.java.file.launcher.api.SourceLauncher;
import org.openide.filesystems.FileAttributeEvent;
@@ -36,8 +33,6 @@
import org.openide.filesystems.FileEvent;
import org.openide.filesystems.FileObject;
import org.openide.filesystems.FileUtil;
-import org.openide.modules.SpecificationVersion;
-import org.openide.util.Exceptions;
/**
*
@@ -108,10 +103,7 @@ private synchronized void setNewProperties(Map newProperties) {
}
String joinedCommandLine = SourceLauncher.joinCommandLines(options.values());
try {
- if (
- !root.getFileSystem().isReadOnly() // Skip read-only FSes (like JarFileSystem)
- && !joinedCommandLine.equals(root.getAttribute(SingleSourceFileUtil.FILE_VM_OPTIONS))
- ) {
+ if (!joinedCommandLine.equals(root.getAttribute(SingleSourceFileUtil.FILE_VM_OPTIONS))) {
root.setAttribute(SingleSourceFileUtil.FILE_VM_OPTIONS, joinedCommandLine);
}
} catch (IOException ex) {
diff --git a/java/java.file.launcher/src/org/netbeans/modules/java/file/launcher/SingleSourceFileUtil.java b/java/java.file.launcher/src/org/netbeans/modules/java/file/launcher/SingleSourceFileUtil.java
index 65b6fc08fd36..0d18a7b12c3b 100644
--- a/java/java.file.launcher/src/org/netbeans/modules/java/file/launcher/SingleSourceFileUtil.java
+++ b/java/java.file.launcher/src/org/netbeans/modules/java/file/launcher/SingleSourceFileUtil.java
@@ -34,6 +34,7 @@
import org.netbeans.modules.java.file.launcher.spi.SingleFileOptionsQueryImplementation.Result;
import org.netbeans.spi.java.queries.CompilerOptionsQueryImplementation;
import org.openide.filesystems.FileObject;
+import org.openide.filesystems.FileStateInvalidException;
import org.openide.filesystems.FileUtil;
import org.openide.loaders.DataObject;
import org.openide.util.Lookup;
@@ -74,13 +75,21 @@ public static FileObject getJavaFileWithoutProjectFromLookup(Lookup lookup) {
}
public static boolean isSingleSourceFile(FileObject fObj) {
- Project p = FileOwnerQuery.getOwner(fObj);
- if (p != null || !fObj.getExt().equalsIgnoreCase("java")) { //NOI18N
+ if (!isSupportedFile(fObj) || !fObj.getExt().equalsIgnoreCase("java")) { //NOI18N
return false;
}
return true;
}
+ public static boolean isSupportedFile(FileObject file) {
+ try {
+ return !MultiSourceRootProvider.DISABLE_MULTI_SOURCE_ROOT &&
+ FileOwnerQuery.getOwner(file) == null &&
+ !file.getFileSystem().isReadOnly();
+ } catch (FileStateInvalidException ex) {
+ return false;
+ }
+ }
public static Process compileJavaSource(FileObject fileObject) {
FileObject javac = JavaPlatformManager.getDefault().getDefaultPlatform().findTool("javac"); //NOI18N
File javacFile = FileUtil.toFile(javac);
diff --git a/java/java.file.launcher/src/org/netbeans/modules/java/file/launcher/indexer/CompilerOptionsIndexer.java b/java/java.file.launcher/src/org/netbeans/modules/java/file/launcher/indexer/CompilerOptionsIndexer.java
index d541b4c77600..b8fe279be40d 100644
--- a/java/java.file.launcher/src/org/netbeans/modules/java/file/launcher/indexer/CompilerOptionsIndexer.java
+++ b/java/java.file.launcher/src/org/netbeans/modules/java/file/launcher/indexer/CompilerOptionsIndexer.java
@@ -20,11 +20,12 @@
import org.netbeans.modules.java.file.launcher.SharedRootData;
import org.netbeans.api.editor.mimelookup.MimeRegistration;
-import org.netbeans.api.project.FileOwnerQuery;
+import org.netbeans.modules.java.file.launcher.SingleSourceFileUtil;
import org.netbeans.modules.parsing.spi.indexing.Context;
import org.netbeans.modules.parsing.spi.indexing.CustomIndexer;
import org.netbeans.modules.parsing.spi.indexing.CustomIndexerFactory;
import org.netbeans.modules.parsing.spi.indexing.Indexable;
+import org.openide.filesystems.FileObject;
/**
*
@@ -35,10 +36,17 @@ public class CompilerOptionsIndexer extends CustomIndexer {
@Override
protected void index(Iterable extends Indexable> files, Context context) {
- if (FileOwnerQuery.getOwner(context.getRoot()) != null) {
+ FileObject root = context.getRoot();
+
+ if (root == null) {
+ return ; //ignore
+ }
+
+ if (!SingleSourceFileUtil.isSupportedFile(root)) {
return ; //ignore roots under projects
}
- SharedRootData.ensureRootRegistered(context.getRoot());
+
+ SharedRootData.ensureRootRegistered(root);
}
diff --git a/java/java.file.launcher/src/org/netbeans/modules/java/file/launcher/queries/MultiSourceRootProvider.java b/java/java.file.launcher/src/org/netbeans/modules/java/file/launcher/queries/MultiSourceRootProvider.java
index 7f5061d3fac4..ad76218b3e4a 100644
--- a/java/java.file.launcher/src/org/netbeans/modules/java/file/launcher/queries/MultiSourceRootProvider.java
+++ b/java/java.file.launcher/src/org/netbeans/modules/java/file/launcher/queries/MultiSourceRootProvider.java
@@ -21,6 +21,8 @@
import java.beans.PropertyChangeListener;
import java.beans.PropertyChangeSupport;
import java.io.IOException;
+import java.lang.ref.Reference;
+import java.lang.ref.WeakReference;
import java.net.URL;
import java.util.ArrayList;
import java.util.Arrays;
@@ -32,6 +34,7 @@
import java.util.Objects;
import java.util.Set;
import java.util.WeakHashMap;
+import java.util.concurrent.atomic.AtomicReference;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import org.netbeans.api.java.classpath.ClassPath;
@@ -41,6 +44,7 @@
import org.netbeans.api.java.platform.JavaPlatformManager;
import org.netbeans.api.lexer.TokenHierarchy;
import org.netbeans.api.lexer.TokenSequence;
+import org.netbeans.api.project.FileOwnerQuery;
import org.netbeans.api.queries.FileEncodingQuery;
import org.netbeans.modules.java.file.launcher.SingleSourceFileUtil;
import org.netbeans.modules.java.file.launcher.spi.SingleFileOptionsQueryImplementation;
@@ -48,11 +52,14 @@
import org.netbeans.spi.java.classpath.ClassPathImplementation;
import static org.netbeans.spi.java.classpath.ClassPathImplementation.PROP_RESOURCES;
import org.netbeans.spi.java.classpath.ClassPathProvider;
+import org.netbeans.spi.java.classpath.FilteringPathResourceImplementation;
import org.netbeans.spi.java.classpath.PathResourceImplementation;
import org.netbeans.spi.java.classpath.support.ClassPathSupport;
import org.openide.filesystems.FileObject;
import org.openide.filesystems.FileUtil;
+import org.openide.filesystems.URLMapper;
import org.openide.util.Exceptions;
+import org.openide.util.NbBundle.Messages;
import org.openide.util.lookup.ServiceProvider;
import org.openide.util.lookup.ServiceProviders;
@@ -89,7 +96,7 @@ public ClassPath findClassPath(FileObject file, String type) {
}
private ClassPath getSourcePath(FileObject file) {
- if (DISABLE_MULTI_SOURCE_ROOT) return null;
+ if (!SingleSourceFileUtil.isSupportedFile(file)) return null;
synchronized (this) {
//XXX: what happens if there's a Java file in user's home???
if (file.isValid() && file.isData() && "text/x-java".equals(file.getMIMEType())) {
@@ -116,8 +123,10 @@ private ClassPath getSourcePath(FileObject file) {
}
return root2SourceCP.computeIfAbsent(root, r -> {
- ClassPath srcCP = ClassPathSupport.createClassPath(r);
- GlobalPathRegistry.getDefault().register(ClassPath.SOURCE, new ClassPath[] {srcCP});
+ ClassPath srcCP = ClassPathSupport.createClassPath(Arrays.asList(new RootPathResourceImplementation(r)));
+ if (registerRoot(r)) {
+ GlobalPathRegistry.getDefault().register(ClassPath.SOURCE, new ClassPath[] {srcCP});
+ }
return srcCP;
});
} catch (IOException ex) {
@@ -234,6 +243,13 @@ private ClassPath attributeBasedPath(FileObject file, Map
}
}
+ @Messages({
+ "SETTING_AutoRegisterAsRoot=false"
+ })
+ private static boolean registerRoot(FileObject root) {
+ return "true".equals(Bundle.SETTING_AutoRegisterAsRoot());
+ }
+
private static final class AttributeBasedClassPathImplementation implements ChangeListener, ClassPathImplementation {
private final PropertyChangeSupport pcs = new PropertyChangeSupport(this);
private final SingleFileOptionsQueryImplementation.Result delegate;
@@ -299,4 +315,54 @@ public void removePropertyChangeListener(PropertyChangeListener listener) {
}
+ private static final class RootPathResourceImplementation implements FilteringPathResourceImplementation {
+
+ private final URL root;
+ private final URL[] roots;
+ private final AtomicReference lastCheckedAsIncluded = new AtomicReference<>();
+
+ public RootPathResourceImplementation(FileObject root) {
+ this.root = root.toURL();
+ this.roots = new URL[] {this.root};
+ }
+
+ @Override
+ public boolean includes(URL root, String resource) {
+ if (!resource.endsWith("/")) {
+ int lastSlash = resource.lastIndexOf('/');
+ if (lastSlash != (-1)) {
+ resource = resource.substring(0, lastSlash + 1);
+ }
+ }
+ if (resource.equals(lastCheckedAsIncluded.get())) {
+ return true;
+ }
+ FileObject fo = URLMapper.findFileObject(root);
+ fo = fo != null ? fo.getFileObject(resource) : null;
+ boolean included = fo == null || FileOwnerQuery.getOwner(fo) == null;
+ if (included) {
+ lastCheckedAsIncluded.set(resource);
+ }
+ return included;
+ }
+
+ @Override
+ public URL[] getRoots() {
+ return roots;
+ }
+
+ @Override
+ public ClassPathImplementation getContent() {
+ return null;
+ }
+
+ @Override
+ public void addPropertyChangeListener(PropertyChangeListener listener) {
+ }
+
+ @Override
+ public void removePropertyChangeListener(PropertyChangeListener listener) {
+ }
+
+ }
}
diff --git a/java/java.lsp.server/nbcode/branding/modules/org-netbeans-modules-java-file-launcher.jar/org/netbeans/modules/java/file/launcher/queries/Bundle.properties b/java/java.lsp.server/nbcode/branding/modules/org-netbeans-modules-java-file-launcher.jar/org/netbeans/modules/java/file/launcher/queries/Bundle.properties
new file mode 100644
index 000000000000..684c2d3a5fff
--- /dev/null
+++ b/java/java.lsp.server/nbcode/branding/modules/org-netbeans-modules-java-file-launcher.jar/org/netbeans/modules/java/file/launcher/queries/Bundle.properties
@@ -0,0 +1,18 @@
+# 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.
+
+SETTING_AutoRegisterAsRoot=true
diff --git a/java/java.source.base/src/org/netbeans/modules/java/source/indexing/APTUtils.java b/java/java.source.base/src/org/netbeans/modules/java/source/indexing/APTUtils.java
index 5f47ca7cd445..58f01106fcb6 100644
--- a/java/java.source.base/src/org/netbeans/modules/java/source/indexing/APTUtils.java
+++ b/java/java.source.base/src/org/netbeans/modules/java/source/indexing/APTUtils.java
@@ -135,7 +135,9 @@ private APTUtils(@NonNull final FileObject root) {
this.root = root;
bootPath = ClassPath.getClassPath(root, ClassPath.BOOT);
compilePath = ClassPath.getClassPath(root, ClassPath.COMPILE);
- compilePath.addPropertyChangeListener(this);
+ if (compilePath != null) {
+ compilePath.addPropertyChangeListener(this);
+ }
processorPath = new AtomicReference<>(ClassPath.getClassPath(root, JavaClassPathConstants.PROCESSOR_PATH));
processorModulePath = new AtomicReference<>(ClassPath.getClassPath(root, JavaClassPathConstants.MODULE_PROCESSOR_PATH));
aptOptions = AnnotationProcessingQuery.getAnnotationProcessingOptions(root);
@@ -360,7 +362,9 @@ private ClassPath[] validatePaths() {
compilePath.removePropertyChangeListener(this);
}
compilePath = ClassPath.getClassPath(root, ClassPath.COMPILE);
- compilePath.addPropertyChangeListener(this);
+ if (compilePath != null) {
+ compilePath.addPropertyChangeListener(this);
+ }
listenOnProcessorPath(pp, this);
classLoaderCache = null;
}