diff --git a/base/src/com/google/idea/blaze/base/run/BlazeCommandRunConfiguration.java b/base/src/com/google/idea/blaze/base/run/BlazeCommandRunConfiguration.java index f8dd6c07a7c..4a8509cef5e 100644 --- a/base/src/com/google/idea/blaze/base/run/BlazeCommandRunConfiguration.java +++ b/base/src/com/google/idea/blaze/base/run/BlazeCommandRunConfiguration.java @@ -256,12 +256,11 @@ public void setTarget(@Nullable TargetExpression target) { private void updateHandler() { BlazeCommandRunConfigurationHandlerProvider handlerProvider = - BlazeCommandRunConfigurationHandlerProvider.findHandlerProvider( - getTargetState(), getTargetKind()); + BlazeCommandRunConfigurationHandlerProvider.findHandlerProvider(this); updateHandlerIfDifferentProvider(handlerProvider); } - private TargetState getTargetState() { + public TargetState getTargetState() { return targetPatterns.isEmpty() && pendingContext != null ? TargetState.PENDING : TargetState.KNOWN; diff --git a/base/src/com/google/idea/blaze/base/run/confighandler/BlazeCommandRunConfigurationHandlerProvider.java b/base/src/com/google/idea/blaze/base/run/confighandler/BlazeCommandRunConfigurationHandlerProvider.java index 46fd6c5fa64..ef9819431ef 100644 --- a/base/src/com/google/idea/blaze/base/run/confighandler/BlazeCommandRunConfigurationHandlerProvider.java +++ b/base/src/com/google/idea/blaze/base/run/confighandler/BlazeCommandRunConfigurationHandlerProvider.java @@ -51,6 +51,22 @@ static BlazeCommandRunConfigurationHandlerProvider findHandlerProvider( "No BlazeCommandRunConfigurationHandlerProvider found for Kind " + kind); } + /** + * Find a {@link BlazeCommandRunConfigurationHandlerProvider} applicable to the given configuration. Providers that + * need richer context than just the {@link Kind} can override {@link canHandleConfig} to make use of it. + */ + static BlazeCommandRunConfigurationHandlerProvider findHandlerProvider( + BlazeCommandRunConfiguration configuration) { + for (BlazeCommandRunConfigurationHandlerProvider handlerProvider : EP_NAME.getExtensions()) { + if (handlerProvider.canHandleConfig(configuration)) { + return handlerProvider; + } + } + + throw new RuntimeException( + "No BlazeCommandRunConfigurationHandlerProvider found for configuration " + configuration.getName()); + } + /** Get the BlazeCommandRunConfigurationHandlerProvider with the given ID, if one exists. */ @Nullable static BlazeCommandRunConfigurationHandlerProvider getHandlerProvider(@Nullable String id) { @@ -65,6 +81,14 @@ static BlazeCommandRunConfigurationHandlerProvider getHandlerProvider(@Nullable /** Whether this extension is applicable to the kind. */ boolean canHandleKind(TargetState state, @Nullable Kind kind); + /** + * Whether this extension is applicable to the given configuration. Defaults to delegating to + * {@link #canHandleKind}; override when the decision depends on details beyond the rule kind. + */ + default boolean canHandleConfig(BlazeCommandRunConfiguration configuration) { + return canHandleKind(configuration.getTargetState(), configuration.getTargetKind()); + } + /** Returns the corresponding {@link BlazeCommandRunConfigurationHandler}. */ BlazeCommandRunConfigurationHandler createHandler(BlazeCommandRunConfiguration configuration); diff --git a/java/src/com/google/idea/blaze/java/run/BlazeJavaDebuggerRunner.java b/java/src/com/google/idea/blaze/java/run/BlazeJavaDebuggerRunner.java index 19eda392eb6..30187b0cb6b 100644 --- a/java/src/com/google/idea/blaze/java/run/BlazeJavaDebuggerRunner.java +++ b/java/src/com/google/idea/blaze/java/run/BlazeJavaDebuggerRunner.java @@ -17,7 +17,6 @@ import com.google.idea.blaze.base.command.BlazeCommandName; import com.google.idea.blaze.base.logging.EventLoggingService; -import com.google.idea.blaze.base.model.primitives.Kind; import com.google.idea.blaze.base.run.BlazeCommandRunConfiguration; import com.intellij.debugger.impl.GenericDebuggerRunner; import com.intellij.execution.ExecutionException; @@ -49,8 +48,7 @@ public boolean canRun(final String executorId, final RunProfile profile) { return false; } BlazeCommandRunConfiguration configuration = (BlazeCommandRunConfiguration) profile; - Kind kind = configuration.getTargetKind(); - if (kind == null || !BlazeJavaRunConfigurationHandlerProvider.supportsKind(kind)) { + if (!BlazeJavaRunConfigurationHandlerProvider.supports(configuration)) { return false; } return canDebug(configuration.getHandler().getCommandName()); diff --git a/java/src/com/google/idea/blaze/java/run/BlazeJavaRunConfigurationHandlerProvider.java b/java/src/com/google/idea/blaze/java/run/BlazeJavaRunConfigurationHandlerProvider.java index 8e6aed82f5d..be6c3c14427 100644 --- a/java/src/com/google/idea/blaze/java/run/BlazeJavaRunConfigurationHandlerProvider.java +++ b/java/src/com/google/idea/blaze/java/run/BlazeJavaRunConfigurationHandlerProvider.java @@ -16,10 +16,17 @@ package com.google.idea.blaze.java.run; import com.google.common.collect.ImmutableSet; +import com.google.idea.blaze.base.ideinfo.TargetIdeInfo; +import com.google.idea.blaze.base.ideinfo.TargetKey; +import com.google.idea.blaze.base.model.BlazeProjectData; import com.google.idea.blaze.base.model.primitives.Kind; +import com.google.idea.blaze.base.model.primitives.Label; +import com.google.idea.blaze.base.model.primitives.RuleType; +import com.google.idea.blaze.base.model.primitives.TargetExpression; import com.google.idea.blaze.base.run.BlazeCommandRunConfiguration; import com.google.idea.blaze.base.run.confighandler.BlazeCommandRunConfigurationHandler; import com.google.idea.blaze.base.run.confighandler.BlazeCommandRunConfigurationHandlerProvider; +import com.google.idea.blaze.base.sync.data.BlazeProjectDataManager; import com.google.idea.blaze.java.sync.source.JavaLikeLanguage; import javax.annotation.Nullable; @@ -30,15 +37,61 @@ public class BlazeJavaRunConfigurationHandlerProvider private static final ImmutableSet RELEVANT_RULE_KINDS = JavaLikeLanguage.getAllDebuggableKinds(); + /** + * A fallback for {@link supports} that can be used when synced target data isn't available. Prefer to call + * {@link supports} instead. + */ static boolean supportsKind(@Nullable Kind kind) { return RELEVANT_RULE_KINDS.contains(kind); } + /** + * Returns whether the Java handler should drive this configuration. True if either (a) the + * target's synced {@link TargetIdeInfo} carries a {@code JavaIdeInfo} and is a test or binary, or (b) the rule kind + * is explicitly registered as Java-like. + */ + public static boolean supports(BlazeCommandRunConfiguration configuration) { + TargetIdeInfo target = resolveTarget(configuration); + + if (target != null && target.getJavaIdeInfo() != null) { + RuleType ruleType = target.getKind().getRuleType(); + + if (ruleType == RuleType.TEST || ruleType == RuleType.BINARY) { + return true; + } + } + + return supportsKind(configuration.getTargetKind()); + } + + @Nullable + private static TargetIdeInfo resolveTarget(BlazeCommandRunConfiguration configuration) { + TargetExpression target = configuration.getSingleTarget(); + + if (!(target instanceof Label)) { + return null; + } + + BlazeProjectData projectData = + BlazeProjectDataManager.getInstance(configuration.getProject()).getBlazeProjectData(); + + if (projectData == null) { + return null; + } + + return projectData.getTargetMap().get(TargetKey.forPlainTarget((Label) target)); + } + @Override public boolean canHandleKind(TargetState state, @Nullable Kind kind) { return supportsKind(kind); } + @Override + public boolean canHandleConfig(BlazeCommandRunConfiguration configuration) { + return supports(configuration); + } + @Override public BlazeCommandRunConfigurationHandler createHandler(BlazeCommandRunConfiguration config) { return new BlazeJavaRunConfigurationHandler(config);