blob: 8609d1474443020bd08eeca1dec9c48489b5fb1e [file] [log] [blame]
/*
* 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;
import static com.google.idea.blaze.android.cppapi.NdkSupport.NDK_SUPPORT;
import com.android.tools.idea.run.ValidationError;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Lists;
import com.google.idea.blaze.android.cppapi.NdkSupport;
import com.google.idea.blaze.android.run.runner.BlazeAndroidRunConfigurationDebuggerManager;
import com.google.idea.blaze.android.run.runner.BlazeAndroidRunConfigurationDeployTargetManager;
import com.google.idea.blaze.base.command.BlazeCommandName;
import com.google.idea.blaze.base.command.BlazeFlags;
import com.google.idea.blaze.base.command.BlazeInvocationContext;
import com.google.idea.blaze.base.projectview.ProjectViewSet;
import com.google.idea.blaze.base.run.state.RunConfigurationFlagsState;
import com.google.idea.blaze.base.run.state.RunConfigurationState;
import com.google.idea.blaze.base.run.state.RunConfigurationStateEditor;
import com.google.idea.blaze.base.ui.UiUtil;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.InvalidDataException;
import com.intellij.openapi.util.WriteExternalException;
import java.awt.Component;
import java.util.List;
import javax.annotation.Nullable;
import javax.swing.JCheckBox;
import javax.swing.JComponent;
import org.jdom.Element;
import org.jetbrains.android.facet.AndroidFacet;
/** A shared state class for run configurations targeting Blaze Android rules. */
public class BlazeAndroidRunConfigurationCommonState implements RunConfigurationState {
private static final String DEPLOY_TARGET_STATES_TAG = "android-deploy-target-states";
private static final String DEBUGGER_STATES_TAG = "android-debugger-states";
private static final String USER_BLAZE_FLAG_TAG = "blaze-user-flag";
private static final String USER_EXE_FLAG_TAG = "blaze-user-exe-flag";
private static final String NATIVE_DEBUG_ATTR = "blaze-native-debug";
// We need to split "-c dbg" into two flags because we pass flags
// as a list of strings to the command line executor and we need blaze
// to see -c and dbg as two separate entities, not one.
private static final ImmutableList<String> NATIVE_DEBUG_FLAGS =
ImmutableList.of("--fission=no", "-c", "dbg");
private final BlazeAndroidRunConfigurationDeployTargetManager deployTargetManager;
private final BlazeAndroidRunConfigurationDebuggerManager debuggerManager;
private final RunConfigurationFlagsState blazeFlags;
private final RunConfigurationFlagsState exeFlags;
private boolean nativeDebuggingEnabled = false;
public BlazeAndroidRunConfigurationCommonState(String buildSystemName, boolean isAndroidTest) {
this.deployTargetManager = new BlazeAndroidRunConfigurationDeployTargetManager(isAndroidTest);
this.debuggerManager = new BlazeAndroidRunConfigurationDebuggerManager(this);
this.blazeFlags =
new RunConfigurationFlagsState(USER_BLAZE_FLAG_TAG, buildSystemName + " flags:");
this.exeFlags =
new RunConfigurationFlagsState(
USER_EXE_FLAG_TAG, "Executable flags (mobile-install only):");
}
public BlazeAndroidRunConfigurationDeployTargetManager getDeployTargetManager() {
return deployTargetManager;
}
public BlazeAndroidRunConfigurationDebuggerManager getDebuggerManager() {
return debuggerManager;
}
public RunConfigurationFlagsState getBlazeFlagsState() {
return blazeFlags;
}
public RunConfigurationFlagsState getExeFlagsState() {
return exeFlags;
}
public boolean isNativeDebuggingEnabled() {
return nativeDebuggingEnabled && NDK_SUPPORT.getValue();
}
public void setNativeDebuggingEnabled(boolean nativeDebuggingEnabled) {
this.nativeDebuggingEnabled = nativeDebuggingEnabled;
}
public ImmutableList<String> getExpandedBuildFlags(
Project project, ProjectViewSet projectViewSet, BlazeCommandName command) {
return ImmutableList.<String>builder()
.addAll(
BlazeFlags.blazeFlags(
project, projectViewSet, command, BlazeInvocationContext.RunConfiguration))
.addAll(getBlazeFlagsState().getExpandedFlags())
.addAll(getNativeDebuggerFlags())
.build();
}
private ImmutableList<String> getNativeDebuggerFlags() {
return isNativeDebuggingEnabled() ? NATIVE_DEBUG_FLAGS : ImmutableList.of();
}
/**
* We collect errors rather than throwing to avoid missing fatal errors by exiting early for a
* warning.
*/
public List<ValidationError> validate(@Nullable AndroidFacet facet) {
List<ValidationError> errors = Lists.newArrayList();
// If facet is null, we can't validate the managers, but that's fine because
// BlazeAndroidRunConfigurationValidationUtil.validateFacet will give a fatal error.
if (facet != null) {
errors.addAll(deployTargetManager.validate(facet));
errors.addAll(debuggerManager.validate(facet));
}
return errors;
}
@Override
public void readExternal(Element element) throws InvalidDataException {
blazeFlags.readExternal(element);
exeFlags.readExternal(element);
setNativeDebuggingEnabled(Boolean.parseBoolean(element.getAttributeValue(NATIVE_DEBUG_ATTR)));
Element deployTargetStatesElement = element.getChild(DEPLOY_TARGET_STATES_TAG);
if (deployTargetStatesElement != null) {
deployTargetManager.readExternal(deployTargetStatesElement);
}
Element debuggerStatesElement = element.getChild(DEBUGGER_STATES_TAG);
if (debuggerStatesElement != null) {
debuggerManager.readExternal(debuggerStatesElement);
}
}
@Override
public void writeExternal(Element element) throws WriteExternalException {
blazeFlags.writeExternal(element);
exeFlags.writeExternal(element);
element.setAttribute(NATIVE_DEBUG_ATTR, Boolean.toString(nativeDebuggingEnabled));
element.removeChildren(DEPLOY_TARGET_STATES_TAG);
Element deployTargetStatesElement = new Element(DEPLOY_TARGET_STATES_TAG);
deployTargetManager.writeExternal(deployTargetStatesElement);
element.addContent(deployTargetStatesElement);
element.removeChildren(DEBUGGER_STATES_TAG);
Element debuggerStatesElement = new Element(DEBUGGER_STATES_TAG);
debuggerManager.writeExternal(debuggerStatesElement);
element.addContent(debuggerStatesElement);
}
@Override
public RunConfigurationStateEditor getEditor(Project project) {
return new BlazeAndroidRunConfigurationCommonStateEditor(this, project);
}
private static class BlazeAndroidRunConfigurationCommonStateEditor
implements RunConfigurationStateEditor {
private final RunConfigurationStateEditor blazeFlagsEditor;
private final RunConfigurationStateEditor exeFlagsEditor;
private final JCheckBox enableNativeDebuggingCheckBox;
BlazeAndroidRunConfigurationCommonStateEditor(
BlazeAndroidRunConfigurationCommonState state, Project project) {
blazeFlagsEditor = state.blazeFlags.getEditor(project);
exeFlagsEditor = state.exeFlags.getEditor(project);
enableNativeDebuggingCheckBox = new JCheckBox("Enable native debugging", false);
}
@Override
public void resetEditorFrom(RunConfigurationState genericState) {
BlazeAndroidRunConfigurationCommonState state =
(BlazeAndroidRunConfigurationCommonState) genericState;
blazeFlagsEditor.resetEditorFrom(state.blazeFlags);
exeFlagsEditor.resetEditorFrom(state.exeFlags);
enableNativeDebuggingCheckBox.setSelected(state.isNativeDebuggingEnabled());
}
@Override
public void applyEditorTo(RunConfigurationState genericState) {
BlazeAndroidRunConfigurationCommonState state =
(BlazeAndroidRunConfigurationCommonState) genericState;
blazeFlagsEditor.applyEditorTo(state.blazeFlags);
exeFlagsEditor.applyEditorTo(state.exeFlags);
state.setNativeDebuggingEnabled(enableNativeDebuggingCheckBox.isSelected());
}
@Override
public JComponent createComponent() {
List<Component> result =
Lists.newArrayList(blazeFlagsEditor.createComponent(), exeFlagsEditor.createComponent());
if (NdkSupport.NDK_SUPPORT.getValue()) {
result.add(enableNativeDebuggingCheckBox);
}
return UiUtil.createBox(result);
}
@Override
public void setComponentEnabled(boolean enabled) {
blazeFlagsEditor.setComponentEnabled(enabled);
exeFlagsEditor.setComponentEnabled(enabled);
enableNativeDebuggingCheckBox.setEnabled(enabled);
}
}
}