2 * Copyright 2000-2011 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.
17 package com.intellij.testFramework.fixtures.impl;
19 import com.intellij.analysis.AnalysisScope;
20 import com.intellij.codeHighlighting.HighlightDisplayLevel;
21 import com.intellij.codeInsight.TargetElementUtilBase;
22 import com.intellij.codeInsight.completion.CodeCompletionHandlerBase;
23 import com.intellij.codeInsight.completion.CompletionProgressIndicator;
24 import com.intellij.codeInsight.completion.CompletionType;
25 import com.intellij.codeInsight.daemon.DaemonCodeAnalyzer;
26 import com.intellij.codeInsight.daemon.DaemonCodeAnalyzerSettings;
27 import com.intellij.codeInsight.daemon.HighlightDisplayKey;
28 import com.intellij.codeInsight.daemon.impl.DaemonCodeAnalyzerImpl;
29 import com.intellij.codeInsight.daemon.impl.HighlightInfo;
30 import com.intellij.codeInsight.daemon.impl.HighlightInfoType;
31 import com.intellij.codeInsight.daemon.impl.ShowIntentionsPass;
32 import com.intellij.codeInsight.folding.CodeFoldingManager;
33 import com.intellij.codeInsight.highlighting.actions.HighlightUsagesAction;
34 import com.intellij.codeInsight.intention.IntentionAction;
35 import com.intellij.codeInsight.intention.impl.ShowIntentionActionsHandler;
36 import com.intellij.codeInsight.lookup.LookupElement;
37 import com.intellij.codeInsight.lookup.LookupManager;
38 import com.intellij.codeInsight.lookup.impl.LookupImpl;
39 import com.intellij.codeInspection.*;
40 import com.intellij.codeInspection.ex.*;
41 import com.intellij.facet.Facet;
42 import com.intellij.facet.FacetManager;
43 import com.intellij.find.FindManager;
44 import com.intellij.find.findUsages.FindUsagesHandler;
45 import com.intellij.find.findUsages.FindUsagesOptions;
46 import com.intellij.find.impl.FindManagerImpl;
47 import com.intellij.ide.DataManager;
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.lang.LanguageStructureViewBuilder;
53 import com.intellij.openapi.Disposable;
54 import com.intellij.openapi.actionSystem.*;
55 import com.intellij.openapi.actionSystem.ex.ActionManagerEx;
56 import com.intellij.openapi.application.ApplicationManager;
57 import com.intellij.openapi.application.Result;
58 import com.intellij.openapi.command.CommandProcessor;
59 import com.intellij.openapi.command.WriteCommandAction;
60 import com.intellij.openapi.editor.*;
61 import com.intellij.openapi.editor.actionSystem.DocCommandGroupId;
62 import com.intellij.openapi.editor.actionSystem.EditorActionManager;
63 import com.intellij.openapi.editor.ex.EditorEx;
64 import com.intellij.openapi.editor.ex.util.EditorUtil;
65 import com.intellij.openapi.editor.impl.DocumentImpl;
66 import com.intellij.openapi.editor.impl.DocumentMarkupModel;
67 import com.intellij.openapi.editor.markup.GutterIconRenderer;
68 import com.intellij.openapi.editor.markup.RangeHighlighter;
69 import com.intellij.openapi.extensions.ExtensionPoint;
70 import com.intellij.openapi.extensions.ExtensionPointName;
71 import com.intellij.openapi.extensions.Extensions;
72 import com.intellij.openapi.extensions.ExtensionsArea;
73 import com.intellij.openapi.fileEditor.*;
74 import com.intellij.openapi.fileEditor.impl.text.TextEditorProvider;
75 import com.intellij.openapi.fileTypes.FileType;
76 import com.intellij.openapi.fileTypes.FileTypeManager;
77 import com.intellij.openapi.fileTypes.StdFileTypes;
78 import com.intellij.openapi.module.Module;
79 import com.intellij.openapi.project.DumbService;
80 import com.intellij.openapi.project.Project;
81 import com.intellij.openapi.util.*;
82 import com.intellij.openapi.util.io.FileUtil;
83 import com.intellij.openapi.util.text.StringUtil;
84 import com.intellij.openapi.vfs.LocalFileSystem;
85 import com.intellij.openapi.vfs.VfsUtil;
86 import com.intellij.openapi.vfs.VirtualFile;
87 import com.intellij.openapi.vfs.VirtualFileFilter;
88 import com.intellij.profile.codeInspection.InspectionProfileManager;
89 import com.intellij.profile.codeInspection.InspectionProjectProfileManager;
90 import com.intellij.psi.*;
91 import com.intellij.psi.codeStyle.CodeStyleSettingsManager;
92 import com.intellij.psi.impl.PsiManagerImpl;
93 import com.intellij.psi.impl.PsiModificationTrackerImpl;
94 import com.intellij.psi.impl.cache.CacheManager;
95 import com.intellij.psi.impl.cache.impl.todo.TodoIndex;
96 import com.intellij.psi.impl.source.PostprocessReformattingAspect;
97 import com.intellij.psi.impl.source.PsiFileImpl;
98 import com.intellij.psi.impl.source.tree.injected.InjectedLanguageUtil;
99 import com.intellij.psi.search.GlobalSearchScope;
100 import com.intellij.psi.search.UsageSearchContext;
101 import com.intellij.psi.statistics.StatisticsManager;
102 import com.intellij.psi.statistics.impl.StatisticsManagerImpl;
103 import com.intellij.psi.stubs.StubUpdatingIndex;
104 import com.intellij.psi.util.PsiTreeUtil;
105 import com.intellij.refactoring.move.moveFilesOrDirectories.MoveFilesOrDirectoriesProcessor;
106 import com.intellij.refactoring.rename.RenameProcessor;
107 import com.intellij.refactoring.rename.RenamePsiElementProcessor;
108 import com.intellij.testFramework.*;
109 import com.intellij.testFramework.fixtures.*;
110 import com.intellij.usageView.UsageInfo;
111 import com.intellij.util.*;
112 import com.intellij.util.containers.ContainerUtil;
113 import com.intellij.util.indexing.FileBasedIndex;
114 import com.intellij.util.ui.UIUtil;
115 import gnu.trove.THashMap;
116 import junit.framework.Assert;
117 import org.jetbrains.annotations.NonNls;
118 import org.jetbrains.annotations.NotNull;
119 import org.jetbrains.annotations.Nullable;
121 import javax.swing.*;
123 import java.io.IOException;
127 * @author Dmitry Avdeev
129 @SuppressWarnings({"TestMethodWithIncorrectSignature", "JUnitTestCaseWithNoTests", "JUnitTestClassNamingConvention"})
130 public class CodeInsightTestFixtureImpl extends BaseFixture implements CodeInsightTestFixture {
132 @NonNls private static final String PROFILE = "Configurable";
134 private static final Function<IntentionAction,String> INTENTION_NAME_FUN = new Function<IntentionAction, String>() {
136 public String fun(final IntentionAction intentionAction) {
137 return "\"" + intentionAction.getText() + "\"";
141 private PsiManagerImpl myPsiManager;
142 private PsiFile myFile;
143 private Editor myEditor;
144 private String myTestDataPath;
145 private boolean myEmptyLookup;
147 private InspectionProfileEntry[] myInspections;
148 private final Map<String, InspectionProfileEntry> myAvailableTools = new THashMap<String, InspectionProfileEntry>();
149 private final Map<String, InspectionTool> myAvailableLocalTools = new THashMap<String, InspectionTool>();
151 private final TempDirTestFixture myTempDirFixture;
152 protected final IdeaProjectTestFixture myProjectFixture;
153 @NonNls private static final String XXX = "XXX";
154 private final FileTreeAccessFilter myJavaFilesFilter = new FileTreeAccessFilter();
155 private boolean myAllowDirt;
156 private final Map<String, LocalInspectionEP> myExtensions = new HashMap<String, LocalInspectionEP>();
158 public CodeInsightTestFixtureImpl(IdeaProjectTestFixture projectFixture, TempDirTestFixture tempDirTestFixture) {
159 myProjectFixture = projectFixture;
160 myTempDirFixture = tempDirTestFixture;
164 public void setTestDataPath(String dataPath) {
165 myTestDataPath = dataPath;
169 public String getTempDirPath() {
170 return myTempDirFixture.getTempDirPath();
174 public TempDirTestFixture getTempDirFixture() {
175 return myTempDirFixture;
179 public VirtualFile copyFileToProject(@NonNls final String sourceFilePath, @NonNls final String targetPath) {
180 File fromFile = new File(getTestDataPath() + "/" + sourceFilePath);
181 if (!fromFile.exists()) {
182 fromFile = new File(sourceFilePath);
185 if (myTempDirFixture instanceof LightTempDirTestFixtureImpl) {
186 VirtualFile fromVFile = LocalFileSystem.getInstance().refreshAndFindFileByIoFile(fromFile);
187 if (fromVFile == null) {
188 fromVFile = myTempDirFixture.getFile(sourceFilePath);
190 assert fromVFile != null : "can't find test data file " + sourceFilePath + " (" + getTestDataPath() + ")";
191 return myTempDirFixture.copyFile(fromVFile, targetPath);
194 final File destFile = new File(getTempDirPath() + "/" + targetPath);
195 if (!destFile.exists()) {
196 if (fromFile.isDirectory()) {
197 assert destFile.mkdirs() : destFile;
200 if (!fromFile.exists()) {
201 fail("Cannot find source file: '"+sourceFilePath+"'. getTestDataPath()='"+getTestDataPath()+"'. getHomePath()='"+getHomePath()+"'.");
204 FileUtil.copy(fromFile, destFile);
206 catch (IOException e) {
207 throw new RuntimeException("Cannot copy " + fromFile + " to " + destFile, e);
212 final VirtualFile file = LocalFileSystem.getInstance().refreshAndFindFileByIoFile(destFile);
213 assert file != null : destFile;
218 public VirtualFile copyDirectoryToProject(@NonNls final String sourceFilePath, @NonNls final String targetPath) {
219 assert getTestDataPath() != null : "test data path not specified";
220 final File fromFile = new File(getTestDataPath() + "/" + sourceFilePath);
221 if (myTempDirFixture instanceof LightTempDirTestFixtureImpl) {
222 return myTempDirFixture.copyAll(fromFile.getPath(), targetPath);
225 final File destFile = new File(getTempDirPath() + "/" + targetPath);
227 FileUtil.copyDir(fromFile, destFile);
229 catch (IOException e) {
230 throw new RuntimeException(e);
232 final VirtualFile file = LocalFileSystem.getInstance().refreshAndFindFileByIoFile(destFile);
233 Assert.assertNotNull(file);
234 file.refresh(false, true);
240 public VirtualFile copyFileToProject(@NonNls final String sourceFilePath) {
241 return copyFileToProject(sourceFilePath, sourceFilePath);
245 public void enableInspections(InspectionProfileEntry... inspections) {
246 myInspections = inspections;
247 if (isInitialized()) {
248 configureInspections(myInspections);
252 private boolean isInitialized() {
253 return myPsiManager != null;
257 public void enableInspections(final Class<? extends LocalInspectionTool>... inspections) {
258 final ArrayList<LocalInspectionTool> tools = new ArrayList<LocalInspectionTool>();
259 for (Class clazz : inspections) {
261 LocalInspectionTool inspection = (LocalInspectionTool)clazz.getConstructor().newInstance();
262 tools.add(inspection);
264 catch (Exception e) {
265 throw new RuntimeException("Cannot instantiate " + clazz);
268 enableInspections(tools.toArray(new LocalInspectionTool[tools.size()]));
272 public void disableInspections(InspectionProfileEntry... inspections) {
273 myAvailableTools.clear();
274 myAvailableLocalTools.clear();
275 final ArrayList<InspectionProfileEntry> tools = new ArrayList<InspectionProfileEntry>(Arrays.asList(myInspections));
276 for (Iterator<InspectionProfileEntry> i = tools.iterator(); i.hasNext();) {
277 final InspectionProfileEntry tool = i.next();
278 for (InspectionProfileEntry toRemove : inspections) {
279 if (tool.getShortName().equals(toRemove.getShortName())) {
285 myInspections = tools.toArray(new InspectionProfileEntry[tools.size()]);
286 configureInspections(myInspections);
290 public void enableInspections(InspectionToolProvider... providers) {
291 final ArrayList<LocalInspectionTool> tools = new ArrayList<LocalInspectionTool>();
292 for (InspectionToolProvider provider : providers) {
293 for (Class clazz : provider.getInspectionClasses()) {
295 Object o = clazz.getConstructor().newInstance();
296 if (o instanceof LocalInspectionTool) {
297 LocalInspectionTool inspection = (LocalInspectionTool)o;
298 tools.add(inspection);
301 catch (Exception e) {
302 throw new RuntimeException("Cannot instantiate " + clazz, e);
306 myInspections = tools.toArray(new LocalInspectionTool[tools.size()]);
307 configureInspections(myInspections);
311 public long testHighlighting(final boolean checkWarnings,
312 final boolean checkInfos,
313 final boolean checkWeakWarnings,
314 final String... filePaths) {
315 final Ref<Long> duration = new Ref<Long>();
316 if (filePaths.length > 0) {
317 configureByFilesInner(filePaths);
320 collectAndCheckHighlightings(checkWarnings, checkInfos, checkWeakWarnings, duration);
322 catch (Exception e) {
323 throw new RuntimeException(e);
325 return duration.get().longValue();
329 public long testHighlightingAllFiles(final boolean checkWarnings,
330 final boolean checkInfos,
331 final boolean checkWeakWarnings,
332 @NonNls final String... filePaths) {
333 final ArrayList<VirtualFile> files = new ArrayList<VirtualFile>();
334 for (String path : filePaths) {
335 files.add(copyFileToProject(path));
337 return testHighlightingAllFiles(checkWarnings, checkInfos, checkWeakWarnings, VfsUtil.toVirtualFileArray(files));
341 public long testHighlightingAllFiles(final boolean checkWarnings,
342 final boolean checkInfos,
343 final boolean checkWeakWarnings,
344 @NonNls final VirtualFile... files) {
345 final Ref<Long> duration = new Ref<Long>();
346 collectAndCheckHighlightings(checkWarnings, checkInfos, checkWeakWarnings, duration, files);
347 return duration.get().longValue();
350 private void collectAndCheckHighlightings(final boolean checkWarnings,
351 final boolean checkInfos,
352 final boolean checkWeakWarnings,
353 final Ref<Long> duration,
354 final VirtualFile[] files) {
355 final List<Trinity<PsiFile, Editor, ExpectedHighlightingData>> datas =
356 ContainerUtil.map2List(files, new Function<VirtualFile, Trinity<PsiFile, Editor, ExpectedHighlightingData>>() {
358 public Trinity<PsiFile, Editor, ExpectedHighlightingData> fun(final VirtualFile file) {
359 final PsiFile psiFile = myPsiManager.findFile(file);
360 assertNotNull(psiFile);
361 final Document document = PsiDocumentManager.getInstance(getProject()).getDocument(psiFile);
362 assertNotNull(document);
363 ExpectedHighlightingData data = new ExpectedHighlightingData(document, checkWarnings, checkWeakWarnings, checkInfos, psiFile);
365 return Trinity.create(psiFile, createEditor(file), data);
368 for (Trinity<PsiFile, Editor, ExpectedHighlightingData> trinity : datas) {
369 myEditor = trinity.second;
370 myFile = trinity.first;
371 collectAndCheckHighlightings(trinity.third, duration);
376 public long checkHighlighting(final boolean checkWarnings, final boolean checkInfos, final boolean checkWeakWarnings) {
377 final Ref<Long> duration = new Ref<Long>();
379 collectAndCheckHighlightings(checkWarnings, checkInfos, checkWeakWarnings, duration);
381 catch (Exception e) {
382 throw new RuntimeException(e);
384 return duration.get().longValue();
388 public long checkHighlighting() {
389 return checkHighlighting(true, true, true);
393 public long testHighlighting(final String... filePaths) {
394 return testHighlighting(true, true, true, filePaths);
398 public long testHighlighting(final boolean checkWarnings,
399 final boolean checkInfos,
400 final boolean checkWeakWarnings,
401 final VirtualFile file) {
402 final Ref<Long> duration = new Ref<Long>();
403 openFileInEditor(file);
405 collectAndCheckHighlightings(checkWarnings, checkInfos, checkWeakWarnings, duration);
407 catch (Exception e) {
408 throw new RuntimeException(e);
410 return duration.get().longValue();
414 public HighlightTestInfo testFile(@NonNls @NotNull String... filePath) {
415 return new HighlightTestInfo(getTestRootDisposable(), filePath){
417 public HighlightTestInfo doTest() throws Exception {
418 configureByFiles(filePaths);
419 ExpectedHighlightingData data = new ExpectedHighlightingData(myEditor.getDocument(), checkWarnings, checkWeakWarnings, checkInfos, myFile);
420 if (checkSymbolNames) data.checkSymbolNames();
422 collectAndCheckHighlightings(data, Ref.create(0L));
428 public void openFileInEditor(@NotNull final VirtualFile file) {
429 myFile = myPsiManager.findFile(file);
430 myEditor = createEditor(file);
434 public void testInspection(String testDir, InspectionTool tool) {
435 VirtualFile sourceDir = copyDirectoryToProject(new File(testDir, "src").getPath(), "src");
436 AnalysisScope scope = new AnalysisScope(getPsiManager().findDirectory(sourceDir));
440 InspectionManagerEx inspectionManager = (InspectionManagerEx)InspectionManager.getInstance(getProject());
441 GlobalInspectionContextImpl globalContext = createGlobalContextForTool(scope, getProject(), inspectionManager, tool);
443 InspectionTestUtil.runTool(tool, scope, globalContext, inspectionManager);
444 InspectionTestUtil.compareToolResults(tool, false, new File(getTestDataPath(), testDir).getPath());
447 public static GlobalInspectionContextImpl createGlobalContextForTool(AnalysisScope scope,
448 final Project project,
449 final InspectionManagerEx inspectionManager,
450 final InspectionTool... tools) {
451 final GlobalInspectionContextImpl globalContext = new GlobalInspectionContextImpl(project, inspectionManager.getContentManager()){
453 protected List<ToolsImpl> getUsedTools() {
454 List<ToolsImpl> result = new ArrayList<ToolsImpl>();
455 for (InspectionTool tool : tools) {
456 result.add(new ToolsImpl(tool, tool.getDefaultLevel(), true));
462 public boolean isToCheckMember(PsiElement element, InspectionProfileEntry tool) {
466 globalContext.setCurrentScope(scope);
467 return globalContext;
472 public PsiReference getReferenceAtCaretPosition(final String... filePaths) {
473 if (filePaths.length > 0) {
474 configureByFilesInner(filePaths);
476 return getFile().findReferenceAt(myEditor.getCaretModel().getOffset());
481 public PsiReference getReferenceAtCaretPositionWithAssertion(final String... filePaths) {
482 final PsiReference reference = getReferenceAtCaretPosition(filePaths);
483 assert reference != null : "no reference found at " + myEditor.getCaretModel().getLogicalPosition();
489 public List<IntentionAction> getAvailableIntentions(final String... filePaths) {
490 if (filePaths.length > 0) {
491 configureByFilesInner(filePaths);
493 return getAvailableIntentions();
498 public List<IntentionAction> getAllQuickFixes(@NonNls final String... filePaths) {
499 if (filePaths.length != 0) {
500 configureByFilesInner(filePaths);
502 List<HighlightInfo> infos = doHighlighting();
503 ArrayList<IntentionAction> actions = new ArrayList<IntentionAction>();
504 for (HighlightInfo info : infos) {
505 for (Pair<HighlightInfo.IntentionActionDescriptor, TextRange> pair : info.quickFixActionRanges) {
506 actions.add(pair.getFirst().getAction());
514 public List<IntentionAction> getAvailableIntentions() {
516 return getAvailableIntentions(myEditor, myFile);
520 public List<IntentionAction> filterAvailableIntentions(@NotNull final String hint) {
521 final List<IntentionAction> availableIntentions = getAvailableIntentions();
522 return ContainerUtil.findAll(availableIntentions, new Condition<IntentionAction>() {
524 public boolean value(final IntentionAction intentionAction) {
525 return intentionAction.getText().startsWith(hint);
531 public IntentionAction findSingleIntention(@NotNull final String hint) {
532 final List<IntentionAction> list = filterAvailableIntentions(hint);
533 if (list.isEmpty()) {
534 Assert.fail("\"" + hint + "\" not in [" + StringUtil.join(getAvailableIntentions(), INTENTION_NAME_FUN, ", ") + "]");
536 else if (list.size() > 1) {
537 Assert.fail("Too many intention found for \"" + hint + "\": [" + StringUtil.join(list, INTENTION_NAME_FUN, ", ") + "]");
539 return UsefulTestCase.assertOneElement(list);
543 public IntentionAction getAvailableIntention(final String intentionName, final String... filePaths) {
544 List<IntentionAction> intentions = getAvailableIntentions(filePaths);
545 return CodeInsightTestUtil.findIntentionByText(intentions, intentionName);
549 public void launchAction(@NotNull final IntentionAction action) {
550 ShowIntentionActionsHandler.chooseActionAndInvoke(getFile(), getEditor(), action, action.getText());
554 public void testCompletion(final String[] filesBefore, final String fileAfter) {
556 configureByFiles(filesBefore);
557 complete(CompletionType.BASIC);
558 checkResultByFile(fileAfter);
561 protected void assertInitialized() {
562 Assert.assertNotNull("setUp() hasn't been called", myPsiManager);
566 public void testCompletion(String fileBefore, String fileAfter, final String... additionalFiles) {
567 testCompletion(ArrayUtil.reverseArray(ArrayUtil.append(additionalFiles, fileBefore)), fileAfter);
571 public void testCompletionVariants(final String fileBefore, final String... expectedItems) {
573 final List<String> result = getCompletionVariants(fileBefore);
574 Assert.assertNotNull(result);
575 UsefulTestCase.assertSameElements(result, expectedItems);
579 public List<String> getCompletionVariants(final String... filesBefore) {
581 configureByFiles(filesBefore);
582 final LookupElement[] items = complete(CompletionType.BASIC);
583 Assert.assertNotNull("No lookup was shown, probably there was only one lookup element that was inserted automatically", items);
584 return getLookupElementStrings();
589 public List<String> getLookupElementStrings() {
591 final LookupElement[] elements = getLookupElements();
592 if (elements == null) return null;
594 return ContainerUtil.map(elements, new Function<LookupElement, String>() {
596 public String fun(final LookupElement lookupItem) {
597 return lookupItem.getLookupString();
603 public void testRename(final String fileBefore, final String fileAfter, final String newName, final String... additionalFiles) {
605 configureByFiles(ArrayUtil.reverseArray(ArrayUtil.append(additionalFiles, fileBefore)));
606 testRename(fileAfter, newName);
610 public void testRename(final String fileAfter, final String newName) {
611 renameElementAtCaret(newName);
612 checkResultByFile(fileAfter);
617 public PsiElement getElementAtCaret() {
619 final PsiElement element = TargetElementUtilBase.findTargetElement(getCompletionEditor(),
620 TargetElementUtilBase.REFERENCED_ELEMENT_ACCEPTED |
621 TargetElementUtilBase.ELEMENT_NAME_ACCEPTED);
622 assert element != null : "element not found in file " +
624 " at caret position, offset " +
625 myEditor.getCaretModel().getOffset();
630 public void renameElementAtCaret(final String newName) {
631 renameElement(getElementAtCaret(), newName);
635 public void renameElement(final PsiElement element, final String newName) {
636 final boolean searchInComments = false;
637 final boolean searchTextOccurrences = false;
638 renameElement(element, newName, searchInComments, searchTextOccurrences);
642 public void renameElement(final PsiElement element,
643 final String newName,
644 final boolean searchInComments,
645 final boolean searchTextOccurrences) {
646 final PsiElement substitution = RenamePsiElementProcessor.forElement(element).substituteElementToRename(element, myEditor);
647 if (substitution == null) return;
648 new RenameProcessor(getProject(), substitution, newName, searchInComments, searchTextOccurrences).run();
652 public <T extends PsiElement> T findElementByText(String text, Class<T> elementClass) {
653 int pos = PsiDocumentManager.getInstance(getProject()).getDocument(getFile()).getText().indexOf(text);
654 assert pos >= 0 : "text not found in file";
655 return PsiTreeUtil.getParentOfType(getFile().findElementAt(pos), elementClass);
659 public void type(final char c) {
661 UIUtil.invokeAndWaitIfNeeded(new Runnable() {
664 final EditorActionManager actionManager = EditorActionManager.getInstance();
666 performEditorAction(IdeActions.ACTION_EDITOR_BACKSPACE);
670 if (_performEditorAction(IdeActions.ACTION_CHOOSE_LOOKUP_ITEM)) {
674 performEditorAction(IdeActions.ACTION_EDITOR_ENTER);
678 if (_performEditorAction(IdeActions.ACTION_CHOOSE_LOOKUP_ITEM_REPLACE)) {
681 if (_performEditorAction(IdeActions.ACTION_EXPAND_LIVE_TEMPLATE_BY_TAB)) {
684 if (_performEditorAction(IdeActions.ACTION_EDITOR_TAB)) {
689 CommandProcessor.getInstance().executeCommand(getProject(), new Runnable() {
692 CommandProcessor.getInstance().setCurrentCommandGroupId(myEditor.getDocument());
693 ActionManagerEx.getInstanceEx().fireBeforeEditorTyping(c, getEditorDataContext());
694 actionManager.getTypedAction().actionPerformed(getEditor(), c, getEditorDataContext());
696 }, null, DocCommandGroupId.noneGroupId(myEditor.getDocument()));
701 private DataContext getEditorDataContext() {
702 return ((EditorEx)myEditor).getDataContext();
706 public void type(String s) {
707 for (int i = 0; i < s.length(); i++) {
713 public void performEditorAction(final String actionId) {
715 _performEditorAction(actionId);
718 private boolean _performEditorAction(String actionId) {
719 final DataContext dataContext = getEditorDataContext();
721 ActionManagerEx managerEx = ActionManagerEx.getInstanceEx();
722 AnAction action = managerEx.getAction(actionId);
723 AnActionEvent event = new AnActionEvent(null, dataContext, ActionPlaces.UNKNOWN, new Presentation(), managerEx, 0);
725 action.update(event);
727 if (!event.getPresentation().isEnabled()) {
731 managerEx.fireBeforeActionPerformed(action, dataContext, event);
733 action.actionPerformed(event);
735 managerEx.fireAfterActionPerformed(action, dataContext, event);
740 public Presentation testAction(AnAction action) {
741 DataContext context = DataManager.getInstance().getDataContext();
742 TestActionEvent e = new TestActionEvent(context, action);
743 action.beforeActionPerformedUpdate(e);
744 if (e.getPresentation().isEnabled() && e.getPresentation().isVisible()) {
745 action.actionPerformed(e);
747 return e.getPresentation();
751 public Collection<UsageInfo> testFindUsages(@NonNls final String... fileNames) {
753 configureByFiles(fileNames);
754 final PsiElement targetElement = TargetElementUtilBase
755 .findTargetElement(getEditor(), TargetElementUtilBase.ELEMENT_NAME_ACCEPTED | TargetElementUtilBase.REFERENCED_ELEMENT_ACCEPTED);
756 assert targetElement != null : "Cannot find referenced element";
757 return findUsages(targetElement);
761 public Collection<UsageInfo> findUsages(@NotNull final PsiElement targetElement) {
762 final Project project = getProject();
763 final FindUsagesHandler handler =
764 ((FindManagerImpl)FindManager.getInstance(project)).getFindUsagesManager().getFindUsagesHandler(targetElement, false);
766 final CommonProcessors.CollectProcessor<UsageInfo> processor = new CommonProcessors.CollectProcessor<UsageInfo>();
767 assert handler != null : "Cannot find handler for: " + targetElement;
768 final PsiElement[] psiElements = ArrayUtil.mergeArrays(handler.getPrimaryElements(), handler.getSecondaryElements());
769 final FindUsagesOptions options = handler.getFindUsagesOptions(null);
770 for (PsiElement psiElement : psiElements) {
771 handler.processElementUsages(psiElement, processor, options);
773 return processor.getResults();
777 public RangeHighlighter[] testHighlightUsages(final String... files) {
778 configureByFiles(files);
779 testAction(new HighlightUsagesAction());
780 final Editor editor = getEditor();
781 //final Editor editor = PlatformDataKeys.EDITOR.getData(DataManager.getInstance().getDataContext());
782 //assert editor != null;
783 //HighlightUsagesHandler.invoke(getProject(), editor, getFile());
784 return editor.getMarkupModel().getAllHighlighters();
788 public void moveFile(@NonNls final String filePath, @NonNls final String to, final String... additionalFiles) {
790 final Project project = getProject();
791 new WriteCommandAction.Simple(project) {
793 protected void run() throws Exception {
794 configureByFiles(ArrayUtil.reverseArray(ArrayUtil.append(additionalFiles, filePath)));
795 final VirtualFile file = findFileInTempDir(to);
796 assert file != null : "Directory " + to + " not found";
797 assert file.isDirectory() : to + " is not a directory";
798 final PsiDirectory directory = myPsiManager.findDirectory(file);
799 new MoveFilesOrDirectoriesProcessor(project, new PsiElement[]{myFile}, directory,
800 false, false, null, null).run();
802 }.execute().throwException();
807 public GutterIconRenderer findGutter(final String filePath) {
808 configureByFilesInner(filePath);
809 int offset = myEditor.getCaretModel().getOffset();
811 final Collection<HighlightInfo> infos = doHighlighting();
812 for (HighlightInfo info : infos) {
813 if (info.endOffset >= offset && info.startOffset <= offset) {
814 final GutterIconRenderer renderer = info.getGutterIconRenderer();
815 if (renderer != null) {
820 RangeHighlighter[] highlighters = DocumentMarkupModel.forDocument(myEditor.getDocument(), getProject(), true).getAllHighlighters();
821 for (RangeHighlighter highlighter : highlighters) {
822 if (highlighter.getEndOffset() >= offset && highlighter.getStartOffset() <= offset) {
823 GutterIconRenderer renderer = highlighter.getGutterIconRenderer();
824 if (renderer != null) {
834 public Collection<GutterIconRenderer> findAllGutters(final String filePath) {
835 final Project project = getProject();
836 final SortedMap<Integer, List<GutterIconRenderer>> result = new TreeMap<Integer, List<GutterIconRenderer>>();
837 configureByFilesInner(filePath);
839 List<HighlightInfo> infos = doHighlighting();
840 for (HighlightInfo info : infos) {
841 addGutterIconRenderer(info.getGutterIconRenderer(), info.startOffset, result);
844 RangeHighlighter[] highlighters = DocumentMarkupModel.forDocument(myEditor.getDocument(), project, true).getAllHighlighters();
845 for (final RangeHighlighter highlighter : highlighters) {
846 if (!highlighter.isValid()) continue;
847 addGutterIconRenderer(highlighter.getGutterIconRenderer(), highlighter.getStartOffset(), result);
849 return ContainerUtil.concat(result.values());
852 private static void addGutterIconRenderer(final GutterIconRenderer renderer,
854 SortedMap<Integer, List<GutterIconRenderer>> result) {
855 if (renderer == null) return;
857 List<GutterIconRenderer> renderers = result.get(offset);
858 if (renderers == null) {
859 result.put(offset, renderers = new SmartList<GutterIconRenderer>());
861 renderers.add(renderer);
866 public PsiFile addFileToProject(@NonNls final String relativePath, @NonNls final String fileText) {
868 return addFileToProject(getTempDirPath(), relativePath, fileText);
871 protected PsiFile addFileToProject(String rootPath, String relativePath, String fileText) {
873 if (myTempDirFixture instanceof LightTempDirTestFixtureImpl) {
874 final VirtualFile file = myTempDirFixture.createFile(relativePath, fileText);
875 return PsiManager.getInstance(getProject()).findFile(file);
878 return ((HeavyIdeaTestFixture)myProjectFixture).addFileToProject(rootPath, relativePath, fileText);
880 catch (IOException e) {
881 throw new RuntimeException(e);
884 ((PsiModificationTrackerImpl)PsiManager.getInstance(getProject()).getModificationTracker()).incCounter();
888 public <T> void registerExtension(final ExtensionsArea area, final ExtensionPointName<T> epName, final T extension) {
890 final ExtensionPoint<T> extensionPoint = area.getExtensionPoint(epName);
891 extensionPoint.registerExtension(extension);
892 disposeOnTearDown(new Disposable() {
894 public void dispose() {
895 extensionPoint.unregisterExtension(extension);
901 public PsiManager getPsiManager() {
906 public LookupElement[] complete(CompletionType type) {
907 return complete(type, 1);
911 public LookupElement[] complete(final CompletionType type, final int invocationCount) {
913 myEmptyLookup = false;
914 UIUtil.invokeAndWaitIfNeeded(new Runnable() {
917 CommandProcessor.getInstance().executeCommand(getProject(), new Runnable() {
920 final CodeCompletionHandlerBase handler = new CodeCompletionHandlerBase(type) {
923 protected void completionFinished(int offset1,
925 CompletionProgressIndicator indicator,
926 LookupElement[] items,
927 boolean hasModifiers) {
928 myEmptyLookup = items.length == 0;
929 super.completionFinished(offset1, offset2, indicator, items, hasModifiers);
932 Editor editor = getCompletionEditor();
933 handler.invokeCompletion(getProject(), editor, invocationCount, false);
934 PsiDocumentManager.getInstance(getProject()).commitAllDocuments(); // to compare with file text
940 return getLookupElements();
944 protected Editor getCompletionEditor() {
945 return InjectedLanguageUtil.getEditorForInjectedLanguageNoCommit(myEditor, myFile);
950 public LookupElement[] completeBasic() {
951 return complete(CompletionType.BASIC);
956 public LookupElement[] getLookupElements() {
957 LookupImpl lookup = getLookup();
958 if (lookup == null) {
959 return myEmptyLookup ? LookupElement.EMPTY_ARRAY : null;
962 final List<LookupElement> list = lookup.getItems();
963 return list.toArray(new LookupElement[list.size()]);
968 public void checkResult(final String text) {
969 checkResult(text, false);
973 public void checkResult(final String text, final boolean stripTrailingSpaces) {
974 new WriteCommandAction(getProject()) {
976 protected void run(Result result) throws Throwable {
977 PsiDocumentManager.getInstance(getProject()).commitAllDocuments();
978 EditorUtil.fillVirtualSpaceUntilCaret(myEditor);
979 checkResult("TEXT", stripTrailingSpaces, SelectionAndCaretMarkupLoader.fromText(text, getProject()), myFile.getText());
985 public void checkResultByFile(final String expectedFile) {
986 checkResultByFile(expectedFile, false);
990 public void checkResultByFile(final String expectedFile, final boolean ignoreTrailingWhitespaces) {
992 new WriteCommandAction.Simple(getProject()) {
995 protected void run() throws Exception {
996 checkResultByFile(expectedFile, myFile, ignoreTrailingWhitespaces);
998 }.execute().throwException();
1002 public void checkResultByFile(final String filePath, final String expectedFile, final boolean ignoreTrailingWhitespaces) {
1003 assertInitialized();
1005 new WriteCommandAction.Simple(getProject()) {
1008 protected void run() throws Exception {
1009 final String path = filePath.replace(File.separatorChar, '/');
1010 final VirtualFile copy = findFileInTempDir(path);
1012 throw new IllegalArgumentException("could not find results file " + path);
1014 final PsiFile psiFile = myPsiManager.findFile(copy);
1015 assert psiFile != null;
1016 checkResultByFile(expectedFile, psiFile, ignoreTrailingWhitespaces);
1018 }.execute().throwException();
1022 public void setUp() throws Exception {
1025 myProjectFixture.setUp();
1026 myTempDirFixture.setUp();
1027 myPsiManager = (PsiManagerImpl)PsiManager.getInstance(getProject());
1028 configureInspections(myInspections == null ? LocalInspectionTool.EMPTY_ARRAY : myInspections);
1030 DaemonCodeAnalyzerImpl daemonCodeAnalyzer = (DaemonCodeAnalyzerImpl)DaemonCodeAnalyzer.getInstance(getProject());
1031 daemonCodeAnalyzer.prepareForTest();
1033 DaemonCodeAnalyzerSettings.getInstance().setImportHintEnabled(false);
1034 ensureIndexesUpToDate(getProject());
1035 ((StartupManagerImpl)StartupManagerEx.getInstanceEx(getProject())).runPostStartupActivities();
1036 LocalInspectionEP[] extensions = Extensions.getExtensions(LocalInspectionEP.LOCAL_INSPECTION);
1037 for (LocalInspectionEP extension : extensions) {
1038 myExtensions.put(extension.shortName, extension);
1043 public void tearDown() throws Exception {
1044 ((StatisticsManagerImpl)StatisticsManager.getInstance()).clearStatistics();
1046 FileEditorManager editorManager = FileEditorManager.getInstance(getProject());
1047 VirtualFile[] openFiles = editorManager.getOpenFiles();
1048 for (VirtualFile openFile : openFiles) {
1049 editorManager.closeFile(openFile);
1054 myPsiManager = null;
1055 myInspections = null;
1056 myAvailableLocalTools.clear();
1057 myAvailableTools.clear();
1059 myProjectFixture.tearDown();
1060 myTempDirFixture.tearDown();
1065 private void enableInspectionTool(InspectionProfileEntry tool) {
1066 final String shortName = tool.getShortName();
1067 final HighlightDisplayKey key = HighlightDisplayKey.find(shortName);
1069 String id = tool instanceof LocalInspectionTool ? ((LocalInspectionTool)tool).getID() : shortName;
1070 HighlightDisplayKey.register(shortName, tool.getDisplayName(), id);
1072 myAvailableTools.put(shortName, tool);
1073 InspectionTool inspectionTool;
1074 if (tool instanceof LocalInspectionTool) {
1075 LocalInspectionEP ep = myExtensions.get(tool.getShortName());
1076 inspectionTool = new LocalInspectionToolWrapper((LocalInspectionTool)tool, ep);
1079 inspectionTool = (InspectionTool)tool;
1081 myAvailableLocalTools.put(shortName, inspectionTool);
1084 private void configureInspections(final InspectionProfileEntry[] tools) {
1085 for (InspectionProfileEntry tool : tools) {
1086 enableInspectionTool(tool);
1089 final InspectionProfileImpl profile = new InspectionProfileImpl(PROFILE) {
1092 public ModifiableModel getModifiableModel() {
1099 public InspectionProfileEntry[] getInspectionTools(PsiElement element) {
1100 final Collection<InspectionTool> tools = myAvailableLocalTools.values();
1101 return tools.toArray(new InspectionTool[tools.size()]);
1105 public List<ToolsImpl> getAllEnabledInspectionTools(Project project) {
1106 List<ToolsImpl> result = new ArrayList<ToolsImpl>();
1107 for (InspectionProfileEntry entry : getInspectionTools(null)) {
1108 result.add(new ToolsImpl(entry, entry.getDefaultLevel(), true));
1114 public boolean isToolEnabled(HighlightDisplayKey key, PsiElement element) {
1115 return key != null && key.toString() != null && myAvailableTools.containsKey(key.toString());
1119 public InspectionProfileEntry getInspectionTool(@NotNull String shortName) {
1120 return myAvailableTools.get(shortName);
1124 public HighlightDisplayLevel getErrorLevel(@NotNull HighlightDisplayKey key, PsiElement element) {
1125 final InspectionProfileEntry entry = myAvailableTools.get(key.toString());
1126 return entry != null ? entry.getDefaultLevel() : HighlightDisplayLevel.WARNING;
1130 public InspectionTool getInspectionTool(@NotNull String shortName, @NotNull PsiElement element) {
1131 return myAvailableLocalTools.get(shortName);
1134 final InspectionProfileManager inspectionProfileManager = InspectionProfileManager.getInstance();
1135 inspectionProfileManager.addProfile(profile);
1136 Disposer.register(getTestRootDisposable(), new Disposable() {
1138 public void dispose() {
1139 inspectionProfileManager.deleteProfile(PROFILE);
1142 inspectionProfileManager.setRootProfile(profile.getName());
1143 InspectionProjectProfileManager.getInstance(getProject()).updateProfile(profile);
1144 InspectionProjectProfileManager.getInstance(getProject()).setProjectProfile(profile.getName());
1147 private PsiFile[] configureByFilesInner(@NonNls String... filePaths) {
1148 assertInitialized();
1151 PsiFile[] psiFiles = new PsiFile[filePaths.length];
1152 for (int i = filePaths.length - 1; i >= 0; i--) {
1153 psiFiles[i] = configureByFileInner(filePaths[i]);
1159 public PsiFile configureByFile(final String file) {
1160 configureByFilesInner(file);
1165 public PsiFile[] configureByFiles(@NonNls final String... files) {
1166 return configureByFilesInner(files);
1170 public PsiFile configureByText(final FileType fileType, @NonNls final String text) {
1171 assertInitialized();
1172 final String extension = fileType.getDefaultExtension();
1173 final FileTypeManager fileTypeManager = FileTypeManager.getInstance();
1174 if (fileTypeManager.getFileTypeByExtension(extension) != fileType) {
1175 new WriteCommandAction(getProject()) {
1177 protected void run(Result result) throws Exception {
1178 fileTypeManager.associateExtension(fileType, extension);
1182 final String fileName = "aaa." + extension;
1183 return configureByText(fileName, text);
1187 public PsiFile configureByText(final String fileName, @NonNls final String text) {
1188 assertInitialized();
1189 new WriteCommandAction(getProject()) {
1191 protected void run(Result result) throws Throwable {
1192 final VirtualFile vFile;
1193 if (myTempDirFixture instanceof LightTempDirTestFixtureImpl) {
1194 final VirtualFile root = LightPlatformTestCase.getSourceRoot();
1195 root.refresh(false, false);
1196 vFile = root.findOrCreateChildData(this, fileName);
1199 String prefix = StringUtil.getPackageName(fileName);
1200 if (prefix.length() < 3) {
1203 final File tempFile = FileUtil.createTempFile(new File(getTempDirPath()), prefix, "." + StringUtil.getShortName(fileName), true);
1204 vFile = LocalFileSystem.getInstance().refreshAndFindFileByIoFile(tempFile);
1206 final Document document = FileDocumentManager.getInstance().getCachedDocument(vFile);
1207 if (document != null) {
1208 FileDocumentManager.getInstance().saveDocument(document);
1211 VfsUtil.saveText(vFile, text);
1212 configureInner(vFile, SelectionAndCaretMarkupLoader.fromFile(vFile, getProject()));
1219 public Document getDocument(final PsiFile file) {
1220 assertInitialized();
1221 return PsiDocumentManager.getInstance(getProject()).getDocument(file);
1226 * @throws IOException
1228 private PsiFile configureByFileInner(@NonNls String filePath) {
1229 assertInitialized();
1230 final VirtualFile file = copyFileToProject(filePath);
1231 return configureByFileInner(file);
1235 public PsiFile configureFromTempProjectFile(final String filePath) {
1236 final VirtualFile fileInTempDir = findFileInTempDir(filePath);
1237 if (fileInTempDir == null) {
1238 throw new IllegalArgumentException("Could not find file in temp dir: " + filePath);
1240 return configureByFileInner(fileInTempDir);
1244 public void configureFromExistingVirtualFile(VirtualFile f) {
1245 configureByFileInner(f);
1248 private PsiFile configureByFileInner(final VirtualFile copy) {
1249 return configureInner(copy, SelectionAndCaretMarkupLoader.fromFile(copy, getProject()));
1252 private PsiFile configureInner(@NotNull final VirtualFile copy, final SelectionAndCaretMarkupLoader loader) {
1253 assertInitialized();
1254 new WriteCommandAction.Simple(getProject()) {
1257 copy.setBinaryContent(loader.newFileText.getBytes(copy.getCharset()), 0, 0, null);
1259 catch (IOException e) {
1260 throw new RuntimeException(e);
1262 myFile = myPsiManager.findFile(copy);
1263 myEditor = createEditor(copy);
1264 assert myEditor != null : "Editor couldn't be created for file: " +
1266 ", use copyFileToProject(..) method for this file instead of configureByFile(..)";
1267 if (loader.caretMarker != null) {
1268 int offset = loader.caretMarker.getStartOffset();
1269 myEditor.getCaretModel().moveToOffset(offset);
1271 if (loader.selStartMarker != null && loader.selEndMarker != null) {
1272 myEditor.getSelectionModel().setSelection(loader.selStartMarker.getStartOffset(), loader.selEndMarker.getStartOffset());
1275 Module module = getModule();
1276 if (module != null) {
1277 for (Facet facet : FacetManager.getInstance(module).getAllFacets()) {
1278 module.getMessageBus().syncPublisher(FacetManager.FACETS_TOPIC).facetConfigurationChanged(facet);
1282 }.execute().throwException();
1289 public VirtualFile findFileInTempDir(final String filePath) {
1290 if (myTempDirFixture instanceof LightTempDirTestFixtureImpl) {
1291 return myTempDirFixture.getFile(filePath);
1293 String fullPath = getTempDirPath() + "/" + filePath;
1295 final VirtualFile copy = LocalFileSystem.getInstance().refreshAndFindFileByPath(fullPath.replace(File.separatorChar, '/'));
1296 assert copy != null : "file " + fullPath + " not found";
1301 private Editor createEditor(VirtualFile file) {
1302 final Project project = getProject();
1303 final FileEditorManager instance = FileEditorManager.getInstance(project);
1304 if (file.getFileType().isBinary()) {
1307 return instance.openTextEditor(new OpenFileDescriptor(project, file, 0), false);
1310 private void collectAndCheckHighlightings(boolean checkWarnings, boolean checkInfos, boolean checkWeakWarnings, Ref<Long> duration)
1312 ExpectedHighlightingData data =
1313 new ExpectedHighlightingData(myEditor.getDocument(), checkWarnings, checkWeakWarnings, checkInfos, myFile);
1315 collectAndCheckHighlightings(data, duration);
1318 private void collectAndCheckHighlightings(final ExpectedHighlightingData data, final Ref<Long> duration) {
1319 final Project project = getProject();
1320 PsiDocumentManager.getInstance(project).commitAllDocuments();
1322 ((PsiFileImpl)myFile).calcTreeElement(); //to load text
1324 //to initialize caches
1325 CacheManager.SERVICE.getInstance(project).getFilesWithWord(XXX, UsageSearchContext.IN_COMMENTS, GlobalSearchScope.allScope(project), true);
1327 List<HighlightInfo> infos;
1329 ((PsiManagerImpl)PsiManager.getInstance(project)).setAssertOnFileLoadingFilter(myJavaFilesFilter);
1331 final long start = System.currentTimeMillis();
1332 // ProfilingUtil.startCPUProfiling();
1333 infos = doHighlighting();
1334 removeDuplicatedRangesForInjected(infos);
1335 final long elapsed = System.currentTimeMillis() - start;
1336 duration.set(duration.isNull() ? elapsed : duration.get().longValue() + elapsed);
1337 // ProfilingUtil.captureCPUSnapshot("testing");
1340 ((PsiManagerImpl)PsiManager.getInstance(project)).setAssertOnFileLoadingFilter(VirtualFileFilter.NONE);
1344 data.checkResult(infos, myEditor.getDocument().getText());
1347 private static void removeDuplicatedRangesForInjected(List<HighlightInfo> infos) {
1348 Collections.sort(infos, new Comparator<HighlightInfo>() {
1350 public int compare(HighlightInfo o1, HighlightInfo o2) {
1351 final int i = o2.startOffset - o1.startOffset;
1352 return i != 0 ? i : o1.getSeverity().myVal - o2.getSeverity().myVal;
1355 HighlightInfo prevInfo = null;
1356 for (Iterator<HighlightInfo> it = infos.iterator(); it.hasNext();) {
1357 final HighlightInfo info = it.next();
1358 if (prevInfo != null &&
1359 info.getSeverity() == HighlightInfoType.SYMBOL_TYPE_SEVERITY &&
1360 info.description == null &&
1361 info.startOffset == prevInfo.startOffset &&
1362 info.endOffset == prevInfo.endOffset) {
1365 prevInfo = info.type == HighlightInfoType.INJECTED_LANGUAGE_FRAGMENT ? info : null;
1371 public List<HighlightInfo> doHighlighting() {
1372 final Project project = getProject();
1373 PsiDocumentManager.getInstance(project).commitAllDocuments();
1375 return instantiateAndRun(getFile(), getEditor(), ArrayUtil.EMPTY_INT_ARRAY, myAllowDirt);
1379 public static List<HighlightInfo> instantiateAndRun(@NotNull PsiFile file,
1380 @NotNull Editor editor,
1381 @NotNull int[] toIgnore,
1382 boolean canChangeDocument) {
1383 Project project = file.getProject();
1384 ensureIndexesUpToDate(project);
1385 DaemonCodeAnalyzerImpl codeAnalyzer = (DaemonCodeAnalyzerImpl)DaemonCodeAnalyzer.getInstance(project);
1386 TextEditor textEditor = TextEditorProvider.getInstance().getTextEditor(editor);
1387 List<HighlightInfo> infos = codeAnalyzer.runPasses(file, editor.getDocument(), textEditor, toIgnore, canChangeDocument, null);
1388 infos.addAll(DaemonCodeAnalyzerImpl.getFileLevelHighlights(project, file));
1392 public static void ensureIndexesUpToDate(Project project) {
1393 if (!DumbService.isDumb(project)) {
1394 FileBasedIndex.getInstance().ensureUpToDate(StubUpdatingIndex.INDEX_ID, project, null);
1395 FileBasedIndex.getInstance().ensureUpToDate(TodoIndex.NAME, project, null);
1400 public String getTestDataPath() {
1401 return myTestDataPath;
1405 public Project getProject() {
1406 return myProjectFixture.getProject();
1410 public Module getModule() {
1411 return myProjectFixture.getModule();
1415 public Editor getEditor() {
1420 public int getCaretOffset() {
1421 return myEditor.getCaretModel().getOffset();
1425 public PsiFile getFile() {
1429 public static List<IntentionAction> getAvailableIntentions(@NotNull final Editor editor, @NotNull final PsiFile file) {
1430 return ApplicationManager.getApplication().runReadAction(new Computable<List<IntentionAction>>() {
1432 public List<IntentionAction> compute() {
1433 return doGetAvailableIntentions(editor, file);
1438 private static List<IntentionAction> doGetAvailableIntentions(@NotNull Editor editor, @NotNull PsiFile file) {
1439 ShowIntentionsPass.IntentionsInfo intentions = new ShowIntentionsPass.IntentionsInfo();
1440 ShowIntentionsPass.getActionsToShow(editor, file, intentions, -1);
1441 List<HighlightInfo.IntentionActionDescriptor> descriptors = new ArrayList<HighlightInfo.IntentionActionDescriptor>();
1442 descriptors.addAll(intentions.intentionsToShow);
1443 descriptors.addAll(intentions.errorFixesToShow);
1444 descriptors.addAll(intentions.inspectionFixesToShow);
1445 descriptors.addAll(intentions.guttersToShow);
1447 PsiElement element = file.findElementAt(editor.getCaretModel().getOffset());
1448 List<IntentionAction> result = new ArrayList<IntentionAction>();
1450 List<HighlightInfo> infos = DaemonCodeAnalyzerImpl.getFileLevelHighlights(file.getProject(), file);
1451 for (HighlightInfo info : infos) {
1452 for (Pair<HighlightInfo.IntentionActionDescriptor, TextRange> pair : info.quickFixActionRanges) {
1453 HighlightInfo.IntentionActionDescriptor actionInGroup = pair.first;
1454 if (actionInGroup.getAction().isAvailable(file.getProject(), editor, file)) {
1455 descriptors.add(actionInGroup);
1460 // add all intention options for simplicity
1461 for (HighlightInfo.IntentionActionDescriptor descriptor : descriptors) {
1462 result.add(descriptor.getAction());
1463 List<IntentionAction> options = descriptor.getOptions(element,editor);
1464 if (options != null) {
1465 for (IntentionAction option : options) {
1466 if (option.isAvailable(file.getProject(), editor, file)) {
1476 public void allowTreeAccessForFile(final VirtualFile file) {
1477 myJavaFilesFilter.allowTreeAccessForFile(file);
1481 public void allowTreeAccessForAllFiles() {
1482 myJavaFilesFilter.allowTreeAccessForAllFiles();
1485 static class SelectionAndCaretMarkupLoader {
1486 final String newFileText;
1487 final RangeMarker caretMarker;
1488 final RangeMarker selStartMarker;
1489 final RangeMarker selEndMarker;
1491 static SelectionAndCaretMarkupLoader fromFile(String path, Project project) throws IOException {
1492 return new SelectionAndCaretMarkupLoader(StringUtil.convertLineSeparators(FileUtil.loadFile(new File(path))),
1496 static SelectionAndCaretMarkupLoader fromFile(VirtualFile file, Project project) {
1499 text = VfsUtil.loadText(file);
1501 catch (IOException e) {
1502 throw new RuntimeException(e);
1504 return new SelectionAndCaretMarkupLoader(StringUtil.convertLineSeparators(text), project);
1507 static SelectionAndCaretMarkupLoader fromText(String text, Project project) {
1508 return new SelectionAndCaretMarkupLoader(text, project);
1511 private SelectionAndCaretMarkupLoader(String fileText, Project project) {
1512 final Document document = EditorFactory.getInstance().createDocument(fileText);
1514 int caretIndex = fileText.indexOf(CARET_MARKER);
1515 int selStartIndex = fileText.indexOf(SELECTION_START_MARKER);
1516 int selEndIndex = fileText.indexOf(SELECTION_END_MARKER);
1518 caretMarker = caretIndex >= 0 ? document.createRangeMarker(caretIndex, caretIndex) : null;
1519 selStartMarker = selStartIndex >= 0 ? document.createRangeMarker(selStartIndex, selStartIndex) : null;
1520 selEndMarker = selEndIndex >= 0 ? document.createRangeMarker(selEndIndex, selEndIndex) : null;
1522 new WriteCommandAction(project) {
1524 protected void run(Result result) throws Exception {
1525 if (caretMarker != null) {
1526 document.deleteString(caretMarker.getStartOffset(), caretMarker.getStartOffset() + CARET_MARKER.length());
1528 if (selStartMarker != null) {
1529 document.deleteString(selStartMarker.getStartOffset(), selStartMarker.getStartOffset() + SELECTION_START_MARKER.length());
1531 if (selEndMarker != null) {
1532 document.deleteString(selEndMarker.getStartOffset(), selEndMarker.getStartOffset() + SELECTION_END_MARKER.length());
1537 newFileText = document.getText();
1541 private void checkResultByFile(@NonNls String expectedFile,
1542 @NotNull PsiFile originalFile,
1543 boolean stripTrailingSpaces) throws IOException {
1544 if (!stripTrailingSpaces) {
1545 EditorUtil.fillVirtualSpaceUntilCaret(myEditor);
1547 PsiDocumentManager.getInstance(getProject()).commitAllDocuments();
1549 final String fileText = originalFile.getText();
1550 final String path = getTestDataPath() + "/" + expectedFile;
1552 /*final VirtualFile result = LocalFileSystem.getInstance().findFileByPath(path);
1553 final int caret = myEditor.getCaretModel().getOffset();
1554 final String newText = myFile == originalFile ? fileText.substring(0, caret) + "<caret>" + fileText.substring(caret) : fileText;
1555 VfsUtil.saveText(result, newText);*/
1557 checkResult(expectedFile, stripTrailingSpaces,
1558 SelectionAndCaretMarkupLoader.fromFile(path, getProject()), fileText);
1562 private void checkResult(final String expectedFile,
1563 final boolean stripTrailingSpaces,
1564 final SelectionAndCaretMarkupLoader loader,
1565 String actualText) {
1566 assertInitialized();
1567 Project project = getProject();
1569 project.getComponent(PostprocessReformattingAspect.class).doPostponedFormatting();
1570 if (stripTrailingSpaces) {
1571 actualText = stripTrailingSpaces(actualText);
1574 PsiDocumentManager.getInstance(project).commitAllDocuments();
1576 String newFileText1 = loader.newFileText;
1577 if (stripTrailingSpaces) {
1578 newFileText1 = stripTrailingSpaces(newFileText1);
1581 actualText = StringUtil.convertLineSeparators(actualText);
1583 //noinspection HardCodedStringLiteral
1584 Assert.assertEquals("Text mismatch in file " + expectedFile, newFileText1, actualText);
1586 if (loader.caretMarker != null) {
1587 final int tabSize = CodeStyleSettingsManager.getSettings(getProject()).getIndentOptions(StdFileTypes.JAVA).TAB_SIZE;
1589 int caretLine = StringUtil.offsetToLineNumber(loader.newFileText, loader.caretMarker.getStartOffset());
1590 int caretCol = EditorUtil.calcColumnNumber(null, loader.newFileText, StringUtil.lineColToOffset(loader.newFileText, caretLine, 0), loader.caretMarker.getStartOffset(), tabSize);
1592 final int actualLine = myEditor.getCaretModel().getLogicalPosition().line;
1593 final int actualCol = myEditor.getCaretModel().getLogicalPosition().column;
1594 boolean caretPositionEquals = caretLine == actualLine && caretCol == actualCol;
1595 assertTrue("Caret position in " + expectedFile + " differs. Expected " + genCaretPositionPresentation(caretLine, caretCol) +
1596 ". Actual " + genCaretPositionPresentation(actualLine, actualCol), caretPositionEquals);
1599 if (loader.selStartMarker != null && loader.selEndMarker != null) {
1600 int selStartLine = StringUtil.offsetToLineNumber(loader.newFileText, loader.selStartMarker.getStartOffset());
1601 int selStartCol = loader.selStartMarker.getStartOffset() - StringUtil.lineColToOffset(loader.newFileText, selStartLine, 0);
1603 int selEndLine = StringUtil.offsetToLineNumber(loader.newFileText, loader.selEndMarker.getEndOffset());
1604 int selEndCol = loader.selEndMarker.getEndOffset() - StringUtil.lineColToOffset(loader.newFileText, selEndLine, 0);
1606 final int selStartLineActual = StringUtil.offsetToLineNumber(loader.newFileText, myEditor.getSelectionModel().getSelectionStart());
1607 final int selStartColActual = myEditor.getSelectionModel().getSelectionStart() - StringUtil.lineColToOffset(loader.newFileText, selStartLineActual, 0);
1609 final int selEndLineActual = StringUtil.offsetToLineNumber(loader.newFileText, myEditor.getSelectionModel().getSelectionEnd());
1610 final int selEndColActual = myEditor.getSelectionModel().getSelectionEnd() - StringUtil.lineColToOffset(loader.newFileText, selEndLineActual, 0);
1612 final boolean selectionEquals = selStartCol == selStartColActual &&
1613 selStartLine == selStartLineActual &&
1614 selEndCol == selEndColActual &&
1615 selEndLine == selEndLineActual;
1616 Assert.assertTrue("selection in " +
1618 " differs. Expected " +
1619 genSelectionPresentation(selStartLine, selStartCol, selEndLine, selEndCol) +
1621 genSelectionPresentation(selStartLineActual, selStartColActual, selEndLineActual, selEndColActual),
1624 else if (myEditor != null) {
1625 Assert.assertTrue("has no selection in " + expectedFile, !myEditor.getSelectionModel().hasSelection());
1629 private static String genCaretPositionPresentation(int line, int col) {
1632 return "(" + line + ", " + col + ")";
1635 private static String genSelectionPresentation(int startLine, int startCol, int endLine, int endCol) {
1640 return "(" + startLine + ", " + startCol + ")-(" + endLine + ", " + endCol + ")";
1643 private static String stripTrailingSpaces(String actualText) {
1644 final Document document = EditorFactory.getInstance().createDocument(actualText);
1645 ((DocumentImpl)document).stripTrailingSpaces();
1646 actualText = document.getText();
1650 public void canChangeDocumentDuringHighlighting(boolean canI) {
1654 private static final String START_FOLD = "<fold\\stext=\'[^\']*\'(\\sexpand=\'[^\']*\')*>";
1655 private static final String END_FOLD = "</fold>";
1657 private class Border implements Comparable<Border> {
1658 public static final boolean LEFT = true;
1659 public static final boolean RIGHT = false;
1660 public boolean mySide;
1661 public int myOffset;
1662 public String myText;
1663 public boolean myIsExpanded;
1665 private Border(boolean side, int offset, String text, boolean isExpanded) {
1669 myIsExpanded = isExpanded;
1672 public boolean isExpanded() {
1673 return myIsExpanded;
1676 public boolean isSide() {
1680 public int getOffset() {
1684 public String getText() {
1688 public int compareTo(Border o) {
1689 return getOffset() < o.getOffset() ? 1 : -1;
1693 private String getFoldingDescription(@NotNull String content, @NotNull String initialFileName,
1694 boolean doCheckCollapseStatus) {
1695 configureByText(FileTypeManager.getInstance().getFileTypeByFileName(initialFileName), content);
1696 CodeFoldingManager.getInstance(getProject()).buildInitialFoldings(myEditor);
1698 final FoldingModel model = myEditor.getFoldingModel();
1699 final FoldRegion[] foldingRegions = model.getAllFoldRegions();
1700 final List<Border> borders = new LinkedList<Border>();
1702 for (FoldRegion region : foldingRegions) {
1703 borders.add(new Border(Border.LEFT, region.getStartOffset(), region.getPlaceholderText(), region.isExpanded()));
1704 borders.add(new Border(Border.RIGHT, region.getEndOffset(), "", region.isExpanded()));
1706 Collections.sort(borders);
1708 StringBuilder result = new StringBuilder(myEditor.getDocument().getText());
1709 for (Border border : borders) {
1710 result.insert(border.getOffset(), border.isSide() == Border.LEFT ? "<fold text=\'" + border.getText() + "\'" +
1711 (doCheckCollapseStatus ? " expand=\'" +
1712 border.isExpanded() +
1717 return result.toString();
1720 private void testFoldingRegions(final String verificationFileName, boolean doCheckCollapseStatus) {
1721 String expectedContent;
1723 expectedContent = FileUtil.loadFile(new File(verificationFileName));
1725 catch (IOException e) {
1726 throw new RuntimeException(e);
1728 Assert.assertNotNull(expectedContent);
1730 expectedContent = StringUtil.replace(expectedContent, "\r", "");
1731 final String cleanContent = expectedContent.replaceAll(START_FOLD, "").replaceAll(END_FOLD, "");
1732 final String actual = getFoldingDescription(cleanContent, verificationFileName, doCheckCollapseStatus);
1734 assertEquals(expectedContent, actual);
1737 public void testFoldingWithCollapseStatus(final String verificationFileName) {
1738 testFoldingRegions(verificationFileName, true);
1741 public void testFolding(final String verificationFileName) {
1742 testFoldingRegions(verificationFileName, false);
1746 public void assertPreferredCompletionItems(final int selected, @NonNls final String... expected) {
1747 final LookupImpl lookup = getLookup();
1748 assertNotNull(lookup);
1750 final LinkedHashMap<LookupElement,StringBuilder> relevanceStrings = lookup.getRelevanceStrings();
1752 final JList list = lookup.getList();
1753 final List<LookupElement> model = lookup.getItems();
1754 final List<String> actual = new ArrayList<String>();
1755 final int count = lookup.getPreferredItemsCount();
1756 for (int i = 0; i < count; i++) {
1757 actual.add(model.get(i).getLookupString());
1759 if (!actual.equals(Arrays.asList(expected))) {
1760 final List<String> strings = new ArrayList<String>();
1761 for (int i = 0; i < model.size(); i++) {
1762 final LookupElement item = model.get(i);
1763 strings.add(item.getLookupString() + " " + relevanceStrings.get(item));
1764 if (i == count - 1) {
1768 assertOrderedEquals(strings, expected);
1770 assertEquals(selected, list.getSelectedIndex());
1774 public void testStructureView(Consumer<StructureViewComponent> consumer) {
1775 assert myFile != null : "configure first";
1777 final VirtualFile vFile = myFile.getVirtualFile();
1778 assert vFile != null : "no virtual file for " + myFile;
1780 final FileEditor fileEditor = FileEditorManager.getInstance(getProject()).getSelectedEditor(vFile);
1781 assert fileEditor != null : "editor not opened for " + vFile;
1783 final StructureViewBuilder builder = LanguageStructureViewBuilder.INSTANCE.getStructureViewBuilder(myFile);
1784 assert builder != null : "no builder for " + myFile;
1786 StructureViewComponent component = null;
1788 component = (StructureViewComponent)builder.createStructureView(fileEditor, myProjectFixture.getProject());
1789 consumer.consume(component);
1792 if (component != null) Disposer.dispose(component);
1796 private LookupImpl getLookup() {
1797 return (LookupImpl)LookupManager.getActiveLookup(myEditor);