diff --git a/java/java.source.base/src/org/netbeans/modules/java/source/classpath/SourcePath.java b/java/java.source.base/src/org/netbeans/modules/java/source/classpath/SourcePath.java index b82b569d2bbc..6d8b00f23c6f 100644 --- a/java/java.source.base/src/org/netbeans/modules/java/source/classpath/SourcePath.java +++ b/java/java.source.base/src/org/netbeans/modules/java/source/classpath/SourcePath.java @@ -204,7 +204,12 @@ public URL[] getRoots() { final URL[] origRoots = pr.getRoots(); final List rootsList = new ArrayList(origRoots.length); for (URL url : origRoots) { - if (forcePreferSources || JavaIndex.hasSourceCache(url,true)) { + // Use the weaker hasSourceCache variant: it also sees transiently created usages + // queries (which ClassIndex.createQueriesForRoots would query anyway) and does + // not require State.INITIALIZED (which only means "re-indexed in this session"). + // The stricter variant silently dropped otherwise searchable source roots from + // the source path whenever their index had not been re-indexed in this session. + if (forcePreferSources || JavaIndex.hasSourceCache(url, false)) { rootsList.add(url); } } diff --git a/java/java.source.base/test/unit/src/org/netbeans/modules/java/source/classpath/SourcePathTest.java b/java/java.source.base/test/unit/src/org/netbeans/modules/java/source/classpath/SourcePathTest.java index 0172bcb78e54..40ad5f019dbf 100644 --- a/java/java.source.base/test/unit/src/org/netbeans/modules/java/source/classpath/SourcePathTest.java +++ b/java/java.source.base/test/unit/src/org/netbeans/modules/java/source/classpath/SourcePathTest.java @@ -20,16 +20,15 @@ package org.netbeans.modules.java.source.classpath; import java.io.File; -import java.io.IOException; import java.net.URL; import java.util.Arrays; import java.util.List; import org.netbeans.api.java.classpath.ClassPath; import org.netbeans.api.java.source.TestUtilities; -import org.netbeans.junit.NbTestCase; import org.netbeans.modules.java.source.ClassIndexTestCase; +import org.netbeans.modules.java.source.indexing.JavaIndex; import org.netbeans.modules.java.source.usages.ClassIndexManager; -import org.netbeans.modules.parsing.lucene.support.IndexManager; +import org.netbeans.modules.java.source.usages.ClassIndexImpl; import org.netbeans.spi.java.classpath.ClassPathFactory; import org.netbeans.spi.java.classpath.ClassPathImplementation; import org.netbeans.spi.java.classpath.PathResourceImplementation; @@ -80,7 +79,40 @@ public void testSourcePath () throws Exception { final ClassPath sp3 = ClassPathFactory.createClassPath(SourcePath.filtered(baseImpl, false)); assertEquals (base,sp3); } - + + /** + * A source root whose usages index was created in a previous session + * (the "source" attribute is present) but was not re-indexed in the + * current session: the index exists only as a transient, NEW + * ClassIndexImpl. The source path must still keep the root, otherwise + * sources-only searches (e.g. the "Open Projects" Find Usages scope) + * silently drop the root's usages. + */ + public void testSourcePathKeepsTransientUsagesIndexRoot() throws Exception { + + File wd = this.getWorkDir(); + File cache = new File(wd, "cache"); + cache.mkdir(); + TestUtilities.setCacheFolder(cache); + File r1 = new File(wd, "root1"); + r1.mkdir(); + URL r1url = Utilities.toURI(r1).toURL(); + + JavaIndex.setAttribute(r1url, ClassIndexManager.PROP_SOURCE_ROOT, "true"); + ClassIndexImpl uq = ClassIndexManager.getDefault().getUsagesQuery(r1url, true); + assertNotNull(uq); + assertEquals(ClassIndexImpl.Type.SOURCE, uq.getType()); + assertEquals(ClassIndexImpl.State.NEW, uq.getState()); + + ClassPathImplementation baseImpl = ClassPathSupport.createClassPathImplementation( + List.of(new PathResourceImplementation[]{ ClassPathSupport.createResource(r1url) }) + ); + ClassPath base = ClassPathFactory.createClassPath(baseImpl); + + ClassPath sp = ClassPathFactory.createClassPath(SourcePath.filtered(baseImpl, false)); + assertEquals(base, sp); + } + private static void assertEquals (ClassPath ecp, ClassPath rcp) { List ee = ecp.entries(); List re = rcp.entries();