From ddda06d8250fd70a320bd9aa926fd1dd7d52c6f3 Mon Sep 17 00:00:00 2001 From: Dmitry Lomov Date: Tue, 19 Jan 2016 15:58:11 +0000 Subject: Skylark IDE info aspect: sources and dependencies. 1. Refactored IntelliJSkylarkAspectTest. Eventually that test will be merged with AndroidStudioInfoAspect test to validate implementation equivalence. 2. Exposed ``root`` and ``is_source`` on Artifacts to Skylark. 3. Skylark aspect implementation outputs sources and dependencies information. -- MOS_MIGRATED_REVID=112473407 --- .../devtools/build/lib/actions/Artifact.java | 5 ++ .../devtools/build/lib/actions/ArtifactTest.java | 21 +++++++ .../ideinfo/AndroidStudioInfoAspectTestBase.java | 5 +- .../lib/ideinfo/IntelliJSkylarkAspectTest.java | 65 +++++++++++++++++--- .../devtools/build/lib/ideinfo/intellij_info.bzl | 71 +++++++++++++++++----- 5 files changed, 139 insertions(+), 28 deletions(-) diff --git a/src/main/java/com/google/devtools/build/lib/actions/Artifact.java b/src/main/java/com/google/devtools/build/lib/actions/Artifact.java index 5a98552c9b..d4de3db2ad 100644 --- a/src/main/java/com/google/devtools/build/lib/actions/Artifact.java +++ b/src/main/java/com/google/devtools/build/lib/actions/Artifact.java @@ -271,6 +271,9 @@ public class Artifact implements FileType.HasFilename, ActionInput, SkylarkValue * package-path entries (for source Artifacts), or one of the bin, genfiles or includes dirs * (for derived Artifacts). It will always be an ancestor of getPath(). */ + @SkylarkCallable(name = "root", structField = true, + doc = "The root beneath which this file resides." + ) public final Root getRoot() { return root; } @@ -289,6 +292,8 @@ public class Artifact implements FileType.HasFilename, ActionInput, SkylarkValue * root relationships. Note that this will report all Artifacts in the output * tree, including in the include symlink tree, as non-source. */ + @SkylarkCallable(name = "is_source", structField = true, + doc = "Returns true if this is a source file, i.e. it is not generated") public final boolean isSourceArtifact() { return execPath == rootRelativePath; } diff --git a/src/test/java/com/google/devtools/build/lib/actions/ArtifactTest.java b/src/test/java/com/google/devtools/build/lib/actions/ArtifactTest.java index 81fabbb16a..cd978217d0 100644 --- a/src/test/java/com/google/devtools/build/lib/actions/ArtifactTest.java +++ b/src/test/java/com/google/devtools/build/lib/actions/ArtifactTest.java @@ -337,6 +337,27 @@ public class ArtifactTest { assertThat(constructed).isEqualTo("aaa/bbb/ccc/ddd"); } + @Test + public void testIsSourceArtifact() throws Exception { + assertThat( + new Artifact(scratch.file("/src/foo.cc"), Root.asSourceRoot(scratch.dir("/")), + new PathFragment("src/foo.cc")) + .isSourceArtifact()) + .isTrue(); + assertThat( + new Artifact(scratch.file("/genfiles/aaa/bar.out"), + Root.asDerivedRoot(scratch.dir("/genfiles"), scratch.dir("/genfiles/aaa"))) + .isSourceArtifact()) + .isFalse(); + + } + + @Test + public void testGetRoot() throws Exception { + Root root = Root.asDerivedRoot(scratch.dir("/newRoot")); + assertThat(new Artifact(scratch.file("/newRoot/foo"), root).getRoot()).isEqualTo(root); + } + private Artifact createDirNameArtifact() throws Exception { return new Artifact(scratch.file("/aaa/bbb/ccc/ddd"), Root.asDerivedRoot(scratch.dir("/"))); } diff --git a/src/test/java/com/google/devtools/build/lib/ideinfo/AndroidStudioInfoAspectTestBase.java b/src/test/java/com/google/devtools/build/lib/ideinfo/AndroidStudioInfoAspectTestBase.java index 6c3213491b..f91eec07ea 100644 --- a/src/test/java/com/google/devtools/build/lib/ideinfo/AndroidStudioInfoAspectTestBase.java +++ b/src/test/java/com/google/devtools/build/lib/ideinfo/AndroidStudioInfoAspectTestBase.java @@ -81,8 +81,7 @@ abstract class AndroidStudioInfoAspectTestBase extends BuildViewTestCase { } }; - private AnalysisResult analysisResult; - private ConfiguredAspect configuredAspect; + protected ConfiguredAspect configuredAspect; /** * Constructs a string that matches OutputJar#toString for comparison testing. @@ -114,7 +113,7 @@ abstract class AndroidStudioInfoAspectTestBase extends BuildViewTestCase { } protected void buildTarget(String target) throws Exception { - this.analysisResult = + AnalysisResult analysisResult = update( ImmutableList.of(target), ImmutableList.of(AndroidStudioInfoAspect.NAME), diff --git a/src/test/java/com/google/devtools/build/lib/ideinfo/IntelliJSkylarkAspectTest.java b/src/test/java/com/google/devtools/build/lib/ideinfo/IntelliJSkylarkAspectTest.java index 7efbb6351c..fc965e0ef5 100644 --- a/src/test/java/com/google/devtools/build/lib/ideinfo/IntelliJSkylarkAspectTest.java +++ b/src/test/java/com/google/devtools/build/lib/ideinfo/IntelliJSkylarkAspectTest.java @@ -23,7 +23,6 @@ import com.google.devtools.build.lib.actions.Artifact; import com.google.devtools.build.lib.analysis.BuildView.AnalysisResult; import com.google.devtools.build.lib.analysis.OutputGroupProvider; import com.google.devtools.build.lib.analysis.actions.FileWriteAction; -import com.google.devtools.build.lib.analysis.util.BuildViewTestCase; import com.google.devtools.build.lib.collect.nestedset.NestedSet; import com.google.devtools.build.lib.ideinfo.androidstudio.AndroidStudioIdeInfo.RuleIdeInfo; import com.google.devtools.build.lib.ideinfo.androidstudio.AndroidStudioIdeInfo.RuleIdeInfo.Builder; @@ -42,12 +41,14 @@ import java.io.InputStreamReader; import java.nio.charset.StandardCharsets; import java.util.ArrayList; import java.util.Collection; +import java.util.HashMap; +import java.util.Map; /** * Tests for Skylark implementation of Android Studio info aspect */ @RunWith(JUnit4.class) -public class IntelliJSkylarkAspectTest extends BuildViewTestCase { +public class IntelliJSkylarkAspectTest extends AndroidStudioInfoAspectTestBase { @Before public void setupBzl() throws Exception { InputStream stream = IntelliJSkylarkAspectTest.class @@ -73,8 +74,53 @@ public class IntelliJSkylarkAspectTest extends BuildViewTestCase { " name = 'simple',", " srcs = ['simple/Simple.java']", ")"); + String target = "//com/google/example:simple"; + Map ruleIdeInfos = buildRuleIdeInfo(target); + + RuleIdeInfo ruleIdeInfo = + getRuleInfoAndVerifyLabel("//com/google/example:simple", ruleIdeInfos); + assertThat(ruleIdeInfo.getKind()).isEqualTo(Kind.JAVA_LIBRARY); + assertThat(ruleIdeInfo.getDependenciesCount()).isEqualTo(0); + assertThat(relativePathsForSourcesOf(ruleIdeInfo)) + .containsExactly("com/google/example/simple/Simple.java"); + } + + @Test + public void testJavaLibraryWithTransitiveDependencies() throws Exception { + scratch.file( + "com/google/example/BUILD", + "java_library(", + " name = 'simple',", + " srcs = ['simple/Simple.java']", + ")", + "java_library(", + " name = 'complex',", + " srcs = ['complex/Complex.java'],", + " deps = [':simple']", + ")", + "java_library(", + " name = 'extracomplex',", + " srcs = ['extracomplex/ExtraComplex.java'],", + " deps = [':complex']", + ")"); + Map ruleIdeInfos = buildRuleIdeInfo("//com/google/example:extracomplex"); + assertThat(ruleIdeInfos.size()).isEqualTo(3); + + getRuleInfoAndVerifyLabel("//com/google/example:simple", ruleIdeInfos); + getRuleInfoAndVerifyLabel("//com/google/example:complex", ruleIdeInfos); + + RuleIdeInfo extraComplexRuleIdeInfo = getRuleInfoAndVerifyLabel( + "//com/google/example:extracomplex", ruleIdeInfos); + + assertThat(relativePathsForSourcesOf(extraComplexRuleIdeInfo)) + .containsExactly("com/google/example/extracomplex/ExtraComplex.java"); + assertThat(extraComplexRuleIdeInfo.getDependenciesList()) + .containsExactly("//com/google/example:complex"); + } + + protected Map buildRuleIdeInfo(String target) throws Exception { AnalysisResult analysisResult = update( - ImmutableList.of("//com/google/example:simple"), + ImmutableList.of(target), ImmutableList.of("intellij_tools/intellij_info.bzl%intellij_info_aspect"), false, LOADING_PHASE_THREADS, @@ -84,20 +130,19 @@ public class IntelliJSkylarkAspectTest extends BuildViewTestCase { Collection aspects = analysisResult.getAspects(); assertThat(aspects).hasSize(1); AspectValue aspectValue = aspects.iterator().next(); - OutputGroupProvider provider = aspectValue.getConfiguredAspect() - .getProvider(OutputGroupProvider.class); + this.configuredAspect = aspectValue.getConfiguredAspect(); + OutputGroupProvider provider = configuredAspect.getProvider(OutputGroupProvider.class); NestedSet outputGroup = provider.getOutputGroup("ide-info-text"); - assertThat(outputGroup.toList()).hasSize(1); + Map ruleIdeInfos = new HashMap<>(); for (Artifact artifact : outputGroup) { Action generatingAction = getGeneratingAction(artifact); assertThat(generatingAction).isInstanceOf(FileWriteAction.class); String fileContents = ((FileWriteAction) generatingAction).getFileContents(); Builder builder = RuleIdeInfo.newBuilder(); TextFormat.getParser().merge(fileContents, builder); - RuleIdeInfo build = builder.build(); - assertThat(build.getLabel()).isEqualTo("//com/google/example:simple"); - assertThat(build.getKind()).isEqualTo(Kind.JAVA_LIBRARY); + RuleIdeInfo ruleIdeInfo = builder.build(); + ruleIdeInfos.put(ruleIdeInfo.getLabel(), ruleIdeInfo); } - + return ruleIdeInfos; } } 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 251a0a2155..feb37fef59 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 @@ -28,23 +28,72 @@ _kind_to_kind_id = { _unrecognized_rule = -1; +DEPENDENCY_ATTRIBUTES = [ + "deps", + "exports", + "_robolectric", # From android_robolectric_test + "_junit", # From android_robolectric_test + "binary_under_test", # From android_test + "java_lib",# From proto_library + "_proto1_java_lib", # From proto_library +] + def get_kind(target, ctx): return _kind_to_kind_id.get(ctx.rule.kind, _unrecognized_rule) +def is_java_rule(target, ctx): + return ctx.rule.kind != "android_sdk"; + +def artifact_location(file): + return struct( + root_path = file.root.path, # todo(dslomov): this gives path relative to execution root + relative_path = file.short_path, + is_source = file.is_source, + ) + +def java_rule_ide_info(target, ctx): + if hasattr(ctx.rule.attr, "srcs"): + sources = [artifact_location(file) + for src in ctx.rule.attr.srcs + for file in src.files] + else: + sources = [] + return struct(sources = sources) # todo(dslomov): more fields + + def _aspect_impl(target, ctx): - ide_info_text = set() kind = get_kind(target, ctx) + rule_attrs = ctx.rule.attr + + ide_info_text = set() + all_deps = [] + + for attr_name in DEPENDENCY_ATTRIBUTES: + if hasattr(rule_attrs, attr_name): + deps = getattr(rule_attrs, attr_name) + for dep in deps: + ide_info_text += dep.android_studio_info_files + all_deps += [str(dep.label) for dep in deps] + if kind != _unrecognized_rule: + if is_java_rule(target, ctx): + info = struct( + label = str(target.label), + kind = kind, + dependencies = all_deps, + # build_file = ??? + java_rule_ide_info = java_rule_ide_info(target, ctx) + ) + else: info = struct( label = str(target.label), kind = kind, + dependencies = all_deps, # build_file = ??? ) - output = ctx.new_file(target.label.name + ".aswb-build.txt") - ctx.file_action(output, info.to_proto()) - ide_info_text += set([output]) - for dep in ctx.rule.attr.deps: - ide_info_text += dep.android_studio_info_files + output = ctx.new_file(target.label.name + ".aswb-build.txt") + ctx.file_action(output, info.to_proto()) + ide_info_text += set([output]) return struct( output_groups = { @@ -54,13 +103,5 @@ def _aspect_impl(target, ctx): ) intellij_info_aspect = aspect(implementation = _aspect_impl, - attr_aspects = [ - "deps", - "exports", - "_robolectric", # From android_robolectric_test - "_junit", # From android_robolectric_test - "binary_under_test", # From android_test - "java_lib",# From proto_library - "_proto1_java_lib", # From proto_library - ] + attr_aspects = DEPENDENCY_ATTRIBUTES ) \ No newline at end of file -- cgit v1.2.3