Skip to content

Commit

Permalink
Add proto toolchains as dependencies and collect runtime jar in the a…
Browse files Browse the repository at this point in the history
…spect

Introduces ImplicitDepsProvider, which stores a mapping of rule types to implicit dependencies that need to be added to targets of the rule type (for the kotlin proto rule, this is determined dynamically according to the "variant" attribute), and augments the query proto during summarization. These labels can be found in the query output itself via "rule-input" fields of each target.

Adds attributes to the build_deps aspect so these dependencies can be reached for protos. This required adjusting the logic to allow traversal to go through targets without JavaInfo (the proto toolchain targets do not have a JavaInfo provider, but their "runtime" attribute is the java_library the IDE needs for resolving base classes.

Adds proto libraries as JAVA_RULE_TYPES in BlazeQueryParser so their deps are adequately reflected in the IDE.

For current query sync projects, this does not change what deps are built (as the runtime jars are picked up in the transitive deps for in-project proto libraries, which are "always build"), but it ensures that the runtime jars are marked as dependencies and built even if the ide doesn't need to build in-project protos.

PiperOrigin-RevId: 555229414
  • Loading branch information
Googler authored and copybara-github committed Aug 14, 2023
1 parent 5843e0b commit 598a5f7
Show file tree
Hide file tree
Showing 17 changed files with 256 additions and 48 deletions.
59 changes: 35 additions & 24 deletions aspect/build_dependencies.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -122,12 +122,13 @@ def _target_within_project_scope(label, include, exclude):

def _get_followed_dependency_infos(rule):
deps = []
if hasattr(rule.attr, "deps"):
deps += rule.attr.deps
if hasattr(rule.attr, "exports"):
deps += rule.attr.exports
if hasattr(rule.attr, "_junit"):
deps.append(rule.attr._junit)
for (attr, kinds) in FOLLOW_ATTRIBUTES_DETAILS:
if hasattr(rule.attr, attr) and (not kinds or rule.kind in kinds):
to_add = getattr(rule.attr, attr)
if type(to_add) == "list":
deps += to_add
else:
deps.append(to_add)

return [
dep[DependenciesInfo]
Expand Down Expand Up @@ -163,10 +164,11 @@ def _collect_own_artifacts(
# only gather their own compile jars and continue down the tree.
# This is done primarily for rules like proto, where they don't have dependencies
# and add their "toolchain" classes to transitive deps.
if can_follow_dependencies:
own_jar_depsets.append(target[JavaInfo].compile_jars)
else:
own_jar_depsets.append(target[JavaInfo].transitive_compile_time_jars)
if JavaInfo in target:
if can_follow_dependencies:
own_jar_depsets.append(target[JavaInfo].compile_jars)
else:
own_jar_depsets.append(target[JavaInfo].transitive_compile_time_jars)

if declares_android_resources(target, ctx):
ide_aar = _get_ide_aar_file(target, ctx)
Expand All @@ -187,9 +189,10 @@ def _collect_own_artifacts(

# Add generated java_outputs (e.g. from annotation processing
generated_class_jars = []
for java_output in target[JavaInfo].java_outputs:
if java_output.generated_class_jar:
generated_class_jars.append(java_output.generated_class_jar)
if JavaInfo in target:
for java_output in target[JavaInfo].java_outputs:
if java_output.generated_class_jar:
generated_class_jars.append(java_output.generated_class_jar)
if generated_class_jars:
own_jar_files += generated_class_jars

Expand Down Expand Up @@ -280,15 +283,6 @@ def _collect_dependencies_core_impl(
always_build_rules,
generate_aidl_classes,
test_mode):
if JavaInfo not in target:
return [DependenciesInfo(
compile_time_jars = depset(),
target_to_artifacts = {},
aars = depset(),
gensrcs = depset(),
test_mode_own_files = None,
)]

target_is_within_project_scope = _target_within_project_scope(str(target.label), include, exclude) and not test_mode
dependency_infos = _get_followed_dependency_infos(ctx.rule)

Expand Down Expand Up @@ -433,10 +427,27 @@ def _output_relative_path(path):
path = path[10:]
return path

# List of tuples containing:
# 1. An attribute for the aspect to traverse
# 2. Whether the attribute is a list of labels
# 3. A list of rule kind to specify which rules for which the attribute labels
# need to be added as dependencies. If empty, the attribute is followed for
# all rules.
FOLLOW_ATTRIBUTES_DETAILS = [
("deps", []),
("exports", []),
("_junit", []),
("_aspect_proto_toolchain_for_javalite", []),
("_aspect_java_proto_toolchain", []),
("runtime", ["proto_lang_toolchain"]),
]

FOLLOW_ATTRIBUTES = [attr for (attr, _) in FOLLOW_ATTRIBUTES_DETAILS]

collect_dependencies = aspect(
implementation = _collect_dependencies_impl,
provides = [DependenciesInfo],
attr_aspects = ["deps", "exports", "_junit"],
attr_aspects = FOLLOW_ATTRIBUTES,
attrs = {
"include": attr.string(
doc = "Comma separated list of workspace paths included in the project as source. Any targets inside here will not be built.",
Expand Down Expand Up @@ -474,7 +485,7 @@ collect_all_dependencies_for_tests = aspect(
""",
implementation = _collect_all_dependencies_for_tests_impl,
provides = [DependenciesInfo],
attr_aspects = ["deps", "exports", "_junit"],
attr_aspects = FOLLOW_ATTRIBUTES,
attrs = {
"_build_zip": attr.label(
allow_files = True,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,11 +27,13 @@
import com.google.idea.blaze.base.projectview.ProjectViewSet;
import com.google.idea.blaze.base.projectview.section.sections.BazelBinarySection;
import com.google.idea.blaze.base.qsync.BazelQueryRunner;
import com.google.idea.blaze.base.qsync.QuerySyncManager;
import com.google.idea.blaze.base.run.ExecutorType;
import com.google.idea.blaze.base.scope.BlazeContext;
import com.google.idea.blaze.base.settings.BlazeUserSettings;
import com.google.idea.blaze.base.settings.BuildBinaryType;
import com.google.idea.blaze.base.settings.BuildSystemName;
import com.google.idea.blaze.qsync.query.QuerySummaryProvider;
import com.intellij.openapi.project.Project;
import java.io.File;
import java.util.Optional;
Expand Down Expand Up @@ -115,6 +117,9 @@ public void populateBlazeVersionData(

@Override
public BazelQueryRunner createQueryRunner(Project project) {
return new BazelQueryRunner(project, this);
return new BazelQueryRunner(
project,
this,
new QuerySummaryProvider(QuerySyncManager.getInstance(project).getImplicitDepsProvider()));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
import com.google.idea.blaze.exception.BuildException;
import com.google.idea.blaze.qsync.query.QuerySpec;
import com.google.idea.blaze.qsync.query.QuerySummary;
import com.google.idea.blaze.qsync.query.QuerySummaryProvider;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.project.Project;
import java.io.IOException;
Expand All @@ -45,10 +46,13 @@ public class BazelQueryRunner implements QueryRunner {

private final Project project;
private final BuildSystem buildSystem;
private final QuerySummaryProvider querySummaryProvider;

public BazelQueryRunner(Project project, BuildSystem buildSystem) {
public BazelQueryRunner(
Project project, BuildSystem buildSystem, QuerySummaryProvider querySummaryProvider) {
this.project = project;
this.buildSystem = buildSystem;
this.querySummaryProvider = querySummaryProvider;
}

@Override
Expand Down Expand Up @@ -105,7 +109,7 @@ protected QuerySummary readFrom(InputStream in, BlazeContext context) throws Bui
logger.info(String.format("Summarising query from %s", in));
Instant start = Instant.now();
try {
QuerySummary summary = QuerySummary.create(in);
QuerySummary summary = querySummaryProvider.getSummary(in);
logger.info(
String.format(
"Summarised query in %ds", Duration.between(start, Instant.now()).toSeconds()));
Expand Down
3 changes: 2 additions & 1 deletion base/src/com/google/idea/blaze/base/qsync/ProjectLoader.java
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,8 @@ public QuerySyncProject loadProject(BlazeContext context) throws IOException {
createWorkspaceRelativePackageReader(),
vcsHandler.map(BlazeVcsHandler::getVcsStateDiffer).orElse(VcsStateDiffer.NONE),
workspaceRoot.path(),
graph::getCurrent);
graph::getCurrent,
QuerySyncManager.getInstance(project).getImplicitDepsProvider().getVersionWithName());
QueryRunner queryRunner = createQueryRunner(buildSystem);
ProjectQuerier projectQuerier = createProjectQuerier(projectRefresher, queryRunner, vcsHandler);
ProjectUpdater projectUpdater =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@
import com.google.idea.blaze.qsync.project.BlazeProjectSnapshot;
import com.google.idea.blaze.qsync.project.PostQuerySyncData;
import com.google.idea.blaze.qsync.project.ProjectDefinition;
import com.google.idea.blaze.qsync.query.ImplicitDepsProvider;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.vfs.VirtualFile;
Expand Down Expand Up @@ -304,4 +305,8 @@ private boolean projectDefinitionHasChanged() {
SaveUtil.saveAllFiles();
return !loadedProject.isDefinitionCurrent();
}

public ImplicitDepsProvider getImplicitDepsProvider() {
return ImplicitDepsProvider.EMPTY;
}
}
15 changes: 12 additions & 3 deletions querysync/java/com/google/idea/blaze/qsync/BlazeQueryParser.java
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,15 @@ public class BlazeQueryParser {
"java_stubby_library",
"aar_import");
private static final ImmutableSet<String> JAVA_RULE_TYPES =
ImmutableSet.of("java_library", "java_binary", "kt_jvm_library_helper", "java_test");
ImmutableSet.of(
"java_library",
"java_binary",
"kt_jvm_library_helper",
"java_proto_library",
"java_lite_proto_library",
"kt_proto_library_helper",
"java_test");

private static final ImmutableSet<String> ANDROID_RULE_TYPES =
ImmutableSet.of(
"android_library",
Expand Down Expand Up @@ -163,15 +171,16 @@ public BuildGraphData parse(QuerySummary query) {
targetSources.put(ruleEntry.getKey(), Label.of(ruleEntry.getValue().getManifest()));
}
}
} else if (ALWAYS_BUILD_RULE_TYPES.contains(ruleClass)) {
}
if (ALWAYS_BUILD_RULE_TYPES.contains(ruleClass)) {
projectTargetsToBuild.add(ruleEntry.getKey());
}
}
int nTargets = query.proto().getRulesCount();

// Calculate all the dependencies outside the project.
for (Label dep : deps) {
if (!ruleDeps.containsKey(dep)) {
if (!query.getRulesMap().containsKey(dep)) {
projectDeps.add(dep);
}
}
Expand Down
12 changes: 10 additions & 2 deletions querysync/java/com/google/idea/blaze/qsync/ProjectRefresher.java
Original file line number Diff line number Diff line change
Expand Up @@ -38,18 +38,21 @@ public class ProjectRefresher {
private final VcsStateDiffer vcsDiffer;
private final Path workspaceRoot;
private final Supplier<Optional<BlazeProjectSnapshot>> latestProjectSnapshotSupplier;
private final String implicitDepsVersion;

public ProjectRefresher(
ListeningExecutorService executor,
PackageReader workspaceRelativePackageReader,
VcsStateDiffer vcsDiffer,
Path workspaceRoot,
Supplier<Optional<BlazeProjectSnapshot>> latestProjectSnapshotSupplier) {
Supplier<Optional<BlazeProjectSnapshot>> latestProjectSnapshotSupplier,
String implicitDepsVerion) {
this.executor = executor;
this.workspaceRelativePackageReader = workspaceRelativePackageReader;
this.vcsDiffer = vcsDiffer;
this.workspaceRoot = workspaceRoot;
this.latestProjectSnapshotSupplier = latestProjectSnapshotSupplier;
this.implicitDepsVersion = implicitDepsVerion;
}

public FullProjectUpdate startFullUpdate(
Expand All @@ -72,7 +75,12 @@ public RefreshOperation startPartialRefresh(
ProjectDefinition latestProjectDefinition)
throws BuildException {
return startPartialRefresh(
new RefreshParameters(currentProject, latestVcsState, latestProjectDefinition, vcsDiffer),
new RefreshParameters(
currentProject,
latestVcsState,
latestProjectDefinition,
vcsDiffer,
implicitDepsVersion),
context);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,20 +40,23 @@ public class RefreshParameters {
final Optional<VcsState> latestVcsState;
final ProjectDefinition latestProjectDefinition;
final VcsStateDiffer vcsDiffer;
final String implicitDepsVersion;

RefreshParameters(
PostQuerySyncData currentProject,
Optional<VcsState> latestVcsState,
ProjectDefinition latestProjectDefinition,
VcsStateDiffer vcsDiffer) {
VcsStateDiffer vcsDiffer,
String implicitDepsVersion) {
this.currentProject = currentProject;
this.latestVcsState = latestVcsState;
this.latestProjectDefinition = latestProjectDefinition;
this.vcsDiffer = vcsDiffer;
this.implicitDepsVersion = implicitDepsVersion;
}

boolean requiresFullUpdate(Context<?> context) {
if (!currentProject.querySummary().isCompatibleWithCurrentPluginVersion()) {
if (!currentProject.querySummary().isCompatibleWithCurrentPluginVersion(implicitDepsVersion)) {
context.output(PrintOutput.output("IDE has updated since last sync; performing full query"));
return true;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
/*
* Copyright 2023 The Bazel Authors. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.idea.blaze.qsync.query;

import com.google.common.collect.ImmutableList;
import com.google.devtools.build.lib.query2.proto.proto2api.Build.Rule;

/**
* Interface for providing information about deps implicit for certain rules (e.g. runtime jars for
* proto java libraries).
*/
public interface ImplicitDepsProvider {
ImmutableList<String> forRule(Rule rule);

String name();

/**
* Version of the provider. If the provider implementation changes, the version should be changed
* to prevent possible errors during partial syncs.
*/
int version();

default String getVersionWithName() {
return String.format("%s:%d", name(), version());
}

ImplicitDepsProvider EMPTY =
new ImplicitDepsProvider() {

private static final int VERSION = 0;

@Override
public ImmutableList<String> forRule(Rule rule) {
return ImmutableList.of();
}

@Override
public String name() {
return "Default";
}

@Override
public int version() {
return VERSION;
}
};
}
Loading

0 comments on commit 598a5f7

Please sign in to comment.