1 package com
.intellij
.testIntegration
.createTest
;
3 import com
.intellij
.codeInsight
.CodeInsightBundle
;
4 import com
.intellij
.codeInsight
.CodeInsightUtil
;
5 import com
.intellij
.codeInsight
.daemon
.impl
.analysis
.HighlightNamesUtil
;
6 import com
.intellij
.codeInsight
.intention
.PsiElementBaseIntentionAction
;
7 import com
.intellij
.openapi
.application
.ApplicationManager
;
8 import com
.intellij
.openapi
.editor
.Editor
;
9 import com
.intellij
.openapi
.extensions
.Extensions
;
10 import com
.intellij
.openapi
.fileEditor
.ex
.IdeDocumentHistory
;
11 import com
.intellij
.openapi
.module
.Module
;
12 import com
.intellij
.openapi
.module
.ModuleUtil
;
13 import com
.intellij
.openapi
.project
.Project
;
14 import com
.intellij
.openapi
.roots
.ProjectRootManager
;
15 import com
.intellij
.openapi
.ui
.Messages
;
16 import com
.intellij
.openapi
.util
.TextRange
;
17 import com
.intellij
.openapi
.vfs
.VirtualFile
;
18 import com
.intellij
.psi
.*;
19 import com
.intellij
.psi
.impl
.source
.PostprocessReformattingAspect
;
20 import com
.intellij
.psi
.search
.GlobalSearchScope
;
21 import com
.intellij
.psi
.util
.PsiTreeUtil
;
22 import com
.intellij
.refactoring
.util
.classMembers
.MemberInfo
;
23 import com
.intellij
.testIntegration
.TestFrameworkDescriptor
;
24 import com
.intellij
.testIntegration
.TestIntegrationUtils
;
25 import com
.intellij
.util
.IncorrectOperationException
;
26 import org
.jetbrains
.annotations
.NotNull
;
27 import org
.jetbrains
.annotations
.Nullable
;
29 import java
.util
.Collection
;
31 public class CreateTestAction
extends PsiElementBaseIntentionAction
{
33 public String
getText() {
34 return CodeInsightBundle
.message("intention.create.test");
38 public String
getFamilyName() {
42 public boolean isAvailable(@NotNull Project project
, Editor editor
, @Nullable PsiElement element
) {
43 if (element
== null) return false;
44 if (Extensions
.getExtensions(TestFrameworkDescriptor
.EXTENSION_NAME
).length
== 0) return false;
46 if (!isAvailableForElement(element
)) return false;
48 PsiClass psiClass
= getContainingClass(element
);
50 PsiJavaToken leftBrace
= psiClass
.getLBrace();
51 if (leftBrace
== null) return false;
52 if (element
.getTextOffset() >= leftBrace
.getTextOffset()) return false;
54 TextRange declarationRange
= HighlightNamesUtil
.getClassDeclarationTextRange(psiClass
);
55 if (!declarationRange
.contains(element
.getTextRange())) return false;
60 public boolean isAvailableForElement(PsiElement element
) {
61 if (element
== null) return false;
63 PsiClass psiClass
= getContainingClass(element
);
65 if (psiClass
== null) return false;
67 Module srcModule
= ModuleUtil
.findModuleForPsiElement(psiClass
);
68 if (srcModule
== null) return false;
70 if (psiClass
.isAnnotationType() ||
71 psiClass
.isInterface() ||
73 psiClass
instanceof PsiAnonymousClass
||
74 PsiTreeUtil
.getParentOfType(psiClass
, PsiClass
.class) != null || // inner
75 isUnderTestSources(psiClass
)) {
81 private boolean isUnderTestSources(PsiClass c
) {
82 ProjectRootManager rm
= ProjectRootManager
.getInstance(c
.getProject());
83 VirtualFile f
= c
.getContainingFile().getVirtualFile();
84 if (f
== null) return false;
85 return rm
.getFileIndex().isInTestSourceContent(f
);
88 public void invoke(@NotNull final Project project
, final Editor editor
, PsiFile file
) throws IncorrectOperationException
{
89 PsiElement element
= file
.findElementAt(editor
.getCaretModel().getOffset());
91 final Module srcModule
= ModuleUtil
.findModuleForPsiElement(file
);
92 final PsiClass srcClass
= getContainingClass(element
);
94 if (srcClass
== null) return;
96 PsiDirectory srcDir
= file
.getContainingDirectory();
97 PsiPackage srcPackage
= JavaDirectoryService
.getInstance().getPackage(srcDir
);
99 final CreateTestDialog d
= new CreateTestDialog(project
,
105 if (!d
.isOK()) return;
107 PostprocessReformattingAspect
.getInstance(project
).postponeFormattingInside(new Runnable() {
109 ApplicationManager
.getApplication().runWriteAction(new Runnable() {
112 IdeDocumentHistory
.getInstance(project
).includeCurrentPlaceAsChangePlace();
114 PsiClass targetClass
= JavaDirectoryService
.getInstance().createClass(d
.getTargetDirectory(), d
.getClassName());
115 addSuperClass(targetClass
, project
, d
.getSuperClassName());
116 Editor editor
= CodeInsightUtil
.positionCursor(project
, targetClass
.getContainingFile(), targetClass
.getLBrace());
118 addTestMethods(editor
,
120 d
.getSelectedTestFrameworkDescriptor(),
121 d
.getSelectedMethods(),
122 d
.shouldGeneratedBefore(),
123 d
.shouldGeneratedAfter());
125 catch (IncorrectOperationException e
) {
126 showErrorLater(project
, d
.getClassName());
134 private void showErrorLater(final Project project
, final String targetClassName
) {
135 ApplicationManager
.getApplication().invokeLater(new Runnable() {
137 Messages
.showErrorDialog(project
,
138 CodeInsightBundle
.message("intention.error.cannot.create.class.message", targetClassName
),
139 CodeInsightBundle
.message("intention.error.cannot.create.class.title"));
144 private void addSuperClass(PsiClass targetClass
, Project project
, String superClassName
) throws IncorrectOperationException
{
145 if (superClassName
== null) return;
147 PsiElementFactory ef
= JavaPsiFacade
.getInstance(project
).getElementFactory();
148 PsiJavaCodeReferenceElement superClassRef
;
150 PsiClass superClass
= findClass(project
, superClassName
);
151 if (superClass
!= null) {
152 superClassRef
= ef
.createClassReferenceElement(superClass
);
155 superClassRef
= ef
.createFQClassNameReferenceElement(superClassName
, GlobalSearchScope
.allScope(project
));
157 targetClass
.getExtendsList().add(superClassRef
);
160 private PsiClass
findClass(Project project
, String fqName
) {
161 GlobalSearchScope scope
= GlobalSearchScope
.allScope(project
);
162 return JavaPsiFacade
.getInstance(project
).findClass(fqName
, scope
);
165 private void addTestMethods(Editor editor
,
166 PsiClass targetClass
,
167 TestFrameworkDescriptor descriptor
,
168 Collection
<MemberInfo
> methods
,
169 boolean generateBefore
,
170 boolean generateAfter
) throws IncorrectOperationException
{
171 if (generateBefore
) {
172 generateMethod(TestIntegrationUtils
.MethodKind
.SET_UP
, descriptor
, targetClass
, editor
, "setUp");
175 generateMethod(TestIntegrationUtils
.MethodKind
.TEAR_DOWN
, descriptor
, targetClass
, editor
, "tearUp");
177 for (MemberInfo m
: methods
) {
178 generateMethod(TestIntegrationUtils
.MethodKind
.TEST
, descriptor
, targetClass
, editor
, m
.getMember().getName());
182 private void generateMethod(TestIntegrationUtils
.MethodKind methodKind
, TestFrameworkDescriptor descriptor
, PsiClass targetClass
, Editor editor
, String name
) {
183 PsiMethod method
= (PsiMethod
)targetClass
.add(TestIntegrationUtils
.createDummyMethod(targetClass
.getProject()));
184 PsiDocumentManager
.getInstance(targetClass
.getProject()).doPostponedOperationsAndUnblockDocument(editor
.getDocument());
185 TestIntegrationUtils
.runTestMethodTemplate(methodKind
, descriptor
, editor
, targetClass
, method
, name
, true);
188 private PsiClass
getContainingClass(PsiElement element
) {
189 return PsiTreeUtil
.getParentOfType(element
, PsiClass
.class, false);
192 public boolean startInWriteAction() {