2 * Copyright (c) 2000-2006 JetBrains s.r.o. All Rights Reserved.
5 package com
.intellij
.testFramework
.fixtures
.impl
;
7 import com
.intellij
.codeHighlighting
.HighlightDisplayLevel
;
8 import com
.intellij
.codeInsight
.CodeInsightActionHandler
;
9 import com
.intellij
.codeInsight
.TargetElementUtilBase
;
10 import com
.intellij
.codeInsight
.completion
.CodeCompletionHandlerBase
;
11 import com
.intellij
.codeInsight
.completion
.CompletionContext
;
12 import com
.intellij
.codeInsight
.completion
.CompletionProgressIndicator
;
13 import com
.intellij
.codeInsight
.completion
.CompletionType
;
14 import com
.intellij
.codeInsight
.daemon
.HighlightDisplayKey
;
15 import com
.intellij
.codeInsight
.daemon
.impl
.*;
16 import com
.intellij
.codeInsight
.intention
.IntentionAction
;
17 import com
.intellij
.codeInsight
.intention
.IntentionManager
;
18 import com
.intellij
.codeInsight
.lookup
.LookupElement
;
19 import com
.intellij
.codeInsight
.lookup
.LookupManager
;
20 import com
.intellij
.codeInsight
.lookup
.impl
.LookupImpl
;
21 import com
.intellij
.codeInspection
.InspectionProfileEntry
;
22 import com
.intellij
.codeInspection
.InspectionToolProvider
;
23 import com
.intellij
.codeInspection
.LocalInspectionTool
;
24 import com
.intellij
.codeInspection
.ModifiableModel
;
25 import com
.intellij
.codeInspection
.ex
.InspectionProfileImpl
;
26 import com
.intellij
.codeInspection
.ex
.InspectionTool
;
27 import com
.intellij
.codeInspection
.ex
.LocalInspectionToolWrapper
;
28 import com
.intellij
.facet
.Facet
;
29 import com
.intellij
.facet
.FacetManager
;
30 import com
.intellij
.find
.findUsages
.FindUsagesHandler
;
31 import com
.intellij
.find
.findUsages
.FindUsagesManager
;
32 import com
.intellij
.find
.findUsages
.FindUsagesOptions
;
33 import com
.intellij
.ide
.DataManager
;
34 import com
.intellij
.mock
.MockProgressIndicator
;
35 import com
.intellij
.openapi
.Disposable
;
36 import com
.intellij
.openapi
.actionSystem
.DataContext
;
37 import com
.intellij
.openapi
.actionSystem
.IdeActions
;
38 import com
.intellij
.openapi
.application
.ApplicationManager
;
39 import com
.intellij
.openapi
.application
.ModalityState
;
40 import com
.intellij
.openapi
.application
.Result
;
41 import com
.intellij
.openapi
.command
.WriteCommandAction
;
42 import com
.intellij
.openapi
.editor
.*;
43 import com
.intellij
.openapi
.editor
.actionSystem
.EditorActionManager
;
44 import com
.intellij
.openapi
.editor
.ex
.DocumentEx
;
45 import com
.intellij
.openapi
.editor
.ex
.util
.EditorUtil
;
46 import com
.intellij
.openapi
.editor
.markup
.GutterIconRenderer
;
47 import com
.intellij
.openapi
.extensions
.ExtensionPoint
;
48 import com
.intellij
.openapi
.extensions
.ExtensionPointName
;
49 import com
.intellij
.openapi
.extensions
.ExtensionsArea
;
50 import com
.intellij
.openapi
.fileEditor
.FileEditorManager
;
51 import com
.intellij
.openapi
.fileEditor
.OpenFileDescriptor
;
52 import com
.intellij
.openapi
.fileTypes
.FileType
;
53 import com
.intellij
.openapi
.fileTypes
.FileTypeManager
;
54 import com
.intellij
.openapi
.fileTypes
.StdFileTypes
;
55 import com
.intellij
.openapi
.module
.Module
;
56 import com
.intellij
.openapi
.project
.Project
;
57 import com
.intellij
.openapi
.util
.*;
58 import com
.intellij
.openapi
.util
.io
.FileUtil
;
59 import com
.intellij
.openapi
.util
.text
.StringUtil
;
60 import com
.intellij
.openapi
.vfs
.LocalFileSystem
;
61 import com
.intellij
.openapi
.vfs
.VfsUtil
;
62 import com
.intellij
.openapi
.vfs
.VirtualFile
;
63 import com
.intellij
.openapi
.vfs
.VirtualFileFilter
;
64 import com
.intellij
.profile
.codeInspection
.InspectionProfileManager
;
65 import com
.intellij
.profile
.codeInspection
.InspectionProjectProfileManager
;
66 import com
.intellij
.psi
.*;
67 import com
.intellij
.psi
.impl
.JavaPsiFacadeEx
;
68 import com
.intellij
.psi
.impl
.PsiManagerImpl
;
69 import com
.intellij
.psi
.impl
.source
.PostprocessReformattingAspect
;
70 import com
.intellij
.psi
.impl
.source
.PsiFileImpl
;
71 import com
.intellij
.psi
.impl
.source
.resolve
.FileContextUtil
;
72 import com
.intellij
.psi
.impl
.source
.tree
.injected
.InjectedLanguageUtil
;
73 import com
.intellij
.psi
.search
.GlobalSearchScope
;
74 import com
.intellij
.psi
.search
.UsageSearchContext
;
75 import com
.intellij
.psi
.util
.PsiUtilBase
;
76 import com
.intellij
.refactoring
.move
.moveFilesOrDirectories
.MoveFilesOrDirectoriesProcessor
;
77 import com
.intellij
.refactoring
.rename
.RenameProcessor
;
78 import com
.intellij
.refactoring
.rename
.RenamePsiElementProcessor
;
79 import com
.intellij
.testFramework
.ExpectedHighlightingData
;
80 import com
.intellij
.testFramework
.UsefulTestCase
;
81 import com
.intellij
.testFramework
.fixtures
.*;
82 import com
.intellij
.usageView
.UsageInfo
;
83 import com
.intellij
.util
.ArrayUtil
;
84 import com
.intellij
.util
.CommonProcessors
;
85 import com
.intellij
.util
.Function
;
86 import com
.intellij
.util
.SmartList
;
87 import com
.intellij
.util
.containers
.ContainerUtil
;
88 import gnu
.trove
.THashMap
;
89 import gnu
.trove
.THashSet
;
90 import junit
.framework
.Assert
;
91 import org
.jetbrains
.annotations
.NonNls
;
92 import org
.jetbrains
.annotations
.NotNull
;
93 import org
.jetbrains
.annotations
.Nullable
;
97 import java
.io
.IOException
;
98 import java
.io
.OutputStream
;
102 * @author Dmitry Avdeev
104 public class CodeInsightTestFixtureImpl
extends BaseFixture
implements CodeInsightTestFixture
{
106 @NonNls private static final String PROFILE
= "Configurable";
108 private PsiManagerImpl myPsiManager
;
109 private PsiFile myFile
;
110 private Editor myEditor
;
111 private String myTestDataPath
;
112 private boolean myEmptyLookup
;
114 private LocalInspectionTool
[] myInspections
;
115 private final Map
<String
, LocalInspectionTool
> myAvailableTools
= new THashMap
<String
, LocalInspectionTool
>();
116 private final Map
<String
, LocalInspectionToolWrapper
> myAvailableLocalTools
= new THashMap
<String
, LocalInspectionToolWrapper
>();
118 private final TempDirTestFixture myTempDirFixture
= new TempDirTestFixtureImpl();
119 private final IdeaProjectTestFixture myProjectFixture
;
120 private final Set
<VirtualFile
> myAddedClasses
= new THashSet
<VirtualFile
>();
121 @NonNls private static final String XXX
= "XXX";
122 private PsiElement myFileContext
;
124 public CodeInsightTestFixtureImpl(IdeaProjectTestFixture projectFixture
) {
125 myProjectFixture
= projectFixture
;
128 public void setTestDataPath(String dataPath
) {
129 myTestDataPath
= dataPath
;
132 public String
getTempDirPath() {
133 return myTempDirFixture
.getTempDirPath();
136 public TempDirTestFixture
getTempDirFixture() {
137 return myTempDirFixture
;
140 public VirtualFile
copyFileToProject(@NonNls final String sourceFilePath
, @NonNls final String targetPath
) throws IOException
{
141 final File destFile
= new File(getTempDirPath() + "/" + targetPath
);
142 if (!destFile
.exists()) {
143 File fromFile
= new File(getTestDataPath() + "/" + sourceFilePath
);
144 if (!fromFile
.exists()) {
145 fromFile
= new File(sourceFilePath
);
148 if (fromFile
.isDirectory()) {
151 FileUtil
.copy(fromFile
, destFile
);
154 final VirtualFile file
= LocalFileSystem
.getInstance().refreshAndFindFileByIoFile(destFile
);
155 Assert
.assertNotNull(file
);
159 public VirtualFile
copyDirectoryToProject(@NonNls final String sourceFilePath
, @NonNls final String targetPath
) throws IOException
{
160 final File destFile
= new File(getTempDirPath() + "/" + targetPath
);
161 final File fromFile
= new File(getTestDataPath() + "/" + sourceFilePath
);
162 FileUtil
.copyDir(fromFile
, destFile
);
163 final VirtualFile file
= LocalFileSystem
.getInstance().refreshAndFindFileByIoFile(destFile
);
164 Assert
.assertNotNull(file
);
165 file
.refresh(false, true);
169 public VirtualFile
copyFileToProject(@NonNls final String sourceFilePath
) throws IOException
{
170 return copyFileToProject(sourceFilePath
, sourceFilePath
);
173 public void enableInspections(LocalInspectionTool
... inspections
) {
174 myInspections
= inspections
;
175 if (isInitialized()) {
176 configureInspections(myInspections
);
180 private boolean isInitialized() {
181 return myPsiManager
!= null;
184 public void enableInspections(final Class
<?
extends LocalInspectionTool
>... inspections
) {
185 final ArrayList
<LocalInspectionTool
> tools
= new ArrayList
<LocalInspectionTool
>();
186 for (Class clazz
: inspections
) {
188 LocalInspectionTool inspection
= (LocalInspectionTool
)clazz
.getConstructor().newInstance();
189 tools
.add(inspection
);
191 catch (Exception e
) {
192 throw new RuntimeException("Cannot instantiate " + clazz
);
195 enableInspections(tools
.toArray(new LocalInspectionTool
[tools
.size()]));
198 public void disableInspections(LocalInspectionTool
... inspections
) {
199 myAvailableTools
.clear();
200 myAvailableLocalTools
.clear();
201 final ArrayList
<LocalInspectionTool
> tools
= new ArrayList
<LocalInspectionTool
>(Arrays
.asList(myInspections
));
202 for (Iterator
<LocalInspectionTool
> i
= tools
.iterator(); i
.hasNext();) {
203 final LocalInspectionTool tool
= i
.next();
204 for (LocalInspectionTool toRemove
: inspections
) {
205 if (tool
.getShortName().equals(toRemove
.getShortName())) {
211 myInspections
= tools
.toArray(new LocalInspectionTool
[tools
.size()]);
212 configureInspections(myInspections
);
215 public void enableInspections(InspectionToolProvider
... providers
) {
216 final ArrayList
<LocalInspectionTool
> tools
= new ArrayList
<LocalInspectionTool
>();
217 for (InspectionToolProvider provider
: providers
) {
218 for (Class clazz
: provider
.getInspectionClasses()) {
220 LocalInspectionTool inspection
= (LocalInspectionTool
)clazz
.getConstructor().newInstance();
221 tools
.add(inspection
);
223 catch (Exception e
) {
224 throw new RuntimeException("Cannot instantiate " + clazz
);
228 myInspections
= tools
.toArray(new LocalInspectionTool
[tools
.size()]);
229 configureInspections(myInspections
);
232 public long testHighlighting(final boolean checkWarnings
,
233 final boolean checkInfos
,
234 final boolean checkWeakWarnings
,
235 final String
... filePaths
) throws Throwable
{
237 final Ref
<Long
> duration
= new Ref
<Long
>();
238 new WriteCommandAction
.Simple(myProjectFixture
.getProject()) {
240 protected void run() throws Throwable
{
241 configureByFilesInner(filePaths
);
242 collectAndCheckHighlightings(checkWarnings
, checkInfos
, checkWeakWarnings
, duration
);
244 }.execute().throwException();
245 return duration
.get().longValue();
248 public long checkHighlighting(final boolean checkWarnings
, final boolean checkInfos
, final boolean checkWeakWarnings
) throws Throwable
{
249 final Ref
<Long
> duration
= new Ref
<Long
>();
250 new WriteCommandAction
.Simple(myProjectFixture
.getProject()) {
251 protected void run() throws Throwable
{
252 collectAndCheckHighlightings(checkWarnings
, checkInfos
, checkWeakWarnings
, duration
);
254 }.execute().throwException();
255 return duration
.get().longValue();
258 public long checkHighlighting() throws Throwable
{
259 return checkHighlighting(true, true, true);
262 public long testHighlighting(final String
... filePaths
) throws Throwable
{
263 return testHighlighting(true, true, true, filePaths
);
266 public long testHighlighting(final boolean checkWarnings
, final boolean checkInfos
, final boolean checkWeakWarnings
, final VirtualFile file
) throws Throwable
{
267 final Ref
<Long
> duration
= new Ref
<Long
>();
268 new WriteCommandAction
.Simple(myProjectFixture
.getProject()) {
269 protected void run() throws Throwable
{
270 myFile
= myPsiManager
.findFile(file
);
271 myEditor
= createEditor(file
);
272 collectAndCheckHighlightings(checkWarnings
, checkInfos
, checkWeakWarnings
, duration
);
274 }.execute().throwException();
275 return duration
.get().longValue();
279 public PsiReference
getReferenceAtCaretPosition(final String
... filePaths
) throws Throwable
{
280 new WriteCommandAction
<PsiReference
>(myProjectFixture
.getProject()) {
281 protected void run(final Result
<PsiReference
> result
) throws Throwable
{
282 configureByFilesInner(filePaths
);
284 }.execute().throwException();
285 return getFile().findReferenceAt(myEditor
.getCaretModel().getOffset());
289 public PsiReference
getReferenceAtCaretPositionWithAssertion(final String
... filePaths
) throws Throwable
{
290 final PsiReference reference
= getReferenceAtCaretPosition(filePaths
);
291 assert reference
!= null: "no reference found at " + myEditor
.getCaretModel().getLogicalPosition();
296 public List
<IntentionAction
> getAvailableIntentions(final String
... filePaths
) throws Throwable
{
298 final Project project
= myProjectFixture
.getProject();
299 return new WriteCommandAction
<List
<IntentionAction
>>(project
) {
300 protected void run(final Result
<List
<IntentionAction
>> result
) throws Throwable
{
301 configureByFilesInner(filePaths
);
302 result
.setResult(CodeInsightTestFixtureImpl
.this.getAvailableIntentions());
304 }.execute().getResultObject();
308 public List
<IntentionAction
> getAvailableIntentions() {
309 int offset
= myEditor
.getCaretModel().getOffset();
310 return getAvailableIntentions(myProjectFixture
.getProject(), doHighlighting(), offset
, myEditor
, myFile
);
313 public List
<IntentionAction
> filterAvailableIntentions(@NotNull final String hint
) throws Throwable
{
314 return ContainerUtil
.findAll(getAvailableIntentions(),new Condition
<IntentionAction
>() {
315 public boolean value(final IntentionAction intentionAction
) {
316 return intentionAction
.getText().contains(hint
);
321 public IntentionAction
getAvailableIntention(final String intentionName
, final String
... filePaths
) throws Throwable
{
322 List
<IntentionAction
> intentions
= getAvailableIntentions(filePaths
);
323 return CodeInsightTestUtil
.findIntentionByText(intentions
, intentionName
);
326 public void launchAction(@NotNull final IntentionAction action
) throws Throwable
{
327 new WriteCommandAction(myProjectFixture
.getProject()) {
328 protected void run(final Result result
) throws Throwable
{
329 action
.invoke(getProject(), getEditor(), getFile());
331 }.execute().throwException();
335 public void testCompletion(final String
[] filesBefore
, final String fileAfter
) throws Throwable
{
337 configureByFiles(filesBefore
);
338 final LookupElement
[] items
= complete(CompletionType
.BASIC
);
340 System
.out
.println("items = " + Arrays
.toString(items
));
342 checkResultByFile(fileAfter
);
345 private void assertInitialized() {
346 Assert
.assertNotNull("setUp() hasn't been called", myPsiManager
);
349 public void testCompletion(String fileBefore
, String fileAfter
, final String
... additionalFiles
) throws Throwable
{
350 testCompletion(ArrayUtil
.reverseArray(ArrayUtil
.append(additionalFiles
, fileBefore
)), fileAfter
);
353 public void testCompletionVariants(final String fileBefore
, final String
... expectedItems
) throws Throwable
{
355 final List
<String
> result
= getCompletionVariants(fileBefore
);
356 UsefulTestCase
.assertSameElements(result
, expectedItems
);
359 public List
<String
> getCompletionVariants(final String fileBefore
) throws Throwable
{
361 configureByFiles(fileBefore
);
362 final LookupElement
[] items
= complete(CompletionType
.BASIC
);
363 Assert
.assertNotNull("No lookup was shown, probably there was only one lookup element that was inserted automatically", items
);
364 return getLookupElementStrings();
368 public List
<String
> getLookupElementStrings() {
370 final LookupElement
[] elements
= getLookupElements();
371 if (elements
== null) return null;
373 return ContainerUtil
.map(elements
, new Function
<LookupElement
, String
>() {
374 public String
fun(final LookupElement lookupItem
) {
375 return lookupItem
.getLookupString();
380 public void testRename(final String fileBefore
, final String fileAfter
, final String newName
, final String
... additionalFiles
) throws Throwable
{
382 configureByFiles(ArrayUtil
.reverseArray(ArrayUtil
.append(additionalFiles
, fileBefore
)));
383 testRename(fileAfter
, newName
);
386 public void testRename(final String fileAfter
, final String newName
) throws Throwable
{
388 new WriteCommandAction
.Simple(myProjectFixture
.getProject()) {
389 protected void run() throws Throwable
{
390 PsiElement element
= TargetElementUtilBase
.findTargetElement(getCompletionEditor(), TargetElementUtilBase
.REFERENCED_ELEMENT_ACCEPTED
| TargetElementUtilBase
.ELEMENT_NAME_ACCEPTED
);
391 assert element
!= null: "element not found in file " + myFile
.getName() + " at caret position, offset " + myEditor
.getCaretModel().getOffset();
392 final PsiElement substitution
= RenamePsiElementProcessor
.forElement(element
).substituteElementToRename(element
, myEditor
);
393 new RenameProcessor(myProjectFixture
.getProject(), substitution
, newName
, false, false).run();
394 checkResultByFile(fileAfter
, myFile
, false);
396 }.execute().throwException();
399 public void type(final char c
) {
401 new WriteCommandAction(getProject()) {
402 protected void run(Result result
) throws Throwable
{
403 EditorActionManager actionManager
= EditorActionManager
.getInstance();
404 final DataContext dataContext
= DataManager
.getInstance().getDataContext();
406 performEditorAction(IdeActions
.ACTION_EDITOR_BACKSPACE
);
410 performEditorAction(IdeActions
.ACTION_EDITOR_ENTER
);
414 if (LookupManager
.getInstance(getProject()).getActiveLookup() != null) {
415 actionManager
.getActionHandler(IdeActions
.ACTION_CHOOSE_LOOKUP_ITEM_REPLACE
).execute(getEditor(), dataContext
);
420 actionManager
.getTypedAction().actionPerformed(getEditor(), c
, dataContext
);
425 public void performEditorAction(final String actionId
) {
427 final DataContext dataContext
= DataManager
.getInstance().getDataContext();
428 EditorActionManager actionManager
= EditorActionManager
.getInstance();
429 actionManager
.getActionHandler(actionId
).execute(getEditor(), dataContext
);
432 public JavaPsiFacade
getJavaFacade() {
434 return JavaPsiFacade
.getInstance(getProject());
437 public Collection
<UsageInfo
> testFindUsages(@NonNls final String
... fileNames
) throws Throwable
{
439 configureByFiles(fileNames
);
440 PsiElement referenceTo
= TargetElementUtilBase
441 .findTargetElement(getEditor(), TargetElementUtilBase
.ELEMENT_NAME_ACCEPTED
| TargetElementUtilBase
.REFERENCED_ELEMENT_ACCEPTED
);
443 assert referenceTo
!= null : "Cannot find referenced element";
444 final Project project
= getProject();
445 final FindUsagesHandler handler
= new FindUsagesManager(project
, null).getFindUsagesHandler(referenceTo
, false);
447 final CommonProcessors
.CollectProcessor
<UsageInfo
> processor
= new CommonProcessors
.CollectProcessor
<UsageInfo
>();
448 final FindUsagesOptions options
= new FindUsagesOptions(project
);
449 options
.isUsages
= true;
450 assert handler
!= null : "Cannot find handler for: " + referenceTo
;
451 final PsiElement
[] psiElements
= ArrayUtil
.mergeArrays(handler
.getPrimaryElements(), handler
.getSecondaryElements(), PsiElement
.class);
452 for (PsiElement psiElement
: psiElements
) {
453 handler
.processElementUsages(psiElement
, processor
, options
);
455 return processor
.getResults();
458 public void moveFile(@NonNls final String filePath
, @NonNls final String to
, final String
... additionalFiles
) throws Throwable
{
460 final Project project
= myProjectFixture
.getProject();
461 new WriteCommandAction
.Simple(project
) {
462 protected void run() throws Throwable
{
463 configureByFiles(ArrayUtil
.reverseArray(ArrayUtil
.append(additionalFiles
, filePath
)));
464 final VirtualFile file
= findFileInTempDir(to
);
465 assert file
.isDirectory() : to
+ " is not a directory";
466 final PsiDirectory directory
= myPsiManager
.findDirectory(file
);
467 new MoveFilesOrDirectoriesProcessor(project
, new PsiElement
[] {myFile
}, directory
,
468 false, false, null, null).run();
470 }.execute().throwException();
475 public GutterIconRenderer
findGutter(final String filePath
) throws Throwable
{
477 final Project project
= myProjectFixture
.getProject();
478 final Ref
<GutterIconRenderer
> result
= new Ref
<GutterIconRenderer
>();
479 new WriteCommandAction
.Simple(project
) {
481 protected void run() throws Throwable
{
482 final int offset
= configureByFilesInner(filePath
);
484 final Collection
<HighlightInfo
> infos
= doHighlighting();
485 for (HighlightInfo info
:infos
) {
486 if (info
.endOffset
>= offset
&& info
.startOffset
<= offset
) {
487 final GutterIconRenderer renderer
= info
.getGutterIconRenderer();
488 if (renderer
!= null) {
489 result
.set(renderer
);
496 }.execute().throwException();
501 public Collection
<GutterIconRenderer
> findAllGutters(final String filePath
) throws Throwable
{
503 final Project project
= myProjectFixture
.getProject();
504 final SortedMap
<HighlightInfo
, List
<GutterIconRenderer
>> result
= new TreeMap
<HighlightInfo
, List
<GutterIconRenderer
>>(new Comparator
<HighlightInfo
>() {
505 public int compare(final HighlightInfo o1
, final HighlightInfo o2
) {
506 return o1
.startOffset
- o2
.startOffset
;
509 new WriteCommandAction
.Simple(project
) {
511 protected void run() throws Throwable
{
512 configureByFilesInner(filePath
);
514 final Collection
<HighlightInfo
> infos
= doHighlighting();
515 for (HighlightInfo info
:infos
) {
516 final GutterIconRenderer renderer
= info
.getGutterIconRenderer();
517 if (renderer
!= null) {
518 List
<GutterIconRenderer
> renderers
= result
.get(info
);
519 if (renderers
== null) {
520 result
.put(info
, renderers
= new SmartList
<GutterIconRenderer
>());
522 renderers
.add(renderer
);
527 }.execute().throwException();
528 return ContainerUtil
.concat(result
.values());
531 public PsiClass
addClass(@NotNull @NonNls final String classText
) throws IOException
{
533 final PsiClass psiClass
= ((HeavyIdeaTestFixture
)myProjectFixture
).addClass(getTempDirPath(), classText
);
534 myAddedClasses
.add(psiClass
.getContainingFile().getVirtualFile());
538 public PsiFile
addFileToProject(@NonNls final String relativePath
, @NonNls final String fileText
) throws IOException
{
540 return ((HeavyIdeaTestFixture
)myProjectFixture
).addFileToProject(getTempDirPath(), relativePath
, fileText
);
543 public <T
> void registerExtension(final ExtensionsArea area
, final ExtensionPointName
<T
> epName
, final T extension
) {
545 final ExtensionPoint
<T
> extensionPoint
= area
.getExtensionPoint(epName
);
546 extensionPoint
.registerExtension(extension
);
547 disposeOnTearDown(new Disposable() {
548 public void dispose() {
549 extensionPoint
.unregisterExtension(extension
);
554 public PsiManager
getPsiManager() {
558 public LookupElement
[] complete(final CompletionType type
) {
560 myEmptyLookup
= false;
561 new WriteCommandAction(getProject()) {
562 protected void run(Result result
) throws Throwable
{
563 final CodeInsightActionHandler handler
= new CodeCompletionHandlerBase(type
) {
564 protected PsiFile
createFileCopy(final PsiFile file
) {
565 final PsiFile copy
= super.createFileCopy(file
);
566 if (myFileContext
!= null) {
567 final PsiElement contextCopy
= myFileContext
.copy();
568 final PsiFile containingFile
= contextCopy
.getContainingFile();
569 if (containingFile
instanceof PsiFileImpl
) {
570 ((PsiFileImpl
)containingFile
).setOriginalFile(myFileContext
.getContainingFile());
572 setContext(copy
, contextCopy
);
578 protected void completionFinished(final int offset1
, final int offset2
, final CompletionContext context
, final CompletionProgressIndicator indicator
,
579 final LookupElement
[] items
) {
580 myEmptyLookup
= items
.length
== 0;
581 super.completionFinished(offset1
, offset2
, context
, indicator
, items
);
584 Editor editor
= getCompletionEditor();
585 handler
.invoke(getProject(), editor
, PsiUtilBase
.getPsiFileInEditor(editor
, getProject()));
588 return getLookupElements();
592 protected Editor
getCompletionEditor() {
593 return InjectedLanguageUtil
.getEditorForInjectedLanguageNoCommit(myEditor
, myFile
);
597 public LookupElement
[] completeBasic() {
598 return complete(CompletionType
.BASIC
);
602 public LookupElement
[] getLookupElements() {
603 LookupImpl lookup
= (LookupImpl
)LookupManager
.getActiveLookup(myEditor
);
604 if (lookup
== null) {
605 return myEmptyLookup ? LookupElement
.EMPTY_ARRAY
: null;
608 return lookup
.getSortedItems();
612 public void checkResult(final String text
) throws IOException
{
613 PsiDocumentManager
.getInstance(getProject()).commitAllDocuments();
614 checkResult("TEXT", false, SelectionAndCaretMarkupLoader
.fromText(text
, getProject()), myFile
.getText());
617 public void checkResultByFile(final String expectedFile
) throws Throwable
{
618 checkResultByFile(expectedFile
, false);
621 public void checkResultByFile(final String expectedFile
, final boolean ignoreWhitespaces
) throws Throwable
{
623 new WriteCommandAction
.Simple(myProjectFixture
.getProject()) {
625 protected void run() throws Throwable
{
626 checkResultByFile(expectedFile
, myFile
, ignoreWhitespaces
);
628 }.execute().throwException();
631 public void checkResultByFile(final String filePath
, final String expectedFile
, final boolean ignoreWhitespaces
) throws Throwable
{
634 new WriteCommandAction
.Simple(myProjectFixture
.getProject()) {
636 protected void run() throws Throwable
{
637 String fullPath
= getTempDirPath() + "/" + filePath
;
638 final VirtualFile copy
= LocalFileSystem
.getInstance().refreshAndFindFileByPath(fullPath
.replace(File
.separatorChar
, '/'));
639 assert copy
!= null : "file not found: " + fullPath
;
640 final PsiFile psiFile
= myPsiManager
.findFile(copy
);
641 assert psiFile
!= null;
642 checkResultByFile(expectedFile
, psiFile
, ignoreWhitespaces
);
644 }.execute().throwException();
647 public void setUp() throws Exception
{
650 myProjectFixture
.setUp();
651 myTempDirFixture
.setUp();
652 myPsiManager
= (PsiManagerImpl
)PsiManager
.getInstance(getProject());
653 configureInspections(myInspections
== null ?
new LocalInspectionTool
[0] : myInspections
);
656 private void enableInspectionTool(LocalInspectionTool tool
){
657 final String shortName
= tool
.getShortName();
658 final HighlightDisplayKey key
= HighlightDisplayKey
.find(shortName
);
660 HighlightDisplayKey
.register(shortName
, tool
.getDisplayName(), tool
.getID());
662 myAvailableTools
.put(shortName
, tool
);
663 myAvailableLocalTools
.put(shortName
, new LocalInspectionToolWrapper(tool
));
666 private void configureInspections(final LocalInspectionTool
[] tools
) {
667 for (LocalInspectionTool tool
: tools
) {
668 enableInspectionTool(tool
);
671 final InspectionProfileImpl profile
= new InspectionProfileImpl(PROFILE
) {
672 public ModifiableModel
getModifiableModel() {
677 public InspectionProfileEntry
[] getInspectionTools() {
678 final Collection
<LocalInspectionToolWrapper
> tools
= myAvailableLocalTools
.values();
679 return tools
.toArray(new LocalInspectionToolWrapper
[tools
.size()]);
682 public boolean isToolEnabled(HighlightDisplayKey key
) {
683 return key
!= null && key
.toString() != null && myAvailableTools
!= null && myAvailableTools
.containsKey(key
.toString());
686 public HighlightDisplayLevel
getErrorLevel(HighlightDisplayKey key
) {
687 final LocalInspectionTool localInspectionTool
= key
== null ?
null : myAvailableTools
.get(key
.toString());
688 return localInspectionTool
!= null ? localInspectionTool
.getDefaultLevel() : HighlightDisplayLevel
.WARNING
;
691 public InspectionTool
getInspectionTool(String shortName
) {
692 return myAvailableLocalTools
.get(shortName
);
695 final InspectionProfileManager inspectionProfileManager
= InspectionProfileManager
.getInstance();
696 inspectionProfileManager
.addProfile(profile
);
697 Disposer
.register(getProject(), new Disposable() {
698 public void dispose() {
699 inspectionProfileManager
.deleteProfile(PROFILE
);
702 inspectionProfileManager
.setRootProfile(profile
.getName());
703 InspectionProjectProfileManager
.getInstance(getProject()).updateProfile(profile
);
706 public void tearDown() throws Exception
{
707 if (SwingUtilities
.isEventDispatchThread()) {
708 LookupManager
.getInstance(getProject()).hideActiveLookup();
711 ApplicationManager
.getApplication().invokeAndWait(new Runnable() {
713 LookupManager
.getInstance(getProject()).hideActiveLookup();
715 }, ModalityState
.NON_MODAL
);
718 FileEditorManager editorManager
= FileEditorManager
.getInstance(getProject());
719 VirtualFile
[] openFiles
= editorManager
.getOpenFiles();
720 for (VirtualFile openFile
: openFiles
) {
721 editorManager
.closeFile(openFile
);
724 myProjectFixture
.tearDown();
725 myTempDirFixture
.tearDown();
730 private int configureByFilesInner(@NonNls String
... filePaths
) throws IOException
{
734 for (int i
= filePaths
.length
- 1; i
> 0; i
--) {
735 configureByFileInner(filePaths
[i
]);
737 return configureByFileInner(filePaths
[0]);
740 public void configureByFile(final String file
) throws IOException
{
742 new WriteCommandAction
.Simple(getProject()) {
743 protected void run() throws Throwable
{
744 configureByFilesInner(file
);
749 public void configureByFiles(@NonNls final String
... files
) throws Throwable
{
750 new WriteCommandAction
.Simple(getProject()) {
751 protected void run() throws Throwable
{
752 configureByFilesInner(files
);
757 public void configureByDirectory(final String dir
) {
758 //To change body of implemented methods use File | Settings | File Templates.
761 public PsiFile
configureByText(final FileType fileType
, @NonNls final String text
) throws Throwable
{
763 final String extension
= fileType
.getDefaultExtension();
764 final File tempFile
= File
.createTempFile("aaa", "." + extension
, new File(getTempDirPath()));
765 final FileTypeManager fileTypeManager
= FileTypeManager
.getInstance();
766 if (fileTypeManager
.getFileTypeByExtension(extension
) != fileType
) {
767 new WriteCommandAction(getProject()) {
768 protected void run(Result result
) throws Throwable
{
769 fileTypeManager
.associateExtension(fileType
, extension
);
773 final VirtualFile vFile
= LocalFileSystem
.getInstance().refreshAndFindFileByIoFile(tempFile
);
774 VfsUtil
.saveText(vFile
, text
);
775 assert vFile
!= null;
776 configureInner(vFile
, SelectionAndCaretMarkupLoader
.fromFile(vFile
, getProject()));
780 public Document
getDocument(final PsiFile file
) {
782 return PsiDocumentManager
.getInstance(getProject()).getDocument(file
);
785 public void setFileContext(@Nullable final PsiElement context
) {
786 myFileContext
= context
;
787 setContext(myFile
, context
);
793 * @return caret offset or -1 if caret marker does not present
794 * @throws IOException
796 private int configureByFileInner(@NonNls String filePath
) throws IOException
{
798 copyFileToProject(filePath
);
799 return configureFromTempProjectFile(filePath
);
802 public int configureFromTempProjectFile(final String filePath
) throws IOException
{
803 return configureByFileInner(findFileInTempDir(filePath
));
806 public void configureFromExistingVirtualFile(VirtualFile f
) throws IOException
{
807 configureByFileInner(f
);
810 private int configureByFileInner(final VirtualFile copy
) throws IOException
{
811 return configureInner(copy
, SelectionAndCaretMarkupLoader
.fromFile(copy
, getProject()));
814 private int configureInner(@NotNull final VirtualFile copy
, final SelectionAndCaretMarkupLoader loader
) {
817 final OutputStream outputStream
= copy
.getOutputStream(null, 0, 0);
818 outputStream
.write(loader
.newFileText
.getBytes());
819 outputStream
.close();
821 catch (IOException e
) {
822 throw new RuntimeException(e
);
824 myFile
= myPsiManager
.findFile(copy
);
825 setContext(myFile
, myFileContext
);
826 myEditor
= createEditor(copy
);
827 assert myEditor
!= null;
829 if (loader
.caretMarker
!= null) {
830 offset
= loader
.caretMarker
.getStartOffset();
831 myEditor
.getCaretModel().moveToOffset(offset
);
833 if (loader
.selStartMarker
!= null && loader
.selEndMarker
!= null) {
834 myEditor
.getSelectionModel().setSelection(loader
.selStartMarker
.getStartOffset(), loader
.selEndMarker
.getStartOffset());
837 Module module
= getModule();
838 if (module
!= null) {
839 for (Facet facet
: FacetManager
.getInstance(module
).getAllFacets()) {
840 module
.getMessageBus().syncPublisher(FacetManager
.FACETS_TOPIC
).facetConfigurationChanged(facet
);
847 private static void setContext(final PsiFile file
, final PsiElement context
) {
848 if (file
!= null && context
!= null) {
849 file
.putUserData(FileContextUtil
.INJECTED_IN_ELEMENT
, new SmartPsiElementPointer() {
850 public PsiElement
getElement() {
854 public PsiFile
getContainingFile() {
855 return context
.getContainingFile();
861 public VirtualFile
findFileInTempDir(final String filePath
) {
862 String fullPath
= getTempDirPath() + "/" + filePath
;
864 final VirtualFile copy
= LocalFileSystem
.getInstance().refreshAndFindFileByPath(fullPath
.replace(File
.separatorChar
, '/'));
865 assert copy
!= null: "file " + fullPath
+ " not found";
870 private Editor
createEditor(VirtualFile file
) {
871 final Project project
= getProject();
872 final FileEditorManager instance
= FileEditorManager
.getInstance(project
);
873 if (file
.getFileType().isBinary()) {
876 return instance
.openTextEditor(new OpenFileDescriptor(project
, file
, 0), false);
879 private void collectAndCheckHighlightings(boolean checkWarnings
, boolean checkInfos
, boolean checkWeakWarnings
, Ref
<Long
> duration
)
881 final Project project
= getProject();
882 ExpectedHighlightingData data
= new ExpectedHighlightingData(myEditor
.getDocument(), checkWarnings
, checkWeakWarnings
, checkInfos
, myFile
);
884 PsiDocumentManager
.getInstance(project
).commitAllDocuments();
886 ((PsiFileImpl
)myFile
).calcTreeElement(); //to load text
888 //to initialize caches
889 myPsiManager
.getCacheManager().getFilesWithWord(XXX
, UsageSearchContext
.IN_COMMENTS
, GlobalSearchScope
.allScope(project
), true);
890 VirtualFileFilter javaFilesFilter
= new VirtualFileFilter() {
891 public boolean accept(VirtualFile file
) {
892 if (myAddedClasses
.contains(file
)) return false;
894 FileType fileType
= FileTypeManager
.getInstance().getFileTypeByFile(file
);
895 return fileType
== StdFileTypes
.JAVA
|| fileType
== StdFileTypes
.CLASS
;
899 JavaPsiFacadeEx
.getInstanceEx(project
).setAssertOnFileLoadingFilter(javaFilesFilter
); // check repository work
901 final long start
= System
.currentTimeMillis();
902 // ProfilingUtil.startCPUProfiling();
903 Collection
<HighlightInfo
> infos
= doHighlighting();
904 duration
.set(System
.currentTimeMillis() - start
);
905 // ProfilingUtil.captureCPUSnapshot("testing");
907 JavaPsiFacadeEx
.getInstanceEx(project
).setAssertOnFileLoadingFilter(VirtualFileFilter
.NONE
);
909 data
.checkResult(infos
, myEditor
.getDocument().getText());
913 private Collection
<HighlightInfo
> doHighlighting() {
915 final Project project
= myProjectFixture
.getProject();
917 PsiDocumentManager
.getInstance(project
).commitAllDocuments();
919 Document document
= myEditor
.getDocument();
920 GeneralHighlightingPass action1
= new GeneralHighlightingPass(project
, myFile
, document
, 0, myFile
.getTextLength(), true);
921 action1
.doCollectInformation(new MockProgressIndicator());
922 Collection
<HighlightInfo
> highlights1
= action1
.getHighlights();
924 PostHighlightingPass action2
= new PostHighlightingPass(project
, myFile
, myEditor
, 0, myFile
.getTextLength());
925 action2
.doCollectInformation(new MockProgressIndicator());
926 Collection
<HighlightInfo
> highlights2
= action2
.getHighlights();
928 Collection
<HighlightInfo
> highlights3
= null;
929 if (!myAvailableTools
.isEmpty()) {
930 LocalInspectionsPass inspectionsPass
= new LocalInspectionsPass(myFile
, myEditor
.getDocument(), 0, myFile
.getTextLength());
931 inspectionsPass
.doCollectInformation(new MockProgressIndicator());
932 highlights3
= inspectionsPass
.getHighlights();
935 ExternalToolPass action4
= new ExternalToolPass(myFile
, myEditor
, 0, myFile
.getTextLength());
936 action4
.doCollectInformation(new MockProgressIndicator());
937 Collection
<HighlightInfo
> highlights4
= action4
.getHighlights();
939 ArrayList
<HighlightInfo
> list
= new ArrayList
<HighlightInfo
>();
940 list
.addAll(highlights1
);
941 list
.addAll(highlights2
);
942 if (highlights3
!= null) {
943 list
.addAll(highlights3
);
945 list
.addAll(highlights4
);
949 public String
getTestDataPath() {
950 return myTestDataPath
;
953 public Project
getProject() {
954 return myProjectFixture
.getProject();
957 public Module
getModule() {
958 return myProjectFixture
.getModule();
961 public Editor
getEditor() {
965 public PsiFile
getFile() {
969 public static List
<IntentionAction
> getAvailableIntentions(final Project project
, final Collection
<HighlightInfo
> infos
, final int offset
,
970 final Editor editor
, final PsiFile file
) {
971 final List
<IntentionAction
> availableActions
= new ArrayList
<IntentionAction
>();
973 for (HighlightInfo info
:infos
) {
974 if (info
.quickFixActionRanges
!= null) {
975 for (Pair
<HighlightInfo
.IntentionActionDescriptor
, TextRange
> pair
: info
.quickFixActionRanges
) {
976 if (offset
> 0 && !pair
.getSecond().contains(offset
)) {
979 final HighlightInfo
.IntentionActionDescriptor actionDescriptor
= pair
.first
;
980 final IntentionAction action
= actionDescriptor
.getAction();
981 if (action
.isAvailable(project
, editor
, file
)) {
982 availableActions
.add(action
);
983 final PsiElement element
= file
.findElementAt(editor
.getCaretModel().getOffset());
984 assert element
!= null;
985 final List
<IntentionAction
> actions
= actionDescriptor
.getOptions(element
);
986 if (actions
!= null) {
987 for (IntentionAction intentionAction
: actions
) {
988 if (intentionAction
.isAvailable(project
, editor
, file
)) {
989 availableActions
.add(intentionAction
);
998 for (IntentionAction intentionAction
: IntentionManager
.getInstance().getIntentionActions()) {
999 if (intentionAction
.isAvailable(project
, editor
, file
)) {
1000 availableActions
.add(intentionAction
);
1003 return availableActions
;
1006 static class SelectionAndCaretMarkupLoader
{
1007 final String newFileText
;
1008 final RangeMarker caretMarker
;
1009 final RangeMarker selStartMarker
;
1010 final RangeMarker selEndMarker
;
1012 static SelectionAndCaretMarkupLoader
fromFile(String path
, Project project
) throws IOException
{
1013 return new SelectionAndCaretMarkupLoader(StringUtil
.convertLineSeparators(new String(FileUtil
.loadFileText(new File(path
)))), project
);
1015 static SelectionAndCaretMarkupLoader
fromFile(VirtualFile file
, Project project
) throws IOException
{
1016 return new SelectionAndCaretMarkupLoader(StringUtil
.convertLineSeparators(VfsUtil
.loadText(file
)), project
);
1019 static SelectionAndCaretMarkupLoader
fromText(String text
, Project project
) {
1020 return new SelectionAndCaretMarkupLoader(text
, project
);
1023 private SelectionAndCaretMarkupLoader(String fileText
, Project project
) {
1024 final Document document
= EditorFactory
.getInstance().createDocument(fileText
);
1026 int caretIndex
= fileText
.indexOf(CARET_MARKER
);
1027 int selStartIndex
= fileText
.indexOf(SELECTION_START_MARKER
);
1028 int selEndIndex
= fileText
.indexOf(SELECTION_END_MARKER
);
1030 caretMarker
= caretIndex
>= 0 ? document
.createRangeMarker(caretIndex
, caretIndex
) : null;
1031 selStartMarker
= selStartIndex
>= 0 ? document
.createRangeMarker(selStartIndex
, selStartIndex
) : null;
1032 selEndMarker
= selEndIndex
>= 0 ? document
.createRangeMarker(selEndIndex
, selEndIndex
) : null;
1034 new WriteCommandAction(project
) {
1035 protected void run(Result result
) throws Throwable
{
1036 if (caretMarker
!= null) {
1037 document
.deleteString(caretMarker
.getStartOffset(), caretMarker
.getStartOffset() + CARET_MARKER
.length());
1039 if (selStartMarker
!= null) {
1040 document
.deleteString(selStartMarker
.getStartOffset(), selStartMarker
.getStartOffset() + SELECTION_START_MARKER
.length());
1042 if (selEndMarker
!= null) {
1043 document
.deleteString(selEndMarker
.getStartOffset(), selEndMarker
.getStartOffset() + SELECTION_END_MARKER
.length());
1048 newFileText
= document
.getText();
1052 private void checkResultByFile(@NonNls String expectedFile
,
1053 @NotNull PsiFile originalFile
,
1054 boolean stripTrailingSpaces
) throws IOException
{
1055 if (!stripTrailingSpaces
) {
1056 final LogicalPosition position
= myEditor
.getCaretModel().getLogicalPosition();
1057 EditorUtil
.fillVirtualSpaceUntil(myEditor
, position
.column
, position
.line
);
1059 PsiDocumentManager
.getInstance(getProject()).commitAllDocuments();
1060 checkResult(expectedFile
, stripTrailingSpaces
, SelectionAndCaretMarkupLoader
.fromFile(getTestDataPath() + "/" + expectedFile
, getProject()), originalFile
.getText());
1063 private void checkResult(final String expectedFile
,
1064 final boolean stripTrailingSpaces
,
1065 final SelectionAndCaretMarkupLoader loader
,
1066 String actualText
) {
1067 assertInitialized();
1068 Project project
= myProjectFixture
.getProject();
1070 project
.getComponent(PostprocessReformattingAspect
.class).doPostponedFormatting();
1071 if (stripTrailingSpaces
) {
1072 actualText
= stripTrailingSpaces(actualText
);
1075 PsiDocumentManager
.getInstance(project
).commitAllDocuments();
1077 String newFileText1
= loader
.newFileText
;
1078 if (stripTrailingSpaces
) {
1079 newFileText1
= stripTrailingSpaces(newFileText1
);
1082 actualText
= StringUtil
.convertLineSeparators(actualText
, "\n");
1084 //noinspection HardCodedStringLiteral
1085 Assert
.assertEquals("Text mismatch in file " + expectedFile
, newFileText1
, actualText
);
1087 if (loader
.caretMarker
!= null) {
1088 int caretLine
= StringUtil
.offsetToLineNumber(loader
.newFileText
, loader
.caretMarker
.getStartOffset());
1089 int caretCol
= loader
.caretMarker
.getStartOffset() - StringUtil
.lineColToOffset(loader
.newFileText
, caretLine
, 0);
1091 Assert
.assertEquals("caretLine", caretLine
+ 1, myEditor
.getCaretModel().getLogicalPosition().line
+ 1);
1092 Assert
.assertEquals("caretColumn", caretCol
+ 1, myEditor
.getCaretModel().getLogicalPosition().column
+ 1);
1095 if (loader
.selStartMarker
!= null && loader
.selEndMarker
!= null) {
1096 int selStartLine
= StringUtil
.offsetToLineNumber(loader
.newFileText
, loader
.selStartMarker
.getStartOffset());
1097 int selStartCol
= loader
.selStartMarker
.getStartOffset() - StringUtil
.lineColToOffset(loader
.newFileText
, selStartLine
, 0);
1099 int selEndLine
= StringUtil
.offsetToLineNumber(loader
.newFileText
, loader
.selEndMarker
.getEndOffset());
1100 int selEndCol
= loader
.selEndMarker
.getEndOffset() - StringUtil
.lineColToOffset(loader
.newFileText
, selEndLine
, 0);
1102 Assert
.assertEquals("selectionStartLine", selStartLine
+ 1,
1103 StringUtil
.offsetToLineNumber(loader
.newFileText
, myEditor
.getSelectionModel().getSelectionStart()) + 1);
1105 Assert
.assertEquals("selectionStartCol", selStartCol
+ 1, myEditor
.getSelectionModel().getSelectionStart() -
1106 StringUtil
.lineColToOffset(loader
.newFileText
, selStartLine
, 0) + 1);
1108 Assert
.assertEquals("selectionEndLine", selEndLine
+ 1,
1109 StringUtil
.offsetToLineNumber(loader
.newFileText
, myEditor
.getSelectionModel().getSelectionEnd()) + 1);
1111 Assert
.assertEquals("selectionEndCol", selEndCol
+ 1,
1112 myEditor
.getSelectionModel().getSelectionEnd() - StringUtil
.lineColToOffset(loader
.newFileText
, selEndLine
, 0) +
1116 Assert
.assertTrue("has no selection", !myEditor
.getSelectionModel().hasSelection());
1120 private static String
stripTrailingSpaces(String actualText
) {
1121 final Document document
= EditorFactory
.getInstance().createDocument(actualText
);
1122 ((DocumentEx
)document
).stripTrailingSpaces(false);
1123 actualText
= document
.getText();