b24c40004be3e890cedde0b2515e5b145fe362ca
[idea/community.git] / platform / testFramework / src / com / intellij / testFramework / fixtures / impl / CodeInsightTestFixtureImpl.java
1 /*
2  * Copyright 2000-2016 JetBrains s.r.o.
3  *
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
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
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.
15  */
16 package com.intellij.testFramework.fixtures.impl;
17
18 import com.intellij.analysis.AnalysisScope;
19 import com.intellij.codeHighlighting.RainbowHighlighter;
20 import com.intellij.codeInsight.TargetElementUtil;
21 import com.intellij.codeInsight.completion.CodeCompletionHandlerBase;
22 import com.intellij.codeInsight.completion.CompletionProgressIndicator;
23 import com.intellij.codeInsight.completion.CompletionType;
24 import com.intellij.codeInsight.daemon.DaemonCodeAnalyzer;
25 import com.intellij.codeInsight.daemon.DaemonCodeAnalyzerSettings;
26 import com.intellij.codeInsight.daemon.GutterMark;
27 import com.intellij.codeInsight.daemon.impl.*;
28 import com.intellij.codeInsight.folding.CodeFoldingManager;
29 import com.intellij.codeInsight.highlighting.actions.HighlightUsagesAction;
30 import com.intellij.codeInsight.intention.IntentionAction;
31 import com.intellij.codeInsight.intention.impl.IntentionListStep;
32 import com.intellij.codeInsight.intention.impl.ShowIntentionActionsHandler;
33 import com.intellij.codeInsight.lookup.Lookup;
34 import com.intellij.codeInsight.lookup.LookupElement;
35 import com.intellij.codeInsight.lookup.LookupManager;
36 import com.intellij.codeInsight.lookup.impl.LookupImpl;
37 import com.intellij.codeInspection.InspectionProfileEntry;
38 import com.intellij.codeInspection.InspectionToolProvider;
39 import com.intellij.codeInspection.LocalInspectionTool;
40 import com.intellij.codeInspection.ex.InspectionManagerEx;
41 import com.intellij.codeInspection.ex.InspectionProfileImpl;
42 import com.intellij.codeInspection.ex.InspectionToolWrapper;
43 import com.intellij.facet.Facet;
44 import com.intellij.facet.FacetManager;
45 import com.intellij.find.FindManager;
46 import com.intellij.find.findUsages.FindUsagesHandler;
47 import com.intellij.find.findUsages.FindUsagesOptions;
48 import com.intellij.find.impl.FindManagerImpl;
49 import com.intellij.ide.startup.StartupManagerEx;
50 import com.intellij.ide.startup.impl.StartupManagerImpl;
51 import com.intellij.ide.structureView.StructureViewBuilder;
52 import com.intellij.ide.structureView.newStructureView.StructureViewComponent;
53 import com.intellij.injected.editor.DocumentWindow;
54 import com.intellij.injected.editor.EditorWindow;
55 import com.intellij.internal.DumpLookupElementWeights;
56 import com.intellij.lang.LanguageStructureViewBuilder;
57 import com.intellij.lang.annotation.HighlightSeverity;
58 import com.intellij.openapi.Disposable;
59 import com.intellij.openapi.actionSystem.*;
60 import com.intellij.openapi.actionSystem.ex.ActionManagerEx;
61 import com.intellij.openapi.application.AccessToken;
62 import com.intellij.openapi.application.ApplicationManager;
63 import com.intellij.openapi.application.Result;
64 import com.intellij.openapi.application.WriteAction;
65 import com.intellij.openapi.command.CommandProcessor;
66 import com.intellij.openapi.command.WriteCommandAction;
67 import com.intellij.openapi.editor.*;
68 import com.intellij.openapi.editor.actionSystem.DocCommandGroupId;
69 import com.intellij.openapi.editor.actionSystem.EditorActionManager;
70 import com.intellij.openapi.editor.ex.EditorEx;
71 import com.intellij.openapi.editor.ex.util.EditorUtil;
72 import com.intellij.openapi.editor.impl.DocumentImpl;
73 import com.intellij.openapi.editor.impl.DocumentMarkupModel;
74 import com.intellij.openapi.editor.markup.RangeHighlighter;
75 import com.intellij.openapi.editor.markup.TextAttributes;
76 import com.intellij.openapi.extensions.ExtensionPoint;
77 import com.intellij.openapi.extensions.ExtensionPointName;
78 import com.intellij.openapi.extensions.ExtensionsArea;
79 import com.intellij.openapi.fileEditor.*;
80 import com.intellij.openapi.fileEditor.impl.text.TextEditorProvider;
81 import com.intellij.openapi.fileTypes.FileType;
82 import com.intellij.openapi.fileTypes.FileTypeManager;
83 import com.intellij.openapi.module.Module;
84 import com.intellij.openapi.progress.ProcessCanceledException;
85 import com.intellij.openapi.project.DumbService;
86 import com.intellij.openapi.project.Project;
87 import com.intellij.openapi.util.*;
88 import com.intellij.openapi.util.io.FileUtil;
89 import com.intellij.openapi.util.registry.Registry;
90 import com.intellij.openapi.util.registry.RegistryValue;
91 import com.intellij.openapi.util.text.StringUtil;
92 import com.intellij.openapi.vfs.*;
93 import com.intellij.profile.codeInspection.InspectionProjectProfileManager;
94 import com.intellij.psi.*;
95 import com.intellij.psi.impl.DebugUtil;
96 import com.intellij.psi.impl.PsiManagerEx;
97 import com.intellij.psi.impl.PsiManagerImpl;
98 import com.intellij.psi.impl.PsiModificationTrackerImpl;
99 import com.intellij.psi.impl.cache.CacheManager;
100 import com.intellij.psi.impl.cache.impl.todo.TodoIndex;
101 import com.intellij.psi.impl.source.PsiFileImpl;
102 import com.intellij.psi.impl.source.tree.FileElement;
103 import com.intellij.psi.impl.source.tree.injected.InjectedLanguageUtil;
104 import com.intellij.psi.search.GlobalSearchScope;
105 import com.intellij.psi.search.SearchScope;
106 import com.intellij.psi.search.UsageSearchContext;
107 import com.intellij.psi.stubs.StubUpdatingIndex;
108 import com.intellij.psi.util.PsiTreeUtil;
109 import com.intellij.refactoring.move.moveFilesOrDirectories.MoveFilesOrDirectoriesProcessor;
110 import com.intellij.refactoring.rename.*;
111 import com.intellij.rt.execution.junit.FileComparisonFailure;
112 import com.intellij.testFramework.*;
113 import com.intellij.testFramework.fixtures.*;
114 import com.intellij.usageView.UsageInfo;
115 import com.intellij.util.*;
116 import com.intellij.util.containers.ContainerUtil;
117 import com.intellij.util.containers.JBIterable;
118 import com.intellij.util.indexing.FileBasedIndex;
119 import com.intellij.util.ui.UIUtil;
120 import junit.framework.ComparisonFailure;
121 import org.jetbrains.annotations.NotNull;
122 import org.jetbrains.annotations.Nullable;
123 import org.jetbrains.annotations.TestOnly;
124 import org.junit.Assert;
125
126 import javax.swing.*;
127 import java.io.File;
128 import java.io.IOException;
129 import java.util.*;
130
131 /**
132  * @author Dmitry Avdeev
133  */
134 @SuppressWarnings({"TestMethodWithIncorrectSignature", "JUnitTestCaseWithNoTests", "JUnitTestClassNamingConvention", "TestOnlyProblems"})
135 public class CodeInsightTestFixtureImpl extends BaseFixture implements CodeInsightTestFixture {
136   private static final Function<IntentionAction, String> INTENTION_NAME_FUN = intentionAction -> "\"" + intentionAction.getText() + "\"";
137
138   private static final String START_FOLD = "<fold\\stext=\'[^\']*\'(\\sexpand=\'[^\']*\')*>";
139   private static final String END_FOLD = "</fold>";
140   private static final String RAINBOW = "rainbow";
141
142   private final IdeaProjectTestFixture myProjectFixture;
143   private final TempDirTestFixture myTempDirFixture;
144   private PsiManagerImpl myPsiManager;
145   private VirtualFile myFile;
146   private Editor myEditor;
147   private String myTestDataPath;
148   private boolean myEmptyLookup;
149   private VirtualFileFilter myVirtualFileFilter = new FileTreeAccessFilter();
150   private boolean myAllowDirt;
151   private boolean myCaresAboutInjection = true;
152
153   @SuppressWarnings("JUnitTestCaseWithNonTrivialConstructors")
154   public CodeInsightTestFixtureImpl(@NotNull IdeaProjectTestFixture projectFixture, @NotNull TempDirTestFixture tempDirTestFixture) {
155     myProjectFixture = projectFixture;
156     myTempDirFixture = tempDirTestFixture;
157   }
158
159   private static void addGutterIconRenderer(final GutterMark renderer,
160                                             final int offset,
161                                             @NotNull SortedMap<Integer, List<GutterMark>> result) {
162     if (renderer == null) return;
163
164     List<GutterMark> renderers = result.get(offset);
165     if (renderers == null) {
166       result.put(offset, renderers = new SmartList<>());
167     }
168     renderers.add(renderer);
169   }
170
171   private static void removeDuplicatedRangesForInjected(@NotNull List<HighlightInfo> infos) {
172     Collections.sort(infos, (o1, o2) -> {
173       final int i = o2.startOffset - o1.startOffset;
174       return i != 0 ? i : o1.getSeverity().myVal - o2.getSeverity().myVal;
175     });
176     HighlightInfo prevInfo = null;
177     for (Iterator<HighlightInfo> it = infos.iterator(); it.hasNext();) {
178       final HighlightInfo info = it.next();
179       if (prevInfo != null &&
180           info.getSeverity() == HighlightInfoType.SYMBOL_TYPE_SEVERITY &&
181           info.getDescription() == null &&
182           info.startOffset == prevInfo.startOffset &&
183           info.endOffset == prevInfo.endOffset) {
184         it.remove();
185       }
186       prevInfo = info.type == HighlightInfoType.INJECTED_LANGUAGE_FRAGMENT ? info : null;
187     }
188   }
189
190   @NotNull
191   public static List<HighlightInfo> instantiateAndRun(@NotNull PsiFile file,
192                                                       @NotNull Editor editor,
193                                                       @NotNull int[] toIgnore,
194                                                       boolean canChangeDocument) {
195     Project project = file.getProject();
196     ensureIndexesUpToDate(project);
197     DaemonCodeAnalyzerImpl codeAnalyzer = (DaemonCodeAnalyzerImpl)DaemonCodeAnalyzer.getInstance(project);
198     TextEditor textEditor = TextEditorProvider.getInstance().getTextEditor(editor);
199     ProcessCanceledException exception = null;
200     for (int i = 0; i < 1000; i++) {
201       try {
202         List<HighlightInfo> infos = codeAnalyzer.runPasses(file, editor.getDocument(), textEditor, toIgnore, canChangeDocument, null);
203         infos.addAll(DaemonCodeAnalyzerEx.getInstanceEx(project).getFileLevelHighlights(project, file));
204         return infos;
205       }
206       catch (ProcessCanceledException e) {
207         PsiDocumentManager.getInstance(project).commitAllDocuments();
208         UIUtil.dispatchAllInvocationEvents();
209         exception = e;
210       }
211     }
212     // unable to highlight after 100 retries
213     throw exception;
214   }
215
216   public static void ensureIndexesUpToDate(@NotNull Project project) {
217     if (!DumbService.isDumb(project)) {
218       FileBasedIndex.getInstance().ensureUpToDate(StubUpdatingIndex.INDEX_ID, project, null);
219       FileBasedIndex.getInstance().ensureUpToDate(TodoIndex.NAME, project, null);
220     }
221   }
222
223   @NotNull
224   public static List<IntentionAction> getAvailableIntentions(@NotNull final Editor editor, @NotNull final PsiFile file) {
225     return ApplicationManager.getApplication().runReadAction(new Computable<List<IntentionAction>>() {
226       @Override
227       public List<IntentionAction> compute() {
228         return doGetAvailableIntentions(editor, file);
229       }
230     });
231   }
232
233   @NotNull
234   private static List<IntentionAction> doGetAvailableIntentions(@NotNull Editor editor, @NotNull PsiFile file) {
235     ShowIntentionsPass.IntentionsInfo intentions = new ShowIntentionsPass.IntentionsInfo();
236     ShowIntentionsPass.getActionsToShow(editor, file, intentions, -1);
237
238     List<IntentionAction> result = new ArrayList<>();
239     IntentionListStep intentionListStep = new IntentionListStep(null, intentions, editor, file, file.getProject());
240     for (Map.Entry<IntentionAction, List<IntentionAction>> entry : intentionListStep.getActionsWithSubActions().entrySet()) {
241       result.add(entry.getKey());
242       result.addAll(entry.getValue());
243     }
244
245     List<HighlightInfo> infos = DaemonCodeAnalyzerEx.getInstanceEx(file.getProject()).getFileLevelHighlights(file.getProject(), file);
246     for (HighlightInfo info : infos) {
247       for (Pair<HighlightInfo.IntentionActionDescriptor, TextRange> pair : info.quickFixActionRanges) {
248         HighlightInfo.IntentionActionDescriptor actionInGroup = pair.first;
249         if (actionInGroup.getAction().isAvailable(file.getProject(), editor, file)) {
250           result.add(actionInGroup.getAction());
251           List<IntentionAction> options = actionInGroup.getOptions(file, editor);
252           if (options != null) {
253             for (IntentionAction subAction : options) {
254               if (subAction.isAvailable(file.getProject(), editor, file)) {
255                 result.add(subAction);
256               }
257             }
258           }
259         }
260       }
261     }
262     return result;
263   }
264
265   @NotNull
266   @Override
267   public String getTempDirPath() {
268     return myTempDirFixture.getTempDirPath();
269   }
270
271   @NotNull
272   @Override
273   public TempDirTestFixture getTempDirFixture() {
274     return myTempDirFixture;
275   }
276
277   @NotNull
278   @Override
279   public VirtualFile copyFileToProject(@NotNull String sourcePath) {
280     return copyFileToProject(sourcePath, sourcePath);
281   }
282
283   @NotNull
284   @Override
285   public VirtualFile copyFileToProject(@NotNull String sourcePath, @NotNull String targetPath) {
286     String testDataPath = getTestDataPath();
287     File sourceFile = FileUtil.findFirstThatExist(testDataPath + '/' + sourcePath, sourcePath);
288     VirtualFile targetFile = myTempDirFixture.getFile(targetPath);
289
290     if (sourceFile == null && targetFile != null && targetPath.equals(sourcePath)) {
291       return targetFile;
292     }
293
294     Assert.assertNotNull("Cannot find source file: " + sourcePath + "; test data path: " + testDataPath, sourceFile);
295     Assert.assertTrue("Not a file: " + sourceFile, sourceFile.isFile());
296
297     if (targetFile == null) {
298       targetFile = myTempDirFixture.createFile(targetPath);
299       VfsTestUtil.assertFilePathEndsWithCaseSensitivePath(targetFile, sourcePath);
300       targetFile.putUserData(VfsTestUtil.TEST_DATA_FILE_PATH, sourceFile.getAbsolutePath());
301     }
302
303     final File _source = sourceFile;
304     final VirtualFile _target = targetFile;
305     new WriteAction() {
306       @Override
307       protected void run(@NotNull Result result) throws IOException {
308         _target.setBinaryContent(FileUtil.loadFileBytes(_source));
309       }
310     }.execute();
311
312     return targetFile;
313   }
314
315   @NotNull
316   @Override
317   public VirtualFile copyDirectoryToProject(@NotNull String sourcePath, @NotNull String targetPath) {
318     final String testDataPath = getTestDataPath();
319
320     final File fromFile = new File(testDataPath + "/" + sourcePath);
321     if (myTempDirFixture instanceof LightTempDirTestFixtureImpl) {
322       return myTempDirFixture.copyAll(fromFile.getPath(), targetPath);
323     }
324     final File targetFile = new File(getTempDirPath() + "/" + targetPath);
325     try {
326       FileUtil.copyDir(fromFile, targetFile);
327     }
328     catch (IOException e) {
329       throw new RuntimeException(e);
330     }
331
332     final VirtualFile file = LocalFileSystem.getInstance().refreshAndFindFileByIoFile(targetFile);
333     Assert.assertNotNull(file);
334     file.refresh(false, true);
335     return file;
336   }
337
338   @Override
339   public void enableInspections(@NotNull InspectionProfileEntry... inspections) {
340     assertInitialized();
341     InspectionsKt.enableInspectionTools(getProject(), getTestRootDisposable(), inspections);
342   }
343
344   @Override
345   public void enableInspections(@NotNull final Class<? extends LocalInspectionTool>... inspections) {
346     enableInspections(Arrays.asList(inspections));
347   }
348
349   @Override
350   public void enableInspections(@NotNull Collection<Class<? extends LocalInspectionTool>> inspections) {
351     List<InspectionProfileEntry> tools = InspectionTestUtil.instantiateTools(inspections);
352     enableInspections(tools.toArray(new LocalInspectionTool[tools.size()]));
353   }
354
355   @Override
356   public void disableInspections(@NotNull InspectionProfileEntry... inspections) {
357     InspectionProfileImpl profile = (InspectionProfileImpl)InspectionProjectProfileManager.getInstance(getProject()).getCurrentProfile();
358     for (InspectionProfileEntry inspection : inspections) {
359       profile.disableTool(inspection.getShortName(), getProject());
360     }
361   }
362
363   @Override
364     public void enableInspections(@NotNull InspectionToolProvider... providers) {
365       List<Class<? extends LocalInspectionTool>> classes = JBIterable.of(providers)
366         .flatten((o) -> Arrays.asList(o.getInspectionClasses()))
367         .transform((Function<Class, Class<? extends LocalInspectionTool>>)o ->
368           LocalInspectionTool.class.isAssignableFrom(o) ? (Class<? extends LocalInspectionTool>) o : null)
369         .filter(Conditions.notNull())
370         .toList();
371       enableInspections(classes);
372     }
373
374   @Override
375   public long testHighlighting(final boolean checkWarnings,
376                                final boolean checkInfos,
377                                final boolean checkWeakWarnings,
378                                @NotNull final String... filePaths) {
379     if (filePaths.length > 0) {
380       configureByFilesInner(filePaths);
381     }
382     try {
383       return collectAndCheckHighlighting(checkWarnings, checkInfos, checkWeakWarnings);
384     }
385     catch (Exception e) {
386       throw new RuntimeException(e);
387     }
388   }
389
390   @Override
391   public long testHighlightingAllFiles(final boolean checkWarnings,
392                                        final boolean checkInfos,
393                                        final boolean checkWeakWarnings,
394                                        @NotNull final String... filePaths) {
395     final ArrayList<VirtualFile> files = new ArrayList<>();
396     for (String path : filePaths) {
397       files.add(copyFileToProject(path));
398     }
399     return testHighlightingAllFiles(checkWarnings, checkInfos, checkWeakWarnings, VfsUtilCore.toVirtualFileArray(files));
400   }
401
402   @Override
403   public long testHighlightingAllFiles(final boolean checkWarnings,
404                                        final boolean checkInfos,
405                                        final boolean checkWeakWarnings,
406                                        @NotNull final VirtualFile... files) {
407     return collectAndCheckHighlightings(checkWarnings, checkInfos, checkWeakWarnings, files);
408   }
409
410   private long collectAndCheckHighlightings(final boolean checkWarnings,
411                                             final boolean checkInfos,
412                                             final boolean checkWeakWarnings,
413                                             @NotNull VirtualFile[] files) {
414     final List<Trinity<PsiFile, Editor, ExpectedHighlightingData>> datas =
415       ContainerUtil.map2List(files, file -> {
416         final PsiFile psiFile = myPsiManager.findFile(file);
417         Assert.assertNotNull(psiFile);
418         final Document document = PsiDocumentManager.getInstance(getProject()).getDocument(psiFile);
419         Assert.assertNotNull(document);
420         ExpectedHighlightingData data = new ExpectedHighlightingData(document, checkWarnings, checkWeakWarnings, checkInfos, psiFile);
421         data.init();
422         return Trinity.create(psiFile, createEditor(file), data);
423       });
424     long elapsed = 0;
425     for (Trinity<PsiFile, Editor, ExpectedHighlightingData> trinity : datas) {
426       myEditor = trinity.second;
427       myFile = trinity.first.getVirtualFile();
428       elapsed += collectAndCheckHighlighting(trinity.third);
429     }
430     return elapsed;
431   }
432
433   @Override
434   public long checkHighlighting(final boolean checkWarnings, final boolean checkInfos, final boolean checkWeakWarnings) {
435     return checkHighlighting(checkWarnings, checkInfos, checkWeakWarnings, false);
436   }
437
438   @Override
439   public long checkHighlighting(final boolean checkWarnings, final boolean checkInfos, final boolean checkWeakWarnings, boolean ignoreExtraHighlighting) {
440     try {
441       return collectAndCheckHighlighting(checkWarnings, checkInfos, checkWeakWarnings, ignoreExtraHighlighting);
442     }
443     catch (Exception e) {
444       throw new RuntimeException(e);
445     }
446   }
447
448   @Override
449   public long checkHighlighting() {
450     return checkHighlighting(true, false, true);
451   }
452
453   @Override
454   public long testHighlighting(@NotNull final String... filePaths) {
455     return testHighlighting(true, false, true, filePaths);
456   }
457
458   @Override
459   public long testHighlighting(final boolean checkWarnings,
460                                final boolean checkInfos,
461                                final boolean checkWeakWarnings,
462                                @NotNull final VirtualFile file) {
463     openFileInEditor(file);
464     try {
465       return collectAndCheckHighlighting(checkWarnings, checkInfos, checkWeakWarnings);
466     }
467     catch (Exception e) {
468       throw new RuntimeException(e);
469     }
470   }
471
472   @NotNull
473   @Override
474   public HighlightTestInfo testFile(@NotNull String... filePath) {
475     return new HighlightTestInfo(getTestRootDisposable(), filePath) {
476       @Override
477       public HighlightTestInfo doTest() {
478         configureByFiles(filePaths);
479         ExpectedHighlightingData data = new ExpectedHighlightingData(myEditor.getDocument(), checkWarnings, checkWeakWarnings, checkInfos, getFile());
480         if (checkSymbolNames) data.checkSymbolNames();
481         data.init();
482         collectAndCheckHighlighting(data);
483         return this;
484       }
485     };
486   }
487
488   @Override
489   public void openFileInEditor(@NotNull final VirtualFile file) {
490     myFile = file;
491     myEditor = createEditor(file);
492   }
493
494   @Override
495   public void testInspection(@NotNull String testDir, @NotNull InspectionToolWrapper toolWrapper) {
496     VirtualFile sourceDir = copyDirectoryToProject(new File(testDir, "src").getPath(), "src");
497     PsiDirectory psiDirectory = getPsiManager().findDirectory(sourceDir);
498     Assert.assertNotNull(psiDirectory);
499
500     AnalysisScope scope = new AnalysisScope(psiDirectory);
501     scope.invalidate();
502
503     GlobalInspectionContextForTests globalContext = InspectionsKt.createGlobalContextForTool(scope, getProject(), Collections.<InspectionToolWrapper<?, ?>>singletonList(toolWrapper));
504
505     InspectionTestUtil.runTool(toolWrapper, scope, globalContext);
506     InspectionTestUtil.compareToolResults(globalContext, toolWrapper, false, new File(getTestDataPath(), testDir).getPath());
507   }
508
509   @Override
510   @Nullable
511   public PsiReference getReferenceAtCaretPosition(@NotNull final String... filePaths) {
512     if (filePaths.length > 0) {
513       configureByFilesInner(filePaths);
514     }
515     return getFile().findReferenceAt(myEditor.getCaretModel().getOffset());
516   }
517
518   @Override
519   @NotNull
520   public PsiReference getReferenceAtCaretPositionWithAssertion(@NotNull final String... filePaths) {
521     final PsiReference reference = getReferenceAtCaretPosition(filePaths);
522     Assert.assertNotNull("no reference found at " + myEditor.getCaretModel().getLogicalPosition(), reference);
523     return reference;
524   }
525
526   @Override
527   @NotNull
528   public List<IntentionAction> getAvailableIntentions(@NotNull final String... filePaths) {
529     if (filePaths.length > 0) {
530       configureByFilesInner(filePaths);
531     }
532     return getAvailableIntentions();
533   }
534
535   @Override
536   @NotNull
537   public List<IntentionAction> getAllQuickFixes(@NotNull final String... filePaths) {
538     if (filePaths.length != 0) {
539       configureByFilesInner(filePaths);
540     }
541     List<HighlightInfo> infos = doHighlighting();
542     ArrayList<IntentionAction> actions = new ArrayList<>();
543     for (HighlightInfo info : infos) {
544       if (info.quickFixActionRanges != null) {
545         for (Pair<HighlightInfo.IntentionActionDescriptor, TextRange> pair : info.quickFixActionRanges) {
546           actions.add(pair.getFirst().getAction());
547         }
548       }
549     }
550     return actions;
551   }
552
553   @Override
554   @NotNull
555   public List<IntentionAction> getAvailableIntentions() {
556     doHighlighting();
557     PsiFile file = getFile();
558     Editor editor = getEditor();
559     if (editor instanceof EditorWindow) {
560       editor = ((EditorWindow)editor).getDelegate();
561       file = InjectedLanguageUtil.getTopLevelFile(file);
562     }
563     Assert.assertNotNull(file);
564     return getAvailableIntentions(editor, file);
565   }
566
567   @NotNull
568   @Override
569   public List<IntentionAction> filterAvailableIntentions(@NotNull final String hint) {
570     final List<IntentionAction> availableIntentions = getAvailableIntentions();
571     return ContainerUtil.findAll(availableIntentions, intentionAction -> intentionAction.getText().startsWith(hint));
572   }
573
574   @Override
575   public IntentionAction findSingleIntention(@NotNull final String hint) {
576     final List<IntentionAction> list = filterAvailableIntentions(hint);
577     if (list.isEmpty()) {
578       Assert.fail("\"" + hint + "\" not in [" + StringUtil.join(getAvailableIntentions(), INTENTION_NAME_FUN, ", ") + "]");
579     }
580     else if (list.size() > 1) {
581       Assert.fail("Too many intentions found for \"" + hint + "\": [" + StringUtil.join(list, INTENTION_NAME_FUN, ", ") + "]");
582     }
583     return UsefulTestCase.assertOneElement(list);
584   }
585
586   @Override
587   public IntentionAction getAvailableIntention(@NotNull final String intentionName, @NotNull final String... filePaths) {
588     List<IntentionAction> intentions = getAvailableIntentions(filePaths);
589     IntentionAction action = CodeInsightTestUtil.findIntentionByText(intentions, intentionName);
590     if (action == null) {
591       //noinspection UseOfSystemOutOrSystemErr
592       System.out.println(intentionName + " not found among " + StringUtil.join(intentions, IntentionAction::getText, ","));
593     }
594     return action;
595   }
596
597   @Override
598   public void launchAction(@NotNull final IntentionAction action) {
599     ShowIntentionActionsHandler.chooseActionAndInvoke(getFile(), getEditor(), action, action.getText());
600     UIUtil.dispatchAllInvocationEvents();
601   }
602
603   @Override
604   public void testCompletion(@NotNull String[] filesBefore, @NotNull @TestDataFile String fileAfter) {
605     testCompletionTyping(filesBefore, "", fileAfter);
606   }
607
608   @Override
609   public void testCompletionTyping(@NotNull final String[] filesBefore, @NotNull String toType, @NotNull final String fileAfter) {
610     assertInitialized();
611     configureByFiles(filesBefore);
612     complete(CompletionType.BASIC);
613     type(toType);
614     try {
615       checkResultByFile(fileAfter);
616     }
617     catch (RuntimeException e) {
618       //noinspection UseOfSystemOutOrSystemErr
619       System.out.println("LookupElementStrings = " + getLookupElementStrings());
620       throw e;
621     }
622   }
623
624   protected void assertInitialized() {
625     Assert.assertNotNull("setUp() hasn't been called", myPsiManager);
626   }
627
628   @Override
629   public void testCompletion(@NotNull String fileBefore, @NotNull String fileAfter, @NotNull final String... additionalFiles) {
630     testCompletionTyping(fileBefore, "", fileAfter, additionalFiles);
631   }
632
633   @Override
634   public void testCompletionTyping(@NotNull @TestDataFile String fileBefore,
635                                    @NotNull String toType,
636                                    @NotNull @TestDataFile String fileAfter,
637                                    @NotNull String... additionalFiles) {
638     testCompletionTyping(ArrayUtil.reverseArray(ArrayUtil.append(additionalFiles, fileBefore)), toType, fileAfter);
639   }
640
641   @Override
642   public void testCompletionVariants(@NotNull final String fileBefore, @NotNull final String... expectedItems) {
643     assertInitialized();
644     final List<String> result = getCompletionVariants(fileBefore);
645     Assert.assertNotNull(result);
646     UsefulTestCase.assertSameElements(result, expectedItems);
647   }
648
649   @Override
650   public List<String> getCompletionVariants(@NotNull final String... filesBefore) {
651     assertInitialized();
652     configureByFiles(filesBefore);
653     final LookupElement[] items = complete(CompletionType.BASIC);
654     Assert.assertNotNull("No lookup was shown, probably there was only one lookup element that was inserted automatically", items);
655     return getLookupElementStrings();
656   }
657
658   @Override
659   @Nullable
660   public List<String> getLookupElementStrings() {
661     assertInitialized();
662     final LookupElement[] elements = getLookupElements();
663     if (elements == null) return null;
664
665     return ContainerUtil.map(elements, LookupElement::getLookupString);
666   }
667
668   @Override
669   public void finishLookup(final char completionChar) {
670     CommandProcessor.getInstance().executeCommand(getProject(),
671                                                   () -> ((LookupImpl)LookupManager.getActiveLookup(getEditor())).finishLookup(completionChar), null, null);
672   }
673
674   @Override
675   public void testRename(@NotNull final String fileBefore, @NotNull final String fileAfter, @NotNull final String newName, @NotNull final String... additionalFiles) {
676     assertInitialized();
677     configureByFiles(ArrayUtil.reverseArray(ArrayUtil.append(additionalFiles, fileBefore)));
678     testRename(fileAfter, newName);
679   }
680
681   @Override
682   public void testRename(@NotNull final String fileAfter, @NotNull final String newName) {
683     renameElementAtCaret(newName);
684     checkResultByFile(fileAfter);
685   }
686
687   @Override
688   @NotNull
689   public PsiElement getElementAtCaret() {
690     assertInitialized();
691     Editor editor = getCompletionEditor();
692     int findTargetFlags = TargetElementUtil.REFERENCED_ELEMENT_ACCEPTED | TargetElementUtil.ELEMENT_NAME_ACCEPTED;
693     PsiElement element = TargetElementUtil.findTargetElement(editor, findTargetFlags);
694
695     // if no references found in injected fragment, try outer document
696     if (element == null && editor instanceof EditorWindow) {
697       element = TargetElementUtil.findTargetElement(((EditorWindow)editor).getDelegate(), findTargetFlags);
698     }
699
700     if (element == null) {
701       Assert.fail("element not found in file " + myFile.getName() +
702                   " at caret position offset " + myEditor.getCaretModel().getOffset() +  "," +
703                   " psi structure:\n" + DebugUtil.psiToString(getFile(), true, true));
704     }
705     return element;
706   }
707
708   @Override
709   public void renameElementAtCaret(@NotNull final String newName) {
710     renameElement(getElementAtCaret(), newName);
711   }
712
713   @Override
714   public void renameElementAtCaretUsingHandler(@NotNull final String newName) {
715       final DataContext editorContext = ((EditorEx)myEditor).getDataContext();
716       final DataContext context = new DataContext() {
717         @Override
718         public Object getData(final String dataId) {
719           return PsiElementRenameHandler.DEFAULT_NAME.getName().equals(dataId)
720                  ? newName
721                  : editorContext.getData(dataId);
722         }
723       };
724       final RenameHandler renameHandler = RenameHandlerRegistry.getInstance().getRenameHandler(context);
725       Assert.assertNotNull("No handler for this context", renameHandler);
726
727       renameHandler.invoke(getProject(), myEditor, getFile(), context);
728   }
729
730   @Override
731   public void renameElement(@NotNull final PsiElement element, @NotNull final String newName) {
732     final boolean searchInComments = false;
733     final boolean searchTextOccurrences = false;
734     renameElement(element, newName, searchInComments, searchTextOccurrences);
735   }
736
737   @Override
738   public void renameElement(@NotNull final PsiElement element,
739                             @NotNull final String newName,
740                             final boolean searchInComments,
741                             final boolean searchTextOccurrences) {
742     final PsiElement substitution = RenamePsiElementProcessor.forElement(element).substituteElementToRename(element, myEditor);
743     if (substitution == null) return;
744     new RenameProcessor(getProject(), substitution, newName, searchInComments, searchTextOccurrences).run();
745   }
746
747   @Override
748   public <T extends PsiElement> T findElementByText(@NotNull String text, @NotNull Class<T> elementClass) {
749     int pos = PsiDocumentManager.getInstance(getProject()).getDocument(getFile()).getText().indexOf(text);
750     Assert.assertTrue(text, pos >= 0);
751     return PsiTreeUtil.getParentOfType(getFile().findElementAt(pos), elementClass);
752   }
753
754   @Override
755   public void type(final char c) {
756     assertInitialized();
757     UIUtil.invokeAndWaitIfNeeded(new Runnable() {
758       @Override
759       public void run() {
760         final EditorActionManager actionManager = EditorActionManager.getInstance();
761         if (c == '\b') {
762           performEditorAction(IdeActions.ACTION_EDITOR_BACKSPACE);
763           return;
764         }
765         if (c == '\n') {
766           if (_performEditorAction(IdeActions.ACTION_CHOOSE_LOOKUP_ITEM)) {
767             return;
768           }
769           if (_performEditorAction(IdeActions.ACTION_EDITOR_NEXT_TEMPLATE_VARIABLE)) {
770             return;
771           }
772
773           performEditorAction(IdeActions.ACTION_EDITOR_ENTER);
774           return;
775         }
776         if (c == '\t') {
777           if (_performEditorAction(IdeActions.ACTION_CHOOSE_LOOKUP_ITEM_REPLACE)) {
778             return;
779           }
780           if (_performEditorAction(IdeActions.ACTION_EXPAND_LIVE_TEMPLATE_BY_TAB)) {
781             return;
782           }
783           if (_performEditorAction(IdeActions.ACTION_EDITOR_NEXT_TEMPLATE_VARIABLE)) {
784             return;
785           }
786           if (_performEditorAction(IdeActions.ACTION_EDITOR_TAB)) {
787             return;
788           }
789         }
790         if (c == Lookup.COMPLETE_STATEMENT_SELECT_CHAR) {
791           if (_performEditorAction(IdeActions.ACTION_CHOOSE_LOOKUP_ITEM_COMPLETE_STATEMENT)) {
792             return;
793           }
794         }
795
796         CommandProcessor.getInstance().executeCommand(getProject(), () -> {
797           CommandProcessor.getInstance().setCurrentCommandGroupId(myEditor.getDocument());
798           ActionManagerEx.getInstanceEx().fireBeforeEditorTyping(c, getEditorDataContext());
799           actionManager.getTypedAction().actionPerformed(getEditor(), c, getEditorDataContext());
800         }, null, DocCommandGroupId.noneGroupId(myEditor.getDocument()));
801       }
802     });
803   }
804
805   @NotNull
806   private DataContext getEditorDataContext() {
807     return ((EditorEx)myEditor).getDataContext();
808   }
809
810   @Override
811   public void type(@NotNull String s) {
812     for (int i = 0; i < s.length(); i++) {
813       type(s.charAt(i));
814     }
815   }
816
817   @Override
818   public void performEditorAction(@NotNull final String actionId) {
819     assertInitialized();
820     _performEditorAction(actionId);
821   }
822
823   private boolean _performEditorAction(@NotNull String actionId) {
824     final DataContext dataContext = getEditorDataContext();
825
826     final ActionManagerEx managerEx = ActionManagerEx.getInstanceEx();
827     final AnAction action = managerEx.getAction(actionId);
828     final AnActionEvent event = new AnActionEvent(null, dataContext, ActionPlaces.UNKNOWN, new Presentation(), managerEx, 0);
829
830     return WriteCommandAction.runWriteCommandAction(getProject(), new Computable<Boolean>() {
831       @Override
832       public Boolean compute() {
833         action.update(event);
834
835         if (!event.getPresentation().isEnabled()) {
836           return false;
837         }
838
839         managerEx.fireBeforeActionPerformed(action, dataContext, event);
840
841         action.actionPerformed(event);
842
843         managerEx.fireAfterActionPerformed(action, dataContext, event);
844         return true;
845       }
846     });
847   }
848
849   @NotNull
850   @Override
851   public Presentation testAction(@NotNull AnAction action) {
852     TestActionEvent e = new TestActionEvent(action);
853     action.beforeActionPerformedUpdate(e);
854     if (e.getPresentation().isEnabled() && e.getPresentation().isVisible()) {
855       action.actionPerformed(e);
856     }
857     return e.getPresentation();
858   }
859
860   @NotNull
861   @Override
862   public Collection<UsageInfo> testFindUsages(@NotNull final String... fileNames) {
863     assertInitialized();
864     configureByFiles(fileNames);
865     final PsiElement targetElement = TargetElementUtil
866       .findTargetElement(getEditor(), TargetElementUtil.ELEMENT_NAME_ACCEPTED | TargetElementUtil.REFERENCED_ELEMENT_ACCEPTED);
867     Assert.assertNotNull("Cannot find referenced element", targetElement);
868     return findUsages(targetElement);
869   }
870
871   @NotNull
872   @Override
873   public Collection<UsageInfo> findUsages(@NotNull final PsiElement targetElement) {
874     return findUsages(targetElement, null);
875   }
876
877   @NotNull
878   public Collection<UsageInfo> findUsages(@NotNull final PsiElement targetElement, @Nullable SearchScope scope) {
879     final Project project = getProject();
880     final FindUsagesHandler handler =
881       ((FindManagerImpl)FindManager.getInstance(project)).getFindUsagesManager().getFindUsagesHandler(targetElement, false);
882
883     final CommonProcessors.CollectProcessor<UsageInfo> processor = new CommonProcessors.CollectProcessor<>();
884     Assert.assertNotNull("Cannot find handler for: " + targetElement, handler);
885     final PsiElement[] psiElements = ArrayUtil.mergeArrays(handler.getPrimaryElements(), handler.getSecondaryElements());
886     final FindUsagesOptions options = handler.getFindUsagesOptions(null);
887     if (scope != null) options.searchScope = scope;
888     for (PsiElement psiElement : psiElements) {
889       handler.processElementUsages(psiElement, processor, options);
890     }
891     return processor.getResults();
892   }
893
894   @NotNull
895   @Override
896   public RangeHighlighter[] testHighlightUsages(@NotNull final String... files) {
897     configureByFiles(files);
898     testAction(new HighlightUsagesAction());
899     final Editor editor = getEditor();
900     //final Editor editor = com.intellij.openapi.actionSystem.CommonDataKeys.EDITOR.getData(DataManager.getInstance().getDataContext());
901     //assert editor != null;
902     //HighlightUsagesHandler.invoke(getProject(), editor, getFile());
903     return editor.getMarkupModel().getAllHighlighters();
904   }
905
906   @Override
907   public void moveFile(@NotNull final String filePath, @NotNull final String to, @NotNull final String... additionalFiles) {
908     assertInitialized();
909     final Project project = getProject();
910     configureByFiles(ArrayUtil.reverseArray(ArrayUtil.append(additionalFiles, filePath)));
911     final VirtualFile file = findFileInTempDir(to);
912     Assert.assertNotNull("Directory " + to + " not found", file);
913     Assert.assertTrue(to + " is not a directory", file.isDirectory());
914     final PsiDirectory directory = myPsiManager.findDirectory(file);
915     new MoveFilesOrDirectoriesProcessor(project, new PsiElement[]{getFile()}, directory,
916                                         false, false, null, null).run();
917   }
918
919   @Override
920   @Nullable
921   public GutterMark findGutter(@NotNull final String filePath) {
922     configureByFilesInner(filePath);
923     CommonProcessors.FindFirstProcessor<GutterMark> processor = new CommonProcessors.FindFirstProcessor<>();
924     findGutters(processor);
925     return processor.getFoundValue();
926   }
927
928   @NotNull
929   @Override
930   public List<GutterMark> findGuttersAtCaret() {
931     CommonProcessors.CollectProcessor<GutterMark> processor = new CommonProcessors.CollectProcessor<>();
932     findGutters(processor);
933     return new ArrayList<>(processor.getResults());
934   }
935
936   private void findGutters(Processor<GutterMark> processor) {
937     int offset = myEditor.getCaretModel().getOffset();
938
939     final Collection<HighlightInfo> infos = doHighlighting();
940     for (HighlightInfo info : infos) {
941       if (info.endOffset >= offset && info.startOffset <= offset) {
942         final GutterMark renderer = info.getGutterIconRenderer();
943         if (renderer != null && !processor.process(renderer)) {
944           return;
945         }
946       }
947     }
948     RangeHighlighter[] highlighters = DocumentMarkupModel.forDocument(myEditor.getDocument(), getProject(), true).getAllHighlighters();
949     for (RangeHighlighter highlighter : highlighters) {
950       if (highlighter.getEndOffset() >= offset && highlighter.getStartOffset() <= offset) {
951         GutterMark renderer = highlighter.getGutterIconRenderer();
952         if (renderer != null && !processor.process(renderer)) {
953           return;
954         }
955       }
956     }
957   }
958
959   @Override
960   @NotNull
961   public List<GutterMark> findAllGutters(@NotNull final String filePath) {
962     configureByFilesInner(filePath);
963     return findAllGutters();
964   }
965
966   @Override
967   @NotNull
968   public List<GutterMark> findAllGutters() {
969     final Project project = getProject();
970     final SortedMap<Integer, List<GutterMark>> result = new TreeMap<>();
971
972     List<HighlightInfo> infos = doHighlighting();
973     for (HighlightInfo info : infos) {
974       addGutterIconRenderer(info.getGutterIconRenderer(), info.startOffset, result);
975     }
976
977     RangeHighlighter[] highlighters = DocumentMarkupModel.forDocument(myEditor.getDocument(), project, true).getAllHighlighters();
978     for (final RangeHighlighter highlighter : highlighters) {
979       if (!highlighter.isValid()) continue;
980       addGutterIconRenderer(highlighter.getGutterIconRenderer(), highlighter.getStartOffset(), result);
981     }
982     return ContainerUtil.concat(result.values());
983   }
984
985   @Override
986   public PsiFile addFileToProject(@NotNull final String relativePath, @NotNull final String fileText) {
987     assertInitialized();
988     return addFileToProject(getTempDirPath(), relativePath, fileText);
989   }
990
991   protected PsiFile addFileToProject(@NotNull final String rootPath, @NotNull final String relativePath, @NotNull final String fileText) {
992     return new WriteCommandAction<PsiFile>(getProject()) {
993       @Override
994       protected void run(@NotNull Result<PsiFile> result) throws Throwable {
995         try {
996           if (myTempDirFixture instanceof LightTempDirTestFixtureImpl) {
997             final VirtualFile file = myTempDirFixture.createFile(relativePath, fileText);
998             result.setResult(PsiManager.getInstance(getProject()).findFile(file));
999           }
1000           else {
1001             result.setResult(((HeavyIdeaTestFixture)myProjectFixture).addFileToProject(rootPath, relativePath, fileText));
1002           }
1003         }
1004         catch (IOException e) {
1005           throw new RuntimeException(e);
1006         }
1007         finally {
1008           ((PsiModificationTrackerImpl)PsiManager.getInstance(getProject()).getModificationTracker()).incCounter();
1009         }
1010       }
1011     }.execute().getResultObject();
1012   }
1013
1014   public <T> void registerExtension(final ExtensionsArea area, final ExtensionPointName<T> epName, final T extension) {
1015     assertInitialized();
1016     final ExtensionPoint<T> extensionPoint = area.getExtensionPoint(epName);
1017     extensionPoint.registerExtension(extension);
1018     Disposer.register(getTestRootDisposable(), new Disposable() {
1019       @Override
1020       public void dispose() {
1021         extensionPoint.unregisterExtension(extension);
1022       }
1023     });
1024   }
1025
1026   @NotNull
1027   @Override
1028   public PsiManager getPsiManager() {
1029     return myPsiManager;
1030   }
1031
1032   @Override
1033   public LookupElement[] complete(@NotNull CompletionType type) {
1034     return complete(type, 1);
1035   }
1036
1037   @Override
1038   public LookupElement[] complete(@NotNull final CompletionType type, final int invocationCount) {
1039     assertInitialized();
1040     myEmptyLookup = false;
1041     return UIUtil.invokeAndWaitIfNeeded(new Computable<LookupElement[]>() {
1042       @Override
1043       public LookupElement[] compute() {
1044         CommandProcessor.getInstance().executeCommand(getProject(), new Runnable() {
1045           @Override
1046           public void run() {
1047             final CodeCompletionHandlerBase handler = new CodeCompletionHandlerBase(type) {
1048
1049               @Override
1050               protected void completionFinished(CompletionProgressIndicator indicator, boolean hasModifiers) {
1051                 myEmptyLookup = indicator.getLookup().getItems().isEmpty();
1052                 super.completionFinished(indicator, hasModifiers);
1053               }
1054             };
1055             Editor editor = getCompletionEditor();
1056             handler.invokeCompletion(getProject(), editor, invocationCount);
1057             PsiDocumentManager.getInstance(getProject()).commitAllDocuments(); // to compare with file text
1058           }
1059         }, null, null);
1060         return getLookupElements();
1061       }
1062     });
1063   }
1064
1065   @Nullable
1066   protected Editor getCompletionEditor() {
1067     return InjectedLanguageUtil.getEditorForInjectedLanguageNoCommit(myEditor, getFile());
1068   }
1069
1070   @Override
1071   @Nullable
1072   public LookupElement[] completeBasic() {
1073     return complete(CompletionType.BASIC);
1074   }
1075
1076   @Override
1077   @NotNull
1078   public final List<LookupElement> completeBasicAllCarets(@Nullable final Character charToTypeAfterCompletion) {
1079     final CaretModel caretModel = myEditor.getCaretModel();
1080     final List<Caret> carets = caretModel.getAllCarets();
1081
1082     final List<Integer> originalOffsets = new ArrayList<>(carets.size());
1083
1084     for (final Caret caret : carets) {
1085       originalOffsets.add(caret.getOffset());
1086     }
1087     caretModel.removeSecondaryCarets();
1088
1089     // We do it in reverse order because completions would affect offsets
1090     // i.e.: when you complete "spa" to "spam", next caret offset increased by 1
1091     Collections.reverse(originalOffsets);
1092     final List<LookupElement> result = new ArrayList<>();
1093     for (final int originalOffset : originalOffsets) {
1094       caretModel.moveToOffset(originalOffset);
1095       final LookupElement[] lookupElements = completeBasic();
1096       if (charToTypeAfterCompletion != null) {
1097         type(charToTypeAfterCompletion);
1098       }
1099       if (lookupElements != null) {
1100         result.addAll(Arrays.asList(lookupElements));
1101       }
1102     }
1103     return result;
1104   }
1105
1106   @Override
1107   public void saveText(@NotNull final VirtualFile file, @NotNull final String text) {
1108     new WriteAction() {
1109       @Override
1110       protected void run(@NotNull Result result) throws Throwable {
1111         VfsUtil.saveText(file, text);
1112       }
1113     }.execute().throwException();
1114
1115   }
1116
1117   @Override
1118   @Nullable
1119   public LookupElement[] getLookupElements() {
1120     LookupImpl lookup = getLookup();
1121     if (lookup == null) {
1122       return myEmptyLookup ? LookupElement.EMPTY_ARRAY : null;
1123     }
1124     else {
1125       final List<LookupElement> list = lookup.getItems();
1126       return list.toArray(new LookupElement[list.size()]);
1127     }
1128   }
1129
1130   @Override
1131   public void checkResult(@NotNull final String text) {
1132     checkResult(text, false);
1133   }
1134
1135   @Override
1136   public void checkResult(@NotNull final String text, final boolean stripTrailingSpaces) {
1137     new WriteCommandAction(getProject()) {
1138       @Override
1139       protected void run(@NotNull Result result) throws Throwable {
1140         PsiDocumentManager.getInstance(getProject()).commitAllDocuments();
1141         EditorUtil.fillVirtualSpaceUntilCaret(myEditor);
1142         checkResult("TEXT", stripTrailingSpaces, SelectionAndCaretMarkupLoader.fromText(text), getHostFile().getText());
1143       }
1144     }.execute();
1145   }
1146
1147   @Override
1148   public void checkResultByFile(@NotNull final String expectedFile) {
1149     checkResultByFile(expectedFile, false);
1150   }
1151
1152   @Override
1153   public void checkResultByFile(@NotNull final String expectedFile, final boolean ignoreTrailingWhitespaces) {
1154     assertInitialized();
1155     UIUtil.invokeAndWaitIfNeeded(new Runnable() {
1156       @Override
1157       public void run() {
1158         try {
1159           checkResultByFile(expectedFile, getHostFile(), ignoreTrailingWhitespaces);
1160         }
1161         catch (IOException e) {
1162           throw new RuntimeException(e);
1163         }
1164       }
1165     });
1166   }
1167
1168   @Override
1169   public void checkResultByFile(@NotNull final String filePath, @NotNull final String expectedFile, final boolean ignoreTrailingWhitespaces) {
1170     assertInitialized();
1171
1172     UIUtil.invokeAndWaitIfNeeded(new Runnable() {
1173       @Override
1174       public void run() {
1175         final String path = filePath.replace(File.separatorChar, '/');
1176         final VirtualFile copy = findFileInTempDir(path);
1177         if (copy == null) {
1178           throw new IllegalArgumentException("could not find results file " + path);
1179         }
1180         final PsiFile psiFile = myPsiManager.findFile(copy);
1181         Assert.assertNotNull(copy.getPath(), psiFile);
1182         try {
1183           checkResultByFile(expectedFile, psiFile, ignoreTrailingWhitespaces);
1184         }
1185         catch (IOException e) {
1186           throw new RuntimeException(e);
1187         }
1188       }
1189     });
1190   }
1191
1192   @Override
1193   public void setUp() throws Exception {
1194     super.setUp();
1195
1196     TestRunnerUtil.replaceIdeEventQueueSafely();
1197     EdtTestUtil.runInEdtAndWait(() -> {
1198       myProjectFixture.setUp();
1199       myTempDirFixture.setUp();
1200
1201       VirtualFile tempDir = myTempDirFixture.getFile("");
1202       PlatformTestCase.synchronizeTempDirVfs(tempDir);
1203
1204         myPsiManager = (PsiManagerImpl)PsiManager.getInstance(getProject());
1205         InspectionsKt.configureInspections(LocalInspectionTool.EMPTY_ARRAY, getProject(), getTestRootDisposable());
1206
1207       DaemonCodeAnalyzerImpl daemonCodeAnalyzer = (DaemonCodeAnalyzerImpl)DaemonCodeAnalyzer.getInstance(getProject());
1208       daemonCodeAnalyzer.prepareForTest();
1209
1210       DaemonCodeAnalyzerSettings.getInstance().setImportHintEnabled(false);
1211       ensureIndexesUpToDate(getProject());
1212       ((StartupManagerImpl)StartupManagerEx.getInstanceEx(getProject())).runPostStartupActivities();
1213     });
1214   }
1215
1216   @Override
1217   public void tearDown() throws Exception {
1218     try {
1219       EdtTestUtil.runInEdtAndWait(() -> {
1220         try {
1221           DaemonCodeAnalyzerSettings.getInstance().setImportHintEnabled(true); // return default value to avoid unnecessary save
1222           FileEditorManager editorManager = FileEditorManager.getInstance(getProject());
1223           PsiDocumentManager.getInstance(getProject()).commitAllDocuments();
1224           VirtualFile[] openFiles = editorManager.getOpenFiles();
1225           for (VirtualFile openFile : openFiles) {
1226             editorManager.closeFile(openFile);
1227           }
1228         }
1229         finally {
1230           myEditor = null;
1231           myFile = null;
1232           myPsiManager = null;
1233
1234           try {
1235             myProjectFixture.tearDown();
1236           }
1237           finally {
1238             myTempDirFixture.tearDown();
1239           }
1240         }
1241       });
1242     }
1243     finally {
1244       super.tearDown();
1245     }
1246   }
1247
1248   @NotNull
1249   private PsiFile[] configureByFilesInner(@NotNull String... filePaths) {
1250     assertInitialized();
1251     myFile = null;
1252     myEditor = null;
1253     PsiFile[] psiFiles = new PsiFile[filePaths.length];
1254     for (int i = filePaths.length - 1; i >= 0; i--) {
1255       psiFiles[i] = configureByFileInner(filePaths[i]);
1256     }
1257     return psiFiles;
1258   }
1259
1260   @Override
1261   public PsiFile configureByFile(@NotNull final String file) {
1262     configureByFilesInner(file);
1263     return getFile();
1264   }
1265
1266   @NotNull
1267   @Override
1268   public PsiFile[] configureByFiles(@NotNull final String... files) {
1269     return configureByFilesInner(files);
1270   }
1271
1272   @Override
1273   public PsiFile configureByText(@NotNull final FileType fileType, @NotNull final String text) {
1274     assertInitialized();
1275     final String extension = fileType.getDefaultExtension();
1276     final FileTypeManager fileTypeManager = FileTypeManager.getInstance();
1277     if (fileTypeManager.getFileTypeByExtension(extension) != fileType) {
1278       new WriteCommandAction(getProject()) {
1279         @Override
1280         protected void run(@NotNull Result result) throws Exception {
1281           fileTypeManager.associateExtension(fileType, extension);
1282         }
1283       }.execute();
1284     }
1285     final String fileName = "aaa." + extension;
1286     return configureByText(fileName, text);
1287   }
1288
1289   @Override
1290   public PsiFile configureByText(@NotNull final String fileName, @NotNull final String text) {
1291     assertInitialized();
1292     return new WriteCommandAction<PsiFile>(getProject()) {
1293       @Override
1294       protected void run(@NotNull Result<PsiFile> result) throws Throwable {
1295         final VirtualFile vFile;
1296         if (myTempDirFixture instanceof LightTempDirTestFixtureImpl) {
1297           final VirtualFile root = LightPlatformTestCase.getSourceRoot();
1298           root.refresh(false, false);
1299           vFile = root.findOrCreateChildData(this, fileName);
1300           Assert.assertNotNull(fileName + " not found in " + root.getPath(), vFile);
1301         }
1302         else if (myTempDirFixture instanceof TempDirTestFixtureImpl) {
1303           final File tempFile = ((TempDirTestFixtureImpl)myTempDirFixture).createTempFile(fileName);
1304           vFile = LocalFileSystem.getInstance().refreshAndFindFileByIoFile(tempFile);
1305           Assert.assertNotNull(tempFile + " not found", vFile);
1306         }
1307         else {
1308           vFile = LocalFileSystem.getInstance().refreshAndFindFileByIoFile(new File(getTempDirPath(), fileName));
1309           Assert.assertNotNull(fileName + " not found in " + getTempDirPath(), vFile);
1310         }
1311
1312         prepareVirtualFile(vFile);
1313
1314         final Document document = FileDocumentManager.getInstance().getCachedDocument(vFile);
1315         if (document != null) {
1316           PsiDocumentManager.getInstance(getProject()).doPostponedOperationsAndUnblockDocument(document);
1317           FileDocumentManager.getInstance().saveDocument(document);
1318         }
1319
1320         VfsUtil.saveText(vFile, text);
1321         configureInner(vFile, SelectionAndCaretMarkupLoader.fromFile(vFile));
1322         result.setResult(getFile());
1323       }
1324     }.execute().getResultObject();
1325   }
1326
1327   @Override
1328   public Document getDocument(@NotNull final PsiFile file) {
1329     assertInitialized();
1330     return PsiDocumentManager.getInstance(getProject()).getDocument(file);
1331   }
1332
1333   private PsiFile configureByFileInner(@NotNull String filePath) {
1334     assertInitialized();
1335     final VirtualFile file = copyFileToProject(filePath);
1336     return configureByFileInner(file);
1337   }
1338
1339   @Override
1340   public PsiFile configureFromTempProjectFile(@NotNull final String filePath) {
1341     final VirtualFile fileInTempDir = findFileInTempDir(filePath);
1342     if (fileInTempDir == null) {
1343       throw new IllegalArgumentException("Could not find file in temp dir: " + filePath);
1344     }
1345     return configureByFileInner(fileInTempDir);
1346   }
1347
1348   @Override
1349   public void configureFromExistingVirtualFile(@NotNull VirtualFile virtualFile) {
1350     configureByFileInner(virtualFile);
1351   }
1352
1353   private PsiFile configureByFileInner(@NotNull VirtualFile copy) {
1354     return configureInner(copy, SelectionAndCaretMarkupLoader.fromFile(copy));
1355   }
1356
1357   private PsiFile configureInner(@NotNull final VirtualFile copy, @NotNull final SelectionAndCaretMarkupLoader loader) {
1358     assertInitialized();
1359
1360     EdtTestUtil.runInEdtAndWait(() -> {
1361       if (!copy.getFileType().isBinary()) {
1362         AccessToken token = WriteAction.start();
1363         try {
1364           copy.setBinaryContent(loader.newFileText.getBytes(copy.getCharset()));
1365         }
1366         catch (IOException e) {
1367           throw new RuntimeException(e);
1368         }
1369         finally {
1370           token.finish();
1371         }
1372       }
1373       myFile = copy;
1374       myEditor = createEditor(copy);
1375       if (myEditor == null) {
1376         Assert.fail("editor couldn't be created for: " + copy.getPath() + ", use copyFileToProject() instead of configureByFile()");
1377       }
1378
1379       EditorTestUtil.setCaretsAndSelection(myEditor, loader.caretState);
1380
1381       Module module = getModule();
1382       if (module != null) {
1383         for (Facet facet : FacetManager.getInstance(module).getAllFacets()) {
1384           module.getMessageBus().syncPublisher(FacetManager.FACETS_TOPIC).facetConfigurationChanged(facet);
1385         }
1386       }
1387       PsiDocumentManager.getInstance(getProject()).commitAllDocuments();
1388
1389       if (myCaresAboutInjection) {
1390         setupEditorForInjectedLanguage();
1391       }
1392     });
1393
1394     return getFile();
1395   }
1396
1397   protected void prepareVirtualFile(@NotNull VirtualFile file) {
1398   }
1399
1400   private void setupEditorForInjectedLanguage() {
1401     Editor editor = InjectedLanguageUtil.getEditorForInjectedLanguageNoCommit(myEditor, getFile());
1402     if (editor instanceof EditorWindow) {
1403       myFile = ((EditorWindow)editor).getInjectedFile().getViewProvider().getVirtualFile();
1404       myEditor = editor;
1405     }
1406   }
1407
1408   @Override
1409   public VirtualFile findFileInTempDir(@NotNull final String filePath) {
1410     if (myTempDirFixture instanceof LightTempDirTestFixtureImpl) {
1411       return myTempDirFixture.getFile(filePath);
1412     }
1413     String fullPath = getTempDirPath() + "/" + filePath;
1414
1415     final VirtualFile copy = LocalFileSystem.getInstance().refreshAndFindFileByPath(fullPath.replace(File.separatorChar, '/'));
1416     Assert.assertNotNull("file " + fullPath + " not found", copy);
1417     VfsTestUtil.assertFilePathEndsWithCaseSensitivePath(copy, filePath);
1418     return copy;
1419   }
1420
1421   @Nullable
1422   protected Editor createEditor(@NotNull VirtualFile file) {
1423     final Project project = getProject();
1424     final FileEditorManager instance = FileEditorManager.getInstance(project);
1425     PsiDocumentManager.getInstance(getProject()).commitAllDocuments();
1426
1427     Editor editor = instance.openTextEditor(new OpenFileDescriptor(project, file), false);
1428     if (editor != null) {
1429       DaemonCodeAnalyzer.getInstance(getProject()).restart();
1430     }
1431     return editor;
1432   }
1433
1434   private long collectAndCheckHighlighting(boolean checkWarnings, boolean checkInfos, boolean checkWeakWarnings) throws Exception {
1435     return collectAndCheckHighlighting(checkWarnings, checkInfos, checkWeakWarnings, false);
1436   }
1437
1438   private long collectAndCheckHighlighting(boolean checkWarnings, boolean checkInfos, boolean checkWeakWarnings,
1439                                            boolean ignoreExtraHighlighting) throws Exception {
1440     ExpectedHighlightingData data = new ExpectedHighlightingData(myEditor.getDocument(),
1441                                                                  checkWarnings, checkWeakWarnings, checkInfos, ignoreExtraHighlighting, getHostFile());
1442     data.init();
1443     return collectAndCheckHighlighting(data);
1444   }
1445
1446   private PsiFile getHostFile() {
1447     return InjectedLanguageUtil.getTopLevelFile(getFile());
1448   }
1449
1450   private long collectAndCheckHighlighting(@NotNull ExpectedHighlightingData data) {
1451     final Project project = getProject();
1452     PsiDocumentManager.getInstance(project).commitAllDocuments();
1453
1454     PsiFileImpl file = (PsiFileImpl)getHostFile();
1455     FileElement hardRefToFileElement = file.calcTreeElement();//to load text
1456
1457     //to initialize caches
1458     if (!DumbService.isDumb(project)) {
1459       CacheManager.SERVICE.getInstance(project).getFilesWithWord("XXX", UsageSearchContext.IN_COMMENTS, GlobalSearchScope.allScope(project), true);
1460     }
1461
1462     final long start = System.currentTimeMillis();
1463     final VirtualFileFilter fileTreeAccessFilter = myVirtualFileFilter;
1464     Disposable disposable = Disposer.newDisposable();
1465     if (fileTreeAccessFilter != null) {
1466       PsiManagerEx.getInstanceEx(project).setAssertOnFileLoadingFilter(fileTreeAccessFilter, disposable);
1467     }
1468
1469     //    ProfilingUtil.startCPUProfiling();
1470     List<HighlightInfo> infos;
1471     try {
1472       infos = doHighlighting();
1473       removeDuplicatedRangesForInjected(infos);
1474     }
1475     finally {
1476       Disposer.dispose(disposable);
1477     }
1478     //    ProfilingUtil.captureCPUSnapshot("testing");
1479     final long elapsed = System.currentTimeMillis() - start;
1480
1481     data.checkResult(infos, file.getText());
1482     hardRefToFileElement.hashCode(); // use it so gc won't collect it
1483     return elapsed;
1484   }
1485
1486   public void setVirtualFileFilter(@Nullable VirtualFileFilter filter) {
1487     myVirtualFileFilter = filter;
1488   }
1489
1490   @Override
1491   @NotNull
1492   public List<HighlightInfo> doHighlighting() {
1493     final Project project = getProject();
1494     PsiDocumentManager.getInstance(project).commitAllDocuments();
1495
1496     PsiFile file = getFile();
1497     Editor editor = getEditor();
1498     if (editor instanceof EditorWindow) {
1499       editor = ((EditorWindow)editor).getDelegate();
1500       file = InjectedLanguageUtil.getTopLevelFile(file);
1501     }
1502     return instantiateAndRun(file, editor, ArrayUtil.EMPTY_INT_ARRAY, myAllowDirt);
1503   }
1504
1505   @NotNull
1506   @Override
1507   public List<HighlightInfo> doHighlighting(@NotNull final HighlightSeverity minimalSeverity) {
1508     return ContainerUtil.filter(doHighlighting(), info -> info.getSeverity().compareTo(minimalSeverity) >= 0);
1509   }
1510
1511   @NotNull
1512   @Override
1513   public String getTestDataPath() {
1514     return myTestDataPath;
1515   }
1516
1517   @Override
1518   public void setTestDataPath(@NotNull String dataPath) {
1519     myTestDataPath = dataPath;
1520   }
1521
1522   @Override
1523   public Project getProject() {
1524     return myProjectFixture.getProject();
1525   }
1526
1527   @Override
1528   public Module getModule() {
1529     return myProjectFixture.getModule();
1530   }
1531
1532   @Override
1533   public Editor getEditor() {
1534     return myEditor;
1535   }
1536
1537   @Override
1538   public int getCaretOffset() {
1539     return myEditor.getCaretModel().getOffset();
1540   }
1541
1542   @Override
1543   public PsiFile getFile() {
1544     return myFile == null ? null : ApplicationManager.getApplication().runReadAction(new Computable<PsiFile>() {
1545       @Override
1546       public PsiFile compute() {
1547         return PsiManager.getInstance(getProject()).findFile(myFile);
1548       }
1549     });
1550   }
1551
1552   @Override
1553   public void allowTreeAccessForFile(@NotNull final VirtualFile file) {
1554     assert myVirtualFileFilter instanceof FileTreeAccessFilter : "configured filter does not support this method";
1555     ((FileTreeAccessFilter)myVirtualFileFilter).allowTreeAccessForFile(file);
1556   }
1557
1558   @Override
1559   public void allowTreeAccessForAllFiles() {
1560     assert myVirtualFileFilter instanceof FileTreeAccessFilter : "configured filter does not support this method";
1561     ((FileTreeAccessFilter)myVirtualFileFilter).allowTreeAccessForAllFiles();
1562   }
1563
1564   private void checkResultByFile(@NotNull String expectedFile,
1565                                  @NotNull PsiFile originalFile,
1566                                  boolean stripTrailingSpaces) throws IOException {
1567     if (!stripTrailingSpaces) {
1568       EditorUtil.fillVirtualSpaceUntilCaret(myEditor);
1569     }
1570     PsiDocumentManager.getInstance(getProject()).commitAllDocuments();
1571
1572     final String fileText = originalFile.getText();
1573     final String path = getTestDataPath() + "/" + expectedFile;
1574
1575     /*final VirtualFile result = LocalFileSystem.getInstance().findFileByPath(path);
1576     final int caret = myEditor.getCaretModel().getOffset();
1577     final String newText = myFile == originalFile ? fileText.substring(0, caret) + "<caret>" + fileText.substring(caret) : fileText;
1578     VfsUtil.saveText(result, newText);*/
1579
1580     VirtualFile virtualFile = originalFile.getVirtualFile();
1581     String charset = virtualFile == null? null : virtualFile.getCharset().name();
1582     checkResult(expectedFile, stripTrailingSpaces, SelectionAndCaretMarkupLoader.fromFile(path, charset), fileText);
1583
1584   }
1585
1586   private void checkResult(@NotNull String expectedFile,
1587                            final boolean stripTrailingSpaces,
1588                            @NotNull SelectionAndCaretMarkupLoader loader,
1589                            @NotNull String actualText) {
1590     assertInitialized();
1591     Project project = getProject();
1592     Editor editor = getEditor();
1593     if (editor instanceof EditorWindow) {
1594       editor = ((EditorWindow)editor).getDelegate();
1595     }
1596
1597     UsefulTestCase.doPostponedFormatting(getProject());
1598     if (stripTrailingSpaces) {
1599       actualText = stripTrailingSpaces(actualText);
1600     }
1601
1602     PsiDocumentManager.getInstance(project).commitAllDocuments();
1603
1604     String newFileText1 = loader.newFileText;
1605     if (stripTrailingSpaces) {
1606       newFileText1 = stripTrailingSpaces(newFileText1);
1607     }
1608
1609     actualText = StringUtil.convertLineSeparators(actualText);
1610
1611     if (!Comparing.equal(newFileText1, actualText)) {
1612       if (loader.filePath != null) {
1613         throw new FileComparisonFailure(expectedFile, newFileText1, actualText, loader.filePath);
1614       }
1615       else {
1616         throw new ComparisonFailure(expectedFile, newFileText1, actualText);
1617       }
1618     }
1619
1620     EditorTestUtil.verifyCaretAndSelectionState(editor, loader.caretState, expectedFile);
1621   }
1622
1623   @NotNull
1624   private String stripTrailingSpaces(@NotNull String actualText) {
1625     final Document document = EditorFactory.getInstance().createDocument(actualText);
1626     ((DocumentImpl)document).stripTrailingSpaces(getProject());
1627     actualText = document.getText();
1628     return actualText;
1629   }
1630
1631   public void canChangeDocumentDuringHighlighting(boolean canI) {
1632     myAllowDirt = canI;
1633   }
1634
1635   @NotNull
1636   public String getFoldingDescription(boolean withCollapseStatus) {
1637     CodeFoldingManager.getInstance(getProject()).buildInitialFoldings(myEditor);
1638
1639     final FoldingModel model = myEditor.getFoldingModel();
1640     final FoldRegion[] foldingRegions = model.getAllFoldRegions();
1641     final List<Border> borders = new LinkedList<>();
1642
1643     for (FoldRegion region : foldingRegions) {
1644       borders.add(new Border(Border.LEFT, region.getStartOffset(), region.getPlaceholderText(), region.isExpanded()));
1645       borders.add(new Border(Border.RIGHT, region.getEndOffset(), "", region.isExpanded()));
1646     }
1647     Collections.sort(borders);
1648
1649     StringBuilder result = new StringBuilder(myEditor.getDocument().getText());
1650     for (Border border : borders) {
1651       result.insert(border.getOffset(), border.isSide() == Border.LEFT ? "<fold text=\'" + border.getText() + "\'" +
1652                                                                          (withCollapseStatus ? " expand=\'" +
1653                                                                                                     border.isExpanded() +
1654                                                                                                     "\'" : "") +
1655                                                                           ">" : END_FOLD);
1656     }
1657
1658     return result.toString();
1659   }
1660
1661   @NotNull
1662   public String getHighlightingDescription(@NotNull List<HighlightInfo> highlighting, @NotNull String tagName, boolean withColor) {
1663     final List<Border> borders = new LinkedList<>();
1664     for (HighlightInfo region : highlighting) {
1665       TextAttributes attributes = region.getTextAttributes(null, null);
1666       borders.add(new Border(Border.LEFT, region.getStartOffset(),
1667                              attributes == null ? "null"
1668                                                 : attributes.getForegroundColor() == null
1669                                                   ? "null"
1670                                                   : Integer.toHexString(attributes.getForegroundColor().getRGB()),
1671                              false));
1672       borders.add(new Border(Border.RIGHT, region.getEndOffset(), "", false));
1673     }
1674     Collections.sort(borders);
1675
1676     StringBuilder result = new StringBuilder(myEditor.getDocument().getText());
1677     for (Border border : borders) {
1678       StringBuilder info = new StringBuilder();
1679       info.append('<');
1680       if (border.isSide() == Border.LEFT) {
1681         info.append(tagName);
1682         if (withColor) {
1683           info.append(" color=\'").append(border.myText).append('\'');
1684         }
1685       }
1686       else {
1687         info.append('/').append(tagName);
1688       }
1689       info.append('>');
1690       result.insert(border.getOffset(), info);
1691     }
1692
1693     return result.toString();
1694   }
1695
1696   private void testFoldingRegions(@NotNull String verificationFileName, @Nullable String destinationFileName, boolean doCheckCollapseStatus) {
1697     String expectedContent;
1698     try {
1699       expectedContent = FileUtil.loadFile(new File(verificationFileName));
1700     }
1701     catch (IOException e) {
1702       throw new RuntimeException(e);
1703     }
1704     Assert.assertNotNull(expectedContent);
1705
1706     expectedContent = StringUtil.replace(expectedContent, "\r", "");
1707     final String cleanContent = expectedContent.replaceAll(START_FOLD, "").replaceAll(END_FOLD, "");
1708     if (destinationFileName == null) {
1709       configureByText(FileTypeManager.getInstance().getFileTypeByFileName(verificationFileName), cleanContent);
1710     }
1711     else {
1712       try {
1713         FileUtil.writeToFile(new File(destinationFileName), cleanContent);
1714         configureFromExistingVirtualFile(LocalFileSystem.getInstance().refreshAndFindFileByPath(destinationFileName));
1715       }
1716       catch (IOException e) {
1717         throw new RuntimeException(e);
1718       }
1719     }
1720     final String actual = getFoldingDescription(doCheckCollapseStatus);
1721     Assert.assertEquals(expectedContent, actual);
1722   }
1723
1724   @Override
1725   public void testFoldingWithCollapseStatus(@NotNull final String verificationFileName) {
1726     testFoldingRegions(verificationFileName, null, true);
1727   }
1728
1729   @Override
1730   public void testFoldingWithCollapseStatus(@NotNull final String verificationFileName, @Nullable String destinationFileName) {
1731     testFoldingRegions(verificationFileName, destinationFileName, true);
1732   }
1733
1734   @Override
1735   public void testFolding(@NotNull final String verificationFileName) {
1736     testFoldingRegions(verificationFileName, null, false);
1737   }
1738
1739   @Override
1740   public void testRainbow(@NotNull String fileName, @NotNull String text, boolean isRainbowOn, boolean withColor) {
1741     RegistryValue registryValue = Registry.get("editor.rainbow.identifiers");
1742     final boolean rainbowColors = registryValue.asBoolean();
1743     try {
1744       registryValue.setValue(isRainbowOn);
1745       configureByText(fileName, text.replaceAll("<" + RAINBOW + "(\\scolor=\'[^\']*\')?>", "").replace("</" + RAINBOW + ">", ""));
1746
1747       Assert.assertEquals(text, getHighlightingDescription(ContainerUtil.filter(doHighlighting(),
1748                                                            info -> info.type == RainbowHighlighter.RAINBOW_ELEMENT), RAINBOW,
1749                                                            withColor));
1750     }
1751     finally {
1752       registryValue.setValue(rainbowColors);
1753     }
1754   }
1755
1756   @Override
1757   public void assertPreferredCompletionItems(final int selected, @NotNull final String... expected) {
1758     final LookupImpl lookup = getLookup();
1759     Assert.assertNotNull("No lookup is shown", lookup);
1760
1761     final JList list = lookup.getList();
1762     List<String> strings = getLookupElementStrings();
1763     Assert.assertNotNull(strings);
1764     final List<String> actual = strings.subList(0, Math.min(expected.length, strings.size()));
1765     if (!actual.equals(Arrays.asList(expected))) {
1766       UsefulTestCase.assertOrderedEquals(DumpLookupElementWeights.getLookupElementWeights(lookup, false), expected);
1767     }
1768     if (selected != list.getSelectedIndex()) {
1769       System.out.println(DumpLookupElementWeights.getLookupElementWeights(lookup, false));
1770     }
1771     Assert.assertEquals(selected, list.getSelectedIndex());
1772   }
1773
1774   @Override
1775   public void testStructureView(@NotNull Consumer<StructureViewComponent> consumer) {
1776     Assert.assertNotNull("configure first", myFile);
1777
1778     final FileEditor fileEditor = FileEditorManager.getInstance(getProject()).getSelectedEditor(myFile);
1779     Assert.assertNotNull("editor not opened for " + myFile, myFile);
1780
1781     final StructureViewBuilder builder = LanguageStructureViewBuilder.INSTANCE.getStructureViewBuilder(getFile());
1782     Assert.assertNotNull("no builder for " + myFile, myFile);
1783
1784     StructureViewComponent component = null;
1785     try {
1786       component = (StructureViewComponent)builder.createStructureView(fileEditor, myProjectFixture.getProject());
1787       consumer.consume(component);
1788     }
1789     finally {
1790       if (component != null) Disposer.dispose(component);
1791     }
1792   }
1793
1794   @Override
1795   public void setCaresAboutInjection(boolean caresAboutInjection) {
1796     myCaresAboutInjection = caresAboutInjection;
1797   }
1798
1799   @Override
1800   public LookupImpl getLookup() {
1801     return (LookupImpl)LookupManager.getActiveLookup(myEditor);
1802   }
1803
1804   protected void bringRealEditorBack() {
1805     PsiDocumentManager.getInstance(getProject()).commitAllDocuments();
1806     if (myEditor instanceof EditorWindow) {
1807       Document document = ((DocumentWindow)myEditor.getDocument()).getDelegate();
1808       myFile = FileDocumentManager.getInstance().getFile(document);
1809       myEditor = ((EditorWindow)myEditor).getDelegate();
1810     }
1811   }
1812
1813   private static class SelectionAndCaretMarkupLoader {
1814     private final String filePath;
1815     @NotNull
1816     private final String newFileText;
1817     private final EditorTestUtil.CaretAndSelectionState caretState;
1818
1819     private SelectionAndCaretMarkupLoader(@NotNull String fileText, String filePath) {
1820       this.filePath = filePath;
1821       final Document document = EditorFactory.getInstance().createDocument(fileText);
1822       caretState = EditorTestUtil.extractCaretAndSelectionMarkers(document);
1823       newFileText = document.getText();
1824     }
1825
1826     @NotNull
1827     private static SelectionAndCaretMarkupLoader fromFile(@NotNull String path, String charset) throws IOException {
1828       return new SelectionAndCaretMarkupLoader(StringUtil.convertLineSeparators(FileUtil.loadFile(new File(path), charset)), path);
1829     }
1830
1831     @NotNull
1832     static SelectionAndCaretMarkupLoader fromFile(@NotNull VirtualFile file) {
1833       final String text;
1834       try {
1835         text = VfsUtilCore.loadText(file);
1836       }
1837       catch (IOException e) {
1838         throw new RuntimeException(e);
1839       }
1840       return new SelectionAndCaretMarkupLoader(StringUtil.convertLineSeparators(text), file.getPath());
1841     }
1842
1843     @NotNull
1844     static SelectionAndCaretMarkupLoader fromText(@NotNull String text) {
1845       return new SelectionAndCaretMarkupLoader(text, null);
1846     }
1847   }
1848
1849   private static class Border implements Comparable<Border> {
1850     private static final boolean LEFT = true;
1851     private static final boolean RIGHT = false;
1852     private final boolean mySide;
1853     private final int myOffset;
1854     private final String myText;
1855     private final boolean myIsExpanded;
1856
1857     private Border(boolean side, int offset, String text, boolean isExpanded) {
1858       mySide = side;
1859       myOffset = offset;
1860       myText = text;
1861       myIsExpanded = isExpanded;
1862     }
1863
1864     public boolean isExpanded() {
1865       return myIsExpanded;
1866     }
1867
1868     public boolean isSide() {
1869       return mySide;
1870     }
1871
1872     public int getOffset() {
1873       return myOffset;
1874     }
1875
1876     public String getText() {
1877       return myText;
1878     }
1879
1880     @Override
1881     public int compareTo(@NotNull Border o) {
1882       return getOffset() < o.getOffset() ? 1 : -1;
1883     }
1884   }
1885
1886   @SuppressWarnings("unused")
1887   @NotNull
1888   @TestOnly
1889   @Deprecated
1890   public static GlobalInspectionContextForTests createGlobalContextForTool(@NotNull AnalysisScope scope,
1891                                                                            @NotNull final Project project,
1892                                                                            @NotNull InspectionManagerEx inspectionManager,
1893                                                                            @NotNull final InspectionToolWrapper... toolWrappers) {
1894     return InspectionsKt.createGlobalContextForTool(scope, project, Arrays.<InspectionToolWrapper<?, ?>>asList(toolWrappers));
1895   }
1896 }