2 * Copyright 2000-2017 JetBrains s.r.o.
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
16 package com.intellij.testFramework.fixtures.impl;
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.InspectionToolWrapper;
42 import com.intellij.facet.Facet;
43 import com.intellij.facet.FacetManager;
44 import com.intellij.find.FindManager;
45 import com.intellij.find.findUsages.FindUsagesHandler;
46 import com.intellij.find.findUsages.FindUsagesOptions;
47 import com.intellij.find.impl.FindManagerImpl;
48 import com.intellij.ide.startup.StartupManagerEx;
49 import com.intellij.ide.startup.impl.StartupManagerImpl;
50 import com.intellij.ide.structureView.StructureViewBuilder;
51 import com.intellij.ide.structureView.newStructureView.StructureViewComponent;
52 import com.intellij.ide.util.gotoByName.ChooseByNameBase;
53 import com.intellij.ide.util.gotoByName.ChooseByNamePopup;
54 import com.intellij.ide.util.gotoByName.GotoClassModel2;
55 import com.intellij.injected.editor.DocumentWindow;
56 import com.intellij.injected.editor.EditorWindow;
57 import com.intellij.internal.DumpLookupElementWeights;
58 import com.intellij.lang.Language;
59 import com.intellij.lang.LanguageStructureViewBuilder;
60 import com.intellij.lang.annotation.HighlightSeverity;
61 import com.intellij.mock.MockProgressIndicator;
62 import com.intellij.openapi.Disposable;
63 import com.intellij.openapi.actionSystem.*;
64 import com.intellij.openapi.actionSystem.ex.ActionManagerEx;
65 import com.intellij.openapi.application.ApplicationManager;
66 import com.intellij.openapi.application.ReadAction;
67 import com.intellij.openapi.application.Result;
68 import com.intellij.openapi.application.WriteAction;
69 import com.intellij.openapi.command.CommandProcessor;
70 import com.intellij.openapi.command.WriteCommandAction;
71 import com.intellij.openapi.editor.*;
72 import com.intellij.openapi.editor.actionSystem.EditorActionManager;
73 import com.intellij.openapi.editor.colors.EditorColorsManager;
74 import com.intellij.openapi.editor.colors.EditorColorsScheme;
75 import com.intellij.openapi.editor.ex.EditorEx;
76 import com.intellij.openapi.editor.ex.util.EditorUtil;
77 import com.intellij.openapi.editor.impl.DocumentImpl;
78 import com.intellij.openapi.editor.impl.DocumentMarkupModel;
79 import com.intellij.openapi.editor.markup.RangeHighlighter;
80 import com.intellij.openapi.editor.markup.TextAttributes;
81 import com.intellij.openapi.extensions.ExtensionPoint;
82 import com.intellij.openapi.extensions.ExtensionPointName;
83 import com.intellij.openapi.extensions.ExtensionsArea;
84 import com.intellij.openapi.fileEditor.*;
85 import com.intellij.openapi.fileEditor.ex.FileEditorManagerEx;
86 import com.intellij.openapi.fileEditor.impl.EditorHistoryManager;
87 import com.intellij.openapi.fileEditor.impl.text.TextEditorProvider;
88 import com.intellij.openapi.fileTypes.FileType;
89 import com.intellij.openapi.fileTypes.FileTypeManager;
90 import com.intellij.openapi.module.Module;
91 import com.intellij.openapi.module.ModuleManager;
92 import com.intellij.openapi.progress.ProcessCanceledException;
93 import com.intellij.openapi.project.DumbService;
94 import com.intellij.openapi.project.Project;
95 import com.intellij.openapi.roots.ModuleRootManager;
96 import com.intellij.openapi.util.*;
97 import com.intellij.openapi.util.io.FileUtil;
98 import com.intellij.openapi.util.text.StringUtil;
99 import com.intellij.openapi.vcs.readOnlyHandler.ReadonlyStatusHandlerImpl;
100 import com.intellij.openapi.vfs.*;
101 import com.intellij.openapi.vfs.impl.VirtualFilePointerTracker;
102 import com.intellij.psi.*;
103 import com.intellij.psi.impl.DebugUtil;
104 import com.intellij.psi.impl.PsiManagerEx;
105 import com.intellij.psi.impl.PsiManagerImpl;
106 import com.intellij.psi.impl.cache.CacheManager;
107 import com.intellij.psi.impl.cache.impl.todo.TodoIndex;
108 import com.intellij.psi.impl.source.PsiFileImpl;
109 import com.intellij.psi.impl.source.tree.FileElement;
110 import com.intellij.psi.impl.source.tree.injected.InjectedLanguageUtil;
111 import com.intellij.psi.search.GlobalSearchScope;
112 import com.intellij.psi.search.SearchScope;
113 import com.intellij.psi.search.UsageSearchContext;
114 import com.intellij.psi.stubs.StubTextInconsistencyException;
115 import com.intellij.psi.stubs.StubUpdatingIndex;
116 import com.intellij.psi.util.PsiTreeUtil;
117 import com.intellij.refactoring.move.moveFilesOrDirectories.MoveFilesOrDirectoriesProcessor;
118 import com.intellij.refactoring.rename.*;
119 import com.intellij.rt.execution.junit.FileComparisonFailure;
120 import com.intellij.testFramework.*;
121 import com.intellij.testFramework.fixtures.*;
122 import com.intellij.testFramework.utils.inlays.CaretAndInlaysInfo;
123 import com.intellij.testFramework.utils.inlays.InlayHintsChecker;
124 import com.intellij.ui.breadcrumbs.BreadcrumbsProvider;
125 import com.intellij.ui.breadcrumbs.BreadcrumbsUtil;
126 import com.intellij.ui.components.breadcrumbs.Crumb;
127 import com.intellij.usageView.UsageInfo;
128 import com.intellij.util.*;
129 import com.intellij.util.containers.ContainerUtil;
130 import com.intellij.util.indexing.FileBasedIndex;
131 import com.intellij.util.io.ReadOnlyAttributeUtil;
132 import com.intellij.util.ui.UIUtil;
133 import junit.framework.ComparisonFailure;
134 import org.jetbrains.annotations.NotNull;
135 import org.jetbrains.annotations.Nullable;
136 import org.jetbrains.annotations.TestOnly;
138 import javax.swing.*;
140 import java.io.IOException;
141 import java.io.UncheckedIOException;
143 import java.util.concurrent.atomic.AtomicBoolean;
144 import java.util.stream.Collectors;
145 import java.util.stream.Stream;
147 import static org.junit.Assert.*;
150 * @author Dmitry Avdeev
152 public class CodeInsightTestFixtureImpl extends BaseFixture implements CodeInsightTestFixture {
153 private static final Function<IntentionAction, String> INTENTION_NAME_FUN = intentionAction -> '"' + intentionAction.getText() + '"';
155 private static final String RAINBOW = "rainbow";
156 private static final String FOLD = "fold";
158 private final IdeaProjectTestFixture myProjectFixture;
159 private final TempDirTestFixture myTempDirFixture;
160 private PsiManagerImpl myPsiManager;
161 private VirtualFile myFile;
162 private Editor myEditor;
163 private String myTestDataPath;
164 private boolean myEmptyLookup;
165 private VirtualFileFilter myVirtualFileFilter = new FileTreeAccessFilter();
166 private ChooseByNameBase myChooseByNamePopup;
167 private boolean myAllowDirt;
168 private boolean myCaresAboutInjection = true;
169 private VirtualFilePointerTracker myVirtualFilePointerTracker;
171 public CodeInsightTestFixtureImpl(@NotNull IdeaProjectTestFixture projectFixture, @NotNull TempDirTestFixture tempDirTestFixture) {
172 myProjectFixture = projectFixture;
173 myTempDirFixture = tempDirTestFixture;
176 private static void addGutterIconRenderer(GutterMark renderer, int offset, @NotNull SortedMap<Integer, List<GutterMark>> result) {
177 if (renderer == null) return;
179 List<GutterMark> renderers = result.computeIfAbsent(offset, k -> new SmartList<>());
180 renderers.add(renderer);
183 private static void removeDuplicatedRangesForInjected(@NotNull List<HighlightInfo> infos) {
184 Collections.sort(infos, (o1, o2) -> {
185 final int i = o2.startOffset - o1.startOffset;
186 return i != 0 ? i : o1.getSeverity().myVal - o2.getSeverity().myVal;
188 HighlightInfo prevInfo = null;
189 for (Iterator<HighlightInfo> it = infos.iterator(); it.hasNext();) {
190 final HighlightInfo info = it.next();
191 if (prevInfo != null &&
192 info.getSeverity() == HighlightInfoType.SYMBOL_TYPE_SEVERITY &&
193 info.getDescription() == null &&
194 info.startOffset == prevInfo.startOffset &&
195 info.endOffset == prevInfo.endOffset) {
198 prevInfo = info.type == HighlightInfoType.INJECTED_LANGUAGE_FRAGMENT ? info : null;
204 public static List<HighlightInfo> instantiateAndRun(@NotNull PsiFile file,
205 @NotNull Editor editor,
206 @NotNull int[] toIgnore,
207 boolean canChangeDocument) {
208 Project project = file.getProject();
209 ensureIndexesUpToDate(project);
210 DaemonCodeAnalyzerImpl codeAnalyzer = (DaemonCodeAnalyzerImpl)DaemonCodeAnalyzer.getInstance(project);
211 TextEditor textEditor = TextEditorProvider.getInstance().getTextEditor(editor);
212 DaemonCodeAnalyzerSettings settings = DaemonCodeAnalyzerSettings.getInstance();
214 ProcessCanceledException exception = null;
216 for (int i = 0; i < retries; i++) {
217 int oldDelay = settings.AUTOREPARSE_DELAY;
219 settings.AUTOREPARSE_DELAY = 0;
220 List<HighlightInfo> infos = new ArrayList<>();
221 EdtTestUtil.runInEdtAndWait(() -> infos.addAll( codeAnalyzer.runPasses(file, editor.getDocument(), Collections.singletonList(textEditor), toIgnore, canChangeDocument, null)));
222 infos.addAll(DaemonCodeAnalyzerEx.getInstanceEx(project).getFileLevelHighlights(project, file));
225 catch (ProcessCanceledException e) {
226 Throwable cause = e.getCause();
227 if (cause != null && cause.getClass() != Throwable.class) {
228 // canceled because of an exception, no need to repeat the same a lot times
232 PsiDocumentManager.getInstance(project).commitAllDocuments();
233 UIUtil.dispatchAllInvocationEvents();
237 settings.AUTOREPARSE_DELAY = oldDelay;
240 throw new AssertionError("Unable to highlight after " + retries + " retries", exception);
243 public static void ensureIndexesUpToDate(@NotNull Project project) {
244 if (!DumbService.isDumb(project)) {
245 ReadAction.run(() -> {
246 FileBasedIndex.getInstance().ensureUpToDate(StubUpdatingIndex.INDEX_ID, project, null);
247 FileBasedIndex.getInstance().ensureUpToDate(TodoIndex.NAME, project, null);
253 public static List<IntentionAction> getAvailableIntentions(@NotNull Editor editor, @NotNull PsiFile file) {
254 return ReadAction.compute(() -> doGetAvailableIntentions(editor, file));
258 private static List<IntentionAction> doGetAvailableIntentions(@NotNull Editor editor, @NotNull PsiFile file) {
259 ShowIntentionsPass.IntentionsInfo intentions = new ShowIntentionsPass.IntentionsInfo();
260 ShowIntentionsPass.getActionsToShow(editor, file, intentions, -1);
262 List<IntentionAction> result = new ArrayList<>();
263 IntentionListStep intentionListStep = new IntentionListStep(null, intentions, editor, file, file.getProject());
264 for (Map.Entry<IntentionAction, List<IntentionAction>> entry : intentionListStep.getActionsWithSubActions().entrySet()) {
265 result.add(entry.getKey());
266 result.addAll(entry.getValue());
269 List<HighlightInfo> infos = DaemonCodeAnalyzerEx.getInstanceEx(file.getProject()).getFileLevelHighlights(file.getProject(), file);
270 for (HighlightInfo info : infos) {
271 for (Pair<HighlightInfo.IntentionActionDescriptor, TextRange> pair : info.quickFixActionRanges) {
272 HighlightInfo.IntentionActionDescriptor actionInGroup = pair.first;
273 if (actionInGroup.getAction().isAvailable(file.getProject(), editor, file)) {
274 result.add(actionInGroup.getAction());
275 List<IntentionAction> options = actionInGroup.getOptions(file, editor);
276 if (options != null) {
277 for (IntentionAction subAction : options) {
278 if (subAction.isAvailable(file.getProject(), editor, file)) {
279 result.add(subAction);
291 public String getTempDirPath() {
292 return myTempDirFixture.getTempDirPath();
297 public TempDirTestFixture getTempDirFixture() {
298 return myTempDirFixture;
303 public VirtualFile copyFileToProject(@NotNull String sourcePath) {
304 return copyFileToProject(sourcePath, sourcePath);
309 public VirtualFile copyFileToProject(@NotNull String sourcePath, @NotNull String targetPath) {
310 String testDataPath = getTestDataPath();
311 File sourceFile = FileUtil.findFirstThatExist(testDataPath + '/' + sourcePath, sourcePath);
312 VirtualFile targetFile = myTempDirFixture.getFile(targetPath);
314 if (sourceFile == null && targetFile != null && targetPath.equals(sourcePath)) {
318 assertFileEndsWithCaseSensitivePath(sourceFile);
320 assertNotNull("Cannot find source file: " + sourcePath + "; test data path: " + testDataPath, sourceFile);
321 assertTrue("Not a file: " + sourceFile, sourceFile.isFile());
323 if (targetFile == null) {
324 targetFile = myTempDirFixture.createFile(targetPath);
325 VfsTestUtil.assertFilePathEndsWithCaseSensitivePath(targetFile, sourcePath);
326 targetFile.putUserData(VfsTestUtil.TEST_DATA_FILE_PATH, sourceFile.getAbsolutePath());
329 copyContent(sourceFile, targetFile);
334 private static void assertFileEndsWithCaseSensitivePath(@Nullable File sourceFile) {
335 if (sourceFile == null) return;
337 String sourceName = sourceFile.getName();
338 File realFile = sourceFile.getCanonicalFile();
339 String realFileName = realFile.getName();
340 if (sourceName.equalsIgnoreCase(realFileName) && !sourceName.equals(realFileName)) {
341 fail("Please correct case-sensitivity of path to prevent test failure on case-sensitive file systems:\n" +
342 " path " + sourceFile.getPath() + "\n" +
343 "real path " + realFile.getPath());
346 catch (IOException e) {
347 throw new UncheckedIOException(e);
351 private static void copyContent(File sourceFile, VirtualFile targetFile) {
354 protected void run(@NotNull Result result) throws IOException {
355 targetFile.setBinaryContent(FileUtil.loadFileBytes(sourceFile));
356 // update the document now, otherwise MemoryDiskConflictResolver will do it later at unexpected moment of time
357 FileDocumentManager.getInstance().reloadFiles(targetFile);
364 public VirtualFile copyDirectoryToProject(@NotNull String sourcePath, @NotNull String targetPath) {
365 final String testDataPath = getTestDataPath();
367 final File fromFile = new File(testDataPath + "/" + sourcePath);
368 if (myTempDirFixture instanceof LightTempDirTestFixtureImpl) {
369 return myTempDirFixture.copyAll(fromFile.getPath(), targetPath);
372 final File targetFile = new File(getTempDirPath() + "/" + targetPath);
374 FileUtil.copyDir(fromFile, targetFile);
376 catch (IOException e) {
377 throw new RuntimeException(e);
380 final VirtualFile file = LocalFileSystem.getInstance().refreshAndFindFileByIoFile(targetFile);
382 file.refresh(false, true);
387 public void enableInspections(@NotNull InspectionProfileEntry... inspections) {
389 InspectionsKt.enableInspectionTools(getProject(), myProjectFixture.getTestRootDisposable(), inspections);
394 public final void enableInspections(@NotNull Class<? extends LocalInspectionTool>... inspections) {
395 enableInspections(Arrays.asList(inspections));
399 public void enableInspections(@NotNull Collection<Class<? extends LocalInspectionTool>> inspections) {
400 List<InspectionProfileEntry> tools = InspectionTestUtil.instantiateTools(inspections);
401 enableInspections(tools.toArray(new InspectionProfileEntry[tools.size()]));
405 public void disableInspections(@NotNull InspectionProfileEntry... inspections) {
406 InspectionsKt.disableInspections(getProject(), inspections);
410 public void enableInspections(@NotNull InspectionToolProvider... providers) {
411 List<Class<? extends LocalInspectionTool>> classes = Stream.of(providers)
412 .flatMap(p -> Stream.of(p.getInspectionClasses()))
413 .filter(LocalInspectionTool.class::isAssignableFrom)
415 @SuppressWarnings("unchecked") Class<? extends LocalInspectionTool> toolClass = c;
418 .collect(Collectors.toList());
419 enableInspections(classes);
423 public long testHighlighting(boolean checkWarnings, boolean checkInfos, boolean checkWeakWarnings, @NotNull String... filePaths) {
424 if (filePaths.length > 0) {
425 configureByFilesInner(filePaths);
427 return collectAndCheckHighlighting(checkWarnings, checkInfos, checkWeakWarnings);
431 public long testHighlightingAllFiles(boolean checkWarnings, boolean checkInfos, boolean checkWeakWarnings, @NotNull String... paths) {
432 return collectAndCheckHighlighting(checkWarnings, checkInfos, checkWeakWarnings, Stream.of(paths).map(this::copyFileToProject));
436 public long testHighlightingAllFiles(boolean checkWarnings,
438 boolean checkWeakWarnings,
439 @NotNull VirtualFile... files) {
440 return collectAndCheckHighlighting(checkWarnings, checkInfos, checkWeakWarnings, Stream.of(files));
443 private long collectAndCheckHighlighting(boolean checkWarnings,
445 boolean checkWeakWarnings,
446 Stream<VirtualFile> files) {
447 List<Trinity<PsiFile, Editor, ExpectedHighlightingData>> data = files.map(file -> {
448 PsiFile psiFile = myPsiManager.findFile(file);
449 assertNotNull(psiFile);
450 Document document = PsiDocumentManager.getInstance(getProject()).getDocument(psiFile);
451 assertNotNull(document);
452 ExpectedHighlightingData datum = new ExpectedHighlightingData(document, checkWarnings, checkWeakWarnings, checkInfos, psiFile);
454 return Trinity.create(psiFile, createEditor(file), datum);
455 }).collect(Collectors.toList());
457 for (Trinity<PsiFile, Editor, ExpectedHighlightingData> trinity : data) {
458 myEditor = trinity.second;
459 myFile = trinity.first.getVirtualFile();
460 elapsed += collectAndCheckHighlighting(trinity.third);
466 public long checkHighlighting(boolean checkWarnings, boolean checkInfos, boolean checkWeakWarnings) {
467 return checkHighlighting(checkWarnings, checkInfos, checkWeakWarnings, false);
471 public long checkHighlighting(boolean checkWarnings, boolean checkInfos, boolean checkWeakWarnings, boolean ignoreExtraHighlighting) {
472 return collectAndCheckHighlighting(checkWarnings, checkInfos, checkWeakWarnings, ignoreExtraHighlighting);
476 public long checkHighlighting() {
477 return checkHighlighting(true, false, true);
481 public long testHighlighting(@NotNull String... filePaths) {
482 return testHighlighting(true, false, true, filePaths);
486 public long testHighlighting(boolean checkWarnings, boolean checkInfos, boolean checkWeakWarnings, @NotNull VirtualFile file) {
487 openFileInEditor(file);
488 return collectAndCheckHighlighting(checkWarnings, checkInfos, checkWeakWarnings);
493 public HighlightTestInfo testFile(@NotNull String... filePath) {
494 return new HighlightTestInfo(myProjectFixture.getTestRootDisposable(), filePath) {
496 public HighlightTestInfo doTest() {
497 configureByFiles(filePaths);
498 ExpectedHighlightingData data =
499 new ExpectedHighlightingData(myEditor.getDocument(), checkWarnings, checkWeakWarnings, checkInfos, getFile());
500 if (checkSymbolNames) data.checkSymbolNames();
502 collectAndCheckHighlighting(data);
509 public void openFileInEditor(@NotNull final VirtualFile file) {
511 myEditor = createEditor(file);
515 public void testInspection(@NotNull String testDir, @NotNull InspectionToolWrapper toolWrapper) {
516 VirtualFile sourceDir = copyDirectoryToProject(new File(testDir, "src").getPath(), "");
517 PsiDirectory psiDirectory = getPsiManager().findDirectory(sourceDir);
518 assertNotNull(psiDirectory);
520 AnalysisScope scope = new AnalysisScope(psiDirectory);
523 GlobalInspectionContextForTests globalContext =
524 InspectionsKt.createGlobalContextForTool(scope, getProject(), Collections.<InspectionToolWrapper<?, ?>>singletonList(toolWrapper));
526 InspectionTestUtil.runTool(toolWrapper, scope, globalContext);
527 InspectionTestUtil.compareToolResults(globalContext, toolWrapper, false, new File(getTestDataPath(), testDir).getPath());
532 public PsiReference getReferenceAtCaretPosition(@NotNull final String... filePaths) {
533 if (filePaths.length > 0) {
534 configureByFilesInner(filePaths);
536 return getFile().findReferenceAt(myEditor.getCaretModel().getOffset());
541 public PsiReference getReferenceAtCaretPositionWithAssertion(@NotNull final String... filePaths) {
542 final PsiReference reference = getReferenceAtCaretPosition(filePaths);
543 assertNotNull("no reference found at " + myEditor.getCaretModel().getLogicalPosition(), reference);
549 public List<IntentionAction> getAvailableIntentions(@NotNull final String... filePaths) {
550 if (filePaths.length > 0) {
551 configureByFilesInner(filePaths);
553 return getAvailableIntentions();
558 public List<IntentionAction> getAllQuickFixes(@NotNull final String... filePaths) {
559 if (filePaths.length != 0) {
560 configureByFilesInner(filePaths);
562 List<HighlightInfo> infos = doHighlighting();
563 List<IntentionAction> actions = new ArrayList<>();
564 for (HighlightInfo info : infos) {
565 if (info.quickFixActionRanges != null) {
566 for (Pair<HighlightInfo.IntentionActionDescriptor, TextRange> pair : info.quickFixActionRanges) {
567 actions.add(pair.getFirst().getAction());
576 public List<IntentionAction> getAvailableIntentions() {
578 PsiFile file = getFile();
579 Editor editor = getEditor();
580 if (editor instanceof EditorWindow) {
581 editor = ((EditorWindow)editor).getDelegate();
582 file = InjectedLanguageUtil.getTopLevelFile(file);
585 return getAvailableIntentions(editor, file);
590 public List<IntentionAction> filterAvailableIntentions(@NotNull String hint) {
591 return getAvailableIntentions().stream().filter(action -> action.getText().startsWith(hint)).collect(Collectors.toList());
596 public IntentionAction findSingleIntention(@NotNull String hint) {
597 final List<IntentionAction> list = filterAvailableIntentions(hint);
598 if (list.isEmpty()) {
599 fail("\"" + hint + "\" not in [" + StringUtil.join(getAvailableIntentions(), INTENTION_NAME_FUN, ", ") + "]");
601 else if (list.size() > 1) {
602 fail("Too many intentions found for \"" + hint + "\": [" + StringUtil.join(list, INTENTION_NAME_FUN, ", ") + "]");
604 return UsefulTestCase.assertOneElement(list);
608 public IntentionAction getAvailableIntention(@NotNull final String intentionName, @NotNull final String... filePaths) {
609 List<IntentionAction> intentions = getAvailableIntentions(filePaths);
610 IntentionAction action = CodeInsightTestUtil.findIntentionByText(intentions, intentionName);
611 if (action == null) {
612 //noinspection UseOfSystemOutOrSystemErr
613 System.out.println(intentionName + " not found among " + StringUtil.join(intentions, IntentionAction::getText, ","));
619 public void launchAction(@NotNull final IntentionAction action) {
620 invokeIntention(action, getFile(), getEditor(), action.getText());
624 public void testCompletion(@NotNull String[] filesBefore, @NotNull @TestDataFile String fileAfter) {
625 testCompletionTyping(filesBefore, "", fileAfter);
629 public void testCompletionTyping(@NotNull final String[] filesBefore, @NotNull String toType, @NotNull final String fileAfter) {
631 configureByFiles(filesBefore);
632 complete(CompletionType.BASIC);
635 checkResultByFile(fileAfter);
637 catch (RuntimeException e) {
638 //noinspection UseOfSystemOutOrSystemErr
639 System.out.println("LookupElementStrings = " + getLookupElementStrings());
644 protected void assertInitialized() {
645 assertNotNull("setUp() hasn't been called", myPsiManager);
649 public void testCompletion(@NotNull String fileBefore,
650 @NotNull String fileAfter,
651 @TestDataFile @NotNull String... additionalFiles) {
652 testCompletionTyping(fileBefore, "", fileAfter, additionalFiles);
656 public void testCompletionTyping(@NotNull @TestDataFile String fileBefore,
657 @NotNull String toType,
658 @NotNull @TestDataFile String fileAfter,
659 @TestDataFile @NotNull String... additionalFiles) {
660 testCompletionTyping(ArrayUtil.reverseArray(ArrayUtil.append(additionalFiles, fileBefore)), toType, fileAfter);
664 public void testCompletionVariants(@NotNull final String fileBefore, @NotNull final String... expectedItems) {
666 final List<String> result = getCompletionVariants(fileBefore);
667 assertNotNull(result);
668 UsefulTestCase.assertSameElements(result, expectedItems);
672 public List<String> getCompletionVariants(@NotNull final String... filesBefore) {
674 configureByFiles(filesBefore);
675 final LookupElement[] items = complete(CompletionType.BASIC);
676 assertNotNull("No lookup was shown, probably there was only one lookup element that was inserted automatically", items);
677 return getLookupElementStrings();
682 public List<String> getLookupElementStrings() {
684 final LookupElement[] elements = getLookupElements();
685 if (elements == null) return null;
687 return ContainerUtil.map(elements, LookupElement::getLookupString);
691 public void finishLookup(final char completionChar) {
692 Runnable command = () -> {
693 LookupImpl lookup = (LookupImpl)LookupManager.getActiveLookup(getEditor());
694 assertNotNull(lookup);
695 lookup.finishLookup(completionChar);
697 CommandProcessor.getInstance().executeCommand(getProject(), command, null, null);
701 public void testRename(@NotNull final String fileBefore,
702 @NotNull String fileAfter,
703 @NotNull String newName,
704 @TestDataFile @NotNull String... additionalFiles) {
706 configureByFiles(ArrayUtil.reverseArray(ArrayUtil.append(additionalFiles, fileBefore)));
707 testRename(fileAfter, newName);
711 public void testRename(@NotNull final String fileAfter, @NotNull final String newName) {
712 renameElementAtCaret(newName);
713 checkResultByFile(fileAfter);
718 public PsiElement getElementAtCaret() {
720 Editor editor = getCompletionEditor();
721 int findTargetFlags = TargetElementUtil.REFERENCED_ELEMENT_ACCEPTED | TargetElementUtil.ELEMENT_NAME_ACCEPTED;
722 PsiElement element = TargetElementUtil.findTargetElement(editor, findTargetFlags);
724 // if no references found in injected fragment, try outer document
725 if (element == null && editor instanceof EditorWindow) {
726 element = TargetElementUtil.findTargetElement(((EditorWindow)editor).getDelegate(), findTargetFlags);
729 if (element == null) {
730 fail("element not found in file " + myFile.getName() +
731 " at caret position offset " + myEditor.getCaretModel().getOffset() + "," +
732 " psi structure:\n" + DebugUtil.psiToString(getFile(), true, true));
738 public void renameElementAtCaret(@NotNull final String newName) {
739 renameElement(getElementAtCaret(), newName);
743 public void renameElementAtCaretUsingHandler(@NotNull final String newName) {
744 final DataContext editorContext = ((EditorEx)myEditor).getDataContext();
745 final DataContext context = new DataContext() {
747 public Object getData(final String dataId) {
748 return PsiElementRenameHandler.DEFAULT_NAME.getName().equals(dataId)
750 : editorContext.getData(dataId);
753 final RenameHandler renameHandler = RenameHandlerRegistry.getInstance().getRenameHandler(context);
754 assertNotNull("No handler for this context", renameHandler);
756 renameHandler.invoke(getProject(), myEditor, getFile(), context);
760 public void renameElement(@NotNull final PsiElement element, @NotNull final String newName) {
761 final boolean searchInComments = false;
762 final boolean searchTextOccurrences = false;
763 renameElement(element, newName, searchInComments, searchTextOccurrences);
767 public void renameElement(@NotNull final PsiElement element,
768 @NotNull final String newName,
769 final boolean searchInComments,
770 final boolean searchTextOccurrences) {
771 final PsiElement substitution = RenamePsiElementProcessor.forElement(element).substituteElementToRename(element, myEditor);
772 if (substitution == null) return;
773 new RenameProcessor(getProject(), substitution, newName, searchInComments, searchTextOccurrences).run();
777 public <T extends PsiElement> T findElementByText(@NotNull String text, @NotNull Class<T> elementClass) {
778 Document document = PsiDocumentManager.getInstance(getProject()).getDocument(getFile());
779 assertNotNull(document);
780 int pos = document.getText().indexOf(text);
781 assertTrue(text, pos >= 0);
782 return PsiTreeUtil.getParentOfType(getFile().findElementAt(pos), elementClass);
786 public void type(final char c) {
788 ApplicationManager.getApplication().invokeAndWait((Runnable)() -> {
789 final EditorActionManager actionManager = EditorActionManager.getInstance();
791 performEditorAction(IdeActions.ACTION_EDITOR_BACKSPACE);
795 if (_performEditorAction(IdeActions.ACTION_CHOOSE_LOOKUP_ITEM)) {
798 if (_performEditorAction(IdeActions.ACTION_EDITOR_NEXT_TEMPLATE_VARIABLE)) {
802 performEditorAction(IdeActions.ACTION_EDITOR_ENTER);
806 if (_performEditorAction(IdeActions.ACTION_CHOOSE_LOOKUP_ITEM_REPLACE)) {
809 if (_performEditorAction(IdeActions.ACTION_EXPAND_LIVE_TEMPLATE_BY_TAB)) {
812 if (_performEditorAction(IdeActions.ACTION_EDITOR_NEXT_TEMPLATE_VARIABLE)) {
815 if (_performEditorAction(IdeActions.ACTION_EDITOR_TAB)) {
819 if (c == Lookup.COMPLETE_STATEMENT_SELECT_CHAR) {
820 if (_performEditorAction(IdeActions.ACTION_CHOOSE_LOOKUP_ITEM_COMPLETE_STATEMENT)) {
825 ActionManagerEx.getInstanceEx().fireBeforeEditorTyping(c, getEditorDataContext());
826 actionManager.getTypedAction().actionPerformed(getEditor(), c, getEditorDataContext());
831 private DataContext getEditorDataContext() {
832 return ((EditorEx)myEditor).getDataContext();
836 public void type(@NotNull String s) {
837 for (int i = 0; i < s.length(); i++) {
843 public void performEditorAction(@NotNull final String actionId) {
845 _performEditorAction(actionId);
848 private boolean _performEditorAction(@NotNull String actionId) {
849 final DataContext dataContext = getEditorDataContext();
851 final ActionManagerEx managerEx = ActionManagerEx.getInstanceEx();
852 final AnAction action = managerEx.getAction(actionId);
853 final AnActionEvent event = new AnActionEvent(null, dataContext, ActionPlaces.UNKNOWN, new Presentation(), managerEx, 0);
855 action.beforeActionPerformedUpdate(event);
857 if (!event.getPresentation().isEnabled()) {
861 managerEx.fireBeforeActionPerformed(action, dataContext, event);
863 action.actionPerformed(event);
865 managerEx.fireAfterActionPerformed(action, dataContext, event);
871 public Presentation testAction(@NotNull AnAction action) {
872 TestActionEvent e = new TestActionEvent(action);
873 action.beforeActionPerformedUpdate(e);
874 if (e.getPresentation().isEnabled() && e.getPresentation().isVisible()) {
875 action.actionPerformed(e);
877 return e.getPresentation();
882 public Collection<UsageInfo> testFindUsages(@NotNull final String... fileNames) {
884 configureByFiles(fileNames);
885 int flags = TargetElementUtil.ELEMENT_NAME_ACCEPTED | TargetElementUtil.REFERENCED_ELEMENT_ACCEPTED;
886 PsiElement targetElement = TargetElementUtil.findTargetElement(getEditor(), flags);
887 assertNotNull("Cannot find referenced element", targetElement);
888 return findUsages(targetElement);
893 public Collection<UsageInfo> findUsages(@NotNull final PsiElement targetElement) {
894 return findUsages(targetElement, null);
898 public Collection<UsageInfo> findUsages(@NotNull final PsiElement targetElement, @Nullable SearchScope scope) {
899 final Project project = getProject();
900 final FindUsagesHandler handler =
901 ((FindManagerImpl)FindManager.getInstance(project)).getFindUsagesManager().getFindUsagesHandler(targetElement, false);
903 final CommonProcessors.CollectProcessor<UsageInfo> processor = new CommonProcessors.CollectProcessor<>();
904 assertNotNull("Cannot find handler for: " + targetElement, handler);
905 final PsiElement[] psiElements = ArrayUtil.mergeArrays(handler.getPrimaryElements(), handler.getSecondaryElements());
906 final FindUsagesOptions options = handler.getFindUsagesOptions(null);
907 if (scope != null) options.searchScope = scope;
908 for (PsiElement psiElement : psiElements) {
909 handler.processElementUsages(psiElement, processor, options);
911 return processor.getResults();
916 public RangeHighlighter[] testHighlightUsages(@NotNull final String... files) {
917 configureByFiles(files);
918 testAction(new HighlightUsagesAction());
919 final Editor editor = getEditor();
920 //final Editor editor = com.intellij.openapi.actionSystem.CommonDataKeys.EDITOR.getData(DataManager.getInstance().getDataContext());
921 //assert editor != null;
922 //HighlightUsagesHandler.invoke(getProject(), editor, getFile());
923 return editor.getMarkupModel().getAllHighlighters();
927 public void moveFile(@NotNull final String filePath, @NotNull final String to, @TestDataFile @NotNull final String... additionalFiles) {
929 final Project project = getProject();
930 configureByFiles(ArrayUtil.reverseArray(ArrayUtil.append(additionalFiles, filePath)));
931 final VirtualFile file = findFileInTempDir(to);
932 assertNotNull("Directory " + to + " not found", file);
933 assertTrue(to + " is not a directory", file.isDirectory());
934 final PsiDirectory directory = myPsiManager.findDirectory(file);
935 new MoveFilesOrDirectoriesProcessor(project, new PsiElement[]{getFile()}, directory, false, false, null, null).run();
940 public GutterMark findGutter(@NotNull final String filePath) {
941 configureByFilesInner(filePath);
942 CommonProcessors.FindFirstProcessor<GutterMark> processor = new CommonProcessors.FindFirstProcessor<>();
944 processGuttersAtCaret(myEditor, getProject(), processor);
945 return processor.getFoundValue();
950 public List<GutterMark> findGuttersAtCaret() {
951 CommonProcessors.CollectProcessor<GutterMark> processor = new CommonProcessors.CollectProcessor<>();
953 processGuttersAtCaret(myEditor, getProject(), processor);
954 return new ArrayList<>(processor.getResults());
957 public static boolean processGuttersAtCaret(Editor editor, Project project, @NotNull Processor<GutterMark> processor) {
958 int offset = editor.getCaretModel().getOffset();
960 RangeHighlighter[] highlighters = DocumentMarkupModel.forDocument(editor.getDocument(), project, true).getAllHighlighters();
961 for (RangeHighlighter highlighter : highlighters) {
962 GutterMark renderer = highlighter.getGutterIconRenderer();
963 if (renderer != null &&
964 editor.getDocument().getLineNumber(offset) == editor.getDocument().getLineNumber(highlighter.getStartOffset()) &&
965 !processor.process(renderer)) {
974 public List<GutterMark> findAllGutters(@NotNull final String filePath) {
975 configureByFilesInner(filePath);
976 return findAllGutters();
981 public List<GutterMark> findAllGutters() {
982 final Project project = getProject();
983 final SortedMap<Integer, List<GutterMark>> result = new TreeMap<>();
985 List<HighlightInfo> infos = doHighlighting();
986 for (HighlightInfo info : infos) {
987 addGutterIconRenderer(info.getGutterIconRenderer(), info.startOffset, result);
990 RangeHighlighter[] highlighters = DocumentMarkupModel.forDocument(myEditor.getDocument(), project, true).getAllHighlighters();
991 for (final RangeHighlighter highlighter : highlighters) {
992 if (!highlighter.isValid()) continue;
993 addGutterIconRenderer(highlighter.getGutterIconRenderer(), highlighter.getStartOffset(), result);
995 return ContainerUtil.concat(result.values());
999 public PsiFile addFileToProject(@NotNull final String relativePath, @NotNull final String fileText) {
1000 assertInitialized();
1001 return addFileToProject(getTempDirPath(), relativePath, fileText);
1004 protected PsiFile addFileToProject(@NotNull final String rootPath, @NotNull final String relativePath, @NotNull final String fileText) {
1005 return new WriteCommandAction<PsiFile>(getProject()) {
1007 protected void run(@NotNull Result<PsiFile> result) throws Throwable {
1009 if (myTempDirFixture instanceof LightTempDirTestFixtureImpl) {
1010 final VirtualFile file = myTempDirFixture.createFile(relativePath, fileText);
1011 result.setResult(PsiManager.getInstance(getProject()).findFile(file));
1014 result.setResult(((HeavyIdeaTestFixture)myProjectFixture).addFileToProject(rootPath, relativePath, fileText));
1017 catch (IOException e) {
1018 throw new RuntimeException(e);
1021 PsiManager.getInstance(getProject()).dropPsiCaches();
1024 }.execute().getResultObject();
1027 public <T> void registerExtension(final ExtensionsArea area, final ExtensionPointName<T> epName, final T extension) {
1028 assertInitialized();
1029 final ExtensionPoint<T> extensionPoint = area.getExtensionPoint(epName);
1030 extensionPoint.registerExtension(extension);
1031 Disposer.register(myProjectFixture.getTestRootDisposable(), () -> extensionPoint.unregisterExtension(extension));
1036 public PsiManager getPsiManager() {
1037 return myPsiManager;
1041 public LookupElement[] complete(@NotNull CompletionType type) {
1042 return complete(type, 1);
1046 public LookupElement[] complete(@NotNull final CompletionType type, final int invocationCount) {
1047 assertInitialized();
1048 myEmptyLookup = false;
1049 ApplicationManager.getApplication().invokeAndWait(() -> CommandProcessor.getInstance().executeCommand(getProject(), () -> {
1050 final CodeCompletionHandlerBase handler = new CodeCompletionHandlerBase(type) {
1052 @SuppressWarnings("deprecation")
1053 protected void completionFinished(CompletionProgressIndicator indicator, boolean hasModifiers) {
1054 myEmptyLookup = indicator.getLookup().getItems().isEmpty();
1055 super.completionFinished(indicator, hasModifiers);
1058 Editor editor = getCompletionEditor();
1059 assertNotNull(editor);
1060 handler.invokeCompletion(getProject(), editor, invocationCount);
1061 PsiDocumentManager.getInstance(getProject()).commitAllDocuments(); // to compare with file text
1062 }, null, null, getEditor().getDocument()));
1063 return getLookupElements();
1067 protected Editor getCompletionEditor() {
1068 return InjectedLanguageUtil.getEditorForInjectedLanguageNoCommit(myEditor, getFile());
1073 public LookupElement[] completeBasic() {
1074 return complete(CompletionType.BASIC);
1079 public final List<LookupElement> completeBasicAllCarets(@Nullable final Character charToTypeAfterCompletion) {
1080 final CaretModel caretModel = myEditor.getCaretModel();
1081 final List<Caret> carets = caretModel.getAllCarets();
1083 final List<Integer> originalOffsets = new ArrayList<>(carets.size());
1085 for (final Caret caret : carets) {
1086 originalOffsets.add(caret.getOffset());
1088 caretModel.removeSecondaryCarets();
1090 // We do it in reverse order because completions would affect offsets
1091 // i.e.: when you complete "spa" to "spam", next caret offset increased by 1
1092 Collections.reverse(originalOffsets);
1093 final List<LookupElement> result = new ArrayList<>();
1094 for (final int originalOffset : originalOffsets) {
1095 caretModel.moveToOffset(originalOffset);
1096 final LookupElement[] lookupElements = completeBasic();
1097 if (charToTypeAfterCompletion != null) {
1098 type(charToTypeAfterCompletion);
1100 if (lookupElements != null) {
1101 result.addAll(Arrays.asList(lookupElements));
1108 public void saveText(@NotNull final VirtualFile file, @NotNull final String text) {
1111 protected void run(@NotNull Result result) throws Throwable {
1112 VfsUtil.saveText(file, text);
1114 }.execute().throwException();
1119 public LookupElement[] getLookupElements() {
1120 LookupImpl lookup = getLookup();
1121 if (lookup == null) {
1122 return myEmptyLookup ? LookupElement.EMPTY_ARRAY : null;
1125 final List<LookupElement> list = lookup.getItems();
1126 return list.toArray(new LookupElement[list.size()]);
1131 public void checkResult(@NotNull String text) {
1132 checkResult(text, false);
1136 public void checkResult(@NotNull String text, boolean stripTrailingSpaces) {
1137 new WriteCommandAction(getProject()) {
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());
1148 public void checkResult(@NotNull String filePath, @NotNull String text, boolean stripTrailingSpaces) {
1149 new WriteCommandAction(getProject()) {
1151 protected void run(@NotNull Result result) throws Throwable {
1152 PsiDocumentManager.getInstance(getProject()).commitAllDocuments();
1153 PsiFile psiFile = getFileToCheck(filePath);
1154 checkResult("TEXT", stripTrailingSpaces, SelectionAndCaretMarkupLoader.fromText(text), psiFile.getText());
1160 public void checkResultByFile(@NotNull String expectedFile) {
1161 checkResultByFile(expectedFile, false);
1165 public void checkResultByFile(@NotNull String expectedFile, boolean ignoreTrailingWhitespaces) {
1166 assertInitialized();
1167 ApplicationManager.getApplication().invokeAndWait(() -> checkResultByFile(expectedFile, getHostFile(), ignoreTrailingWhitespaces));
1171 public void checkResultByFile(@NotNull String filePath, @NotNull String expectedFile, boolean ignoreTrailingWhitespaces) {
1172 assertInitialized();
1173 ApplicationManager.getApplication().invokeAndWait(() -> checkResultByFile(expectedFile, getFileToCheck(filePath), ignoreTrailingWhitespaces));
1176 private PsiFile getFileToCheck(String filePath) {
1177 String path = filePath.replace(File.separatorChar, '/');
1178 VirtualFile copy = findFileInTempDir(path);
1179 assertNotNull("could not find results file " + path, copy);
1180 PsiFile psiFile = myPsiManager.findFile(copy);
1181 assertNotNull(copy.getPath(), psiFile);
1186 public void setUp() throws Exception {
1189 TestRunnerUtil.replaceIdeEventQueueSafely();
1190 EdtTestUtil.runInEdtAndWait(() -> {
1191 myProjectFixture.setUp();
1192 myTempDirFixture.setUp();
1194 VirtualFile tempDir = myTempDirFixture.getFile("");
1195 assertNotNull(tempDir);
1196 PlatformTestCase.synchronizeTempDirVfs(tempDir);
1198 myPsiManager = (PsiManagerImpl)PsiManager.getInstance(getProject());
1199 InspectionsKt.configureInspections(LocalInspectionTool.EMPTY_ARRAY, getProject(), myProjectFixture.getTestRootDisposable());
1201 DaemonCodeAnalyzerImpl daemonCodeAnalyzer = (DaemonCodeAnalyzerImpl)DaemonCodeAnalyzer.getInstance(getProject());
1202 daemonCodeAnalyzer.prepareForTest();
1204 DaemonCodeAnalyzerSettings.getInstance().setImportHintEnabled(false);
1205 ensureIndexesUpToDate(getProject());
1206 ((StartupManagerImpl)StartupManagerEx.getInstanceEx(getProject())).runPostStartupActivities();
1209 for (Module module : ModuleManager.getInstance(getProject()).getModules()) {
1210 ModuleRootManager.getInstance(module).orderEntries().getAllLibrariesAndSdkClassesRoots(); // instantiate all VFPs
1212 myVirtualFilePointerTracker = new VirtualFilePointerTracker();
1216 public void tearDown() throws Exception {
1218 EdtTestUtil.runInEdtAndWait(() -> {
1220 DaemonCodeAnalyzerSettings.getInstance().setImportHintEnabled(true); // return default value to avoid unnecessary save
1226 myPsiManager = null;
1227 myChooseByNamePopup = null;
1230 myProjectFixture.tearDown();
1233 myTempDirFixture.tearDown();
1240 myVirtualFilePointerTracker.assertPointersAreDisposed();
1244 private void closeOpenFiles() {
1245 PsiDocumentManager.getInstance(getProject()).commitAllDocuments();
1246 FileEditorManagerEx.getInstanceEx(getProject()).closeAllFiles();
1247 for (VirtualFile file : EditorHistoryManager.getInstance(getProject()).getFiles()) {
1248 EditorHistoryManager.getInstance(getProject()).removeFile(file);
1253 private PsiFile[] configureByFilesInner(@NotNull String... filePaths) {
1254 assertInitialized();
1257 PsiFile[] psiFiles = new PsiFile[filePaths.length];
1258 for (int i = filePaths.length - 1; i >= 0; i--) {
1259 psiFiles[i] = configureByFileInner(filePaths[i]);
1265 public PsiFile configureByFile(@NotNull final String file) {
1266 configureByFilesInner(file);
1272 public PsiFile[] configureByFiles(@NotNull final String... files) {
1273 return configureByFilesInner(files);
1277 public PsiFile configureByText(@NotNull final FileType fileType, @NotNull final String text) {
1278 assertInitialized();
1279 final String extension = fileType.getDefaultExtension();
1280 final FileTypeManager fileTypeManager = FileTypeManager.getInstance();
1281 if (fileTypeManager.getFileTypeByExtension(extension) != fileType) {
1282 new WriteCommandAction(getProject()) {
1284 protected void run(@NotNull Result result) throws Exception {
1285 fileTypeManager.associateExtension(fileType, extension);
1289 final String fileName = "aaa." + extension;
1290 return configureByText(fileName, text);
1294 public PsiFile configureByText(@NotNull final String fileName, @NotNull final String text) {
1295 assertInitialized();
1296 VirtualFile vFile = new WriteCommandAction<VirtualFile>(getProject()) {
1298 protected void run(@NotNull Result<VirtualFile> result) throws Throwable {
1299 final VirtualFile vFile;
1300 if (myTempDirFixture instanceof LightTempDirTestFixtureImpl) {
1301 final VirtualFile root = LightPlatformTestCase.getSourceRoot();
1302 root.refresh(false, false);
1303 vFile = root.findOrCreateChildData(this, fileName);
1304 assertNotNull(fileName + " not found in " + root.getPath(), vFile);
1306 else if (myTempDirFixture instanceof TempDirTestFixtureImpl) {
1307 final File tempFile = ((TempDirTestFixtureImpl)myTempDirFixture).createTempFile(fileName);
1308 vFile = LocalFileSystem.getInstance().refreshAndFindFileByIoFile(tempFile);
1309 assertNotNull(tempFile + " not found", vFile);
1312 vFile = LocalFileSystem.getInstance().refreshAndFindFileByIoFile(new File(getTempDirPath(), fileName));
1313 assertNotNull(fileName + " not found in " + getTempDirPath(), vFile);
1316 prepareVirtualFile(vFile);
1318 final Document document = FileDocumentManager.getInstance().getCachedDocument(vFile);
1319 if (document != null) {
1320 PsiDocumentManager.getInstance(getProject()).doPostponedOperationsAndUnblockDocument(document);
1321 FileDocumentManager.getInstance().saveDocument(document);
1324 VfsUtil.saveText(vFile, text);
1325 result.setResult(vFile);
1327 }.execute().getResultObject();
1328 configureInner(vFile, SelectionAndCaretMarkupLoader.fromFile(vFile));
1333 public Document getDocument(@NotNull final PsiFile file) {
1334 assertInitialized();
1335 return PsiDocumentManager.getInstance(getProject()).getDocument(file);
1338 private PsiFile configureByFileInner(@NotNull String filePath) {
1339 assertInitialized();
1340 final VirtualFile file = copyFileToProject(filePath);
1341 return configureByFileInner(file);
1345 public PsiFile configureFromTempProjectFile(@NotNull final String filePath) {
1346 final VirtualFile fileInTempDir = findFileInTempDir(filePath);
1347 if (fileInTempDir == null) {
1348 throw new IllegalArgumentException("Could not find file in temp dir: " + filePath);
1350 return configureByFileInner(fileInTempDir);
1354 public void configureFromExistingVirtualFile(@NotNull VirtualFile virtualFile) {
1355 configureByFileInner(virtualFile);
1358 private PsiFile configureByFileInner(@NotNull VirtualFile copy) {
1359 return configureInner(copy, SelectionAndCaretMarkupLoader.fromFile(copy));
1362 private PsiFile configureInner(@NotNull final VirtualFile copy, @NotNull final SelectionAndCaretMarkupLoader loader) {
1363 assertInitialized();
1365 EdtTestUtil.runInEdtAndWait(() -> {
1366 if (!copy.getFileType().isBinary()) {
1368 WriteAction.run(() -> copy.setBinaryContent(loader.newFileText.getBytes(copy.getCharset())));
1370 catch (IOException e) {
1371 throw new RuntimeException(e);
1375 myEditor = createEditor(copy);
1376 if (myEditor == null) {
1377 fail("editor couldn't be created for: " + copy.getPath() + ", use copyFileToProject() instead of configureByFile()");
1380 EditorTestUtil.setCaretsAndSelection(myEditor, loader.caretState);
1382 Module module = getModule();
1383 if (module != null) {
1384 for (Facet facet : FacetManager.getInstance(module).getAllFacets()) {
1385 module.getMessageBus().syncPublisher(FacetManager.FACETS_TOPIC).facetConfigurationChanged(facet);
1388 PsiDocumentManager.getInstance(getProject()).commitAllDocuments();
1390 if (myCaresAboutInjection) {
1391 setupEditorForInjectedLanguage();
1398 protected void prepareVirtualFile(@NotNull VirtualFile file) {
1401 private void setupEditorForInjectedLanguage() {
1402 Editor editor = InjectedLanguageUtil.getEditorForInjectedLanguageNoCommit(myEditor, getFile());
1403 if (editor instanceof EditorWindow) {
1404 myFile = ((EditorWindow)editor).getInjectedFile().getViewProvider().getVirtualFile();
1410 public VirtualFile findFileInTempDir(@NotNull final String filePath) {
1411 if (myTempDirFixture instanceof LightTempDirTestFixtureImpl) {
1412 return myTempDirFixture.getFile(filePath);
1414 String fullPath = getTempDirPath() + "/" + filePath;
1416 final VirtualFile copy = LocalFileSystem.getInstance().refreshAndFindFileByPath(fullPath.replace(File.separatorChar, '/'));
1417 assertNotNull("file " + fullPath + " not found", copy);
1418 VfsTestUtil.assertFilePathEndsWithCaseSensitivePath(copy, filePath);
1423 protected Editor createEditor(@NotNull VirtualFile file) {
1424 final Project project = getProject();
1425 final FileEditorManager instance = FileEditorManager.getInstance(project);
1426 PsiDocumentManager.getInstance(getProject()).commitAllDocuments();
1428 Editor editor = instance.openTextEditor(new OpenFileDescriptor(project, file), false);
1429 EditorTestUtil.waitForLoading(editor);
1430 if (editor != null) {
1431 DaemonCodeAnalyzer.getInstance(getProject()).restart();
1436 private long collectAndCheckHighlighting(boolean checkWarnings, boolean checkInfos, boolean checkWeakWarnings) {
1437 return collectAndCheckHighlighting(checkWarnings, checkInfos, checkWeakWarnings, false);
1440 private long collectAndCheckHighlighting(boolean checkWarnings,
1442 boolean checkWeakWarnings,
1443 boolean ignoreExtraHighlighting) {
1444 ExpectedHighlightingData data = new ExpectedHighlightingData(
1445 myEditor.getDocument(), checkWarnings, checkWeakWarnings, checkInfos, ignoreExtraHighlighting, getHostFile());
1447 return collectAndCheckHighlighting(data);
1450 private PsiFile getHostFile() {
1451 return InjectedLanguageUtil.getTopLevelFile(getFile());
1454 private long collectAndCheckHighlighting(@NotNull ExpectedHighlightingData data) {
1455 final Project project = getProject();
1456 EdtTestUtil.runInEdtAndWait(() -> PsiDocumentManager.getInstance(project).commitAllDocuments());
1458 PsiFileImpl file = (PsiFileImpl)getHostFile();
1459 FileElement hardRefToFileElement = file.calcTreeElement();//to load text
1461 //to initialize caches
1462 if (!DumbService.isDumb(project)) {
1463 CacheManager.SERVICE.getInstance(project)
1464 .getFilesWithWord("XXX", UsageSearchContext.IN_COMMENTS, GlobalSearchScope.allScope(project), true);
1467 final long start = System.currentTimeMillis();
1468 final VirtualFileFilter fileTreeAccessFilter = myVirtualFileFilter;
1469 Disposable disposable = Disposer.newDisposable();
1470 if (fileTreeAccessFilter != null) {
1471 PsiManagerEx.getInstanceEx(project).setAssertOnFileLoadingFilter(fileTreeAccessFilter, disposable);
1474 // ProfilingUtil.startCPUProfiling();
1475 List<HighlightInfo> infos;
1477 infos = doHighlighting();
1478 removeDuplicatedRangesForInjected(infos);
1481 Disposer.dispose(disposable);
1483 // ProfilingUtil.captureCPUSnapshot("testing");
1484 final long elapsed = System.currentTimeMillis() - start;
1486 data.checkResult(infos, file.getText());
1487 if (data.hasLineMarkers()) {
1488 Document document = getDocument(getFile());
1489 data.checkLineMarkers(DaemonCodeAnalyzerImpl.getLineMarkers(document, getProject()), document.getText());
1491 //noinspection ResultOfMethodCallIgnored
1492 hardRefToFileElement.hashCode(); // use it so gc won't collect it
1496 public void setVirtualFileFilter(@Nullable VirtualFileFilter filter) {
1497 myVirtualFileFilter = filter;
1502 public List<HighlightInfo> doHighlighting() {
1503 final Project project = getProject();
1504 EdtTestUtil.runInEdtAndWait(() -> PsiDocumentManager.getInstance(project).commitAllDocuments());
1506 PsiFile file = getFile();
1507 Editor editor = getEditor();
1508 if (editor instanceof EditorWindow) {
1509 editor = ((EditorWindow)editor).getDelegate();
1510 file = InjectedLanguageUtil.getTopLevelFile(file);
1512 assertNotNull(file);
1513 return instantiateAndRun(file, editor, ArrayUtil.EMPTY_INT_ARRAY, myAllowDirt);
1518 public List<HighlightInfo> doHighlighting(@NotNull final HighlightSeverity minimalSeverity) {
1519 return ContainerUtil.filter(doHighlighting(), info -> info.getSeverity().compareTo(minimalSeverity) >= 0);
1524 public String getTestDataPath() {
1525 return myTestDataPath;
1529 public void setTestDataPath(@NotNull String dataPath) {
1530 myTestDataPath = dataPath;
1534 public Project getProject() {
1535 return myProjectFixture.getProject();
1539 public Module getModule() {
1540 return myProjectFixture.getModule();
1544 public Editor getEditor() {
1549 public int getCaretOffset() {
1550 return myEditor.getCaretModel().getOffset();
1554 public PsiFile getFile() {
1555 return myFile != null ? ReadAction.compute(() -> PsiManager.getInstance(getProject()).findFile(myFile)) : null;
1559 public void allowTreeAccessForFile(@NotNull final VirtualFile file) {
1560 assert myVirtualFileFilter instanceof FileTreeAccessFilter : "configured filter does not support this method";
1561 ((FileTreeAccessFilter)myVirtualFileFilter).allowTreeAccessForFile(file);
1565 public void allowTreeAccessForAllFiles() {
1566 assert myVirtualFileFilter instanceof FileTreeAccessFilter : "configured filter does not support this method";
1567 ((FileTreeAccessFilter)myVirtualFileFilter).allowTreeAccessForAllFiles();
1570 private void checkResultByFile(@NotNull String expectedFile, @NotNull PsiFile originalFile, boolean stripTrailingSpaces) {
1571 if (!stripTrailingSpaces) {
1572 EditorUtil.fillVirtualSpaceUntilCaret(myEditor);
1575 PsiDocumentManager.getInstance(getProject()).commitAllDocuments();
1577 String fileText = originalFile.getText();
1578 String path = getTestDataPath() + "/" + expectedFile;
1579 String charset = Optional.ofNullable(originalFile.getVirtualFile()).map(f -> f.getCharset().name()).orElse(null);
1580 checkResult(expectedFile, stripTrailingSpaces, SelectionAndCaretMarkupLoader.fromFile(path, charset), fileText);
1583 private void checkResult(@NotNull String expectedFile,
1584 boolean stripTrailingSpaces,
1585 @NotNull SelectionAndCaretMarkupLoader loader,
1586 @NotNull String actualText) {
1587 assertInitialized();
1588 Project project = getProject();
1589 Editor editor = getEditor();
1590 if (editor instanceof EditorWindow) {
1591 editor = ((EditorWindow)editor).getDelegate();
1594 UsefulTestCase.doPostponedFormatting(getProject());
1595 if (stripTrailingSpaces) {
1596 actualText = stripTrailingSpaces(actualText);
1599 PsiDocumentManager.getInstance(project).commitAllDocuments();
1601 String newFileText1 = loader.newFileText;
1602 if (stripTrailingSpaces) {
1603 newFileText1 = stripTrailingSpaces(newFileText1);
1606 actualText = StringUtil.convertLineSeparators(actualText);
1608 if (!Comparing.equal(newFileText1, actualText)) {
1609 if (loader.filePath != null) {
1610 throw new FileComparisonFailure(expectedFile, newFileText1, actualText, loader.filePath);
1613 throw new ComparisonFailure(expectedFile, newFileText1, actualText);
1617 EditorTestUtil.verifyCaretAndSelectionState(editor, loader.caretState, expectedFile);
1621 private String stripTrailingSpaces(@NotNull String actualText) {
1622 final Document document = EditorFactory.getInstance().createDocument(actualText);
1623 ((DocumentImpl)document).stripTrailingSpaces(getProject());
1624 actualText = document.getText();
1628 public void canChangeDocumentDuringHighlighting(boolean canI) {
1633 public String getFoldingDescription(boolean withCollapseStatus) {
1634 CodeFoldingManager.getInstance(getProject()).buildInitialFoldings(myEditor);
1635 return getTagsFromSegments(myEditor.getDocument().getText(),
1636 Arrays.asList(myEditor.getFoldingModel().getAllFoldRegions()),
1638 foldRegion -> "text=\'" + foldRegion.getPlaceholderText() + "\'"
1639 + (withCollapseStatus ? (" expand=\'" + foldRegion.isExpanded() + "\'") : ""));
1643 public static <T extends Segment> String getTagsFromSegments(@NotNull String text,
1644 @NotNull Collection<T> segments,
1645 @NotNull String tagName,
1646 @Nullable Function<T, String> attrCalculator) {
1647 final List<Border> borders = new LinkedList<>();
1648 for (T region : segments) {
1649 String attr = attrCalculator == null ? null : attrCalculator.fun(region);
1650 borders.add(new CodeInsightTestFixtureImpl.Border(true, region.getStartOffset(), attr));
1651 borders.add(new CodeInsightTestFixtureImpl.Border(false, region.getEndOffset(), ""));
1653 Collections.sort(borders);
1655 StringBuilder result = new StringBuilder(text);
1656 for (CodeInsightTestFixtureImpl.Border border : borders) {
1657 StringBuilder info = new StringBuilder();
1659 if (border.isLeftBorder) {
1660 info.append(tagName);
1661 if (border.text != null) {
1662 info.append(' ').append(border.text);
1666 info.append('/').append(tagName);
1669 result.insert(border.offset, info);
1671 return result.toString();
1674 private void testFoldingRegions(@NotNull String verificationFileName,
1675 @Nullable String destinationFileName,
1676 boolean doCheckCollapseStatus) {
1677 String expectedContent;
1678 final File verificationFile;
1680 verificationFile = new File(verificationFileName);
1681 expectedContent = FileUtil.loadFile(verificationFile);
1683 catch (IOException e) {
1684 throw new RuntimeException(e);
1686 assertNotNull(expectedContent);
1688 expectedContent = StringUtil.replace(expectedContent, "\r", "");
1689 final String cleanContent = expectedContent.replaceAll("<" + FOLD + "\\stext=\'[^\']*\'(\\sexpand=\'[^\']*\')*>", "")
1690 .replace("</" + FOLD + ">", "");
1691 if (destinationFileName == null) {
1692 configureByText(FileTypeManager.getInstance().getFileTypeByFileName(verificationFileName), cleanContent);
1696 FileUtil.writeToFile(new File(destinationFileName), cleanContent);
1697 VirtualFile file = LocalFileSystem.getInstance().refreshAndFindFileByPath(destinationFileName);
1698 assertNotNull(file);
1699 configureFromExistingVirtualFile(file);
1701 catch (IOException e) {
1702 throw new RuntimeException(e);
1705 final String actual = getFoldingDescription(doCheckCollapseStatus);
1706 if (!expectedContent.equals(actual)) {
1707 throw new FileComparisonFailure(verificationFile.getName(), expectedContent, actual, verificationFile.getPath());
1712 public void testFoldingWithCollapseStatus(@NotNull final String verificationFileName) {
1713 testFoldingRegions(verificationFileName, null, true);
1717 public void testFoldingWithCollapseStatus(@NotNull final String verificationFileName, @Nullable String destinationFileName) {
1718 testFoldingRegions(verificationFileName, destinationFileName, true);
1722 public void testFolding(@NotNull final String verificationFileName) {
1723 testFoldingRegions(verificationFileName, null, false);
1727 public void testRainbow(@NotNull String fileName, @NotNull String text, boolean isRainbowOn, boolean withColor) {
1728 final EditorColorsScheme globalScheme = EditorColorsManager.getInstance().getGlobalScheme();
1729 final boolean isRainbowOnInScheme = RainbowHighlighter.isRainbowEnabled(globalScheme, null);
1731 RainbowHighlighter.setRainbowEnabled(globalScheme, null, isRainbowOn);
1732 configureByText(fileName, text.replaceAll("<" + RAINBOW + "(\\scolor=\'[^\']*\')?>", "").replace("</" + RAINBOW + ">", ""));
1734 List<HighlightInfo> highlighting = ContainerUtil.filter(doHighlighting(), info -> info.type == RainbowHighlighter.RAINBOW_ELEMENT);
1735 assertEquals(text, getTagsFromSegments(myEditor.getDocument().getText(), highlighting, RAINBOW, highlightInfo -> {
1739 TextAttributes attributes = highlightInfo.getTextAttributes(null, null);
1740 String color = attributes == null ? "null"
1741 : attributes.getForegroundColor() == null
1743 : Integer.toHexString(attributes.getForegroundColor().getRGB());
1744 return "color=\'" + color + "\'";
1748 RainbowHighlighter.setRainbowEnabled(globalScheme, null, isRainbowOnInScheme);
1753 public void testInlays() {
1754 InlayHintsChecker checker = new InlayHintsChecker(this);
1757 checker.checkInlays();
1765 public void checkResultWithInlays(String text) {
1766 Document checkDocument = new DocumentImpl(text);
1767 InlayHintsChecker checker = new InlayHintsChecker(this);
1768 CaretAndInlaysInfo inlaysAndCaretInfo = checker.extractInlaysAndCaretInfo(checkDocument);
1769 checkResult(checkDocument.getText());
1770 checker.verifyInlaysAndCaretInfo(inlaysAndCaretInfo, text);
1774 public void assertPreferredCompletionItems(final int selected, @NotNull final String... expected) {
1775 final LookupImpl lookup = getLookup();
1776 assertNotNull("No lookup is shown", lookup);
1778 final JList list = lookup.getList();
1779 List<String> strings = getLookupElementStrings();
1780 assertNotNull(strings);
1781 final List<String> actual = strings.subList(0, Math.min(expected.length, strings.size()));
1782 if (!actual.equals(Arrays.asList(expected))) {
1783 UsefulTestCase.assertOrderedEquals(DumpLookupElementWeights.getLookupElementWeights(lookup, false), expected);
1785 if (selected != list.getSelectedIndex()) {
1786 //noinspection UseOfSystemOutOrSystemErr
1787 System.out.println(DumpLookupElementWeights.getLookupElementWeights(lookup, false));
1789 assertEquals(selected, list.getSelectedIndex());
1793 public void testStructureView(@NotNull Consumer<StructureViewComponent> consumer) {
1794 assertNotNull("configure first", myFile);
1796 final FileEditor fileEditor = FileEditorManager.getInstance(getProject()).getSelectedEditor(myFile);
1797 assertNotNull("editor not opened for " + myFile, myFile);
1799 final StructureViewBuilder builder = LanguageStructureViewBuilder.INSTANCE.getStructureViewBuilder(getFile());
1800 assertNotNull("no builder for " + myFile, builder);
1802 StructureViewComponent component = null;
1804 component = (StructureViewComponent)builder.createStructureView(fileEditor, getProject());
1805 consumer.consume(component);
1808 if (component != null) Disposer.dispose(component);
1813 public void setCaresAboutInjection(boolean caresAboutInjection) {
1814 myCaresAboutInjection = caresAboutInjection;
1818 public LookupImpl getLookup() {
1819 return (LookupImpl)LookupManager.getActiveLookup(myEditor);
1824 public List<Object> getGotoClassResults(@NotNull String pattern, boolean searchEverywhere, @Nullable PsiElement contextForSorting) {
1825 final ChooseByNameBase chooseByNamePopup = getMockChooseByNamePopup(contextForSorting);
1826 final ArrayList<Object> results = new ArrayList<>();
1827 chooseByNamePopup.getProvider().filterElements(chooseByNamePopup,
1828 chooseByNamePopup.transformPattern(pattern),
1830 new MockProgressIndicator(),
1831 new CommonProcessors.CollectProcessor<>(results));
1837 public List<Crumb> getBreadcrumbsAtCaret() {
1838 PsiElement element = getFile().findElementAt(getCaretOffset());
1839 if (element == null) {
1840 return Collections.emptyList();
1842 final Language language = element.getContainingFile().getLanguage();
1844 final BreadcrumbsProvider provider = BreadcrumbsUtil.getInfoProvider(language);
1846 if (provider == null) {
1847 return Collections.emptyList();
1850 List<Crumb> result = new ArrayList<>();
1851 while (element != null) {
1852 if (provider.acceptElement(element)) {
1853 result.add(new Crumb.Impl(provider.getElementIcon(element), provider.getElementInfo(element), provider.getElementTooltip(element)));
1855 element = provider.getParent(element);
1857 return ContainerUtil.reverse(result);
1861 private ChooseByNameBase getMockChooseByNamePopup(@Nullable PsiElement contextForSorting) {
1862 final Project project = getProject();
1863 if (contextForSorting != null) {
1864 return ChooseByNamePopup.createPopup(project, new GotoClassModel2(project), contextForSorting);
1866 if (myChooseByNamePopup == null) {
1867 myChooseByNamePopup = ChooseByNamePopup.createPopup(project, new GotoClassModel2(project), (PsiElement)null);
1869 return myChooseByNamePopup;
1872 protected void bringRealEditorBack() {
1873 PsiDocumentManager.getInstance(getProject()).commitAllDocuments();
1874 if (myEditor instanceof EditorWindow) {
1875 Document document = ((DocumentWindow)myEditor.getDocument()).getDelegate();
1876 myFile = FileDocumentManager.getInstance().getFile(document);
1877 myEditor = ((EditorWindow)myEditor).getDelegate();
1881 public static boolean invokeIntention(@NotNull IntentionAction action, PsiFile file, Editor editor, String actionText) {
1882 // Test that action will automatically clear the read-only attribute if modification is necessary.
1883 // If your test fails due to this, make sure that your quick-fix/intention
1884 // overrides "getElementToMakeWritable" or has the following line:
1885 // if (!FileModificationService.getInstance().prepareFileForWrite(file)) return;
1887 Project project = file.getProject();
1888 ReadonlyStatusHandlerImpl handler = (ReadonlyStatusHandlerImpl)ReadonlyStatusHandler.getInstance(project);
1889 VirtualFile vFile = Objects.requireNonNull(InjectedLanguageUtil.getTopLevelFile(file)).getVirtualFile();
1890 setReadOnly(vFile, true);
1891 handler.setClearReadOnlyInTests(true);
1892 AtomicBoolean result = new AtomicBoolean();
1894 ApplicationManager.getApplication().invokeLater(() -> {
1896 result.set(ShowIntentionActionsHandler.chooseActionAndInvoke(file, editor, action, actionText));
1898 catch (StubTextInconsistencyException e) {
1899 PsiTestUtil.compareStubTexts(e);
1902 UIUtil.dispatchAllInvocationEvents();
1903 checkPsiTextConsistency(project, vFile);
1905 catch (AssertionError e) {
1906 ExceptionUtil.rethrowUnchecked(ExceptionUtil.getRootCause(e));
1910 handler.setClearReadOnlyInTests(false);
1911 setReadOnly(vFile, false);
1913 return result.get();
1916 private static void checkPsiTextConsistency(Project project, VirtualFile vFile) {
1917 PsiFile topLevelPsi = vFile.isValid() ? PsiManager.getInstance(project).findFile(vFile) : null;
1918 if (topLevelPsi != null) {
1919 PsiTestUtil.checkStubsMatchText(topLevelPsi);
1923 private static void setReadOnly(VirtualFile vFile, boolean readOnlyStatus) {
1925 WriteAction.run(() -> ReadOnlyAttributeUtil.setReadOnlyAttribute(vFile, readOnlyStatus));
1927 catch (IOException e) {
1928 throw new UncheckedIOException(e);
1932 private static class SelectionAndCaretMarkupLoader {
1933 private final String filePath;
1934 private final String newFileText;
1935 private final EditorTestUtil.CaretAndSelectionState caretState;
1937 private SelectionAndCaretMarkupLoader(@NotNull String fileText, String filePath) {
1938 this.filePath = filePath;
1939 final Document document = EditorFactory.getInstance().createDocument(fileText);
1940 caretState = EditorTestUtil.extractCaretAndSelectionMarkers(document);
1941 newFileText = document.getText();
1945 private static SelectionAndCaretMarkupLoader fromFile(@NotNull String path, String charset) {
1946 return fromIoSource(() -> FileUtil.loadFile(new File(path), charset), path);
1950 private static SelectionAndCaretMarkupLoader fromFile(@NotNull VirtualFile file) {
1951 return fromIoSource(() -> VfsUtilCore.loadText(file), file.getPath());
1955 private static SelectionAndCaretMarkupLoader fromIoSource(@NotNull ThrowableComputable<String, IOException> source, String path) {
1957 return new SelectionAndCaretMarkupLoader(StringUtil.convertLineSeparators(source.compute()), path);
1959 catch (IOException e) {
1960 throw new RuntimeException(e);
1965 private static SelectionAndCaretMarkupLoader fromText(@NotNull String text) {
1966 return new SelectionAndCaretMarkupLoader(text, null);
1970 private static class Border implements Comparable<Border> {
1971 private final boolean isLeftBorder;
1972 private final int offset;
1973 private final String text;
1975 private Border(boolean isLeftBorder, int offset, String text) {
1976 this.isLeftBorder = isLeftBorder;
1977 this.offset = offset;
1982 public int compareTo(@NotNull Border o) {
1983 return offset < o.offset ? 1 : -1;
1988 public Disposable getProjectDisposable() {
1989 return myProjectFixture.getTestRootDisposable();
1992 //<editor-fold desc="Deprecated stuff.">
1994 public static GlobalInspectionContextForTests createGlobalContextForTool(@NotNull AnalysisScope scope,
1995 @NotNull final Project project,
1996 @NotNull InspectionManagerEx inspectionManager,
1997 @NotNull final InspectionToolWrapper... toolWrappers) {
1998 return InspectionsKt.createGlobalContextForTool(scope, project, Arrays.<InspectionToolWrapper<?, ?>>asList(toolWrappers));