From 955b24ea6204b1d739bb9fb4ee95443dc1465639 Mon Sep 17 00:00:00 2001 From: Googler Date: Thu, 7 Mar 2024 05:20:45 -0800 Subject: [PATCH] Add compiled artifact class jars to the project proto. This implements support for basic java deps with the new artifact tracker, and also adds appropriate support for more types of artifact in the future: - `ProjectProtoUpdate` is a helper class for making updates to the prooject proto, providing simpler access to the `.workspace` module and the like. - `ArtifactDirectoryBuilder` helps to construct an `ArtifactDirectoryContents` proto message and provides paths to the final artifact desinations for adding to other parts of the project proto. - `DependenciesProjectProtoUpdater` to hook this into the existing `ProjectProtoTransform`.i PiperOrigin-RevId: 613549386 --- .../idea/blaze/base/qsync/ProjectLoader.java | 2 + .../blaze/qsync/GraphToProjectConverter.java | 5 +- .../blaze/qsync/deps/AddCompiledJavaDeps.java | 54 ++++++++ .../qsync/deps/ArtifactDirectoryBuilder.java | 127 ++++++++++++++++++ .../com/google/idea/blaze/qsync/deps/BUILD | 3 + .../deps/DependenciesProjectProtoUpdater.java | 49 +++++++ .../blaze/qsync/deps/ProjectProtoUpdate.java | 90 +++++++++++++ .../deps/ProjectProtoUpdateOperation.java | 31 +++++ .../blaze/qsync/java/JavaArtifactInfo.java | 2 + .../blaze/qsync/GraphToProjectConverters.java | 3 +- .../idea/blaze/qsync/TestDataSyncRunner.java | 4 +- .../qsync/deps/AddCompiledJavaDepsTest.java | 103 ++++++++++++++ .../com/google/idea/blaze/qsync/deps/BUILD | 20 +++ .../blaze/qsync/testdata/ProjectProtos.java | 14 +- 14 files changed, 500 insertions(+), 7 deletions(-) create mode 100644 querysync/java/com/google/idea/blaze/qsync/deps/AddCompiledJavaDeps.java create mode 100644 querysync/java/com/google/idea/blaze/qsync/deps/ArtifactDirectoryBuilder.java create mode 100644 querysync/java/com/google/idea/blaze/qsync/deps/DependenciesProjectProtoUpdater.java create mode 100644 querysync/java/com/google/idea/blaze/qsync/deps/ProjectProtoUpdate.java create mode 100644 querysync/java/com/google/idea/blaze/qsync/deps/ProjectProtoUpdateOperation.java create mode 100644 querysync/javatests/com/google/idea/blaze/qsync/deps/AddCompiledJavaDepsTest.java diff --git a/base/src/com/google/idea/blaze/base/qsync/ProjectLoader.java b/base/src/com/google/idea/blaze/base/qsync/ProjectLoader.java index 20ddc85426f..688deeccf3b 100644 --- a/base/src/com/google/idea/blaze/base/qsync/ProjectLoader.java +++ b/base/src/com/google/idea/blaze/base/qsync/ProjectLoader.java @@ -53,6 +53,7 @@ import com.google.idea.blaze.qsync.ProjectRefresher; import com.google.idea.blaze.qsync.VcsStateDiffer; import com.google.idea.blaze.qsync.deps.ArtifactTracker; +import com.google.idea.blaze.qsync.deps.DependenciesProjectProtoUpdater; import com.google.idea.blaze.qsync.deps.NewArtifactTracker; import com.google.idea.blaze.qsync.java.PackageStatementParser; import com.google.idea.blaze.qsync.java.ParallelPackageReader; @@ -154,6 +155,7 @@ public QuerySyncProject loadProject(BlazeContext context) throws BuildException NewArtifactTracker tracker = new NewArtifactTracker<>( BlazeDataStorage.getProjectDataDir(importSettings).toPath(), artifactCache); + projectTransformRegistry.add(new DependenciesProjectProtoUpdater(tracker)); artifactTracker = tracker; renderJarArtifactTracker = new RenderJarArtifactTrackerImpl(); diff --git a/querysync/java/com/google/idea/blaze/qsync/GraphToProjectConverter.java b/querysync/java/com/google/idea/blaze/qsync/GraphToProjectConverter.java index ba41d5cd790..6126445f82e 100644 --- a/querysync/java/com/google/idea/blaze/qsync/GraphToProjectConverter.java +++ b/querysync/java/com/google/idea/blaze/qsync/GraphToProjectConverter.java @@ -114,7 +114,8 @@ public GraphToProjectConverter( Predicate fileExistenceCheck, Context context, ProjectDefinition projectDefinition, - ListeningExecutorService executor) { + ListeningExecutorService executor, + boolean useNewBuildArtifactLogic) { this.packageReader = packageReader; this.fileExistenceCheck = fileExistenceCheck; this.context = context; @@ -122,7 +123,7 @@ public GraphToProjectConverter( this.executor = executor; this.useNewResDirLogic = Suppliers.ofInstance(true); this.guessAndroidResPackages = Suppliers.ofInstance(false); - this.useNewBuildArtifactLogic = false; + this.useNewBuildArtifactLogic = useNewBuildArtifactLogic; } /** diff --git a/querysync/java/com/google/idea/blaze/qsync/deps/AddCompiledJavaDeps.java b/querysync/java/com/google/idea/blaze/qsync/deps/AddCompiledJavaDeps.java new file mode 100644 index 00000000000..ea100aa9d5c --- /dev/null +++ b/querysync/java/com/google/idea/blaze/qsync/deps/AddCompiledJavaDeps.java @@ -0,0 +1,54 @@ +/* + * Copyright 2024 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.deps; + +import com.google.common.base.Supplier; +import com.google.common.collect.ImmutableCollection; +import com.google.idea.blaze.qsync.artifacts.BuildArtifact; +import com.google.idea.blaze.qsync.java.JavaArtifactInfo; +import com.google.idea.blaze.qsync.project.ProjectProto.JarDirectory; +import java.nio.file.Path; + +/** Adds compiled jars from dependencies to the project. */ +public class AddCompiledJavaDeps implements ProjectProtoUpdateOperation { + private final Supplier> builtTargetsSupplier; + + public AddCompiledJavaDeps(Supplier> builtTargetsSupplier) { + this.builtTargetsSupplier = builtTargetsSupplier; + } + + @Override + public void update(ProjectProtoUpdate update) { + ArtifactDirectoryBuilder javaDepsDir = update.artifactDirectory(Path.of("javadeps")); + for (TargetBuildInfo target : builtTargetsSupplier.get()) { + if (target.javaInfo().isPresent()) { + JavaArtifactInfo javaInfo = target.javaInfo().get(); + for (BuildArtifact jar : javaInfo.jars()) { + javaDepsDir.addIfNewer(jar.path(), jar, target.buildContext()); + } + } + } + if (!javaDepsDir.isEmpty()) { + update + .library(JAVA_DEPS_LIB_NAME) + .addClassesJar( + JarDirectory.newBuilder().setPath(javaDepsDir.path().toString()).setRecursive(true)); + if (!update.workspaceModule().getLibraryNameList().contains(JAVA_DEPS_LIB_NAME)) { + update.workspaceModule().addLibraryName(JAVA_DEPS_LIB_NAME); + } + } + } +} diff --git a/querysync/java/com/google/idea/blaze/qsync/deps/ArtifactDirectoryBuilder.java b/querysync/java/com/google/idea/blaze/qsync/deps/ArtifactDirectoryBuilder.java new file mode 100644 index 00000000000..077d996e202 --- /dev/null +++ b/querysync/java/com/google/idea/blaze/qsync/deps/ArtifactDirectoryBuilder.java @@ -0,0 +1,127 @@ +/* + * Copyright 2024 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.deps; + +import static com.google.common.collect.ImmutableMap.toImmutableMap; + +import com.google.auto.value.AutoValue; +import com.google.common.base.Preconditions; +import com.google.common.collect.Maps; +import com.google.errorprone.annotations.CanIgnoreReturnValue; +import com.google.idea.blaze.qsync.artifacts.BuildArtifact; +import com.google.idea.blaze.qsync.project.ProjectPath; +import com.google.idea.blaze.qsync.project.ProjectPath.Root; +import com.google.idea.blaze.qsync.project.ProjectProto; +import com.google.idea.blaze.qsync.project.ProjectProto.ProjectArtifact.ArtifactTransform; +import java.nio.file.Path; +import java.util.Map; +import java.util.Optional; + +/** Populates a {@link ProjectProto.ArtifactDirectoryContents} proto from build artifacts. */ +public class ArtifactDirectoryBuilder { + + @AutoValue + abstract static class Entry { + + abstract String destination(); + + abstract BuildArtifact source(); + + abstract DependencyBuildContext fromBuild(); + + abstract ArtifactTransform transform(); + + static Entry create( + Path destination, + BuildArtifact source, + DependencyBuildContext fromBuild, + ArtifactTransform transform) { + return new AutoValue_ArtifactDirectoryBuilder_Entry( + destination.toString(), source, fromBuild, transform); + } + + ProjectProto.ProjectArtifact toProto() { + return ProjectProto.ProjectArtifact.newBuilder() + .setBuildArtifact( + ProjectProto.BuildArtifact.newBuilder().setDigest(source().digest()).build()) + .setTransform(transform()) + .build(); + } + } + + private final Path path; + private final Map contents = Maps.newHashMap(); + + /** + * @param relativePath Project directory relative path of the destination directory. + */ + public ArtifactDirectoryBuilder(Path relativePath) { + Preconditions.checkState( + !relativePath.isAbsolute(), "Expected a relative path: " + relativePath); + this.path = relativePath; + } + + /** + * @return Project directory relative path of the destination directory. + */ + public Path path() { + return path; + } + + /** + * @return This directories root as a project path. + */ + public ProjectPath root() { + return ProjectPath.projectRelative(path()); + } + + /** + * Adds a new artifact to the directory is it is not already present, or was produced by a more + * recent build that an existing artifact at the same location. + * + * @param relativePath Path to place the artifact at, relative to {@link #root()}. + * @param source The artifact to put there. + * @param fromBuild The build that produced the artifact. + * @return The path to the final artifact, if it was added. + */ + @CanIgnoreReturnValue + public Optional addIfNewer( + Path relativePath, BuildArtifact source, DependencyBuildContext fromBuild) { + Entry existing = contents.get(relativePath); + if (existing != null && existing.fromBuild().startTime().isAfter(fromBuild.startTime())) { + // we already have the same artifact from a more recent build. + return Optional.empty(); + } + Entry e = Entry.create(relativePath, source, fromBuild, ArtifactTransform.COPY); + contents.put(relativePath, e); + return Optional.of(ProjectPath.create(Root.PROJECT, path.resolve(relativePath))); + } + + public boolean isEmpty() { + return contents.isEmpty(); + } + + public ProjectProto.ArtifactDirectoryContents toProto() { + return ProjectProto.ArtifactDirectoryContents.newBuilder() + .putAllContents( + contents.values().stream().collect(toImmutableMap(Entry::destination, Entry::toProto))) + .build(); + } + + public void addTo(ProjectProto.ArtifactDirectories.Builder directories) { + directories.putDirectories(path.toString(), toProto()); + } +} diff --git a/querysync/java/com/google/idea/blaze/qsync/deps/BUILD b/querysync/java/com/google/idea/blaze/qsync/deps/BUILD index bb8bec91fcf..110e459714f 100644 --- a/querysync/java/com/google/idea/blaze/qsync/deps/BUILD +++ b/querysync/java/com/google/idea/blaze/qsync/deps/BUILD @@ -7,11 +7,13 @@ java_library( ], deps = [ ":artifact_tracker_state_java_proto", + "//querysync/java/com/google/idea/blaze/qsync", "//querysync/java/com/google/idea/blaze/qsync/artifacts", "//querysync/java/com/google/idea/blaze/qsync/cc:cc_compilation_info_java_proto", "//querysync/java/com/google/idea/blaze/qsync/java", "//querysync/java/com/google/idea/blaze/qsync/java:java_target_info_java_proto", "//querysync/java/com/google/idea/blaze/qsync/project", + "//querysync/java/com/google/idea/blaze/qsync/project:project_java_proto", "//shared", "//shared:artifact", "//shared:proto", @@ -19,6 +21,7 @@ java_library( "//third_party/auto_value", "@com_google_guava_guava//jar", "@com_google_protobuf//:protobuf_java", + "@jsr305_annotations//jar", ], ) diff --git a/querysync/java/com/google/idea/blaze/qsync/deps/DependenciesProjectProtoUpdater.java b/querysync/java/com/google/idea/blaze/qsync/deps/DependenciesProjectProtoUpdater.java new file mode 100644 index 00000000000..9fc499003ac --- /dev/null +++ b/querysync/java/com/google/idea/blaze/qsync/deps/DependenciesProjectProtoUpdater.java @@ -0,0 +1,49 @@ +/* + * Copyright 2024 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.deps; + +import com.google.common.collect.ImmutableList; +import com.google.idea.blaze.common.Context; +import com.google.idea.blaze.exception.BuildException; +import com.google.idea.blaze.qsync.ProjectProtoTransform; +import com.google.idea.blaze.qsync.project.BuildGraphData; +import com.google.idea.blaze.qsync.project.ProjectProto.Project; + +/** + * A {@link ProjectProtoTransform} that adds built artifact information to the project proto, based + * on all artifacts that have been built. + */ +public class DependenciesProjectProtoUpdater implements ProjectProtoTransform { + private final ImmutableList updateOperations; + + public DependenciesProjectProtoUpdater(NewArtifactTracker dependencyTracker) { + ImmutableList.Builder updateOperations = + ImmutableList.builder() + .add(new AddCompiledJavaDeps(dependencyTracker::getBuiltDeps)); + this.updateOperations = updateOperations.build(); + } + + @Override + public Project apply(Project proto, BuildGraphData graph, Context context) + throws BuildException { + + ProjectProtoUpdate protoUpdate = new ProjectProtoUpdate(proto); + for (ProjectProtoUpdateOperation op : updateOperations) { + op.update(protoUpdate); + } + return protoUpdate.build(); + } +} diff --git a/querysync/java/com/google/idea/blaze/qsync/deps/ProjectProtoUpdate.java b/querysync/java/com/google/idea/blaze/qsync/deps/ProjectProtoUpdate.java new file mode 100644 index 00000000000..98a6986ff2a --- /dev/null +++ b/querysync/java/com/google/idea/blaze/qsync/deps/ProjectProtoUpdate.java @@ -0,0 +1,90 @@ +/* + * Copyright 2024 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.deps; + +import com.google.common.collect.Maps; +import com.google.idea.blaze.qsync.project.BlazeProjectDataStorage; +import com.google.idea.blaze.qsync.project.ProjectProto; +import com.google.idea.blaze.qsync.project.ProjectProto.Library; +import java.nio.file.Path; +import java.util.Map; +import java.util.Optional; + +/** + * Helper class for making a number of updates to the project proto. + * + *

This class provides a convenient way of accessing and updating various interesting parts of + * the project proto, such as the {@code .workspace} module and libraries by name. + */ +public class ProjectProtoUpdate { + + private final ProjectProto.Project.Builder project; + private final ProjectProto.Module.Builder workspaceModule; + private final Map libraries = Maps.newHashMap(); + private final Map artifactDirs = Maps.newHashMap(); + + public ProjectProtoUpdate(ProjectProto.Project existingProject) { + this.project = existingProject.toBuilder(); + this.workspaceModule = getWorkspaceModuleBuilder(project); + } + + private static ProjectProto.Module.Builder getWorkspaceModuleBuilder( + ProjectProto.Project.Builder project) { + for (int i = 0; i < project.getModulesCount(); i++) { + if (project.getModules(i).getName().equals(BlazeProjectDataStorage.WORKSPACE_MODULE_NAME)) { + return project.getModulesBuilder(i); + } + } + throw new IllegalArgumentException( + "Module with name " + + BlazeProjectDataStorage.WORKSPACE_MODULE_NAME + + " not found in project proto."); + } + + public ProjectProto.Project.Builder project() { + return project; + } + + public ProjectProto.Module.Builder workspaceModule() { + return workspaceModule; + } + + /** Gets a builder for a library, creating it if it doesn't already exist. */ + public ProjectProto.Library.Builder library(String name) { + if (!libraries.containsKey(name)) { + Optional existingProto = + project.getLibraryBuilderList().stream() + .filter(l -> l.getName().equals(name)) + .findFirst(); + + if (existingProto.isPresent()) { + libraries.put(name, existingProto.get()); + } else { + libraries.put(name, project.addLibraryBuilder().setName(name)); + } + } + return libraries.get(name); + } + + public ArtifactDirectoryBuilder artifactDirectory(Path relativePath) { + return artifactDirs.computeIfAbsent(relativePath, ArtifactDirectoryBuilder::new); + } + + public ProjectProto.Project build() { + artifactDirs.values().forEach(d -> d.addTo(project.getArtifactDirectoriesBuilder())); + return project.build(); + } +} diff --git a/querysync/java/com/google/idea/blaze/qsync/deps/ProjectProtoUpdateOperation.java b/querysync/java/com/google/idea/blaze/qsync/deps/ProjectProtoUpdateOperation.java new file mode 100644 index 00000000000..38919a7c9d8 --- /dev/null +++ b/querysync/java/com/google/idea/blaze/qsync/deps/ProjectProtoUpdateOperation.java @@ -0,0 +1,31 @@ +/* + * Copyright 2024 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.deps; + +import com.google.common.collect.ImmutableSet; +import com.google.idea.blaze.exception.BuildException; + +/** + * An update to the project proto that operates on a {@link ProjectProtoUpdate}. Also defines some + * constants that are useful to implementations. + */ +public interface ProjectProtoUpdateOperation { + + String JAVA_DEPS_LIB_NAME = ".dependencies"; + ImmutableSet JAVA_ARCHIVE_EXTENSIONS = ImmutableSet.of("jar", "srcjar"); + + void update(ProjectProtoUpdate update) throws BuildException; +} diff --git a/querysync/java/com/google/idea/blaze/qsync/java/JavaArtifactInfo.java b/querysync/java/com/google/idea/blaze/qsync/java/JavaArtifactInfo.java index 321fee571fb..25856f5d008 100644 --- a/querysync/java/com/google/idea/blaze/qsync/java/JavaArtifactInfo.java +++ b/querysync/java/com/google/idea/blaze/qsync/java/JavaArtifactInfo.java @@ -64,6 +64,8 @@ public abstract class JavaArtifactInfo { public abstract String androidResourcesPackage(); + public abstract Builder toBuilder(); + public static Builder builder() { return new AutoValue_JavaArtifactInfo.Builder(); } diff --git a/querysync/javatests/com/google/idea/blaze/qsync/GraphToProjectConverters.java b/querysync/javatests/com/google/idea/blaze/qsync/GraphToProjectConverters.java index d1ecc6f6637..acd635ca63f 100644 --- a/querysync/javatests/com/google/idea/blaze/qsync/GraphToProjectConverters.java +++ b/querysync/javatests/com/google/idea/blaze/qsync/GraphToProjectConverters.java @@ -80,7 +80,8 @@ public GraphToProjectConverter build() { info.projectExcludes(), info.languageClasses(), info.testSources()), - newDirectExecutorService()); + newDirectExecutorService(), + false); } } } diff --git a/querysync/javatests/com/google/idea/blaze/qsync/TestDataSyncRunner.java b/querysync/javatests/com/google/idea/blaze/qsync/TestDataSyncRunner.java index f4185f9e997..273ce4b5cd9 100644 --- a/querysync/javatests/com/google/idea/blaze/qsync/TestDataSyncRunner.java +++ b/querysync/javatests/com/google/idea/blaze/qsync/TestDataSyncRunner.java @@ -41,7 +41,6 @@ public class TestDataSyncRunner { private final Context context; private final PackageReader packageReader; - public TestDataSyncRunner(Context context, PackageReader packageReader) { this.context = context; this.packageReader = packageReader; @@ -69,7 +68,8 @@ public BlazeProjectSnapshot sync(TestData testProject) throws IOException, Build Predicates.alwaysTrue(), context, projectDefinition, - newDirectExecutorService()); + newDirectExecutorService(), + false); Project project = converter.createProject(buildGraphData); return BlazeProjectSnapshot.builder() .queryData(pqsd) diff --git a/querysync/javatests/com/google/idea/blaze/qsync/deps/AddCompiledJavaDepsTest.java b/querysync/javatests/com/google/idea/blaze/qsync/deps/AddCompiledJavaDepsTest.java new file mode 100644 index 00000000000..cee57dc8ef6 --- /dev/null +++ b/querysync/javatests/com/google/idea/blaze/qsync/deps/AddCompiledJavaDepsTest.java @@ -0,0 +1,103 @@ +/* + * Copyright 2024 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.deps; + +import static com.google.common.truth.Truth.assertThat; + +import com.google.common.collect.ImmutableList; +import com.google.idea.blaze.common.Label; +import com.google.idea.blaze.qsync.artifacts.BuildArtifact; +import com.google.idea.blaze.qsync.java.JavaArtifactInfo; +import com.google.idea.blaze.qsync.project.ProjectProto; +import com.google.idea.blaze.qsync.project.ProjectProto.ProjectArtifact.ArtifactTransform; +import com.google.idea.blaze.qsync.testdata.ProjectProtos; +import com.google.idea.blaze.qsync.testdata.TestData; +import java.nio.file.Path; +import java.time.Instant; +import java.util.Optional; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +@RunWith(JUnit4.class) +public class AddCompiledJavaDepsTest { + + @Test + public void no_deps_built() throws Exception { + ProjectProto.Project original = + ProjectProtos.forTestProjectWithNewArtifactLogic(TestData.JAVA_LIBRARY_EXTERNAL_DEP_QUERY); + + AddCompiledJavaDeps javaDeps = new AddCompiledJavaDeps(() -> ImmutableList.of()); + + ProjectProtoUpdate update = new ProjectProtoUpdate(original); + javaDeps.update(update); + ProjectProto.Project newProject = update.build(); + assertThat(newProject.getLibraryList()).isEqualTo(original.getLibraryList()); + assertThat(newProject.getModulesList()).isEqualTo(original.getModulesList()); + assertThat(newProject.getArtifactDirectories().getDirectoriesMap().keySet()) + .containsExactly("javadeps"); + assertThat( + newProject + .getArtifactDirectories() + .getDirectoriesMap() + .get("javadeps") + .getContentsMap()) + .isEmpty(); + } + + @Test + public void dep_built() throws Exception { + ProjectProto.Project original = + ProjectProtos.forTestProjectWithNewArtifactLogic(TestData.JAVA_LIBRARY_EXTERNAL_DEP_QUERY); + + TargetBuildInfo builtDep = + TargetBuildInfo.forJavaTarget( + JavaArtifactInfo.empty(Label.of("@com_google_guava_guava//jar:jar")).toBuilder() + .setJars( + ImmutableList.of( + BuildArtifact.create( + "jardigest", + Path.of("build-out/java/com/google/common/collect/libcollect.jar"), + Label.of("@com_google_guava_guava//jar:jar")))) + .build(), + DependencyBuildContext.create("abc-def", Instant.now(), Optional.empty())); + + AddCompiledJavaDeps javaDeps = new AddCompiledJavaDeps(() -> ImmutableList.of(builtDep)); + + ProjectProtoUpdate update = new ProjectProtoUpdate(original); + javaDeps.update(update); + ProjectProto.Project newProject = update.build(); + assertThat(newProject.getLibraryList()).hasSize(1); + assertThat(newProject.getLibrary(0).getName()).isEqualTo(".dependencies"); + assertThat(newProject.getLibrary(0).getClassesJarList()) + .containsExactly( + ProjectProto.JarDirectory.newBuilder().setPath("javadeps").setRecursive(true).build()); + assertThat(newProject.getArtifactDirectories().getDirectoriesMap().keySet()) + .containsExactly("javadeps"); + assertThat( + newProject + .getArtifactDirectories() + .getDirectoriesMap() + .get("javadeps") + .getContentsMap()) + .containsExactly( + "build-out/java/com/google/common/collect/libcollect.jar", + ProjectProto.ProjectArtifact.newBuilder() + .setBuildArtifact(ProjectProto.BuildArtifact.newBuilder().setDigest("jardigest")) + .setTransform(ArtifactTransform.COPY) + .build()); + } +} diff --git a/querysync/javatests/com/google/idea/blaze/qsync/deps/BUILD b/querysync/javatests/com/google/idea/blaze/qsync/deps/BUILD index 47189cc0d7a..406b6339fb4 100644 --- a/querysync/javatests/com/google/idea/blaze/qsync/deps/BUILD +++ b/querysync/javatests/com/google/idea/blaze/qsync/deps/BUILD @@ -39,3 +39,23 @@ java_test( "@truth//jar", ], ) + +java_test( + name = "AddCompiledJavaDepsTest", + size = "small", + srcs = ["AddCompiledJavaDepsTest.java"], + deps = [ + "//querysync/java/com/google/idea/blaze/qsync/artifacts", + "//querysync/java/com/google/idea/blaze/qsync/deps", + "//querysync/java/com/google/idea/blaze/qsync/java", + "//querysync/java/com/google/idea/blaze/qsync/project:project_java_proto", + "//querysync/javatests/com/google/idea/blaze/qsync:TestUtils", + "//querysync/javatests/com/google/idea/blaze/qsync/testdata", + "//querysync/javatests/com/google/idea/blaze/qsync/testdata:project_protos", + "//shared", + "//shared/javatests/com/google/idea/blaze/common:test_utils", + "@com_google_guava_guava//jar", + "@junit//jar", + "@truth//jar", + ], +) diff --git a/querysync/javatests/com/google/idea/blaze/qsync/testdata/ProjectProtos.java b/querysync/javatests/com/google/idea/blaze/qsync/testdata/ProjectProtos.java index 2e3a00b0565..1997bfc503b 100644 --- a/querysync/javatests/com/google/idea/blaze/qsync/testdata/ProjectProtos.java +++ b/querysync/javatests/com/google/idea/blaze/qsync/testdata/ProjectProtos.java @@ -40,6 +40,16 @@ public class ProjectProtos { private ProjectProtos() {} public static Project forTestProject(TestData project) throws IOException, BuildException { + return create(project, false); + } + + public static Project forTestProjectWithNewArtifactLogic(TestData project) + throws IOException, BuildException { + return create(project, true); + } + + private static Project create(TestData project, boolean useNewArtifactLogic) + throws IOException, BuildException { Path workspaceImportDirectory = project.getQueryOutputPath(); GraphToProjectConverter converter = new GraphToProjectConverter( @@ -51,8 +61,8 @@ public static Project forTestProject(TestData project) throws IOException, Build ImmutableSet.of(), ImmutableSet.of(QuerySyncLanguage.JAVA), ImmutableSet.of()), - newDirectExecutorService()); - + newDirectExecutorService(), + useNewArtifactLogic); return converter.createProject(BuildGraphs.forTestProject(project)); } }