diff --git a/aswb/src/com/google/idea/blaze/android/projectsystem/BlazeModuleSystem.java b/aswb/src/com/google/idea/blaze/android/projectsystem/BlazeModuleSystem.java
index 4c29bc47c92..e8325a68572 100644
--- a/aswb/src/com/google/idea/blaze/android/projectsystem/BlazeModuleSystem.java
+++ b/aswb/src/com/google/idea/blaze/android/projectsystem/BlazeModuleSystem.java
@@ -15,8 +15,6 @@
*/
package com.google.idea.blaze.android.projectsystem;
-import static com.google.common.collect.ImmutableList.toImmutableList;
-
import com.android.ide.common.util.PathString;
import com.android.projectmodel.ExternalAndroidLibrary;
import com.android.projectmodel.ExternalLibraryImpl;
@@ -26,6 +24,7 @@
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.idea.blaze.android.libraries.UnpackedAars;
+import com.google.idea.blaze.android.manifest.ManifestParser;
import com.google.idea.blaze.android.sync.model.AarLibrary;
import com.google.idea.blaze.android.sync.model.AndroidResourceModuleRegistry;
import com.google.idea.blaze.android.sync.model.BlazeAndroidSyncData;
@@ -43,15 +42,20 @@
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.project.Project;
+import org.jetbrains.annotations.Nullable;
+
import java.io.File;
+import java.io.FileInputStream;
import java.io.IOException;
+import java.io.InputStream;
import java.io.UncheckedIOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.Collection;
import java.util.Collections;
import java.util.stream.Stream;
-import org.jetbrains.annotations.Nullable;
+
+import static com.google.common.collect.ImmutableList.toImmutableList;
/** Blaze implementation of {@link AndroidModuleSystem}. */
public class BlazeModuleSystem extends BlazeModuleSystemBase {
@@ -162,14 +166,26 @@ static ExternalAndroidLibrary toExternalLibrary(
library.aarArtifact));
return null;
}
+
File resFolder = unpackedAars.getResourceDirectory(decoder, library);
PathString resFolderPathString = resFolder == null ? null : new PathString(resFolder);
+ PathString manifest = resFolderPathString == null
+ ? null
+ : resFolderPathString.getParentOrRoot().resolve("AndroidManifest.xml");
+ String resourcePackage = library.resourcePackage;
+ if ((resourcePackage == null || resourcePackage == "") && manifest != null) {
+ try (InputStream is = new FileInputStream(manifest.toFile())) {
+ ManifestParser.ParsedManifest parsedManifest = ManifestParser.parseManifestFromInputStream(is);
+ resourcePackage = parsedManifest.packageName;
+ } catch (IOException ioe) {
+ logger.warn(
+ String.format("Could not parse package from manifest in library %s", aarFile.getName()));
+ return null;
+ }
+ }
return new ExternalLibraryImpl(library.key.toString())
.withLocation(new PathString(aarFile))
- .withManifestFile(
- resFolderPathString == null
- ? null
- : resFolderPathString.getParentOrRoot().resolve("AndroidManifest.xml"))
+ .withManifestFile(manifest)
.withResFolder(
resFolderPathString == null
? null
@@ -178,7 +194,7 @@ static ExternalAndroidLibrary toExternalLibrary(
resFolderPathString == null
? null
: resFolderPathString.getParentOrRoot().resolve("R.txt"))
- .withPackageName(library.resourcePackage);
+ .withPackageName(resourcePackage);
}
@Override
diff --git a/aswb/src/com/google/idea/blaze/android/projectsystem/BlazeModuleSystemBase.java b/aswb/src/com/google/idea/blaze/android/projectsystem/BlazeModuleSystemBase.java
index c90ede3f88a..8938c3d9305 100644
--- a/aswb/src/com/google/idea/blaze/android/projectsystem/BlazeModuleSystemBase.java
+++ b/aswb/src/com/google/idea/blaze/android/projectsystem/BlazeModuleSystemBase.java
@@ -205,6 +205,10 @@ public void registerDependency(GradleCoordinate coordinate, DependencyType type)
}
}
+ public void clearCache() {
+ classFileFinder.clearCache();
+ }
+
@Nullable
@Override
public GradleCoordinate getRegisteredDependency(GradleCoordinate coordinate) {
diff --git a/aswb/src/com/google/idea/blaze/android/projectsystem/RenderJarClassFileFinder.java b/aswb/src/com/google/idea/blaze/android/projectsystem/RenderJarClassFileFinder.java
index 617265883a6..7d337b6d978 100644
--- a/aswb/src/com/google/idea/blaze/android/projectsystem/RenderJarClassFileFinder.java
+++ b/aswb/src/com/google/idea/blaze/android/projectsystem/RenderJarClassFileFinder.java
@@ -15,8 +15,6 @@
*/
package com.google.idea.blaze.android.projectsystem;
-import static java.util.stream.Collectors.joining;
-
import com.android.tools.idea.projectsystem.ClassFileFinder;
import com.android.tools.idea.projectsystem.ClassFileFinderUtil;
import com.google.common.annotations.VisibleForTesting;
@@ -25,6 +23,7 @@
import com.google.idea.blaze.android.libraries.RenderJarCache;
import com.google.idea.blaze.android.sync.model.AndroidResourceModule;
import com.google.idea.blaze.android.sync.model.AndroidResourceModuleRegistry;
+import com.google.idea.blaze.android.sync.model.idea.BlazeClassJarProvider;
import com.google.idea.blaze.android.targetmaps.TargetToBinaryMap;
import com.google.idea.blaze.base.ideinfo.TargetIdeInfo;
import com.google.idea.blaze.base.ideinfo.TargetKey;
@@ -34,6 +33,7 @@
import com.google.idea.blaze.base.sync.BlazeSyncModificationTracker;
import com.google.idea.blaze.base.sync.data.BlazeDataStorage;
import com.google.idea.blaze.base.sync.data.BlazeProjectDataManager;
+import com.google.idea.blaze.base.sync.projectstructure.ModuleFinder;
import com.google.idea.common.experiments.BoolExperiment;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.diagnostic.Logger;
@@ -42,9 +42,15 @@
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vfs.JarFileSystem;
import com.intellij.openapi.vfs.VirtualFile;
+import org.jetbrains.annotations.Nullable;
+
import java.io.File;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
import java.util.regex.Pattern;
-import org.jetbrains.annotations.Nullable;
+
+import static java.util.stream.Collectors.joining;
/**
* A {@link ClassFileFinder} that uses deploy JAR like artifacts (called render jar henceforth) for
@@ -62,6 +68,8 @@
*
*
NOTE: Blaze targets that constitutes the resource module will be called "resource target(s)"
* in comments below.
+ *
+ * TODO: The role of this class has expanded beyond just render jar resolution. Should rename it.
*/
public class RenderJarClassFileFinder implements ClassFileFinder {
/** Experiment to control whether class file finding from render jars should be enabled. */
@@ -74,7 +82,7 @@ public class RenderJarClassFileFinder implements ClassFileFinder {
*/
@VisibleForTesting
static final BoolExperiment resolveResourceClasses =
- new BoolExperiment("aswb.resolve.resources.render.jar", false);
+ new BoolExperiment("aswb.resolve.resources.render.jar", true); // needed for previews
private static final Logger log = Logger.getInstance(RenderJarClassFileFinder.class);
@@ -86,6 +94,8 @@ public class RenderJarClassFileFinder implements ClassFileFinder {
private final Module module;
private final Project project;
+ private final BlazeClassJarProvider blazeClassJarProvider;
+
// tracks the binary targets that depend resource targets
// will be recalculated after every sync
private ImmutableSet binaryTargets = ImmutableSet.of();
@@ -98,9 +108,12 @@ public class RenderJarClassFileFinder implements ClassFileFinder {
// true if the current module is the .workspace Module
private final boolean isWorkspaceModule;
+ private Map moduleCache = new HashMap();
+
public RenderJarClassFileFinder(Module module) {
this.module = module;
this.project = module.getProject();
+ this.blazeClassJarProvider = new BlazeClassJarProvider(this.project);
this.isWorkspaceModule = BlazeDataStorage.WORKSPACE_MODULE_NAME.equals(module.getName());
}
@@ -169,14 +182,43 @@ public VirtualFile findClass(String fqcn) {
for (TargetKey binaryTarget : binaryTargets) {
VirtualFile classFile = getClassFromRenderResolveJar(projectData, fqcn, binaryTarget);
if (classFile != null) {
+ log.warn(String.format("Found class %s in target %s", fqcn, binaryTarget.toString()));
return classFile;
}
}
+ // TODO: look into BlazeLightResourceClassService?
+
+ VirtualFile moduleClass = findFQCNInModule(fqcn, this.module);
+ if (moduleClass == null) {
+ moduleClass = findFQCNInModule(fqcn, null);
+ }
+ if (moduleClass != null) {
+ return moduleClass;
+ }
+
log.warn(String.format("Could not find class `%1$s` (module: `%2$s`)", fqcn, module.getName()));
return null;
}
+ public synchronized void clearCache() {
+ log.debug("clearing cache");
+ moduleCache.clear();
+ }
+
+ private synchronized VirtualFile findFQCNInModule(String fqcn, @Nullable Module module) {
+ if (module == null) {
+ module = ModuleFinder.getInstance(this.project)
+ .findModuleByName(BlazeDataStorage.WORKSPACE_MODULE_NAME);
+ }
+ ModuleCache cache = moduleCache.get(module.getName());
+ if (cache == null) {
+ cache = new ModuleCache(module);
+ moduleCache.put(module.getName(), cache);
+ }
+ return cache.searchForFQCNInModule(fqcn);
+ }
+
@VisibleForTesting
static boolean isResourceClass(String fqcn) {
return RESOURCE_CLASS_NAME.matcher(fqcn).matches();
@@ -268,4 +310,43 @@ private static VirtualFile getJarRootForLocalFile(VirtualFile file) {
public static boolean isEnabled() {
return enabled.getValue();
}
+
+ private class ModuleCache {
+ private final List moduleLibraries;
+ private Map packageJarHint = new HashMap();
+
+ private ModuleCache(Module module) {
+ moduleLibraries = blazeClassJarProvider.getModuleExternalLibraries(module);
+ }
+
+ @Nullable
+ private VirtualFile searchForFQCNInModule(String fqcn) {
+ String pkg = null;
+ int pkgIdx = fqcn.lastIndexOf('.');
+ if (pkgIdx != -1) {
+ pkg = fqcn.substring(0, pkgIdx);
+ }
+ VirtualFile hintJarVF = pkg == null ? null : packageJarHint.get(pkg);
+ if (hintJarVF != null) {
+ VirtualFile foundClass = findClassInJar(hintJarVF, fqcn);
+ if (foundClass != null) {
+ return foundClass;
+ }
+ }
+ for (File jar : moduleLibraries) {
+ VirtualFile jarVF = VirtualFileSystemProvider.getInstance().getSystem().findFileByIoFile(jar);
+ if (jarVF == null) {
+ continue;
+ }
+ VirtualFile foundClass = findClassInJar(jarVF, fqcn);
+ if (foundClass != null) {
+ if (pkg != null) {
+ packageJarHint.put(pkg, jarVF);
+ }
+ return foundClass;
+ }
+ }
+ return null;
+ }
+ }
}
diff --git a/aswb/src/com/google/idea/blaze/android/resources/BlazeLightResourceClassService.java b/aswb/src/com/google/idea/blaze/android/resources/BlazeLightResourceClassService.java
index 90697501184..c01b98a0d0c 100644
--- a/aswb/src/com/google/idea/blaze/android/resources/BlazeLightResourceClassService.java
+++ b/aswb/src/com/google/idea/blaze/android/resources/BlazeLightResourceClassService.java
@@ -15,8 +15,6 @@
*/
package com.google.idea.blaze.android.resources;
-import static com.google.common.collect.ImmutableSet.toImmutableSet;
-
import com.android.tools.idea.projectsystem.LightResourceClassService;
import com.android.tools.idea.res.AndroidLightPackage;
import com.google.common.annotations.VisibleForTesting;
@@ -35,12 +33,15 @@
import com.intellij.psi.PsiManager;
import com.intellij.psi.PsiPackage;
import com.intellij.psi.search.GlobalSearchScope;
+import org.jetbrains.android.facet.AndroidFacet;
+import org.jetbrains.annotations.Nullable;
+
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
-import org.jetbrains.android.facet.AndroidFacet;
-import org.jetbrains.annotations.Nullable;
+
+import static com.google.common.collect.ImmutableSet.toImmutableSet;
/** Implementation of {@link LightResourceClassService} set up at Blaze sync time. */
public class BlazeLightResourceClassService implements LightResourceClassService {
diff --git a/aswb/src/com/google/idea/blaze/android/sync/importer/BlazeAndroidWorkspaceImporter.java b/aswb/src/com/google/idea/blaze/android/sync/importer/BlazeAndroidWorkspaceImporter.java
index bc63f3e003d..62a41bf8ba5 100644
--- a/aswb/src/com/google/idea/blaze/android/sync/importer/BlazeAndroidWorkspaceImporter.java
+++ b/aswb/src/com/google/idea/blaze/android/sync/importer/BlazeAndroidWorkspaceImporter.java
@@ -469,30 +469,6 @@ private String createAarLibrary(@NotNull TargetIdeInfo target) {
String libraryKey =
LibraryKey.libraryNameFromArtifactLocation(target.getAndroidAarIdeInfo().getAar());
-
- //TODO: Should not be hardcoded, this is temp workaround, the package should be inferred properly, possibly from the manifest.xml?
- if(target.toString().equals("@maven//:androidx_lifecycle_lifecycle_runtime")) {
- resourcePackage = "androidx.lifecycle.runtime";
- }
- if(target.toString().equals("@maven//:androidx_savedstate_savedstate")) {
- resourcePackage = "androidx.savedstate";
- }
- if(target.toString().equals("@maven//:androidx_lifecycle_lifecycle_viewmodel")) {
- resourcePackage = "androidx.lifecycle.viewmodel";
- }
- if(target.toString().equals("@maven//:androidx_compose_ui_ui")) {
- resourcePackage = "androidx.compose.ui";
- }
- if(target.toString().equals("@maven//:androidx_core_core")) {
- resourcePackage = "androidx.core";
- }
- if(target.toString().equals("@maven//:androidx_constraintlayout_constraintlayout")) {
- resourcePackage = "androidx.constraintlayout";
- }
- if(target.toString().equals("@maven//:androidx_appcompat_appcompat")) {
- resourcePackage = "androidx.appcompat";
- }
-
if (!aarLibraries.containsKey(libraryKey)) {
// aar_import should only have one jar (a merged jar from the AAR's jars).
LibraryArtifact firstJar = target.getJavaIdeInfo().getJars().iterator().next();
diff --git a/aswb/src/com/google/idea/blaze/android/sync/model/idea/BlazeClassJarProvider.java b/aswb/src/com/google/idea/blaze/android/sync/model/idea/BlazeClassJarProvider.java
index 191629e2137..51ae1109e39 100644
--- a/aswb/src/com/google/idea/blaze/android/sync/model/idea/BlazeClassJarProvider.java
+++ b/aswb/src/com/google/idea/blaze/android/sync/model/idea/BlazeClassJarProvider.java
@@ -20,6 +20,7 @@
import com.android.tools.idea.model.ClassJarProvider;
import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableSet;
import com.google.idea.blaze.android.libraries.RenderJarCache;
import com.google.idea.blaze.android.sync.model.AndroidResourceModuleRegistry;
import com.google.idea.blaze.android.targetmaps.TargetToBinaryMap;
@@ -194,7 +195,7 @@ public static boolean testIsClassFileOutOfDate(
}
List getAllExternalLibraires(TargetMap targetMap, ArtifactLocationDecoder decoder) {
- ImmutableList.Builder results = ImmutableList.builder();
+ ImmutableSet.Builder infos = ImmutableSet.builder();
for (TargetIdeInfo target : targetMap.targets()) {
for (TargetKey dependencyTargetKey :
TransitiveDependencyMap.getInstance(project).getTransitiveDependencies(target.getKey())) {
@@ -206,19 +207,28 @@ List getAllExternalLibraires(TargetMap targetMap, ArtifactLocationDecoder
// Add all import jars as external libraries.
JavaIdeInfo javaIdeInfo = dependencyTarget.getJavaIdeInfo();
if (javaIdeInfo != null) {
- for (LibraryArtifact jar : javaIdeInfo.getJars()) {
- ArtifactLocation classJar = jar.getClassJar();
- if (classJar != null) {
- results.add(
- Preconditions.checkNotNull(
- OutputArtifactResolver.resolve(project, decoder, classJar),
- "Fail to find file %s",
- classJar.getRelativePath()));
- }
- }
+ infos.add(javaIdeInfo);
}
}
+ JavaIdeInfo javaIdeInfo = target.getJavaIdeInfo();
+ if (javaIdeInfo != null) {
+ infos.add(javaIdeInfo);
+ }
}
+ ImmutableList.Builder results = ImmutableList.builder();
+ for (JavaIdeInfo javaIdeInfo : infos.build()) {
+ for (LibraryArtifact jar : javaIdeInfo.getJars()) {
+ ArtifactLocation classJar = jar.getClassJar();
+ if (classJar != null) {
+ results.add(
+ Preconditions.checkNotNull(
+ OutputArtifactResolver.resolve(project, decoder, classJar),
+ "Fail to find file %s",
+ classJar.getRelativePath()));
+ }
+ }
+ }
+
return results.build();
}
}
diff --git a/aswb/src/com/google/idea/blaze/android/sync/projectstructure/BlazeAndroidProjectStructureSyncer.java b/aswb/src/com/google/idea/blaze/android/sync/projectstructure/BlazeAndroidProjectStructureSyncer.java
index 2382d6b168e..a73e6d346e6 100644
--- a/aswb/src/com/google/idea/blaze/android/sync/projectstructure/BlazeAndroidProjectStructureSyncer.java
+++ b/aswb/src/com/google/idea/blaze/android/sync/projectstructure/BlazeAndroidProjectStructureSyncer.java
@@ -33,6 +33,7 @@
import com.google.common.util.concurrent.MoreExecutors;
import com.google.idea.blaze.android.manifest.ManifestParser;
import com.google.idea.blaze.android.manifest.ParsedManifestService;
+import com.google.idea.blaze.android.projectsystem.BlazeModuleSystem;
import com.google.idea.blaze.android.projectview.GeneratedAndroidResourcesSection;
import com.google.idea.blaze.android.resources.BlazeLightResourceClassService;
import com.google.idea.blaze.android.sync.importer.BlazeAndroidWorkspaceImporter;
@@ -358,6 +359,7 @@ private static void updateInMemoryState(
configAndroidJava8Libs);
rClassBuilder.addRClass(modulePackage, module);
sourcePackages.remove(modulePackage);
+ BlazeModuleSystem.getInstance(module).clearCache();
}
rClassBuilder.addWorkspacePackages(sourcePackages);