diff --git a/base/src/META-INF/blaze-base.xml b/base/src/META-INF/blaze-base.xml
index b37d79ac279..69bce8f2321 100644
--- a/base/src/META-INF/blaze-base.xml
+++ b/base/src/META-INF/blaze-base.xml
@@ -342,6 +342,9 @@
+
diff --git a/base/src/com/google/idea/blaze/base/model/LibraryFilesProvider.java b/base/src/com/google/idea/blaze/base/model/LibraryFilesProvider.java
index c71ba17a8ed..32e60156675 100644
--- a/base/src/com/google/idea/blaze/base/model/LibraryFilesProvider.java
+++ b/base/src/com/google/idea/blaze/base/model/LibraryFilesProvider.java
@@ -16,9 +16,12 @@
package com.google.idea.blaze.base.model;
import com.google.common.collect.ImmutableList;
+import com.google.idea.blaze.base.sync.libraries.LibraryModifier;
import com.intellij.openapi.roots.libraries.Library;
import java.io.File;
+import static com.google.common.collect.ImmutableList.toImmutableList;
+
/** Provides files to be updated in {@link Library.ModifiableModel}. */
public interface LibraryFilesProvider {
/** Returns the name of library that the modifier will update. */
@@ -30,12 +33,32 @@ public interface LibraryFilesProvider {
*/
ImmutableList getClassFiles(BlazeProjectData blazeProjectData);
+ /**
+ * Returns a list of files' urls that should be added to {@link Library.ModifiableModel} as
+ * OrderRootType.CLASSES.
+ */
+ default ImmutableList getClassFilesUrls(BlazeProjectData blazeProjectData) {
+ return getClassFiles(blazeProjectData).stream()
+ .map(LibraryModifier::pathToUrl)
+ .collect(toImmutableList());
+ };
+
/**
* Returns a list of files that should be added to {@link Library.ModifiableModel} as
* OrderRootType.SOURCES.
*/
ImmutableList getSourceFiles(BlazeProjectData blazeProjectData);
+ /**
+ * Returns a list of files' urls that should be added to {@link Library.ModifiableModel} as
+ * OrderRootType.SOURCES.
+ */
+ default ImmutableList getSourceFilesUrls(BlazeProjectData blazeProjectData) {
+ return getSourceFiles(blazeProjectData).stream()
+ .map(LibraryModifier::pathToUrl)
+ .collect(toImmutableList());
+ }
+
default boolean supportAnchors() {
return false;
}
diff --git a/base/src/com/google/idea/blaze/base/sync/libraries/LibraryModifier.java b/base/src/com/google/idea/blaze/base/sync/libraries/LibraryModifier.java
index 1597cb7dd40..539d79b6a45 100644
--- a/base/src/com/google/idea/blaze/base/sync/libraries/LibraryModifier.java
+++ b/base/src/com/google/idea/blaze/base/sync/libraries/LibraryModifier.java
@@ -26,6 +26,7 @@
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.util.io.FileUtilRt;
import com.intellij.openapi.vfs.StandardFileSystems;
+import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.openapi.vfs.VirtualFileManager;
import com.intellij.util.io.URLUtil;
import java.io.File;
@@ -49,12 +50,12 @@ public Library.ModifiableModel getModifiableModel() {
/** Writes the library content to its {@link Library.ModifiableModel}. */
public void updateModifiableModel(BlazeProjectData blazeProjectData) {
removeAllContents();
- for (File classFile : libraryFilesProvider.getClassFiles(blazeProjectData)) {
- addRoot(classFile, OrderRootType.CLASSES);
+ for (String classFileUrl : libraryFilesProvider.getClassFilesUrls(blazeProjectData)) {
+ addRoot(classFileUrl, OrderRootType.CLASSES);
}
- for (File sourceFile : libraryFilesProvider.getSourceFiles(blazeProjectData)) {
- addRoot(sourceFile, OrderRootType.SOURCES);
+ for (String sourceFileUrl : libraryFilesProvider.getSourceFilesUrls(blazeProjectData)) {
+ addRoot(sourceFileUrl, OrderRootType.SOURCES);
}
}
@@ -68,15 +69,16 @@ private ModifiableModel getLibraryModifiableModel(
return modelsProvider.getModifiableLibraryModel(library);
}
- private void addRoot(File file, OrderRootType orderRootType) {
- if (!file.exists()) {
- logger.warn("No local file found for " + file);
+ private void addRoot(String fileUrl, OrderRootType orderRootType) {
+ VirtualFile virtualFile = VirtualFileManager.getInstance().findFileByUrl(fileUrl);
+ if (virtualFile == null || !virtualFile.exists()) {
+ logger.warn("No local file found for " + fileUrl);
return;
}
- modifiableModel.addRoot(pathToUrl(file), orderRootType);
+ modifiableModel.addRoot(fileUrl, orderRootType);
}
- private String pathToUrl(File path) {
+ public static String pathToUrl(File path) {
String name = path.getName();
boolean isJarFile =
FileUtilRt.extensionEquals(name, "jar")
diff --git a/java/src/com/google/idea/blaze/java/sync/model/BlazeJarLibrary.java b/java/src/com/google/idea/blaze/java/sync/model/BlazeJarLibrary.java
index eeda2c03bf8..76f3918f72d 100644
--- a/java/src/com/google/idea/blaze/java/sync/model/BlazeJarLibrary.java
+++ b/java/src/com/google/idea/blaze/java/sync/model/BlazeJarLibrary.java
@@ -19,6 +19,7 @@
import com.google.common.collect.ImmutableList;
import com.google.devtools.intellij.model.ProjectData;
+import com.google.idea.blaze.base.async.executor.ProgressiveTaskWithProgressIndicator;
import com.google.idea.blaze.base.ideinfo.LibraryArtifact;
import com.google.idea.blaze.base.ideinfo.ProtoWrapper;
import com.google.idea.blaze.base.ideinfo.TargetKey;
@@ -26,12 +27,22 @@
import com.google.idea.blaze.base.model.BlazeProjectData;
import com.google.idea.blaze.base.model.LibraryFilesProvider;
import com.google.idea.blaze.base.model.LibraryKey;
+import com.google.idea.blaze.base.sync.libraries.LibraryModifier;
import com.google.idea.blaze.java.libraries.AttachedSourceJarManager;
import com.google.idea.blaze.java.libraries.JarCache;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.project.Project;
+import com.intellij.openapi.roots.ui.configuration.JavaVfsSourceRootDetectionUtil;
+import com.intellij.openapi.util.registry.Registry;
+import com.intellij.openapi.vfs.VirtualFile;
+import com.intellij.openapi.vfs.VirtualFileManager;
+
import java.io.File;
+import java.util.Collections;
+import java.util.LinkedList;
+import java.util.List;
import java.util.Objects;
+import java.util.concurrent.ExecutionException;
import javax.annotation.Nullable;
import javax.annotation.concurrent.Immutable;
@@ -140,6 +151,36 @@ public ImmutableList getSourceFiles(BlazeProjectData blazeProjectData) {
.collect(toImmutableList());
}
+ @Override
+ public ImmutableList getSourceFilesUrls(BlazeProjectData blazeProjectData) {
+ final ImmutableList sourceFiles = getSourceFiles(blazeProjectData);
+ ImmutableList jarFilesAsSourceRoots = sourceFiles.stream().map(LibraryModifier::pathToUrl).collect(toImmutableList());
+ if (!Registry.is("bazel.sync.detect.source.roots")) {
+ return jarFilesAsSourceRoots;
+ } else {
+ try {
+ return ProgressiveTaskWithProgressIndicator.builder(project, "Locating source roots in source path entry")
+ .setModality(ProgressiveTaskWithProgressIndicator.Modality.MODAL)
+ .submitTaskWithResult(indicator -> {
+ List sourceFilesUrls = new LinkedList<>();
+ for (File sourceFile : sourceFiles) {
+ VirtualFile jarFile = VirtualFileManager.getInstance().findFileByUrl(LibraryModifier.pathToUrl(sourceFile));
+ List candidates = Collections.emptyList();
+ if (jarFile != null && jarFile.exists()) {
+ candidates = JavaVfsSourceRootDetectionUtil.suggestRoots(jarFile, indicator);
+ }
+ if (!candidates.isEmpty()) {
+ candidates.forEach(sourceVirtualFile -> sourceFilesUrls.add(sourceVirtualFile.getUrl()));
+ }
+ }
+ return ImmutableList.copyOf(sourceFilesUrls);
+ }).get();
+ } catch (InterruptedException | ExecutionException e) {
+ return jarFilesAsSourceRoots;
+ }
+ }
+ }
+
@Override
public boolean equals(Object other) {
if (this == other) {