package com.intellij.lang.javascript.flex.flexunit; import com.intellij.execution.actions.ConfigurationContext; import com.intellij.execution.actions.RunConfigurationProducer; import com.intellij.flex.model.bc.TargetPlatform; import com.intellij.lang.javascript.JavaScriptSupportLoader; import com.intellij.lang.javascript.flex.FlexModuleType; import com.intellij.lang.javascript.flex.projectStructure.model.FlexBuildConfiguration; import com.intellij.lang.javascript.flex.projectStructure.model.FlexBuildConfigurationManager; import com.intellij.lang.javascript.flex.run.FlashRunnerParameters; import com.intellij.lang.javascript.psi.JSFile; import com.intellij.lang.javascript.psi.JSFunction; import com.intellij.lang.javascript.psi.ecmal4.JSClass; import com.intellij.lang.javascript.psi.impl.JSPsiImplUtils; import com.intellij.lang.javascript.psi.util.JSUtils; import com.intellij.openapi.module.Module; import com.intellij.openapi.module.ModuleType; import com.intellij.openapi.roots.ProjectFileIndex; import com.intellij.openapi.roots.ProjectRootManager; import com.intellij.openapi.util.Ref; import com.intellij.openapi.vfs.VfsUtilCore; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.psi.PsiDirectory; import com.intellij.psi.PsiDirectoryContainer; import com.intellij.psi.PsiElement; import com.intellij.psi.PsiNamedElement; import com.intellij.psi.search.GlobalSearchScope; import com.intellij.psi.util.PsiTreeUtil; import org.jetbrains.annotations.Nullable; public class FlexUnitRuntimeConfigurationProducer extends RunConfigurationProducer<FlexUnitRunConfiguration> { public FlexUnitRuntimeConfigurationProducer() { super(FlexUnitRunConfigurationType.getInstance()); } protected boolean setupConfigurationFromContext(final FlexUnitRunConfiguration configuration, final ConfigurationContext context, final Ref<PsiElement> sourceElement) { final Module module = context.getModule(); if (module == null || ModuleType.get(module) != FlexModuleType.getInstance()) return false; final PsiElement element = findTestElement(context.getPsiLocation()); if (element == null) return false; if (!configureRunnerParameters(configuration.getRunnerParameters(), module, element)) return false; configuration.setGeneratedName(); return true; } public boolean isConfigurationFromContext(final FlexUnitRunConfiguration configuration, final ConfigurationContext context) { final Module module = context.getModule(); if (module == null || ModuleType.get(module) != FlexModuleType.getInstance()) return false; final PsiElement element = findTestElement(context.getPsiLocation()); if (element == null) return false; final FlexUnitRunnerParameters fakeParams = new FlexUnitRunnerParameters(); if (!configureRunnerParameters(fakeParams, module, element)) return false; final FlexUnitRunnerParameters params = configuration.getRunnerParameters(); if (params.getModuleName().equals(fakeParams.getModuleName()) && params.getScope() == fakeParams.getScope() && (params.getScope() != FlexUnitRunnerParameters.Scope.Package || params.getPackageName().equals(fakeParams.getPackageName())) && (params.getScope() == FlexUnitRunnerParameters.Scope.Package || params.getClassName().equals(fakeParams.getClassName())) && (params.getScope() != FlexUnitRunnerParameters.Scope.Method || params.getMethodName().equals(fakeParams.getMethodName()))) { return true; } return false; } private static boolean configureRunnerParameters(final FlexUnitRunnerParameters params, final Module module, final PsiElement element) { final FlexBuildConfigurationManager manager = FlexBuildConfigurationManager.getInstance(module); FlexUnitSupport support = null; FlexBuildConfiguration bc = null; if (module.getName().equals(params.getModuleName()) && !params.getBCName().isEmpty()) { bc = manager.findConfigurationByName(params.getBCName()); if (bc != null) { support = FlexUnitSupport.getSupport(bc, module); } } if (support == null) { bc = manager.getActiveConfiguration(); support = FlexUnitSupport.getSupport(bc, module); } if (support == null) { for (FlexBuildConfiguration anyBC : manager.getBuildConfigurations()) { bc = anyBC; support = FlexUnitSupport.getSupport(bc, module); if (support != null) { break; } } } if (support == null) { return false; } params.setModuleName(module.getName()); params.setBCName(bc.getName()); if (bc.getTargetPlatform() == TargetPlatform.Mobile) { if (bc.getAndroidPackagingOptions().isEnabled()) { params.setAppDescriptorForEmulator(FlashRunnerParameters.AppDescriptorForEmulator.Android); } else if (bc.getIosPackagingOptions().isEnabled()) { params.setAppDescriptorForEmulator(FlashRunnerParameters.AppDescriptorForEmulator.IOS); } } if (element instanceof JSClass) { final JSClass clazz = (JSClass)element; if (!support.isTestClass(clazz, true)) return false; forClass(clazz, params); } else if (element instanceof JSFunction) { final JSFunction method = (JSFunction)element; final String methodName = method.getName(); final JSClass clazz = (JSClass)element.getParent(); if (!support.isTestClass(clazz, true)) return false; if (methodName == null || !support.isTestMethod(method)) { forClass(clazz, params); } else { params.setClassName(clazz.getQualifiedName()); params.setMethodName(methodName); params.setScope(FlexUnitRunnerParameters.Scope.Method); } } else if (element instanceof PsiDirectory) { if (!forDirectory((PsiDirectory)element, module, params)) return false; } else if (element instanceof PsiDirectoryContainer) { if (!forPackage((PsiDirectoryContainer)element, module, params)) return false; } else { return false; } return true; } private static boolean forPackage(PsiDirectoryContainer psiPackage, Module module, FlexUnitRunnerParameters params) { if (module == null) return false; for (PsiDirectory directory : psiPackage.getDirectories(module.getModuleScope())) { if (forDirectory(directory, module, params)) { return true; } } return false; } private static boolean forDirectory(PsiDirectory directory, Module module, FlexUnitRunnerParameters params) { final VirtualFile file = directory.getVirtualFile(); ProjectFileIndex projectFileIndex = ProjectRootManager.getInstance(directory.getProject()).getFileIndex(); VirtualFile rootForFile = projectFileIndex.getSourceRootForFile(file); if (rootForFile == null) return false; String packageName = VfsUtilCore.getRelativePath(file, rootForFile, '.'); if (packageName == null || !JSUtils.packageExists(packageName, GlobalSearchScope.moduleScope(module))) return false; params.setPackageName(packageName); params.setScope(FlexUnitRunnerParameters.Scope.Package); return true; } private static void forClass(JSClass clazz, FlexUnitRunnerParameters params) { params.setClassName(clazz.getQualifiedName()); params.setScope(FlexUnitRunnerParameters.Scope.Class); } @Nullable private static PsiElement findTestElement(PsiElement element) { if (element.getLanguage().isKindOf(JavaScriptSupportLoader.JAVASCRIPT.getLanguage())) { final PsiNamedElement parent = PsiTreeUtil.getNonStrictParentOfType(element, JSFunction.class, JSClass.class, JSFile.class); if (parent instanceof JSClass) { return parent; } if (parent instanceof JSFunction && parent.getParent() instanceof JSClass) { return parent; } if (parent instanceof JSFile) { return JSPsiImplUtils.findClass((JSFile)parent); } } else if (element instanceof PsiDirectory) { return element; } else if (element instanceof PsiDirectoryContainer) { return element; } return null; } }