/* * Copyright 2016 The Chromium Authors. All rights reserved. * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ package io.flutter.run.bazel; import com.google.common.annotations.VisibleForTesting; import com.intellij.execution.ExecutionBundle; import com.intellij.execution.configurations.ConfigurationFactory; import com.intellij.execution.configurations.ConfigurationTypeBase; import com.intellij.execution.configurations.RunConfiguration; import com.intellij.execution.configurations.RunConfigurationSingletonPolicy; import com.intellij.openapi.project.Project; import com.intellij.psi.search.FileTypeIndex; import com.intellij.psi.search.GlobalSearchScope; import com.jetbrains.lang.dart.DartFileType; import icons.FlutterIcons; import io.flutter.FlutterBundle; import io.flutter.utils.FlutterModuleUtils; import org.jetbrains.annotations.NotNull; public class FlutterBazelRunConfigurationType extends ConfigurationTypeBase { @VisibleForTesting final Factory factory = new Factory(this); public FlutterBazelRunConfigurationType() { super("FlutterBazelRunConfigurationType", FlutterBundle.message("runner.flutter.bazel.configuration.name"), FlutterBundle.message("runner.flutter.bazel.configuration.description"), FlutterIcons.BazelRun); addFactory(factory); } /** * Defined here for all Flutter Bazel run configurations. */ public static boolean doShowBazelRunConfigurationForProject(@NotNull Project project) { return FileTypeIndex.containsFileOfType(DartFileType.INSTANCE, GlobalSearchScope.projectScope(project)) && FlutterModuleUtils.isFlutterBazelProject(project); } @VisibleForTesting static class Factory extends ConfigurationFactory { public Factory(FlutterBazelRunConfigurationType type) { super(type); } @Override @NotNull public RunConfiguration createTemplateConfiguration(@NotNull Project project) { // This is always called first when loading a run config, even when it's a non-template config. // See RunManagerImpl.doCreateConfiguration return new BazelRunConfig(project, this, FlutterBundle.message("runner.flutter.bazel.configuration.name")); } @Override @NotNull public RunConfiguration createConfiguration(String name, RunConfiguration template) { // Called in two cases: // - When creating a non-template config from a template. // - whenever the run configuration editor is open (for creating snapshots). // In the first case, we want to override the defaults from the template. // In the second case, don't change anything. if (isNewlyGeneratedName(name) && template instanceof BazelRunConfig) { // TODO(jwren) is this really a good name for a new run config? Not sure why we override this. // Note that if the user creates more than one run config, they will need to rename it manually. name = template.getProject().getName(); return ((BazelRunConfig)template).copyTemplateToNonTemplate(name); } else { return super.createConfiguration(name, template); } } private boolean isNewlyGeneratedName(String name) { // Try to determine if this we are creating a non-template configuration from a template. // This is a hack based on what the code does in RunConfigurable.createUniqueName(). // If it fails to match, the new run config still works, just without any defaults set. final String baseName = ExecutionBundle.message("run.configuration.unnamed.name.prefix"); return name.equals(baseName) || name.startsWith(baseName + " ("); } @Override public boolean isApplicable(@NotNull Project project) { return FlutterBazelRunConfigurationType.doShowBazelRunConfigurationForProject(project); } @Override @NotNull public String getId() { return FlutterBundle.message("runner.flutter.bazel.configuration.name"); } @NotNull @Override public RunConfigurationSingletonPolicy getSingletonPolicy() { return RunConfigurationSingletonPolicy.MULTIPLE_INSTANCE_ONLY; } } }