update copyright
[fedora-idea.git] / java / java-impl / src / com / intellij / testIntegration / createTest / CreateTestAction.java
blob3918fdbde1ea2326aad0eb64492f442c991d6037
1 /*
2 * Copyright 2000-2009 JetBrains s.r.o.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
16 package com.intellij.testIntegration.createTest;
18 import com.intellij.codeInsight.CodeInsightBundle;
19 import com.intellij.codeInsight.CodeInsightUtil;
20 import com.intellij.codeInsight.daemon.impl.analysis.HighlightNamesUtil;
21 import com.intellij.codeInsight.intention.PsiElementBaseIntentionAction;
22 import com.intellij.openapi.application.ApplicationManager;
23 import com.intellij.openapi.editor.Editor;
24 import com.intellij.openapi.extensions.Extensions;
25 import com.intellij.openapi.fileEditor.ex.IdeDocumentHistory;
26 import com.intellij.openapi.module.Module;
27 import com.intellij.openapi.module.ModuleUtil;
28 import com.intellij.openapi.project.Project;
29 import com.intellij.openapi.roots.ProjectRootManager;
30 import com.intellij.openapi.ui.Messages;
31 import com.intellij.openapi.util.TextRange;
32 import com.intellij.openapi.vfs.VirtualFile;
33 import com.intellij.psi.*;
34 import com.intellij.psi.impl.source.PostprocessReformattingAspect;
35 import com.intellij.psi.search.GlobalSearchScope;
36 import com.intellij.psi.util.PsiTreeUtil;
37 import com.intellij.refactoring.util.classMembers.MemberInfo;
38 import com.intellij.testIntegration.TestFrameworkDescriptor;
39 import com.intellij.testIntegration.TestIntegrationUtils;
40 import com.intellij.util.IncorrectOperationException;
41 import org.jetbrains.annotations.NotNull;
42 import org.jetbrains.annotations.Nullable;
44 import java.util.Collection;
46 public class CreateTestAction extends PsiElementBaseIntentionAction {
47 @NotNull
48 public String getText() {
49 return CodeInsightBundle.message("intention.create.test");
52 @NotNull
53 public String getFamilyName() {
54 return getText();
57 public boolean isAvailable(@NotNull Project project, Editor editor, @Nullable PsiElement element) {
58 if (element == null) return false;
59 if (Extensions.getExtensions(TestFrameworkDescriptor.EXTENSION_NAME).length == 0) return false;
61 if (!isAvailableForElement(element)) return false;
63 PsiClass psiClass = getContainingClass(element);
65 PsiJavaToken leftBrace = psiClass.getLBrace();
66 if (leftBrace == null) return false;
67 if (element.getTextOffset() >= leftBrace.getTextOffset()) return false;
69 TextRange declarationRange = HighlightNamesUtil.getClassDeclarationTextRange(psiClass);
70 if (!declarationRange.contains(element.getTextRange())) return false;
72 return true;
75 public boolean isAvailableForElement(PsiElement element) {
76 if (element == null) return false;
78 PsiClass psiClass = getContainingClass(element);
80 if (psiClass == null) return false;
82 Module srcModule = ModuleUtil.findModuleForPsiElement(psiClass);
83 if (srcModule == null) return false;
85 if (psiClass.isAnnotationType() ||
86 psiClass.isInterface() ||
87 psiClass.isEnum() ||
88 psiClass instanceof PsiAnonymousClass ||
89 PsiTreeUtil.getParentOfType(psiClass, PsiClass.class) != null || // inner
90 isUnderTestSources(psiClass)) {
91 return false;
93 return true;
96 private boolean isUnderTestSources(PsiClass c) {
97 ProjectRootManager rm = ProjectRootManager.getInstance(c.getProject());
98 VirtualFile f = c.getContainingFile().getVirtualFile();
99 if (f == null) return false;
100 return rm.getFileIndex().isInTestSourceContent(f);
103 public void invoke(@NotNull final Project project, final Editor editor, PsiFile file) throws IncorrectOperationException {
104 PsiElement element = file.findElementAt(editor.getCaretModel().getOffset());
106 final Module srcModule = ModuleUtil.findModuleForPsiElement(file);
107 final PsiClass srcClass = getContainingClass(element);
109 if (srcClass == null) return;
111 PsiDirectory srcDir = file.getContainingDirectory();
112 PsiPackage srcPackage = JavaDirectoryService.getInstance().getPackage(srcDir);
114 final CreateTestDialog d = new CreateTestDialog(project,
115 getText(),
116 srcClass,
117 srcPackage,
118 srcModule);
119 d.show();
120 if (!d.isOK()) return;
122 PostprocessReformattingAspect.getInstance(project).postponeFormattingInside(new Runnable() {
123 public void run() {
124 ApplicationManager.getApplication().runWriteAction(new Runnable() {
125 public void run() {
126 try {
127 IdeDocumentHistory.getInstance(project).includeCurrentPlaceAsChangePlace();
129 PsiClass targetClass = JavaDirectoryService.getInstance().createClass(d.getTargetDirectory(), d.getClassName());
130 addSuperClass(targetClass, project, d.getSuperClassName());
131 Editor editor = CodeInsightUtil.positionCursor(project, targetClass.getContainingFile(), targetClass.getLBrace());
133 addTestMethods(editor,
134 targetClass,
135 d.getSelectedTestFrameworkDescriptor(),
136 d.getSelectedMethods(),
137 d.shouldGeneratedBefore(),
138 d.shouldGeneratedAfter());
140 catch (IncorrectOperationException e) {
141 showErrorLater(project, d.getClassName());
149 private void showErrorLater(final Project project, final String targetClassName) {
150 ApplicationManager.getApplication().invokeLater(new Runnable() {
151 public void run() {
152 Messages.showErrorDialog(project,
153 CodeInsightBundle.message("intention.error.cannot.create.class.message", targetClassName),
154 CodeInsightBundle.message("intention.error.cannot.create.class.title"));
159 private void addSuperClass(PsiClass targetClass, Project project, String superClassName) throws IncorrectOperationException {
160 if (superClassName == null) return;
162 PsiElementFactory ef = JavaPsiFacade.getInstance(project).getElementFactory();
163 PsiJavaCodeReferenceElement superClassRef;
165 PsiClass superClass = findClass(project, superClassName);
166 if (superClass != null) {
167 superClassRef = ef.createClassReferenceElement(superClass);
169 else {
170 superClassRef = ef.createFQClassNameReferenceElement(superClassName, GlobalSearchScope.allScope(project));
172 targetClass.getExtendsList().add(superClassRef);
175 private PsiClass findClass(Project project, String fqName) {
176 GlobalSearchScope scope = GlobalSearchScope.allScope(project);
177 return JavaPsiFacade.getInstance(project).findClass(fqName, scope);
180 private void addTestMethods(Editor editor,
181 PsiClass targetClass,
182 TestFrameworkDescriptor descriptor,
183 Collection<MemberInfo> methods,
184 boolean generateBefore,
185 boolean generateAfter) throws IncorrectOperationException {
186 if (generateBefore) {
187 generateMethod(TestIntegrationUtils.MethodKind.SET_UP, descriptor, targetClass, editor, "setUp");
189 if (generateAfter) {
190 generateMethod(TestIntegrationUtils.MethodKind.TEAR_DOWN, descriptor, targetClass, editor, "tearUp");
192 for (MemberInfo m : methods) {
193 generateMethod(TestIntegrationUtils.MethodKind.TEST, descriptor, targetClass, editor, m.getMember().getName());
197 private void generateMethod(TestIntegrationUtils.MethodKind methodKind, TestFrameworkDescriptor descriptor, PsiClass targetClass, Editor editor, String name) {
198 PsiMethod method = (PsiMethod)targetClass.add(TestIntegrationUtils.createDummyMethod(targetClass.getProject()));
199 PsiDocumentManager.getInstance(targetClass.getProject()).doPostponedOperationsAndUnblockDocument(editor.getDocument());
200 TestIntegrationUtils.runTestMethodTemplate(methodKind, descriptor, editor, targetClass, method, name, true);
203 private PsiClass getContainingClass(PsiElement element) {
204 return PsiTreeUtil.getParentOfType(element, PsiClass.class, false);
207 public boolean startInWriteAction() {
208 return false;