diff --git a/aspect/intellij_info_impl.bzl b/aspect/intellij_info_impl.bzl index 4345f110d34..3dca7a4534c 100644 --- a/aspect/intellij_info_impl.bzl +++ b/aspect/intellij_info_impl.bzl @@ -149,11 +149,19 @@ def get_source_jars(output): return [output.source_jar] return [] -def library_artifact(java_output): +def get_rule_source_jar(rule): + if hasattr(rule.attr, "srcjar"): + if rule.attr.srcjar != None: + return rule.attr.srcjar.files.to_list() + return [] + +def library_artifact(java_output, rule=None): """Creates a LibraryArtifact representing a given java_output.""" if java_output == None or java_output.class_jar == None: return None src_jars = get_source_jars(java_output) + if rule and not src_jars: + src_jars = get_rule_source_jar(rule) return struct_omit_none( interface_jar = artifact_location(java_output.ijar), jar = artifact_location(java_output.class_jar), @@ -591,7 +599,7 @@ def collect_java_info(target, ctx, semantics, ide_info, ide_info_file, output_gr ide_info_files = [] sources = sources_from_target(ctx) - jars = [library_artifact(output) for output in java_outputs] + jars = [library_artifact(output, ctx.rule) for output in java_outputs] class_jars = [output.class_jar for output in java_outputs if output and output.class_jar] output_jars = [jar for output in java_outputs for jar in jars_from_output(output)] resolve_files = output_jars diff --git a/aswb/src/META-INF/aswb.xml b/aswb/src/META-INF/aswb.xml index f95599dc894..58ae9a915e4 100644 --- a/aswb/src/META-INF/aswb.xml +++ b/aswb/src/META-INF/aswb.xml @@ -70,6 +70,7 @@ + diff --git a/aswb/src/com/google/idea/blaze/android/compose/ExperimentComposeStatusProvider.java b/aswb/src/com/google/idea/blaze/android/compose/ExperimentComposeStatusProvider.java index 50bf172c5d5..00a0d9c471f 100644 --- a/aswb/src/com/google/idea/blaze/android/compose/ExperimentComposeStatusProvider.java +++ b/aswb/src/com/google/idea/blaze/android/compose/ExperimentComposeStatusProvider.java @@ -24,7 +24,7 @@ */ public class ExperimentComposeStatusProvider implements ComposeStatusProvider { private static final BoolExperiment composeEnabled = - new BoolExperiment("aswb.force.enable.compose", false); + new BoolExperiment("aswb.force.enable.compose", true); @Override public boolean composeEnabled(Project project) { 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 223613c89f2..424dc6fcfc8 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; @@ -44,15 +43,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 { @@ -166,14 +170,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 @@ -182,7 +198,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..3578f8533ef 100644 --- a/aswb/src/com/google/idea/blaze/android/projectsystem/BlazeModuleSystemBase.java +++ b/aswb/src/com/google/idea/blaze/android/projectsystem/BlazeModuleSystemBase.java @@ -68,6 +68,10 @@ import com.intellij.psi.PsiElement; import com.intellij.psi.search.GlobalSearchScope; import com.intellij.psi.search.ProjectScope; +import kotlin.Triple; +import org.jetbrains.annotations.Nullable; +import org.jetbrains.annotations.TestOnly; + import java.io.File; import java.io.IOException; import java.nio.file.Path; @@ -78,9 +82,6 @@ import java.util.Set; import java.util.stream.Collectors; import java.util.stream.Stream; -import kotlin.Triple; -import org.jetbrains.annotations.Nullable; -import org.jetbrains.annotations.TestOnly; /** Blaze implementation of {@link AndroidModuleSystem}. */ @SuppressWarnings("NullableProblems") @@ -174,8 +175,6 @@ public void registerDependency(GradleCoordinate coordinate, DependencyType type) } // TODO: automagically edit deps instead of just opening the BUILD file? - // Need to translate Gradle coordinates into blaze targets. - // Will probably need to hardcode for each dependency. FileEditorManager fileEditorManager = FileEditorManager.getInstance(project); PsiElement buildTargetPsi = BuildReferenceManager.getInstance(project).resolveLabel(targetIdeInfo.getKey().getLabel()); @@ -205,6 +204,10 @@ public void registerDependency(GradleCoordinate coordinate, DependencyType type) } } + public void clearCache() { + classFileFinder.clearCache(); + } + @Nullable @Override public GradleCoordinate getRegisteredDependency(GradleCoordinate coordinate) { @@ -327,7 +330,7 @@ private Stream locateArtifactsFor(GradleCoordinate coordinate) { // labels in order to find them. return MavenArtifactLocator.forBuildSystem(Blaze.getBuildSystemName(module.getProject())) .stream() - .map(locator -> locator.labelFor(coordinate)) + .map(locator -> locator.labelFor(module.getProject(), coordinate)) .filter(Objects::nonNull) .map(TargetKey::forPlainTarget); } diff --git a/aswb/src/com/google/idea/blaze/android/projectsystem/BlazeProjectSystemBuildManager.java b/aswb/src/com/google/idea/blaze/android/projectsystem/BlazeProjectSystemBuildManager.java index 38b8b630dfa..c192671f062 100644 --- a/aswb/src/com/google/idea/blaze/android/projectsystem/BlazeProjectSystemBuildManager.java +++ b/aswb/src/com/google/idea/blaze/android/projectsystem/BlazeProjectSystemBuildManager.java @@ -15,8 +15,6 @@ */ package com.google.idea.blaze.android.projectsystem; -import static java.lang.Math.max; - import com.android.annotations.concurrency.UiThread; import com.android.tools.idea.projectsystem.ProjectSystemBuildManager; import com.google.idea.blaze.base.build.BlazeBuildListener; @@ -28,9 +26,12 @@ import com.intellij.openapi.project.Project; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.util.messages.Topic; +import org.jetbrains.annotations.NotNull; + import java.util.Collection; import java.util.concurrent.atomic.AtomicInteger; -import org.jetbrains.annotations.NotNull; + +import static java.lang.Math.max; /** Blaze implementation of {@link ProjectSystemBuildManager} */ public class BlazeProjectSystemBuildManager implements ProjectSystemBuildManager { @@ -51,8 +52,12 @@ public void compileProject() { @Override public void compileFilesAndDependencies(Collection files) { // TODO(b/191937319): Implement incremental builds for individual files - // Just compile the entire project for now. - compileProject(); + // Do an incremental sync for now so that previews update appropriately + //BlazeSyncManager.getInstance(project).workingSetSync("Compile files and dependencies"); + // TODO: use partialSync with targets verived from `files` (see logic in + // BlazeSyncParams.sourceFilesToSync + //compileProject(); + BlazeBuildService.getInstance(project).buildFiles(files); } @Override diff --git a/aswb/src/com/google/idea/blaze/android/projectsystem/DefaultMavenArtifactLocator.java b/aswb/src/com/google/idea/blaze/android/projectsystem/DefaultMavenArtifactLocator.java new file mode 100644 index 00000000000..8fa8d5de175 --- /dev/null +++ b/aswb/src/com/google/idea/blaze/android/projectsystem/DefaultMavenArtifactLocator.java @@ -0,0 +1,60 @@ +package com.google.idea.blaze.android.projectsystem; + +import com.android.ide.common.repository.GradleCoordinate; +import com.google.idea.blaze.base.ideinfo.TargetMap; +import com.google.idea.blaze.base.model.primitives.Label; +import com.google.idea.blaze.base.settings.BuildSystemName; +import com.google.idea.blaze.base.sync.data.BlazeProjectDataManager; +import com.intellij.openapi.diagnostic.Logger; +import com.intellij.openapi.project.Project; + +public class DefaultMavenArtifactLocator implements MavenArtifactLocator { + private static final Logger log = Logger.getInstance(DefaultMavenArtifactLocator.class); + private static final String mavenCoordinateTagPrefix = "maven_coordinates="; + + /** + * Locate an artifact label by maven coordinates. This is somewhat brittle, + * but Android Studio requests specific artifacts needed for their preview + * system, so we make our best attempt here to locate them using `maven_install` + * patterned bazel artifacts. + */ + public Label labelFor(Project project, GradleCoordinate coordinate) { + TargetMap targetMap = BlazeProjectDataManager.getInstance(project) + .getBlazeProjectData().getTargetMap(); + + String desiredCoord = mavenCoordinateTagPrefix + coordinate.getGroupId() + + ":" + coordinate.getArtifactId() + ":"; + String labelSuffix = String.format(":%s_%s", + coordinate.getGroupId().replaceAll("[.-]", "_"), + coordinate.getArtifactId().replaceAll("[.-]", "_") + ); + + // Debug code to list all targets. Some go missing sometimes... + /*String debugString = targetMap.map().keySet().stream() + .sorted(Comparator.comparing(TargetKey::toString)) + .map(x -> x.getLabel().toString()) + .collect(Collectors.joining(", ")); + System.out.println(debugString);*/ + + return targetMap.targets().stream().filter(target -> { + for (String tag : target.getTags()) { + if (tag.startsWith(desiredCoord)) { + return true; + } + } + return false; + }) + .map(x -> x.getKey().getLabel()) + .findFirst().orElseGet(() -> { + Label bestGuess = Label.create("@maven//" + labelSuffix); + log.warn(String.format( + "Could not find exact label for %s, returning best guess of %s", + coordinate, bestGuess)); + return bestGuess; + }); + } + + public BuildSystemName buildSystem() { + return BuildSystemName.Bazel; + } +} \ No newline at end of file diff --git a/aswb/src/com/google/idea/blaze/android/projectsystem/MavenArtifactLocator.java b/aswb/src/com/google/idea/blaze/android/projectsystem/MavenArtifactLocator.java index 6fa59cb4a38..cc1362d906e 100644 --- a/aswb/src/com/google/idea/blaze/android/projectsystem/MavenArtifactLocator.java +++ b/aswb/src/com/google/idea/blaze/android/projectsystem/MavenArtifactLocator.java @@ -20,6 +20,8 @@ import com.google.idea.blaze.base.model.primitives.Label; import com.google.idea.blaze.base.settings.BuildSystemName; import com.intellij.openapi.extensions.ExtensionPointName; +import com.intellij.openapi.project.Project; + import java.util.Arrays; import java.util.List; import java.util.stream.Collectors; @@ -41,7 +43,7 @@ public interface MavenArtifactLocator { * * @param coordinate GradleCoordinate for the artifact. */ - Label labelFor(GradleCoordinate coordinate); + Label labelFor(Project project, GradleCoordinate coordinate); /** Returns the {@link BuildSystemName} this {@link MavenArtifactLocator} supports. */ BuildSystemName buildSystem(); 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..d40f9a8f97b 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; @@ -38,13 +37,22 @@ import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.module.Module; +import com.intellij.openapi.module.ModuleManager; import com.intellij.openapi.project.Project; +import com.intellij.openapi.util.Computable; 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.HashSet; +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 +70,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. */ @@ -70,11 +80,12 @@ public class RenderJarClassFileFinder implements ClassFileFinder { /** * Experiment to toggle whether resource resolution is allowed from Render JARs. Render JARs - * should not resolve resources by default. + * should not resolve resources by default, but the full ClassLoader mechanics of the preview + * screen require that all classes resolve in order to display the content, so we allow it. */ @VisibleForTesting - static final BoolExperiment resolveResourceClasses = - new BoolExperiment("aswb.resolve.resources.render.jar", false); + static final BoolExperiment resolveResourceClasses = // TODO: figure out if this is actually needed...... + new BoolExperiment("aswb.resolve.resources.render.jar", true); private static final Logger log = Logger.getInstance(RenderJarClassFileFinder.class); @@ -86,6 +97,7 @@ public class RenderJarClassFileFinder implements ClassFileFinder { private final Module module; private final Project project; + // tracks the binary targets that depend resource targets // will be recalculated after every sync private ImmutableSet binaryTargets = ImmutableSet.of(); @@ -98,10 +110,13 @@ public class RenderJarClassFileFinder implements ClassFileFinder { // true if the current module is the .workspace Module private final boolean isWorkspaceModule; + private Map> packageJarHint = new HashMap(); + public RenderJarClassFileFinder(Module module) { this.module = module; this.project = module.getProject(); this.isWorkspaceModule = BlazeDataStorage.WORKSPACE_MODULE_NAME.equals(module.getName()); + clearCache(); } @Nullable @@ -169,14 +184,32 @@ 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; } } + VirtualFile moduleClass = searchForFQCNInModule(fqcn); + if (moduleClass != null) { + return moduleClass; + } + + // Fall back to workspace resolution + if (!isWorkspaceModule) { + Module workspaceModule = ModuleManager.getInstance(project) + .findModuleByName(BlazeDataStorage.WORKSPACE_MODULE_NAME); + return BlazeModuleSystem.getInstance(workspaceModule).classFileFinder.findClass(fqcn); + } + log.warn(String.format("Could not find class `%1$s` (module: `%2$s`)", fqcn, module.getName())); return null; } + public synchronized void clearCache() { + //log.warn("clearing cache"); + //packageJarHint = new HashMap(); + } + @VisibleForTesting static boolean isResourceClass(String fqcn) { return RESOURCE_CLASS_NAME.matcher(fqcn).matches(); @@ -247,6 +280,69 @@ private VirtualFile getClassFromRenderResolveJar( return findClassInJar(renderResolveJarVF, fqcn); } + @Nullable + private VirtualFile searchForFQCNInModule(String fqcn) { + // keeps throwing java.lang.Throwable: Slow operations are prohibited on EDT. See SlowOperations.assertSlowOperationsAreAllowed javadoc + /*VirtualFile psiFile = ApplicationManager.getApplication().runReadAction((Computable) () -> { + try { + final JavaPsiFacade facade = JavaPsiFacade.getInstance(project); + PsiClass baseClass = + facade.findClass(fqcn, ProjectScope.getAllScope(project)); + if (baseClass == null) { + return null; + } + VirtualFile theFile = baseClass.getNavigationElement().getContainingFile().getVirtualFile(); + if (theFile.toString().endsWith(".class")) { + return theFile; + } + } catch (Throwable t) { + log.warn("failed to use JavaPsiFacade: " + t.getLocalizedMessage()); + } + return null; + }); + + if (psiFile != null) { + return psiFile; + }*/ + + String pkg = null; + int pkgIdx = fqcn.lastIndexOf('.'); + if (pkgIdx != -1) { + pkg = fqcn.substring(0, pkgIdx); + } + HashSet hintJars = pkg == null ? null : packageJarHint.get(pkg); + if (hintJars != null) { + for (File hintJar : hintJars) { + VirtualFile jarVF = VirtualFileSystemProvider.getInstance().getSystem().findFileByIoFile(hintJar); + if (jarVF != null) { + VirtualFile foundClass = findClassInJar(jarVF, fqcn); + if (foundClass != null) { + return foundClass; + } + } + } + } + List moduleLibraries = new BlazeClassJarProvider(this.project).getModuleExternalLibraries(module); + + 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) { + if (hintJars == null) hintJars = new HashSet<>(); + hintJars.add(jar); + // TODO: better caching + packageJarHint.put(pkg, hintJars); + } + return foundClass; + } + } + return null; + } + @Nullable private static VirtualFile findClassInJar(final VirtualFile classJar, String fqcn) { VirtualFile jarRoot = getJarRootForLocalFile(classJar); 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/AndroidOutputsProvider.java b/aswb/src/com/google/idea/blaze/android/sync/AndroidOutputsProvider.java index 932ad1569e8..5ebe4a84ece 100644 --- a/aswb/src/com/google/idea/blaze/android/sync/AndroidOutputsProvider.java +++ b/aswb/src/com/google/idea/blaze/android/sync/AndroidOutputsProvider.java @@ -70,7 +70,11 @@ public Collection selectAllRelevantOutputs(TargetIdeInfo targe private static void addLibrary( ImmutableList.Builder list, @Nullable LibraryArtifact library) { if (library != null) { - addArtifact(list, library.getInterfaceJar()); + // Interface jars have a different signature, and will break reference to source jars. + // Only add them if we need to. + if (library.getClassJar() == null && library.getSourceJars().isEmpty()) { + addArtifact(list, library.getInterfaceJar()); + } addArtifact(list, library.getClassJar()); library.getSourceJars().forEach(j -> addArtifact(list, j)); } 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 62a41bf8ba5..61e31fef89e 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 @@ -15,8 +15,6 @@ */ package com.google.idea.blaze.android.sync.importer; -import static java.util.stream.Collectors.toCollection; - import com.google.common.annotations.VisibleForTesting; import com.google.common.collect.ArrayListMultimap; import com.google.common.collect.ComparisonChain; @@ -46,6 +44,9 @@ import com.google.idea.blaze.common.Output; import com.google.idea.common.experiments.BoolExperiment; import com.intellij.openapi.project.Project; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + import java.util.Collection; import java.util.Collections; import java.util.Comparator; @@ -58,8 +59,8 @@ import java.util.function.Consumer; import java.util.function.Predicate; import java.util.stream.Collectors; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; + +import static java.util.stream.Collectors.toCollection; /** Builds a BlazeWorkspace. */ public class BlazeAndroidWorkspaceImporter { @@ -280,7 +281,8 @@ public static boolean containsSourcesOrAllowedGeneratedResources( public static boolean isSourceOrAllowedGenPath( ArtifactLocation artifactLocation, Predicate allowlistTest) { - return artifactLocation.isSource() || allowlistTest.test(artifactLocation); + return true; // TODO: TEST: remove later + //return artifactLocation.isSource() || allowlistTest.test(artifactLocation); } private ImmutableList buildAndroidResourceModules( 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 82fe2957c73..b047e176d24 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 @@ -15,8 +15,6 @@ */ package com.google.idea.blaze.android.sync.model.idea; -import static com.google.common.collect.ImmutableList.toImmutableList; - import com.android.tools.idea.model.ClassJarProvider; import com.google.common.base.Preconditions; import com.google.common.collect.ImmutableList; @@ -33,6 +31,7 @@ import com.google.idea.blaze.base.ideinfo.TargetMap; import com.google.idea.blaze.base.model.BlazeProjectData; import com.google.idea.blaze.base.qsync.QuerySync; +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.workspace.ArtifactLocationDecoder; import com.google.idea.blaze.base.targetmaps.TransitiveDependencyMap; @@ -50,9 +49,13 @@ import com.intellij.psi.PsiClass; import com.intellij.psi.PsiFile; import com.intellij.psi.search.GlobalSearchScope; + import java.io.File; import java.util.List; import java.util.Objects; +import java.util.stream.Collectors; + +import static com.google.common.collect.ImmutableList.toImmutableList; /** Collects class jars from the user's build. */ public class BlazeClassJarProvider implements ClassJarProvider { @@ -81,9 +84,14 @@ public List getModuleExternalLibraries(Module module) { TargetMap targetMap = blazeProjectData.getTargetMap(); ArtifactLocationDecoder decoder = blazeProjectData.getArtifactLocationDecoder(); + boolean isWorkspaceModule = BlazeDataStorage.WORKSPACE_MODULE_NAME.equals(module.getName()); + + if (isWorkspaceModule) { + return getAllExternalLibraries(targetMap, decoder); + } if (useRenderJarForExternalLibraries.getValue()) { - return TargetToBinaryMap.getInstance(project).getSourceBinaryTargets().stream() + List renderJarLibraries = TargetToBinaryMap.getInstance(project).getSourceBinaryTargets().stream() .filter(targetMap::contains) .map( (binaryTarget) -> @@ -91,6 +99,9 @@ public List getModuleExternalLibraries(Module module) { .getCachedJarForBinaryTarget(decoder, targetMap.get(binaryTarget))) .filter(Objects::nonNull) .collect(toImmutableList()); + if (!renderJarLibraries.isEmpty()) { + return renderJarLibraries; + } } AndroidResourceModuleRegistry registry = AndroidResourceModuleRegistry.getInstance(project); @@ -112,7 +123,7 @@ public List getModuleExternalLibraries(Module module) { if (javaIdeInfo != null) { for (LibraryArtifact jar : javaIdeInfo.getJars()) { ArtifactLocation classJar = jar.getClassJar(); - if (classJar != null && classJar.isSource()) { + if (classJar != null) { results.add( Preconditions.checkNotNull( OutputArtifactResolver.resolve(project, decoder, classJar), @@ -186,4 +197,14 @@ public static boolean testIsClassFileOutOfDate( return false; } + + List getAllExternalLibraries(TargetMap targetMap, ArtifactLocationDecoder decoder) { + return targetMap.targets().stream() + .map(x -> x.getJavaIdeInfo()) + .filter(Objects::nonNull) + .flatMap(x -> x.getJars().stream()) + .map(LibraryArtifact::getClassJar).filter(Objects::nonNull) + .map(x -> OutputArtifactResolver.resolve(project, decoder, x)) + .collect(Collectors.toList()); + } } 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); diff --git a/aswb/tests/integrationtests/com/google/idea/blaze/android/functional/BlazeModuleSystemExternalDependencyIntegrationTest.java b/aswb/tests/integrationtests/com/google/idea/blaze/android/functional/BlazeModuleSystemExternalDependencyIntegrationTest.java index 16109fc3eef..e15c7f7a9a3 100644 --- a/aswb/tests/integrationtests/com/google/idea/blaze/android/functional/BlazeModuleSystemExternalDependencyIntegrationTest.java +++ b/aswb/tests/integrationtests/com/google/idea/blaze/android/functional/BlazeModuleSystemExternalDependencyIntegrationTest.java @@ -15,10 +15,6 @@ */ package com.google.idea.blaze.android.functional; -import static com.google.common.truth.Truth.assertThat; -import static com.google.idea.blaze.android.targetmapbuilder.NbAarTarget.aar_import; -import static com.google.idea.blaze.android.targetmapbuilder.NbAndroidTarget.android_library; - import com.android.SdkConstants; import com.android.ide.common.repository.GradleCoordinate; import com.android.tools.idea.projectsystem.GoogleMavenArtifactId; @@ -36,15 +32,21 @@ import com.google.idea.blaze.base.settings.BuildSystemName; import com.google.idea.blaze.base.sync.projectstructure.ModuleFinder; import com.intellij.openapi.module.Module; +import com.intellij.openapi.project.Project; import com.intellij.openapi.util.io.FileUtil; import com.intellij.util.PathUtil; -import java.io.File; -import java.nio.file.Path; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.JUnit4; +import java.io.File; +import java.nio.file.Path; + +import static com.google.common.truth.Truth.assertThat; +import static com.google.idea.blaze.android.targetmapbuilder.NbAarTarget.aar_import; +import static com.google.idea.blaze.android.targetmapbuilder.NbAndroidTarget.android_library; + /** * Integration test for external dependency management methods in {@link * com.google.idea.blaze.android.projectsystem.BlazeModuleSystem}. @@ -68,7 +70,7 @@ public void setupSourcesAndProjectView() { .build(); @Override - public Label labelFor(GradleCoordinate coordinate) { + public Label labelFor(Project project, GradleCoordinate coordinate) { return knownArtifacts.get( new GradleCoordinate(coordinate.getGroupId(), coordinate.getArtifactId(), "+")); } diff --git a/aswb/tests/integrationtests/com/google/idea/blaze/android/sync/model/idea/BlazeImportFixture.java b/aswb/tests/integrationtests/com/google/idea/blaze/android/sync/model/idea/BlazeImportFixture.java index 87b07cdc48c..9a9ba6c4568 100644 --- a/aswb/tests/integrationtests/com/google/idea/blaze/android/sync/model/idea/BlazeImportFixture.java +++ b/aswb/tests/integrationtests/com/google/idea/blaze/android/sync/model/idea/BlazeImportFixture.java @@ -64,9 +64,10 @@ import com.google.idea.blaze.java.sync.model.BlazeJavaImportResult; import com.google.idea.blaze.java.sync.model.BlazeJavaSyncData; import com.intellij.openapi.project.Project; -import java.io.File; import org.jetbrains.annotations.NotNull; +import java.io.File; + /** * Fixture that generates a number of data structures related to blaze import for a hardcoded * project. @@ -201,7 +202,7 @@ public MavenArtifactLocator getMavenArtifactLocator() { mavenArtifactLocator = new MavenArtifactLocator() { @Override - public Label labelFor(GradleCoordinate coordinate) { + public Label labelFor(Project project, GradleCoordinate coordinate) { switch (GoogleMavenArtifactId.forCoordinate(coordinate)) { case RECYCLERVIEW_V7: return Label.create("//third_party/recyclerview:recyclerview"); diff --git a/base/src/com/google/idea/blaze/base/build/BlazeBuildService.java b/base/src/com/google/idea/blaze/base/build/BlazeBuildService.java index bb855b6812d..8103ff1a090 100644 --- a/base/src/com/google/idea/blaze/base/build/BlazeBuildService.java +++ b/base/src/com/google/idea/blaze/base/build/BlazeBuildService.java @@ -16,6 +16,7 @@ package com.google.idea.blaze.base.build; import com.google.common.collect.ImmutableCollection; +import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableSet; import com.google.common.collect.Lists; import com.google.common.util.concurrent.FutureCallback; @@ -27,12 +28,14 @@ import com.google.idea.blaze.base.bazel.BuildSystem.BuildInvoker; import com.google.idea.blaze.base.bazel.BuildSystem.SyncStrategy; import com.google.idea.blaze.base.command.BlazeInvocationContext; +import com.google.idea.blaze.base.dependencies.BlazeQuerySourceToTargetProvider; import com.google.idea.blaze.base.experiments.ExperimentScope; import com.google.idea.blaze.base.filecache.FileCaches; import com.google.idea.blaze.base.issueparser.BlazeIssueParser; import com.google.idea.blaze.base.model.BlazeProjectData; import com.google.idea.blaze.base.model.primitives.Label; import com.google.idea.blaze.base.model.primitives.TargetExpression; +import com.google.idea.blaze.base.model.primitives.WorkspacePath; import com.google.idea.blaze.base.model.primitives.WorkspaceRoot; import com.google.idea.blaze.base.projectview.ProjectViewManager; import com.google.idea.blaze.base.projectview.ProjectViewSet; @@ -58,16 +61,23 @@ import com.google.idea.blaze.base.sync.data.BlazeProjectDataManager; import com.google.idea.blaze.base.sync.sharding.BlazeBuildTargetSharder; import com.google.idea.blaze.base.sync.sharding.BlazeBuildTargetSharder.ShardedTargetsResult; +import com.google.idea.blaze.base.sync.workspace.WorkspacePathResolver; import com.google.idea.blaze.base.toolwindow.Task; import com.google.idea.blaze.base.util.SaveUtil; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.components.ServiceManager; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.Key; +import com.intellij.openapi.vfs.VirtualFile; + +import java.io.File; +import java.util.Collection; import java.util.List; import java.util.concurrent.Future; import javax.annotation.Nullable; +import static com.google.common.collect.ImmutableList.toImmutableList; + /** Utility to build various collections of targets. */ public class BlazeBuildService { private static final Key PROJECT_LAST_BUILD_TIMESTAMP_KEY = @@ -112,6 +122,50 @@ public void buildFile(String fileName, ImmutableCollection