Import of bazel plugin using copybara
diff --git a/.gitignore b/.gitignore
index 6d8ad95..25a88ef 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1 +1,2 @@
-bazel-*
\ No newline at end of file
+bazel-*
+!bazel-buildifier
diff --git a/BUILD b/BUILD
index 81608fe..8062413 100644
--- a/BUILD
+++ b/BUILD
@@ -21,7 +21,9 @@
name = "aswb_tests",
tests = [
"//aswb:unit_tests",
+ "//base:integration_tests",
"//base:unit_tests",
+ "//java:integration_tests",
"//java:unit_tests",
],
)
@@ -34,17 +36,3 @@
"//cpp:unit_tests",
],
)
-
-load(
- ":version.bzl",
- "VERSION",
-)
-
-# Version file
-genrule(
- name = "version",
- srcs = [],
- outs = ["VERSION"],
- cmd = "echo '%s' > $@" % VERSION,
- visibility = ["//visibility:public"],
-)
diff --git a/README.md b/README.md
index 0fc36c1..946478a 100644
--- a/README.md
+++ b/README.md
@@ -1,4 +1,4 @@
-# An IntelliJ plugin for [Bazel](http://bazel.io) projects
+# An IntelliJ plugin for [Bazel](http://bazel.build) projects
This is an early-access version of our IntelliJ bazel plugin.
@@ -19,7 +19,7 @@
To import an existing Bazel project, choose 'Import Bazel Project',
and follow the instructions in the project import wizard.
-Detailed docs are available [here](http://ij.bazel.io).
+Detailed docs are available [here](http://ij.bazel.build).
## Building the plugin
diff --git a/aswb/BUILD b/aswb/BUILD
index 6e4a3a2..8c6fd4a 100644
--- a/aswb/BUILD
+++ b/aswb/BUILD
@@ -10,6 +10,7 @@
"merged_plugin_xml",
"stamped_plugin_xml",
)
+load("//:version.bzl", "VERSION")
merged_plugin_xml(
name = "merged_plugin_xml_common",
@@ -39,7 +40,7 @@
plugin_name = "Android Studio with Bazel",
plugin_xml = ":merged_plugin_xml",
stamp_since_build = True,
- version_file = "//:version",
+ version = VERSION,
)
java_library(
diff --git a/aswb/src/META-INF/aswb.xml b/aswb/src/META-INF/aswb.xml
index d8d9334..ab228a2 100644
--- a/aswb/src/META-INF/aswb.xml
+++ b/aswb/src/META-INF/aswb.xml
@@ -18,6 +18,7 @@
<depends>com.intellij.modules.androidstudio</depends>
<depends>org.jetbrains.android</depends>
+ <depends>com.android.tools.idea.updater</depends>
<extensions defaultExtensionNs="com.intellij">
<java.elementFinder implementation="com.google.idea.blaze.android.resources.AndroidResourceClassFinder"
@@ -62,11 +63,6 @@
<sdkEventListener implementation="com.google.idea.blaze.android.sdk.AndroidSdkListener"/>
</extensions>
- <extensionPoints>
- <extensionPoint qualifiedName="com.google.idea.blaze.android.InstrumentationRunnerProvider"
- interface="com.google.idea.blaze.android.run.test.InstrumentationRunnerProvider"/>
- </extensionPoints>
-
<!-- BEGIN NDK SUPPORT -->
<extensions defaultExtensionNs="com.intellij">
<applicationService serviceInterface="com.google.idea.blaze.android.cppapi.BlazeNativeDebuggerIdProvider"
diff --git a/aswb/src/META-INF/aswb_bazel.xml b/aswb/src/META-INF/aswb_bazel.xml
index 4d50f16..4f6f6e9 100644
--- a/aswb/src/META-INF/aswb_bazel.xml
+++ b/aswb/src/META-INF/aswb_bazel.xml
@@ -16,7 +16,7 @@
<idea-plugin>
<description>
<![CDATA[
- <a href="http://bazel.io">Bazel</a> support for Android Studio.
+ <a href="https://bazel.build">Bazel</a> support for Android Studio.
Features:
<ul>
@@ -25,7 +25,7 @@
<li>Support for Bazel run configurations for certain rule classes.</li>
</ul>
- Usage instructions at <a href="http://ij.bazel.io">ij.bazel.io</a>
+ Usage instructions at <a href="https://ij.bazel.build">ij.bazel.build</a>
]]>
</description>
</idea-plugin>
diff --git a/aswb/src/com/google/idea/blaze/android/manifest/ManifestParser.java b/aswb/src/com/google/idea/blaze/android/manifest/ManifestParser.java
index a8fe734..becaa66 100644
--- a/aswb/src/com/google/idea/blaze/android/manifest/ManifestParser.java
+++ b/aswb/src/com/google/idea/blaze/android/manifest/ManifestParser.java
@@ -61,7 +61,9 @@
return null;
}
Manifest manifest = manifestFileMap.get(file);
- if (manifest != null) {
+ // Note: The manifest may be invalid if the underlying VirtualFile is invalidated.
+ // Once invalid, it cannot become valid again, and must be reloaded.
+ if (manifest != null && manifest.isValid()) {
return manifest;
}
final VirtualFile virtualFile;
diff --git a/aswb/src/com/google/idea/blaze/android/run/binary/BlazeAndroidBinaryRunConfigurationState.java b/aswb/src/com/google/idea/blaze/android/run/binary/BlazeAndroidBinaryRunConfigurationState.java
index e657124..6557f8b 100644
--- a/aswb/src/com/google/idea/blaze/android/run/binary/BlazeAndroidBinaryRunConfigurationState.java
+++ b/aswb/src/com/google/idea/blaze/android/run/binary/BlazeAndroidBinaryRunConfigurationState.java
@@ -46,7 +46,7 @@
private static final String WORK_PROFILE_ATTR = "use-work-profile-if-present";
private static final String USER_ID_ATTR = "user-id";
private boolean mobileInstall = false;
- private boolean useSplitApksIfPossible = true;
+ private boolean useSplitApksIfPossible = false;
private boolean instantRun = false;
private boolean useWorkProfileIfPresent = false;
private Integer userId;
@@ -151,7 +151,8 @@
setDeepLink(Strings.nullToEmpty(element.getAttributeValue(DEEP_LINK)));
setActivityClass(Strings.nullToEmpty(element.getAttributeValue(ACTIVITY_CLASS)));
- setMode(Strings.nullToEmpty(element.getAttributeValue(MODE)));
+ String modeValue = element.getAttributeValue(MODE);
+ setMode(Strings.isNullOrEmpty(modeValue) ? LAUNCH_DEFAULT_ACTIVITY : modeValue);
setMobileInstall(Boolean.parseBoolean(element.getAttributeValue(MOBILE_INSTALL_ATTR)));
setUseSplitApksIfPossible(
Boolean.parseBoolean(element.getAttributeValue(USE_SPLIT_APKS_IF_POSSIBLE)));
@@ -173,7 +174,7 @@
activityClass = Strings.nullToEmpty(value);
break;
case MODE:
- mode = Strings.nullToEmpty(value);
+ mode = Strings.isNullOrEmpty(value) ? LAUNCH_DEFAULT_ACTIVITY : value;
break;
case ACTIVITY_EXTRA_FLAGS:
if (userId == null) {
diff --git a/aswb/src/com/google/idea/blaze/android/run/runner/AaptUtil.java b/aswb/src/com/google/idea/blaze/android/run/runner/AaptUtil.java
index 9ad2aa0..8f7ce00 100644
--- a/aswb/src/com/google/idea/blaze/android/run/runner/AaptUtil.java
+++ b/aswb/src/com/google/idea/blaze/android/run/runner/AaptUtil.java
@@ -17,7 +17,7 @@
import com.android.sdklib.BuildToolInfo;
import com.android.sdklib.BuildToolInfo.PathId;
-import com.google.idea.blaze.android.sdk.SdkUtil;
+import com.google.idea.blaze.android.sync.sdk.SdkUtil;
import com.intellij.execution.ExecutionException;
import com.intellij.execution.configurations.GeneralCommandLine;
import com.intellij.execution.process.OSProcessHandler;
diff --git a/aswb/src/com/google/idea/blaze/android/run/test/BlazeAndroidTestRunContext.java b/aswb/src/com/google/idea/blaze/android/run/test/BlazeAndroidTestRunContext.java
index 8f2f218..7ab695c 100644
--- a/aswb/src/com/google/idea/blaze/android/run/test/BlazeAndroidTestRunContext.java
+++ b/aswb/src/com/google/idea/blaze/android/run/test/BlazeAndroidTestRunContext.java
@@ -182,7 +182,6 @@
applicationIdProvider,
launchOptions.isDebug(),
deployInfo,
- facet,
processHandlerLaunchStatus);
}
diff --git a/aswb/src/com/google/idea/blaze/android/run/test/InstrumentationRunnerProvider.java b/aswb/src/com/google/idea/blaze/android/run/test/InstrumentationRunnerProvider.java
deleted file mode 100644
index 3c90aba..0000000
--- a/aswb/src/com/google/idea/blaze/android/run/test/InstrumentationRunnerProvider.java
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * Copyright 2016 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.android.run.test;
-
-import com.intellij.openapi.extensions.ExtensionPointName;
-import javax.annotation.Nullable;
-
-/** Provides a default instrumentation test runner class for android test configurations. */
-public interface InstrumentationRunnerProvider {
-
- ExtensionPointName<InstrumentationRunnerProvider> EP_NAME =
- ExtensionPointName.create("com.google.idea.blaze.android.InstrumentationRunnerProvider");
-
- @Nullable
- static String getDefaultInstrumentationRunnerClass() {
- for (InstrumentationRunnerProvider provider : EP_NAME.getExtensions()) {
- String path = provider.getInstrumentationRunnerClass();
- if (path != null) {
- return path;
- }
- }
- return null;
- }
-
- @Nullable
- String getInstrumentationRunnerClass();
-}
diff --git a/aswb/src/com/google/idea/blaze/android/run/test/StockAndroidTestLaunchTask.java b/aswb/src/com/google/idea/blaze/android/run/test/StockAndroidTestLaunchTask.java
index e17cb97..cf3664b 100644
--- a/aswb/src/com/google/idea/blaze/android/run/test/StockAndroidTestLaunchTask.java
+++ b/aswb/src/com/google/idea/blaze/android/run/test/StockAndroidTestLaunchTask.java
@@ -15,38 +15,36 @@
*/
package com.google.idea.blaze.android.run.test;
-import com.android.builder.model.Variant;
import com.android.ddmlib.IDevice;
import com.android.ddmlib.testrunner.RemoteAndroidTestRunner;
-import com.android.tools.idea.gradle.AndroidGradleModel;
import com.android.tools.idea.run.ApkProvisionException;
import com.android.tools.idea.run.ApplicationIdProvider;
import com.android.tools.idea.run.ConsolePrinter;
import com.android.tools.idea.run.tasks.LaunchTask;
import com.android.tools.idea.run.testing.AndroidTestListener;
import com.android.tools.idea.run.util.LaunchStatus;
+import com.google.common.collect.ImmutableList;
import com.google.idea.blaze.android.run.deployinfo.BlazeAndroidDeployInfo;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.util.Computable;
import com.intellij.openapi.util.text.StringUtil;
-import com.intellij.psi.PsiClass;
-import org.jetbrains.android.dom.manifest.Instrumentation;
+import java.util.List;
+import java.util.Objects;
+import java.util.stream.Collectors;
import org.jetbrains.android.dom.manifest.Manifest;
-import org.jetbrains.android.facet.AndroidFacet;
-import org.jetbrains.annotations.Nullable;
final class StockAndroidTestLaunchTask implements LaunchTask {
private static final Logger LOG = Logger.getInstance(StockAndroidTestLaunchTask.class);
private final BlazeAndroidTestRunConfigurationState configState;
- @Nullable private final String instrumentationTestRunner;
+ private final String instrumentationTestRunner;
private final String testApplicationId;
private final boolean waitForDebugger;
private StockAndroidTestLaunchTask(
BlazeAndroidTestRunConfigurationState configState,
- @Nullable String runner,
+ String runner,
String testPackage,
boolean waitForDebugger) {
this.configState = configState;
@@ -60,12 +58,7 @@
ApplicationIdProvider applicationIdProvider,
boolean waitForDebugger,
BlazeAndroidDeployInfo deployInfo,
- AndroidFacet facet,
LaunchStatus launchStatus) {
- String runner =
- StringUtil.isEmpty(configState.getInstrumentationRunnerClass())
- ? findInstrumentationRunner(deployInfo, facet)
- : configState.getInstrumentationRunnerClass();
String testPackage;
try {
testPackage = applicationIdProvider.getTestPackageName();
@@ -78,51 +71,80 @@
return null;
}
+ List<String> availableRunners = getRunnersFromManifest(deployInfo);
+ if (availableRunners.isEmpty()) {
+ launchStatus.terminateLaunch(
+ String.format(
+ "No instrumentation test runner is defined in the manifest.\n"
+ + "At least one instrumentation tag must be defined for the\n"
+ + "\"%1$s\" package in the AndroidManifest.xml, e.g.:\n"
+ + "\n"
+ + "<manifest\n"
+ + " package=\"%1$s\"\n"
+ + " xmlns:android=\"http://schemas.android.com/apk/res/android\">\n"
+ + "\n"
+ + " <instrumentation\n"
+ + " android:name=\"android.support.test.runner.AndroidJUnitRunner\"\n"
+ + " android:targetPackage=\"%1$s\">\n"
+ + " </instrumentation>\n"
+ + "\n"
+ + "</manifest>",
+ testPackage));
+ // Note: Gradle users will never see the above message, so don't mention Gradle here.
+ // Even if no runners are defined in build.gradle, Gradle will add a default to the manifest.
+ return null;
+ }
+ String runner = configState.getInstrumentationRunnerClass();
+ if (!StringUtil.isEmpty(runner)) {
+ if (!availableRunners.contains(runner)) {
+ launchStatus.terminateLaunch(
+ String.format(
+ "Instrumentation test runner \"%2$s\"\n"
+ + "is not defined for the \"%1$s\" package in the manifest.\n"
+ + "Clear the 'Specific instrumentation runner' field in your configuration\n"
+ + "to default to \"%3$s\",\n"
+ + "or add the runner to your AndroidManifest.xml:\n"
+ + "\n"
+ + "<manifest\n"
+ + " package=\"%1$s\"\n"
+ + " xmlns:android=\"http://schemas.android.com/apk/res/android\">\n"
+ + "\n"
+ + " <instrumentation\n"
+ + " android:name=\"%2$s\"\n"
+ + " android:targetPackage=\"%1$s\">\n"
+ + " </instrumentation>\n"
+ + "\n"
+ + "</manifest>",
+ testPackage, runner, availableRunners.get(0)));
+ return null;
+ }
+ } else {
+ // Default to the first available runner.
+ runner = availableRunners.get(0);
+ }
+
return new StockAndroidTestLaunchTask(configState, runner, testPackage, waitForDebugger);
}
- @Nullable
- private static String findInstrumentationRunner(
- BlazeAndroidDeployInfo deployInfo, AndroidFacet facet) {
- String runner = getRunnerFromManifest(deployInfo);
-
- // TODO: Resolve direct AndroidGradleModel dep (b/22596984)
- AndroidGradleModel androidModel = AndroidGradleModel.get(facet);
- if (runner == null && androidModel != null) {
- Variant selectedVariant = androidModel.getSelectedVariant();
- String testRunner = selectedVariant.getMergedFlavor().getTestInstrumentationRunner();
- if (testRunner != null) {
- runner = testRunner;
- }
- }
-
- // Fall back to the default runner.
- if (runner == null) {
- runner = InstrumentationRunnerProvider.getDefaultInstrumentationRunnerClass();
- }
-
- return runner;
- }
-
- @Nullable
- private static String getRunnerFromManifest(final BlazeAndroidDeployInfo deployInfo) {
+ private static ImmutableList<String> getRunnersFromManifest(
+ final BlazeAndroidDeployInfo deployInfo) {
if (!ApplicationManager.getApplication().isReadAccessAllowed()) {
return ApplicationManager.getApplication()
- .runReadAction((Computable<String>) () -> getRunnerFromManifest(deployInfo));
+ .runReadAction(
+ (Computable<ImmutableList<String>>) () -> getRunnersFromManifest(deployInfo));
}
Manifest manifest = deployInfo.getMergedManifest();
if (manifest != null) {
- for (Instrumentation instrumentation : manifest.getInstrumentations()) {
- if (instrumentation != null) {
- PsiClass instrumentationClass = instrumentation.getInstrumentationClass().getValue();
- if (instrumentationClass != null) {
- return instrumentationClass.getQualifiedName();
- }
- }
- }
+ return ImmutableList.copyOf(
+ manifest
+ .getInstrumentations()
+ .stream()
+ .map(instrumentation -> instrumentation.getInstrumentationClass().getStringValue())
+ .filter(Objects::nonNull)
+ .collect(Collectors.toList()));
}
- return null;
+ return ImmutableList.of();
}
@Override
diff --git a/aswb/src/com/google/idea/blaze/android/settings/AswbGlobalSettings.java b/aswb/src/com/google/idea/blaze/android/settings/AswbGlobalSettings.java
index 9532859..53577f5 100644
--- a/aswb/src/com/google/idea/blaze/android/settings/AswbGlobalSettings.java
+++ b/aswb/src/com/google/idea/blaze/android/settings/AswbGlobalSettings.java
@@ -26,7 +26,7 @@
@State(name = "AswbGlobalSettings", storages = @Storage("aswb.global.xml"))
public class AswbGlobalSettings implements PersistentStateComponent<AswbGlobalSettings> {
- private String localSdkLocation;
+ @Deprecated private String localSdkLocation;
public static AswbGlobalSettings getInstance() {
return ServiceManager.getService(AswbGlobalSettings.class);
@@ -43,10 +43,12 @@
XmlSerializerUtil.copyBean(state, this);
}
+ @Deprecated
public void setLocalSdkLocation(String localSdkLocation) {
this.localSdkLocation = localSdkLocation;
}
+ @Deprecated
public String getLocalSdkLocation() {
return localSdkLocation;
}
diff --git a/aswb/src/com/google/idea/blaze/android/sync/BlazeAndroidSyncPlugin.java b/aswb/src/com/google/idea/blaze/android/sync/BlazeAndroidSyncPlugin.java
index 0755074..a33fa08 100644
--- a/aswb/src/com/google/idea/blaze/android/sync/BlazeAndroidSyncPlugin.java
+++ b/aswb/src/com/google/idea/blaze/android/sync/BlazeAndroidSyncPlugin.java
@@ -15,6 +15,7 @@
*/
package com.google.idea.blaze.android.sync;
+import com.android.tools.idea.sdk.IdeSdks;
import com.google.common.base.Joiner;
import com.google.common.base.Strings;
import com.google.common.collect.ImmutableList;
@@ -26,6 +27,9 @@
import com.google.idea.blaze.android.sync.model.BlazeAndroidImportResult;
import com.google.idea.blaze.android.sync.model.BlazeAndroidSyncData;
import com.google.idea.blaze.android.sync.projectstructure.BlazeAndroidProjectStructureSyncer;
+import com.google.idea.blaze.android.sync.sdk.AndroidSdkFromProjectView;
+import com.google.idea.blaze.android.sync.sdk.SdkExperiment;
+import com.google.idea.blaze.android.sync.sdklegacy.AndroidSdkPlatformSyncer;
import com.google.idea.blaze.base.ideinfo.RuleMap;
import com.google.idea.blaze.base.model.BlazeProjectData;
import com.google.idea.blaze.base.model.SyncState;
@@ -37,6 +41,7 @@
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;
+import com.google.idea.blaze.base.scope.output.StatusOutput;
import com.google.idea.blaze.base.scope.scopes.TimingScope;
import com.google.idea.blaze.base.sync.BlazeSyncPlugin;
import com.google.idea.blaze.base.sync.projectview.WorkspaceLanguageSettings;
@@ -46,6 +51,7 @@
import com.google.idea.blaze.base.sync.workspace.WorkspacePathResolver;
import com.google.idea.blaze.java.projectview.JavaLanguageLevelSection;
import com.intellij.openapi.application.ApplicationManager;
+import com.intellij.openapi.application.ModalityState;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.module.ModuleManager;
import com.intellij.openapi.module.ModuleType;
@@ -57,6 +63,7 @@
import com.intellij.openapi.roots.ex.ProjectRootManagerEx;
import com.intellij.pom.java.LanguageLevel;
import com.intellij.util.ui.UIUtil;
+import java.io.File;
import java.util.Collection;
import java.util.Set;
import javax.annotation.Nullable;
@@ -98,6 +105,20 @@
}
@Override
+ public void installSdks(BlazeContext context) {
+ File path = IdeSdks.getAndroidSdkPath();
+ if (path != null) {
+ context.output(new StatusOutput("Installing SDK platforms..."));
+ ApplicationManager.getApplication()
+ .invokeAndWait(
+ () -> {
+ IdeSdks.createAndroidSdkPerAndroidTarget(path);
+ },
+ ModalityState.defaultModalityState());
+ }
+ }
+
+ @Override
public void updateSyncState(
Project project,
BlazeContext context,
@@ -115,8 +136,13 @@
return;
}
- AndroidSdkPlatform androidSdkPlatform =
- AndroidSdkPlatformSyncer.getAndroidSdkPlatform(project, context);
+ final AndroidSdkPlatform androidSdkPlatform;
+ if (SdkExperiment.useStandardSdkManager()) {
+ androidSdkPlatform = AndroidSdkFromProjectView.getAndroidSdkPlatform(context, projectViewSet);
+ } else {
+ androidSdkPlatform = AndroidSdkPlatformSyncer.getAndroidSdkPlatform(project, context);
+ }
+
BlazeAndroidWorkspaceImporter workspaceImporter =
new BlazeAndroidWorkspaceImporter(project, context, workspaceRoot, projectViewSet, ruleMap);
BlazeAndroidImportResult importResult =
@@ -131,7 +157,7 @@
}
@Override
- public void updateSdk(
+ public void updateProjectSdk(
Project project,
BlazeContext context,
ProjectViewSet projectViewSet,
@@ -216,20 +242,27 @@
return false;
}
- String androidSdkPlatform = projectViewSet.getScalarValue(AndroidSdkPlatformSection.KEY);
- if (Strings.isNullOrEmpty(androidSdkPlatform)) {
- String error =
- Joiner.on('\n')
- .join(
- "No android_sdk_platform set.",
- "You should specify the android SDK platform in your '.blazeproject' file.",
- "To set this add an 'android_sdk_platform' line to your .blazeproject file,",
- "e.g. 'android_sdk_platform: \"android-N\"', where 'android-N' is a",
- "platform directory name in your local SDK directory.");
- IssueOutput.error(error)
- .inFile(projectViewSet.getTopLevelProjectViewFile().projectViewFile)
- .submit(context);
+ if (SdkExperiment.useStandardSdkManager()) {
+ if (AndroidSdkFromProjectView.getAndroidSdkPlatform(context, projectViewSet) == null) {
+ return false;
+ }
+ } else {
+ String androidSdkPlatform = projectViewSet.getScalarValue(AndroidSdkPlatformSection.KEY);
+ if (Strings.isNullOrEmpty(androidSdkPlatform)) {
+ String error =
+ Joiner.on('\n')
+ .join(
+ "No android_sdk_platform set.",
+ "You should specify the android SDK platform in your '.blazeproject' file.",
+ "To set this add an 'android_sdk_platform' line to your .blazeproject file,",
+ "e.g. 'android_sdk_platform: \"android-N\"', where 'android-N' is a",
+ "platform directory name in your local SDK directory.");
+ IssueOutput.error(error)
+ .inFile(projectViewSet.getTopLevelProjectViewFile().projectViewFile)
+ .submit(context);
+ }
}
+
return true;
}
diff --git a/aswb/src/com/google/idea/blaze/android/sync/projectstructure/AndroidFacetModuleCustomizer.java b/aswb/src/com/google/idea/blaze/android/sync/projectstructure/AndroidFacetModuleCustomizer.java
index 62a06a2..db6443a 100755
--- a/aswb/src/com/google/idea/blaze/android/sync/projectstructure/AndroidFacetModuleCustomizer.java
+++ b/aswb/src/com/google/idea/blaze/android/sync/projectstructure/AndroidFacetModuleCustomizer.java
@@ -59,5 +59,6 @@
facetState.MANIFEST_FILE_RELATIVE_PATH = "";
facetState.RES_FOLDER_RELATIVE_PATH = "";
facetState.ASSETS_FOLDER_RELATIVE_PATH = "";
+ facetState.ENABLE_SOURCES_AUTOGENERATION = false;
}
}
diff --git a/aswb/src/com/google/idea/blaze/android/sync/projectstructure/BlazeAndroidProjectStructureSyncer.java b/aswb/src/com/google/idea/blaze/android/sync/projectstructure/BlazeAndroidProjectStructureSyncer.java
index aff9a7e..7442635 100644
--- a/aswb/src/com/google/idea/blaze/android/sync/projectstructure/BlazeAndroidProjectStructureSyncer.java
+++ b/aswb/src/com/google/idea/blaze/android/sync/projectstructure/BlazeAndroidProjectStructureSyncer.java
@@ -21,12 +21,12 @@
import com.google.common.collect.Sets;
import com.google.idea.blaze.android.resources.LightResourceClassService;
import com.google.idea.blaze.android.run.BlazeAndroidRunConfigurationHandler;
-import com.google.idea.blaze.android.sync.AndroidSdkPlatformSyncer;
import com.google.idea.blaze.android.sync.model.AndroidResourceModule;
import com.google.idea.blaze.android.sync.model.AndroidSdkPlatform;
import com.google.idea.blaze.android.sync.model.BlazeAndroidSyncData;
import com.google.idea.blaze.android.sync.model.idea.BlazeAndroidModel;
import com.google.idea.blaze.android.sync.model.idea.SourceProviderImpl;
+import com.google.idea.blaze.android.sync.sdk.SdkUtil;
import com.google.idea.blaze.base.ideinfo.AndroidRuleIdeInfo;
import com.google.idea.blaze.base.ideinfo.ArtifactLocation;
import com.google.idea.blaze.base.ideinfo.RuleIdeInfo;
@@ -220,8 +220,7 @@
if (blazeProjectData == null) {
return null;
}
- AndroidSdkPlatform androidSdkPlatform =
- AndroidSdkPlatformSyncer.getAndroidSdkPlatform(blazeProjectData);
+ AndroidSdkPlatform androidSdkPlatform = SdkUtil.getAndroidSdkPlatform(blazeProjectData);
if (androidSdkPlatform == null) {
return null;
}
diff --git a/aswb/src/com/google/idea/blaze/android/sync/sdk/AndroidSdkFromProjectView.java b/aswb/src/com/google/idea/blaze/android/sync/sdk/AndroidSdkFromProjectView.java
new file mode 100644
index 0000000..2740352
--- /dev/null
+++ b/aswb/src/com/google/idea/blaze/android/sync/sdk/AndroidSdkFromProjectView.java
@@ -0,0 +1,121 @@
+/*
+ * Copyright 2016 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.android.sync.sdk;
+
+import com.google.common.base.Joiner;
+import com.google.common.collect.Lists;
+import com.google.idea.blaze.android.projectview.AndroidSdkPlatformSection;
+import com.google.idea.blaze.android.sync.model.AndroidSdkPlatform;
+import com.google.idea.blaze.base.projectview.ProjectViewSet;
+import com.google.idea.blaze.base.scope.BlazeContext;
+import com.google.idea.blaze.base.scope.output.IssueOutput;
+import com.intellij.openapi.projectRoots.Sdk;
+import com.intellij.pom.Navigatable;
+import java.util.Collection;
+import java.util.List;
+import javax.annotation.Nullable;
+import org.jetbrains.android.sdk.AndroidPlatform;
+import org.jetbrains.android.sdk.AndroidSdkAdditionalData;
+import org.jetbrains.android.sdk.AndroidSdkUtils;
+
+/** Calculates AndroidSdkPlatform. */
+public class AndroidSdkFromProjectView {
+ @Nullable
+ public static AndroidSdkPlatform getAndroidSdkPlatform(
+ BlazeContext context, ProjectViewSet projectViewSet) {
+ Collection<Sdk> sdks = AndroidSdkUtils.getAllAndroidSdks();
+ if (sdks.isEmpty()) {
+ IssueOutput.error("No Android SDK configured. Please use the SDK manager to configure.")
+ .navigatable(
+ new Navigatable() {
+ @Override
+ public void navigate(boolean b) {
+ SdkUtil.openSdkManager();
+ }
+
+ @Override
+ public boolean canNavigate() {
+ return true;
+ }
+
+ @Override
+ public boolean canNavigateToSource() {
+ return false;
+ }
+ })
+ .submit(context);
+ return null;
+ }
+ String androidSdk = null;
+ if (projectViewSet != null) {
+ androidSdk = projectViewSet.getScalarValue(AndroidSdkPlatformSection.KEY);
+ }
+
+ if (androidSdk == null) {
+ IssueOutput.error(
+ ("No android_sdk_platform set. Please set to an android platform. "
+ + "Available android_sdk_platforms are: "
+ + getAvailableSdkPlatforms(sdks)))
+ .inFile(projectViewSet.getTopLevelProjectViewFile().projectViewFile)
+ .submit(context);
+ return null;
+ }
+
+ Sdk sdk = AndroidSdkUtils.findSuitableAndroidSdk(androidSdk);
+ if (sdk == null) {
+ IssueOutput.error(
+ ("No such android_sdk_platform: '"
+ + androidSdk
+ + "'. "
+ + "Available android_sdk_platforms are: "
+ + getAvailableSdkPlatforms(sdks)
+ + ". "
+ + "Please change android_sdk_platform or run SDK manager "
+ + "to download missing SDK platforms."))
+ .inFile(projectViewSet.getTopLevelProjectViewFile().projectViewFile)
+ .submit(context);
+ return null;
+ }
+
+ int androidSdkApiLevel = getAndroidSdkApiLevel(sdk);
+ return new AndroidSdkPlatform(androidSdk, androidSdkApiLevel);
+ }
+
+ private static String getAvailableSdkPlatforms(Collection<Sdk> sdks) {
+ List<String> names = Lists.newArrayList();
+ for (Sdk sdk : sdks) {
+ AndroidSdkAdditionalData additionalData = AndroidSdkUtils.getAndroidSdkAdditionalData(sdk);
+ if (additionalData == null) {
+ continue;
+ }
+ String targetHash = additionalData.getBuildTargetHashString();
+ names.add(targetHash);
+ }
+ return "{" + Joiner.on(", ").join(names) + "}";
+ }
+
+ private static int getAndroidSdkApiLevel(Sdk sdk) {
+ int androidSdkApiLevel = 1;
+ AndroidSdkAdditionalData additionalData = (AndroidSdkAdditionalData) sdk.getSdkAdditionalData();
+ if (additionalData != null) {
+ AndroidPlatform androidPlatform = additionalData.getAndroidPlatform();
+ if (androidPlatform != null) {
+ androidSdkApiLevel = androidPlatform.getApiLevel();
+ }
+ }
+ return androidSdkApiLevel;
+ }
+}
diff --git a/aswb/src/com/google/idea/blaze/android/sync/sdk/SdkExperiment.java b/aswb/src/com/google/idea/blaze/android/sync/sdk/SdkExperiment.java
new file mode 100644
index 0000000..1ad1842
--- /dev/null
+++ b/aswb/src/com/google/idea/blaze/android/sync/sdk/SdkExperiment.java
@@ -0,0 +1,30 @@
+/*
+ * Copyright 2016 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.android.sync.sdk;
+
+import com.android.tools.idea.startup.AndroidStudioInitializer;
+
+/**
+ * Wrapper class to keep track of "experiment" for later deletion.
+ *
+ * <p>The experiment is actually controlled by the JVM property, and we can't use a "normal"
+ * experiment for that since the JVM property also affects upstream Android Studio.
+ */
+public class SdkExperiment {
+ public static boolean useStandardSdkManager() {
+ return AndroidStudioInitializer.isAndroidSdkManagerEnabled();
+ }
+}
diff --git a/aswb/src/com/google/idea/blaze/android/sdk/SdkUtil.java b/aswb/src/com/google/idea/blaze/android/sync/sdk/SdkUtil.java
similarity index 60%
rename from aswb/src/com/google/idea/blaze/android/sdk/SdkUtil.java
rename to aswb/src/com/google/idea/blaze/android/sync/sdk/SdkUtil.java
index a48166a..933679d 100644
--- a/aswb/src/com/google/idea/blaze/android/sdk/SdkUtil.java
+++ b/aswb/src/com/google/idea/blaze/android/sync/sdk/SdkUtil.java
@@ -13,12 +13,16 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package com.google.idea.blaze.android.sdk;
+package com.google.idea.blaze.android.sync.sdk;
-import com.google.idea.blaze.android.sync.AndroidSdkPlatformSyncer;
+import com.android.tools.idea.updater.configure.SdkUpdaterConfigurableProvider;
import com.google.idea.blaze.android.sync.model.AndroidSdkPlatform;
+import com.google.idea.blaze.android.sync.model.BlazeAndroidSyncData;
import com.google.idea.blaze.base.model.BlazeProjectData;
import com.google.idea.blaze.base.sync.data.BlazeProjectDataManager;
+import com.intellij.openapi.options.Configurable;
+import com.intellij.openapi.options.ShowSettingsUtil;
+import com.intellij.openapi.options.ex.ConfigurableExtensionPointUtil;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.projectRoots.Sdk;
import org.jetbrains.android.sdk.AndroidPlatform;
@@ -29,14 +33,19 @@
/** SDK utilities. */
public class SdkUtil {
@Nullable
+ public static AndroidSdkPlatform getAndroidSdkPlatform(BlazeProjectData blazeProjectData) {
+ BlazeAndroidSyncData syncData = blazeProjectData.syncState.get(BlazeAndroidSyncData.class);
+ return syncData != null ? syncData.androidSdkPlatform : null;
+ }
+
+ @Nullable
public static AndroidPlatform getAndroidPlatform(@NotNull Project project) {
BlazeProjectData blazeProjectData =
BlazeProjectDataManager.getInstance(project).getBlazeProjectData();
if (blazeProjectData == null) {
return null;
}
- AndroidSdkPlatform androidSdkPlatform =
- AndroidSdkPlatformSyncer.getAndroidSdkPlatform(blazeProjectData);
+ AndroidSdkPlatform androidSdkPlatform = getAndroidSdkPlatform(blazeProjectData);
if (androidSdkPlatform == null) {
return null;
}
@@ -46,4 +55,12 @@
}
return AndroidPlatform.getInstance(sdk);
}
+
+ /** Opens the SDK manager settings page */
+ public static void openSdkManager() {
+ Configurable configurable =
+ ConfigurableExtensionPointUtil.createApplicationConfigurableForProvider(
+ SdkUpdaterConfigurableProvider.class);
+ ShowSettingsUtil.getInstance().showSettingsDialog(null, configurable.getClass());
+ }
}
diff --git a/aswb/src/com/google/idea/blaze/android/sync/AndroidSdkPlatformSyncer.java b/aswb/src/com/google/idea/blaze/android/sync/sdklegacy/AndroidSdkPlatformSyncer.java
similarity index 91%
rename from aswb/src/com/google/idea/blaze/android/sync/AndroidSdkPlatformSyncer.java
rename to aswb/src/com/google/idea/blaze/android/sync/sdklegacy/AndroidSdkPlatformSyncer.java
index c219263..aa0fcd0 100644
--- a/aswb/src/com/google/idea/blaze/android/sync/AndroidSdkPlatformSyncer.java
+++ b/aswb/src/com/google/idea/blaze/android/sync/sdklegacy/AndroidSdkPlatformSyncer.java
@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package com.google.idea.blaze.android.sync;
+package com.google.idea.blaze.android.sync.sdklegacy;
import com.android.tools.idea.startup.AndroidStudioInitializer;
import com.google.common.base.Joiner;
@@ -23,8 +23,6 @@
import com.google.idea.blaze.android.projectview.AndroidSdkPlatformSection;
import com.google.idea.blaze.android.settings.AswbGlobalSettings;
import com.google.idea.blaze.android.sync.model.AndroidSdkPlatform;
-import com.google.idea.blaze.android.sync.model.BlazeAndroidSyncData;
-import com.google.idea.blaze.base.model.BlazeProjectData;
import com.google.idea.blaze.base.projectview.ProjectViewManager;
import com.google.idea.blaze.base.projectview.ProjectViewSet;
import com.google.idea.blaze.base.scope.BlazeContext;
@@ -41,9 +39,10 @@
import org.jetbrains.android.sdk.AndroidSdkUtils;
/** Calculates AndroidSdkPlatform. */
+@Deprecated
public class AndroidSdkPlatformSyncer {
@Nullable
- static AndroidSdkPlatform getAndroidSdkPlatform(Project project, BlazeContext context) {
+ public static AndroidSdkPlatform getAndroidSdkPlatform(Project project, BlazeContext context) {
final String localSdkLocation;
if (AndroidStudioInitializer.isAndroidSdkManagerEnabled()) {
@@ -143,12 +142,6 @@
return "<No platforms found>";
}
- @Nullable
- public static AndroidSdkPlatform getAndroidSdkPlatform(BlazeProjectData blazeProjectData) {
- BlazeAndroidSyncData syncData = blazeProjectData.syncState.get(BlazeAndroidSyncData.class);
- return syncData != null ? syncData.androidSdkPlatform : null;
- }
-
private static int getAndroidSdkApiLevel(String androidSdk) {
int androidSdkApiLevel = 1;
Sdk sdk = AndroidSdkUtils.findSuitableAndroidSdk(androidSdk);
diff --git a/aswb/src/com/google/idea/blaze/android/sync/BlazeAndroidSdk.java b/aswb/src/com/google/idea/blaze/android/sync/sdklegacy/BlazeAndroidSdk.java
similarity index 96%
rename from aswb/src/com/google/idea/blaze/android/sync/BlazeAndroidSdk.java
rename to aswb/src/com/google/idea/blaze/android/sync/sdklegacy/BlazeAndroidSdk.java
index e9e838e..bee2b3b 100644
--- a/aswb/src/com/google/idea/blaze/android/sync/BlazeAndroidSdk.java
+++ b/aswb/src/com/google/idea/blaze/android/sync/sdklegacy/BlazeAndroidSdk.java
@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package com.google.idea.blaze.android.sync;
+package com.google.idea.blaze.android.sync.sdklegacy;
import com.android.SdkConstants;
import com.android.sdklib.AndroidTargetHash;
@@ -28,7 +28,8 @@
import javax.annotation.Nullable;
/** Utility methods for handling the android sdk. */
-public final class BlazeAndroidSdk {
+@Deprecated
+final class BlazeAndroidSdk {
private static final Logger LOG = Logger.getInstance(BlazeAndroidSdk.class);
private BlazeAndroidSdk() {}
diff --git a/base/BUILD b/base/BUILD
index 0cd244d..2921507 100644
--- a/base/BUILD
+++ b/base/BUILD
@@ -6,6 +6,7 @@
resources = glob(["resources/**/*"]),
visibility = ["//visibility:public"],
deps = [
+ "//common/binaryhelper",
"//common/experiments",
"//intellij_platform_sdk:plugin_api",
"//proto_deps",
diff --git a/base/scripts/create_bugreport.sh b/base/scripts/create_bugreport.sh
deleted file mode 100755
index d0c40d7..0000000
--- a/base/scripts/create_bugreport.sh
+++ /dev/null
@@ -1,144 +0,0 @@
-#!/bin/bash
-
-# Copyright 2016 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.
-
-#
-# Use this to create a bug report for IntelliJ plugin bugs.
-#
-# Usage: create_bugreport.sh
-#
-
-# For all jars in specified plugin directory, extracts plugin.xml
-# and copies to the specified output directory.
-# args:
-# - IJ plugin directory
-# - output directory
-attach_plugin_xmls() {
- if [ ! -e $1 ]; then return; fi
- pushd $1 >/dev/null
- jars=(*.jar)
- for jar in ${jars[@]}; do
- plugin=${jar%.jar}
- if [ -e $jar ]; then
- mkdir -p $2
- unzip -p $jar "META-INF/plugin.xml" > "$2/${plugin}.xml"
- [ $? -eq 0 ] || { exit 1; }
- fi
- done
- popd >/dev/null
-}
-
-files=""
-tmp_dir=$(mktemp -d)
-output_name=intellij-bug-report-$USER
-tar_dir=$tmp_dir/$output_name
-output_file=${output_name}.tar.gz
-
-mkdir -p "$tar_dir"
-[ $? -eq 0 ] || { exit 1; }
-
-# Attach process information
-process_info_dir=$tar_dir/process_info
-mkdir -p $process_info_dir
-
-pids=$(jps | awk '/[0-9]+ (Main)$/ { print $1 }')
-ts=$(date +%H%M%S)
-if [ -z "$pids" ]; then
- echo "Warn: Could not find any IntelliJ processes."
-fi
-for pid in $pids
-do
- stack_file=$process_info_dir/stack_${pid}_${ts}.txt
- mem_file=$process_info_dir/mem_${pid}_${ts}.txt
- capacity_file=$process_info_dir/capacity_${pid}_${ts}.txt
- cmd_file=$process_info_dir/cmd_${pid}_${ts}.txt
- uptime_file=$process_info_dir/uptime_${pid}_${ts}.txt
- jps -v | grep $pid > $cmd_file
- jstack $pid > $stack_file
- jstat -gc $pid > $mem_file
- jstat -gccapacity $pid > $capacity_file
- ps -p $pid -o etime= > $uptime_file
-done
-
-# Copy core dumps
-mkdir -p $tar_dir/jvm-dumps
-cp -p $HOME/java_error_in_* $tar_dir/jvm-dumps 2>/dev/null
-
-# Copy vmoptions files
-mkdir -p $tar_dir
-cp -p $HOME/*.vmoptions $tar_dir 2>/dev/null
-
-# Copy details from IJ log directories
-dir_names=(
- '.IntelliJIdea*'
- '.IdeaIC*'
- '.AndroidStudio*'
- '.CLion*'
-)
-# other product codes, to add if we end up supporting them:
-# PhpStorm, WebStorm, RubyMine, PyCharm, WebIde, AppCode, DataGrip
-
-pushd $HOME >/dev/null
-for log_dirs in ${dir_names[@]}; do
- for log_dir in $log_dirs ; do
- if [ ! -e $log_dir ]; then
- continue
- fi
- product=${log_dir:1}
- mkdir ${tar_dir}/${product}
- pushd ${tar_dir}/${product} >/dev/null
-
- # Attach user's log directories
- if [ -d ${HOME}/${log_dir}/system/log ]; then
- mkdir -p "system/log"
- cp -r "${HOME}/${log_dir}/system/log" "system"
- [ $? -eq 0 ] || { exit 1; }
- fi
-
- # Attach product version
- ij_home=$(<"${HOME}/${log_dir}/system/.home")
- cp "${ij_home}/build.txt" "version"
-
- # Attach plugin.xmls
- attach_plugin_xmls "${HOME}/${log_dir}/system/plugins" "${tar_dir}/${product}/system/plugins"
- attach_plugin_xmls "${HOME}/${log_dir}/config/plugins" "${tar_dir}/${product}/config/plugins"
-
- # copy vmoptions
- mkdir -p vmoptions/home
- cp -p ${HOME}/${log_dir}/*.vmoptions vmoptions/home 2>/dev/null
- mkdir -p vmoptions/installation
- cp -p ${ij_home}/bin/*.vmoptions vmoptions/installation 2>/dev/null
-
- popd >/dev/null
- done
-done
-popd >/dev/null
-
-# Attach user's .blazerc
-if [ -f $HOME/.blazerc ]; then
- cp $HOME/.blazerc $tar_dir/.blazerc
-fi
-
-pushd $tmp_dir >/dev/null
-tar -chzf $output_file $output_name
-[ $? -eq 0 ] || { exit 1; }
-popd >/dev/null
-
-tar_file=$tmp_dir/$output_file
-echo "Bug report produced in: $tar_file"
-echo "Path has been copied to clipboard."
-echo -n $tar_file | xclip -selection primary
-echo -n $tar_file | xclip -selection clipboard
-
diff --git a/base/src/META-INF/blaze-base.xml b/base/src/META-INF/blaze-base.xml
index 7559da7..1715ec6 100644
--- a/base/src/META-INF/blaze-base.xml
+++ b/base/src/META-INF/blaze-base.xml
@@ -257,6 +257,7 @@
<extensionPoint qualifiedName="com.google.idea.blaze.BlazePsiDirectoryRootNodeNameModifier" interface="com.google.idea.blaze.base.treeview.BlazePsiDirectoryRootNodeNameModifier"/>
<extensionPoint qualifiedName="com.google.idea.blaze.FileCache" interface="com.google.idea.blaze.base.filecache.FileCache"/>
<extensionPoint qualifiedName="com.google.idea.blaze.TestRuleHeuristic" interface="com.google.idea.blaze.base.run.TestRuleHeuristic"/>
+ <extensionPoint qualifiedName="com.google.idea.blaze.ProjectDataDirectoryValidator" interface="com.google.idea.blaze.base.wizard2.ProjectDataDirectoryValidator"/>
</extensionPoints>
<extensions defaultExtensionNs="com.google.idea.blaze">
diff --git a/base/src/com/google/idea/blaze/base/bazel/BazelBuildSystemProvider.java b/base/src/com/google/idea/blaze/base/bazel/BazelBuildSystemProvider.java
index a3cee43..d207ff2 100644
--- a/base/src/com/google/idea/blaze/base/bazel/BazelBuildSystemProvider.java
+++ b/base/src/com/google/idea/blaze/base/bazel/BazelBuildSystemProvider.java
@@ -16,9 +16,13 @@
package com.google.idea.blaze.base.bazel;
import com.google.common.collect.ImmutableList;
+import com.google.idea.blaze.base.io.FileAttributeProvider;
import com.google.idea.blaze.base.lang.buildfile.language.semantics.RuleDefinition;
import com.google.idea.blaze.base.model.primitives.WorkspaceRoot;
import com.google.idea.blaze.base.settings.Blaze.BuildSystem;
+import com.intellij.openapi.fileTypes.ExactFileNameMatcher;
+import com.intellij.openapi.fileTypes.FileNameMatcher;
+import java.io.File;
import javax.annotation.Nullable;
/** Provides the bazel build system name string. */
@@ -44,6 +48,28 @@
@Override
public String getRuleDocumentationUrl(RuleDefinition rule) {
// TODO: URL pointing to specific BUILD rule.
- return "http://www.bazel.io/docs/be/overview.html";
+ return "http://www.bazel.build/docs/be/overview.html";
+ }
+
+ // TODO: Update the methods below when https://github.com/bazelbuild/bazel/issues/552 lands.
+ @Override
+ public boolean isBuildFile(String fileName) {
+ return fileName.equals("BUILD");
+ }
+
+ @Nullable
+ @Override
+ public File findBuildFileInDirectory(File directory) {
+ FileAttributeProvider provider = FileAttributeProvider.getInstance();
+ File child = new File(directory, "BUILD");
+ if (!provider.exists(child)) {
+ return null;
+ }
+ return child;
+ }
+
+ @Override
+ public FileNameMatcher buildFileMatcher() {
+ return new ExactFileNameMatcher("BUILD");
}
}
diff --git a/base/src/com/google/idea/blaze/base/bazel/BuildSystemProvider.java b/base/src/com/google/idea/blaze/base/bazel/BuildSystemProvider.java
index 42bd43b..4b47716 100644
--- a/base/src/com/google/idea/blaze/base/bazel/BuildSystemProvider.java
+++ b/base/src/com/google/idea/blaze/base/bazel/BuildSystemProvider.java
@@ -21,6 +21,9 @@
import com.google.idea.blaze.base.settings.Blaze.BuildSystem;
import com.intellij.openapi.components.ServiceManager;
import com.intellij.openapi.extensions.ExtensionPointName;
+import com.intellij.openapi.fileTypes.FileNameMatcher;
+import com.intellij.openapi.vfs.VirtualFile;
+import java.io.File;
import javax.annotation.Nullable;
/**
@@ -79,4 +82,27 @@
/** The URL providing the built-in BUILD rule's documentation, if one can be found. */
@Nullable
String getRuleDocumentationUrl(RuleDefinition rule);
+
+ /** Check if the given filename is a valid BUILD file name. */
+ boolean isBuildFile(String fileName);
+
+ /**
+ * Check if the given directory has a child with a valid BUILD file name, and if so, returns the
+ * first such file.
+ */
+ @Nullable
+ File findBuildFileInDirectory(File directory);
+
+ /**
+ * Check if the given directory has a child with a valid BUILD file name, and if so, returns the
+ * first such file.
+ */
+ @Nullable
+ default VirtualFile findBuildFileInDirectory(VirtualFile directory) {
+ File file = new File(directory.getPath());
+ File buildFile = findBuildFileInDirectory(file);
+ return buildFile != null ? directory.getFileSystem().findFileByPath(buildFile.getPath()) : null;
+ }
+
+ FileNameMatcher buildFileMatcher();
}
diff --git a/base/src/com/google/idea/blaze/base/buildmodifier/BazelBuildifierBinaryProvider.java b/base/src/com/google/idea/blaze/base/buildmodifier/BazelBuildifierBinaryProvider.java
index 25079b2..b0b867a 100644
--- a/base/src/com/google/idea/blaze/base/buildmodifier/BazelBuildifierBinaryProvider.java
+++ b/base/src/com/google/idea/blaze/base/buildmodifier/BazelBuildifierBinaryProvider.java
@@ -15,7 +15,7 @@
*/
package com.google.idea.blaze.base.buildmodifier;
-import com.google.idea.blaze.base.util.BlazeHelperBinaryUtil;
+import com.google.idea.common.binaryhelper.HelperBinaryUtil;
import java.io.File;
import javax.annotation.Nullable;
@@ -29,6 +29,6 @@
@Nullable
@Override
public File getBuildifierBinary() {
- return BlazeHelperBinaryUtil.getBlazeHelperBinary(BUILDIFIER_BINARY_PATH);
+ return HelperBinaryUtil.getHelperBinary(BUILDIFIER_BINARY_PATH);
}
}
diff --git a/base/src/com/google/idea/blaze/base/buildmodifier/FileSaveHandler.java b/base/src/com/google/idea/blaze/base/buildmodifier/FileSaveHandler.java
index 02aa3f2..df5e61a 100644
--- a/base/src/com/google/idea/blaze/base/buildmodifier/FileSaveHandler.java
+++ b/base/src/com/google/idea/blaze/base/buildmodifier/FileSaveHandler.java
@@ -15,6 +15,7 @@
*/
package com.google.idea.blaze.base.buildmodifier;
+import com.google.idea.blaze.base.bazel.BuildSystemProvider;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.command.CommandProcessor;
import com.intellij.openapi.editor.Document;
@@ -61,6 +62,6 @@
}
private static boolean isBuildFile(VirtualFile file) {
- return file.getName().equals("BUILD");
+ return BuildSystemProvider.defaultBuildSystem().isBuildFile(file.getName());
}
}
diff --git a/base/src/com/google/idea/blaze/base/command/BlazeFlags.java b/base/src/com/google/idea/blaze/base/command/BlazeFlags.java
index d0d9887..484924b 100644
--- a/base/src/com/google/idea/blaze/base/command/BlazeFlags.java
+++ b/base/src/com/google/idea/blaze/base/command/BlazeFlags.java
@@ -15,7 +15,6 @@
*/
package com.google.idea.blaze.base.command;
-import com.google.common.base.Strings;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Lists;
import com.google.idea.blaze.base.projectview.ProjectViewSet;
@@ -24,9 +23,7 @@
import com.google.idea.blaze.base.settings.Blaze.BuildSystem;
import com.intellij.openapi.project.Project;
import com.intellij.util.PlatformUtils;
-import java.util.Collection;
import java.util.List;
-import javax.annotation.Nullable;
/** The collection of all the Bazel flag strings we use. */
public final class BlazeFlags {
@@ -100,40 +97,5 @@
return TOOL_TAG + platformPrefix;
}
- public static String testFilterFlagForClass(String className) {
- return testFilterFlagForClassAndMethod(className, null);
- }
-
- public static String testFilterFlagForClassAndMethod(
- String className, @Nullable String methodName) {
- StringBuilder output = new StringBuilder(TEST_FILTER);
- output.append('=');
- output.append(className);
-
- if (!Strings.isNullOrEmpty(methodName)) {
- output.append('#');
- output.append(methodName);
- output.append('$');
- }
-
- return output.toString();
- }
-
- public static String testFilterFlagForClassAndMethods(
- String className, Collection<String> methodNames, boolean isJUnit3Class) {
- if (methodNames.size() == 0) {
- return testFilterFlagForClass(className);
- } else if (methodNames.size() == 1) {
- return testFilterFlagForClassAndMethod(className, methodNames.iterator().next());
- }
- String methodNamePattern;
- if (isJUnit3Class) {
- methodNamePattern = String.join(",", methodNames);
- } else {
- methodNamePattern = String.format("(%s)", String.join("|", methodNames));
- }
- return testFilterFlagForClassAndMethod(className, methodNamePattern);
- }
-
private BlazeFlags() {}
}
diff --git a/base/src/com/google/idea/blaze/base/console/BlazeConsoleView.java b/base/src/com/google/idea/blaze/base/console/BlazeConsoleView.java
index f507a52..d5c02c3 100644
--- a/base/src/com/google/idea/blaze/base/console/BlazeConsoleView.java
+++ b/base/src/com/google/idea/blaze/base/console/BlazeConsoleView.java
@@ -90,6 +90,7 @@
Content console =
layoutUi.createContent(
BlazeConsoleToolWindowFactory.ID, myConsoleView.getComponent(), "", null, null);
+ console.setCloseable(false);
layoutUi.addContent(console, 0, PlaceInGrid.right, false);
// Adding actions
@@ -110,6 +111,7 @@
//noinspection ConstantConditions
Content content =
ContentFactory.SERVICE.getInstance().createContent(layoutComponent, null, true);
+ content.setCloseable(false);
toolWindow.getContentManager().addContent(content);
}
diff --git a/base/src/com/google/idea/blaze/base/help/BlazeHelpHandlerImpl.java b/base/src/com/google/idea/blaze/base/help/BlazeHelpHandlerImpl.java
index e9a23b6..ec5471a 100644
--- a/base/src/com/google/idea/blaze/base/help/BlazeHelpHandlerImpl.java
+++ b/base/src/com/google/idea/blaze/base/help/BlazeHelpHandlerImpl.java
@@ -18,7 +18,7 @@
import com.intellij.ide.BrowserUtil;
class BlazeHelpHandlerImpl implements BlazeHelpHandler {
- private static final String URL_BASE = "https://ij.bazel.io/";
+ private static final String URL_BASE = "https://ij.bazel.build/";
@Override
public void handleHelp(String urlFragment) {
diff --git a/base/src/com/google/idea/blaze/base/ide/NewBlazeRuleAction.java b/base/src/com/google/idea/blaze/base/ide/NewBlazeRuleAction.java
index a8aaee8..d67dccf 100644
--- a/base/src/com/google/idea/blaze/base/ide/NewBlazeRuleAction.java
+++ b/base/src/com/google/idea/blaze/base/ide/NewBlazeRuleAction.java
@@ -19,9 +19,7 @@
import com.google.idea.blaze.base.actions.BlazeAction;
import com.google.idea.blaze.base.experiments.ExperimentScope;
import com.google.idea.blaze.base.metrics.Action;
-import com.google.idea.blaze.base.scope.BlazeContext;
import com.google.idea.blaze.base.scope.Scope;
-import com.google.idea.blaze.base.scope.ScopedOperation;
import com.google.idea.blaze.base.scope.scopes.BlazeConsoleScope;
import com.google.idea.blaze.base.scope.scopes.IdeaLogScope;
import com.google.idea.blaze.base.scope.scopes.IssuesScope;
@@ -56,19 +54,16 @@
}
Scope.root(
- new ScopedOperation() {
- @Override
- public void execute(@NotNull BlazeContext context) {
- context
- .push(new ExperimentScope())
- .push(new BlazeConsoleScope.Builder(project).build())
- .push(new IssuesScope(project))
- .push(new IdeaLogScope())
- .push(new LoggedTimingScope(project, Action.CREATE_BLAZE_RULE));
- NewBlazeRuleDialog newBlazeRuleDialog =
- new NewBlazeRuleDialog(context, project, virtualFile);
- newBlazeRuleDialog.show();
- }
+ context -> {
+ context
+ .push(new ExperimentScope())
+ .push(new BlazeConsoleScope.Builder(project).build())
+ .push(new IssuesScope(project))
+ .push(new IdeaLogScope())
+ .push(new LoggedTimingScope(project, Action.CREATE_BLAZE_RULE));
+ NewBlazeRuleDialog newBlazeRuleDialog =
+ new NewBlazeRuleDialog(context, project, virtualFile);
+ newBlazeRuleDialog.show();
});
}
@@ -78,7 +73,10 @@
DataContext dataContext = event.getDataContext();
VirtualFile file = CommonDataKeys.VIRTUAL_FILE.getData(dataContext);
Project project = CommonDataKeys.PROJECT.getData(dataContext);
- boolean enabled = (project != null && file != null && file.getName().equals("BUILD"));
+ boolean enabled =
+ (project != null
+ && file != null
+ && Blaze.getBuildSystemProvider(project).isBuildFile(file.getName()));
presentation.setVisible(enabled || ActionPlaces.isMainMenuOrActionSearch(event.getPlace()));
presentation.setEnabled(enabled);
presentation.setText(getText(project));
diff --git a/base/src/com/google/idea/blaze/base/lang/buildfile/language/BuildFileTypeFactory.java b/base/src/com/google/idea/blaze/base/lang/buildfile/language/BuildFileTypeFactory.java
index 32243bc..4c4a21c 100644
--- a/base/src/com/google/idea/blaze/base/lang/buildfile/language/BuildFileTypeFactory.java
+++ b/base/src/com/google/idea/blaze/base/lang/buildfile/language/BuildFileTypeFactory.java
@@ -15,10 +15,8 @@
*/
package com.google.idea.blaze.base.lang.buildfile.language;
-import com.google.common.collect.ImmutableList;
-import com.intellij.openapi.fileTypes.ExactFileNameMatcher;
+import com.google.idea.blaze.base.bazel.BuildSystemProvider;
import com.intellij.openapi.fileTypes.ExtensionFileNameMatcher;
-import com.intellij.openapi.fileTypes.FileNameMatcher;
import com.intellij.openapi.fileTypes.FileTypeConsumer;
import com.intellij.openapi.fileTypes.FileTypeFactory;
import org.jetbrains.annotations.NotNull;
@@ -26,11 +24,11 @@
/** Factory for BuildFileType */
public class BuildFileTypeFactory extends FileTypeFactory {
- private static ImmutableList<FileNameMatcher> DEFAULT_ASSOCIATIONS =
- ImmutableList.of(new ExactFileNameMatcher("BUILD"), new ExtensionFileNameMatcher("bzl"));
-
@Override
public void createFileTypes(@NotNull final FileTypeConsumer consumer) {
- consumer.consume(BuildFileType.INSTANCE, DEFAULT_ASSOCIATIONS.toArray(new FileNameMatcher[0]));
+ consumer.consume(
+ BuildFileType.INSTANCE,
+ BuildSystemProvider.defaultBuildSystem().buildFileMatcher(),
+ new ExtensionFileNameMatcher("bzl"));
}
}
diff --git a/base/src/com/google/idea/blaze/base/lang/buildfile/references/BuildReferenceManager.java b/base/src/com/google/idea/blaze/base/lang/buildfile/references/BuildReferenceManager.java
index 454ab79..6d728b8 100644
--- a/base/src/com/google/idea/blaze/base/lang/buildfile/references/BuildReferenceManager.java
+++ b/base/src/com/google/idea/blaze/base/lang/buildfile/references/BuildReferenceManager.java
@@ -23,12 +23,14 @@
import com.google.idea.blaze.base.model.primitives.Label;
import com.google.idea.blaze.base.model.primitives.RuleName;
import com.google.idea.blaze.base.model.primitives.WorkspacePath;
+import com.google.idea.blaze.base.settings.Blaze;
import com.google.idea.blaze.base.sync.workspace.WorkspacePathResolver;
import com.google.idea.blaze.base.sync.workspace.WorkspacePathResolverProvider;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.components.ServiceManager;
import com.intellij.openapi.progress.ProgressManager;
import com.intellij.openapi.project.Project;
+import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vfs.LocalFileSystem;
import com.intellij.openapi.vfs.VirtualFile;
@@ -128,6 +130,10 @@
*/
public BuildLookupElement[] resolvePackageLookupElements(FileLookupData lookupData) {
String relativePath = lookupData.filePathFragment;
+ if (!relativePath.equals(FileUtil.toCanonicalUriPath(relativePath))) {
+ // ignore invalid labels containing './', '../', etc.
+ return BuildLookupElement.EMPTY_ARRAY;
+ }
File file = resolveWorkspaceRelativePath(relativePath);
FileAttributeProvider provider = FileAttributeProvider.getInstance();
@@ -155,7 +161,7 @@
List<VirtualFile> validChildren = Lists.newArrayListWithCapacity(children.length);
for (VirtualFile child : children) {
ProgressManager.checkCanceled();
- if (child.getName().startsWith(pathFragment) && lookupData.acceptFile(child)) {
+ if (child.getName().startsWith(pathFragment) && lookupData.acceptFile(project, child)) {
validChildren.add(child);
}
}
@@ -202,15 +208,15 @@
if (packageDirectory == null || !provider.isDirectory(packageDirectory)) {
return null;
}
- File buildFile = new File(packageDirectory, "BUILD");
- if (!provider.exists(buildFile)) {
- return null;
- }
- VirtualFile vf = getFileSystem().findFileByPath(buildFile.getPath());
+ VirtualFile vf = getFileSystem().findFileByPath(packageDirectory.getPath());
if (vf == null) {
return null;
}
- PsiFile psiFile = PsiManager.getInstance(project).findFile(vf);
+ VirtualFile buildFile = Blaze.getBuildSystemProvider(project).findBuildFileInDirectory(vf);
+ if (buildFile == null) {
+ return null;
+ }
+ PsiFile psiFile = PsiManager.getInstance(project).findFile(buildFile);
return psiFile instanceof BuildFile ? (BuildFile) psiFile : null;
}
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 c6fe9ed..eabe428 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
@@ -20,6 +20,7 @@
import com.google.idea.blaze.base.lang.buildfile.psi.StringLiteral;
import com.google.idea.blaze.base.lang.buildfile.search.BlazePackage;
import com.google.idea.blaze.base.model.primitives.WorkspacePath;
+import com.google.idea.blaze.base.settings.Blaze;
import com.intellij.icons.AllIcons;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.NullableLazyValue;
@@ -133,7 +134,7 @@
|| (containingPackage != null && containingFile != null));
}
- public boolean acceptFile(VirtualFile file) {
+ public boolean acceptFile(Project project, VirtualFile file) {
if (fileFilter != null && !fileFilter.accept(file)) {
return false;
}
@@ -143,7 +144,8 @@
if (file.equals(containingFile.getOriginalFile().getVirtualFile())) {
return false;
}
- boolean blazePackage = file.findChild("BUILD") != null;
+ boolean blazePackage =
+ Blaze.getBuildSystemProvider(project).findBuildFileInDirectory(file) != null;
return !blazePackage;
}
@@ -188,6 +190,9 @@
private String getItemText(String relativePath) {
if (pathFormat == PathFormat.PackageLocal) {
+ if (containingPackage.length() > relativePath.length()) {
+ return "";
+ }
return StringUtil.trimStart(relativePath.substring(containingPackage.length()), "/");
}
String parentPath = PathUtil.getParentPath(relativePath);
diff --git a/base/src/com/google/idea/blaze/base/lang/buildfile/search/BlazePackage.java b/base/src/com/google/idea/blaze/base/lang/buildfile/search/BlazePackage.java
index 6c2e3a3..6f1b102 100644
--- a/base/src/com/google/idea/blaze/base/lang/buildfile/search/BlazePackage.java
+++ b/base/src/com/google/idea/blaze/base/lang/buildfile/search/BlazePackage.java
@@ -38,7 +38,8 @@
if (file instanceof PsiFile) {
file = ((PsiFile) file).getOriginalFile();
}
- if (file instanceof BuildFile && file.getName().equals("BUILD")) {
+ if (file instanceof BuildFile
+ && Blaze.getBuildSystemProvider(file.getProject()).isBuildFile(file.getName())) {
return new BlazePackage((BuildFile) file);
}
return getContainingPackage(getPsiDirectory(file));
@@ -61,9 +62,14 @@
@Nullable
public static BlazePackage getContainingPackage(@Nullable PsiDirectory dir) {
while (dir != null) {
- PsiFile buildFile = dir.findFile("BUILD");
+ VirtualFile buildFile =
+ Blaze.getBuildSystemProvider(dir.getProject())
+ .findBuildFileInDirectory(dir.getVirtualFile());
if (buildFile != null) {
- return buildFile instanceof BuildFile ? new BlazePackage((BuildFile) buildFile) : null;
+ PsiFile psiFile = dir.getManager().findFile(buildFile);
+ if (psiFile != null) {
+ return psiFile instanceof BuildFile ? new BlazePackage((BuildFile) psiFile) : null;
+ }
}
dir = dir.getParentDirectory();
}
@@ -151,8 +157,10 @@
}
}
- private static boolean isBlazePackage(PsiDirectory directory) {
- return directory.findFile("BUILD") != null;
+ private static boolean isBlazePackage(PsiDirectory dir) {
+ return Blaze.getBuildSystemProvider(dir.getProject())
+ .findBuildFileInDirectory(dir.getVirtualFile())
+ != null;
}
private static void processDirectory(Processor<PsiFile> processor, PsiDirectory directory) {
diff --git a/base/src/com/google/idea/blaze/base/model/primitives/WorkspacePath.java b/base/src/com/google/idea/blaze/base/model/primitives/WorkspacePath.java
index 3bb2ccd..00ce9ee 100644
--- a/base/src/com/google/idea/blaze/base/model/primitives/WorkspacePath.java
+++ b/base/src/com/google/idea/blaze/base/model/primitives/WorkspacePath.java
@@ -70,7 +70,8 @@
if (relativePath.startsWith("/")) {
BlazeValidationError.collect(
errors,
- new BlazeValidationError("Workspace path may not start with '/': " + relativePath));
+ new BlazeValidationError(
+ "Workspace path must be relative; cannot start with '/': " + relativePath));
return false;
}
diff --git a/base/src/com/google/idea/blaze/base/settings/Blaze.java b/base/src/com/google/idea/blaze/base/settings/Blaze.java
index d9e5537..65d5b93 100644
--- a/base/src/com/google/idea/blaze/base/settings/Blaze.java
+++ b/base/src/com/google/idea/blaze/base/settings/Blaze.java
@@ -77,7 +77,9 @@
* blaze build system if the project is null or not a blaze project.
*/
public static BuildSystemProvider getBuildSystemProvider(@Nullable Project project) {
- return BuildSystemProvider.getBuildSystemProvider(getBuildSystem(project));
+ BuildSystemProvider provider =
+ BuildSystemProvider.getBuildSystemProvider(getBuildSystem(project));
+ return provider != null ? provider : BuildSystemProvider.defaultBuildSystem();
}
/**
diff --git a/base/src/com/google/idea/blaze/base/settings/ui/BlazeUserSettingsConfigurable.java b/base/src/com/google/idea/blaze/base/settings/ui/BlazeUserSettingsConfigurable.java
index d541dc9..3b09467 100644
--- a/base/src/com/google/idea/blaze/base/settings/ui/BlazeUserSettingsConfigurable.java
+++ b/base/src/com/google/idea/blaze/base/settings/ui/BlazeUserSettingsConfigurable.java
@@ -119,8 +119,12 @@
suppressConsoleForRunAction.isSelected(), settings.getSuppressConsoleForRunAction())
|| !Objects.equal(resyncAutomatically.isSelected(), settings.getResyncAutomatically())
|| !Objects.equal(collapseProjectView.isSelected(), settings.getCollapseProjectView())
- || !Objects.equal(blazeBinaryPathField.getText(), settings.getBlazeBinaryPath())
- || !Objects.equal(bazelBinaryPathField.getText(), settings.getBazelBinaryPath());
+ || !Objects.equal(
+ Strings.nullToEmpty(blazeBinaryPathField.getText()),
+ Strings.nullToEmpty(settings.getBlazeBinaryPath()))
+ || !Objects.equal(
+ Strings.nullToEmpty(bazelBinaryPathField.getText()),
+ Strings.nullToEmpty(settings.getBazelBinaryPath()));
for (BlazeUserSettingsContributor settingsContributor : settingsContributors) {
isModified |= settingsContributor.isModified();
diff --git a/base/src/com/google/idea/blaze/base/sync/BlazeSyncPlugin.java b/base/src/com/google/idea/blaze/base/sync/BlazeSyncPlugin.java
index 4c7d64e..f2639cf 100644
--- a/base/src/com/google/idea/blaze/base/sync/BlazeSyncPlugin.java
+++ b/base/src/com/google/idea/blaze/base/sync/BlazeSyncPlugin.java
@@ -90,6 +90,9 @@
/** @return The set of supported languages under this workspace type. */
Set<LanguageClass> getSupportedLanguagesInWorkspace(WorkspaceType workspaceType);
+ /** Installs any global SDKs */
+ void installSdks(BlazeContext context);
+
/** Given the rule map, update the sync state for this plugin. Should not have side effects. */
void updateSyncState(
Project project,
@@ -105,8 +108,8 @@
SyncState.Builder syncStateBuilder,
@Nullable SyncState previousSyncState);
- /** Updates the sdk. */
- void updateSdk(
+ /** Updates the sdk for the project. */
+ void updateProjectSdk(
Project project,
BlazeContext context,
ProjectViewSet projectViewSet,
@@ -152,9 +155,6 @@
/** Returns any custom sections that this plugin supports. */
Collection<SectionParser> getSections();
- /** Returns whether this plugin requires resolving ide artifacts to function. */
- boolean requiresResolveIdeArtifacts();
-
/** Convenience adapter to help stubbing out methods. */
class Adapter implements BlazeSyncPlugin {
@@ -176,6 +176,9 @@
}
@Override
+ public void installSdks(BlazeContext context) {}
+
+ @Override
public void updateSyncState(
Project project,
BlazeContext context,
@@ -191,7 +194,7 @@
@Nullable SyncState previousSyncState) {}
@Override
- public void updateSdk(
+ public void updateProjectSdk(
Project project,
BlazeContext context,
ProjectViewSet projectViewSet,
@@ -237,9 +240,5 @@
return ImmutableList.of();
}
- @Override
- public boolean requiresResolveIdeArtifacts() {
- return false;
- }
}
}
diff --git a/base/src/com/google/idea/blaze/base/sync/BlazeSyncTask.java b/base/src/com/google/idea/blaze/base/sync/BlazeSyncTask.java
index 6b5c4dc..d8d3642 100755
--- a/base/src/com/google/idea/blaze/base/sync/BlazeSyncTask.java
+++ b/base/src/com/google/idea/blaze/base/sync/BlazeSyncTask.java
@@ -19,6 +19,7 @@
import com.google.common.collect.ImmutableMultimap;
import com.google.common.collect.Iterables;
import com.google.common.collect.Lists;
+import com.google.common.collect.Sets;
import com.google.common.util.concurrent.ListenableFuture;
import com.google.common.util.concurrent.ListeningExecutorService;
import com.google.idea.blaze.base.async.AsyncUtil;
@@ -66,6 +67,7 @@
import com.google.idea.blaze.base.sync.projectstructure.ContentEntryEditor;
import com.google.idea.blaze.base.sync.projectstructure.ModuleEditorImpl;
import com.google.idea.blaze.base.sync.projectstructure.ModuleEditorProvider;
+import com.google.idea.blaze.base.sync.projectview.ImportRoots;
import com.google.idea.blaze.base.sync.projectview.LanguageSupport;
import com.google.idea.blaze.base.sync.projectview.WorkspaceLanguageSettings;
import com.google.idea.blaze.base.sync.workspace.ArtifactLocationDecoder;
@@ -92,6 +94,7 @@
import java.util.Collection;
import java.util.Collections;
import java.util.List;
+import java.util.Set;
import java.util.stream.Collectors;
import javax.annotation.Nullable;
@@ -226,6 +229,10 @@
return SyncResult.FAILURE;
}
+ for (BlazeSyncPlugin syncPlugin : BlazeSyncPlugin.EP_NAME.getExtensions()) {
+ syncPlugin.installSdks(context);
+ }
+
if (!ProjectViewVerifier.verifyProjectView(
context, workspaceRoot, projectViewSet, workspaceLanguageSettings)) {
return SyncResult.FAILURE;
@@ -258,17 +265,12 @@
SyncState previousSyncState =
oldBlazeProjectData != null ? oldBlazeProjectData.syncState : null;
- boolean syncPluginRequiresBuild = false;
- for (BlazeSyncPlugin syncPlugin : BlazeSyncPlugin.EP_NAME.getExtensions()) {
- syncPluginRequiresBuild |= syncPlugin.requiresResolveIdeArtifacts();
- }
-
List<TargetExpression> targets = Lists.newArrayList();
if (syncParams.addProjectViewTargets || oldBlazeProjectData == null) {
targets.addAll(projectViewSet.listItems(TargetSection.KEY));
}
if (syncParams.addWorkingSet && workingSet != null) {
- targets.addAll(getWorkingSetTargets(workingSet));
+ targets.addAll(getWorkingSetTargets(projectViewSet, workingSet));
}
targets.addAll(syncParams.targetExpressions);
@@ -298,14 +300,11 @@
ListenableFuture<ImmutableMultimap<RuleKey, RuleKey>> reverseDependenciesFuture =
BlazeExecutor.getInstance().submit(() -> ReverseDependencyMap.createRdepsMap(ruleMap));
- boolean doResolve = syncPluginRequiresBuild || oldBlazeProjectData == null;
- if (doResolve) {
- ideResolveResult =
- resolveIdeArtifacts(project, context, workspaceRoot, projectViewSet, targets);
- if (ideResolveResult == BuildResult.FATAL_ERROR) {
- context.setHasError();
- return SyncResult.FAILURE;
- }
+ ideResolveResult =
+ resolveIdeArtifacts(project, context, workspaceRoot, projectViewSet, targets);
+ if (ideResolveResult == BuildResult.FATAL_ERROR) {
+ context.setHasError();
+ return SyncResult.FAILURE;
}
if (context.isCancelled()) {
return SyncResult.CANCELLED;
@@ -494,15 +493,22 @@
}
}
- private Collection<? extends TargetExpression> getWorkingSetTargets(WorkingSet workingSet) {
- List<TargetExpression> result = Lists.newArrayList();
+ private Collection<? extends TargetExpression> getWorkingSetTargets(
+ ProjectViewSet projectViewSet, WorkingSet workingSet) {
+ ImportRoots importRoots =
+ ImportRoots.builder(workspaceRoot, importSettings.getBuildSystem())
+ .add(projectViewSet)
+ .build();
+ BuildTargetFinder buildTargetFinder =
+ new BuildTargetFinder(project, workspaceRoot, importRoots);
+
+ Set<TargetExpression> result = Sets.newHashSet();
for (WorkspacePath workspacePath :
Iterables.concat(workingSet.addedFiles, workingSet.modifiedFiles)) {
- File buildFile = workspaceRoot.fileForPath(workspacePath);
- if (buildFile.getName().equals("BUILD")) {
- result.add(
- TargetExpression.allFromPackageNonRecursive(
- workspaceRoot.workspacePathFor(buildFile.getParentFile())));
+ File file = workspaceRoot.fileForPath(workspacePath);
+ TargetExpression targetExpression = buildTargetFinder.findTargetForFile(file);
+ if (targetExpression != null) {
+ result.add(targetExpression);
}
}
return result;
@@ -587,7 +593,7 @@
ProjectRootManagerEx.getInstanceEx(this.project)
.mergeRootsChangesDuring(
() -> {
- updateSdk(context, projectViewSet, newBlazeProjectData);
+ updateProjectSdk(context, projectViewSet, newBlazeProjectData);
updateProjectStructure(
context,
importSettings,
@@ -607,10 +613,10 @@
});
}
- private void updateSdk(
+ private void updateProjectSdk(
BlazeContext context, ProjectViewSet projectViewSet, BlazeProjectData newBlazeProjectData) {
for (BlazeSyncPlugin syncPlugin : BlazeSyncPlugin.EP_NAME.getExtensions()) {
- syncPlugin.updateSdk(project, context, projectViewSet, newBlazeProjectData);
+ syncPlugin.updateProjectSdk(project, context, projectViewSet, newBlazeProjectData);
}
}
diff --git a/base/src/com/google/idea/blaze/base/sync/BuildTargetFinder.java b/base/src/com/google/idea/blaze/base/sync/BuildTargetFinder.java
new file mode 100644
index 0000000..8525a20
--- /dev/null
+++ b/base/src/com/google/idea/blaze/base/sync/BuildTargetFinder.java
@@ -0,0 +1,77 @@
+/*
+ * Copyright 2016 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.sync;
+
+import com.google.idea.blaze.base.bazel.BuildSystemProvider;
+import com.google.idea.blaze.base.io.FileAttributeProvider;
+import com.google.idea.blaze.base.model.primitives.TargetExpression;
+import com.google.idea.blaze.base.model.primitives.WorkspaceRoot;
+import com.google.idea.blaze.base.settings.Blaze;
+import com.google.idea.blaze.base.sync.projectview.ImportRoots;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.util.io.FileUtil;
+import java.io.File;
+import javax.annotation.Nullable;
+
+/** Finds the best target to sync for a file. */
+public class BuildTargetFinder {
+ private final WorkspaceRoot workspaceRoot;
+ private final ImportRoots importRoots;
+ private final FileAttributeProvider fileAttributeProvider;
+ private final BuildSystemProvider buildSystemProvider;
+
+ public BuildTargetFinder(Project project, WorkspaceRoot workspaceRoot, ImportRoots importRoots) {
+ this.workspaceRoot = workspaceRoot;
+ this.importRoots = importRoots;
+ this.fileAttributeProvider = FileAttributeProvider.getInstance();
+ this.buildSystemProvider = Blaze.getBuildSystemProvider(project);
+ }
+
+ @Nullable
+ public TargetExpression findTargetForFile(File file) {
+ if (fileAttributeProvider.isFile(file)) {
+ file = file.getParentFile();
+ if (file == null) {
+ return null;
+ }
+ }
+
+ final File directory = file;
+ File root =
+ importRoots
+ .rootDirectories()
+ .stream()
+ .map(workspaceRoot::fileForPath)
+ .filter(potentialRoot -> FileUtil.isAncestor(potentialRoot, directory, false))
+ .findFirst()
+ .orElse(null);
+ if (root == null) {
+ return null;
+ }
+
+ File currentDirectory = directory;
+ do {
+ File buildFile = buildSystemProvider.findBuildFileInDirectory(currentDirectory);
+ if (buildFile != null) {
+ return TargetExpression.allFromPackageNonRecursive(
+ workspaceRoot.workspacePathFor(currentDirectory));
+ }
+ currentDirectory = currentDirectory.getParentFile();
+ } while (currentDirectory != null && FileUtil.isAncestor(root, currentDirectory, false));
+
+ return null;
+ }
+}
diff --git a/base/src/com/google/idea/blaze/base/sync/actions/PartialSyncAction.java b/base/src/com/google/idea/blaze/base/sync/actions/PartialSyncAction.java
index cba67de..08010af 100644
--- a/base/src/com/google/idea/blaze/base/sync/actions/PartialSyncAction.java
+++ b/base/src/com/google/idea/blaze/base/sync/actions/PartialSyncAction.java
@@ -19,10 +19,15 @@
import com.google.idea.blaze.base.actions.BlazeAction;
import com.google.idea.blaze.base.model.primitives.TargetExpression;
import com.google.idea.blaze.base.model.primitives.WorkspaceRoot;
+import com.google.idea.blaze.base.projectview.ProjectViewManager;
+import com.google.idea.blaze.base.projectview.ProjectViewSet;
import com.google.idea.blaze.base.rulemaps.SourceToRuleMap;
import com.google.idea.blaze.base.settings.Blaze;
+import com.google.idea.blaze.base.settings.Blaze.BuildSystem;
import com.google.idea.blaze.base.sync.BlazeSyncManager;
import com.google.idea.blaze.base.sync.BlazeSyncParams;
+import com.google.idea.blaze.base.sync.BuildTargetFinder;
+import com.google.idea.blaze.base.sync.projectview.ImportRoots;
import com.intellij.openapi.actionSystem.AnActionEvent;
import com.intellij.openapi.actionSystem.CommonDataKeys;
import com.intellij.openapi.actionSystem.Presentation;
@@ -80,32 +85,29 @@
return null;
}
- String objectName = null;
WorkspaceRoot workspaceRoot = WorkspaceRoot.fromProject(project);
+ SourceToRuleMap.getInstance(project);
- if (virtualFile.isDirectory()) {
- if (workspaceRoot.isInWorkspace(virtualFile)) {
- targets.add(
- TargetExpression.allFromPackageRecursive(workspaceRoot.workspacePathFor(virtualFile)));
- }
- objectName = "Package";
- } else {
+ String objectName = virtualFile.isDirectory() ? "Package" : "File";
+ if (!virtualFile.isDirectory()) {
targets.addAll(
SourceToRuleMap.getInstance(project)
.getTargetsToBuildForSourceFile(new File(virtualFile.getPath())));
-
- // If empty, try to build parent package
- if (targets.isEmpty()) {
- VirtualFile parent = virtualFile.getParent();
- if (parent.isDirectory()) {
- if (workspaceRoot.isInWorkspace(parent)) {
- targets.add(
- TargetExpression.allFromPackageNonRecursive(
- workspaceRoot.workspacePathFor(parent)));
- }
+ }
+ if (targets.isEmpty()) {
+ ProjectViewSet projectViewSet = ProjectViewManager.getInstance(project).getProjectViewSet();
+ if (projectViewSet != null) {
+ BuildSystem buildSystem = Blaze.getBuildSystem(project);
+ ImportRoots importRoots =
+ ImportRoots.builder(workspaceRoot, buildSystem).add(projectViewSet).build();
+ BuildTargetFinder buildTargetFinder =
+ new BuildTargetFinder(project, workspaceRoot, importRoots);
+ TargetExpression targetExpression =
+ buildTargetFinder.findTargetForFile(new File(virtualFile.getPath()));
+ if (targetExpression != null) {
+ targets.add(targetExpression);
}
}
- objectName = "File";
}
return objectName;
diff --git a/base/src/com/google/idea/blaze/base/sync/status/BlazeSyncStatusImpl.java b/base/src/com/google/idea/blaze/base/sync/status/BlazeSyncStatusImpl.java
index a6b062b..396f27d 100644
--- a/base/src/com/google/idea/blaze/base/sync/status/BlazeSyncStatusImpl.java
+++ b/base/src/com/google/idea/blaze/base/sync/status/BlazeSyncStatusImpl.java
@@ -16,6 +16,7 @@
package com.google.idea.blaze.base.sync.status;
import com.google.idea.blaze.base.projectview.ProjectViewStorageManager;
+import com.google.idea.blaze.base.settings.Blaze;
import com.google.idea.blaze.base.settings.BlazeUserSettings;
import com.google.idea.blaze.base.sync.BlazeSyncManager;
import com.google.idea.blaze.base.sync.BlazeSyncParams;
@@ -175,7 +176,7 @@
/**
* Listens for changes to files which impact the sync process (BUILD files and project view files)
*/
- private static class FileFocusListener extends FileEditorManagerAdapter {
+ private class FileFocusListener extends FileEditorManagerAdapter {
@Override
public void fileClosed(@NotNull FileEditorManager source, @NotNull VirtualFile file) {
processEvent(file);
@@ -197,12 +198,12 @@
}
}
- private static boolean isSyncSensitiveFile(@Nullable VirtualFile file) {
+ private boolean isSyncSensitiveFile(@Nullable VirtualFile file) {
return file != null
&& (isBuildFile(file) || ProjectViewStorageManager.isProjectViewFile(file.getPath()));
}
- private static boolean isBuildFile(VirtualFile file) {
- return file.getName().equals("BUILD");
+ private boolean isBuildFile(VirtualFile file) {
+ return Blaze.getBuildSystemProvider(project).isBuildFile(file.getName());
}
}
diff --git a/base/src/com/google/idea/blaze/base/sync/workspace/BlazeRoots.java b/base/src/com/google/idea/blaze/base/sync/workspace/BlazeRoots.java
index 092fb48..bd54a39 100644
--- a/base/src/com/google/idea/blaze/base/sync/workspace/BlazeRoots.java
+++ b/base/src/com/google/idea/blaze/base/sync/workspace/BlazeRoots.java
@@ -125,4 +125,8 @@
this.blazeBinExecutionRootPath = blazeBinExecutionRootPath;
this.blazeGenfilesExecutionRootPath = blazeGenfilesExecutionRootPath;
}
+
+ public File getGenfilesDirectory() {
+ return blazeGenfilesExecutionRootPath.getFileRootedAt(executionRoot);
+ }
}
diff --git a/base/src/com/google/idea/blaze/base/wizard2/BlazeNewProjectBuilder.java b/base/src/com/google/idea/blaze/base/wizard2/BlazeNewProjectBuilder.java
index ad36704..11b4fbb 100644
--- a/base/src/com/google/idea/blaze/base/wizard2/BlazeNewProjectBuilder.java
+++ b/base/src/com/google/idea/blaze/base/wizard2/BlazeNewProjectBuilder.java
@@ -15,6 +15,10 @@
*/
package com.google.idea.blaze.base.wizard2;
+import com.google.common.base.Joiner;
+import com.google.common.base.Strings;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.Lists;
import com.google.idea.blaze.base.model.primitives.WorkspaceRoot;
import com.google.idea.blaze.base.plugin.dependency.PluginDependencyHelper;
import com.google.idea.blaze.base.projectview.ProjectView;
@@ -30,19 +34,25 @@
import com.intellij.openapi.util.text.StringUtil;
import java.io.File;
import java.io.IOException;
+import java.util.Arrays;
+import java.util.List;
import java.util.UUID;
/** Contains the state to build a new project throughout the new project wizard process. */
public final class BlazeNewProjectBuilder {
private static final Logger LOG = Logger.getInstance(BlazeNewProjectBuilder.class);
+ // The import wizard should keep this many items around for fields that care about history
+ public static final int HISTORY_SIZE = 8;
+
// Stored in user settings as the last imported workspace
private static final String LAST_IMPORTED_BLAZE_WORKSPACE =
"blaze-wizard.last-imported-workspace";
private static final String LAST_IMPORTED_BAZEL_WORKSPACE =
"blaze-wizard.last-imported-bazel-workspace";
+ private static final String HISTORY_SEPARATOR = "::";
- public static String lastImportedWorkspaceKey(BuildSystem buildSystem) {
+ private static String lastImportedWorkspaceKey(BuildSystem buildSystem) {
switch (buildSystem) {
case Blaze:
return LAST_IMPORTED_BLAZE_WORKSPACE;
@@ -72,6 +82,29 @@
return userSettings;
}
+ public String getLastImportedWorkspace(BuildSystem buildSystem) {
+ List<String> workspaceHistory = getWorkspaceHistory(buildSystem);
+ return workspaceHistory.isEmpty() ? "" : workspaceHistory.get(0);
+ }
+
+ public List<String> getWorkspaceHistory(BuildSystem buildSystem) {
+ String value = userSettings.get(lastImportedWorkspaceKey(buildSystem), "");
+ return Strings.isNullOrEmpty(value)
+ ? ImmutableList.of()
+ : Arrays.asList(value.split(HISTORY_SEPARATOR));
+ }
+
+ private void writeWorkspaceHistory(BuildSystem buildSystem, String newValue) {
+ List<String> history = Lists.newArrayList(getWorkspaceHistory(buildSystem));
+ history.remove(newValue);
+ history.add(0, newValue);
+ while (history.size() > HISTORY_SIZE) {
+ history.remove(history.size() - 1);
+ }
+ userSettings.put(
+ lastImportedWorkspaceKey(buildSystem), Joiner.on(HISTORY_SEPARATOR).join(history));
+ }
+
public BlazeSelectWorkspaceOption getWorkspaceOption() {
return workspaceOption;
}
@@ -151,8 +184,8 @@
workspaceOption.commit();
projectViewOption.commit();
- String workspaceKey = lastImportedWorkspaceKey(workspaceOption.getBuildSystemForWorkspace());
- userSettings.put(workspaceKey, workspaceRoot.toString());
+ BuildSystem buildSystem = workspaceOption.getBuildSystemForWorkspace();
+ writeWorkspaceHistory(buildSystem, workspaceRoot.toString());
if (!StringUtil.isEmpty(projectDataDirectory)) {
File projectDataDir = new File(projectDataDirectory);
diff --git a/base/src/com/google/idea/blaze/base/wizard2/CopyExternalProjectViewOption.java b/base/src/com/google/idea/blaze/base/wizard2/CopyExternalProjectViewOption.java
index 437f736..2d94db8 100644
--- a/base/src/com/google/idea/blaze/base/wizard2/CopyExternalProjectViewOption.java
+++ b/base/src/com/google/idea/blaze/base/wizard2/CopyExternalProjectViewOption.java
@@ -24,6 +24,7 @@
import com.intellij.openapi.fileChooser.FileChooserFactory;
import com.intellij.openapi.vfs.LocalFileSystem;
import com.intellij.openapi.vfs.VirtualFile;
+import com.intellij.ui.TextFieldWithStoredHistory;
import java.awt.Dimension;
import java.io.File;
import java.io.IOException;
@@ -34,20 +35,20 @@
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JLabel;
-import javax.swing.JTextField;
class CopyExternalProjectViewOption implements BlazeSelectProjectViewOption {
private static final String LAST_WORKSPACE_PATH = "copy-external.last-project-view-path";
final BlazeWizardUserSettings userSettings;
final JComponent component;
- final JTextField projectViewPathField;
+ final TextFieldWithStoredHistory projectViewPathField;
CopyExternalProjectViewOption(BlazeNewProjectBuilder builder) {
this.userSettings = builder.getUserSettings();
- String defaultWorkspacePath = userSettings.get(LAST_WORKSPACE_PATH, "");
- this.projectViewPathField = new JTextField(defaultWorkspacePath);
+ this.projectViewPathField = new TextFieldWithStoredHistory(LAST_WORKSPACE_PATH);
+ projectViewPathField.setHistorySize(BlazeNewProjectBuilder.HISTORY_SIZE);
+ projectViewPathField.setText(userSettings.get(LAST_WORKSPACE_PATH, ""));
JButton button = new JButton("...");
button.addActionListener(action -> chooseWorkspacePath());
@@ -108,6 +109,7 @@
@Override
public void commit() {
userSettings.put(LAST_WORKSPACE_PATH, getProjectViewPath());
+ projectViewPathField.addCurrentTextToHistory();
}
private String getProjectViewPath() {
diff --git a/base/src/com/google/idea/blaze/base/wizard2/GenerateFromBuildFileSelectProjectViewOption.java b/base/src/com/google/idea/blaze/base/wizard2/GenerateFromBuildFileSelectProjectViewOption.java
index 9826c2a..dce0fb7 100644
--- a/base/src/com/google/idea/blaze/base/wizard2/GenerateFromBuildFileSelectProjectViewOption.java
+++ b/base/src/com/google/idea/blaze/base/wizard2/GenerateFromBuildFileSelectProjectViewOption.java
@@ -15,6 +15,7 @@
*/
package com.google.idea.blaze.base.wizard2;
+import com.google.idea.blaze.base.bazel.BuildSystemProvider;
import com.google.idea.blaze.base.model.primitives.TargetExpression;
import com.google.idea.blaze.base.model.primitives.WorkspacePath;
import com.google.idea.blaze.base.model.primitives.WorkspaceRoot;
@@ -32,29 +33,31 @@
import com.intellij.openapi.fileChooser.FileChooserDialog;
import com.intellij.openapi.fileChooser.FileChooserFactory;
import com.intellij.openapi.util.io.FileUtil;
+import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vfs.LocalFileSystem;
import com.intellij.openapi.vfs.VirtualFile;
+import com.intellij.ui.TextFieldWithStoredHistory;
import java.awt.Dimension;
import java.io.File;
import javax.annotation.Nullable;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JLabel;
-import javax.swing.JTextField;
class GenerateFromBuildFileSelectProjectViewOption implements BlazeSelectProjectViewOption {
private static final String LAST_WORKSPACE_PATH = "generate-from-build-file.last-workspace-path";
private final BlazeNewProjectBuilder builder;
private final BlazeWizardUserSettings userSettings;
- private final JTextField buildFilePathField;
+ private final TextFieldWithStoredHistory buildFilePathField;
private final JComponent component;
public GenerateFromBuildFileSelectProjectViewOption(BlazeNewProjectBuilder builder) {
this.builder = builder;
this.userSettings = builder.getUserSettings();
- String defaultWorkspacePath = userSettings.get(LAST_WORKSPACE_PATH, "");
- this.buildFilePathField = new JTextField(defaultWorkspacePath);
+ this.buildFilePathField = new TextFieldWithStoredHistory(LAST_WORKSPACE_PATH);
+ buildFilePathField.setHistorySize(BlazeNewProjectBuilder.HISTORY_SIZE);
+ buildFilePathField.setText(userSettings.get(LAST_WORKSPACE_PATH, ""));
JButton button = new JButton("...");
button.addActionListener(action -> chooseWorkspacePath());
@@ -117,6 +120,7 @@
@Override
public void commit() {
userSettings.put(LAST_WORKSPACE_PATH, getBuildFilePath());
+ buildFilePathField.addCurrentTextToHistory();
}
private static String guessProjectViewFromLocation(
@@ -174,13 +178,15 @@
}
private void chooseWorkspacePath() {
+ BuildSystemProvider buildSystem =
+ BuildSystemProvider.getBuildSystemProvider(builder.getBuildSystem());
FileChooserDescriptor descriptor =
new FileChooserDescriptor(true, false, false, false, false, false)
.withShowHiddenFiles(true) // Show root project view file
.withHideIgnored(false)
.withTitle("Select BUILD File")
.withDescription("Select a BUILD file to synthesize a project view from.")
- .withFileFilter(virtualFile -> virtualFile.getName().equals("BUILD"));
+ .withFileFilter(virtualFile -> buildSystem.isBuildFile(virtualFile.getName()));
FileChooserDialog chooser =
FileChooserFactory.getInstance().createFileChooser(descriptor, null, null);
@@ -188,10 +194,15 @@
File startingLocation = temporaryWorkspaceRoot.directory();
String buildFilePath = getBuildFilePath();
- if (!buildFilePath.isEmpty()) {
- File fileLocation = temporaryWorkspaceRoot.fileForPath(new WorkspacePath(buildFilePath));
- if (fileLocation.exists()) {
- startingLocation = fileLocation;
+ if (!buildFilePath.isEmpty() && WorkspacePath.validate(buildFilePath)) {
+ // If the user has typed part of the path then clicked the '...', try to start from the
+ // partial state
+ buildFilePath = StringUtil.trimEnd(buildFilePath, '/');
+ if (WorkspacePath.validate(buildFilePath)) {
+ File fileLocation = temporaryWorkspaceRoot.fileForPath(new WorkspacePath(buildFilePath));
+ if (fileLocation.exists()) {
+ startingLocation = fileLocation;
+ }
}
}
VirtualFile toSelect =
diff --git a/base/src/com/google/idea/blaze/base/wizard2/ImportFromWorkspaceProjectViewOption.java b/base/src/com/google/idea/blaze/base/wizard2/ImportFromWorkspaceProjectViewOption.java
index 1162d05..b7f2340 100644
--- a/base/src/com/google/idea/blaze/base/wizard2/ImportFromWorkspaceProjectViewOption.java
+++ b/base/src/com/google/idea/blaze/base/wizard2/ImportFromWorkspaceProjectViewOption.java
@@ -15,9 +15,11 @@
*/
package com.google.idea.blaze.base.wizard2;
+import com.google.common.collect.Lists;
import com.google.idea.blaze.base.model.primitives.WorkspacePath;
import com.google.idea.blaze.base.model.primitives.WorkspaceRoot;
import com.google.idea.blaze.base.projectview.ProjectViewStorageManager;
+import com.google.idea.blaze.base.ui.BlazeValidationError;
import com.google.idea.blaze.base.ui.BlazeValidationResult;
import com.google.idea.blaze.base.ui.UiUtil;
import com.intellij.openapi.fileChooser.FileChooserDescriptor;
@@ -28,13 +30,14 @@
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vfs.LocalFileSystem;
import com.intellij.openapi.vfs.VirtualFile;
+import com.intellij.ui.TextFieldWithStoredHistory;
import java.awt.Dimension;
import java.io.File;
+import java.util.List;
import javax.annotation.Nullable;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JLabel;
-import javax.swing.JTextField;
class ImportFromWorkspaceProjectViewOption implements BlazeSelectProjectViewOption {
private static final String LAST_WORKSPACE_PATH = "import-from-workspace.last-workspace-path";
@@ -42,14 +45,15 @@
final BlazeNewProjectBuilder builder;
final BlazeWizardUserSettings userSettings;
final JComponent component;
- final JTextField projectViewPathField;
+ final TextFieldWithStoredHistory projectViewPathField;
ImportFromWorkspaceProjectViewOption(BlazeNewProjectBuilder builder) {
this.builder = builder;
this.userSettings = builder.getUserSettings();
- String defaultWorkspacePath = userSettings.get(LAST_WORKSPACE_PATH, "");
- this.projectViewPathField = new JTextField(defaultWorkspacePath);
+ this.projectViewPathField = new TextFieldWithStoredHistory(LAST_WORKSPACE_PATH);
+ projectViewPathField.setHistorySize(BlazeNewProjectBuilder.HISTORY_SIZE);
+ projectViewPathField.setText(userSettings.get(LAST_WORKSPACE_PATH, ""));
JButton button = new JButton("...");
button.addActionListener(action -> chooseWorkspacePath());
@@ -83,6 +87,10 @@
if (getProjectViewPath().isEmpty()) {
return BlazeValidationResult.failure("Workspace path to project view file cannot be empty.");
}
+ List<BlazeValidationError> errors = Lists.newArrayList();
+ if (!WorkspacePath.validate(getProjectViewPath(), errors)) {
+ return BlazeValidationResult.failure(errors.get(0));
+ }
WorkspaceRoot temporaryWorkspaceRoot = builder.getWorkspaceOption().getTemporaryWorkspaceRoot();
File file = temporaryWorkspaceRoot.fileForPath(getSharedProjectView());
if (!file.exists()) {
@@ -107,6 +115,7 @@
@Override
public void commit() {
userSettings.put(LAST_WORKSPACE_PATH, getProjectViewPath());
+ projectViewPathField.addCurrentTextToHistory();
}
private String getProjectViewPath() {
@@ -131,12 +140,14 @@
File startingLocation = temporaryWorkspaceRoot.directory();
String projectViewPath = getProjectViewPath();
if (!projectViewPath.isEmpty()) {
- // Avoid exception -- workspace paths cannot end with trailing slash
+ // If the user has typed part of the path then clicked the '...', try to start from the
+ // partial state
projectViewPath = StringUtil.trimEnd(projectViewPath, '/');
-
- File fileLocation = temporaryWorkspaceRoot.fileForPath(new WorkspacePath(projectViewPath));
- if (fileLocation.exists()) {
- startingLocation = fileLocation;
+ if (WorkspacePath.validate(projectViewPath)) {
+ File fileLocation = temporaryWorkspaceRoot.fileForPath(new WorkspacePath(projectViewPath));
+ if (fileLocation.exists()) {
+ startingLocation = fileLocation;
+ }
}
}
VirtualFile toSelect =
diff --git a/base/src/com/google/idea/blaze/base/wizard2/ProjectDataDirectoryValidator.java b/base/src/com/google/idea/blaze/base/wizard2/ProjectDataDirectoryValidator.java
new file mode 100644
index 0000000..0c3520d
--- /dev/null
+++ b/base/src/com/google/idea/blaze/base/wizard2/ProjectDataDirectoryValidator.java
@@ -0,0 +1,28 @@
+/*
+ * Copyright 2016 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.wizard2;
+
+import com.google.idea.blaze.base.ui.BlazeValidationResult;
+import com.intellij.openapi.extensions.ExtensionPointName;
+import java.io.File;
+
+/** Validates the project data directory. */
+public interface ProjectDataDirectoryValidator {
+ ExtensionPointName<ProjectDataDirectoryValidator> EP_NAME =
+ ExtensionPointName.create("com.google.idea.blaze.ProjectDataDirectoryValidator");
+
+ BlazeValidationResult validateDataDirectory(File projectDataDirectory);
+}
diff --git a/base/src/com/google/idea/blaze/base/wizard2/UseExistingWorkspaceOption.java b/base/src/com/google/idea/blaze/base/wizard2/UseExistingWorkspaceOption.java
index 9d18f4e..cff86ed 100644
--- a/base/src/com/google/idea/blaze/base/wizard2/UseExistingWorkspaceOption.java
+++ b/base/src/com/google/idea/blaze/base/wizard2/UseExistingWorkspaceOption.java
@@ -28,6 +28,7 @@
import com.intellij.openapi.util.IconLoader;
import com.intellij.openapi.vfs.LocalFileSystem;
import com.intellij.openapi.vfs.VirtualFile;
+import com.intellij.ui.TextFieldWithHistory;
import java.awt.Dimension;
import java.io.File;
import java.util.Arrays;
@@ -37,24 +38,21 @@
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JLabel;
-import javax.swing.JTextField;
/** Option to use an existing workspace */
public abstract class UseExistingWorkspaceOption implements BlazeSelectWorkspaceOption {
- private final BlazeWizardUserSettings userSettings;
private final JComponent component;
- private final JTextField directoryField;
+ private final TextFieldWithHistory directoryField;
private final BuildSystem buildSystem;
protected UseExistingWorkspaceOption(BlazeNewProjectBuilder builder, BuildSystem buildSystem) {
- this.userSettings = builder.getUserSettings();
this.buildSystem = buildSystem;
- String defaultDirectory =
- userSettings.get(BlazeNewProjectBuilder.lastImportedWorkspaceKey(buildSystem), "");
-
- this.directoryField = new JTextField(defaultDirectory);
+ this.directoryField = new TextFieldWithHistory();
+ directoryField.setHistory(builder.getWorkspaceHistory(buildSystem));
+ directoryField.setHistorySize(BlazeNewProjectBuilder.HISTORY_SIZE);
+ directoryField.setText(builder.getLastImportedWorkspace(buildSystem));
JButton button = new JButton("...");
button.addActionListener(action -> chooseDirectory());
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 de7e373..81ace4e 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
@@ -23,22 +23,32 @@
import com.google.idea.blaze.base.projectview.ProjectView;
import com.google.idea.blaze.base.projectview.ProjectViewSet;
import com.google.idea.blaze.base.projectview.ProjectViewStorageManager;
+import com.google.idea.blaze.base.projectview.ProjectViewVerifier;
import com.google.idea.blaze.base.projectview.section.ScalarSection;
import com.google.idea.blaze.base.projectview.section.sections.ImportSection;
+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;
import com.google.idea.blaze.base.scope.output.IssueOutput;
+import com.google.idea.blaze.base.scope.output.IssueOutput.Category;
import com.google.idea.blaze.base.settings.ui.JPanelProvidingProject;
import com.google.idea.blaze.base.settings.ui.ProjectViewUi;
+import com.google.idea.blaze.base.sync.BlazeSyncPlugin;
+import com.google.idea.blaze.base.sync.projectview.LanguageSupport;
+import com.google.idea.blaze.base.sync.projectview.WorkspaceLanguageSettings;
import com.google.idea.blaze.base.ui.BlazeValidationError;
import com.google.idea.blaze.base.ui.BlazeValidationResult;
import com.google.idea.blaze.base.ui.UiUtil;
import com.google.idea.blaze.base.wizard2.BlazeNewProjectBuilder;
import com.google.idea.blaze.base.wizard2.BlazeSelectProjectViewOption;
import com.google.idea.blaze.base.wizard2.BlazeSelectWorkspaceOption;
+import com.google.idea.blaze.base.wizard2.ProjectDataDirectoryValidator;
import com.intellij.ide.RecentProjectsManager;
import com.intellij.openapi.Disposable;
import com.intellij.openapi.application.ApplicationNamesInfo;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.fileChooser.FileChooserDescriptor;
+import com.intellij.openapi.progress.ProgressManager;
import com.intellij.openapi.ui.TextComponentAccessor;
import com.intellij.openapi.ui.TextFieldWithBrowseButton;
import com.intellij.openapi.util.io.FileUtil;
@@ -55,6 +65,7 @@
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextField;
+import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
/** The UI control to collect project settings when importing a Blaze project. */
@@ -72,6 +83,7 @@
private JTextField projectNameField;
private HashCode paramsHash;
private WorkspaceRoot workspaceRoot;
+ private WorkspaceRoot temporaryWorkspaceRoot;
public BlazeEditProjectViewControl(BlazeNewProjectBuilder builder, Disposable parentDisposable) {
this.projectViewUi = new ProjectViewUi(parentDisposable);
@@ -162,6 +174,7 @@
@Nullable WorkspacePath sharedProjectView,
@Nullable String initialProjectViewText) {
this.workspaceRoot = workspaceRoot;
+ this.temporaryWorkspaceRoot = temporaryWorkspaceRoot;
projectNameField.setText(workspaceName);
String defaultDataDir = getDefaultProjectDataDirectory(workspaceName);
projectDataDirField.setText(defaultDataDir);
@@ -252,6 +265,13 @@
return BlazeValidationResult.failure(
new BlazeValidationError("Project data directory is not valid"));
}
+ for (ProjectDataDirectoryValidator validator :
+ ProjectDataDirectoryValidator.EP_NAME.getExtensions()) {
+ BlazeValidationResult result = validator.validateDataDirectory(projectDataDir);
+ if (!result.success) {
+ return result;
+ }
+ }
File workspaceRootDirectory = workspaceRoot.directory();
if (FileUtil.isAncestor(projectDataDir, workspaceRootDirectory, false)) {
return BlazeValidationResult.failure(
@@ -268,15 +288,71 @@
List<IssueOutput> issues = Lists.newArrayList();
- projectViewUi.parseProjectView(issues);
+ ProjectViewSet projectViewSet = projectViewUi.parseProjectView(issues);
BlazeValidationError projectViewParseError = validationErrorFromIssueList(issues);
if (projectViewParseError != null) {
return BlazeValidationResult.failure(projectViewParseError);
}
+ ProjectViewValidator projectViewValidator =
+ new ProjectViewValidator(temporaryWorkspaceRoot, projectViewSet);
+ ProgressManager.getInstance()
+ .runProcessWithProgressSynchronously(
+ projectViewValidator, "Validating Project", false, null);
+
+ if (!projectViewValidator.success) {
+ if (!projectViewValidator.errors.isEmpty()) {
+ return BlazeValidationResult.failure(
+ validationErrorFromIssueList(projectViewValidator.errors));
+ }
+ return BlazeValidationResult.failure(
+ "Project view validation failed, but we couldn't find an error message. "
+ + "Please report a bug.");
+ }
+
return BlazeValidationResult.success();
}
+ private static class ProjectViewValidator implements Runnable {
+ private final WorkspaceRoot workspaceRoot;
+ private final ProjectViewSet projectViewSet;
+
+ private boolean success;
+ List<IssueOutput> errors = Lists.newArrayList();
+
+ ProjectViewValidator(WorkspaceRoot workspaceRoot, ProjectViewSet projectViewSet) {
+ this.workspaceRoot = workspaceRoot;
+ this.projectViewSet = projectViewSet;
+ }
+
+ @Override
+ public void run() {
+ success = Scope.root(this::validateProjectView);
+ }
+
+ @NotNull
+ private Boolean validateProjectView(BlazeContext context) {
+ context.addOutputSink(
+ IssueOutput.class,
+ output -> {
+ if (output.getCategory() == Category.ERROR) {
+ errors.add(output);
+ }
+ return Propagation.Continue;
+ });
+ for (BlazeSyncPlugin syncPlugin : BlazeSyncPlugin.EP_NAME.getExtensions()) {
+ syncPlugin.installSdks(context);
+ }
+ WorkspaceLanguageSettings workspaceLanguageSettings =
+ LanguageSupport.createWorkspaceLanguageSettings(context, projectViewSet);
+ if (workspaceLanguageSettings == null) {
+ return false;
+ }
+ return ProjectViewVerifier.verifyProjectView(
+ context, workspaceRoot, projectViewSet, workspaceLanguageSettings);
+ }
+ }
+
@Nullable
private static BlazeValidationError validationErrorFromIssueList(List<IssueOutput> issues) {
List<IssueOutput> errors =
diff --git a/base/tests/integrationtests/com/google/idea/blaze/base/lang/buildfile/language/BuildFileTypeTest.java b/base/tests/integrationtests/com/google/idea/blaze/base/lang/buildfile/language/BuildFileTypeTest.java
index 50a490a..32825ed 100644
--- a/base/tests/integrationtests/com/google/idea/blaze/base/lang/buildfile/language/BuildFileTypeTest.java
+++ b/base/tests/integrationtests/com/google/idea/blaze/base/lang/buildfile/language/BuildFileTypeTest.java
@@ -40,18 +40,4 @@
assertThat(file).isInstanceOf(BuildFile.class);
}
- /**
- * We may want to support these in the future (and in the meantime the user can manually have them
- * recognized as BUILD files, for syntax highlighting, etc.).<br>
- * Currently, turned off by default because references won't resolve correctly -- they'll point
- * back to normal BUILD files.
- */
- @Test
- public void testOtherBuildFilesNotRecognized() {
- PsiFile file = createPsiFile("java/com/google/foo/BUILD.tools");
- assertThat(file).isNotInstanceOf(BuildFile.class);
-
- file = createPsiFile("java/com/google/foo/BUILD.bazel");
- assertThat(file).isNotInstanceOf(BuildFile.class);
- }
}
diff --git a/base/tests/unittests/com/google/idea/blaze/base/model/primitives/WorkspacePathTest.java b/base/tests/unittests/com/google/idea/blaze/base/model/primitives/WorkspacePathTest.java
index 67e74e7..3a69631 100644
--- a/base/tests/unittests/com/google/idea/blaze/base/model/primitives/WorkspacePathTest.java
+++ b/base/tests/unittests/com/google/idea/blaze/base/model/primitives/WorkspacePathTest.java
@@ -50,11 +50,13 @@
List<BlazeValidationError> errors = Lists.newArrayList();
WorkspacePath.validate("/foo", errors);
- assertThat(errors.get(0).getError()).isEqualTo("Workspace path may not start with '/': /foo");
+ assertThat(errors.get(0).getError())
+ .isEqualTo("Workspace path must be relative; cannot start with '/': /foo");
errors.clear();
WorkspacePath.validate("/", errors);
- assertThat(errors.get(0).getError()).isEqualTo("Workspace path may not start with '/': /");
+ assertThat(errors.get(0).getError())
+ .isEqualTo("Workspace path must be relative; cannot start with '/': /");
errors.clear();
WorkspacePath.validate("foo/", errors);
diff --git a/base/tests/unittests/com/google/idea/blaze/base/sync/BuildTargetFinderTest.java b/base/tests/unittests/com/google/idea/blaze/base/sync/BuildTargetFinderTest.java
new file mode 100644
index 0000000..c1ff46d
--- /dev/null
+++ b/base/tests/unittests/com/google/idea/blaze/base/sync/BuildTargetFinderTest.java
@@ -0,0 +1,160 @@
+/*
+ * Copyright 2016 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.sync;
+
+import static com.google.common.truth.Truth.assertThat;
+import static org.mockito.Mockito.mock;
+
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.Lists;
+import com.google.common.collect.Sets;
+import com.google.idea.blaze.base.BlazeTestCase;
+import com.google.idea.blaze.base.bazel.BazelBuildSystemProvider;
+import com.google.idea.blaze.base.bazel.BuildSystemProvider;
+import com.google.idea.blaze.base.io.FileAttributeProvider;
+import com.google.idea.blaze.base.model.primitives.TargetExpression;
+import com.google.idea.blaze.base.model.primitives.WorkspacePath;
+import com.google.idea.blaze.base.model.primitives.WorkspaceRoot;
+import com.google.idea.blaze.base.projectview.section.sections.DirectoryEntry;
+import com.google.idea.blaze.base.settings.Blaze.BuildSystem;
+import com.google.idea.blaze.base.settings.BlazeImportSettingsManager;
+import com.google.idea.blaze.base.sync.projectview.ImportRoots;
+import com.intellij.openapi.extensions.ExtensionPoint;
+import java.io.File;
+import java.util.Collection;
+import java.util.Set;
+import org.jetbrains.annotations.NotNull;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+/** Tests for build target finder. */
+@RunWith(JUnit4.class)
+public class BuildTargetFinderTest extends BlazeTestCase {
+
+ private static class MockFileAttributeProvider extends FileAttributeProvider {
+ final Set<File> files = Sets.newHashSet();
+
+ void addFiles(File... files) {
+ this.files.addAll(Lists.newArrayList(files));
+ }
+
+ @Override
+ public boolean isFile(File file) {
+ return files.contains(file);
+ }
+
+ @Override
+ public boolean exists(File file) {
+ return files.contains(file);
+ }
+ }
+
+ private final MockFileAttributeProvider fileAttributeProvider = new MockFileAttributeProvider();
+ private final WorkspaceRoot workspaceRoot = new WorkspaceRoot(new File("/root"));
+
+ @Override
+ protected void initTest(
+ @NotNull Container applicationServices, @NotNull Container projectServices) {
+ super.initTest(applicationServices, projectServices);
+
+ applicationServices.register(FileAttributeProvider.class, fileAttributeProvider);
+ applicationServices.register(
+ BlazeImportSettingsManager.class, mock(BlazeImportSettingsManager.class));
+ ExtensionPoint<BuildSystemProvider> extensionPoint =
+ registerExtensionPoint(BuildSystemProvider.EP_NAME, BuildSystemProvider.class);
+ extensionPoint.registerExtension(new BazelBuildSystemProvider());
+ }
+
+ private BuildTargetFinder buildTargetFinder(Collection<WorkspacePath> roots) {
+ ImportRoots.Builder builder = ImportRoots.builder(workspaceRoot, BuildSystem.Bazel);
+ for (WorkspacePath root : roots) {
+ builder.add(DirectoryEntry.include(root));
+ }
+
+ return new BuildTargetFinder(project, workspaceRoot, builder.build());
+ }
+
+ @Test
+ public void firstBuildFileInDirectoryIsFound() {
+ BuildTargetFinder buildTargetFinder =
+ buildTargetFinder(ImmutableList.of(new WorkspacePath(".")));
+
+ fileAttributeProvider.addFiles(
+ new File("/root/j/c/g/some/BUILD"),
+ new File("/root/j/c/g/BUILD"),
+ new File("/root/j/c/g/some/dir/File.java"));
+
+ assertThat(buildTargetFinder.findTargetForFile(new File("/root/j/c/g/some/dir/File.java")))
+ .isEqualTo(TargetExpression.fromString("//j/c/g/some:all"));
+ }
+
+ @Test
+ public void testNothingFound() {
+ BuildTargetFinder buildTargetFinder =
+ buildTargetFinder(ImmutableList.of(new WorkspacePath(".")));
+
+ fileAttributeProvider.addFiles(
+ new File("/root/j/c/g/other/BUILD"), new File("/root/j/c/g/some/dir/File.java"));
+
+ assertThat(buildTargetFinder.findTargetForFile(new File("/root/j/c/g/some/dir/File.java")))
+ .isNull();
+ }
+
+ @Test
+ public void buildFilesBelowWorkspaceRootsNotFound() {
+ BuildTargetFinder buildTargetFinder =
+ buildTargetFinder(ImmutableList.of(new WorkspacePath("j/c/g/some")));
+
+ fileAttributeProvider.addFiles(
+ new File("/root/j/c/g/BUILD"), new File("/root/j/c/g/some/dir/File.java"));
+
+ assertThat(buildTargetFinder.findTargetForFile(new File("/root/j/c/g/some/dir/File.java")))
+ .isNull();
+ }
+
+ @Test
+ public void rightContentRootFound() {
+ BuildTargetFinder buildTargetFinder =
+ buildTargetFinder(
+ ImmutableList.of(
+ new WorkspacePath("j/c/g/foo"),
+ new WorkspacePath("j/c/g/bar"),
+ new WorkspacePath("j/c/g/baz")));
+
+ fileAttributeProvider.addFiles(
+ new File("/root/j/c/g/BUILD"),
+ new File("/root/j/c/g/foo/BUILD"),
+ new File("/root/j/c/g/bar/BUILD"),
+ new File("/root/j/c/g/baz/BUILD"),
+ new File("/root/j/c/g/bar/dir/File.java"));
+
+ assertThat(buildTargetFinder.findTargetForFile(new File("/root/j/c/g/bar/dir/File.java")))
+ .isEqualTo(TargetExpression.fromString("//j/c/g/bar:all"));
+ }
+
+ @Test
+ public void buildFileFindsSelf() {
+ BuildTargetFinder buildTargetFinder =
+ buildTargetFinder(ImmutableList.of(new WorkspacePath(".")));
+
+ fileAttributeProvider.addFiles(
+ new File("/root/j/c/g/some/BUILD"), new File("/root/j/c/g/BUILD"));
+
+ assertThat(buildTargetFinder.findTargetForFile(new File("/root/j/c/g/some/BUILD")))
+ .isEqualTo(TargetExpression.fromString("//j/c/g/some:all"));
+ }
+}
diff --git a/build_defs/BUILD b/build_defs/BUILD
index 0988550..3c8b0b3 100644
--- a/build_defs/BUILD
+++ b/build_defs/BUILD
@@ -1,5 +1,27 @@
+# Description:
+#
+# Scripts for building IntelliJ plugins
+
package(default_visibility = ["//visibility:public"])
licenses(["notice"]) # Apache 2.0
-exports_files(["LICENSE"])
+py_binary(
+ name = "merge_xml",
+ srcs = ["merge_xml.py"],
+)
+
+py_binary(
+ name = "stamp_plugin_xml",
+ srcs = ["stamp_plugin_xml.py"],
+)
+
+py_binary(
+ name = "product_build_txt",
+ srcs = ["product_build_txt.py"],
+)
+
+py_binary(
+ name = "api_version_txt",
+ srcs = ["api_version_txt.py"],
+)
diff --git a/build_defs/shared/api_version_txt.py b/build_defs/api_version_txt.py
similarity index 100%
rename from build_defs/shared/api_version_txt.py
rename to build_defs/api_version_txt.py
diff --git a/build_defs/build_defs.bzl b/build_defs/build_defs.bzl
index d8c9613..f836204 100644
--- a/build_defs/build_defs.bzl
+++ b/build_defs/build_defs.bzl
@@ -1,29 +1,30 @@
-"""Custom build macros for plugin.xml handling.
+"""Custom build macros for IntelliJ plugin handling.
"""
-load("//build_defs/shared:build_defs.bzl",
- "merged_plugin_xml_impl",
- "stamped_plugin_xml_impl",
- "product_build_txt_impl",
- "api_version_txt_impl",
- "intellij_plugin_impl",
- "plugin_bundle_impl")
-
def merged_plugin_xml(name, srcs, **kwargs):
"""Merges N plugin.xml files together."""
- merged_plugin_xml_impl(
+ merge_tool = "//build_defs:merge_xml"
+ native.genrule(
name = name,
srcs = srcs,
- merge_tool = "//build_defs/shared:merge_xml",
+ outs = [name + ".xml"],
+ cmd = "./$(location {merge_tool}) $(SRCS) > $@".format(
+ merge_tool=merge_tool,
+ ),
+ tools = [merge_tool],
**kwargs)
+def _optstr(name, value):
+ return ("--" + name) if value else ""
+
def stamped_plugin_xml(name,
plugin_xml,
- plugin_id=None,
- plugin_name=None,
+ plugin_id = None,
+ plugin_name = None,
stamp_since_build=False,
stamp_until_build=False,
include_product_code_in_stamp=False,
+ version=None,
version_file=None,
changelog_file=None,
description_file=None,
@@ -39,60 +40,202 @@
stamp_since_build: Add build number to idea-version since-build.
stamp_until_build: Add build number to idea-version until-build.
include_product_code_in_stamp: Whether the product code (eg. "IC")
- is included in since-build and until-build.
+ is included in since-build and until-build.
+ version: A version number to stamp.
version_file: A file with the version number to be included.
- changelog_file: A file with changelog to be included.
+ changelog_file: A file with the changelog to be included.
description_file: A file containing a plugin description to be included.
vendor_file: A file containing the vendor info to be included.
**kwargs: Any additional arguments to pass to the final target.
"""
+ stamp_tool = "//build_defs:stamp_plugin_xml"
+
+ api_version_txt_name = name + "_api_version"
api_version_txt(
- name = name + "_api_version",
+ name = api_version_txt_name,
)
- stamped_plugin_xml_impl(
+
+ args = [
+ "./$(location {stamp_tool})",
+ "--plugin_xml=$(location {plugin_xml})",
+ "--api_version_txt=$(location {api_version_txt_name})",
+ "{stamp_since_build}",
+ "{stamp_until_build}",
+ "{include_product_code_in_stamp}",
+ ]
+ srcs = [plugin_xml, api_version_txt_name]
+
+ if version and version_file:
+ fail("Cannot supply both version and version_file")
+
+ if plugin_id:
+ args.append("--plugin_id=%s" % plugin_id)
+
+ if plugin_name:
+ args.append("--plugin_name='%s'" % plugin_name)
+
+ if version:
+ args.append("--version='%s'" % version)
+
+ if version_file:
+ args.append("--version_file=$(location {version_file})")
+ srcs.append(version_file)
+
+ if changelog_file:
+ args.append("--changelog_file=$(location {changelog_file})")
+ srcs.append(changelog_file)
+
+ if description_file:
+ args.append("--description_file=$(location {description_file})")
+ srcs.append(description_file)
+
+ if vendor_file:
+ args.append("--vendor_file=$(location {vendor_file})")
+ srcs.append(vendor_file)
+
+ cmd = " ".join(args).format(
+ plugin_xml=plugin_xml,
+ api_version_txt_name=api_version_txt_name,
+ stamp_tool=stamp_tool,
+ stamp_since_build=_optstr("stamp_since_build",
+ stamp_since_build),
+ stamp_until_build=_optstr("stamp_until_build",
+ stamp_until_build),
+ include_product_code_in_stamp=_optstr(
+ "include_product_code_in_stamp",
+ include_product_code_in_stamp),
+ version_file=version_file,
+ changelog_file=changelog_file,
+ description_file=description_file,
+ vendor_file=vendor_file,
+ ) + "> $@"
+
+ native.genrule(
name = name,
- api_version_txt = name + "_api_version",
- plugin_id = plugin_id,
- plugin_name = plugin_name,
- stamp_tool = "//build_defs/shared:stamp_plugin_xml",
- plugin_xml = plugin_xml,
- stamp_since_build = stamp_since_build,
- stamp_until_build = stamp_until_build,
- include_product_code_in_stamp = include_product_code_in_stamp,
- version_file = version_file,
- changelog_file = changelog_file,
- description_file = description_file,
- vendor_file = vendor_file,
+ srcs = srcs,
+ outs = [name + ".xml"],
+ cmd = cmd,
+ tools = [stamp_tool],
**kwargs)
def product_build_txt(name, **kwargs):
- """Produces a product-build.txt file with the build number."""
- product_build_txt_impl(
+ """Produces a product-build.txt file with the build number.
+
+ Args:
+ name: name of this target
+ **kwargs: Any additional arguments to pass to the final target.
+ """
+ application_info_jar = "//intellij_platform_sdk:application_info_jar"
+ application_info_name = "//intellij_platform_sdk:application_info_name"
+ product_build_txt_tool = "//build_defs:product_build_txt"
+
+ args = [
+ "./$(location {product_build_txt_tool})",
+ "--application_info_jar=$(location {application_info_jar})",
+ "--application_info_name=$(location {application_info_name})",
+ ]
+ cmd = " ".join(args).format(
+ application_info_jar=application_info_jar,
+ application_info_name=application_info_name,
+ product_build_txt_tool=product_build_txt_tool,
+ ) + "> $@"
+ native.genrule(
name = name,
- application_info_jar = "//intellij_platform_sdk:application_info_jar",
- application_info_name = "//intellij_platform_sdk:application_info_name",
- product_build_txt_tool = "//build_defs/shared:product_build_txt",
+ srcs = [application_info_jar, application_info_name],
+ outs = ["product-build.txt"],
+ cmd = cmd,
+ tools = [product_build_txt_tool],
**kwargs)
def api_version_txt(name, **kwargs):
- """Produces an api_version.txt file with the api version, including the product code."""
- api_version_txt_impl(
+ """Produces an api_version.txt file with the api version, including the product code.
+
+ Args:
+ name: name of this target
+ **kwargs: Any additional arguments to pass to the final target.
+ """
+ application_info_jar = "//intellij_platform_sdk:application_info_jar"
+ application_info_name = "//intellij_platform_sdk:application_info_name"
+ api_version_txt_tool = "//build_defs:api_version_txt"
+
+ args = [
+ "./$(location {api_version_txt_tool})",
+ "--application_info_jar=$(location {application_info_jar})",
+ "--application_info_name=$(location {application_info_name})",
+ ]
+ cmd = " ".join(args).format(
+ application_info_jar=application_info_jar,
+ application_info_name=application_info_name,
+ api_version_txt_tool=api_version_txt_tool,
+ ) + "> $@"
+ native.genrule(
name = name,
- application_info_jar = "//intellij_platform_sdk:application_info_jar",
- application_info_name = "//intellij_platform_sdk:application_info_name",
- api_version_txt_tool = "//build_defs/shared:api_version_txt",
+ srcs = [application_info_jar, application_info_name],
+ outs = [name + ".txt"],
+ cmd = cmd,
+ tools = [api_version_txt_tool],
**kwargs)
-def intellij_plugin(name, plugin_xml, deps, meta_inf_files=[], **kwargs):
+def intellij_plugin(name, deps, plugin_xml, meta_inf_files=[], **kwargs):
"""Creates an intellij plugin from the given deps and plugin.xml."""
- intellij_plugin_impl(
+ zip_tool = "//third_party:zip"
+ binary_name = name + "_binary"
+ deploy_jar = binary_name + "_deploy.jar"
+ native.java_binary(
+ name = binary_name,
+ runtime_deps = deps,
+ create_executable = 0,
+ )
+ cmd = [
+ "cp $(location {deploy_jar}) $@".format(deploy_jar=deploy_jar),
+ "chmod +w $@",
+ "mkdir -p META-INF",
+ "cp $(location {plugin_xml}) META-INF/plugin.xml".format(plugin_xml=plugin_xml),
+ "$(location {zip_tool}) -u $@ META-INF/plugin.xml >/dev/null".format(zip_tool=zip_tool),
+ ]
+ srcs = [
+ plugin_xml,
+ deploy_jar,
+ ]
+
+ for meta_inf_file in meta_inf_files:
+ cmd.append("cp $(location {meta_inf_file}) META-INF/$$(basename $(location {meta_inf_file}))".format(
+ meta_inf_file=meta_inf_file,
+ ))
+ cmd.append("$(location {zip_tool}) -u $@ META-INF/$$(basename $(location {meta_inf_file})) >/dev/null".format(
+ zip_tool=zip_tool,
+ meta_inf_file=meta_inf_file,
+ ))
+ srcs.append(meta_inf_file)
+
+ native.genrule(
+ name = name + "_genrule",
+ srcs = srcs,
+ tools = [zip_tool],
+ outs = [name + ".jar"],
+ cmd = " ; ".join(cmd),
+ )
+
+ # included (with tag) as a hack so that IJwB can recognize this is an intellij plugin
+ native.java_import(
name = name,
- plugin_xml = plugin_xml,
- zip_tool = "//third_party:zip",
- deps = deps,
- meta_inf_files = meta_inf_files,
+ jars = [name + ".jar"],
+ tags = ["intellij-plugin"],
**kwargs)
+def plugin_bundle(name, plugins):
+ """Communicates to IJwB a set of plugins which should be loaded together in a run configuration.
+
+ Args:
+ name: the name of this target
+ plugins: the 'intellij_plugin' targets to be bundled
+ """
+ native.java_library(
+ name = name,
+ exports = plugins,
+ tags = ["intellij-plugin-bundle"],
+ )
+
def repackage_jar(name, src_rule, out,
rules = [
"com.google.common.** com.google.repackaged.common.@1",
@@ -142,12 +285,3 @@
name = name,
jars = [out],
**kwargs)
-
-def plugin_bundle(name, plugins):
- """Communicates to IJwB a set of plugins which should be loaded together in a run configuration.
-
- Args:
- name: the name of this target
- plugins: the 'intellij_plugin' targets to be bundled
- """
- plugin_bundle_impl(name, plugins)
diff --git a/build_defs/shared/merge_xml.py b/build_defs/merge_xml.py
similarity index 100%
rename from build_defs/shared/merge_xml.py
rename to build_defs/merge_xml.py
diff --git a/build_defs/shared/product_build_txt.py b/build_defs/product_build_txt.py
similarity index 100%
rename from build_defs/shared/product_build_txt.py
rename to build_defs/product_build_txt.py
diff --git a/build_defs/shared/BUILD b/build_defs/shared/BUILD
deleted file mode 100644
index 3c8b0b3..0000000
--- a/build_defs/shared/BUILD
+++ /dev/null
@@ -1,27 +0,0 @@
-# Description:
-#
-# Scripts for building IntelliJ plugins
-
-package(default_visibility = ["//visibility:public"])
-
-licenses(["notice"]) # Apache 2.0
-
-py_binary(
- name = "merge_xml",
- srcs = ["merge_xml.py"],
-)
-
-py_binary(
- name = "stamp_plugin_xml",
- srcs = ["stamp_plugin_xml.py"],
-)
-
-py_binary(
- name = "product_build_txt",
- srcs = ["product_build_txt.py"],
-)
-
-py_binary(
- name = "api_version_txt",
- srcs = ["api_version_txt.py"],
-)
diff --git a/build_defs/shared/build_defs.bzl b/build_defs/shared/build_defs.bzl
deleted file mode 100644
index 5726ed0..0000000
--- a/build_defs/shared/build_defs.bzl
+++ /dev/null
@@ -1,235 +0,0 @@
-"""Custom build macros for IntelliJ plugin handling.
-"""
-
-def merged_plugin_xml_impl(name, srcs, merge_tool, **kwargs):
- """Merges N plugin.xml files together."""
- native.genrule(
- name = name,
- srcs = srcs,
- outs = [name + ".xml"],
- cmd = "./$(location {merge_tool}) $(SRCS) > $@".format(
- merge_tool=merge_tool,
- ),
- tools = [merge_tool],
- **kwargs)
-
-def _optstr(name, value):
- return ("--" + name) if value else ""
-
-def stamped_plugin_xml_impl(name,
- plugin_xml,
- api_version_txt,
- stamp_tool,
- plugin_id = None,
- plugin_name = None,
- stamp_since_build=False,
- stamp_until_build=False,
- include_product_code_in_stamp=False,
- version_file=None,
- changelog_file=None,
- description_file=None,
- vendor_file=None,
- **kwargs):
- """Stamps a plugin xml file with the IJ build number.
-
- Args:
- name: name of this target
- plugin_xml: target plugin_xml to stamp
- api_version_txt: the file containing the api version
- stamp_tool: the tool to use to stamp the version
- plugin_id: the plugin ID to stamp
- plugin_name: the plugin name to stamp
- stamp_since_build: Add build number to idea-version since-build.
- stamp_until_build: Add build number to idea-version until-build.
- include_product_code_in_stamp: Whether the product code (eg. "IC")
- is included in since-build and until-build.
- version_file: A file with the version number to be included.
- changelog_file: A file with the changelog to be included.
- description_file: A file containing a plugin description to be included.
- vendor_file: A file containing the vendor info to be included.
- **kwargs: Any additional arguments to pass to the final target.
- """
- args = [
- "./$(location {stamp_tool})",
- "--plugin_xml=$(location {plugin_xml})",
- "--api_version_txt=$(location {api_version_txt})",
- "{stamp_since_build}",
- "{stamp_until_build}",
- "{include_product_code_in_stamp}",
- ]
- srcs = [plugin_xml, api_version_txt]
-
- if plugin_id:
- args.append("--plugin_id=%s" % plugin_id)
-
- if plugin_name:
- args.append("--plugin_name='%s'" % plugin_name)
-
- if version_file:
- args.append("--version_file=$(location {version_file})")
- srcs.append(version_file)
-
- if changelog_file:
- args.append("--changelog_file=$(location {changelog_file})")
- srcs.append(changelog_file)
-
- if description_file:
- args.append("--description_file=$(location {description_file})")
- srcs.append(description_file)
-
- if vendor_file:
- args.append("--vendor_file=$(location {vendor_file})")
- srcs.append(vendor_file)
-
- cmd = " ".join(args).format(
- plugin_xml=plugin_xml,
- api_version_txt=api_version_txt,
- stamp_tool=stamp_tool,
- stamp_since_build=_optstr("stamp_since_build",
- stamp_since_build),
- stamp_until_build=_optstr("stamp_until_build",
- stamp_until_build),
- include_product_code_in_stamp=_optstr(
- "include_product_code_in_stamp",
- include_product_code_in_stamp),
- version_file=version_file,
- changelog_file=changelog_file,
- description_file=description_file,
- vendor_file=vendor_file,
- ) + "> $@"
-
- native.genrule(
- name = name,
- srcs = srcs,
- outs = [name + ".xml"],
- cmd = cmd,
- tools = [stamp_tool],
- **kwargs)
-
-def product_build_txt_impl(name,
- product_build_txt_tool,
- application_info_jar,
- application_info_name,
- **kwargs):
- """Produces a product-build.txt file with the build number.
-
- Args:
- name: name of this target
- product_build_txt_tool: the product build tool
- application_info_jar: the jar containing the application info
- application_info_name: a file with the name of the application info
- **kwargs: Any additional arguments to pass to the final target.
- """
- args = [
- "./$(location {product_build_txt_tool})",
- "--application_info_jar=$(location {application_info_jar})",
- "--application_info_name=$(location {application_info_name})",
- ]
- cmd = " ".join(args).format(
- application_info_jar=application_info_jar,
- application_info_name=application_info_name,
- product_build_txt_tool=product_build_txt_tool,
- ) + "> $@"
- native.genrule(
- name = name,
- srcs = [application_info_jar, application_info_name],
- outs = ["product-build.txt"],
- cmd = cmd,
- tools = [product_build_txt_tool],
- **kwargs)
-
-def api_version_txt_impl(name,
- api_version_txt_tool,
- application_info_jar,
- application_info_name,
- **kwargs):
- """Produces an api_version.txt file with the api version, including the product code.
-
- Args:
- name: name of this target
- api_version_txt_tool: the api version tool
- application_info_jar: the jar containing the application info
- application_info_name: a file with the name of the application info
- **kwargs: Any additional arguments to pass to the final target.
- """
- args = [
- "./$(location {api_version_txt_tool})",
- "--application_info_jar=$(location {application_info_jar})",
- "--application_info_name=$(location {application_info_name})",
- ]
- cmd = " ".join(args).format(
- application_info_jar=application_info_jar,
- application_info_name=application_info_name,
- api_version_txt_tool=api_version_txt_tool,
- ) + "> $@"
- native.genrule(
- name = name,
- srcs = [application_info_jar, application_info_name],
- outs = [name + ".txt"],
- cmd = cmd,
- tools = [api_version_txt_tool],
- **kwargs)
-
-def intellij_plugin_impl(name,
- deps,
- plugin_xml,
- zip_tool,
- meta_inf_files=[],
- **kwargs):
- """Creates an intellij plugin from the given deps and plugin.xml."""
- binary_name = name + "_binary"
- deploy_jar = binary_name + "_deploy.jar"
- native.java_binary(
- name = binary_name,
- runtime_deps = deps,
- create_executable = 0,
- )
- cmd = [
- "cp $(location {deploy_jar}) $@".format(deploy_jar=deploy_jar),
- "chmod +w $@",
- "mkdir -p META-INF",
- "cp $(location {plugin_xml}) META-INF/plugin.xml".format(plugin_xml=plugin_xml),
- "$(location {zip_tool}) -u $@ META-INF/plugin.xml >/dev/null".format(zip_tool=zip_tool),
- ]
- srcs = [
- plugin_xml,
- deploy_jar,
- ]
-
- for meta_inf_file in meta_inf_files:
- cmd.append("cp $(location {meta_inf_file}) META-INF/$$(basename $(location {meta_inf_file}))".format(
- meta_inf_file=meta_inf_file,
- ))
- cmd.append("$(location {zip_tool}) -u $@ META-INF/$$(basename $(location {meta_inf_file})) >/dev/null".format(
- zip_tool=zip_tool,
- meta_inf_file=meta_inf_file,
- ))
- srcs.append(meta_inf_file)
-
- native.genrule(
- name = name + "_genrule",
- srcs = srcs,
- tools = [zip_tool],
- outs = [name + ".jar"],
- cmd = " ; ".join(cmd),
- )
-
- # included (with tag) as a hack so that IJwB can recognize this is an intellij plugin
- native.java_import(
- name = name,
- jars = [name + ".jar"],
- tags = ["intellij-plugin"],
- **kwargs)
-
-def plugin_bundle_impl(name, plugins):
- """Communicates to IJwB a set of plugins which should be loaded together in a run configuration.
-
- Args:
- name: the name of this target
- plugins: the 'intellij_plugin' targets to be bundled
- """
- native.java_library(
- name = name,
- exports = plugins,
- tags = ["intellij-plugin-bundle"],
- )
diff --git a/build_defs/shared/stamp_plugin_xml.py b/build_defs/stamp_plugin_xml.py
similarity index 89%
rename from build_defs/shared/stamp_plugin_xml.py
rename to build_defs/stamp_plugin_xml.py
index aeaf5d2..72baa66 100755
--- a/build_defs/shared/stamp_plugin_xml.py
+++ b/build_defs/stamp_plugin_xml.py
@@ -35,6 +35,9 @@
help="plugin name to stamp into the plugin.xml",
)
parser.add_argument(
+ "--version",
+ help="Version to stamp into the plugin.xml",)
+parser.add_argument(
"--version_file",
help="Version file to stamp into the plugin.xml",
)
@@ -100,23 +103,24 @@
idea_plugin = dom.documentElement
- version_element = None
- version_elements = idea_plugin.getElementsByTagName("version")
- if len(version_elements) > 1:
- raise ValueError("Ambigious version element")
+ if args.version and args.version_file:
+ raise ValueError("Cannot supply both version and version_file")
- if len(version_elements) == 1:
- version_element = version_elements[0].firstChild
-
- if args.version_file:
- if version_element:
- raise ValueError("version element already in plugin.xml")
+ if args.version or args.version_file:
+ version_elements = idea_plugin.getElementsByTagName("version")
+ for element in version_elements:
+ idea_plugin.removeChild(element)
version_element = dom.createElement("version")
new_elements.append(version_element)
- with open(args.version_file) as f:
- value = f.read().strip()
- version_text = dom.createTextNode(value)
- version_element.appendChild(version_text)
+
+ version_value = None
+ if args.version:
+ version_value = args.version
+ else:
+ with open(args.version_file) as f:
+ version_value = f.read().strip()
+ version_text = dom.createTextNode(version_value)
+ version_element.appendChild(version_text)
if args.stamp_since_build or args.stamp_until_build:
if idea_plugin.getElementsByTagName("idea-version"):
diff --git a/clwb/BUILD b/clwb/BUILD
index 792d459..f1048b9 100644
--- a/clwb/BUILD
+++ b/clwb/BUILD
@@ -10,6 +10,7 @@
"merged_plugin_xml",
"stamped_plugin_xml",
)
+load("//:version.bzl", "VERSION")
merged_plugin_xml(
name = "merged_plugin_xml_common",
@@ -36,7 +37,7 @@
plugin_name = "CLion with Bazel",
plugin_xml = ":merged_plugin_xml",
stamp_since_build = True,
- version_file = "//:version",
+ version = VERSION,
)
java_library(
diff --git a/clwb/src/META-INF/clwb.xml b/clwb/src/META-INF/clwb.xml
index 4e871ca..b6d8dbf 100644
--- a/clwb/src/META-INF/clwb.xml
+++ b/clwb/src/META-INF/clwb.xml
@@ -17,8 +17,6 @@
<vendor>Google</vendor>
<depends>com.intellij.modules.clion</depends>
- <depends>com.intellij.modules.cidr.lang</depends>
- <depends>com.intellij.modules.cidr.debugger</depends>
<extensions defaultExtensionNs="com.intellij">
<applicationService serviceInterface="com.google.idea.blaze.base.plugin.BlazePluginId"
@@ -70,6 +68,9 @@
<component>
<implementation-class>com.google.idea.blaze.plugin.ClwbProjectSpecificInitializer</implementation-class>
</component>
+ <component>
+ <implementation-class>com.google.idea.blaze.clwb.run.producers.NonBlazeProducerSuppressor</implementation-class>
+ </component>
</project-components>
</idea-plugin>
diff --git a/clwb/src/META-INF/clwb_bazel.xml b/clwb/src/META-INF/clwb_bazel.xml
index 9bd8aff..4f66c87 100644
--- a/clwb/src/META-INF/clwb_bazel.xml
+++ b/clwb/src/META-INF/clwb_bazel.xml
@@ -16,7 +16,7 @@
<idea-plugin>
<description>
<![CDATA[
- <a href="http://bazel.io">Bazel</a> support for CLion.
+ <a href="https://bazel.build">Bazel</a> support for CLion.
Features:
<ul>
@@ -25,7 +25,7 @@
<li>Support for Bazel run configurations for certain rule classes.</li>
</ul>
- Usage instructions at <a href="http://ij.bazel.io">ij.bazel.io</a>
+ Usage instructions at <a href="https://ij.bazel.build">ij.bazel.build</a>
]]>
</description>
-</idea-plugin>
\ No newline at end of file
+</idea-plugin>
diff --git a/clwb/src/com/google/idea/blaze/clwb/run/producers/NonBlazeProducerSuppressor.java b/clwb/src/com/google/idea/blaze/clwb/run/producers/NonBlazeProducerSuppressor.java
new file mode 100644
index 0000000..8f163a7
--- /dev/null
+++ b/clwb/src/com/google/idea/blaze/clwb/run/producers/NonBlazeProducerSuppressor.java
@@ -0,0 +1,49 @@
+/*
+ * Copyright 2016 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.clwb.run.producers;
+
+import com.google.common.collect.ImmutableList;
+import com.google.idea.blaze.base.settings.Blaze;
+import com.intellij.execution.RunConfigurationProducerService;
+import com.intellij.execution.actions.RunConfigurationProducer;
+import com.intellij.openapi.components.AbstractProjectComponent;
+import com.intellij.openapi.project.Project;
+import com.jetbrains.cidr.cpp.execution.testing.CMakeGoogleTestRunConfigurationProducer;
+import java.util.Collection;
+
+/** Suppresses certain non-Blaze configuration producers in Blaze projects. */
+public class NonBlazeProducerSuppressor extends AbstractProjectComponent {
+
+ private static final Collection<Class<? extends RunConfigurationProducer<?>>>
+ PRODUCERS_TO_SUPPRESS = ImmutableList.of(CMakeGoogleTestRunConfigurationProducer.class);
+
+ public NonBlazeProducerSuppressor(Project project) {
+ super(project);
+ }
+
+ @Override
+ public void projectOpened() {
+ if (Blaze.isBlazeProject(myProject)) {
+ suppressProducers(myProject);
+ }
+ }
+
+ private static void suppressProducers(Project project) {
+ RunConfigurationProducerService producerService =
+ RunConfigurationProducerService.getInstance(project);
+ PRODUCERS_TO_SUPPRESS.forEach(producerService::addIgnoredProducer);
+ }
+}
diff --git a/common/BUILD b/common/BUILD
new file mode 100644
index 0000000..fe756e1
--- /dev/null
+++ b/common/BUILD
@@ -0,0 +1 @@
+licenses(["notice"]) # Apache 2.0
diff --git a/common/binaryhelper/BUILD b/common/binaryhelper/BUILD
new file mode 100644
index 0000000..85ec9ff
--- /dev/null
+++ b/common/binaryhelper/BUILD
@@ -0,0 +1,11 @@
+licenses(["notice"]) # Apache 2.0
+
+java_library(
+ name = "binaryhelper",
+ srcs = glob(["src/**/*.java"]),
+ visibility = ["//visibility:public"],
+ deps = [
+ "//intellij_platform_sdk:plugin_api",
+ "@jsr305_annotations//jar",
+ ],
+)
diff --git a/base/src/com/google/idea/blaze/base/util/BlazeHelperBinaryUtil.java b/common/binaryhelper/src/com/google/idea/common/binaryhelper/HelperBinaryUtil.java
similarity index 63%
rename from base/src/com/google/idea/blaze/base/util/BlazeHelperBinaryUtil.java
rename to common/binaryhelper/src/com/google/idea/common/binaryhelper/HelperBinaryUtil.java
index 49fb501..fb1be91 100644
--- a/base/src/com/google/idea/blaze/base/util/BlazeHelperBinaryUtil.java
+++ b/common/binaryhelper/src/com/google/idea/common/binaryhelper/HelperBinaryUtil.java
@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package com.google.idea.blaze.base.util;
+package com.google.idea.common.binaryhelper;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.util.io.URLUtil;
@@ -25,34 +25,35 @@
import java.nio.file.StandardCopyOption;
import java.util.HashMap;
import java.util.Map;
-import org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.Nullable;
+import javax.annotation.Nullable;
-/** Extracts binaries from the resource section of the jar for execution */
-public final class BlazeHelperBinaryUtil {
+/** Binaries provided to IntelliJ at runtime */
+public final class HelperBinaryUtil {
- private static final Logger LOG = Logger.getInstance(BlazeHelperBinaryUtil.class);
+ private static final Logger LOG = Logger.getInstance(HelperBinaryUtil.class);
- private static final File tempDirectory = com.google.common.io.Files.createTempDir();
+ private static File tempDirectory;
private static final Map<String, File> cachedFiles = new HashMap<>();
@Nullable
- public static synchronized File getBlazeHelperBinary(@NotNull String binaryName) {
+ public static synchronized File getHelperBinary(String binaryFilePath) {
+ // Assume the binaries have unique names. This saves having
+ // to recursively clean up directories
+ String binaryName = new File(binaryFilePath).getName();
+
File file = cachedFiles.get(binaryName);
if (file != null) {
return file;
}
- file = new File(tempDirectory, binaryName);
- File directory = file.getParentFile();
-
- if (!directory.mkdirs()) {
- LOG.error("Could not create temporary dir: " + directory);
- return null;
+ if (tempDirectory == null) {
+ tempDirectory = com.google.common.io.Files.createTempDir();
+ tempDirectory.deleteOnExit();
}
+ file = new File(tempDirectory, binaryName);
- URL url = BlazeHelperBinaryUtil.class.getResource(binaryName);
+ URL url = HelperBinaryUtil.class.getResource(binaryFilePath);
if (url == null) {
- LOG.error(String.format("Blaze binary '%s' was not found", binaryName));
+ LOG.error(String.format("Helper binary '%s' was not found", binaryFilePath));
return null;
}
try (InputStream inputStream = URLUtil.openResourceStream(url)) {
@@ -62,7 +63,7 @@
cachedFiles.put(binaryName, file);
return file;
} catch (IOException e) {
- LOG.error(String.format("Error loading blaze binary '%s'", binaryName));
+ LOG.error(String.format("Error loading helper binary '%s'", binaryFilePath));
return null;
}
}
diff --git a/common/experiments/src/com/google/idea/common/experiments/ExperimentServiceImpl.java b/common/experiments/src/com/google/idea/common/experiments/ExperimentServiceImpl.java
index 6b908c1..62246fa 100644
--- a/common/experiments/src/com/google/idea/common/experiments/ExperimentServiceImpl.java
+++ b/common/experiments/src/com/google/idea/common/experiments/ExperimentServiceImpl.java
@@ -19,6 +19,7 @@
import com.google.common.annotations.VisibleForTesting;
import com.google.common.collect.ImmutableList;
+import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.components.ApplicationComponent;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.util.SystemProperties;
@@ -60,7 +61,9 @@
@Override
public void initComponent() {
- services.forEach(ExperimentLoader::initialize);
+ if (!ApplicationManager.getApplication().isUnitTestMode()) {
+ services.forEach(ExperimentLoader::initialize);
+ }
}
@Override
diff --git a/cpp/src/META-INF/blaze-cpp.xml b/cpp/src/META-INF/blaze-cpp.xml
index 8b78eca..3c71cad 100644
--- a/cpp/src/META-INF/blaze-cpp.xml
+++ b/cpp/src/META-INF/blaze-cpp.xml
@@ -14,6 +14,9 @@
~ limitations under the License.
-->
<idea-plugin>
+ <depends>com.intellij.modules.cidr.lang</depends>
+ <depends>com.intellij.modules.cidr.debugger</depends>
+
<extensions defaultExtensionNs="com.google.idea.blaze">
<SyncPlugin implementation="com.google.idea.blaze.cpp.BlazeCSyncPlugin"/>
<PrefetchFileSource implementation="com.google.idea.blaze.cpp.CPrefetchFileSource"/>
@@ -22,6 +25,7 @@
<extensions defaultExtensionNs="cidr.lang">
<languageKindHelper implementation="com.google.idea.blaze.cpp.BlazeLanguageKindCalculatorHelper"/>
<autoImportHelper implementation="com.google.idea.blaze.cpp.BlazeCppAutoImportHelper"/>
+ <customHeaderProvider implementation="com.google.idea.blaze.cpp.BlazeCustomHeaderProvider"/>
</extensions>
<extensions defaultExtensionNs="com.intellij">
<projectService serviceImplementation="com.google.idea.blaze.cpp.BlazeCWorkspace"/>
diff --git a/cpp/src/com/google/idea/blaze/cpp/BlazeCWorkspace.java b/cpp/src/com/google/idea/blaze/cpp/BlazeCWorkspace.java
index 84fc646..e2c5a60 100644
--- a/cpp/src/com/google/idea/blaze/cpp/BlazeCWorkspace.java
+++ b/cpp/src/com/google/idea/blaze/cpp/BlazeCWorkspace.java
@@ -24,11 +24,13 @@
import com.intellij.openapi.components.ServiceManager;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.project.Project;
+import com.intellij.openapi.vfs.LocalFileSystem;
import com.intellij.openapi.vfs.VirtualFile;
import com.jetbrains.cidr.lang.symbols.OCSymbol;
import com.jetbrains.cidr.lang.workspace.OCResolveConfiguration;
import com.jetbrains.cidr.lang.workspace.OCWorkspace;
import com.jetbrains.cidr.lang.workspace.OCWorkspaceModificationTrackers;
+import java.io.File;
import java.util.Collection;
import java.util.List;
import javax.annotation.Nullable;
@@ -70,12 +72,15 @@
LOG.info(String.format("Blaze OCWorkspace update took: %d ms", (end - start)));
ApplicationManager.getApplication()
- .runReadAction(
+ .runWriteAction(
() -> {
if (project.isDisposed()) {
return;
}
+ File genfilesDir = blazeProjectData.blazeRoots.getGenfilesDirectory();
+ LocalFileSystem.getInstance().refreshIoFiles(ImmutableList.of(genfilesDir));
+
// TODO(salguarnieri) Avoid bumping all of these trackers; figure out what has changed
modTrackers.getProjectFilesListTracker().incModificationCount();
modTrackers.getSourceFilesListTracker().incModificationCount();
diff --git a/cpp/src/com/google/idea/blaze/cpp/BlazeConfigurationResolver.java b/cpp/src/com/google/idea/blaze/cpp/BlazeConfigurationResolver.java
index 6204439..c9b7c37 100644
--- a/cpp/src/com/google/idea/blaze/cpp/BlazeConfigurationResolver.java
+++ b/cpp/src/com/google/idea/blaze/cpp/BlazeConfigurationResolver.java
@@ -145,7 +145,6 @@
WorkspacePathResolver workspacePathResolver,
BlazeProjectData blazeProjectData) {
RuleKey ruleKey = rule.key;
- LOG.info("Resolving " + ruleKey);
CToolchainIdeInfo toolchainIdeInfo = toolchainLookupMap.get(ruleKey);
if (toolchainIdeInfo != null) {
diff --git a/cpp/src/com/google/idea/blaze/cpp/BlazeCustomHeaderProvider.java b/cpp/src/com/google/idea/blaze/cpp/BlazeCustomHeaderProvider.java
new file mode 100644
index 0000000..9130e7e
--- /dev/null
+++ b/cpp/src/com/google/idea/blaze/cpp/BlazeCustomHeaderProvider.java
@@ -0,0 +1,83 @@
+/*
+ * Copyright 2016 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.cpp;
+
+import com.intellij.openapi.application.ApplicationManager;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.vfs.LocalFileSystem;
+import com.intellij.openapi.vfs.VirtualFile;
+import com.intellij.openapi.vfs.ex.temp.TempFileSystem;
+import com.jetbrains.cidr.lang.CustomHeaderProvider;
+import com.jetbrains.cidr.lang.workspace.OCResolveConfiguration;
+import com.jetbrains.cidr.lang.workspace.OCResolveRootAndConfiguration;
+import java.io.File;
+import org.jetbrains.annotations.Nullable;
+
+/**
+ * Provides a quick path to resolving non-generated includes, without file-system operations.
+ *
+ * <p>In typical projects, only a tiny fraction of includes are generated files (~0.1%), so handling
+ * non-generated files efficiently is very low hanging fruit.
+ *
+ * <p>Ideally our aspect would record which generated files are used, and we could avoid FS
+ * operations entirely.
+ */
+public class BlazeCustomHeaderProvider extends CustomHeaderProvider {
+
+ @Override
+ public boolean accepts(@Nullable OCResolveRootAndConfiguration configuration) {
+ return configuration != null
+ && configuration.getConfiguration() instanceof BlazeResolveConfiguration;
+ }
+
+ @Nullable
+ @Override
+ public VirtualFile getCustomHeaderFile(
+ String includeString,
+ HeaderSearchStage stage,
+ @Nullable OCResolveConfiguration configuration) {
+ if (stage != HeaderSearchStage.BEFORE_START
+ || includeString.startsWith("/")
+ || configuration == null) {
+ return null;
+ }
+ File file =
+ ((BlazeResolveConfiguration) configuration)
+ .getWorkspacePathResolver()
+ .resolveToFile(includeString);
+ return getFileSystem().findFileByIoFile(file);
+ }
+
+ @Nullable
+ @Override
+ public String provideSerializationPath(VirtualFile file) {
+ return null;
+ }
+
+ @Nullable
+ @Override
+ public VirtualFile getCustomSerializedHeaderFile(
+ String serializationPath, Project project, VirtualFile currentFile) {
+ return null;
+ }
+
+ private static LocalFileSystem getFileSystem() {
+ if (ApplicationManager.getApplication().isUnitTestMode()) {
+ return TempFileSystem.getInstance();
+ }
+ return LocalFileSystem.getInstance();
+ }
+}
diff --git a/cpp/src/com/google/idea/blaze/cpp/BlazeResolveConfigurationTemporaryBase.java b/cpp/src/com/google/idea/blaze/cpp/BlazeResolveConfigurationTemporaryBase.java
index ef7b9c0..a2a2b77 100644
--- a/cpp/src/com/google/idea/blaze/cpp/BlazeResolveConfigurationTemporaryBase.java
+++ b/cpp/src/com/google/idea/blaze/cpp/BlazeResolveConfigurationTemporaryBase.java
@@ -219,6 +219,10 @@
return project;
}
+ public WorkspacePathResolver getWorkspacePathResolver() {
+ return workspacePathResolver;
+ }
+
@Override
public String getDisplayName(boolean shorten) {
return ruleKey.toString();
diff --git a/ijwb/BUILD b/ijwb/BUILD
index fdc10ee..c9524bd 100644
--- a/ijwb/BUILD
+++ b/ijwb/BUILD
@@ -10,6 +10,7 @@
"merged_plugin_xml",
"stamped_plugin_xml",
)
+load("//:version.bzl", "VERSION")
merged_plugin_xml(
name = "merged_plugin_xml_common",
@@ -37,7 +38,7 @@
plugin_name = "IntelliJ with Bazel",
plugin_xml = ":merged_plugin_xml",
stamp_since_build = True,
- version_file = "//:version",
+ version = VERSION,
)
java_library(
diff --git a/ijwb/src/META-INF/ijwb.xml b/ijwb/src/META-INF/ijwb.xml
index f81f4bf..b5fcb39 100644
--- a/ijwb/src/META-INF/ijwb.xml
+++ b/ijwb/src/META-INF/ijwb.xml
@@ -15,7 +15,6 @@
-->
<idea-plugin>
<vendor>Google</vendor>
- <depends>com.intellij.modules.java</depends>
<extensions defaultExtensionNs="com.intellij">
<applicationService serviceInterface="com.google.idea.blaze.base.plugin.BlazePluginId"
diff --git a/ijwb/src/META-INF/ijwb_bazel.xml b/ijwb/src/META-INF/ijwb_bazel.xml
index 0c72d38..00430e9 100644
--- a/ijwb/src/META-INF/ijwb_bazel.xml
+++ b/ijwb/src/META-INF/ijwb_bazel.xml
@@ -17,7 +17,7 @@
<description>
<![CDATA[
- <a href="http://bazel.io">Bazel</a> support for IntelliJ.
+ <a href="https://bazel.build">Bazel</a> support for IntelliJ.
Features:
<ul>
@@ -26,7 +26,7 @@
<li>Support for Bazel run configurations for certain rule classes.</li>
</ul>
- Usage instructions at <a href="http://ij.bazel.io">ij.bazel.io</a>
+ Usage instructions at <a href="https://ij.bazel.build">ij.bazel.build</a>
]]>
</description>
@@ -36,4 +36,4 @@
</component>
</application-components>
-</idea-plugin>
\ No newline at end of file
+</idea-plugin>
diff --git a/intellij_platform_sdk/BUILD.android_studio b/intellij_platform_sdk/BUILD.android_studio
index 7a4839a..00edce8 100644
--- a/intellij_platform_sdk/BUILD.android_studio
+++ b/intellij_platform_sdk/BUILD.android_studio
@@ -29,6 +29,7 @@
"android-studio/plugins/Groovy/lib/*.jar",
"android-studio/plugins/java-i18n/lib/*.jar",
"android-studio/plugins/junit/lib/*.jar",
+ "android-studio/plugins/ndk-workspace/lib/*.jar",
"android-studio/plugins/properties/lib/*.jar",
]),
tags = ["intellij-provided-by-sdk"],
diff --git a/java/BUILD b/java/BUILD
index 2655b20..80799c3 100644
--- a/java/BUILD
+++ b/java/BUILD
@@ -7,6 +7,7 @@
deps = [
"//base",
"//common/experiments",
+ "//intellij_platform_sdk:junit",
"//intellij_platform_sdk:plugin_api",
"//proto_deps",
"@jsr305_annotations//jar",
diff --git a/java/src/META-INF/blaze-java.xml b/java/src/META-INF/blaze-java.xml
index 157152f..937cb85 100644
--- a/java/src/META-INF/blaze-java.xml
+++ b/java/src/META-INF/blaze-java.xml
@@ -15,6 +15,7 @@
-->
<idea-plugin>
<depends>JUnit</depends>
+ <depends>com.intellij.modules.java</depends>
<actions>
<action class="com.google.idea.blaze.java.libraries.ExcludeLibraryAction"
@@ -99,6 +100,12 @@
<projectService serviceImplementation="com.google.idea.blaze.java.syncstatus.SyncStatusHelper"/>
</extensions>
+ <project-components>
+ <component>
+ <implementation-class>com.google.idea.blaze.java.run.producers.NonBlazeProducerSuppressor</implementation-class>
+ </component>
+ </project-components>
+
<extensionPoints>
<extensionPoint qualifiedName="com.google.idea.blaze.java.JavaSyncAugmenter"
interface="com.google.idea.blaze.java.sync.BlazeJavaSyncAugmenter"/>
diff --git a/java/src/com/google/idea/blaze/java/run/producers/BlazeJUnitTestFilterFlags.java b/java/src/com/google/idea/blaze/java/run/producers/BlazeJUnitTestFilterFlags.java
new file mode 100644
index 0000000..1c6fef8
--- /dev/null
+++ b/java/src/com/google/idea/blaze/java/run/producers/BlazeJUnitTestFilterFlags.java
@@ -0,0 +1,76 @@
+/*
+ * Copyright 2016 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.java.run.producers;
+
+import com.google.common.base.Strings;
+import com.google.idea.blaze.base.command.BlazeFlags;
+import java.util.Collection;
+import javax.annotation.Nullable;
+
+/** Utilities for building test filter flags for JUnit tests. */
+public final class BlazeJUnitTestFilterFlags {
+
+ /** A version of JUnit to generate test filter flags for. */
+ public enum JUnitVersion {
+ JUNIT_3,
+ JUNIT_4
+ }
+
+ public static String testFilterFlagForClass(String className, JUnitVersion jUnitVersion) {
+ return testFilterFlagForClassAndMethod(className, null, jUnitVersion);
+ }
+
+ public static String testFilterFlagForClassAndMethod(
+ String className, @Nullable String methodName, JUnitVersion jUnitVersion) {
+ StringBuilder output = new StringBuilder(BlazeFlags.TEST_FILTER);
+ output.append('=');
+ output.append(className);
+
+ if (!Strings.isNullOrEmpty(methodName)) {
+ output.append('#');
+ output.append(methodName);
+ // JUnit 4 test filters are regexes, and must be terminated to avoid matching
+ // unintended classes/methods. JUnit 3 test filters do not need or support this syntax.
+ if (jUnitVersion == JUnitVersion.JUNIT_4) {
+ output.append('$');
+ }
+ } else if (jUnitVersion == JUnitVersion.JUNIT_4) {
+ output.append('#');
+ }
+
+ return output.toString();
+ }
+
+ public static String testFilterFlagForClassAndMethods(
+ String className, Collection<String> methodNames, JUnitVersion jUnitVersion) {
+ if (methodNames.size() == 0) {
+ return testFilterFlagForClass(className, jUnitVersion);
+ } else if (methodNames.size() == 1) {
+ return testFilterFlagForClassAndMethod(
+ className, methodNames.iterator().next(), jUnitVersion);
+ }
+ String methodNamePattern;
+ if (jUnitVersion == JUnitVersion.JUNIT_4) {
+ methodNamePattern = String.format("(%s)", String.join("|", methodNames));
+ } else {
+ methodNamePattern = String.join(",", methodNames);
+ }
+ return testFilterFlagForClassAndMethod(className, methodNamePattern, jUnitVersion);
+ }
+
+ private BlazeJUnitTestFilterFlags() {}
+}
diff --git a/java/src/com/google/idea/blaze/java/run/producers/BlazeJavaTestClassConfigurationProducer.java b/java/src/com/google/idea/blaze/java/run/producers/BlazeJavaTestClassConfigurationProducer.java
index cd1764c..6a92166 100644
--- a/java/src/com/google/idea/blaze/java/run/producers/BlazeJavaTestClassConfigurationProducer.java
+++ b/java/src/com/google/idea/blaze/java/run/producers/BlazeJavaTestClassConfigurationProducer.java
@@ -26,6 +26,7 @@
import com.google.idea.blaze.base.run.producers.BlazeRunConfigurationProducer;
import com.google.idea.blaze.base.run.state.BlazeCommandRunConfigurationCommonState;
import com.google.idea.blaze.java.run.RunUtil;
+import com.google.idea.blaze.java.run.producers.BlazeJUnitTestFilterFlags.JUnitVersion;
import com.intellij.execution.JavaExecutionUtil;
import com.intellij.execution.Location;
import com.intellij.execution.actions.ConfigurationContext;
@@ -34,6 +35,7 @@
import com.intellij.psi.PsiClass;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiMethod;
+import com.intellij.psi.PsiModifier;
import java.util.List;
import java.util.Objects;
import org.jetbrains.annotations.NotNull;
@@ -67,6 +69,9 @@
if (testClass == null) {
return false;
}
+ if (testClass.hasModifierProperty(PsiModifier.ABSTRACT)) {
+ return false;
+ }
sourceElement.set(testClass);
TestIdeInfo.TestSize testSize = TestSizeAnnotationMap.getTestSize(testClass);
@@ -85,9 +90,11 @@
ImmutableList.Builder<String> flags = ImmutableList.builder();
- String qualifiedName = testClass.getQualifiedName();
+ final String qualifiedName = testClass.getQualifiedName();
if (qualifiedName != null) {
- flags.add(BlazeFlags.testFilterFlagForClass(qualifiedName));
+ final JUnitVersion jUnitVersion =
+ JUnitUtil.isJUnit4TestClass(testClass) ? JUnitVersion.JUNIT_4 : JUnitVersion.JUNIT_3;
+ flags.add(BlazeJUnitTestFilterFlags.testFilterFlagForClass(qualifiedName, jUnitVersion));
}
flags.add(BlazeFlags.TEST_OUTPUT_STREAMED);
@@ -142,6 +149,10 @@
}
List<String> flags = handlerState.getBlazeFlags();
- return flags.contains(BlazeFlags.testFilterFlagForClass(testClass.getQualifiedName()));
+ final JUnitVersion jUnitVersion =
+ JUnitUtil.isJUnit4TestClass(testClass) ? JUnitVersion.JUNIT_4 : JUnitVersion.JUNIT_3;
+ return flags.contains(
+ BlazeJUnitTestFilterFlags.testFilterFlagForClass(
+ testClass.getQualifiedName(), jUnitVersion));
}
}
diff --git a/java/src/com/google/idea/blaze/java/run/producers/BlazeJavaTestMethodConfigurationProducer.java b/java/src/com/google/idea/blaze/java/run/producers/BlazeJavaTestMethodConfigurationProducer.java
index d10be31..419f979 100644
--- a/java/src/com/google/idea/blaze/java/run/producers/BlazeJavaTestMethodConfigurationProducer.java
+++ b/java/src/com/google/idea/blaze/java/run/producers/BlazeJavaTestMethodConfigurationProducer.java
@@ -26,6 +26,7 @@
import com.google.idea.blaze.base.run.producers.BlazeRunConfigurationProducer;
import com.google.idea.blaze.base.run.state.BlazeCommandRunConfigurationCommonState;
import com.google.idea.blaze.java.run.RunUtil;
+import com.google.idea.blaze.java.run.producers.BlazeJUnitTestFilterFlags.JUnitVersion;
import com.intellij.execution.actions.ConfigurationContext;
import com.intellij.execution.junit.JUnitUtil;
import com.intellij.openapi.util.Ref;
@@ -162,9 +163,11 @@
if (qualifiedName == null) {
return null;
}
- final boolean isJUnit3Class = JUnitUtil.isJUnit3TestClass(containingClass);
+ final JUnitVersion jUnitVersion =
+ JUnitUtil.isJUnit4TestClass(containingClass) ? JUnitVersion.JUNIT_4 : JUnitVersion.JUNIT_3;
final String testFilterFlag =
- BlazeFlags.testFilterFlagForClassAndMethods(qualifiedName, methodNames, isJUnit3Class);
+ BlazeJUnitTestFilterFlags.testFilterFlagForClassAndMethods(
+ qualifiedName, methodNames, jUnitVersion);
return new SelectedMethodInfo(firstMethod, containingClass, methodNames, testFilterFlag);
}
diff --git a/java/src/com/google/idea/blaze/java/run/producers/NonBlazeProducerSuppressor.java b/java/src/com/google/idea/blaze/java/run/producers/NonBlazeProducerSuppressor.java
new file mode 100644
index 0000000..7c4f4ca
--- /dev/null
+++ b/java/src/com/google/idea/blaze/java/run/producers/NonBlazeProducerSuppressor.java
@@ -0,0 +1,54 @@
+/*
+ * Copyright 2016 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.java.run.producers;
+
+import com.google.common.collect.ImmutableList;
+import com.google.idea.blaze.base.settings.Blaze;
+import com.intellij.execution.RunConfigurationProducerService;
+import com.intellij.execution.actions.RunConfigurationProducer;
+import com.intellij.openapi.components.AbstractProjectComponent;
+import com.intellij.openapi.project.Project;
+import java.util.Collection;
+
+/** Suppresses certain non-Blaze configuration producers in Blaze projects. */
+public class NonBlazeProducerSuppressor extends AbstractProjectComponent {
+
+ private static final Collection<Class<? extends RunConfigurationProducer<?>>>
+ PRODUCERS_TO_SUPPRESS =
+ ImmutableList.of(
+ // JUnit test producers
+ com.intellij.execution.junit.AllInDirectoryConfigurationProducer.class,
+ com.intellij.execution.junit.AllInPackageConfigurationProducer.class,
+ com.intellij.execution.junit.TestClassConfigurationProducer.class,
+ com.intellij.execution.junit.TestMethodConfigurationProducer.class);
+
+ public NonBlazeProducerSuppressor(Project project) {
+ super(project);
+ }
+
+ @Override
+ public void projectOpened() {
+ if (Blaze.isBlazeProject(myProject)) {
+ suppressProducers(myProject);
+ }
+ }
+
+ private static void suppressProducers(Project project) {
+ RunConfigurationProducerService producerService =
+ RunConfigurationProducerService.getInstance(project);
+ PRODUCERS_TO_SUPPRESS.forEach(producerService::addIgnoredProducer);
+ }
+}
diff --git a/java/src/com/google/idea/blaze/java/sync/BlazeJavaSyncPlugin.java b/java/src/com/google/idea/blaze/java/sync/BlazeJavaSyncPlugin.java
index 257dcab..088be73 100644
--- a/java/src/com/google/idea/blaze/java/sync/BlazeJavaSyncPlugin.java
+++ b/java/src/com/google/idea/blaze/java/sync/BlazeJavaSyncPlugin.java
@@ -33,6 +33,7 @@
import com.google.idea.blaze.base.scope.output.IssueOutput;
import com.google.idea.blaze.base.scope.output.PerformanceWarning;
import com.google.idea.blaze.base.scope.scopes.TimingScope;
+import com.google.idea.blaze.base.settings.Blaze;
import com.google.idea.blaze.base.sync.BlazeSyncPlugin;
import com.google.idea.blaze.base.sync.projectview.WorkspaceLanguageSettings;
import com.google.idea.blaze.base.sync.workspace.ArtifactLocationDecoder;
@@ -114,7 +115,9 @@
@Nullable SyncState previousSyncState) {
JavaWorkingSet javaWorkingSet = null;
if (workingSet != null) {
- javaWorkingSet = new JavaWorkingSet(workspaceRoot, workingSet);
+ javaWorkingSet =
+ new JavaWorkingSet(
+ workspaceRoot, workingSet, Blaze.getBuildSystemProvider(project)::isBuildFile);
}
JavaSourceFilter sourceFilter =
@@ -165,7 +168,7 @@
}
@Override
- public void updateSdk(
+ public void updateProjectSdk(
Project project,
BlazeContext context,
ProjectViewSet projectViewSet,
@@ -283,11 +286,6 @@
JavaLanguageLevelSection.PARSER);
}
- @Override
- public boolean requiresResolveIdeArtifacts() {
- return true;
- }
-
/**
* Looks at your jars for anything that seems to be a deploy jar and warns about it. This often
* turns out to be a duplicate copy of all your application's code, so you don't want it in your
diff --git a/java/src/com/google/idea/blaze/java/sync/workingset/JavaWorkingSet.java b/java/src/com/google/idea/blaze/java/sync/workingset/JavaWorkingSet.java
index 0f40445..02c6881 100644
--- a/java/src/com/google/idea/blaze/java/sync/workingset/JavaWorkingSet.java
+++ b/java/src/com/google/idea/blaze/java/sync/workingset/JavaWorkingSet.java
@@ -23,6 +23,7 @@
import com.google.idea.blaze.base.model.primitives.WorkspaceRoot;
import com.google.idea.blaze.base.sync.workspace.WorkingSet;
import java.util.Set;
+import java.util.function.Predicate;
/**
* Computes the working set of files of directories from source control.
@@ -41,13 +42,16 @@
private final Set<String> modifiedBuildFileRelativePaths;
private final Set<String> modifiedJavaFileRelativePaths;
- public JavaWorkingSet(WorkspaceRoot workspaceRoot, WorkingSet workingSet) {
+ public JavaWorkingSet(
+ WorkspaceRoot workspaceRoot,
+ WorkingSet workingSet,
+ Predicate<String> buildFileNamePredicate) {
Set<String> modifiedBuildFileRelativePaths = Sets.newHashSet();
Set<String> modifiedJavaFileRelativePaths = Sets.newHashSet();
for (WorkspacePath workspacePath :
Iterables.concat(workingSet.addedFiles, workingSet.modifiedFiles)) {
- if (workspaceRoot.fileForPath(workspacePath).getName().equals("BUILD")) {
+ if (buildFileNamePredicate.test(workspaceRoot.fileForPath(workspacePath).getName())) {
modifiedBuildFileRelativePaths.add(workspacePath.relativePath());
} else if (workspacePath.relativePath().endsWith(".java")) {
modifiedJavaFileRelativePaths.add(workspacePath.relativePath());
diff --git a/java/src/com/google/idea/blaze/java/syncstatus/SyncStatusHelper.java b/java/src/com/google/idea/blaze/java/syncstatus/SyncStatusHelper.java
index 74fc43f..352553b 100644
--- a/java/src/com/google/idea/blaze/java/syncstatus/SyncStatusHelper.java
+++ b/java/src/com/google/idea/blaze/java/syncstatus/SyncStatusHelper.java
@@ -21,39 +21,60 @@
import com.google.idea.blaze.base.scope.BlazeContext;
import com.google.idea.blaze.base.settings.BlazeImportSettings;
import com.google.idea.blaze.base.sync.SyncListener;
+import com.google.idea.blaze.base.sync.data.BlazeProjectDataManager;
import com.google.idea.blaze.base.sync.workspace.ArtifactLocationDecoder;
import com.google.idea.blaze.java.sync.model.BlazeJavaSyncData;
import com.intellij.openapi.components.ServiceManager;
import com.intellij.openapi.project.Project;
+import com.intellij.openapi.roots.ProjectFileIndex;
import com.intellij.openapi.vfs.VirtualFile;
import java.io.File;
import java.util.Set;
class SyncStatusHelper {
+
static SyncStatusHelper getInstance(Project project) {
return ServiceManager.getService(project, SyncStatusHelper.class);
}
- private Set<File> syncedJavaFiles = ImmutableSet.of();
+ private final Project project;
+ private Set<File> syncedJavaFiles = null;
+
+ SyncStatusHelper(Project project) {
+ this.project = project;
+ }
boolean isUnsynced(VirtualFile virtualFile) {
if (!virtualFile.isInLocalFileSystem()) {
return false;
}
+ if (ProjectFileIndex.SERVICE.getInstance(project).getModuleForFile(virtualFile) == null) {
+ return false;
+ }
+ if (syncedJavaFiles == null) {
+ syncedJavaFiles = refresh();
+ }
+ if (syncedJavaFiles == null) {
+ return false;
+ }
File file = new File(virtualFile.getPath());
return !syncedJavaFiles.contains(file);
}
- void refresh(BlazeProjectData blazeProjectData) {
+ Set<File> refresh() {
+ BlazeProjectData blazeProjectData =
+ BlazeProjectDataManager.getInstance(project).getBlazeProjectData();
+ if (blazeProjectData == null) {
+ return null;
+ }
BlazeJavaSyncData syncData = blazeProjectData.syncState.get(BlazeJavaSyncData.class);
if (syncData == null) {
- return;
+ return null;
}
ArtifactLocationDecoder artifactLocationDecoder = blazeProjectData.artifactLocationDecoder;
- syncedJavaFiles =
- ImmutableSet.<File>builder()
- .addAll(artifactLocationDecoder.decodeAll(syncData.importResult.javaSourceFiles))
- .build();
+ return ImmutableSet.<File>builder()
+ .addAll(artifactLocationDecoder.decodeAll(syncData.importResult.javaSourceFiles))
+ .build();
}
static class UpdateSyncStatusMap extends SyncListener.Adapter {
@@ -65,7 +86,7 @@
ProjectViewSet projectViewSet,
BlazeProjectData blazeProjectData,
SyncResult syncResult) {
- getInstance(project).refresh(blazeProjectData);
+ getInstance(project).syncedJavaFiles = null;
}
}
}
diff --git a/java/tests/unittests/com/google/idea/blaze/java/sync/importer/BlazeJavaWorkspaceImporterTest.java b/java/tests/unittests/com/google/idea/blaze/java/sync/importer/BlazeJavaWorkspaceImporterTest.java
index c5461f1..f6e59f8 100644
--- a/java/tests/unittests/com/google/idea/blaze/java/sync/importer/BlazeJavaWorkspaceImporterTest.java
+++ b/java/tests/unittests/com/google/idea/blaze/java/sync/importer/BlazeJavaWorkspaceImporterTest.java
@@ -81,6 +81,7 @@
import java.util.Collection;
import java.util.List;
import java.util.Map;
+import java.util.function.Predicate;
import java.util.stream.Collectors;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -1021,7 +1022,8 @@
new WorkingSet(
ImmutableList.of(new WorkspacePath("java/apps/example/Test.java")),
ImmutableList.of(),
- ImmutableList.of()));
+ ImmutableList.of()),
+ Predicate.isEqual("BUILD"));
BlazeJavaImportResult result = importWorkspace(workspaceRoot, ruleMapBuilder, projectView);
assertThat(
@@ -1047,7 +1049,8 @@
workingSet =
new JavaWorkingSet(
workspaceRoot,
- new WorkingSet(ImmutableList.of(), ImmutableList.of(), ImmutableList.of()));
+ new WorkingSet(ImmutableList.of(), ImmutableList.of(), ImmutableList.of()),
+ Predicate.isEqual("BUILD"));
BlazeJavaImportResult result = importWorkspace(workspaceRoot, ruleMapBuilder, projectView);
assertThat(
@@ -1214,7 +1217,8 @@
workingSet =
new JavaWorkingSet(
workspaceRoot,
- new WorkingSet(ImmutableList.of(), ImmutableList.of(), ImmutableList.of()));
+ new WorkingSet(ImmutableList.of(), ImmutableList.of(), ImmutableList.of()),
+ Predicate.isEqual("BUILD"));
// First test - make sure that jdeps is working
jdepsMap.put(
@@ -1233,7 +1237,8 @@
new WorkingSet(
ImmutableList.of(new WorkspacePath("java/example/BUILD")),
ImmutableList.of(),
- ImmutableList.of()));
+ ImmutableList.of()),
+ Predicate.isEqual("BUILD"));
result = importWorkspace(workspaceRoot, ruleMapBuilder, projectView);
errorCollector.assertNoIssues();
diff --git a/plugin_dev/src/com/google/idea/blaze/plugin/sync/IntellijPluginSyncPlugin.java b/plugin_dev/src/com/google/idea/blaze/plugin/sync/IntellijPluginSyncPlugin.java
index b4d13c7..93a27a3 100644
--- a/plugin_dev/src/com/google/idea/blaze/plugin/sync/IntellijPluginSyncPlugin.java
+++ b/plugin_dev/src/com/google/idea/blaze/plugin/sync/IntellijPluginSyncPlugin.java
@@ -63,7 +63,7 @@
}
@Override
- public void updateSdk(
+ public void updateProjectSdk(
Project project,
BlazeContext context,
ProjectViewSet projectViewSet,
diff --git a/testing/test_defs.bzl b/testing/test_defs.bzl
index 38baa7c..9fdbd90 100644
--- a/testing/test_defs.bzl
+++ b/testing/test_defs.bzl
@@ -6,6 +6,62 @@
"api_version_txt",
)
+def _generate_test_suite_impl(ctx):
+ """Generates a JUnit4 test suite pulling in all the referenced classes.
+
+ Args:
+ ctx: the rule context
+ """
+ suite_class_name = ctx.label.name
+ lines = []
+ lines.append("package %s;" % ctx.attr.test_package_root)
+ lines.append("")
+ test_srcs = _get_test_srcs(ctx.attr.srcs)
+ test_classes = [_get_test_class(test_src, ctx.attr.test_package_root) for test_src in test_srcs]
+ class_rules = ctx.attr.class_rules
+ if (class_rules):
+ lines.append("import org.junit.ClassRule;")
+ lines.append("import org.junit.runner.RunWith;")
+ lines.append("import org.junit.runners.Suite;")
+ lines.append("")
+ for test_class in test_classes:
+ lines.append("import %s;" % test_class)
+ lines.append("")
+ lines.append("@RunWith(Suite.class)")
+ lines.append("@Suite.SuiteClasses({")
+ for test_class in test_classes:
+ lines.append(" %s.class," % test_class.split(".")[-1])
+ lines.append("})")
+ lines.append("public class %s {" % suite_class_name)
+ lines.append("")
+
+ i = 1
+ for class_rule in class_rules:
+ lines.append("@ClassRule")
+ lines.append("public static %s setupRule_%d = new %s();" % (class_rule, i, class_rule))
+ i += 1
+
+ lines.append("}")
+
+ contents = "\n".join(lines)
+ ctx.file_action(
+ output = ctx.outputs.out,
+ content = contents,
+ )
+
+_generate_test_suite = rule(
+ implementation = _generate_test_suite_impl,
+ attrs = {
+ # srcs for the test classes included in the suite (only keep those ending in Test.java)
+ "srcs": attr.label_list(allow_files=True, mandatory=True),
+ # the package string of the output test suite.
+ "test_package_root": attr.string(mandatory=True),
+ # optional list of classes to instantiate as a @ClassRule in the test suite.
+ "class_rules": attr.string_list()
+ },
+ outputs={"out": "%{name}.java"},
+)
+
def intellij_unit_test_suite(name, srcs, test_package_root, **kwargs):
"""Creates a java_test rule comprising all valid test classes in the specified srcs.
@@ -17,14 +73,12 @@
test_package_root: only tests under this package root will be run.
**kwargs: Any other args to be passed to the java_test.
"""
- test_srcs = [test for test in srcs if test.endswith("Test.java")]
- test_classes = [_get_test_class(test_src, test_package_root) for test_src in test_srcs]
suite_class_name = name + "TestSuite"
suite_class = test_package_root + "." + suite_class_name
_generate_test_suite(
name = suite_class_name,
+ srcs = srcs,
test_package_root = test_package_root,
- test_classes = test_classes,
)
native.java_test(
name = name,
@@ -62,15 +116,13 @@
these plugins aren't loaded at runtime.
**kwargs: Any other args to be passed to the java_test.
"""
- test_srcs = [test for test in srcs if test.endswith("Test.java")]
- test_classes = [_get_test_class(test_src, test_package_root) for test_src in test_srcs]
suite_class_name = name + "TestSuite"
suite_class = test_package_root + "." + suite_class_name
_generate_test_suite(
name = suite_class_name,
+ srcs = srcs,
test_package_root = test_package_root,
- test_classes = test_classes,
- class_rules = ["com.google.idea.testing.BlazeTestSystemPropertiesRule"]
+ class_rules = ["com.google.idea.testing.BlazeTestSystemPropertiesRule"],
)
api_version_txt_name = name + "_api_version"
@@ -85,7 +137,7 @@
runtime_deps = list(runtime_deps)
runtime_deps.extend([
"//intellij_platform_sdk:bundled_plugins",
- "//third_party:jdk8_tools",
+ "//third_party:jpda-jdi",
])
jvm_flags = list(jvm_flags)
@@ -111,56 +163,20 @@
**kwargs
)
-def _generate_test_suite(name, test_package_root, test_classes, class_rules = []):
- """Generates a JUnit4 test suite pulling in all the referenced classes.
-
- Args:
- name: the name of the genrule and output test suite class.
- test_package_root: the package string of the output test suite.
- test_classes: the test classes included in the suite.
- class_rules: optional list of classes to instantiate as a @ClassRule in the test suite.
- """
- lines = []
- lines.append("package %s;" % test_package_root)
- lines.append("")
- if (class_rules):
- lines.append("import org.junit.ClassRule;")
- lines.append("import org.junit.runner.RunWith;")
- lines.append("import org.junit.runners.Suite;")
- lines.append("")
- for test_class in test_classes:
- lines.append("import %s;" % test_class)
- lines.append("")
- lines.append("@RunWith(Suite.class)")
- lines.append("@Suite.SuiteClasses({")
- for test_class in test_classes:
- lines.append(" %s.class," % test_class.split(".")[-1])
- lines.append("})")
- lines.append("public class %s {" % name)
- lines.append("")
-
- i = 1
- for class_rule in class_rules:
- lines.append("@ClassRule")
- lines.append("public static %s setupRule_%d = new %s();" % (class_rule, i, class_rule))
- i += 1
-
- lines.append("}")
-
- contents = "\\n".join(lines)
- native.genrule(
- name = name,
- cmd = "printf '%s' > $@" % contents,
- outs = [name + ".java"],
- )
-
def _get_test_class(test_src, test_package_root):
"""Returns the package string of the test class, beginning with the given root."""
- full_path = PACKAGE_NAME + "/" + test_src
- temp = full_path[:-5]
+ test_path = test_src.short_path
+ temp = test_path[:-len(".java")]
temp = temp.replace("/", ".")
i = temp.rfind(test_package_root)
if i < 0:
- fail("Test source '%s' not under package root '%s'" % (full_path, test_package_root))
+ fail("Test source '%s' not under package root '%s'" % (test_path, test_package_root))
test_class = temp[i:]
return test_class
+
+def _get_test_srcs(targets):
+ """Returns all files of the given targets that end with Test.java."""
+ files = set()
+ for target in targets:
+ files += target.files
+ return [f for f in files if f.basename.endswith("Test.java")]
diff --git a/third_party/BUILD b/third_party/BUILD
index d7eae12..04f13a6 100644
--- a/third_party/BUILD
+++ b/third_party/BUILD
@@ -1,8 +1,9 @@
package(default_visibility = ["//visibility:public"])
+# The JDI parts of tools.jar.
java_import(
- name = "jdk8_tools",
- jars = ["jdk8/tools.jar"],
+ name = "jpda-jdi",
+ jars = ["jdk8/jpda-jdi.jar"],
)
sh_binary(
diff --git a/third_party/jdk8/jpda-jdi.jar b/third_party/jdk8/jpda-jdi.jar
new file mode 100755
index 0000000..70c5058
--- /dev/null
+++ b/third_party/jdk8/jpda-jdi.jar
Binary files differ
diff --git a/third_party/jdk8/tools.jar b/third_party/jdk8/tools.jar
deleted file mode 100644
index f9f71d6..0000000
--- a/third_party/jdk8/tools.jar
+++ /dev/null
Binary files differ
diff --git a/version.bzl b/version.bzl
index 5cdb6a6..3775bd9 100644
--- a/version.bzl
+++ b/version.bzl
@@ -1,3 +1,3 @@
"""Version of the blaze plugin."""
-VERSION = "1.9.4"
+VERSION = "1.11.0"