diff --git a/.idea/libraries/testng_plugin.xml b/.idea/libraries/testng_plugin.xml new file mode 100644 index 00000000000..cacf809be54 --- /dev/null +++ b/.idea/libraries/testng_plugin.xml @@ -0,0 +1,12 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/idea/idea.iml b/idea/idea.iml index 827ac8384c5..3bf10075ea9 100644 --- a/idea/idea.iml +++ b/idea/idea.iml @@ -26,6 +26,7 @@ + diff --git a/idea/src/META-INF/plugin.xml b/idea/src/META-INF/plugin.xml index ad170be5a14..984d6b8550a 100644 --- a/idea/src/META-INF/plugin.xml +++ b/idea/src/META-INF/plugin.xml @@ -9,6 +9,7 @@ JUnit + TestNG-J com.intellij.copyright @@ -210,6 +211,7 @@ + diff --git a/idea/src/org/jetbrains/jet/plugin/run/JetJUnitConfigurationProducer.java b/idea/src/org/jetbrains/jet/plugin/run/JetJUnitConfigurationProducer.java index f728cea2367..f0c5381c9c0 100644 --- a/idea/src/org/jetbrains/jet/plugin/run/JetJUnitConfigurationProducer.java +++ b/idea/src/org/jetbrains/jet/plugin/run/JetJUnitConfigurationProducer.java @@ -114,7 +114,7 @@ public class JetJUnitConfigurationProducer extends RuntimeConfigurationProducer } @Nullable - private static JetClass getClassDeclarationInFile(JetFile jetFile) { + static JetClass getClassDeclarationInFile(JetFile jetFile) { JetClass tempSingleDeclaration = null; for (JetDeclaration jetDeclaration : jetFile.getDeclarations()) { diff --git a/idea/src/org/jetbrains/jet/plugin/run/JetTestNgConfigurationProducer.java b/idea/src/org/jetbrains/jet/plugin/run/JetTestNgConfigurationProducer.java new file mode 100644 index 00000000000..2709a0dace0 --- /dev/null +++ b/idea/src/org/jetbrains/jet/plugin/run/JetTestNgConfigurationProducer.java @@ -0,0 +1,136 @@ +/* + * Copyright 2010-2013 JetBrains s.r.o. + * + * 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 org.jetbrains.jet.plugin.run; + +import com.intellij.execution.JavaRunConfigurationExtensionManager; +import com.intellij.execution.Location; +import com.intellij.execution.PsiLocation; +import com.intellij.execution.RunnerAndConfigurationSettings; +import com.intellij.execution.actions.ConfigurationContext; +import com.intellij.openapi.module.Module; +import com.intellij.openapi.project.Project; +import com.intellij.psi.PsiClass; +import com.intellij.psi.PsiElement; +import com.intellij.psi.PsiMethod; +import com.intellij.psi.util.PsiClassUtil; +import com.intellij.psi.util.PsiTreeUtil; +import com.theoryinpractice.testng.configuration.TestNGConfiguration; +import com.theoryinpractice.testng.configuration.TestNGConfigurationProducer; +import com.theoryinpractice.testng.util.TestNGUtil; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import org.jetbrains.jet.asJava.LightClassUtil; +import org.jetbrains.jet.lang.psi.*; + +public class JetTestNgConfigurationProducer extends TestNGConfigurationProducer { + + public JetTestNgConfigurationProducer() { + super(); + } + + private JetElement myElement = null; + + @Override + public PsiElement getSourceElement() { + return myElement; + } + + @Override + @Nullable + protected RunnerAndConfigurationSettings createConfigurationByElement(Location location, ConfigurationContext context) { + // TODO: check TestNG Pattern running first, before method/class (see TestNGInClassConfigurationProducer for logic) + // TODO: and PsiClassOwner not handled, which is in TestNGInClassConfigurationProducer + + Project project = location.getProject(); + PsiElement leaf = location.getPsiElement(); + + if (!(leaf.getContainingFile() instanceof JetFile)) { + return null; + } + + JetFile jetFile = (JetFile) leaf.getContainingFile(); + + JetNamedFunction function = PsiTreeUtil.getParentOfType(leaf, JetNamedFunction.class, false); + if (function != null) { + @SuppressWarnings("unchecked") + JetElement owner = PsiTreeUtil.getParentOfType(function, JetFunction.class, JetClass.class); + + if (owner instanceof JetClass) { + PsiClass delegate = LightClassUtil.getPsiClass((JetClass) owner); + if (delegate != null) { + for (PsiMethod method : delegate.getMethods()) { + if (method.getNavigationElement() == function) { + if (TestNGUtil.hasTest(method)) { + myElement = function; + return createRuntimeConfigSettings(location, context, project, delegate, method); + } + break; + } + } + } + } + } + + JetClass jetClass = PsiTreeUtil.getParentOfType(leaf, JetClass.class, false); + + if (jetClass == null) { + jetClass = JetJUnitConfigurationProducer.getClassDeclarationInFile(jetFile); + } + + if (jetClass == null) { + return null; + } + + PsiClass delegate = LightClassUtil.getPsiClass(jetClass); + if (!isTestNGClass(delegate)) { + return null; + } + + myElement = jetClass; + return createRuntimeConfigSettings(location, context, project, delegate, null); + } + + private RunnerAndConfigurationSettings createRuntimeConfigSettings( + Location location, ConfigurationContext context, Project project, + @Nullable PsiClass delegate, @Nullable PsiMethod method) { + if (delegate == null) { + return null; + } + + RunnerAndConfigurationSettings settings = cloneTemplateConfiguration(project, context); + TestNGConfiguration configuration = (TestNGConfiguration) settings.getConfiguration(); + setupConfigurationModule(context, configuration); + Module originalModule = configuration.getConfigurationModule().getModule(); + configuration.setClassConfiguration(delegate); + if (method != null) { + configuration.setMethodConfiguration(PsiLocation.fromPsiElement(project, method)); + } + configuration.restoreOriginalModule(originalModule); + settings.setName(configuration.getName()); + JavaRunConfigurationExtensionManager.getInstance().extendCreatedConfiguration(configuration, location); + return settings; + } + + private static boolean isTestNGClass(PsiClass psiClass) { + return psiClass != null && PsiClassUtil.isRunnableClass(psiClass, true, false) && TestNGUtil.hasTest(psiClass); + } + + @Override + public int compareTo(@NotNull Object o) { + return 0; + } +}