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