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;
+ }
+}