package com.intellij.lang.javascript.flex.flexunit;
import com.intellij.execution.*;
import com.intellij.execution.configuration.EmptyRunProfileState;
import com.intellij.execution.configurations.*;
import com.intellij.execution.process.ProcessHandler;
import com.intellij.execution.runners.ExecutionEnvironment;
import com.intellij.execution.runners.ProgramRunner;
import com.intellij.execution.ui.ExecutionConsole;
import com.intellij.flex.model.bc.BuildConfigurationNature;
import com.intellij.lang.javascript.flex.FlexModuleType;
import com.intellij.lang.javascript.flex.FlexRefactoringListenerProvider;
import com.intellij.lang.javascript.flex.projectStructure.model.FlexBuildConfiguration;
import com.intellij.lang.javascript.flex.run.FlashRunConfiguration;
import com.intellij.lang.javascript.flex.run.FlexBaseRunner;
import com.intellij.lang.javascript.flex.run.FlexRunConfigRefactoringListener;
import com.intellij.lang.javascript.psi.JSFunction;
import com.intellij.lang.javascript.psi.ecmal4.JSClass;
import com.intellij.lang.javascript.psi.ecmal4.JSPackage;
import com.intellij.lang.javascript.psi.ecmal4.JSPackageStatement;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.module.ModuleManager;
import com.intellij.openapi.module.ModuleType;
import com.intellij.openapi.module.ModuleUtilCore;
import com.intellij.openapi.options.SettingsEditor;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Comparing;
import com.intellij.openapi.util.InvalidDataException;
import com.intellij.openapi.util.WriteExternalException;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.psi.PsiDirectory;
import com.intellij.psi.PsiDirectoryContainer;
import com.intellij.psi.PsiElement;
import com.intellij.refactoring.listeners.RefactoringElementListener;
import com.intellij.util.xmlb.XmlSerializer;
import org.jdom.Element;
import org.jetbrains.annotations.NotNull;
public class FlexUnitRunConfiguration extends LocatableConfigurationBase
implements RunProfileWithCompileBeforeLaunchOption, RefactoringListenerProvider {
private FlexUnitRunnerParameters myRunnerParameters = new FlexUnitRunnerParameters();
protected FlexUnitRunConfiguration(Project project, ConfigurationFactory factory, String name) {
super(project, factory, name);
}
@NotNull
@Override
public SettingsEditor<? extends RunConfiguration> getConfigurationEditor() {
return new FlexUnitRunConfigurationForm(getProject());
}
@Override
public void readExternal(final Element element) throws InvalidDataException {
super.readExternal(element);
myRunnerParameters = new FlexUnitRunnerParameters();
XmlSerializer.deserializeInto(myRunnerParameters, element);
}
@Override
public void writeExternal(final Element element) throws WriteExternalException {
super.writeExternal(element);
XmlSerializer.serializeInto(myRunnerParameters, element);
}
@Override
public FlexUnitRunConfiguration clone() {
final FlexUnitRunConfiguration clone = (FlexUnitRunConfiguration)super.clone();
clone.myRunnerParameters = myRunnerParameters.clone();
return clone;
}
@NotNull
public FlexUnitRunnerParameters getRunnerParameters() {
return myRunnerParameters;
}
@Override
public String suggestedName() {
switch (myRunnerParameters.getScope()) {
case Class:
return StringUtil.getShortName(myRunnerParameters.getClassName());
case Method:
return StringUtil.getShortName(myRunnerParameters.getClassName()) + "." + myRunnerParameters.getMethodName() + "()";
case Package:
return StringUtil.isEmpty(myRunnerParameters.getPackageName())
? myRunnerParameters.getModuleName()
: myRunnerParameters.getPackageName();
default:
assert false : "Unknown scope: " + myRunnerParameters.getScope();
return null;
}
}
@Override
@NotNull
public Module[] getModules() {
final Module module = ModuleManager.getInstance(getProject()).findModuleByName(myRunnerParameters.getModuleName());
if (module != null && ModuleType.get(module) instanceof FlexModuleType) {
return new Module[]{module};
}
else {
return Module.EMPTY_ARRAY;
}
}
@Override
public RunProfileState getState(@NotNull final Executor executor, @NotNull final ExecutionEnvironment env) throws ExecutionException {
final FlexBuildConfiguration bc;
try {
bc = myRunnerParameters.checkAndGetModuleAndBC(getProject()).second;
}
catch (RuntimeConfigurationError e) {
throw new ExecutionException(e.getMessage());
}
final BuildConfigurationNature nature = bc.getNature();
if (nature.isDesktopPlatform() || nature.isMobilePlatform()) {
return new FlashRunConfiguration.AirRunState(getProject(), env, myRunnerParameters) {
@NotNull
@Override
public ExecutionResult execute(@NotNull Executor executor, @NotNull ProgramRunner runner) throws ExecutionException {
final ProcessHandler processHandler = startProcess();
final ExecutionConsole console = FlexBaseRunner.createFlexUnitRunnerConsole(getProject(), env, processHandler);
return new DefaultExecutionResult(console, processHandler);
}
};
}
return EmptyRunProfileState.INSTANCE;
}
@Override
public void checkConfiguration() throws RuntimeConfigurationError {
myRunnerParameters.check(getProject());
}
@Override
public RefactoringElementListener getRefactoringElementListener(final PsiElement element) {
final FlexUnitRunnerParameters params = getRunnerParameters();
final Module module = ModuleManager.getInstance(getProject()).findModuleByName(params.getModuleName());
if (!(element instanceof PsiDirectoryContainer) && !(element instanceof JSPackage) && !(element instanceof JSPackageStatement)
&& (module == null || !module.equals(ModuleUtilCore.findModuleForPsiElement(element)))) {
return null;
}
switch (params.getScope()) {
case Method:
if (element instanceof JSFunction) {
final PsiElement parent = element.getParent();
if (parent instanceof JSClass &&
Comparing.strEqual(((JSClass)parent).getQualifiedName(), params.getClassName()) &&
Comparing.strEqual(((JSFunction)element).getName(), params.getMethodName())) {
return new FlexRunConfigRefactoringListener.JSFunctionRefactoringListener(this);
}
}
// no break here!
case Class:
if (element instanceof PsiDirectory &&
FlashRunConfiguration.containsClass(module, ((PsiDirectory)element), params.getClassName())) {
return new FlexRunConfigRefactoringListener.PsiDirectoryRefactoringListener(this);
}
final JSClass jsClass = FlexRefactoringListenerProvider.getJSClass(element);
if (jsClass != null && Comparing.strEqual(jsClass.getQualifiedName(), params.getClassName())) {
return new FlexRunConfigRefactoringListener.JSClassRefactoringListener(this);
}
// no break here!
case Package:
final String currentPackage = params.getScope() == FlexUnitRunnerParameters.Scope.Package
? params.getPackageName()
: StringUtil.getPackageName(params.getClassName());
if ((element instanceof PsiDirectoryContainer || element instanceof JSPackage || element instanceof JSPackageStatement) &&
Comparing.strEqual(FlexRefactoringListenerProvider.getPackageName(element), currentPackage)) {
return new FlexRunConfigRefactoringListener.PackageRefactoringListener(this);
}
}
return null;
}
}