diff --git a/base/src/META-INF/blaze-base.xml b/base/src/META-INF/blaze-base.xml
index 6554b37379e..43036e9c301 100644
--- a/base/src/META-INF/blaze-base.xml
+++ b/base/src/META-INF/blaze-base.xml
@@ -360,6 +360,7 @@
+
List listItems(SectionKey> key) {
}
/** Returns all values from all scalar sections in the project views, in order */
- public List listScalarItems(SectionKey> key) {
+ public List listScalarItems(SectionKey>... keys) {
List result = Lists.newArrayList();
- for (ScalarSection section : getSections(key)) {
- result.add(section.getValue());
+ for (SectionKey> key: keys) {
+ for (ScalarSection section : getSections(key)) {
+ result.add(section.getValue());
+ }
}
return result;
}
diff --git a/base/src/com/google/idea/blaze/base/projectview/section/sections/ImportSection.java b/base/src/com/google/idea/blaze/base/projectview/section/sections/ImportSection.java
index 4b6a47a86f8..11d4dc5d022 100644
--- a/base/src/com/google/idea/blaze/base/projectview/section/sections/ImportSection.java
+++ b/base/src/com/google/idea/blaze/base/projectview/section/sections/ImportSection.java
@@ -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;
@@ -31,15 +34,25 @@ public class ImportSection {
SectionKey.of("import");
public static final SectionParser PARSER = new ImportSectionParser();
- private static class ImportSectionParser extends ScalarSectionParser {
+ protected static class ImportSectionParser extends ScalarSectionParser {
public ImportSectionParser() {
- super(KEY, ' ');
+ this(KEY, ' ');
+ }
+
+ protected ImportSectionParser(SectionKey> 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);
@@ -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);
}
diff --git a/base/src/com/google/idea/blaze/base/projectview/section/sections/Sections.java b/base/src/com/google/idea/blaze/base/projectview/section/sections/Sections.java
index 1d73508f256..5aea4db980c 100644
--- a/base/src/com/google/idea/blaze/base/projectview/section/sections/Sections.java
+++ b/base/src/com/google/idea/blaze/base/projectview/section/sections/Sections.java
@@ -28,6 +28,7 @@ public class Sections {
Lists.newArrayList(
TextBlockSection.PARSER,
ImportSection.PARSER,
+ TryImportSection.PARSER,
DirectorySection.PARSER,
AutomaticallyDeriveTargetsSection.PARSER,
SyncManualTargetsSection.PARSER,
diff --git a/base/src/com/google/idea/blaze/base/projectview/section/sections/TryImportSection.java b/base/src/com/google/idea/blaze/base/projectview/section/sections/TryImportSection.java
new file mode 100644
index 00000000000..76cb76e2fd5
--- /dev/null
+++ b/base/src/com/google/idea/blaze/base/projectview/section/sections/TryImportSection.java
@@ -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> 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);
+ }
+ }
+}
diff --git a/base/src/com/google/idea/blaze/base/qsync/ProjectStatsLogger.java b/base/src/com/google/idea/blaze/base/qsync/ProjectStatsLogger.java
index 5f06b14f13e..1b70e5e51cd 100644
--- a/base/src/com/google/idea/blaze/base/qsync/ProjectStatsLogger.java
+++ b/base/src/com/google/idea/blaze/base/qsync/ProjectStatsLogger.java
@@ -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;
@@ -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
diff --git a/base/src/com/google/idea/blaze/base/sync/SyncPhaseCoordinator.java b/base/src/com/google/idea/blaze/base/sync/SyncPhaseCoordinator.java
index 48453fb3d69..61f2830d3d8 100644
--- a/base/src/com/google/idea/blaze/base/sync/SyncPhaseCoordinator.java
+++ b/base/src/com/google/idea/blaze/base/sync/SyncPhaseCoordinator.java
@@ -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;
@@ -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
diff --git a/base/src/com/google/idea/blaze/base/wizard2/ui/BlazeEditProjectViewControl.java b/base/src/com/google/idea/blaze/base/wizard2/ui/BlazeEditProjectViewControl.java
index a4174cb65ee..4630fdff3bc 100644
--- a/base/src/com/google/idea/blaze/base/wizard2/ui/BlazeEditProjectViewControl.java
+++ b/base/src/com/google/idea/blaze/base/wizard2/ui/BlazeEditProjectViewControl.java
@@ -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;
@@ -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()
diff --git a/base/tests/integrationtests/com/google/idea/blaze/base/lang/projectview/references/ProjectViewLabelReferenceTest.java b/base/tests/integrationtests/com/google/idea/blaze/base/lang/projectview/references/ProjectViewLabelReferenceTest.java
index 179bd57a506..f16dd98054b 100644
--- a/base/tests/integrationtests/com/google/idea/blaze/base/lang/projectview/references/ProjectViewLabelReferenceTest.java
+++ b/base/tests/integrationtests/com/google/idea/blaze/base/lang/projectview/references/ProjectViewLabelReferenceTest.java
@@ -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"));
diff --git a/base/tests/unittests/com/google/idea/blaze/base/projectview/ProjectViewSetTest.java b/base/tests/unittests/com/google/idea/blaze/base/projectview/ProjectViewSetTest.java
index 6f7c4aa71d8..32d95c4e975 100644
--- a/base/tests/unittests/com/google/idea/blaze/base/projectview/ProjectViewSetTest.java
+++ b/base/tests/unittests/com/google/idea/blaze/base/projectview/ProjectViewSetTest.java
@@ -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;
@@ -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"))
diff --git a/base/tests/unittests/com/google/idea/blaze/base/projectview/parser/ProjectViewParserTest.java b/base/tests/unittests/com/google/idea/blaze/base/projectview/parser/ProjectViewParserTest.java
index 80158007c6c..90313950d2b 100644
--- a/base/tests/unittests/com/google/idea/blaze/base/projectview/parser/ProjectViewParserTest.java
+++ b/base/tests/unittests/com/google/idea/blaze/base/projectview/parser/ProjectViewParserTest.java
@@ -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;
@@ -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;
@@ -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)
@@ -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
@@ -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");
diff --git a/base/tests/utils/unit/com/google/idea/blaze/base/scope/ErrorCollector.java b/base/tests/utils/unit/com/google/idea/blaze/base/scope/ErrorCollector.java
index 9283e7d9d52..e3e02b8e9a8 100644
--- a/base/tests/utils/unit/com/google/idea/blaze/base/scope/ErrorCollector.java
+++ b/base/tests/utils/unit/com/google/idea/blaze/base/scope/ErrorCollector.java
@@ -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 messages = Lists.newArrayList();
for (IssueOutput issue : issues) {