diff --git a/WORKSPACE b/WORKSPACE
index e9843d37675..ca9f4e14537 100644
--- a/WORKSPACE
+++ b/WORKSPACE
@@ -83,7 +83,6 @@ http_archive(
url = IC_233_URL,
)
-
# The plugin api for IntelliJ UE 2021.2. This is required to run UE-specific
# integration tests.
http_archive(
diff --git a/base/src/META-INF/blaze-base.xml b/base/src/META-INF/blaze-base.xml
index 4591042bbbc..69813037d2a 100644
--- a/base/src/META-INF/blaze-base.xml
+++ b/base/src/META-INF/blaze-base.xml
@@ -234,6 +234,7 @@
+
@@ -571,6 +572,7 @@
+
diff --git a/base/src/com/google/idea/blaze/base/lang/buildfile/completion/BuildLookupElement.java b/base/src/com/google/idea/blaze/base/lang/buildfile/completion/BuildLookupElement.java
index cd01e0d70eb..9e99d40ff8c 100644
--- a/base/src/com/google/idea/blaze/base/lang/buildfile/completion/BuildLookupElement.java
+++ b/base/src/com/google/idea/blaze/base/lang/buildfile/completion/BuildLookupElement.java
@@ -57,6 +57,10 @@ public String getLookupString() {
@Nullable
public abstract Icon getIcon();
+ public String getLabel() {
+ return baseName;
+ }
+
protected String getItemText() {
return baseName;
}
diff --git a/base/src/com/google/idea/blaze/base/lang/buildfile/completion/FilePathLookupElement.java b/base/src/com/google/idea/blaze/base/lang/buildfile/completion/FilePathLookupElement.java
index 0a5a958e6b7..0c39268620d 100644
--- a/base/src/com/google/idea/blaze/base/lang/buildfile/completion/FilePathLookupElement.java
+++ b/base/src/com/google/idea/blaze/base/lang/buildfile/completion/FilePathLookupElement.java
@@ -24,12 +24,18 @@
public class FilePathLookupElement extends BuildLookupElement {
private final String itemText;
+ private final Boolean isDirectory;
private final NullableLazyValue icon;
public FilePathLookupElement(
- String fullLabel, String itemText, QuoteType quoteWrapping, NullableLazyValue icon) {
+ String fullLabel,
+ String itemText,
+ QuoteType quoteWrapping,
+ Boolean isDirectory,
+ NullableLazyValue icon) {
super(fullLabel, quoteWrapping);
this.itemText = itemText;
+ this.isDirectory = isDirectory;
this.icon = icon;
}
@@ -38,6 +44,10 @@ protected String getItemText() {
return itemText;
}
+ public Boolean getIsDirectory() {
+ return isDirectory;
+ }
+
@Nullable
@Override
public Icon getIcon() {
diff --git a/base/src/com/google/idea/blaze/base/lang/buildfile/completion/LabelRuleLookupElement.java b/base/src/com/google/idea/blaze/base/lang/buildfile/completion/LabelRuleLookupElement.java
index 0b9af98bfa0..8442d362085 100644
--- a/base/src/com/google/idea/blaze/base/lang/buildfile/completion/LabelRuleLookupElement.java
+++ b/base/src/com/google/idea/blaze/base/lang/buildfile/completion/LabelRuleLookupElement.java
@@ -94,4 +94,8 @@ protected String getTypeText() {
protected String getItemText() {
return targetName;
}
+
+ public String getRuleType() {
+ return ruleType;
+ }
}
diff --git a/base/src/com/google/idea/blaze/base/lang/buildfile/references/FileLookupData.java b/base/src/com/google/idea/blaze/base/lang/buildfile/references/FileLookupData.java
index 8714ad71321..2e55be3bd63 100644
--- a/base/src/com/google/idea/blaze/base/lang/buildfile/references/FileLookupData.java
+++ b/base/src/com/google/idea/blaze/base/lang/buildfile/references/FileLookupData.java
@@ -180,7 +180,7 @@ protected Icon compute() {
String fullLabel =
workspacePath != null ? getFullLabel(workspacePath.relativePath()) : file.getPath();
String itemText = workspacePath != null ? getItemText(workspacePath.relativePath()) : fullLabel;
- return new FilePathLookupElement(fullLabel, itemText, quoteType, icon);
+ return new FilePathLookupElement(fullLabel, itemText, quoteType, file.isDirectory(), icon);
}
private String getFullLabel(String relativePath) {
diff --git a/base/src/com/google/idea/blaze/base/lang/buildfile/references/VisibilityReference.java b/base/src/com/google/idea/blaze/base/lang/buildfile/references/VisibilityReference.java
new file mode 100644
index 00000000000..a1d31ae9221
--- /dev/null
+++ b/base/src/com/google/idea/blaze/base/lang/buildfile/references/VisibilityReference.java
@@ -0,0 +1,83 @@
+package com.google.idea.blaze.base.lang.buildfile.references;
+
+import com.google.common.collect.ImmutableSet;
+import com.google.idea.blaze.base.lang.buildfile.completion.FilePathLookupElement;
+import com.google.idea.blaze.base.lang.buildfile.completion.LabelRuleLookupElement;
+import com.google.idea.blaze.base.lang.buildfile.psi.StringLiteral;
+import com.google.idea.blaze.base.model.primitives.Label;
+import com.intellij.codeInsight.lookup.LookupElement;
+import com.intellij.codeInsight.lookup.LookupElementBuilder;
+import com.intellij.icons.AllIcons;
+import java.util.ArrayList;
+import java.util.List;
+
+public class VisibilityReference extends LabelReference {
+
+ private static final ImmutableSet PSEUDO_VISIBILITIES =
+ ImmutableSet.of("__pkg__", "__subpackages__");
+
+ public VisibilityReference(StringLiteral element, boolean soft) {
+ super(element, soft);
+ }
+
+ @Override
+ public Object[] getVariants() {
+ Object[] variants = super.getVariants();
+ ArrayList results = new ArrayList<>();
+ for (Object v : variants) {
+ if (v instanceof FilePathLookupElement) {
+ FilePathLookupElement le = ((FilePathLookupElement) v);
+ if (le.getIsDirectory()) {
+ results.add(
+ LookupElementBuilder.create("\"" + le.getLabel() + "/")
+ .withPresentableText(le.getLabel())
+ .withIcon(AllIcons.Nodes.Variable));
+ results.addAll(createPseudoVisibilitiesForPackage(le.getLabel()));
+ }
+
+ } else if (v instanceof LabelRuleLookupElement) {
+ LabelRuleLookupElement le = ((LabelRuleLookupElement) v);
+ if (le.getRuleType().equals("package_group")) {
+ results.add(((LookupElement) le));
+ Label lbl = Label.createIfValid(le.getLabel());
+ if (lbl != null) {
+ String pkg = "//" + lbl.blazePackage();
+ results.addAll(createPseudoVisibilitiesForPackage(pkg));
+ }
+ }
+ }
+ }
+
+ ArrayList globalVisibilities = new ArrayList<>();
+ globalVisibilities.add("//visibility:public");
+ globalVisibilities.add("//visibility:private");
+
+ for (String v : globalVisibilities) {
+ results.add(
+ LookupElementBuilder.create("\"" + v)
+ .withIcon(AllIcons.Nodes.Variable)
+ .withPresentableText(v));
+ results.add(
+ LookupElementBuilder.create("'" + v)
+ .withIcon(AllIcons.Nodes.Variable)
+ .withPresentableText(v));
+ }
+
+ return results.toArray();
+ }
+
+ private List createPseudoVisibilitiesForPackage(String pkg) {
+ List result = new ArrayList<>(PSEUDO_VISIBILITIES.size() * 2);
+ for (String pv : PSEUDO_VISIBILITIES) {
+ result.add(
+ LookupElementBuilder.create("\"" + pkg + ":" + pv)
+ .withPresentableText(pkg + ":" + pv)
+ .withIcon(AllIcons.Nodes.Variable));
+ result.add(
+ LookupElementBuilder.create("'" + pkg + ":" + pv)
+ .withPresentableText(pkg + ":" + pv)
+ .withIcon(AllIcons.Nodes.Variable));
+ }
+ return result;
+ }
+}
diff --git a/base/src/com/google/idea/blaze/base/lang/buildfile/references/VisibilityReferenceContributor.java b/base/src/com/google/idea/blaze/base/lang/buildfile/references/VisibilityReferenceContributor.java
new file mode 100644
index 00000000000..53da5cb2687
--- /dev/null
+++ b/base/src/com/google/idea/blaze/base/lang/buildfile/references/VisibilityReferenceContributor.java
@@ -0,0 +1,13 @@
+package com.google.idea.blaze.base.lang.buildfile.references;
+
+import com.intellij.psi.PsiReferenceContributor;
+import com.intellij.psi.PsiReferenceRegistrar;
+import org.jetbrains.annotations.NotNull;
+
+public class VisibilityReferenceContributor extends PsiReferenceContributor {
+ @Override
+ public void registerReferenceProviders(@NotNull PsiReferenceRegistrar registrar) {
+ registrar.registerReferenceProvider(
+ VisibilityReferenceProvider.PATTERN, new VisibilityReferenceProvider());
+ }
+}
diff --git a/base/src/com/google/idea/blaze/base/lang/buildfile/references/VisibilityReferenceProvider.java b/base/src/com/google/idea/blaze/base/lang/buildfile/references/VisibilityReferenceProvider.java
new file mode 100644
index 00000000000..10ba3d199a5
--- /dev/null
+++ b/base/src/com/google/idea/blaze/base/lang/buildfile/references/VisibilityReferenceProvider.java
@@ -0,0 +1,58 @@
+package com.google.idea.blaze.base.lang.buildfile.references;
+
+import static com.intellij.patterns.PlatformPatterns.psiElement;
+
+import com.google.common.collect.ImmutableSet;
+import com.google.idea.blaze.base.lang.buildfile.language.BuildFileLanguage;
+import com.google.idea.blaze.base.lang.buildfile.psi.Argument;
+import com.google.idea.blaze.base.lang.buildfile.psi.StringLiteral;
+import com.intellij.patterns.ElementPattern;
+import com.intellij.patterns.PatternCondition;
+import com.intellij.patterns.PatternConditionPlus;
+import com.intellij.patterns.StandardPatterns;
+import com.intellij.psi.PsiElement;
+import com.intellij.psi.PsiReference;
+import com.intellij.psi.PsiReferenceProvider;
+import com.intellij.psi.impl.PsiElementBase;
+import com.intellij.util.PairProcessor;
+import com.intellij.util.ProcessingContext;
+import org.jetbrains.annotations.NotNull;
+
+public class VisibilityReferenceProvider extends PsiReferenceProvider
+ implements AttributeSpecificStringLiteralReferenceProvider {
+
+ private static final ImmutableSet VISIBILITY_STRING_TYPES = ImmutableSet.of("visibility");
+
+ public static final ElementPattern PATTERN =
+ psiElement(StringLiteral.class)
+ .withLanguage(BuildFileLanguage.INSTANCE)
+ .inside(
+ psiElement(Argument.Keyword.class)
+ .with(nameCondition(StandardPatterns.string().oneOf(VISIBILITY_STRING_TYPES))));
+
+ private static PatternCondition nameCondition(final ElementPattern> pattern) {
+ return new PatternConditionPlus("_withPsiName", pattern) {
+ @Override
+ public boolean processValues(
+ PsiElementBase t,
+ ProcessingContext context,
+ PairProcessor super String, ? super ProcessingContext> processor) {
+ return processor.process(t.getName(), context);
+ }
+ };
+ }
+
+ @Override
+ public PsiReference[] getReferences(String attributeName, StringLiteral literal) {
+ if (!VISIBILITY_STRING_TYPES.contains(attributeName)) {
+ return PsiReference.EMPTY_ARRAY;
+ }
+ return new PsiReference[] {new VisibilityReference(literal, true)};
+ }
+
+ @Override
+ public PsiReference[] getReferencesByElement(
+ @NotNull PsiElement psiElement, @NotNull ProcessingContext processingContext) {
+ return new PsiReference[] {psiElement.getReference()};
+ }
+}
diff --git a/base/tests/integrationtests/com/google/idea/blaze/base/lang/buildfile/completion/VisibilityCompletionTest.java b/base/tests/integrationtests/com/google/idea/blaze/base/lang/buildfile/completion/VisibilityCompletionTest.java
new file mode 100644
index 00000000000..a130b8661eb
--- /dev/null
+++ b/base/tests/integrationtests/com/google/idea/blaze/base/lang/buildfile/completion/VisibilityCompletionTest.java
@@ -0,0 +1,88 @@
+/*
+ * 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.base.lang.buildfile.completion;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import com.google.idea.blaze.base.lang.buildfile.BuildFileIntegrationTestCase;
+import com.google.idea.blaze.base.lang.buildfile.psi.BuildFile;
+import com.google.idea.blaze.base.model.primitives.WorkspacePath;
+import com.intellij.openapi.editor.Editor;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+@RunWith(JUnit4.class)
+public class VisibilityCompletionTest extends BuildFileIntegrationTestCase {
+
+ @Test
+ public void testVisibilityReferenceWithDoubleQuote() throws Throwable {
+ BuildFile file = createBuildFile(new WorkspacePath("BUILD"), "sh_binary(visibility = [\"/\"])");
+
+ Editor editor = editorTest.openFileInEditor(file);
+ editorTest.setCaretPosition(editor, 0, "sh_binary(visibility = [\"/".length());
+
+ assertThat(editorTest.getCompletionItemsAsStrings())
+ .asList()
+ .containsExactly("\"//visibility:private", "\"//visibility:public");
+ }
+
+ @Test
+ public void testVisibilityReferenceWithSimpleQuote() throws Throwable {
+ BuildFile file = createBuildFile(new WorkspacePath("BUILD"), "sh_binary(visibility = ['/'])");
+
+ Editor editor = editorTest.openFileInEditor(file);
+ editorTest.setCaretPosition(editor, 0, "sh_binary(visibility = ['/".length());
+
+ assertThat(editorTest.getCompletionItemsAsStrings())
+ .asList()
+ .containsExactly("'//visibility:private", "'//visibility:public");
+ }
+
+ @Test
+ public void testVisibilityReferenceWithOtherPackages() throws Throwable {
+ createBuildFile(new WorkspacePath("pkg/foo/BUILD"), "");
+ BuildFile file = createBuildFile(new WorkspacePath("BUILD"), "sh_binary(visibility = ['/'])");
+
+ Editor editor = editorTest.openFileInEditor(file);
+ editorTest.setCaretPosition(editor, 0, "sh_binary(visibility = ['/".length());
+
+ assertThat(editorTest.getCompletionItemsAsStrings())
+ .asList()
+ .containsExactly(
+ "'//visibility:private",
+ "'//visibility:public",
+ "'//pkg/foo:__pkg__",
+ "'//pkg/foo:__subpackages__");
+ }
+
+ @Test
+ public void testVisibilityReferenceWithPackageGroup() throws Throwable {
+ createBuildFile(new WorkspacePath("pkg/foo/BUILD"), "package_group(name = 'bob')");
+ BuildFile file =
+ createBuildFile(new WorkspacePath("BUILD"), "sh_binary(visibility = ['//pkg/foo:'])");
+
+ Editor editor = editorTest.openFileInEditor(file);
+ editorTest.setCaretPosition(editor, 0, "sh_binary(visibility = ['//pkg/foo:".length());
+
+ assertThat(editorTest.getCompletionItemsAsStrings())
+ .asList()
+ .containsExactly(
+ "'//pkg/foo:bob'",
+ "'//pkg/foo:__pkg__",
+ "'//pkg/foo:__subpackages__");
+ }
+}
diff --git a/cpp/BUILD b/cpp/BUILD
index b8c142987bd..16b83ab0b5f 100644
--- a/cpp/BUILD
+++ b/cpp/BUILD
@@ -57,8 +57,8 @@ optional_plugin_xml(
intellij_plugin_library(
name = "plugin_library",
- plugin_xmls = [":non_optional_cidr"],
optional_plugin_xmls = [":optional_cidr"],
+ plugin_xmls = [":non_optional_cidr"],
visibility = PLUGIN_PACKAGES_VISIBILITY,
deps = [":cpp"],
)
diff --git a/sdkcompat/v233/BUILD b/sdkcompat/v233/BUILD
index 8278ce5f0d1..86fec73e8e9 100644
--- a/sdkcompat/v233/BUILD
+++ b/sdkcompat/v233/BUILD
@@ -24,8 +24,8 @@ java_library(
]) + ["com/google/idea/sdkcompat/refactoring/safedelete/JavaSafeDeleteProcessorCompat.java"],
clion = glob([
"com/google/idea/sdkcompat/cpp/**",
- "com/google/idea/sdkcompat/clion/**", # For classes incompatible with Android Studio
- "com/google/idea/sdkcompat/javascript/**", #api223
+ "com/google/idea/sdkcompat/clion/**", # For classes incompatible with Android Studio
+ "com/google/idea/sdkcompat/javascript/**", #api223
]),
intellij = glob([
"com/google/idea/sdkcompat/java/**",
diff --git a/third_party/go/BUILD b/third_party/go/BUILD
index 25d44d98442..292314a6601 100644
--- a/third_party/go/BUILD
+++ b/third_party/go/BUILD
@@ -21,7 +21,7 @@ java_library(
"intellij-2023.2": ["@go_2023_2//:go"],
"intellij-ue-2023.2": ["@go_2023_2//:go"],
"intellij-2023.3": ["@go_2023_3//:go"],
- "intellij-ue-2023.3": ["@go_2023_3//:go"],
+ "intellij-ue-2023.3": ["@go_2023_3//:go"],
"default": [],
}),
)
diff --git a/third_party/python/BUILD b/third_party/python/BUILD
index 7a76782f4dd..bfd2a8ffdb0 100644
--- a/third_party/python/BUILD
+++ b/third_party/python/BUILD
@@ -21,7 +21,7 @@ java_library(
"intellij-2023.2": ["@python_2023_2//:python"],
"intellij-ue-2023.2": ["@python_2023_2//:python"],
"intellij-2023.3": ["@python_2023_3//:python"],
- "intellij-ue-2023.3": ["@python_2023_3//:python"],
+ "intellij-ue-2023.3": ["@python_2023_3//:python"],
"clion-2021.3": ["@clion_2021_3//:python"],
"clion-2022.1": ["@clion_2022_1//:python"],
"clion-2022.2": ["@clion_2022_2//:python"],