diff options
5 files changed, 916 insertions, 493 deletions
diff --git a/src/main/java/com/google/devtools/build/lib/ideinfo/AndroidStudioInfoAspect.java b/src/main/java/com/google/devtools/build/lib/ideinfo/AndroidStudioInfoAspect.java index deab1cff3d..8d2f52c340 100644 --- a/src/main/java/com/google/devtools/build/lib/ideinfo/AndroidStudioInfoAspect.java +++ b/src/main/java/com/google/devtools/build/lib/ideinfo/AndroidStudioInfoAspect.java @@ -88,9 +88,7 @@ import java.util.Collection; import java.util.List; import javax.annotation.Nullable; -/** - * Generates ide-build information for Android Studio. - */ +/** Generates ide-build information for Android Studio. */ public class AndroidStudioInfoAspect extends NativeAspectClass implements ConfiguredAspectFactory { public static final String NAME = "AndroidStudioInfoAspect"; @@ -106,8 +104,7 @@ public class AndroidStudioInfoAspect extends NativeAspectClass implements Config private final ImmutableList<PrerequisiteAttr> prerequisiteAttrs; public AndroidStudioInfoAspect( - String toolsRepository, - AndroidStudioInfoSemantics androidStudioInfoSemantics) { + String toolsRepository, AndroidStudioInfoSemantics androidStudioInfoSemantics) { this.toolsRepository = toolsRepository; this.androidStudioInfoSemantics = androidStudioInfoSemantics; this.prerequisiteAttrs = buildPrerequisiteAttrs(); @@ -118,12 +115,11 @@ public class AndroidStudioInfoAspect extends NativeAspectClass implements Config return NAME; } - /** - * Attribute to propagate dependencies along. - */ + /** Attribute to propagate dependencies along. */ public static class PrerequisiteAttr { public final String name; public final Type<?> type; + public PrerequisiteAttr(String name, Type<?> type) { this.name = name; this.type = type; @@ -149,25 +145,35 @@ public class AndroidStudioInfoAspect extends NativeAspectClass implements Config // File suffixes. public static final String ASWB_BUILD_SUFFIX = ".aswb-build"; public static final String ASWB_BUILD_TEXT_SUFFIX = ".aswb-build.txt"; - public static final Function<Label, String> LABEL_TO_STRING = new Function<Label, String>() { - @Nullable - @Override - public String apply(Label label) { - return label.toString(); - } - }; + public static final Function<Label, String> LABEL_TO_STRING = + new Function<Label, String>() { + @Nullable + @Override + public String apply(Label label) { + return label.toString(); + } + }; @Override public AspectDefinition getDefinition(AspectParameters aspectParameters) { - AspectDefinition.Builder builder = new AspectDefinition.Builder(NAME) - .attributeAspect("runtime_deps", this) - .attributeAspect("resources", this) - .add(attr("$packageParser", LABEL).cfg(HOST).exec() - .value(Label.parseAbsoluteUnchecked( - toolsRepository + "//tools/android:PackageParser"))) - .add(attr("$jarFilter", LABEL).cfg(HOST).exec() - .value(Label.parseAbsoluteUnchecked( - toolsRepository + "//tools/android:JarFilter"))); + AspectDefinition.Builder builder = + new AspectDefinition.Builder(NAME) + .attributeAspect("runtime_deps", this) + .attributeAspect("resources", this) + .add( + attr("$packageParser", LABEL) + .cfg(HOST) + .exec() + .value( + Label.parseAbsoluteUnchecked( + toolsRepository + "//tools/android:PackageParser"))) + .add( + attr("$jarFilter", LABEL) + .cfg(HOST) + .exec() + .value( + Label.parseAbsoluteUnchecked( + toolsRepository + "//tools/android:JarFilter"))); for (PrerequisiteAttr prerequisiteAttr : prerequisiteAttrs) { builder.attributeAspect(prerequisiteAttr.name, this); @@ -215,19 +221,21 @@ public class AndroidStudioInfoAspect extends NativeAspectClass implements Config } private static class DependenciesResult { - private DependenciesResult(Iterable<Label> deps, - Iterable<Label> runtimeDeps, @Nullable Label resources) { + private DependenciesResult( + Iterable<Label> deps, Iterable<Label> runtimeDeps, @Nullable Label resources) { this.deps = deps; this.runtimeDeps = runtimeDeps; this.resources = resources; } + final Iterable<Label> deps; final Iterable<Label> runtimeDeps; @Nullable final Label resources; } private DependenciesResult processDependencies( - ConfiguredTarget base, RuleContext ruleContext, + ConfiguredTarget base, + RuleContext ruleContext, AndroidStudioInfoFilesProvider.Builder providerBuilder) { // Calculate direct dependencies @@ -236,8 +244,8 @@ public class AndroidStudioInfoAspect extends NativeAspectClass implements Config if (ruleContext.attributes().has(prerequisiteAttr.name, prerequisiteAttr.type)) { Mode mode = ruleContext.getAttributeMode(prerequisiteAttr.name); if (mode == Mode.TARGET || mode == Mode.SPLIT) { - directDepsBuilder - .addAll(ruleContext.getPrerequisites(prerequisiteAttr.name, Mode.TARGET)); + directDepsBuilder.addAll( + ruleContext.getPrerequisites(prerequisiteAttr.name, Mode.TARGET)); } } } @@ -257,14 +265,15 @@ public class AndroidStudioInfoAspect extends NativeAspectClass implements Config // Propagate my own exports JavaExportsProvider javaExportsProvider = base.getProvider(JavaExportsProvider.class); if (javaExportsProvider != null) { - providerBuilder.exportedDepsBuilder() + providerBuilder + .exportedDepsBuilder() .addTransitive(javaExportsProvider.getTransitiveExports()); } // android_library without sources exports all its deps if (ruleContext.getRule().getRuleClass().equals("android_library")) { JavaSourceInfoProvider sourceInfoProvider = base.getProvider(JavaSourceInfoProvider.class); - boolean hasSources = sourceInfoProvider != null - && !sourceInfoProvider.getSourceFiles().isEmpty(); + boolean hasSources = + sourceInfoProvider != null && !sourceInfoProvider.getSourceFiles().isEmpty(); if (!hasSources) { for (TransitiveInfoCollection dep : directDeps) { providerBuilder.exportedDepsBuilder().add(dep.getLabel()); @@ -283,7 +292,8 @@ public class AndroidStudioInfoAspect extends NativeAspectClass implements Config } // resources - @Nullable TransitiveInfoCollection resources = + @Nullable + TransitiveInfoCollection resources = ruleContext.attributes().has("resources", BuildType.LABEL) ? ruleContext.getPrerequisite("resources", Mode.TARGET) : null; @@ -340,8 +350,8 @@ public class AndroidStudioInfoAspect extends NativeAspectClass implements Config JavaRuleOutputJarsProvider outputJarsProvider = base.getProvider(JavaRuleOutputJarsProvider.class); if (outputJarsProvider != null && !androidStudioInfoSemantics.suppressJavaRuleInfo(base)) { - JavaRuleIdeInfo javaRuleIdeInfo = makeJavaRuleIdeInfo(base, ruleContext, - outputJarsProvider, providerBuilder); + JavaRuleIdeInfo javaRuleIdeInfo = + makeJavaRuleIdeInfo(base, ruleContext, outputJarsProvider, providerBuilder); outputBuilder.setJavaRuleIdeInfo(javaRuleIdeInfo); } @@ -370,15 +380,16 @@ public class AndroidStudioInfoAspect extends NativeAspectClass implements Config // Android rules AndroidIdeInfoProvider androidIdeInfoProvider = base.getProvider(AndroidIdeInfoProvider.class); if (androidIdeInfoProvider != null) { - outputBuilder.setAndroidRuleIdeInfo(makeAndroidRuleIdeInfo( - androidIdeInfoProvider, dependenciesResult, ideResolveArtifacts)); + outputBuilder.setAndroidRuleIdeInfo( + makeAndroidRuleIdeInfo(androidIdeInfoProvider, dependenciesResult, ideResolveArtifacts)); } // Test rules if (TargetUtils.isTestRule(base.getTarget())) { TestInfo.Builder builder = TestInfo.newBuilder(); - String attr = NonconfigurableAttributeMapper.of(base.getTarget().getAssociatedRule()) - .get("size", Type.STRING); + String attr = + NonconfigurableAttributeMapper.of(base.getTarget().getAssociatedRule()) + .get("size", Type.STRING); if (attr != null) { builder.setSize(attr); } @@ -388,9 +399,10 @@ public class AndroidStudioInfoAspect extends NativeAspectClass implements Config // Java toolchain rule JavaToolchainProvider javaToolchainProvider = base.getProvider(JavaToolchainProvider.class); if (javaToolchainProvider != null) { - outputBuilder.setJavaToolchainIdeInfo(JavaToolchainIdeInfo.newBuilder() - .setSourceVersion(javaToolchainProvider.getSourceVersion()) - .setTargetVersion(javaToolchainProvider.getTargetVersion())); + outputBuilder.setJavaToolchainIdeInfo( + JavaToolchainIdeInfo.newBuilder() + .setSourceVersion(javaToolchainProvider.getSourceVersion()) + .setTargetVersion(javaToolchainProvider.getTargetVersion())); } androidStudioInfoSemantics.augmentRuleInfo( @@ -427,18 +439,17 @@ public class AndroidStudioInfoAspect extends NativeAspectClass implements Config } private static Action[] makePackageManifestAction( - RuleContext ruleContext, - Artifact packageManifest, - Collection<Artifact> sourceFiles) { + RuleContext ruleContext, Artifact packageManifest, Collection<Artifact> sourceFiles) { return new SpawnAction.Builder() .addInputs(sourceFiles) .addOutput(packageManifest) .setExecutable(ruleContext.getExecutablePrerequisite("$packageParser", Mode.HOST)) - .setCommandLine(CustomCommandLine.builder() - .addExecPath("--output_manifest", packageManifest) - .addJoinStrings("--sources", ":", toSerializedArtifactLocations(sourceFiles)) - .build()) + .setCommandLine( + CustomCommandLine.builder() + .addExecPath("--output_manifest", packageManifest) + .addJoinStrings("--sources", ":", toSerializedArtifactLocations(sourceFiles)) + .build()) .useParameterFile(ParameterFileType.SHELL_QUOTED) .setProgressMessage("Parsing java package strings for " + ruleContext.getRule()) .setMnemonic("JavaPackageManifest") @@ -447,8 +458,7 @@ public class AndroidStudioInfoAspect extends NativeAspectClass implements Config private static Iterable<String> toSerializedArtifactLocations(Iterable<Artifact> artifacts) { return Iterables.transform( - Iterables.filter(artifacts, Artifact.MIDDLEMAN_FILTER), - PACKAGE_PARSER_SERIALIZER); + Iterables.filter(artifacts, Artifact.MIDDLEMAN_FILTER), PACKAGE_PARSER_SERIALIZER); } private static final Function<Artifact, String> PACKAGE_PARSER_SERIALIZER = @@ -456,47 +466,58 @@ public class AndroidStudioInfoAspect extends NativeAspectClass implements Config @Override public String apply(Artifact artifact) { Root root = artifact.getRoot(); - return Joiner.on(",").join( - root.getExecPath().toString(), - artifact.getRootRelativePath().toString() - ); + return Joiner.on(",") + .join(root.getExecPath().toString(), artifact.getRootRelativePath().toString()); } }; private static Action[] makeFilteredJarAction( RuleContext ruleContext, - List<Artifact> jars, - Artifact generatedPackageManifest, - Artifact output) { + List<Artifact> filterJars, + List<Artifact> filterSourceJars, + List<Artifact> keepJavaFiles, + List<Artifact> keepSourceJars, + Artifact filteredJar, + Artifact filteredSrcJar) { + + CustomCommandLine.Builder commandLine = + CustomCommandLine.builder() + .addExecPaths("--filter_jars", filterJars) + .addExecPaths("--filter_source_jars", filterSourceJars) + .addExecPath("--filtered_jar", filteredJar) + .addExecPath("--filtered_source_jar", filteredSrcJar); + + if (!keepJavaFiles.isEmpty()) { + commandLine.addExecPaths("--keep_java_files", keepJavaFiles); + } + if (!keepSourceJars.isEmpty()) { + commandLine.addExecPaths("--keep_source_jars", keepSourceJars); + } return new SpawnAction.Builder() - .addInputs(jars) - .addInput(generatedPackageManifest) - .addOutput(output) + .addInputs(filterJars) + .addInputs(filterSourceJars) + .addInputs(keepJavaFiles) + .addInputs(keepSourceJars) + .addOutput(filteredJar) + .addOutput(filteredSrcJar) .setExecutable(ruleContext.getExecutablePrerequisite("$jarFilter", Mode.HOST)) - .setCommandLine(CustomCommandLine.builder() - .addExecPaths("--jars", jars) - .addExecPath("--manifest", generatedPackageManifest) - .addExecPath("--output", output) - .build()) + .setCommandLine(commandLine.build()) .useParameterFile(ParameterFileType.SHELL_QUOTED) .setProgressMessage("Filtering generated code for " + ruleContext.getRule()) .setMnemonic("JarFilter") .build(ruleContext); } - private static Artifact derivedArtifact(ConfiguredTarget base, RuleContext ruleContext, - String suffix) { + private static Artifact derivedArtifact( + ConfiguredTarget base, RuleContext ruleContext, String suffix) { BuildConfiguration configuration = ruleContext.getConfiguration(); assert configuration != null; - Root binDirectory = configuration.getBinDirectory( - ruleContext.getRule().getRepository()); + Root binDirectory = configuration.getBinDirectory(ruleContext.getRule().getRepository()); - PathFragment derivedFilePath = - getOutputFilePath(base, ruleContext, suffix); + PathFragment derivedFilePath = getOutputFilePath(base, ruleContext, suffix); - return ruleContext.getAnalysisEnvironment().getDerivedArtifact( - derivedFilePath, binDirectory); + return ruleContext.getAnalysisEnvironment().getDerivedArtifact(derivedFilePath, binDirectory); } private static AndroidRuleIdeInfo makeAndroidRuleIdeInfo( @@ -533,8 +554,12 @@ public class AndroidStudioInfoAspect extends NativeAspectClass implements Config boolean hasIdlSources = !androidIdeInfoProvider.getIdlSrcs().isEmpty(); builder.setHasIdlSources(hasIdlSources); if (hasIdlSources) { - LibraryArtifact idlLibraryArtifact = makeLibraryArtifact(ideResolveArtifacts, - androidIdeInfoProvider.getIdlClassJar(), null, androidIdeInfoProvider.getIdlSourceJar()); + LibraryArtifact idlLibraryArtifact = + makeLibraryArtifact( + ideResolveArtifacts, + androidIdeInfoProvider.getIdlClassJar(), + null, + androidIdeInfoProvider.getIdlSourceJar()); if (idlLibraryArtifact != null) { builder.setIdlJar(idlLibraryArtifact); } @@ -548,8 +573,12 @@ public class AndroidStudioInfoAspect extends NativeAspectClass implements Config OutputJar resourceJar = androidIdeInfoProvider.getResourceJar(); if (resourceJar != null) { - LibraryArtifact resourceLibraryArtifact = makeLibraryArtifact(ideResolveArtifacts, - resourceJar.getClassJar(), resourceJar.getIJar(), resourceJar.getSrcJar()); + LibraryArtifact resourceLibraryArtifact = + makeLibraryArtifact( + ideResolveArtifacts, + resourceJar.getClassJar(), + resourceJar.getIJar(), + resourceJar.getSrcJar()); if (resourceLibraryArtifact != null) { builder.setResourceJar(resourceLibraryArtifact); } @@ -591,8 +620,8 @@ public class AndroidStudioInfoAspect extends NativeAspectClass implements Config } private static ArtifactLocation makeArtifactLocation(Package pkg) { - Root root = Root.asSourceRoot(pkg.getSourceRoot(), - pkg.getPackageIdentifier().getRepository().isMain()); + Root root = + Root.asSourceRoot(pkg.getSourceRoot(), pkg.getPackageIdentifier().getRepository().isMain()); PathFragment relativePath = pkg.getBuildFile().getPath().relativeTo(root.getPath()); return makeArtifactLocation(root, relativePath); } @@ -623,38 +652,55 @@ public class AndroidStudioInfoAspect extends NativeAspectClass implements Config List<Artifact> javaSources = Lists.newArrayList(); List<Artifact> generatedJavaSources = Lists.newArrayList(); - getJavaSourcesForPackageManifest(ruleContext, javaSources, generatedJavaSources); + List<Artifact> srcjars = Lists.newArrayList(); + divideJavaSources(ruleContext, javaSources, generatedJavaSources, srcjars); if (!javaSources.isEmpty()) { Artifact packageManifest = derivedArtifact(base, ruleContext, ".manifest"); providerBuilder.ideInfoFilesBuilder().add(packageManifest); - ruleContext.registerAction(makePackageManifestAction( - ruleContext, packageManifest, javaSources)); + ruleContext.registerAction( + makePackageManifestAction(ruleContext, packageManifest, javaSources)); builder.setPackageManifest(makeArtifactLocation(packageManifest)); } - if (!javaSources.isEmpty() && !generatedJavaSources.isEmpty()) { - Artifact generatedPackageManifest = derivedArtifact( - base, ruleContext, "-filtered-gen.manifest"); - ruleContext.registerAction(makePackageManifestAction(ruleContext, - generatedPackageManifest, generatedJavaSources)); + // HACK -- android_library rules with the resources attribute do not support srcjar inputs + // to the filtered gen jar generation, because we don't want all resource classes in this jar. + // This can be removed once android_resources is deleted + if (ruleContext.attributes().has("resources", BuildType.LABEL) + && ruleContext.getRule().getRuleClass().startsWith("android_")) { + srcjars = ImmutableList.of(); + } + + if (!javaSources.isEmpty() && (!generatedJavaSources.isEmpty() || !srcjars.isEmpty())) { Artifact filteredGenJar = derivedArtifact(base, ruleContext, "-filtered-gen.jar"); + Artifact filteredGenSrcJar = derivedArtifact(base, ruleContext, "-filtered-gen-src.jar"); List<Artifact> jars = Lists.newArrayList(); + List<Artifact> sourceJars = Lists.newArrayList(); for (OutputJar outputJar : outputJarsProvider.getOutputJars()) { Artifact jar = outputJar.getIJar(); if (jar == null) { jar = outputJar.getClassJar(); } - if (jar == null) { - continue; + if (jar != null) { + jars.add(jar); + } + if (outputJar.getSrcJar() != null) { + sourceJars.add(outputJar.getSrcJar()); } - jars.add(jar); } - ruleContext.registerAction(makeFilteredJarAction(ruleContext, - jars, generatedPackageManifest, filteredGenJar)); + ruleContext.registerAction( + makeFilteredJarAction( + ruleContext, + jars, + sourceJars, + generatedJavaSources, + srcjars, + filteredGenJar, + filteredGenSrcJar)); ideResolveArtifacts.add(filteredGenJar); - builder.setFilteredGenJar(makeLibraryArtifact( - ideResolveArtifacts, filteredGenJar, null, null)); + ideResolveArtifacts.add(filteredGenSrcJar); + builder.setFilteredGenJar( + makeLibraryArtifact(ideResolveArtifacts, filteredGenJar, null, filteredGenSrcJar)); } collectJarsFromOutputJarsProvider(builder, ideResolveArtifacts, outputJarsProvider); @@ -664,8 +710,7 @@ public class AndroidStudioInfoAspect extends NativeAspectClass implements Config builder.setJdeps(makeArtifactLocation(jdeps)); } - JavaGenJarsProvider genJarsProvider = - base.getProvider(JavaGenJarsProvider.class); + JavaGenJarsProvider genJarsProvider = base.getProvider(JavaGenJarsProvider.class); if (genJarsProvider != null) { collectGenJars(builder, ideResolveArtifacts, genJarsProvider); } @@ -736,15 +781,13 @@ public class AndroidStudioInfoAspect extends NativeAspectClass implements Config builder.addAllLinkOption(cppConfiguration.getLinkOptions()); // This includes options such as system includes from toolchains. - builder.addAllUnfilteredCompilerOption( - cppConfiguration.getUnfilteredCompilerOptions(features)); + builder.addAllUnfilteredCompilerOption(cppConfiguration.getUnfilteredCompilerOptions(features)); builder.setPreprocessorExecutable( cppConfiguration.getCpreprocessorExecutable().getSafePathString()); builder.setCppExecutable(cppConfiguration.getCppExecutable().getSafePathString()); - List<PathFragment> builtInIncludeDirectories = cppConfiguration - .getBuiltInIncludeDirectories(); + List<PathFragment> builtInIncludeDirectories = cppConfiguration.getBuiltInIncludeDirectories(); for (PathFragment builtInIncludeDirectory : builtInIncludeDirectories) { builder.addBuiltInIncludeDirectory(builtInIncludeDirectory.getSafePathString()); } @@ -756,8 +799,12 @@ public class AndroidStudioInfoAspect extends NativeAspectClass implements Config NestedSetBuilder<Artifact> ideResolveArtifacts, JavaRuleOutputJarsProvider outputJarsProvider) { for (OutputJar outputJar : outputJarsProvider.getOutputJars()) { - LibraryArtifact libraryArtifact = makeLibraryArtifact(ideResolveArtifacts, - outputJar.getClassJar(), outputJar.getIJar(), outputJar.getSrcJar()); + LibraryArtifact libraryArtifact = + makeLibraryArtifact( + ideResolveArtifacts, + outputJar.getClassJar(), + outputJar.getIJar(), + outputJar.getSrcJar()); if (libraryArtifact != null) { builder.addJars(libraryArtifact); @@ -770,8 +817,7 @@ public class AndroidStudioInfoAspect extends NativeAspectClass implements Config NestedSetBuilder<Artifact> ideResolveArtifacts, @Nullable Artifact classJar, @Nullable Artifact iJar, - @Nullable Artifact sourceJar - ) { + @Nullable Artifact sourceJar) { // We don't want to add anything that doesn't have a class jar if (classJar == null) { return null; @@ -815,8 +861,11 @@ public class AndroidStudioInfoAspect extends NativeAspectClass implements Config } } - private static void getJavaSourcesForPackageManifest(RuleContext ruleContext, - List<Artifact> javaSources, List<Artifact> generatedSources) { + private static void divideJavaSources( + RuleContext ruleContext, + List<Artifact> javaSources, + List<Artifact> generatedSources, + List<Artifact> srcjars) { Collection<Artifact> srcs = getSources(ruleContext); for (Artifact src : srcs) { if (src.getRootRelativePathString().endsWith(".java")) { @@ -825,6 +874,8 @@ public class AndroidStudioInfoAspect extends NativeAspectClass implements Config } else { generatedSources.add(src); } + } else if (src.getRootRelativePathString().endsWith(".srcjar")) { + srcjars.add(src); } } } @@ -845,32 +896,31 @@ public class AndroidStudioInfoAspect extends NativeAspectClass implements Config return getStringListAttribute(ruleContext, "copts"); } - private static Collection<Artifact> getTargetListAttribute(RuleContext ruleContext, - String attributeName) { + private static Collection<Artifact> getTargetListAttribute( + RuleContext ruleContext, String attributeName) { return (ruleContext.attributes().has(attributeName, BuildType.LABEL_LIST) - && ruleContext.getAttributeMode(attributeName) == Mode.TARGET) + && ruleContext.getAttributeMode(attributeName) == Mode.TARGET) ? ruleContext.getPrerequisiteArtifacts(attributeName, Mode.TARGET).list() : ImmutableList.<Artifact>of(); } - private static Collection<String> getStringListAttribute(RuleContext ruleContext, - String attributeName) { + private static Collection<String> getStringListAttribute( + RuleContext ruleContext, String attributeName) { return ruleContext.attributes().has(attributeName, Type.STRING_LIST) ? ruleContext.attributes().get(attributeName, Type.STRING_LIST) : ImmutableList.<String>of(); } - private static PathFragment getOutputFilePath(ConfiguredTarget base, RuleContext ruleContext, - String suffix) { + private static PathFragment getOutputFilePath( + ConfiguredTarget base, RuleContext ruleContext, String suffix) { PathFragment packagePathFragment = ruleContext.getLabel().getPackageIdentifier().getSourceRoot(); String name = base.getLabel().getName(); return new PathFragment(packagePathFragment, new PathFragment(name + suffix)); } - - private static void addResolveArtifact(NestedSetBuilder<Artifact> ideResolveArtifacts, - Artifact artifact) { + private static void addResolveArtifact( + NestedSetBuilder<Artifact> ideResolveArtifacts, Artifact artifact) { if (!artifact.isSourceArtifact()) { ideResolveArtifacts.add(artifact); } @@ -914,13 +964,13 @@ public class AndroidStudioInfoAspect extends NativeAspectClass implements Config case "java_wrap_cc": return Kind.JAVA_WRAP_CC; default: - { - if (base.getProvider(AndroidSdkProvider.class) != null) { - return RuleIdeInfo.Kind.ANDROID_SDK; - } else { - return RuleIdeInfo.Kind.UNRECOGNIZED; + { + if (base.getProvider(AndroidSdkProvider.class) != null) { + return RuleIdeInfo.Kind.ANDROID_SDK; + } else { + return RuleIdeInfo.Kind.UNRECOGNIZED; + } } - } } } } diff --git a/src/test/java/com/google/devtools/build/android/ideinfo/JarFilterTest.java b/src/test/java/com/google/devtools/build/android/ideinfo/JarFilterTest.java index 64cdc6e005..cdca1a6406 100644 --- a/src/test/java/com/google/devtools/build/android/ideinfo/JarFilterTest.java +++ b/src/test/java/com/google/devtools/build/android/ideinfo/JarFilterTest.java @@ -15,82 +15,224 @@ package com.google.devtools.build.android.ideinfo; import static com.google.common.truth.Truth.assertThat; +import static java.nio.charset.StandardCharsets.UTF_8; import com.google.common.collect.ImmutableList; +import com.google.common.collect.Lists; +import com.google.common.io.Files; +import com.google.devtools.build.android.ideinfo.JarFilter.JarFilterOptions; import com.google.devtools.build.lib.ideinfo.androidstudio.PackageManifestOuterClass.ArtifactLocation; import com.google.devtools.build.lib.ideinfo.androidstudio.PackageManifestOuterClass.JavaSourcePackage; import com.google.devtools.build.lib.ideinfo.androidstudio.PackageManifestOuterClass.PackageManifest; - import java.io.File; -import java.nio.file.Paths; +import java.io.FileOutputStream; +import java.util.Enumeration; import java.util.List; +import java.util.zip.ZipEntry; +import java.util.zip.ZipFile; +import java.util.zip.ZipOutputStream; +import org.junit.Rule; import org.junit.Test; +import org.junit.rules.TemporaryFolder; import org.junit.runner.RunWith; import org.junit.runners.JUnit4; -/** - * Unit tests for {@link JarFilter} - */ +/** Unit tests for {@link JarFilter} */ @RunWith(JUnit4.class) public class JarFilterTest { + @Rule public TemporaryFolder folder = new TemporaryFolder(); + @Test - public void testParseCommandLineArguments() throws Exception { - String[] args = new String[]{ - "--jars", - "/tmp/1.jar" + File.pathSeparator + "/tmp/2.jar", - "--output", - "/tmp/out.jar", - "--manifest", - "/tmp/manifest.file", - }; - JarFilter.JarFilterOptions options = JarFilter.parseArgs(args); - assertThat(options.jars).containsExactly( - Paths.get("/tmp/1.jar"), - Paths.get("/tmp/2.jar") - ); - assertThat(options.output.toString()).isEqualTo(Paths.get("/tmp/out.jar").toString()); - assertThat(options.manifest.toString()).isEqualTo(Paths.get("/tmp/manifest.file").toString()); + public void testFilterMethod() throws Exception { + List<String> prefixes = + ImmutableList.of("com/google/foo/Foo", "com/google/bar/Bar", "com/google/baz/Baz"); + assertThat(JarFilter.shouldKeepClass(prefixes, "com/google/foo/Foo.class")).isTrue(); + assertThat(JarFilter.shouldKeepClass(prefixes, "com/google/foo/Foo$Inner.class")).isTrue(); + assertThat(JarFilter.shouldKeepClass(prefixes, "com/google/bar/Bar.class")).isTrue(); + assertThat(JarFilter.shouldKeepClass(prefixes, "com/google/foo/Foo/NotFoo.class")).isFalse(); + assertThat(JarFilter.shouldKeepClass(prefixes, "wrong/com/google/foo/Foo.class")).isFalse(); } @Test - public void testFilterMethod() throws Exception { - List<String> prefixes = ImmutableList.of( - "com/google/foo/Foo", - "com/google/bar/Bar", - "com/google/baz/Baz" - ); - assertThat(JarFilter.shouldKeep(prefixes, "com/google/foo/Foo.class")).isTrue(); - assertThat(JarFilter.shouldKeep(prefixes, "com/google/foo/Foo$Inner.class")).isTrue(); - assertThat(JarFilter.shouldKeep(prefixes, "com/google/bar/Bar.class")).isTrue(); - assertThat(JarFilter.shouldKeep(prefixes, "com/google/foo/Foo/NotFoo.class")).isFalse(); - assertThat(JarFilter.shouldKeep(prefixes, "wrong/com/google/foo/Foo.class")).isFalse(); + public void legacyIntegrationTest() throws Exception { + PackageManifest packageManifest = + PackageManifest.newBuilder() + .addSources( + JavaSourcePackage.newBuilder() + .setArtifactLocation( + ArtifactLocation.newBuilder() + .setIsSource(true) + .setRelativePath("com/google/foo/Foo.java")) + .setPackageString("com.google.foo")) + .addSources( + JavaSourcePackage.newBuilder() + .setArtifactLocation( + ArtifactLocation.newBuilder() + .setIsSource(true) + .setRelativePath("com/google/bar/Bar.java")) + .setPackageString("com.google.bar")) + .addSources( + JavaSourcePackage.newBuilder() + .setArtifactLocation( + ArtifactLocation.newBuilder() + .setIsSource(true) + .setRelativePath("some/path/Test.java")) + .setPackageString("com.google.test")) + .build(); + assertThat(JarFilter.parsePackageManifest(packageManifest)) + .containsExactly("com/google/foo/Foo", "com/google/bar/Bar", "com/google/test/Test"); + File manifest = folder.newFile("foo.manifest"); + try (FileOutputStream outputStream = new FileOutputStream(manifest)) { + packageManifest.writeTo(outputStream); + } + + File filterJar = folder.newFile("foo.jar"); + try (ZipOutputStream zo = new ZipOutputStream(new FileOutputStream(filterJar))) { + zo.putNextEntry(new ZipEntry("com/google/foo/Foo.class")); + zo.closeEntry(); + zo.putNextEntry(new ZipEntry("com/google/foo/Foo$Inner.class")); + zo.closeEntry(); + zo.putNextEntry(new ZipEntry("com/google/bar/Bar.class")); + zo.closeEntry(); + zo.putNextEntry(new ZipEntry("com/google/test/Test.class")); + zo.closeEntry(); + zo.putNextEntry(new ZipEntry("com/google/foo/Foo2.class")); + zo.closeEntry(); + } + + File outputJar = folder.newFile("foo-filtered-gen.jar"); + + String[] args = + new String[] { + "--jars", + filterJar.getPath(), + "--output", + outputJar.getPath(), + "--manifest", + manifest.getPath() + }; + JarFilter.JarFilterOptions options = JarFilter.parseArgs(args); + JarFilter.main(options); + + List<String> filteredJarNames = Lists.newArrayList(); + try (ZipFile zipFile = new ZipFile(outputJar)) { + Enumeration<? extends ZipEntry> entries = zipFile.entries(); + while (entries.hasMoreElements()) { + ZipEntry zipEntry = entries.nextElement(); + filteredJarNames.add(zipEntry.getName()); + } + } + + assertThat(filteredJarNames) + .containsExactly( + "com/google/foo/Foo.class", + "com/google/foo/Foo$Inner.class", + "com/google/bar/Bar.class", + "com/google/test/Test.class"); } @Test - public void testManifestParser() throws Exception { - PackageManifest packageManifest = PackageManifest.newBuilder() - .addSources(JavaSourcePackage.newBuilder() - .setArtifactLocation(ArtifactLocation.newBuilder() - .setIsSource(true) - .setRelativePath("com/google/foo/Foo.java")) - .setPackageString("com.google.foo")) - .addSources(JavaSourcePackage.newBuilder() - .setArtifactLocation(ArtifactLocation.newBuilder() - .setIsSource(true) - .setRelativePath("com/google/bar/Bar.java")) - .setPackageString("com.google.bar")) - .addSources(JavaSourcePackage.newBuilder() - .setArtifactLocation(ArtifactLocation.newBuilder() - .setIsSource(true) - .setRelativePath("some/path/Test.java")) - .setPackageString("com.google.test")) - .build(); - assertThat(JarFilter.parsePackageManifest(packageManifest)).containsExactly( - "com/google/foo/Foo", - "com/google/bar/Bar", - "com/google/test/Test" - ); + public void fullIntegrationTest() throws Exception { + File fooJava = folder.newFile("Foo.java"); + Files.write("package com.google.foo; class Foo { class Inner {} }".getBytes(UTF_8), fooJava); + + File barJava = folder.newFile("Bar.java"); + Files.write("package com.google.foo.bar; class Bar {}".getBytes(UTF_8), barJava); + + File srcJar = folder.newFile("gen.srcjar"); + try (ZipOutputStream zo = new ZipOutputStream(new FileOutputStream(srcJar))) { + zo.putNextEntry(new ZipEntry("com/google/foo/gen/Gen.java")); + zo.write("package gen; class Gen {}".getBytes(UTF_8)); + zo.closeEntry(); + zo.putNextEntry(new ZipEntry("com/google/foo/gen/Gen2.java")); + zo.write("package gen; class Gen2 {}".getBytes(UTF_8)); + zo.closeEntry(); + } + + File filterJar = folder.newFile("foo.jar"); + try (ZipOutputStream zo = new ZipOutputStream(new FileOutputStream(filterJar))) { + zo.putNextEntry(new ZipEntry("com/google/foo/Foo.class")); + zo.closeEntry(); + zo.putNextEntry(new ZipEntry("com/google/foo/Foo$Inner.class")); + zo.closeEntry(); + zo.putNextEntry(new ZipEntry("com/google/foo/bar/Bar.class")); + zo.closeEntry(); + zo.putNextEntry(new ZipEntry("gen/Gen.class")); + zo.closeEntry(); + zo.putNextEntry(new ZipEntry("gen/Gen2.class")); + zo.closeEntry(); + zo.putNextEntry(new ZipEntry("com/google/foo/Foo2.class")); + zo.closeEntry(); + } + File filterSrcJar = folder.newFile("foo-src.jar"); + try (ZipOutputStream zo = new ZipOutputStream(new FileOutputStream(filterSrcJar))) { + zo.putNextEntry(new ZipEntry("com/google/foo/Foo.java")); + zo.closeEntry(); + zo.putNextEntry(new ZipEntry("com/google/foo/bar/Bar.java")); + zo.closeEntry(); + zo.putNextEntry(new ZipEntry("gen/Gen.java")); + zo.closeEntry(); + zo.putNextEntry(new ZipEntry("gen/Gen2.java")); + zo.closeEntry(); + zo.putNextEntry(new ZipEntry("com/google/foo/Foo2.java")); + zo.closeEntry(); + zo.putNextEntry(new ZipEntry("com/google/foo/bar/Bar2.java")); + zo.closeEntry(); + } + + File filteredJar = folder.newFile("foo-filtered-gen.jar"); + File filteredSourceJar = folder.newFile("foo-filtered-gen-src.jar"); + + String[] args = + new String[] { + "--keep_java_files", + fooJava.getPath() + File.pathSeparator + barJava.getPath(), + "--keep_source_jars", + srcJar.getPath(), + "--filter_jars", + filterJar.getPath(), + "--filter_source_jars", + filterSrcJar.getPath(), + "--filtered_jar", + filteredJar.getPath(), + "--filtered_source_jar", + filteredSourceJar.getPath() + }; + JarFilterOptions options = JarFilter.parseArgs(args); + JarFilter.main(options); + + List<String> filteredJarNames = Lists.newArrayList(); + try (ZipFile zipFile = new ZipFile(filteredJar)) { + Enumeration<? extends ZipEntry> entries = zipFile.entries(); + while (entries.hasMoreElements()) { + ZipEntry zipEntry = entries.nextElement(); + filteredJarNames.add(zipEntry.getName()); + } + } + + List<String> filteredSourceJarNames = Lists.newArrayList(); + try (ZipFile zipFile = new ZipFile(filteredSourceJar)) { + Enumeration<? extends ZipEntry> entries = zipFile.entries(); + while (entries.hasMoreElements()) { + ZipEntry zipEntry = entries.nextElement(); + filteredSourceJarNames.add(zipEntry.getName()); + } + } + + assertThat(filteredJarNames) + .containsExactly( + "com/google/foo/Foo.class", + "com/google/foo/Foo$Inner.class", + "com/google/foo/bar/Bar.class", + "gen/Gen.class", + "gen/Gen2.class"); + + assertThat(filteredSourceJarNames) + .containsExactly( + "com/google/foo/Foo.java", + "com/google/foo/bar/Bar.java", + "gen/Gen.java", + "gen/Gen2.java"); } } - diff --git a/src/test/java/com/google/devtools/build/lib/ideinfo/AndroidStudioInfoAspectTest.java b/src/test/java/com/google/devtools/build/lib/ideinfo/AndroidStudioInfoAspectTest.java index bd5f2414e0..1dbb6d9a6c 100644 --- a/src/test/java/com/google/devtools/build/lib/ideinfo/AndroidStudioInfoAspectTest.java +++ b/src/test/java/com/google/devtools/build/lib/ideinfo/AndroidStudioInfoAspectTest.java @@ -37,9 +37,7 @@ import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.JUnit4; -/** - * Tests for {@link AndroidStudioInfoAspect} validating proto's contents. - */ +/** Tests for {@link AndroidStudioInfoAspect} validating proto's contents. */ @RunWith(JUnit4.class) public class AndroidStudioInfoAspectTest extends AndroidStudioInfoAspectTestBase { @@ -57,8 +55,8 @@ public class AndroidStudioInfoAspectTest extends AndroidStudioInfoAspectTestBase " srcs = ['simple/Simple.java']", ")"); Map<String, RuleIdeInfo> ruleIdeInfos = buildRuleIdeInfo("//com/google/example:simple"); - RuleIdeInfo ruleIdeInfo = getRuleInfoAndVerifyLabel( - "//com/google/example:simple", ruleIdeInfos); + RuleIdeInfo ruleIdeInfo = + getRuleInfoAndVerifyLabel("//com/google/example:simple", ruleIdeInfos); ArtifactLocation location = ruleIdeInfo.getBuildFileArtifactLocation(); assertThat(Paths.get(location.getRelativePath()).toString()) .isEqualTo(Paths.get("com/google/example/BUILD").toString()); @@ -90,9 +88,9 @@ public class AndroidStudioInfoAspectTest extends AndroidStudioInfoAspectTestBase " srcs = ['simple/Simple.java']", ")"); Map<String, RuleIdeInfo> ruleIdeInfos = buildRuleIdeInfo("//com/google/example:simple"); - RuleIdeInfo ruleIdeInfo = getRuleInfoAndVerifyLabel( - "//com/google/example:simple", ruleIdeInfos); - + RuleIdeInfo ruleIdeInfo = + getRuleInfoAndVerifyLabel("//com/google/example:simple", ruleIdeInfos); + ArtifactLocation packageManifest = ruleIdeInfo.getJavaRuleIdeInfo().getPackageManifest(); assertNotNull(packageManifest); assertEquals(packageManifest.getRelativePath(), "com/google/example/simple.manifest"); @@ -112,8 +110,8 @@ public class AndroidStudioInfoAspectTest extends AndroidStudioInfoAspectTestBase " srcs = [':gen_sources']", ")"); Map<String, RuleIdeInfo> ruleIdeInfos = buildRuleIdeInfo("//com/google/example:simple"); - RuleIdeInfo ruleIdeInfo = getRuleInfoAndVerifyLabel( - "//com/google/example:simple", ruleIdeInfos); + RuleIdeInfo ruleIdeInfo = + getRuleInfoAndVerifyLabel("//com/google/example:simple", ruleIdeInfos); assertThat(ruleIdeInfo.getJavaRuleIdeInfo().hasPackageManifest()).isFalse(); } @@ -126,8 +124,8 @@ public class AndroidStudioInfoAspectTest extends AndroidStudioInfoAspectTestBase " srcs = ['Test.java']", ")"); Map<String, RuleIdeInfo> ruleIdeInfos = buildRuleIdeInfo("//com/google/example:simple"); - RuleIdeInfo ruleIdeInfo = getRuleInfoAndVerifyLabel( - "//com/google/example:simple", ruleIdeInfos); + RuleIdeInfo ruleIdeInfo = + getRuleInfoAndVerifyLabel("//com/google/example:simple", ruleIdeInfos); assertThat(ruleIdeInfo.getJavaRuleIdeInfo().hasFilteredGenJar()).isFalse(); } @@ -145,13 +143,13 @@ public class AndroidStudioInfoAspectTest extends AndroidStudioInfoAspectTestBase " srcs = [':gen_sources']", ")"); Map<String, RuleIdeInfo> ruleIdeInfos = buildRuleIdeInfo("//com/google/example:simple"); - RuleIdeInfo ruleIdeInfo = getRuleInfoAndVerifyLabel( - "//com/google/example:simple", ruleIdeInfos); + RuleIdeInfo ruleIdeInfo = + getRuleInfoAndVerifyLabel("//com/google/example:simple", ruleIdeInfos); assertThat(ruleIdeInfo.getJavaRuleIdeInfo().hasFilteredGenJar()).isFalse(); } @Test - public void testFilteredGenJarIsCreatedForMixedGenAndSourcesRule() throws Exception { + public void testFilteredGenJar() throws Exception { scratch.file( "com/google/example/BUILD", "genrule(", @@ -159,15 +157,23 @@ public class AndroidStudioInfoAspectTest extends AndroidStudioInfoAspectTestBase " outs = ['Gen.java'],", " cmd = '',", ")", + "genrule(", + " name = 'gen_srcjar',", + " outs = ['gen.srcjar'],", + " cmd = '',", + ")", "java_library(", - " name = 'simple',", - " srcs = [':gen_sources', 'Test.java']", + " name = 'lib',", + " srcs = [':gen_sources', ':gen_srcjar', 'Test.java']", ")"); - Map<String, RuleIdeInfo> ruleIdeInfos = buildRuleIdeInfo("//com/google/example:simple"); - RuleIdeInfo ruleIdeInfo = getRuleInfoAndVerifyLabel( - "//com/google/example:simple", ruleIdeInfos); + Map<String, RuleIdeInfo> ruleIdeInfos = buildRuleIdeInfo("//com/google/example:lib"); + RuleIdeInfo ruleIdeInfo = getRuleInfoAndVerifyLabel("//com/google/example:lib", ruleIdeInfos); + assertThat(ruleIdeInfo.getJavaRuleIdeInfo().hasFilteredGenJar()).isTrue(); assertThat(ruleIdeInfo.getJavaRuleIdeInfo().getFilteredGenJar().getJar().getRelativePath()) - .isEqualTo("com/google/example/simple-filtered-gen.jar"); + .isEqualTo("com/google/example/lib-filtered-gen.jar"); + assertThat( + ruleIdeInfo.getJavaRuleIdeInfo().getFilteredGenJar().getSourceJar().getRelativePath()) + .isEqualTo("com/google/example/lib-filtered-gen-src.jar"); } @Test @@ -187,15 +193,14 @@ public class AndroidStudioInfoAspectTest extends AndroidStudioInfoAspectTestBase Map<String, RuleIdeInfo> ruleIdeInfos = buildRuleIdeInfo("//com/google/example:complex"); getRuleInfoAndVerifyLabel("//com/google/example:simple", ruleIdeInfos); - RuleIdeInfo complexRuleIdeInfo = getRuleInfoAndVerifyLabel( - "//com/google/example:complex", ruleIdeInfos); + RuleIdeInfo complexRuleIdeInfo = + getRuleInfoAndVerifyLabel("//com/google/example:complex", ruleIdeInfos); assertThat(relativePathsForJavaSourcesOf(complexRuleIdeInfo)) .containsExactly("com/google/example/complex/Complex.java"); - assertThat(complexRuleIdeInfo.getDependenciesList()) - .contains("//com/google/example:simple"); + assertThat(complexRuleIdeInfo.getDependenciesList()).contains("//com/google/example:simple"); } - + @Test public void testJavaLibraryWithTransitiveDependencies() throws Exception { scratch.file( @@ -219,8 +224,8 @@ public class AndroidStudioInfoAspectTest extends AndroidStudioInfoAspectTestBase getRuleInfoAndVerifyLabel("//com/google/example:simple", ruleIdeInfos); getRuleInfoAndVerifyLabel("//com/google/example:complex", ruleIdeInfos); - RuleIdeInfo extraComplexRuleIdeInfo = getRuleInfoAndVerifyLabel( - "//com/google/example:extracomplex", ruleIdeInfos); + RuleIdeInfo extraComplexRuleIdeInfo = + getRuleInfoAndVerifyLabel("//com/google/example:extracomplex", ruleIdeInfos); assertThat(relativePathsForJavaSourcesOf(extraComplexRuleIdeInfo)) .containsExactly("com/google/example/extracomplex/ExtraComplex.java"); @@ -269,14 +274,13 @@ public class AndroidStudioInfoAspectTest extends AndroidStudioInfoAspectTestBase getRuleInfoAndVerifyLabel("//com/google/example:complex", ruleIdeInfos); getRuleInfoAndVerifyLabel("//com/google/example:complex1", ruleIdeInfos); - RuleIdeInfo extraComplexRuleIdeInfo = getRuleInfoAndVerifyLabel( - "//com/google/example:extracomplex", ruleIdeInfos); + RuleIdeInfo extraComplexRuleIdeInfo = + getRuleInfoAndVerifyLabel("//com/google/example:extracomplex", ruleIdeInfos); assertThat(relativePathsForJavaSourcesOf(extraComplexRuleIdeInfo)) .containsExactly("com/google/example/extracomplex/ExtraComplex.java"); - assertThat(extraComplexRuleIdeInfo.getDependenciesList()).containsAllOf( - "//com/google/example:complex", - "//com/google/example:complex1"); + assertThat(extraComplexRuleIdeInfo.getDependenciesList()) + .containsAllOf("//com/google/example:complex", "//com/google/example:complex1"); } @Test @@ -302,17 +306,15 @@ public class AndroidStudioInfoAspectTest extends AndroidStudioInfoAspectTestBase getRuleInfoAndVerifyLabel("//com/google/example:simple", ruleIdeInfos); getRuleInfoAndVerifyLabel("//com/google/example:complex", ruleIdeInfos); - RuleIdeInfo complexRuleIdeInfo = getRuleInfoAndVerifyLabel("//com/google/example:complex", - ruleIdeInfos); - RuleIdeInfo extraComplexRuleIdeInfo = getRuleInfoAndVerifyLabel( - "//com/google/example:extracomplex", ruleIdeInfos); + RuleIdeInfo complexRuleIdeInfo = + getRuleInfoAndVerifyLabel("//com/google/example:complex", ruleIdeInfos); + RuleIdeInfo extraComplexRuleIdeInfo = + getRuleInfoAndVerifyLabel("//com/google/example:extracomplex", ruleIdeInfos); - assertThat(complexRuleIdeInfo.getDependenciesList()) - .contains("//com/google/example:simple"); + assertThat(complexRuleIdeInfo.getDependenciesList()).contains("//com/google/example:simple"); - assertThat(extraComplexRuleIdeInfo.getDependenciesList()).containsAllOf( - "//com/google/example:simple", - "//com/google/example:complex"); + assertThat(extraComplexRuleIdeInfo.getDependenciesList()) + .containsAllOf("//com/google/example:simple", "//com/google/example:complex"); assertThat(getIdeResolveFiles()) .containsExactly( "com/google/example/libextracomplex.jar", @@ -348,23 +350,23 @@ public class AndroidStudioInfoAspectTest extends AndroidStudioInfoAspectTestBase " name = 'megacomplex',", " srcs = ['megacomplex/MegaComplex.java'],", " deps = [':extracomplex'],", - ")" - ); + ")"); Map<String, RuleIdeInfo> ruleIdeInfos = buildRuleIdeInfo("//com/google/example:megacomplex"); getRuleInfoAndVerifyLabel("//com/google/example:simple", ruleIdeInfos); getRuleInfoAndVerifyLabel("//com/google/example:complex", ruleIdeInfos); getRuleInfoAndVerifyLabel("//com/google/example:extracomplex", ruleIdeInfos); - RuleIdeInfo megaComplexRuleIdeInfo = getRuleInfoAndVerifyLabel( - "//com/google/example:megacomplex", ruleIdeInfos); + RuleIdeInfo megaComplexRuleIdeInfo = + getRuleInfoAndVerifyLabel("//com/google/example:megacomplex", ruleIdeInfos); assertThat(relativePathsForJavaSourcesOf(megaComplexRuleIdeInfo)) .containsExactly("com/google/example/megacomplex/MegaComplex.java"); - assertThat(megaComplexRuleIdeInfo.getDependenciesList()).containsAllOf( - "//com/google/example:simple", - "//com/google/example:complex", - "//com/google/example:extracomplex"); + assertThat(megaComplexRuleIdeInfo.getDependenciesList()) + .containsAllOf( + "//com/google/example:simple", + "//com/google/example:complex", + "//com/google/example:extracomplex"); } @Test @@ -396,18 +398,25 @@ public class AndroidStudioInfoAspectTest extends AndroidStudioInfoAspectTestBase assertThat(javaRuleIdeInfo).isNotNull(); assertThat(transform(javaRuleIdeInfo.getJarsList(), LIBRARY_ARTIFACT_TO_STRING)) .containsExactly( - jarString("com/google/example", - "a.jar", "_ijar/imp/com/google/example/a-ijar.jar", "impsrc.jar"), - jarString("com/google/example", - "b.jar", "_ijar/imp/com/google/example/b-ijar.jar", "impsrc.jar")) + jarString( + "com/google/example", + "a.jar", + "_ijar/imp/com/google/example/a-ijar.jar", + "impsrc.jar"), + jarString( + "com/google/example", + "b.jar", + "_ijar/imp/com/google/example/b-ijar.jar", + "impsrc.jar")) .inOrder(); - assertThat(getIdeResolveFiles()).containsExactly( - "com/google/example/_ijar/imp/com/google/example/a-ijar.jar", - "com/google/example/_ijar/imp/com/google/example/b-ijar.jar", - "com/google/example/liblib.jar", - "com/google/example/liblib-hjar.jar", - "com/google/example/liblib-src.jar"); + assertThat(getIdeResolveFiles()) + .containsExactly( + "com/google/example/_ijar/imp/com/google/example/a-ijar.jar", + "com/google/example/_ijar/imp/com/google/example/b-ijar.jar", + "com/google/example/liblib.jar", + "com/google/example/liblib-hjar.jar", + "com/google/example/liblib-src.jar"); } @Test @@ -439,9 +448,8 @@ public class AndroidStudioInfoAspectTest extends AndroidStudioInfoAspectTestBase } assertThat(impInfo.getKindString()).isEqualTo("java_import"); assertThat(impInfo.getDependenciesList()).contains("//com/google/example:foobar"); - assertThat(libInfo.getDependenciesList()).containsAllOf( - "//com/google/example:foobar", - "//com/google/example:imp"); + assertThat(libInfo.getDependenciesList()) + .containsAllOf("//com/google/example:foobar", "//com/google/example:imp"); } @Test @@ -463,11 +471,11 @@ public class AndroidStudioInfoAspectTest extends AndroidStudioInfoAspectTestBase " srcs = ['Lib.java'],", " deps = [':imp'],", ")"); - + Map<String, RuleIdeInfo> ruleIdeInfos = buildRuleIdeInfo("//com/google/example:lib"); RuleIdeInfo libInfo = getRuleInfoAndVerifyLabel("//com/google/example:lib", ruleIdeInfos); RuleIdeInfo impInfo = getRuleInfoAndVerifyLabel("//com/google/example:imp", ruleIdeInfos); - + assertThat(!impInfo.getJavaRuleIdeInfo().hasPackageManifest()).isTrue(); assertThat(libInfo.getJavaRuleIdeInfo().hasPackageManifest()).isTrue(); } @@ -492,10 +500,11 @@ public class AndroidStudioInfoAspectTest extends AndroidStudioInfoAspectTestBase " cmd = '',", ")"); buildTarget("//com/google/example:imp"); - assertThat(getIdeResolveFiles()).containsExactly( - "com/google/example/_ijar/imp/com/google/example/gen_jar-ijar.jar", - "com/google/example/gen_jar.jar", - "com/google/example/gen_srcjar.jar"); + assertThat(getIdeResolveFiles()) + .containsExactly( + "com/google/example/_ijar/imp/com/google/example/gen_jar-ijar.jar", + "com/google/example/gen_jar.jar", + "com/google/example/gen_srcjar.jar"); } @Test @@ -530,10 +539,10 @@ public class AndroidStudioInfoAspectTest extends AndroidStudioInfoAspectTestBase " size = 'large',", " deps = [':foobar'],", ")"); - Map<String, RuleIdeInfo> ruleIdeInfos = buildRuleIdeInfo( - "//java/com/google/example:FooBarTest"); - RuleIdeInfo testInfo = getRuleInfoAndVerifyLabel( - "//java/com/google/example:FooBarTest", ruleIdeInfos); + Map<String, RuleIdeInfo> ruleIdeInfos = + buildRuleIdeInfo("//java/com/google/example:FooBarTest"); + RuleIdeInfo testInfo = + getRuleInfoAndVerifyLabel("//java/com/google/example:FooBarTest", ruleIdeInfos); if (testLegacyAswbPluginVersionCompatibility()) { assertThat(testInfo.getKind()).isEqualTo(Kind.JAVA_TEST); } @@ -542,8 +551,8 @@ public class AndroidStudioInfoAspectTest extends AndroidStudioInfoAspectTestBase .containsExactly("java/com/google/example/FooBarTest.java"); assertThat(testInfo.getDependenciesList()).contains("//java/com/google/example:foobar"); assertThat(transform(testInfo.getJavaRuleIdeInfo().getJarsList(), LIBRARY_ARTIFACT_TO_STRING)) - .containsExactly(jarString("java/com/google/example", - "FooBarTest.jar", null, "FooBarTest-src.jar")); + .containsExactly( + jarString("java/com/google/example", "FooBarTest.jar", null, "FooBarTest-src.jar")); assertThat(getIdeResolveFiles()) .containsExactly( @@ -573,8 +582,8 @@ public class AndroidStudioInfoAspectTest extends AndroidStudioInfoAspectTestBase " deps = [':foobar'],", ")"); Map<String, RuleIdeInfo> ruleIdeInfos = buildRuleIdeInfo("//com/google/example:foobar-exe"); - RuleIdeInfo binaryInfo = getRuleInfoAndVerifyLabel( - "//com/google/example:foobar-exe", ruleIdeInfos); + RuleIdeInfo binaryInfo = + getRuleInfoAndVerifyLabel("//com/google/example:foobar-exe", ruleIdeInfos); if (testLegacyAswbPluginVersionCompatibility()) { assertThat(binaryInfo.getKind()).isEqualTo(Kind.JAVA_BINARY); @@ -585,8 +594,8 @@ public class AndroidStudioInfoAspectTest extends AndroidStudioInfoAspectTestBase assertThat(binaryInfo.getDependenciesList()).contains("//com/google/example:foobar"); assertThat(transform(binaryInfo.getJavaRuleIdeInfo().getJarsList(), LIBRARY_ARTIFACT_TO_STRING)) - .containsExactly(jarString("com/google/example", - "foobar-exe.jar", null, "foobar-exe-src.jar")); + .containsExactly( + jarString("com/google/example", "foobar-exe.jar", null, "foobar-exe-src.jar")); assertThat(getIdeResolveFiles()) .containsExactly( @@ -622,9 +631,8 @@ public class AndroidStudioInfoAspectTest extends AndroidStudioInfoAspectTestBase assertThat(toolChainInfo.getJavaToolchainIdeInfo().getTargetVersion()).isNotEmpty(); RuleIdeInfo a = ruleIdeInfos.get("//com/google/example:a"); - assertThat(a.getDependenciesList()).containsAllOf( - "//com/google/example:b", - toolChainInfo.getLabel()); + assertThat(a.getDependenciesList()) + .containsAllOf("//com/google/example:b", toolChainInfo.getLabel()); } @Test @@ -667,7 +675,8 @@ public class AndroidStudioInfoAspectTest extends AndroidStudioInfoAspectTestBase assertThat(ruleInfo.getKind()).isEqualTo(Kind.ANDROID_LIBRARY); } assertThat(ruleInfo.getKindString()).isEqualTo("android_library"); - assertThat(relativePathsForJavaSourcesOf(ruleInfo)).containsExactly("com/google/example/Main.java"); + assertThat(relativePathsForJavaSourcesOf(ruleInfo)) + .containsExactly("com/google/example/Main.java"); assertThat(transform(ruleInfo.getJavaRuleIdeInfo().getJarsList(), LIBRARY_ARTIFACT_TO_STRING)) .containsExactly( jarString("com/google/example", "libl.jar", "libl-hjar.jar", "libl-src.jar"), @@ -680,9 +689,7 @@ public class AndroidStudioInfoAspectTest extends AndroidStudioInfoAspectTestBase .isEqualTo("com/google/example/AndroidManifest.xml"); assertThat(ruleInfo.getAndroidRuleIdeInfo().getJavaPackage()).isEqualTo("com.google.example"); assertThat(LIBRARY_ARTIFACT_TO_STRING.apply(ruleInfo.getAndroidRuleIdeInfo().getResourceJar())) - .isEqualTo(jarString("com/google/example", - "l_resources.jar", null, "l_resources-src.jar" - )); + .isEqualTo(jarString("com/google/example", "l_resources.jar", null, "l_resources-src.jar")); assertThat(ruleInfo.getDependenciesList()).contains("//com/google/example:l1"); assertThat(getIdeResolveFiles()) @@ -725,7 +732,8 @@ public class AndroidStudioInfoAspectTest extends AndroidStudioInfoAspectTestBase assertThat(ruleInfo.getKind()).isEqualTo(Kind.ANDROID_BINARY); } assertThat(ruleInfo.getKindString()).isEqualTo("android_binary"); - assertThat(relativePathsForJavaSourcesOf(ruleInfo)).containsExactly("com/google/example/Main.java"); + assertThat(relativePathsForJavaSourcesOf(ruleInfo)) + .containsExactly("com/google/example/Main.java"); assertThat(transform(ruleInfo.getJavaRuleIdeInfo().getJarsList(), LIBRARY_ARTIFACT_TO_STRING)) .containsExactly( jarString("com/google/example", "libb.jar", "libb-hjar.jar", "libb-src.jar"), @@ -741,7 +749,6 @@ public class AndroidStudioInfoAspectTest extends AndroidStudioInfoAspectTestBase assertThat(ruleInfo.getAndroidRuleIdeInfo().getApk().getRelativePath()) .isEqualTo("com/google/example/b.apk"); - assertThat(ruleInfo.getDependenciesList()).contains("//com/google/example:l1"); assertThat(getIdeResolveFiles()) @@ -788,8 +795,7 @@ public class AndroidStudioInfoAspectTest extends AndroidStudioInfoAspectTestBase "android_library(", " name = 'no_idl',", " srcs = ['Test.java'],", - ")" - ); + ")"); String noIdlTarget = "//java/com/google/example:no_idl"; Map<String, RuleIdeInfo> ruleIdeInfos = buildRuleIdeInfo(noIdlTarget); RuleIdeInfo noIdlRuleInfo = getRuleInfoAndVerifyLabel(noIdlTarget, ruleIdeInfos); @@ -804,18 +810,17 @@ public class AndroidStudioInfoAspectTest extends AndroidStudioInfoAspectTestBase "android_library(", " name = 'has_idl',", " idl_srcs = ['a.aidl'],", - ")" - ); + ")"); String idlTarget = "//java/com/google/example:has_idl"; Map<String, RuleIdeInfo> ruleIdeInfos = buildRuleIdeInfo(idlTarget); RuleIdeInfo idlRuleInfo = getRuleInfoAndVerifyLabel(idlTarget, ruleIdeInfos); assertThat(idlRuleInfo.getAndroidRuleIdeInfo().getHasIdlSources()).isTrue(); assertThat(LIBRARY_ARTIFACT_TO_STRING.apply(idlRuleInfo.getAndroidRuleIdeInfo().getIdlJar())) - .isEqualTo(jarString("java/com/google/example", - "libhas_idl-idl.jar", null, "libhas_idl-idl.srcjar")); - assertThat(relativePathsForJavaSourcesOf(idlRuleInfo)) - .isEmpty(); + .isEqualTo( + jarString( + "java/com/google/example", "libhas_idl-idl.jar", null, "libhas_idl-idl.srcjar")); + assertThat(relativePathsForJavaSourcesOf(idlRuleInfo)).isEmpty(); assertThat(getIdeResolveFiles()) .containsExactly( "java/com/google/example/libhas_idl.jar", @@ -869,12 +874,13 @@ public class AndroidStudioInfoAspectTest extends AndroidStudioInfoAspectTestBase " cmd = '',", ")"); buildTarget("//com/google/example:lib"); - assertThat(getIdeResolveFiles()).containsExactly( - "com/google/example/liblib.jar", - "com/google/example/liblib-src.jar", - "com/google/example/lib_resources.jar", - "com/google/example/lib_resources-src.jar", - "com/google/example/AndroidManifest.xml"); + assertThat(getIdeResolveFiles()) + .containsExactly( + "com/google/example/liblib.jar", + "com/google/example/liblib-src.jar", + "com/google/example/lib_resources.jar", + "com/google/example/lib_resources-src.jar", + "com/google/example/AndroidManifest.xml"); } @Test @@ -884,14 +890,12 @@ public class AndroidStudioInfoAspectTest extends AndroidStudioInfoAspectTestBase "java_library(", " name = 'no_plugin',", " srcs = ['Test.java'],", - ")" - ); + ")"); Map<String, RuleIdeInfo> ruleIdeInfos = buildRuleIdeInfo("//java/com/google/example:no_plugin"); - RuleIdeInfo ruleIdeInfo = getRuleInfoAndVerifyLabel( - "//java/com/google/example:no_plugin", ruleIdeInfos); + RuleIdeInfo ruleIdeInfo = + getRuleInfoAndVerifyLabel("//java/com/google/example:no_plugin", ruleIdeInfos); - assertThat(ruleIdeInfo.getJavaRuleIdeInfo().getGeneratedJarsList()) - .isEmpty(); + assertThat(ruleIdeInfo.getJavaRuleIdeInfo().getGeneratedJarsList()).isEmpty(); } @Test @@ -911,17 +915,17 @@ public class AndroidStudioInfoAspectTest extends AndroidStudioInfoAspectTestBase "java_library(", " name = 'plugin_lib',", " srcs = ['Plugin.java'],", - ")" - ); + ")"); Map<String, RuleIdeInfo> ruleIdeInfos = buildRuleIdeInfo("//java/com/google/example:test"); - RuleIdeInfo ruleIdeInfo = getRuleInfoAndVerifyLabel( - "//java/com/google/example:test", ruleIdeInfos); - - assertThat(transform( - ruleIdeInfo.getJavaRuleIdeInfo().getGeneratedJarsList(), - LIBRARY_ARTIFACT_TO_STRING)) - .containsExactly(jarString("java/com/google/example", - "libtest-gen.jar", null, "libtest-gensrc.jar")); + RuleIdeInfo ruleIdeInfo = + getRuleInfoAndVerifyLabel("//java/com/google/example:test", ruleIdeInfos); + + assertThat( + transform( + ruleIdeInfo.getJavaRuleIdeInfo().getGeneratedJarsList(), + LIBRARY_ARTIFACT_TO_STRING)) + .containsExactly( + jarString("java/com/google/example", "libtest-gen.jar", null, "libtest-gensrc.jar")); assertThat(getIdeResolveFiles()) .containsExactly( "java/com/google/example/libtest.jar", @@ -942,8 +946,7 @@ public class AndroidStudioInfoAspectTest extends AndroidStudioInfoAspectTestBase ")"); Map<String, RuleIdeInfo> ruleIdeInfos = buildRuleIdeInfo("//com/google/example:lib"); RuleIdeInfo ruleIdeInfo = getRuleInfoAndVerifyLabel("//com/google/example:lib", ruleIdeInfos); - assertThat(ruleIdeInfo.getTagsList()) - .containsExactly("a", "b", "c", "d"); + assertThat(ruleIdeInfo.getTagsList()).containsExactly("a", "b", "c", "d"); } @Test @@ -963,12 +966,11 @@ public class AndroidStudioInfoAspectTest extends AndroidStudioInfoAspectTestBase " deps = [':forward'],", ")"); Map<String, RuleIdeInfo> ruleIdeInfos = buildRuleIdeInfo("//java/com/google/example:super"); - RuleIdeInfo ruleInfo = getRuleInfoAndVerifyLabel( - "//java/com/google/example:super", ruleIdeInfos); + RuleIdeInfo ruleInfo = + getRuleInfoAndVerifyLabel("//java/com/google/example:super", ruleIdeInfos); - assertThat(ruleInfo.getDependenciesList()).containsAllOf( - "//java/com/google/example:forward", - "//java/com/google/example:lib"); + assertThat(ruleInfo.getDependenciesList()) + .containsAllOf("//java/com/google/example:forward", "//java/com/google/example:lib"); } @Test @@ -991,10 +993,8 @@ public class AndroidStudioInfoAspectTest extends AndroidStudioInfoAspectTestBase Map<String, RuleIdeInfo> ruleIdeInfos = buildRuleIdeInfo("//com/google/example:lib"); RuleIdeInfo ruleInfo = getRuleInfoAndVerifyLabel("//com/google/example:lib", ruleIdeInfos); RuleIdeInfo javaToolchain = Iterables.getOnlyElement(findJavaToolchain(ruleIdeInfos)); - assertThat(ruleInfo.getDependenciesList()).containsExactly( - javaToolchain.getLabel(), - "//com/google/example:middle" - ); + assertThat(ruleInfo.getDependenciesList()) + .containsExactly(javaToolchain.getLabel(), "//com/google/example:middle"); } @Test @@ -1013,17 +1013,18 @@ public class AndroidStudioInfoAspectTest extends AndroidStudioInfoAspectTestBase Map<String, RuleIdeInfo> ruleIdeInfos = buildRuleIdeInfo("//com/google/example:lib"); RuleIdeInfo ruleIdeInfo = getRuleInfoAndVerifyLabel("//com/google/example:lib", ruleIdeInfos); // todo(dslomov): Skylark aspect implementation does not yet return a correct root path. - assertThat(ruleIdeInfo.getJavaRuleIdeInfo().getSourcesList()).containsExactly( - ArtifactLocation.newBuilder() - .setRootExecutionPathFragment( - targetConfig.getGenfilesDirectory(RepositoryName.MAIN).getExecPathString()) - .setRelativePath("com/google/example/gen.java") - .setIsSource(false) - .build(), - ArtifactLocation.newBuilder() - .setRelativePath("com/google/example/Test.java") - .setIsSource(true) - .build()); + assertThat(ruleIdeInfo.getJavaRuleIdeInfo().getSourcesList()) + .containsExactly( + ArtifactLocation.newBuilder() + .setRootExecutionPathFragment( + targetConfig.getGenfilesDirectory(RepositoryName.MAIN).getExecPathString()) + .setRelativePath("com/google/example/gen.java") + .setIsSource(false) + .build(), + ArtifactLocation.newBuilder() + .setRelativePath("com/google/example/Test.java") + .setIsSource(true) + .build()); } @Test @@ -1100,12 +1101,12 @@ public class AndroidStudioInfoAspectTest extends AndroidStudioInfoAspectTestBase ")"); Map<String, RuleIdeInfo> ruleIdeInfos = buildRuleIdeInfo("//java/com/google/example:neither"); - RuleIdeInfo neither = getRuleInfoAndVerifyLabel( - "//java/com/google/example:neither", ruleIdeInfos); - RuleIdeInfo resourceFiles = getRuleInfoAndVerifyLabel( - "//java/com/google/example:resource_files", ruleIdeInfos); - RuleIdeInfo manifest = getRuleInfoAndVerifyLabel( - "//java/com/google/example:manifest", ruleIdeInfos); + RuleIdeInfo neither = + getRuleInfoAndVerifyLabel("//java/com/google/example:neither", ruleIdeInfos); + RuleIdeInfo resourceFiles = + getRuleInfoAndVerifyLabel("//java/com/google/example:resource_files", ruleIdeInfos); + RuleIdeInfo manifest = + getRuleInfoAndVerifyLabel("//java/com/google/example:manifest", ruleIdeInfos); assertThat(neither.getAndroidRuleIdeInfo().getGenerateResourceClass()).isFalse(); assertThat(resourceFiles.getAndroidRuleIdeInfo().getGenerateResourceClass()).isTrue(); @@ -1120,11 +1121,10 @@ public class AndroidStudioInfoAspectTest extends AndroidStudioInfoAspectTestBase " name = 'plugin',", " srcs = ['Plugin.java'],", " processor_class = 'com.google.example.Plugin',", - ")" - ); + ")"); Map<String, RuleIdeInfo> ruleIdeInfos = buildRuleIdeInfo("//java/com/google/example:plugin"); - RuleIdeInfo plugin = getRuleInfoAndVerifyLabel( - "//java/com/google/example:plugin", ruleIdeInfos); + RuleIdeInfo plugin = + getRuleInfoAndVerifyLabel("//java/com/google/example:plugin", ruleIdeInfos); if (testLegacyAswbPluginVersionCompatibility()) { assertThat(plugin.getKind()).isEqualTo(Kind.JAVA_PLUGIN); @@ -1151,12 +1151,9 @@ public class AndroidStudioInfoAspectTest extends AndroidStudioInfoAspectTestBase ")"); Map<String, RuleIdeInfo> ruleIdeInfos = buildRuleIdeInfo("//com/google/example:simple"); assertThat(ruleIdeInfos).hasSize(2); - RuleIdeInfo ruleInfo = getRuleInfoAndVerifyLabel( - "//com/google/example:simple", - ruleIdeInfos - ); - Entry<String, RuleIdeInfo> toolchainEntry = getCcToolchainRuleAndVerifyThereIsOnlyOne( - ruleIdeInfos); + RuleIdeInfo ruleInfo = getRuleInfoAndVerifyLabel("//com/google/example:simple", ruleIdeInfos); + Entry<String, RuleIdeInfo> toolchainEntry = + getCcToolchainRuleAndVerifyThereIsOnlyOne(ruleIdeInfos); RuleIdeInfo toolchainInfo = toolchainEntry.getValue(); ArtifactLocation location = ruleInfo.getBuildFileArtifactLocation(); assertThat(Paths.get(location.getRelativePath()).toString()) @@ -1178,8 +1175,8 @@ public class AndroidStudioInfoAspectTest extends AndroidStudioInfoAspectTestBase ")"); Map<String, RuleIdeInfo> ruleIdeInfos = buildRuleIdeInfo("//com/google/example:simple"); assertThat(ruleIdeInfos).hasSize(2); - RuleIdeInfo ruleIdeInfo = getRuleInfoAndVerifyLabel( - "//com/google/example:simple", ruleIdeInfos); + RuleIdeInfo ruleIdeInfo = + getRuleInfoAndVerifyLabel("//com/google/example:simple", ruleIdeInfos); ArtifactLocation location = ruleIdeInfo.getBuildFileArtifactLocation(); assertThat(Paths.get(location.getRelativePath()).toString()) .isEqualTo(Paths.get("com/google/example/BUILD").toString()); @@ -1220,8 +1217,8 @@ public class AndroidStudioInfoAspectTest extends AndroidStudioInfoAspectTestBase ")"); Map<String, RuleIdeInfo> ruleIdeInfos = buildRuleIdeInfo("//com/google/example:simple"); assertThat(ruleIdeInfos).hasSize(2); - RuleIdeInfo ruleIdeInfo = getRuleInfoAndVerifyLabel( - "//com/google/example:simple", ruleIdeInfos); + RuleIdeInfo ruleIdeInfo = + getRuleInfoAndVerifyLabel("//com/google/example:simple", ruleIdeInfos); assertThat(ruleIdeInfo.hasCRuleIdeInfo()).isTrue(); CRuleIdeInfo cRuleIdeInfo = ruleIdeInfo.getCRuleIdeInfo(); @@ -1229,8 +1226,8 @@ public class AndroidStudioInfoAspectTest extends AndroidStudioInfoAspectTestBase assertThat(cRuleIdeInfo.getRuleIncludeList()).containsExactly("foo/bar"); // Make sure our understanding of where this attributes show up in other providers is correct. - Entry<String, RuleIdeInfo> toolchainEntry = getCcToolchainRuleAndVerifyThereIsOnlyOne( - ruleIdeInfos); + Entry<String, RuleIdeInfo> toolchainEntry = + getCcToolchainRuleAndVerifyThereIsOnlyOne(ruleIdeInfos); RuleIdeInfo toolchainInfo = toolchainEntry.getValue(); assertThat(toolchainInfo.hasCToolchainIdeInfo()).isTrue(); CToolchainIdeInfo cToolchainIdeInfo = toolchainInfo.getCToolchainIdeInfo(); @@ -1266,8 +1263,8 @@ public class AndroidStudioInfoAspectTest extends AndroidStudioInfoAspectTestBase ")"); Map<String, RuleIdeInfo> ruleIdeInfos = buildRuleIdeInfo("//com/google/example:simple"); assertThat(ruleIdeInfos).hasSize(2); - RuleIdeInfo ruleIdeInfo = getRuleInfoAndVerifyLabel( - "//com/google/example:simple", ruleIdeInfos); + RuleIdeInfo ruleIdeInfo = + getRuleInfoAndVerifyLabel("//com/google/example:simple", ruleIdeInfos); assertThat(ruleIdeInfo.hasCRuleIdeInfo()).isTrue(); CRuleIdeInfo cRuleIdeInfo = ruleIdeInfo.getCRuleIdeInfo(); @@ -1275,8 +1272,8 @@ public class AndroidStudioInfoAspectTest extends AndroidStudioInfoAspectTestBase assertThat(cRuleIdeInfo.getRuleCoptList()).containsExactly("-DGOPT", "-Ifoo/baz/"); // Make sure our understanding of where this attributes show up in other providers is correct. - Entry<String, RuleIdeInfo> toolchainEntry = getCcToolchainRuleAndVerifyThereIsOnlyOne( - ruleIdeInfos); + Entry<String, RuleIdeInfo> toolchainEntry = + getCcToolchainRuleAndVerifyThereIsOnlyOne(ruleIdeInfos); RuleIdeInfo toolchainInfo = toolchainEntry.getValue(); assertThat(toolchainInfo.hasCToolchainIdeInfo()).isTrue(); CToolchainIdeInfo cToolchainIdeInfo = toolchainInfo.getCToolchainIdeInfo(); @@ -1305,8 +1302,8 @@ public class AndroidStudioInfoAspectTest extends AndroidStudioInfoAspectTestBase ")"); Map<String, RuleIdeInfo> ruleIdeInfos = buildRuleIdeInfo("//com/google/example:simple"); assertThat(ruleIdeInfos).hasSize(2); - RuleIdeInfo ruleIdeInfo = getRuleInfoAndVerifyLabel( - "//com/google/example:simple", ruleIdeInfos); + RuleIdeInfo ruleIdeInfo = + getRuleInfoAndVerifyLabel("//com/google/example:simple", ruleIdeInfos); assertThat(ruleIdeInfo.hasCRuleIdeInfo()).isTrue(); CRuleIdeInfo cRuleIdeInfo = ruleIdeInfo.getCRuleIdeInfo(); @@ -1328,8 +1325,8 @@ public class AndroidStudioInfoAspectTest extends AndroidStudioInfoAspectTestBase ")"); Map<String, RuleIdeInfo> ruleIdeInfos = buildRuleIdeInfo("//com/google/example:simple"); assertThat(ruleIdeInfos).hasSize(2); - RuleIdeInfo ruleIdeInfo = getRuleInfoAndVerifyLabel( - "//com/google/example:simple", ruleIdeInfos); + RuleIdeInfo ruleIdeInfo = + getRuleInfoAndVerifyLabel("//com/google/example:simple", ruleIdeInfos); ArtifactLocation location = ruleIdeInfo.getBuildFileArtifactLocation(); assertThat(Paths.get(location.getRelativePath()).toString()) .isEqualTo(Paths.get("com/google/example/BUILD").toString()); @@ -1363,8 +1360,8 @@ public class AndroidStudioInfoAspectTest extends AndroidStudioInfoAspectTestBase ")"); Map<String, RuleIdeInfo> ruleIdeInfos = buildRuleIdeInfo("//com/google/example:simple"); assertThat(ruleIdeInfos).hasSize(2); - RuleIdeInfo ruleIdeInfo = getRuleInfoAndVerifyLabel( - "//com/google/example:simple", ruleIdeInfos); + RuleIdeInfo ruleIdeInfo = + getRuleInfoAndVerifyLabel("//com/google/example:simple", ruleIdeInfos); ArtifactLocation location = ruleIdeInfo.getBuildFileArtifactLocation(); assertThat(Paths.get(location.getRelativePath()).toString()) .isEqualTo(Paths.get("com/google/example/BUILD").toString()); @@ -1407,14 +1404,14 @@ public class AndroidStudioInfoAspectTest extends AndroidStudioInfoAspectTestBase ")"); Map<String, RuleIdeInfo> ruleIdeInfos = buildRuleIdeInfo("//com/google/example:simple"); assertThat(ruleIdeInfos).hasSize(3); - RuleIdeInfo ruleIdeInfo = getRuleInfoAndVerifyLabel( - "//com/google/example:simple", ruleIdeInfos); + RuleIdeInfo ruleIdeInfo = + getRuleInfoAndVerifyLabel("//com/google/example:simple", ruleIdeInfos); assertThat(ruleIdeInfo.getDependenciesList()).contains("//com/google/example:lib"); assertThat(ruleIdeInfo.getDependenciesList()).hasSize(2); - assertThat(getIdeCompileFiles()).containsExactly( - "com/google/example/_objs/simple/com/google/example/simple/simple.o"); + assertThat(getIdeCompileFiles()) + .containsExactly("com/google/example/_objs/simple/com/google/example/simple/simple.o"); } @Test @@ -1432,8 +1429,8 @@ public class AndroidStudioInfoAspectTest extends AndroidStudioInfoAspectTestBase " hdrs = ['simple/simple.h'],", ")"); Map<String, RuleIdeInfo> ruleIdeInfos = buildRuleIdeInfo("//com/google/example:androidlib"); - RuleIdeInfo ruleIdeInfo = getRuleInfoAndVerifyLabel( - "//com/google/example:androidlib", ruleIdeInfos); + RuleIdeInfo ruleIdeInfo = + getRuleInfoAndVerifyLabel("//com/google/example:androidlib", ruleIdeInfos); assertThat(ruleIdeInfo.getDependenciesList()).contains("//com/google/example:simple"); } @@ -1457,8 +1454,7 @@ public class AndroidStudioInfoAspectTest extends AndroidStudioInfoAspectTestBase ")"); Map<String, RuleIdeInfo> ruleIdeInfos = buildRuleIdeInfo("//com/google/example:lib1"); assertThat(ruleIdeInfos).hasSize(3); - RuleIdeInfo lib1 = getRuleInfoAndVerifyLabel( - "//com/google/example:lib1", ruleIdeInfos); + RuleIdeInfo lib1 = getRuleInfoAndVerifyLabel("//com/google/example:lib1", ruleIdeInfos); assertThat(lib1.hasCRuleIdeInfo()).isTrue(); CRuleIdeInfo cRuleIdeInfo = lib1.getCRuleIdeInfo(); @@ -1466,8 +1462,8 @@ public class AndroidStudioInfoAspectTest extends AndroidStudioInfoAspectTestBase assertThat(cRuleIdeInfo.getRuleIncludeList()).containsExactly("foo/bar"); // Make sure our understanding of where this attributes show up in other providers is correct. - Entry<String, RuleIdeInfo> toolchainEntry = getCcToolchainRuleAndVerifyThereIsOnlyOne( - ruleIdeInfos); + Entry<String, RuleIdeInfo> toolchainEntry = + getCcToolchainRuleAndVerifyThereIsOnlyOne(ruleIdeInfos); RuleIdeInfo toolchainInfo = toolchainEntry.getValue(); assertThat(toolchainInfo.hasCToolchainIdeInfo()).isTrue(); CToolchainIdeInfo cToolchainIdeInfo = toolchainInfo.getCToolchainIdeInfo(); @@ -1518,8 +1514,7 @@ public class AndroidStudioInfoAspectTest extends AndroidStudioInfoAspectTestBase ")"); Map<String, RuleIdeInfo> ruleIdeInfos = buildRuleIdeInfo("//com/google/example:lib1"); assertThat(ruleIdeInfos).hasSize(3); - RuleIdeInfo lib1 = getRuleInfoAndVerifyLabel( - "//com/google/example:lib1", ruleIdeInfos); + RuleIdeInfo lib1 = getRuleInfoAndVerifyLabel("//com/google/example:lib1", ruleIdeInfos); assertThat(lib1.hasCRuleIdeInfo()).isTrue(); CRuleIdeInfo cRuleIdeInfo = lib1.getCRuleIdeInfo(); @@ -1527,8 +1522,8 @@ public class AndroidStudioInfoAspectTest extends AndroidStudioInfoAspectTestBase assertThat(cRuleIdeInfo.getRuleCoptList()).containsExactly("-DGOPT", "-Ifoo/baz/"); // Make sure our understanding of where this attributes show up in other providers is correct. - Entry<String, RuleIdeInfo> toolchainEntry = getCcToolchainRuleAndVerifyThereIsOnlyOne( - ruleIdeInfos); + Entry<String, RuleIdeInfo> toolchainEntry = + getCcToolchainRuleAndVerifyThereIsOnlyOne(ruleIdeInfos); RuleIdeInfo toolchainInfo = toolchainEntry.getValue(); assertThat(toolchainInfo.hasCToolchainIdeInfo()).isTrue(); CToolchainIdeInfo cToolchainIdeInfo = toolchainInfo.getCToolchainIdeInfo(); @@ -1570,8 +1565,7 @@ public class AndroidStudioInfoAspectTest extends AndroidStudioInfoAspectTestBase ")"); Map<String, RuleIdeInfo> ruleIdeInfos = buildRuleIdeInfo("//com/google/example:lib1"); assertThat(ruleIdeInfos).hasSize(3); - RuleIdeInfo lib1 = getRuleInfoAndVerifyLabel( - "//com/google/example:lib1", ruleIdeInfos); + RuleIdeInfo lib1 = getRuleInfoAndVerifyLabel("//com/google/example:lib1", ruleIdeInfos); assertThat(lib1.hasCRuleIdeInfo()).isTrue(); CRuleIdeInfo cRuleIdeInfo = lib1.getCRuleIdeInfo(); @@ -1601,8 +1595,8 @@ public class AndroidStudioInfoAspectTest extends AndroidStudioInfoAspectTestBase " name = 'simple',", ")"); Map<String, RuleIdeInfo> ruleIdeInfos = buildRuleIdeInfo("//java/com/google/example:simple"); - RuleIdeInfo ruleIdeInfo = getRuleInfoAndVerifyLabel( - "//java/com/google/example:simple", ruleIdeInfos); + RuleIdeInfo ruleIdeInfo = + getRuleInfoAndVerifyLabel("//java/com/google/example:simple", ruleIdeInfos); if (testLegacyAswbPluginVersionCompatibility()) { assertThat(ruleIdeInfo.getKind()).isEqualTo(Kind.ANDROID_BINARY); } @@ -1635,12 +1629,9 @@ public class AndroidStudioInfoAspectTest extends AndroidStudioInfoAspectTestBase ")"); Map<String, RuleIdeInfo> ruleIdeInfos = buildRuleIdeInfo("//com/google/example:simple"); assertThat(ruleIdeInfos).hasSize(2); - RuleIdeInfo ruleInfo = getRuleInfoAndVerifyLabel( - "//com/google/example:simple", - ruleIdeInfos - ); - Entry<String, RuleIdeInfo> toolchainEntry = getCcToolchainRuleAndVerifyThereIsOnlyOne( - ruleIdeInfos); + RuleIdeInfo ruleInfo = getRuleInfoAndVerifyLabel("//com/google/example:simple", ruleIdeInfos); + Entry<String, RuleIdeInfo> toolchainEntry = + getCcToolchainRuleAndVerifyThereIsOnlyOne(ruleIdeInfos); RuleIdeInfo toolchainInfo = toolchainEntry.getValue(); ArtifactLocation location = ruleInfo.getBuildFileArtifactLocation(); assertThat(Paths.get(location.getRelativePath()).toString()) @@ -1659,8 +1650,8 @@ public class AndroidStudioInfoAspectTest extends AndroidStudioInfoAspectTestBase " srcs = ['simple/Simple.java']", ")"); Map<String, RuleIdeInfo> ruleIdeInfos = buildRuleIdeInfo("//com/google/example:simple"); - RuleIdeInfo ruleIdeInfo = getRuleInfoAndVerifyLabel( - "//com/google/example:simple", ruleIdeInfos); + RuleIdeInfo ruleIdeInfo = + getRuleInfoAndVerifyLabel("//com/google/example:simple", ruleIdeInfos); assertThat(ruleIdeInfo.hasCRuleIdeInfo()).isFalse(); } @@ -1686,10 +1677,8 @@ public class AndroidStudioInfoAspectTest extends AndroidStudioInfoAspectTestBase " srcs = ['Real.java'],", ")"); Map<String, RuleIdeInfo> ruleIdeInfos = buildRuleIdeInfo("//com/google/example:test"); - RuleIdeInfo testInfo = getRuleInfoAndVerifyLabel( - "//com/google/example:test", ruleIdeInfos); - assertThat(testInfo.getDependenciesList()) - .contains("//com/google/example:real"); + RuleIdeInfo testInfo = getRuleInfoAndVerifyLabel("//com/google/example:test", ruleIdeInfos); + assertThat(testInfo.getDependenciesList()).contains("//com/google/example:real"); assertThat(getRuleInfoAndVerifyLabel("//com/google/example:real", ruleIdeInfos)).isNotNull(); } @@ -1703,8 +1692,7 @@ public class AndroidStudioInfoAspectTest extends AndroidStudioInfoAspectTestBase "foo = rule(", " implementation=impl,", " attrs={'deps': attr.label_list(cfg='data')},", - ")" - ); + ")"); scratch.file( "com/google/example/BUILD", "load('//com/google/example:foo.bzl', 'foo')", @@ -1715,18 +1703,15 @@ public class AndroidStudioInfoAspectTest extends AndroidStudioInfoAspectTestBase } /** - * Returns true if we are testing the native aspect, not the Skylark one. - * Eventually Skylark aspect will be equivalent to a native one, and this method - * will be removed. + * Returns true if we are testing the native aspect, not the Skylark one. Eventually Skylark + * aspect will be equivalent to a native one, and this method will be removed. */ @Override protected boolean isNativeTest() { return true; } - /** - * Test for Skylark version of the aspect. - */ + /** Test for Skylark version of the aspect. */ @RunWith(JUnit4.class) public static class IntelliJSkylarkAspectTest extends AndroidStudioInfoAspectTest { diff --git a/src/test/java/com/google/devtools/build/lib/ideinfo/intellij_info.bzl b/src/test/java/com/google/devtools/build/lib/ideinfo/intellij_info.bzl index f179b68727..364429559f 100644 --- a/src/test/java/com/google/devtools/build/lib/ideinfo/intellij_info.bzl +++ b/src/test/java/com/google/devtools/build/lib/ideinfo/intellij_info.bzl @@ -287,7 +287,13 @@ def build_java_rule_ide_info(target, ctx): jdeps = artifact_location(target.java.outputs.jdeps) - java_sources, gen_java_sources = java_sources_for_package_manifest(ctx) + java_sources, gen_java_sources, srcjars = divide_java_sources(ctx) + + # HACK -- android_library rules with the resources attribute do not support srcjar inputs + # to the filtered gen jar generation, because we don't want all resource classes in this jar. + # This can be removed once android_resources is deleted + if hasattr(ctx.rule.attr, LEGACY_RESOURCE_ATTR) and ctx.rule.kind.startswith("android_"): + srcjars = [] package_manifest = None if java_sources: @@ -295,29 +301,14 @@ def build_java_rule_ide_info(target, ctx): ide_info_files = ide_info_files | set([package_manifest]) filtered_gen_jar = None - if java_sources and gen_java_sources: - gen_package_manifest = build_java_package_manifest( + if java_sources and (gen_java_sources or srcjars): + filtered_gen_jar, filtered_gen_resolve_files = build_filtered_gen_jar( ctx, target, gen_java_sources, - "-filtered-gen.manifest" - ) - jar_artifacts = [] - for jar in target.java.outputs.jars: - if jar.ijar: - jar_artifacts.append(jar.ijar) - elif jar.class_jar: - jar_artifacts.append(jar.class_jar) - filtered_gen_jar_artifact = build_filtered_gen_jar( - ctx, - target, - jar_artifacts, - gen_package_manifest - ) - ide_resolve_files = ide_resolve_files | set([filtered_gen_jar_artifact]) - filtered_gen_jar = struct( - jar=artifact_location(filtered_gen_jar_artifact), + srcjars ) + ide_resolve_files = ide_resolve_files | filtered_gen_resolve_files java_rule_ide_info = struct_omit_none( sources = sources, @@ -351,34 +342,67 @@ def build_java_package_manifest(ctx, target, source_files, suffix): ) return output -def build_filtered_gen_jar(ctx, target, jars, manifest): +def build_filtered_gen_jar(ctx, target, gen_java_sources, srcjars): """Filters the passed jar to contain only classes from the given manifest.""" - output = ctx.new_file(target.label.name + "-filtered-gen.jar") + jar_artifacts = [] + source_jar_artifacts = [] + for jar in target.java.outputs.jars: + if jar.ijar: + jar_artifacts.append(jar.ijar) + elif jar.class_jar: + jar_artifacts.append(jar.class_jar) + if jar.source_jar: + source_jar_artifacts.append(jar.source_jar) + + filtered_jar = ctx.new_file(target.label.name + "-filtered-gen.jar") + filtered_source_jar = ctx.new_file(target.label.name + "-filtered-gen-src.jar") args = [] - args += ["--jars"] - args += [":".join([jar.path for jar in jars])] - args += ["--manifest", manifest.path] - args += ["--output", output.path] + args += ["--filter_jars"] + args += [":".join([jar.path for jar in jar_artifacts])] + args += ["--filter_source_jars"] + args += [":".join([jar.path for jar in source_jar_artifacts])] + args += ["--filtered_jar", filtered_jar.path] + args += ["--filtered_source_jar", filtered_source_jar.path] + if gen_java_sources: + args += ["--keep_java_files"] + args += [":".join([java_file.path for java_file in gen_java_sources])] + if srcjars: + args += ["--keep_source_jars"] + args += [":".join([source_jar.path for source_jar in srcjars])] ctx.action( - inputs = jars + [manifest], - outputs = [output], + inputs = jar_artifacts + source_jar_artifacts + gen_java_sources + srcjars, + outputs = [filtered_jar, filtered_source_jar], executable = ctx.executable._jar_filter, arguments = args, mnemonic = "JarFilter", progress_message = "Filtering generated code for " + str(target.label), ) - return output + output_jar = struct( + jar=artifact_location(filtered_jar), + source_jar=artifact_location(filtered_source_jar), + ) + ide_resolve_files = set([filtered_jar, filtered_source_jar]) + return output_jar, ide_resolve_files -def java_sources_for_package_manifest(ctx): - """Get the list of non-generated java sources to go in the package manifest.""" +def divide_java_sources(ctx): + """Divide sources into plain java, generated java, and srcjars.""" + java_sources = [] + gen_java_sources = [] + srcjars = [] if hasattr(ctx.rule.attr, "srcs"): srcs = ctx.rule.attr.srcs - all_java_sources = [f for src in srcs for f in src.files if f.basename.endswith(".java")] - java_sources = [f for f in all_java_sources if f.is_source] - gen_java_sources = [f for f in all_java_sources if not f.is_source] - return java_sources, gen_java_sources - return [], [] + for src in srcs: + for f in src.files: + if f.basename.endswith(".java"): + if f.is_source: + java_sources.append(f) + else: + gen_java_sources.append(f) + elif f.basename.endswith(".srcjar"): + srcjars.append(f) + + return java_sources, gen_java_sources, srcjars def build_android_rule_ide_info(target, ctx, legacy_resource_label): """Build AndroidRuleIdeInfo. diff --git a/src/tools/android/java/com/google/devtools/build/android/ideinfo/JarFilter.java b/src/tools/android/java/com/google/devtools/build/android/ideinfo/JarFilter.java index 2a373565cf..92f55db9aa 100644 --- a/src/tools/android/java/com/google/devtools/build/android/ideinfo/JarFilter.java +++ b/src/tools/android/java/com/google/devtools/build/android/ideinfo/JarFilter.java @@ -14,10 +14,18 @@ package com.google.devtools.build.android.ideinfo; +import static java.nio.charset.StandardCharsets.UTF_8; + import com.google.common.annotations.VisibleForTesting; import com.google.common.base.Preconditions; +import com.google.common.base.Predicate; +import com.google.common.collect.ImmutableList; import com.google.common.collect.Lists; import com.google.common.io.Files; +import com.google.common.util.concurrent.Futures; +import com.google.common.util.concurrent.ListenableFuture; +import com.google.common.util.concurrent.ListeningExecutorService; +import com.google.common.util.concurrent.MoreExecutors; import com.google.devtools.build.android.Converters.PathConverter; import com.google.devtools.build.android.Converters.PathListConverter; import com.google.devtools.build.lib.ideinfo.androidstudio.PackageManifestOuterClass.ArtifactLocation; @@ -26,63 +34,131 @@ import com.google.devtools.build.lib.ideinfo.androidstudio.PackageManifestOuterC import com.google.devtools.common.options.Option; import com.google.devtools.common.options.OptionsBase; import com.google.devtools.common.options.OptionsParser; +import java.io.BufferedReader; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; +import java.io.InputStreamReader; import java.nio.charset.StandardCharsets; import java.nio.file.Path; import java.util.Enumeration; import java.util.List; +import java.util.concurrent.Callable; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.Executors; import java.util.logging.Level; import java.util.logging.Logger; +import java.util.regex.Matcher; +import java.util.regex.Pattern; import java.util.zip.ZipEntry; import java.util.zip.ZipFile; import java.util.zip.ZipOutputStream; import javax.annotation.Nonnull; import javax.annotation.Nullable; -/** - * Filters a jar, keeping only the classes that are contained - * in the supplied package manifest. - */ +/** Filters a jar, keeping only the classes that are indicated. */ public final class JarFilter { /** The options for a {@JarFilter} action. */ public static final class JarFilterOptions extends OptionsBase { - @Option(name = "jars", - defaultValue = "null", - converter = PathListConverter.class, - category = "input", - help = "A list of the paths to jars to filter for generated sources.") + @Option( + name = "filter_jars", + defaultValue = "null", + converter = PathListConverter.class, + category = "input", + help = "A list of the paths to target output jars to filter for generated sources." + ) + public List<Path> filterJars; + + @Option( + name = "filter_source_jars", + defaultValue = "null", + converter = PathListConverter.class, + category = "input", + help = "A list of the paths to target output source jars to filter for generated sources." + ) + public List<Path> filterSourceJars; + + @Option( + name = "keep_java_files", + defaultValue = "null", + converter = PathListConverter.class, + category = "input", + help = "A list of target input java files to keep." + ) + public List<Path> keepJavaFiles; + + @Option( + name = "keep_source_jars", + defaultValue = "null", + converter = PathListConverter.class, + category = "input", + help = "A list of target input .srcjar files to keep." + ) + public List<Path> keepSourceJars; + + @Option( + name = "filtered_jar", + defaultValue = "null", + converter = PathConverter.class, + category = "output", + help = "The path to the jar to output." + ) + public Path filteredJar; + + @Option( + name = "filtered_source_jar", + defaultValue = "null", + converter = PathConverter.class, + category = "output", + help = "The path to the source jar to output." + ) + public Path filteredSourceJar; + + // Deprecated options -- only here to maintain command line backwards compatibility + // with the current blaze native IDE aspect + + @Deprecated + @Option( + name = "jars", + defaultValue = "null", + converter = PathListConverter.class, + category = "input", + help = "A list of the paths to jars to filter for generated sources." + ) public List<Path> jars; - @Option(name = "manifest", - defaultValue = "null", - converter = PathConverter.class, - category = "input", - help = "The path to a package manifest generated only from generated sources.") + @Deprecated + @Option( + name = "manifest", + defaultValue = "null", + converter = PathConverter.class, + category = "input", + help = "The path to a package manifest generated only from generated sources." + ) public Path manifest; - @Option(name = "output", - defaultValue = "null", - converter = PathConverter.class, - category = "output", - help = "The path to the jar to output.") + @Deprecated + @Option( + name = "output", + defaultValue = "null", + converter = PathConverter.class, + category = "output", + help = "The path to the jar to output." + ) public Path output; } private static final Logger logger = Logger.getLogger(JarFilter.class.getName()); + private static final Pattern JAVA_PACKAGE_PATTERN = + Pattern.compile("^\\s*package\\s+([\\w\\.]+);"); + public static void main(String[] args) throws Exception { JarFilterOptions options = parseArgs(args); - Preconditions.checkNotNull(options.jars); - Preconditions.checkNotNull(options.manifest); - Preconditions.checkNotNull(options.output); - try { - List<String> archiveFileNamePrefixes = parsePackageManifest(options.manifest); - filterJars(options.jars, options.output, archiveFileNamePrefixes); + main(options); } catch (Throwable e) { logger.log(Level.SEVERE, "Error parsing package strings", e); System.exit(1); @@ -91,11 +167,64 @@ public final class JarFilter { } @VisibleForTesting + static void main(JarFilterOptions options) throws Exception { + Preconditions.checkNotNull(options.filteredJar); + + if (options.filterJars == null) { + options.filterJars = ImmutableList.of(); + } + if (options.filterSourceJars == null) { + options.filterSourceJars = ImmutableList.of(); + } + + final List<String> archiveFileNamePrefixes = Lists.newArrayList(); + if (options.manifest != null) { + archiveFileNamePrefixes.addAll(parsePackageManifest(options.manifest)); + } + if (options.keepJavaFiles != null) { + archiveFileNamePrefixes.addAll(parseJavaFiles(options.keepJavaFiles)); + } + if (options.keepSourceJars != null) { + archiveFileNamePrefixes.addAll(parseSrcJars(options.keepSourceJars)); + } + + filterJars( + options.filterJars, + options.filteredJar, + new Predicate<String>() { + @Override + public boolean apply(@Nullable String s) { + return shouldKeepClass(archiveFileNamePrefixes, s); + } + }); + if (options.filteredSourceJar != null) { + filterJars( + options.filterSourceJars, + options.filteredSourceJar, + new Predicate<String>() { + @Override + public boolean apply(@Nullable String s) { + return shouldKeepJavaFile(archiveFileNamePrefixes, s); + } + }); + } + } + + @VisibleForTesting static JarFilterOptions parseArgs(String[] args) { args = parseParamFileIfUsed(args); OptionsParser optionsParser = OptionsParser.newOptionsParser(JarFilterOptions.class); optionsParser.parseAndExitUponError(args); - return optionsParser.getOptions(JarFilterOptions.class); + + // Migrate options from v1 jar filter + JarFilterOptions options = optionsParser.getOptions(JarFilterOptions.class); + if (options.filterJars == null && options.jars != null) { + options.filterJars = options.jars; + } + if (options.filteredJar == null && options.output != null) { + options.filteredJar = options.output; + } + return options; } private static String[] parseParamFileIfUsed(@Nonnull String[] args) { @@ -110,19 +239,140 @@ public final class JarFilter { } } - private static void filterJars(List<Path> jars, Path output, - List<String> archiveFileNamePrefixes) throws IOException { + /** Finds the expected jar archive file name prefixes for the java files. */ + static List<String> parseJavaFiles(List<Path> javaFiles) throws IOException { + ListeningExecutorService executorService = + MoreExecutors.listeningDecorator( + Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors())); + + List<ListenableFuture<String>> futures = Lists.newArrayList(); + for (final Path javaFile : javaFiles) { + futures.add( + executorService.submit( + new Callable<String>() { + @Override + public String call() throws Exception { + String packageString = getDeclaredPackageOfJavaFile(javaFile); + return packageString != null + ? getArchiveFileNamePrefix(javaFile.toString(), packageString) + : null; + } + })); + } + try { + List<String> archiveFileNamePrefixes = Futures.allAsList(futures).get(); + List<String> result = Lists.newArrayList(); + for (String archiveFileNamePrefix : archiveFileNamePrefixes) { + if (archiveFileNamePrefix != null) { + result.add(archiveFileNamePrefix); + } + } + return result; + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + throw new IOException(e); + } catch (ExecutionException e) { + throw new IOException(e); + } + } + + static List<String> parseSrcJars(List<Path> srcJars) throws IOException { + List<String> result = Lists.newArrayList(); + for (Path srcJar : srcJars) { + try (ZipFile sourceZipFile = new ZipFile(srcJar.toFile())) { + Enumeration<? extends ZipEntry> entries = sourceZipFile.entries(); + while (entries.hasMoreElements()) { + ZipEntry entry = entries.nextElement(); + if (!entry.getName().endsWith(".java")) { + continue; + } + try (BufferedReader reader = + new BufferedReader( + new InputStreamReader(sourceZipFile.getInputStream(entry), UTF_8))) { + String packageString = parseDeclaredPackage(reader); + if (packageString != null) { + String archiveFileNamePrefix = + getArchiveFileNamePrefix(entry.getName(), packageString); + result.add(archiveFileNamePrefix); + } + } + } + } + } + return result; + } + + @Nullable + private static String getDeclaredPackageOfJavaFile(Path javaFile) { + try (BufferedReader reader = + java.nio.file.Files.newBufferedReader(javaFile, StandardCharsets.UTF_8)) { + return parseDeclaredPackage(reader); + + } catch (IOException e) { + logger.log(Level.WARNING, "Error parsing package string from java source: " + javaFile, e); + return null; + } + } + + @Nullable + private static String parseDeclaredPackage(BufferedReader reader) throws IOException { + String line; + while ((line = reader.readLine()) != null) { + Matcher packageMatch = JAVA_PACKAGE_PATTERN.matcher(line); + if (packageMatch.find()) { + return packageMatch.group(1); + } + } + return null; + } + + /** + * Computes the expected archive file name prefix of a java class. + * + * <p>Eg.: file java/com/google/foo/Foo.java, package com.google.foo -> com/google/foo/Foo + */ + private static String getArchiveFileNamePrefix(String javaFile, String packageString) { + int lastSlashIndex = javaFile.lastIndexOf('/'); + String fileName = lastSlashIndex != -1 ? javaFile.substring(lastSlashIndex + 1) : javaFile; + String className = fileName.substring(0, fileName.length() - ".java".length()); + return packageString.replace('.', '/') + '/' + className; + } + + /** Reads the package manifest and computes a list of the expected jar archive file names. */ + private static List<String> parsePackageManifest(Path manifest) throws IOException { + try (InputStream inputStream = java.nio.file.Files.newInputStream(manifest)) { + PackageManifest packageManifest = PackageManifest.parseFrom(inputStream); + return parsePackageManifest(packageManifest); + } + } + + @VisibleForTesting + static List<String> parsePackageManifest(PackageManifest packageManifest) { + List<String> result = Lists.newArrayList(); + for (JavaSourcePackage javaSourcePackage : packageManifest.getSourcesList()) { + ArtifactLocation artifactLocation = javaSourcePackage.getArtifactLocation(); + String packageString = javaSourcePackage.getPackageString(); + String archiveFileNamePrefix = + getArchiveFileNamePrefix(artifactLocation.getRelativePath(), packageString); + result.add(archiveFileNamePrefix); + } + return result; + } + + /** Filters a list of jars, keeping anything matching the passed predicate. */ + private static void filterJars(List<Path> jars, Path output, Predicate<String> shouldKeep) + throws IOException { final int bufferSize = 8 * 1024; byte[] buffer = new byte[bufferSize]; - try (ZipOutputStream outputStream = new ZipOutputStream( - new FileOutputStream(output.toFile()))) { + try (ZipOutputStream outputStream = + new ZipOutputStream(new FileOutputStream(output.toFile()))) { for (Path jar : jars) { try (ZipFile sourceZipFile = new ZipFile(jar.toFile())) { Enumeration<? extends ZipEntry> entries = sourceZipFile.entries(); while (entries.hasMoreElements()) { ZipEntry entry = entries.nextElement(); - if (!shouldKeep(archiveFileNamePrefixes, entry.getName())) { + if (!shouldKeep.apply(entry.getName())) { continue; } @@ -141,7 +391,10 @@ public final class JarFilter { } @VisibleForTesting - static boolean shouldKeep(List<String> archiveFileNamePrefixes, String name) { + static boolean shouldKeepClass(List<String> archiveFileNamePrefixes, String name) { + if (!name.endsWith(".class")) { + return false; + } for (String archiveFileNamePrefix : archiveFileNamePrefixes) { if (name.startsWith(archiveFileNamePrefix) && name.length() > archiveFileNamePrefix.length()) { @@ -154,42 +407,11 @@ public final class JarFilter { return false; } - @Nullable - private static List<String> parsePackageManifest(Path manifest) throws IOException { - try (InputStream inputStream = java.nio.file.Files.newInputStream(manifest)) { - PackageManifest packageManifest = PackageManifest.parseFrom(inputStream); - return parsePackageManifest(packageManifest); - } - } - - /** - * Reads the package manifest and computes a list of the expected jar archive - * file names. - * - * Eg.: - * file java/com/google/foo/Foo.java, package com.google.foo -> - * com/google/foo/Foo - */ - @VisibleForTesting - static List<String> parsePackageManifest(PackageManifest packageManifest) { - List<String> result = Lists.newArrayList(); - for (JavaSourcePackage javaSourcePackage : packageManifest.getSourcesList()) { - ArtifactLocation artifactLocation = javaSourcePackage.getArtifactLocation(); - String packageString = javaSourcePackage.getPackageString(); - String archiveFileNamePrefix = getArchiveFileNamePrefix(artifactLocation, packageString); - result.add(archiveFileNamePrefix); + private static boolean shouldKeepJavaFile(List<String> archiveFileNamePrefixes, String name) { + if (!name.endsWith(".java")) { + return false; } - return result; - } - - @Nullable - private static String getArchiveFileNamePrefix(ArtifactLocation artifactLocation, - String packageString) { - String relativePath = artifactLocation.getRelativePath(); - int lastSlashIndex = relativePath.lastIndexOf('/'); - String fileName = lastSlashIndex != -1 - ? relativePath.substring(lastSlashIndex + 1) : relativePath; - String className = fileName.substring(0, fileName.length() - ".java".length()); - return packageString.replace('.', '/') + '/' + className; + String nameWithoutJava = name.substring(0, name.length() - ".java".length()); + return archiveFileNamePrefixes.contains(nameWithoutJava); } } |