Skip to content

Commit

Permalink
Allow to have non-existent import entries in projectview that point…
Browse files Browse the repository at this point in the history
…ing to … (#5689)

* Introduce `try_import` directive for project view files that allows to have non-existent entries in 
`projectview` that pointing to optional files missing for some of the users
  • Loading branch information
dkashyn-sfdc authored Dec 11, 2023
1 parent 76ff407 commit fec469b
Show file tree
Hide file tree
Showing 12 changed files with 126 additions and 9 deletions.
1 change: 1 addition & 0 deletions base/src/META-INF/blaze-base.xml
Original file line number Diff line number Diff line change
Expand Up @@ -360,6 +360,7 @@
<notificationGroup displayType="STICKY_BALLOON" id="QuerySyncPromo" />
<notificationGroup displayType="BALLOON" id="QuerySyncBuild" />
<registryKey defaultValue="false" description="Disable auto import of bazel projects" key="bazel.auto.import.disabled"/>
<registryKey defaultValue="false" description="Allow to have optional imports in project view" key="bazel.projectview.optional.imports"/>
<registryKey
key="bazel.sync.resolve.virtual.includes"
description="Apply heuristics to detect correct location of headers which are accessed from _virtual_includes during build"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,10 +52,12 @@ public <T> List<T> listItems(SectionKey<T, ListSection<T>> key) {
}

/** Returns all values from all scalar sections in the project views, in order */
public <T> List<T> listScalarItems(SectionKey<T, ScalarSection<T>> key) {
public <T> List<T> listScalarItems(SectionKey<T, ScalarSection<T>>... keys) {
List<T> result = Lists.newArrayList();
for (ScalarSection<T> section : getSections(key)) {
result.add(section.getValue());
for (SectionKey<T, ScalarSection<T>> key: keys) {
for (ScalarSection<T> section : getSections(key)) {
result.add(section.getValue());
}
}
return result;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,9 @@
import com.google.idea.blaze.base.projectview.section.ScalarSectionParser;
import com.google.idea.blaze.base.projectview.section.SectionKey;
import com.google.idea.blaze.base.projectview.section.SectionParser;
import com.google.idea.blaze.base.scope.output.IssueOutput;
import com.intellij.openapi.util.registry.Registry;

import java.io.File;
import javax.annotation.Nullable;

Expand All @@ -31,15 +34,25 @@ public class ImportSection {
SectionKey.of("import");
public static final SectionParser PARSER = new ImportSectionParser();

private static class ImportSectionParser extends ScalarSectionParser<WorkspacePath> {
protected static class ImportSectionParser extends ScalarSectionParser<WorkspacePath> {
public ImportSectionParser() {
super(KEY, ' ');
this(KEY, ' ');
}

protected ImportSectionParser(SectionKey<WorkspacePath, ScalarSection<WorkspacePath>> key, char divider) {
super(key, divider);
}

@Nullable
@Override
protected WorkspacePath parseItem(
ProjectViewParser parser, ParseContext parseContext, String text) {
boolean projectViewImportsMandatory = !Registry.is("bazel.projectview.optional.imports");
return parseItem(parser, parseContext, text, projectViewImportsMandatory);
}

@Nullable
protected static WorkspacePath parseItem(ProjectViewParser parser, ParseContext parseContext, String text, boolean projectViewImportsMandatory) {
String error = WorkspacePath.validate(text);
if (error != null) {
parseContext.addError(error);
Expand All @@ -50,7 +63,13 @@ protected WorkspacePath parseItem(
if (parser.isRecursive()) {
File projectViewFile = parseContext.getWorkspacePathResolver().resolveToFile(workspacePath);
if (projectViewFile != null) {
parser.parseProjectView(projectViewFile);
if (projectViewImportsMandatory || projectViewFile.exists()) {
parser.parseProjectView(projectViewFile);
} else {
IssueOutput.warn(
String.format("Could not load project view file: '%s'", projectViewFile.getPath()))
.submit(parseContext.getContext());
}
} else {
parseContext.addError("Could not resolve import: " + workspacePath);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ public class Sections {
Lists.newArrayList(
TextBlockSection.PARSER,
ImportSection.PARSER,
TryImportSection.PARSER,
DirectorySection.PARSER,
AutomaticallyDeriveTargetsSection.PARSER,
SyncManualTargetsSection.PARSER,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package com.google.idea.blaze.base.projectview.section.sections;

import com.google.idea.blaze.base.model.primitives.WorkspacePath;
import com.google.idea.blaze.base.projectview.parser.ParseContext;
import com.google.idea.blaze.base.projectview.parser.ProjectViewParser;
import com.google.idea.blaze.base.projectview.section.ScalarSection;
import com.google.idea.blaze.base.projectview.section.SectionKey;
import com.google.idea.blaze.base.projectview.section.SectionParser;

import javax.annotation.Nullable;

/** "try_import" section. */
public class TryImportSection extends ImportSection {

public static final SectionKey<WorkspacePath, ScalarSection<WorkspacePath>> KEY =
SectionKey.of("try_import");

public static final SectionParser PARSER = new TryImportSectionParser();

private static class TryImportSectionParser extends ImportSectionParser {

public TryImportSectionParser() {
super(KEY, ' ');
}

@Nullable
@Override
protected WorkspacePath parseItem(
ProjectViewParser parser, ParseContext parseContext, String text) {
return parseItem(parser, parseContext, text, false);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
import com.google.idea.blaze.base.model.primitives.WorkspacePath;
import com.google.idea.blaze.base.projectview.ProjectViewSet;
import com.google.idea.blaze.base.projectview.section.sections.ImportSection;
import com.google.idea.blaze.base.projectview.section.sections.TryImportSection;
import com.google.idea.blaze.common.Context;
import com.google.idea.blaze.qsync.BlazeProjectListener;
import com.google.idea.blaze.qsync.project.BlazeProjectSnapshot;
Expand Down Expand Up @@ -55,7 +56,7 @@ public void onNewProjectSnapshot(Context<?> context, BlazeProjectSnapshot instan
.getProjectInfoStatsBuilder()
.setLanguagesActive(instance.queryData().projectDefinition().languageClasses())
.setBlazeProjectFiles(
projectViewSet.listScalarItems(ImportSection.KEY).stream()
projectViewSet.listScalarItems(ImportSection.KEY, TryImportSection.KEY).stream()
.map(WorkspacePath::asPath)
.collect(toImmutableSet()));
scope
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@
import com.google.idea.blaze.base.projectview.ProjectViewManager;
import com.google.idea.blaze.base.projectview.ProjectViewSet;
import com.google.idea.blaze.base.projectview.section.sections.ImportSection;
import com.google.idea.blaze.base.projectview.section.sections.TryImportSection;
import com.google.idea.blaze.base.scope.BlazeContext;
import com.google.idea.blaze.base.scope.Scope;
import com.google.idea.blaze.base.scope.output.IssueOutput;
Expand Down Expand Up @@ -722,7 +723,7 @@ private static void fillInBuildStats(
.setWorkspaceType(projectState.getLanguageSettings().getWorkspaceType())
.setLanguagesActive(projectState.getLanguageSettings().getActiveLanguages())
.setBlazeProjectFiles(
projectState.getProjectViewSet().listScalarItems(ImportSection.KEY));
projectState.getProjectViewSet().listScalarItems(ImportSection.KEY, TryImportSection.KEY));
}
if (buildResult != null) {
buildResult
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@
import com.google.idea.blaze.base.projectview.section.sections.ImportSection;
import com.google.idea.blaze.base.projectview.section.sections.Sections;
import com.google.idea.blaze.base.projectview.section.sections.TargetSection;
import com.google.idea.blaze.base.projectview.section.sections.TryImportSection;
import com.google.idea.blaze.base.scope.BlazeContext;
import com.google.idea.blaze.base.scope.OutputSink.Propagation;
import com.google.idea.blaze.base.scope.Scope;
Expand Down Expand Up @@ -599,6 +600,9 @@ public void updateBuilder(BlazeNewProjectBuilder builder) {
.add(
ScalarSection.builder(ImportSection.KEY)
.set(selectProjectViewOption.getSharedProjectView()))
.add(
ScalarSection.builder(TryImportSection.KEY)
.set(selectProjectViewOption.getSharedProjectView()))
.build();
projectViewSet =
ProjectViewSet.builder()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,24 @@ public void testFileReference() {
assertThat(importItem.getReference().resolve()).isEqualTo(referencedFile);
}

@Test
public void testFileReferenceTryImport() {
PsiFile referencedFile =
workspace.createPsiFile(
new WorkspacePath("ijwb.bazelproject"),
"directories:",
" java/com/google/foo",
"targets:",
" //java/com/google/foo/...");
PsiFile file =
workspace.createPsiFile(new WorkspacePath(".bazelproject"), "try_import ijwb.bazelproject");

ProjectViewPsiSectionItem importItem =
PsiUtils.findFirstChildOfClassRecursive(file, ProjectViewPsiSectionItem.class);
assertThat(importItem).isNotNull();
assertThat(importItem.getReference().resolve()).isEqualTo(referencedFile);
}

@Test
public void testDirectoryReference() {
PsiDirectory directory = workspace.createPsiDirectory(new WorkspacePath("foo/bar"));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@
import com.google.idea.blaze.base.projectview.section.sections.TestSourceSection;
import com.google.idea.blaze.base.projectview.section.sections.TextBlock;
import com.google.idea.blaze.base.projectview.section.sections.TextBlockSection;
import com.google.idea.blaze.base.projectview.section.sections.TryImportSection;
import com.google.idea.blaze.base.projectview.section.sections.WorkspaceTypeSection;
import com.google.idea.blaze.base.sync.BlazeSyncPlugin;
import com.google.idea.common.experiments.ExperimentService;
Expand Down Expand Up @@ -85,6 +86,7 @@ public void testProjectViewSetSerializable() {
ListSection.builder(TargetSection.KEY)
.add(TargetExpression.fromStringSafe("//test:all")))
.add(ScalarSection.builder(ImportSection.KEY).set(new WorkspacePath("test")))
.add(ScalarSection.builder(TryImportSection.KEY).set(new WorkspacePath("test-optional")))
.add(ListSection.builder(TestSourceSection.KEY).add(new Glob("javatests/*")))
.add(ListSection.builder(ExcludedSourceSection.KEY).add(new Glob("*.java")))
.add(ListSection.builder(BuildFlagsSection.KEY).add("--android_sdk=abcd"))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
import com.google.idea.blaze.base.projectview.section.sections.TestSourceSection;
import com.google.idea.blaze.base.projectview.section.sections.TextBlock;
import com.google.idea.blaze.base.projectview.section.sections.TextBlockSection;
import com.google.idea.blaze.base.projectview.section.sections.TryImportSection;
import com.google.idea.blaze.base.projectview.section.sections.WorkspaceTypeSection;
import com.google.idea.blaze.base.scope.BlazeContext;
import com.google.idea.blaze.base.scope.ErrorCollector;
Expand All @@ -51,6 +52,9 @@
import java.util.Collection;
import java.util.Map;
import javax.annotation.Nullable;

import com.intellij.openapi.util.registry.Registry;
import com.intellij.openapi.util.registry.RegistryValue;
import org.jetbrains.annotations.NotNull;
import org.junit.Test;
import org.junit.runner.RunWith;
Expand Down Expand Up @@ -190,6 +194,9 @@ public void testPrint() {
.add(
ScalarSection.builder(ImportSection.KEY)
.set(new WorkspacePath("some/file.blazeproject")))
.add(
ScalarSection.builder(TryImportSection.KEY)
.set(new WorkspacePath("some/file.blazeproject.optional")))
.build();
String text = ProjectViewParser.projectViewToString(projectView);
assertThat(text)
Expand All @@ -202,7 +209,8 @@ public void testPrint() {
"targets:",
" //java/com/google:one",
" //java/com/google:two",
"import some/file.blazeproject"));
"import some/file.blazeproject",
"try_import some/file.blazeproject.optional"));
}

@Test
Expand Down Expand Up @@ -303,11 +311,34 @@ public void testCanParseWithMissingCarriageReturnAtEndOfSection() {

@Test
public void testImportMissingFileResultsInIssue() {
Registry.get("bazel.projectview.optional.imports").setValue(false);
projectViewStorageManager.add(".blazeproject", "import parent.blazeproject");
projectViewParser.parseProjectView(new File(".blazeproject"));
errorCollector.assertIssues("Could not load project view file: '/parent.blazeproject'");
}

@Test
public void testImportMissingFileResultsInWarning() {
RegistryValue importsTreatmentRegistryValue = Registry.get("bazel.projectview.optional.imports");
try {
importsTreatmentRegistryValue.setValue(true);
projectViewStorageManager.add(".blazeproject", "import parent.blazeproject");
projectViewParser.parseProjectView(new File(".blazeproject"));
errorCollector.assertIssues("Could not load project view file: '/parent.blazeproject'");
errorCollector.assertHasNoErrors();
} finally {
importsTreatmentRegistryValue.setValue(false);
}
}

@Test
public void testTryImportMissingFileResultsInWarning() {
projectViewStorageManager.add(".blazeproject", "try_import parent.blazeproject");
projectViewParser.parseProjectView(new File(".blazeproject"));
errorCollector.assertIssues("Could not load project view file: '/parent.blazeproject'");
errorCollector.assertHasNoErrors();
}

@Test
public void testMissingSectionResultsInIssue() {
projectViewStorageManager.add(".blazeproject", "nosuchsection:", " java/com/google");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,10 @@ public void assertHasErrors() {
assertThat(issues.stream().anyMatch(i -> i.getCategory() == Category.ERROR)).isTrue();
}

public void assertHasNoErrors() {
assertThat(issues.stream().anyMatch(i -> i.getCategory() == Category.ERROR)).isFalse();
}

public void assertIssues(String... requiredMessages) {
List<String> messages = Lists.newArrayList();
for (IssueOutput issue : issues) {
Expand Down

0 comments on commit fec469b

Please sign in to comment.