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
.CodeCompletionHandler
;
11 import com
.intellij
.codeInsight
.completion
.LookupData
;
12 import com
.intellij
.codeInsight
.completion
.actions
.CodeCompletionAction
;
13 import com
.intellij
.codeInsight
.daemon
.HighlightDisplayKey
;
14 import com
.intellij
.codeInsight
.daemon
.impl
.GeneralHighlightingPass
;
15 import com
.intellij
.codeInsight
.daemon
.impl
.HighlightInfo
;
16 import com
.intellij
.codeInsight
.daemon
.impl
.LocalInspectionsPass
;
17 import com
.intellij
.codeInsight
.daemon
.impl
.PostHighlightingPass
;
18 import com
.intellij
.codeInsight
.intention
.IntentionAction
;
19 import com
.intellij
.codeInsight
.intention
.IntentionManager
;
20 import com
.intellij
.codeInsight
.lookup
.Lookup
;
21 import com
.intellij
.codeInsight
.lookup
.LookupItem
;
22 import com
.intellij
.codeInsight
.lookup
.LookupManager
;
23 import com
.intellij
.codeInspection
.InspectionProfileEntry
;
24 import com
.intellij
.codeInspection
.InspectionToolProvider
;
25 import com
.intellij
.codeInspection
.LocalInspectionTool
;
26 import com
.intellij
.codeInspection
.ModifiableModel
;
27 import com
.intellij
.codeInspection
.ex
.InspectionProfileImpl
;
28 import com
.intellij
.codeInspection
.ex
.InspectionTool
;
29 import com
.intellij
.codeInspection
.ex
.LocalInspectionToolWrapper
;
30 import com
.intellij
.ide
.DataManager
;
31 import com
.intellij
.lang
.findUsages
.FindUsagesProvider
;
32 import com
.intellij
.lang
.findUsages
.LanguageFindUsages
;
33 import com
.intellij
.mock
.MockProgressIndicator
;
34 import com
.intellij
.openapi
.Disposable
;
35 import com
.intellij
.openapi
.application
.Result
;
36 import com
.intellij
.openapi
.application
.RunResult
;
37 import com
.intellij
.openapi
.command
.WriteCommandAction
;
38 import com
.intellij
.openapi
.editor
.Document
;
39 import com
.intellij
.openapi
.editor
.Editor
;
40 import com
.intellij
.openapi
.editor
.EditorFactory
;
41 import com
.intellij
.openapi
.editor
.RangeMarker
;
42 import com
.intellij
.openapi
.editor
.actionSystem
.EditorActionManager
;
43 import com
.intellij
.openapi
.editor
.actionSystem
.TypedAction
;
44 import com
.intellij
.openapi
.editor
.ex
.DocumentEx
;
45 import com
.intellij
.openapi
.editor
.markup
.GutterIconRenderer
;
46 import com
.intellij
.openapi
.extensions
.ExtensionPoint
;
47 import com
.intellij
.openapi
.extensions
.ExtensionPointName
;
48 import com
.intellij
.openapi
.extensions
.ExtensionsArea
;
49 import com
.intellij
.openapi
.fileEditor
.FileEditorManager
;
50 import com
.intellij
.openapi
.fileEditor
.OpenFileDescriptor
;
51 import com
.intellij
.openapi
.fileTypes
.FileType
;
52 import com
.intellij
.openapi
.fileTypes
.FileTypeManager
;
53 import com
.intellij
.openapi
.fileTypes
.StdFileTypes
;
54 import com
.intellij
.openapi
.project
.Project
;
55 import com
.intellij
.openapi
.roots
.ModuleRootManager
;
56 import com
.intellij
.openapi
.util
.Disposer
;
57 import com
.intellij
.openapi
.util
.Pair
;
58 import com
.intellij
.openapi
.util
.Ref
;
59 import com
.intellij
.openapi
.util
.TextRange
;
60 import com
.intellij
.openapi
.util
.io
.FileUtil
;
61 import com
.intellij
.openapi
.util
.text
.StringUtil
;
62 import com
.intellij
.openapi
.vfs
.*;
63 import com
.intellij
.profile
.codeInspection
.InspectionProfileManager
;
64 import com
.intellij
.profile
.codeInspection
.InspectionProjectProfileManager
;
65 import com
.intellij
.psi
.*;
66 import com
.intellij
.psi
.impl
.JavaPsiFacadeEx
;
67 import com
.intellij
.psi
.impl
.PsiManagerImpl
;
68 import com
.intellij
.psi
.impl
.source
.PostprocessReformattingAspect
;
69 import com
.intellij
.psi
.impl
.source
.PsiFileImpl
;
70 import com
.intellij
.psi
.impl
.source
.resolve
.FileContextUtil
;
71 import com
.intellij
.psi
.impl
.source
.tree
.injected
.InjectedLanguageUtil
;
72 import com
.intellij
.psi
.search
.GlobalSearchScope
;
73 import com
.intellij
.psi
.search
.UsageSearchContext
;
74 import com
.intellij
.psi
.search
.searches
.ReferencesSearch
;
75 import com
.intellij
.refactoring
.move
.moveFilesOrDirectories
.MoveFilesOrDirectoriesProcessor
;
76 import com
.intellij
.refactoring
.rename
.RenameProcessor
;
77 import com
.intellij
.testFramework
.ExpectedHighlightingData
;
78 import com
.intellij
.testFramework
.UsefulTestCase
;
79 import com
.intellij
.testFramework
.fixtures
.CodeInsightTestFixture
;
80 import com
.intellij
.testFramework
.fixtures
.IdeaProjectTestFixture
;
81 import com
.intellij
.testFramework
.fixtures
.TempDirTestFixture
;
82 import com
.intellij
.util
.Function
;
83 import com
.intellij
.util
.SmartList
;
84 import com
.intellij
.util
.containers
.ContainerUtil
;
85 import gnu
.trove
.THashMap
;
86 import gnu
.trove
.THashSet
;
87 import junit
.framework
.Assert
;
88 import junit
.framework
.TestCase
;
89 import org
.jetbrains
.annotations
.NonNls
;
90 import org
.jetbrains
.annotations
.NotNull
;
91 import org
.jetbrains
.annotations
.Nullable
;
94 import java
.io
.IOException
;
95 import java
.io
.OutputStream
;
99 * @author Dmitry Avdeev
101 public class CodeInsightTestFixtureImpl
extends BaseFixture
implements CodeInsightTestFixture
{
103 @NonNls private static final String PROFILE
= "Configurable";
105 private PsiManagerImpl myPsiManager
;
106 private PsiFile myFile
;
107 private Editor myEditor
;
108 private String myTestDataPath
;
110 private LocalInspectionTool
[] myInspections
;
111 private final Map
<String
, LocalInspectionTool
> myAvailableTools
= new THashMap
<String
, LocalInspectionTool
>();
112 private final Map
<String
, LocalInspectionToolWrapper
> myAvailableLocalTools
= new THashMap
<String
, LocalInspectionToolWrapper
>();
114 private final TempDirTestFixture myTempDirFixture
= new TempDirTextFixtureImpl();
115 private final IdeaProjectTestFixture myProjectFixture
;
116 private final Set
<VirtualFile
> myAddedClasses
= new THashSet
<VirtualFile
>();
117 @NonNls private static final String XXX
= "XXX";
118 private PsiElement myFileContext
;
120 public CodeInsightTestFixtureImpl(IdeaProjectTestFixture projectFixture
) {
121 myProjectFixture
= projectFixture
;
124 public void setTestDataPath(String dataPath
) {
125 myTestDataPath
= dataPath
;
128 public String
getTempDirPath() {
129 return myTempDirFixture
.getTempDirPath();
132 public TempDirTestFixture
getTempDirFixture() {
133 return myTempDirFixture
;
136 public String
copyFileToProject(@NonNls final String sourceFilePath
, @NonNls final String targetPath
) throws IOException
{
137 final File destFile
= new File(getTempDirPath() + "/" + targetPath
);
138 FileUtil
.copy(new File(sourceFilePath
), destFile
);
139 Assert
.assertNotNull(LocalFileSystem
.getInstance().refreshAndFindFileByIoFile(destFile
));
143 public String
copyFileToProject(@NonNls final String sourceFilePath
) throws IOException
{
144 return copyFileToProject(sourceFilePath
, StringUtil
.getShortName(StringUtil
.getShortName(sourceFilePath
, '\\'), '/'));
147 public void enableInspections(LocalInspectionTool
... inspections
) {
148 myInspections
= inspections
;
149 if (isInitialized()) {
150 configureInspections(myInspections
);
154 private boolean isInitialized() {
155 return myPsiManager
!= null;
158 public void enableInspections(final Class
<?
extends LocalInspectionTool
>... inspections
) {
159 final ArrayList
<LocalInspectionTool
> tools
= new ArrayList
<LocalInspectionTool
>();
160 for (Class clazz
: inspections
) {
162 LocalInspectionTool inspection
= (LocalInspectionTool
)clazz
.getConstructor().newInstance();
163 tools
.add(inspection
);
165 catch (Exception e
) {
166 throw new RuntimeException("Cannot instantiate " + clazz
);
169 enableInspections(tools
.toArray(new LocalInspectionTool
[tools
.size()]));
172 public void disableInspections(LocalInspectionTool
... inspections
) {
173 myAvailableTools
.clear();
174 myAvailableLocalTools
.clear();
175 final ArrayList
<LocalInspectionTool
> tools
= new ArrayList
<LocalInspectionTool
>(Arrays
.asList(myInspections
));
176 for (Iterator
<LocalInspectionTool
> i
= tools
.iterator(); i
.hasNext();) {
177 final LocalInspectionTool tool
= i
.next();
178 for (LocalInspectionTool toRemove
: inspections
) {
179 if (tool
.getShortName().equals(toRemove
.getShortName())) {
185 myInspections
= tools
.toArray(new LocalInspectionTool
[tools
.size()]);
186 configureInspections(myInspections
);
189 public void enableInspections(InspectionToolProvider
... providers
) {
190 final ArrayList
<LocalInspectionTool
> tools
= new ArrayList
<LocalInspectionTool
>();
191 for (InspectionToolProvider provider
: providers
) {
192 for (Class clazz
: provider
.getInspectionClasses()) {
194 LocalInspectionTool inspection
= (LocalInspectionTool
)clazz
.getConstructor().newInstance();
195 tools
.add(inspection
);
197 catch (Exception e
) {
198 throw new RuntimeException("Cannot instantiate " + clazz
);
202 myInspections
= tools
.toArray(new LocalInspectionTool
[tools
.size()]);
203 configureInspections(myInspections
);
206 public long testHighlighting(final boolean checkWarnings
,
207 final boolean checkInfos
,
208 final boolean checkWeakWarnings
,
209 final String
... filePaths
) throws Throwable
{
211 final Ref
<Long
> duration
= new Ref
<Long
>();
212 new WriteCommandAction
.Simple(myProjectFixture
.getProject()) {
214 protected void run() throws Throwable
{
215 configureByFilesInner(filePaths
);
216 collectAndCheckHighlightings(checkWarnings
, checkInfos
, checkWeakWarnings
, duration
);
218 }.execute().throwException();
219 return duration
.get().longValue();
222 public long checkHighlighting(final boolean checkWarnings
, final boolean checkInfos
, final boolean checkWeakWarnings
) throws Throwable
{
223 final Ref
<Long
> duration
= new Ref
<Long
>();
224 new WriteCommandAction
.Simple(myProjectFixture
.getProject()) {
225 protected void run() throws Throwable
{
226 collectAndCheckHighlightings(checkWarnings
, checkInfos
, checkWeakWarnings
, duration
);
228 }.execute().throwException();
229 return duration
.get().longValue();
232 public long checkHighlighting() throws Throwable
{
233 return checkHighlighting(true, true, true);
236 public long testHighlighting(final String
... filePaths
) throws Throwable
{
237 return testHighlighting(true, true, true, filePaths
);
240 public long testHighlighting(final boolean checkWarnings
, final boolean checkInfos
, final boolean checkWeakWarnings
, final VirtualFile file
) throws Throwable
{
241 final Ref
<Long
> duration
= new Ref
<Long
>();
242 new WriteCommandAction
.Simple(myProjectFixture
.getProject()) {
243 protected void run() throws Throwable
{
244 myFile
= myPsiManager
.findFile(file
);
245 myEditor
= createEditor(file
);
246 collectAndCheckHighlightings(checkWarnings
, checkInfos
, checkWeakWarnings
, duration
);
248 }.execute().throwException();
249 return duration
.get().longValue();
253 public PsiReference
getReferenceAtCaretPosition(final String filePath
) throws Throwable
{
254 final RunResult
<PsiReference
> runResult
= new WriteCommandAction
<PsiReference
>(myProjectFixture
.getProject()) {
255 protected void run(final Result
<PsiReference
> result
) throws Throwable
{
256 configureByFilesInner(filePath
);
257 final int offset
= myEditor
.getCaretModel().getOffset();
258 final PsiReference psiReference
= getFile().findReferenceAt(offset
);
259 result
.setResult(psiReference
);
262 runResult
.throwException();
263 return runResult
.getResultObject();
267 public PsiReference
getReferenceAtCaretPositionWithAssertion(final String filePath
) throws Throwable
{
268 final PsiReference reference
= getReferenceAtCaretPosition(filePath
);
269 assert reference
!= null: "no reference found at " + myEditor
.getCaretModel().getLogicalPosition();
274 public List
<IntentionAction
> getAvailableIntentions(final String
... filePaths
) throws Throwable
{
276 final Project project
= myProjectFixture
.getProject();
277 return new WriteCommandAction
<List
<IntentionAction
>>(project
) {
278 protected void run(final Result
<List
<IntentionAction
>> result
) throws Throwable
{
279 final int offset
= configureByFilesInner(filePaths
);
280 result
.setResult(getAvailableIntentions(project
, doHighlighting(), offset
, myEditor
, myFile
));
282 }.execute().getResultObject();
285 public void launchAction(@NotNull final IntentionAction action
) throws Throwable
{
286 new WriteCommandAction(myProjectFixture
.getProject()) {
287 protected void run(final Result result
) throws Throwable
{
288 action
.invoke(getProject(), getEditor(), getFile());
290 }.execute().throwException();
294 public void testCompletion(final String
[] filesBefore
, final String fileAfter
) throws Throwable
{
295 new WriteCommandAction
.Simple(myProjectFixture
.getProject()) {
297 protected void run() throws Throwable
{
298 configureByFilesInner(filesBefore
);
300 checkResultByFile(fileAfter
, myFile
, false);
302 }.execute().throwException();
305 public void testCompletion(String fileBefore
, String fileAfter
) throws Throwable
{
306 testCompletion(new String
[] { fileBefore
}, fileAfter
);
309 public void testCompletionVariants(final String fileBefore
, final String
... expectedItems
) throws Throwable
{
310 new WriteCommandAction
.Simple(myProjectFixture
.getProject()) {
312 protected void run() throws Throwable
{
313 configureByFilesInner(fileBefore
);
314 LookupItem
[] lookupItems
= completeBasic();
315 UsefulTestCase
.assertNotNull("No lookup was shown, probably there was only one lookup element that was inserted automatically", lookupItems
);
316 UsefulTestCase
.assertSameElements(ContainerUtil
.map(lookupItems
, new Function
<LookupItem
, String
>() {
317 public String
fun(final LookupItem lookupItem
) {
318 return lookupItem
.getLookupString();
322 }.execute().throwException();
325 public void testRename(final String fileBefore
, final String fileAfter
, final String newName
) throws Throwable
{
326 new WriteCommandAction
.Simple(myProjectFixture
.getProject()) {
327 protected void run() throws Throwable
{
328 configureByFilesInner(fileBefore
);
330 }.execute().throwException();
331 testRename(fileAfter
, newName
);
334 public void testRename(final String fileAfter
, final String newName
) throws Throwable
{
335 new WriteCommandAction
.Simple(myProjectFixture
.getProject()) {
336 protected void run() throws Throwable
{
337 PsiElement element
= TargetElementUtilBase
.findTargetElement(myEditor
, TargetElementUtilBase
.REFERENCED_ELEMENT_ACCEPTED
);
338 assert element
!= null: "element not found at caret position, offset " + myEditor
.getCaretModel().getOffset();
339 new RenameProcessor(myProjectFixture
.getProject(), element
, newName
, false, false).run();
340 checkResultByFile(fileAfter
, myFile
, false);
342 }.execute().throwException();
345 public void type(final char c
) {
346 EditorActionManager actionManager
= EditorActionManager
.getInstance();
347 TypedAction action
= actionManager
.getTypedAction();
348 action
.actionPerformed(getEditor(), c
, DataManager
.getInstance().getDataContext());
351 public JavaPsiFacade
getJavaFacade() {
352 return JavaPsiFacade
.getInstance(getProject());
355 public PsiReference
[] testFindUsages(@NonNls final String
... fileNames
) throws Throwable
{
356 configureByFiles(fileNames
);
357 FindUsagesProvider handler
= LanguageFindUsages
.INSTANCE
.forLanguage(getFile().getLanguage());
358 PsiElement referenceTo
= TargetElementUtilBase
359 .findTargetElement(getEditor(), TargetElementUtilBase
.ELEMENT_NAME_ACCEPTED
| TargetElementUtilBase
.REFERENCED_ELEMENT_ACCEPTED
);
361 assert referenceTo
!= null && handler
.canFindUsagesFor(referenceTo
) : "Cannot find element in caret";
362 final Project project
= getProject();
363 return ReferencesSearch
.search(referenceTo
, GlobalSearchScope
.projectScope(project
), false).toArray(new PsiReference
[0]);
366 public void moveFile(@NonNls final String filePath
, @NonNls final String to
) throws Throwable
{
367 final Project project
= myProjectFixture
.getProject();
368 new WriteCommandAction
.Simple(project
) {
369 protected void run() throws Throwable
{
370 configureByFile(filePath
);
371 final VirtualFile file
= findFile(to
);
372 assert file
.isDirectory() : to
+ " is not a directory";
373 final PsiDirectory directory
= myPsiManager
.findDirectory(file
);
374 new MoveFilesOrDirectoriesProcessor(project
, new PsiElement
[] {myFile
}, directory
,
375 false, false, null, null).run();
377 }.execute().throwException();
382 public GutterIconRenderer
findGutter(final String filePath
) throws Throwable
{
383 final Project project
= myProjectFixture
.getProject();
384 final Ref
<GutterIconRenderer
> result
= new Ref
<GutterIconRenderer
>();
385 new WriteCommandAction
.Simple(project
) {
387 protected void run() throws Throwable
{
388 final int offset
= configureByFilesInner(filePath
);
390 final Collection
<HighlightInfo
> infos
= doHighlighting();
391 for (HighlightInfo info
:infos
) {
392 if (info
.endOffset
>= offset
&& info
.startOffset
<= offset
) {
393 final GutterIconRenderer renderer
= info
.getGutterIconRenderer();
394 if (renderer
!= null) {
395 result
.set(renderer
);
402 }.execute().throwException();
407 public Collection
<GutterIconRenderer
> findAllGutters(final String filePath
) throws Throwable
{
408 final Project project
= myProjectFixture
.getProject();
409 final SortedMap
<HighlightInfo
, List
<GutterIconRenderer
>> result
= new TreeMap
<HighlightInfo
, List
<GutterIconRenderer
>>(new Comparator
<HighlightInfo
>() {
410 public int compare(final HighlightInfo o1
, final HighlightInfo o2
) {
411 return o1
.startOffset
- o2
.startOffset
;
414 new WriteCommandAction
.Simple(project
) {
416 protected void run() throws Throwable
{
417 configureByFilesInner(filePath
);
419 final Collection
<HighlightInfo
> infos
= doHighlighting();
420 for (HighlightInfo info
:infos
) {
421 final GutterIconRenderer renderer
= info
.getGutterIconRenderer();
422 if (renderer
!= null) {
423 List
<GutterIconRenderer
> renderers
= result
.get(info
);
424 if (renderers
== null) {
425 result
.put(info
, renderers
= new SmartList
<GutterIconRenderer
>());
427 renderers
.add(renderer
);
432 }.execute().throwException();
433 return ContainerUtil
.concat(result
.values());
436 public PsiClass
addClass(@NotNull @NonNls final String classText
) throws IOException
{
437 final PsiClass aClass
= ((PsiJavaFile
)PsiFileFactory
.getInstance(getProject()).createFileFromText("a.java", classText
)).getClasses()[0];
438 final String qName
= aClass
.getQualifiedName();
439 assert qName
!= null;
441 final VirtualFile root
= ModuleRootManager
.getInstance(myProjectFixture
.getModule()).getSourceRoots()[0];
442 final VirtualFile dir
= VfsUtil
.createDirectories(root
.getPath() + "/" + StringUtil
.getPackageName(qName
).replace('.', '/'));
443 final VirtualFile virtualFile
= dir
.createChildData(this, StringUtil
.getShortName(qName
) + ".java");
444 VfsUtil
.saveText(virtualFile
, classText
);
445 myAddedClasses
.add(virtualFile
);
446 return ((PsiJavaFile
)getPsiManager().findFile(virtualFile
)).getClasses()[0];
449 public <T
> void registerExtension(final ExtensionsArea area
, final ExtensionPointName
<T
> epName
, final T extension
) {
450 final ExtensionPoint
<T
> extensionPoint
= area
.getExtensionPoint(epName
);
451 extensionPoint
.registerExtension(extension
);
452 disposeOnTearDown(new Disposable() {
453 public void dispose() {
454 extensionPoint
.unregisterExtension(extension
);
459 public PsiManager
getPsiManager() {
464 protected Editor
getCompletionEditor() {
465 return InjectedLanguageUtil
.getEditorForInjectedLanguage(myEditor
, myFile
);
470 public LookupItem
[] completeBasic() {
471 return new WriteCommandAction
<LookupItem
[]>(getProject()) {
472 protected void run(final Result
<LookupItem
[]> result
) throws Throwable
{
473 new CodeCompletionAction() {
474 public CodeInsightActionHandler
getHandler() {
475 return new CodeCompletionHandler() {
476 protected PsiFile
createFileCopy(final PsiFile file
) {
477 final PsiFile copy
= super.createFileCopy(file
);
478 if (myFileContext
!= null) {
479 final PsiElement contextCopy
= myFileContext
.copy();
480 final PsiFile containingFile
= contextCopy
.getContainingFile();
481 if (containingFile
instanceof PsiFileImpl
) {
482 ((PsiFileImpl
)containingFile
).setOriginalFile(myFileContext
.getContainingFile());
484 setContext(copy
, contextCopy
);
489 protected Lookup
showLookup(final Project project
, final Editor editor
, final LookupItem
[] items
, final String prefix
, final LookupData data
,
491 final String bottomText
) {
492 result
.setResult(items
);
493 return super.showLookup(project
, editor
, items
, prefix
, data
, file
, bottomText
);
497 }.actionPerformedImpl(getProject(), InjectedLanguageUtil
.getEditorForInjectedLanguage(myEditor
, myFile
));
500 }.execute().getResultObject();
503 public void checkResult(final String text
) throws IOException
{
504 PsiDocumentManager
.getInstance(getProject()).commitAllDocuments();
505 checkResult("TEXT", false, SelectionAndCaretMarkupLoader
.fromText(text
, getProject()), myFile
.getText());
508 public void checkResultByFile(final String filePath
) throws Throwable
{
509 new WriteCommandAction
.Simple(myProjectFixture
.getProject()) {
511 protected void run() throws Throwable
{
512 checkResultByFile(filePath
, myFile
, false);
514 }.execute().throwException();
517 public void checkResultByFile(final String filePath
, final String expectedFile
, final boolean ignoreWhitespaces
) throws Throwable
{
519 new WriteCommandAction
.Simple(myProjectFixture
.getProject()) {
521 protected void run() throws Throwable
{
522 String fullPath
= getTempDirPath() + "/" + filePath
;
523 final VirtualFile copy
= LocalFileSystem
.getInstance().refreshAndFindFileByPath(fullPath
.replace(File
.separatorChar
, '/'));
524 assert copy
!= null : "file not found: " + fullPath
;
525 final PsiFile psiFile
= myPsiManager
.findFile(copy
);
526 assert psiFile
!= null;
527 checkResultByFile(expectedFile
, psiFile
, ignoreWhitespaces
);
529 }.execute().throwException();
532 public void setUp() throws Exception
{
535 final String testDataPath
= getTestDataPath();
536 if (testDataPath
!= null) {
537 FileUtil
.copyDir(new File(testDataPath
), new File(getTempDirPath()), false);
539 myProjectFixture
.setUp();
540 myTempDirFixture
.setUp();
541 myPsiManager
= (PsiManagerImpl
)PsiManager
.getInstance(getProject());
542 configureInspections(myInspections
== null ?
new LocalInspectionTool
[0] : myInspections
);
545 private void enableInspectionTool(LocalInspectionTool tool
){
546 final String shortName
= tool
.getShortName();
547 final HighlightDisplayKey key
= HighlightDisplayKey
.find(shortName
);
549 HighlightDisplayKey
.register(shortName
, tool
.getDisplayName(), tool
.getID());
551 myAvailableTools
.put(shortName
, tool
);
552 myAvailableLocalTools
.put(shortName
, new LocalInspectionToolWrapper(tool
));
555 private void configureInspections(final LocalInspectionTool
[] tools
) {
556 for (LocalInspectionTool tool
: tools
) {
557 enableInspectionTool(tool
);
560 final InspectionProfileImpl profile
= new InspectionProfileImpl(PROFILE
) {
561 public ModifiableModel
getModifiableModel() {
566 public InspectionProfileEntry
[] getInspectionTools() {
567 final Collection
<LocalInspectionToolWrapper
> tools
= myAvailableLocalTools
.values();
568 return tools
.toArray(new LocalInspectionToolWrapper
[tools
.size()]);
571 public boolean isToolEnabled(HighlightDisplayKey key
) {
572 return key
!= null && key
.toString() != null && myAvailableTools
!= null && myAvailableTools
.containsKey(key
.toString());
575 public HighlightDisplayLevel
getErrorLevel(HighlightDisplayKey key
) {
576 final LocalInspectionTool localInspectionTool
= myAvailableTools
.get(key
.toString());
577 return localInspectionTool
!= null ? localInspectionTool
.getDefaultLevel() : HighlightDisplayLevel
.WARNING
;
580 public InspectionTool
getInspectionTool(String shortName
) {
581 return myAvailableLocalTools
.get(shortName
);
584 final InspectionProfileManager inspectionProfileManager
= InspectionProfileManager
.getInstance();
585 inspectionProfileManager
.addProfile(profile
);
586 Disposer
.register(getProject(), new Disposable() {
587 public void dispose() {
588 inspectionProfileManager
.deleteProfile(PROFILE
);
591 inspectionProfileManager
.setRootProfile(profile
.getName());
592 InspectionProjectProfileManager
.getInstance(getProject()).updateProfile(profile
);
595 public void tearDown() throws Exception
{
596 LookupManager
.getInstance(getProject()).hideActiveLookup();
598 FileEditorManager editorManager
= FileEditorManager
.getInstance(getProject());
599 VirtualFile
[] openFiles
= editorManager
.getOpenFiles();
600 for (VirtualFile openFile
: openFiles
) {
601 editorManager
.closeFile(openFile
);
604 myProjectFixture
.tearDown();
605 myTempDirFixture
.tearDown();
610 private int configureByFilesInner(@NonNls String
... filePaths
) throws IOException
{
614 for (int i
= filePaths
.length
- 1; i
>= 0; i
--) {
615 String filePath
= filePaths
[i
];
616 int fileOffset
= configureByFileInner(filePath
);
617 if (fileOffset
> 0) {
624 public void configureByFile(final String file
) throws IOException
{
625 new WriteCommandAction
.Simple(getProject()) {
626 protected void run() throws Throwable
{
627 configureByFileInner(file
);
632 public void configureByFiles(@NonNls final String
... files
) throws Throwable
{
633 new WriteCommandAction
.Simple(getProject()) {
634 protected void run() throws Throwable
{
635 configureByFilesInner(files
);
640 public PsiFile
configureByText(final FileType fileType
, @NonNls final String text
) throws Throwable
{
641 final String extension
= fileType
.getDefaultExtension();
642 final File tempFile
= File
.createTempFile("aaa", "." + extension
, new File(getTempDirPath()));
643 final FileTypeManager fileTypeManager
= FileTypeManager
.getInstance();
644 if (fileTypeManager
.getFileTypeByExtension(extension
) != fileType
) {
645 fileTypeManager
.associateExtension(fileType
, extension
);
647 final VirtualFile vFile
= LocalFileSystem
.getInstance().refreshAndFindFileByIoFile(tempFile
);
648 VfsUtil
.saveText(vFile
, text
);
649 configureInner(vFile
, SelectionAndCaretMarkupLoader
.fromFile(vFile
, getProject()));
653 public Document
getDocument(final PsiFile file
) {
654 return PsiDocumentManager
.getInstance(getProject()).getDocument(file
);
657 public void setFileContext(@Nullable final PsiElement context
) {
658 myFileContext
= context
;
659 setContext(myFile
, context
);
665 * @return caret offset or -1 if caret marker does not present
666 * @throws IOException
668 private int configureByFileInner(@NonNls String filePath
) throws IOException
{
669 return configureByFileInner(findFile(filePath
));
672 private int configureByFileInner(final VirtualFile copy
) throws IOException
{
673 return configureInner(copy
, SelectionAndCaretMarkupLoader
.fromFile(copy
, getProject()));
676 private int configureInner(final VirtualFile copy
, final SelectionAndCaretMarkupLoader loader
) {
678 final OutputStream outputStream
= copy
.getOutputStream(null, 0, 0);
679 outputStream
.write(loader
.newFileText
.getBytes());
680 outputStream
.close();
682 catch (IOException e
) {
683 throw new RuntimeException(e
);
685 myFile
= myPsiManager
.findFile(copy
);
686 setContext(myFile
, myFileContext
);
688 myEditor
= createEditor(copy
);
689 assert myEditor
!= null;
690 if (loader
.caretMarker
!= null) {
691 offset
= loader
.caretMarker
.getStartOffset();
692 myEditor
.getCaretModel().moveToOffset(offset
);
694 if (loader
.selStartMarker
!= null && loader
.selEndMarker
!= null) {
695 myEditor
.getSelectionModel().setSelection(loader
.selStartMarker
.getStartOffset(), loader
.selEndMarker
.getStartOffset());
700 private static void setContext(final PsiFile file
, final PsiElement context
) {
701 if (file
!= null && context
!= null) {
702 file
.putUserData(FileContextUtil
.INJECTED_IN_ELEMENT
, new SmartPsiElementPointer() {
703 public PsiElement
getElement() {
710 private VirtualFile
findFile(final String filePath
) {
711 String fullPath
= getTempDirPath() + "/" + filePath
;
713 final VirtualFile copy
= LocalFileSystem
.getInstance().refreshAndFindFileByPath(fullPath
.replace(File
.separatorChar
, '/'));
714 assert copy
!= null: "file " + fullPath
+ " not found";
719 private Editor
createEditor(VirtualFile file
) {
720 final Project project
= getProject();
721 final FileEditorManager instance
= FileEditorManager
.getInstance(project
);
722 if (file
.getFileType().isBinary()) {
725 return instance
.openTextEditor(new OpenFileDescriptor(project
, file
, 0), false);
728 private void collectAndCheckHighlightings(boolean checkWarnings
, boolean checkInfos
, boolean checkWeakWarnings
, Ref
<Long
> duration
)
730 final Project project
= getProject();
731 ExpectedHighlightingData data
= new ExpectedHighlightingData(myEditor
.getDocument(), checkWarnings
, checkWeakWarnings
, checkInfos
, myFile
);
733 PsiDocumentManager
.getInstance(project
).commitAllDocuments();
735 ((PsiFileImpl
)myFile
).calcTreeElement(); //to load text
737 //to initialize caches
738 myPsiManager
.getCacheManager().getFilesWithWord(XXX
, UsageSearchContext
.IN_COMMENTS
, GlobalSearchScope
.allScope(project
), true);
739 VirtualFileFilter javaFilesFilter
= new VirtualFileFilter() {
740 public boolean accept(VirtualFile file
) {
741 if (myAddedClasses
.contains(file
)) return false;
743 FileType fileType
= FileTypeManager
.getInstance().getFileTypeByFile(file
);
744 return fileType
== StdFileTypes
.JAVA
|| fileType
== StdFileTypes
.CLASS
;
748 JavaPsiFacadeEx
.getInstanceEx(project
).setAssertOnFileLoadingFilter(javaFilesFilter
); // check repository work
750 final long start
= System
.currentTimeMillis();
751 // ProfilingUtil.startCPUProfiling();
752 Collection
<HighlightInfo
> infos
= doHighlighting();
753 duration
.set(System
.currentTimeMillis() - start
);
754 // ProfilingUtil.captureCPUSnapshot("testing");
756 JavaPsiFacadeEx
.getInstanceEx(project
).setAssertOnFileLoadingFilter(VirtualFileFilter
.NONE
);
758 data
.checkResult(infos
, myEditor
.getDocument().getText());
762 private Collection
<HighlightInfo
> doHighlighting() {
764 final Project project
= myProjectFixture
.getProject();
766 PsiDocumentManager
.getInstance(project
).commitAllDocuments();
768 Document document
= myEditor
.getDocument();
769 GeneralHighlightingPass action1
= new GeneralHighlightingPass(project
, myFile
, document
, 0, myFile
.getTextLength(), true);
770 action1
.doCollectInformation(new MockProgressIndicator());
771 Collection
<HighlightInfo
> highlights1
= action1
.getHighlights();
773 PostHighlightingPass action2
= new PostHighlightingPass(project
, myFile
, myEditor
, 0, myFile
.getTextLength());
774 action2
.doCollectInformation(new MockProgressIndicator());
775 Collection
<HighlightInfo
> highlights2
= action2
.getHighlights();
777 Collection
<HighlightInfo
> highlights3
= null;
778 if (myAvailableTools
.size() > 0) {
779 LocalInspectionsPass inspectionsPass
= new LocalInspectionsPass(myFile
, myEditor
.getDocument(), 0, myFile
.getTextLength());
780 inspectionsPass
.doCollectInformation(new MockProgressIndicator());
781 highlights3
= inspectionsPass
.getHighlights();
784 ArrayList
<HighlightInfo
> list
= new ArrayList
<HighlightInfo
>();
785 list
.addAll(highlights1
);
786 list
.addAll(highlights2
);
787 if (highlights3
!= null) {
788 list
.addAll(highlights3
);
793 private String
getTestDataPath() {
794 return myTestDataPath
;
797 public Project
getProject() {
798 return myProjectFixture
.getProject();
801 public Editor
getEditor() {
805 public PsiFile
getFile() {
809 public static List
<IntentionAction
> getAvailableIntentions(final Project project
, final Collection
<HighlightInfo
> infos
, final int offset
,
810 final Editor editor
, final PsiFile file
) {
811 final List
<IntentionAction
> availableActions
= new ArrayList
<IntentionAction
>();
813 for (HighlightInfo info
:infos
) {
814 if (info
.quickFixActionRanges
!= null) {
815 for (Pair
<HighlightInfo
.IntentionActionDescriptor
, TextRange
> pair
: info
.quickFixActionRanges
) {
816 if (offset
> 0 && !pair
.getSecond().contains(offset
)) {
819 final HighlightInfo
.IntentionActionDescriptor actionDescriptor
= pair
.first
;
820 final IntentionAction action
= actionDescriptor
.getAction();
821 if (action
.isAvailable(project
, editor
, file
)) {
822 availableActions
.add(action
);
823 final PsiElement element
= file
.findElementAt(editor
.getCaretModel().getOffset());
824 assert element
!= null;
825 final List
<IntentionAction
> actions
= actionDescriptor
.getOptions(element
);
826 if (actions
!= null) {
827 for (IntentionAction intentionAction
: actions
) {
828 if (intentionAction
.isAvailable(project
, editor
, file
)) {
829 availableActions
.add(intentionAction
);
838 for (IntentionAction intentionAction
: IntentionManager
.getInstance().getIntentionActions()) {
839 if (intentionAction
.isAvailable(project
, editor
, file
)) {
840 availableActions
.add(intentionAction
);
843 return availableActions
;
846 static class SelectionAndCaretMarkupLoader
{
847 final String newFileText
;
848 final RangeMarker caretMarker
;
849 final RangeMarker selStartMarker
;
850 final RangeMarker selEndMarker
;
852 static SelectionAndCaretMarkupLoader
fromFile(String path
, Project project
) throws IOException
{
853 return new SelectionAndCaretMarkupLoader(StringUtil
.convertLineSeparators(new String(FileUtil
.loadFileText(new File(path
)))), project
);
855 static SelectionAndCaretMarkupLoader
fromFile(VirtualFile file
, Project project
) throws IOException
{
856 return new SelectionAndCaretMarkupLoader(StringUtil
.convertLineSeparators(new String(VfsUtil
.loadText(file
))), project
);
859 static SelectionAndCaretMarkupLoader
fromText(String text
, Project project
) throws IOException
{
860 return new SelectionAndCaretMarkupLoader(text
, project
);
863 private SelectionAndCaretMarkupLoader(String fileText
, Project project
) throws IOException
{
864 final Document document
= EditorFactory
.getInstance().createDocument(fileText
);
866 int caretIndex
= fileText
.indexOf(CARET_MARKER
);
867 int selStartIndex
= fileText
.indexOf(SELECTION_START_MARKER
);
868 int selEndIndex
= fileText
.indexOf(SELECTION_END_MARKER
);
870 caretMarker
= caretIndex
>= 0 ? document
.createRangeMarker(caretIndex
, caretIndex
) : null;
871 selStartMarker
= selStartIndex
>= 0 ? document
.createRangeMarker(selStartIndex
, selStartIndex
) : null;
872 selEndMarker
= selEndIndex
>= 0 ? document
.createRangeMarker(selEndIndex
, selEndIndex
) : null;
874 new WriteCommandAction(project
) {
875 protected void run(Result result
) throws Throwable
{
876 if (caretMarker
!= null) {
877 document
.deleteString(caretMarker
.getStartOffset(), caretMarker
.getStartOffset() + CARET_MARKER
.length());
879 if (selStartMarker
!= null) {
880 document
.deleteString(selStartMarker
.getStartOffset(), selStartMarker
.getStartOffset() + SELECTION_START_MARKER
.length());
882 if (selEndMarker
!= null) {
883 document
.deleteString(selEndMarker
.getStartOffset(), selEndMarker
.getStartOffset() + SELECTION_END_MARKER
.length());
888 newFileText
= document
.getText();
892 private void checkResultByFile(@NonNls String expectedFile
,
893 @NotNull PsiFile originalFile
,
894 boolean stripTrailingSpaces
) throws IOException
{
895 PsiDocumentManager
.getInstance(getProject()).commitAllDocuments();
896 checkResult(expectedFile
, stripTrailingSpaces
, SelectionAndCaretMarkupLoader
.fromFile(getTestDataPath() + "/" + expectedFile
, getProject()), originalFile
.getText());
899 private void checkResult(final String expectedFile
,
900 final boolean stripTrailingSpaces
,
901 final SelectionAndCaretMarkupLoader markupLoader
,
903 Project project
= myProjectFixture
.getProject();
905 project
.getComponent(PostprocessReformattingAspect
.class).doPostponedFormatting();
906 if (stripTrailingSpaces
) {
907 ((DocumentEx
)myEditor
.getDocument()).stripTrailingSpaces(false);
910 PsiDocumentManager
.getInstance(project
).commitAllDocuments();
912 SelectionAndCaretMarkupLoader loader
= markupLoader
;
913 String newFileText1
= loader
.newFileText
;
914 if (stripTrailingSpaces
) {
915 Document document1
= EditorFactory
.getInstance().createDocument(loader
.newFileText
);
916 ((DocumentEx
)document1
).stripTrailingSpaces(false);
917 newFileText1
= document1
.getText();
920 actualText
= StringUtil
.convertLineSeparators(actualText
, "\n");
922 //noinspection HardCodedStringLiteral
923 TestCase
.assertEquals( "Text mismatch in file " + expectedFile
, newFileText1
, actualText
);
925 if (loader
.caretMarker
!= null) {
926 int caretLine
= StringUtil
.offsetToLineNumber(loader
.newFileText
, loader
.caretMarker
.getStartOffset());
927 int caretCol
= loader
.caretMarker
.getStartOffset() - StringUtil
.lineColToOffset(loader
.newFileText
, caretLine
, 0);
929 TestCase
.assertEquals("caretLine", caretLine
+ 1, myEditor
.getCaretModel().getLogicalPosition().line
+ 1);
930 TestCase
.assertEquals("caretColumn", caretCol
+ 1, myEditor
.getCaretModel().getLogicalPosition().column
+ 1);
933 if (loader
.selStartMarker
!= null && loader
.selEndMarker
!= null) {
934 int selStartLine
= StringUtil
.offsetToLineNumber(loader
.newFileText
, loader
.selStartMarker
.getStartOffset());
935 int selStartCol
= loader
.selStartMarker
.getStartOffset() - StringUtil
.lineColToOffset(loader
.newFileText
, selStartLine
, 0);
937 int selEndLine
= StringUtil
.offsetToLineNumber(loader
.newFileText
, loader
.selEndMarker
.getEndOffset());
938 int selEndCol
= loader
.selEndMarker
.getEndOffset() - StringUtil
.lineColToOffset(loader
.newFileText
, selEndLine
, 0);
940 TestCase
.assertEquals("selectionStartLine", selStartLine
+ 1,
941 StringUtil
.offsetToLineNumber(loader
.newFileText
, myEditor
.getSelectionModel().getSelectionStart()) + 1);
943 TestCase
.assertEquals("selectionStartCol", selStartCol
+ 1, myEditor
.getSelectionModel().getSelectionStart() -
944 StringUtil
.lineColToOffset(loader
.newFileText
, selStartLine
, 0) + 1);
946 TestCase
.assertEquals("selectionEndLine", selEndLine
+ 1,
947 StringUtil
.offsetToLineNumber(loader
.newFileText
, myEditor
.getSelectionModel().getSelectionEnd()) + 1);
949 TestCase
.assertEquals("selectionEndCol", selEndCol
+ 1,
950 myEditor
.getSelectionModel().getSelectionEnd() - StringUtil
.lineColToOffset(loader
.newFileText
, selEndLine
, 0) + 1);
953 TestCase
.assertTrue("has no selection", !myEditor
.getSelectionModel().hasSelection());