package com.intellij.lang.javascript.flex.flexunit;
import com.intellij.execution.configurations.RuntimeConfigurationError;
import com.intellij.flex.FlexCommonBundle;
import com.intellij.flex.FlexCommonUtils;
import com.intellij.flex.model.bc.LinkageType;
import com.intellij.flex.model.bc.OutputType;
import com.intellij.javascript.flex.resolve.ActionScriptClassResolver;
import com.intellij.lang.javascript.flex.FlexBundle;
import com.intellij.lang.javascript.flex.FlexUtils;
import com.intellij.lang.javascript.flex.projectStructure.model.FlexBuildConfiguration;
import com.intellij.lang.javascript.flex.projectStructure.model.ModifiableDependencyEntry;
import com.intellij.lang.javascript.flex.projectStructure.model.ModifiableFlexBuildConfiguration;
import com.intellij.lang.javascript.flex.projectStructure.model.impl.Factory;
import com.intellij.lang.javascript.flex.run.BCBasedRunnerParameters;
import com.intellij.lang.javascript.flex.run.FlashRunnerParameters;
import com.intellij.lang.javascript.flex.run.LauncherParameters;
import com.intellij.lang.javascript.psi.JSFunction;
import com.intellij.lang.javascript.psi.ecmal4.JSClass;
import com.intellij.lang.javascript.psi.util.JSUtils;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.project.DumbService;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.projectRoots.Sdk;
import com.intellij.openapi.roots.CompilerModuleExtension;
import com.intellij.openapi.util.Pair;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vfs.VfsUtilCore;
import com.intellij.psi.PsiElement;
import com.intellij.psi.search.GlobalSearchScope;
import com.intellij.util.xmlb.annotations.Attribute;
import com.intellij.util.xmlb.annotations.Transient;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.Collections;
import static com.intellij.lang.javascript.flex.run.FlashRunnerParameters.AppDescriptorForEmulator;
public class FlexUnitRunnerParameters extends BCBasedRunnerParameters {
public enum Scope {
Method, Class, Package
}
public enum OutputLogLevel {
Fatal("1000"), Error("8"), Warn("6"), Info("4"), Debug("2"), All("0");
private final String myFlexConstant;
OutputLogLevel(String flexConstant) {
myFlexConstant = flexConstant;
}
public String getFlexConstant() {
return myFlexConstant;
}
}
private @NotNull Scope myScope = Scope.Class;
private @NotNull String myPackageName = "";
private @NotNull String myClassName = "";
private @NotNull String myMethodName = "";
private @Nullable OutputLogLevel myOutputLogLevel = null;
private @NotNull LauncherParameters myLauncherParameters = new LauncherParameters();
private boolean myTrusted = true;
private String myEmulatorAdlOptions = "";
private @NotNull AppDescriptorForEmulator myAppDescriptorForEmulator = AppDescriptorForEmulator.Android;
private int myPort;
private int mySocketPolicyPort;
public FlexUnitRunnerParameters() {
}
@NotNull
@Attribute("scope")
public Scope getScope() {
return myScope;
}
public void setScope(@NotNull Scope scope) {
myScope = scope;
}
@NotNull
@Attribute("package_name")
public String getPackageName() {
return myPackageName;
}
public void setPackageName(@NotNull String packageName) {
myPackageName = packageName;
}
@NotNull
@Attribute("class_name")
public String getClassName() {
return myClassName;
}
public void setClassName(@NotNull String className) {
myClassName = className;
}
@NotNull
@Attribute("method_name")
public String getMethodName() {
return myMethodName;
}
public void setMethodName(@NotNull String methodName) {
myMethodName = methodName;
}
@Transient
public int getPort() {
return myPort;
}
public void setPort(int port) {
myPort = port;
}
@Transient
public int getSocketPolicyPort() {
return mySocketPolicyPort;
}
public void setSocketPolicyPort(int port) {
mySocketPolicyPort = port;
}
@Nullable
@Attribute("output_log_level")
public OutputLogLevel getOutputLogLevel() {
return myOutputLogLevel;
}
public void setOutputLogLevel(@Nullable OutputLogLevel outputLogLevel) {
myOutputLogLevel = outputLogLevel;
}
@NotNull
public LauncherParameters getLauncherParameters() {
return myLauncherParameters;
}
public void setLauncherParameters(@NotNull final LauncherParameters launcherParameters) {
myLauncherParameters = launcherParameters;
}
public boolean isTrusted() {
return myTrusted;
}
public void setTrusted(final boolean trusted) {
myTrusted = trusted;
}
@NotNull
@Attribute("emulatorAdlOptions")
public String getEmulatorAdlOptions() {
return myEmulatorAdlOptions;
}
public void setEmulatorAdlOptions(final String emulatorAdlOptions) {
myEmulatorAdlOptions = emulatorAdlOptions;
}
@NotNull
@Attribute("appDescriptorForEmulator")
public AppDescriptorForEmulator getAppDescriptorForEmulator() {
return myAppDescriptorForEmulator;
}
public void setAppDescriptorForEmulator(@NotNull final AppDescriptorForEmulator appDescriptorForEmulator) {
myAppDescriptorForEmulator = appDescriptorForEmulator;
}
public void check(final Project project) throws RuntimeConfigurationError {
doCheck(project, super.checkAndGetModuleAndBC(project));
}
public Pair<Module, FlexBuildConfiguration> checkAndGetModuleAndBC(final Project project) throws RuntimeConfigurationError {
final Pair<Module, FlexBuildConfiguration> moduleAndBC = super.checkAndGetModuleAndBC(project);
doCheck(project, moduleAndBC);
final ModifiableFlexBuildConfiguration overriddenBC = Factory.getTemporaryCopyForCompilation(moduleAndBC.second);
overriddenBC.setOutputType(OutputType.Application);
overriddenBC.setMainClass(FlexCommonUtils.FLEX_UNIT_LAUNCHER);
overriddenBC.setOutputFileName("_flexunit.swf");
overriddenBC
.setOutputFolder(VfsUtilCore.urlToPath(CompilerModuleExtension.getInstance(moduleAndBC.first).getCompilerOutputUrlForTests()));
overriddenBC.setUseHtmlWrapper(false);
overriddenBC.setRLMs(Collections.emptyList());
overriddenBC.setCssFilesToCompile(Collections.emptyList());
overriddenBC.setSkipCompile(false);
overriddenBC.getDependencies().setFrameworkLinkage(LinkageType.Merged);
for (ModifiableDependencyEntry entry : overriddenBC.getDependencies().getModifiableEntries()) {
if (entry.getDependencyType().getLinkageType() == LinkageType.External) {
entry.getDependencyType().setLinkageType(LinkageType.Merged);
}
}
//overriddenBC.getAirDesktopPackagingOptions().setUseGeneratedDescriptor(true);
/*
overriddenBC.getAndroidPackagingOptions().setPackageFileName("_flexunit.apk");
final ModifiableAndroidPackagingOptions androidOptions = overriddenBC.getAndroidPackagingOptions();
androidOptions.setEnabled(true);
androidOptions.setUseGeneratedDescriptor(true);
androidOptions.getSigningOptions().setUseTempCertificate(true);
overriddenBC.getIosPackagingOptions().setEnabled(false);
overriddenBC.getIosPackagingOptions().setPackageFileName("_flexunit.ipa");
*/
return Pair.create(moduleAndBC.first, ((FlexBuildConfiguration)overriddenBC));
}
private void doCheck(final Project project, final Pair<Module, FlexBuildConfiguration> moduleAndBC) throws RuntimeConfigurationError {
if (DumbService.getInstance(project).isDumb()) return;
final FlexBuildConfiguration bc = moduleAndBC.second;
final Sdk sdk = bc.getSdk();
if (sdk == null) {
throw new RuntimeConfigurationError(
FlexCommonBundle.message("sdk.not.set.for.bc.0.of.module.1", bc.getName(), moduleAndBC.first.getName()));
}
switch (bc.getTargetPlatform()) {
case Web:
break;
case Desktop:
FlashRunnerParameters.checkAdlAndAirRuntime(sdk);
if (bc.getOutputType() == OutputType.Application) {
FlashRunnerParameters.checkCustomDescriptor(bc.getAirDesktopPackagingOptions(), getBCName(), getModuleName());
}
break;
case Mobile:
FlashRunnerParameters.checkAdlAndAirRuntime(sdk);
switch (myAppDescriptorForEmulator) {
case Android:
if (bc.getOutputType() == OutputType.Application) {
FlashRunnerParameters.checkCustomDescriptor(bc.getAndroidPackagingOptions(), getBCName(), getModuleName());
}
break;
case IOS:
if (bc.getOutputType() == OutputType.Application) {
FlashRunnerParameters.checkCustomDescriptor(bc.getIosPackagingOptions(), getBCName(), getModuleName());
}
break;
}
break;
}
final FlexUnitSupport support = FlexUnitSupport.getSupport(bc, moduleAndBC.first);
if (support == null) {
throw new RuntimeConfigurationError(FlexBundle.message("flexunit.not.found.for.bc", bc.getName()));
}
if (!support.flexUnit4Present && bc.isPureAs()) {
throw new RuntimeConfigurationError(FlexBundle.message("cant.execute.flexunit1.for.pure.as.bc"));
}
final GlobalSearchScope searchScope = FlexUtils.getModuleWithDependenciesAndLibrariesScope(moduleAndBC.first, bc, true);
switch (getScope()) {
case Class:
getClassToTest(getClassName(), searchScope, support, true);
break;
case Method:
final JSClass classToTest = getClassToTest(getClassName(), searchScope, support, false);
if (StringUtil.isEmpty(getMethodName())) {
throw new RuntimeConfigurationError(FlexBundle.message("no.test.method.specified"));
}
final JSFunction methodToTest = classToTest.findFunctionByNameAndKind(getMethodName(), JSFunction.FunctionKind.SIMPLE);
if (methodToTest == null || !support.isTestMethod(methodToTest)) {
throw new RuntimeConfigurationError(FlexBundle.message("method.not.valid", getMethodName()));
}
break;
case Package:
if (!JSUtils.packageExists(getPackageName(), searchScope)) {
throw new RuntimeConfigurationError(FlexBundle.message("package.not.valid", getPackageName()));
}
break;
default:
assert false : "Unknown scope: " + getScope();
}
}
private static JSClass getClassToTest(String className,
GlobalSearchScope searchScope,
@NotNull FlexUnitSupport flexUnitSupport,
boolean allowSuite) throws RuntimeConfigurationError {
if (StringUtil.isEmpty(className)) {
throw new RuntimeConfigurationError(FlexBundle.message("test.class.not.specified"));
}
final PsiElement classToTest = ActionScriptClassResolver.findClassByQNameStatic(className, searchScope);
if (!(classToTest instanceof JSClass)) {
throw new RuntimeConfigurationError(FlexBundle.message("class.not.found", className));
}
if (!flexUnitSupport.isTestClass((JSClass)classToTest, allowSuite)) {
throw new RuntimeConfigurationError(FlexBundle.message("class.contains.no.tests", className));
}
return (JSClass)classToTest;
}
@Override
public FlexUnitRunnerParameters clone() {
final FlexUnitRunnerParameters clone = (FlexUnitRunnerParameters)super.clone();
clone.myLauncherParameters = myLauncherParameters.clone();
return clone;
}
public boolean equals(final Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
if (!super.equals(o)) return false;
final FlexUnitRunnerParameters that = (FlexUnitRunnerParameters)o;
if (myTrusted != that.myTrusted) return false;
if (!myClassName.equals(that.myClassName)) return false;
if (!myLauncherParameters.equals(that.myLauncherParameters)) return false;
if (!myMethodName.equals(that.myMethodName)) return false;
if (myOutputLogLevel != that.myOutputLogLevel) return false;
if (!myPackageName.equals(that.myPackageName)) return false;
if (myScope != that.myScope) return false;
return true;
}
}