2 * Copyright 2000-2016 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.codeInsight.daemon.quickFix;
18 import com.intellij.codeInsight.daemon.LightDaemonAnalyzerTestCase;
19 import com.intellij.codeInsight.daemon.impl.HighlightInfo;
20 import com.intellij.codeInsight.intention.IntentionAction;
21 import com.intellij.codeInsight.intention.impl.ShowIntentionActionsHandler;
22 import com.intellij.openapi.application.ApplicationManager;
23 import com.intellij.openapi.application.WriteAction;
24 import com.intellij.openapi.command.CommandProcessor;
25 import com.intellij.openapi.editor.Editor;
26 import com.intellij.openapi.project.Project;
27 import com.intellij.openapi.util.io.FileUtil;
28 import com.intellij.openapi.util.text.StringUtil;
29 import com.intellij.openapi.vcs.readOnlyHandler.ReadonlyStatusHandlerImpl;
30 import com.intellij.openapi.vfs.CharsetToolkit;
31 import com.intellij.openapi.vfs.ReadonlyStatusHandler;
32 import com.intellij.psi.PsiFile;
33 import com.intellij.rt.execution.junit.FileComparisonFailure;
34 import com.intellij.testFramework.LightPlatformCodeInsightTestCase;
35 import com.intellij.testFramework.LightPlatformTestCase;
36 import com.intellij.testFramework.fixtures.impl.CodeInsightTestFixtureImpl;
37 import com.intellij.util.IncorrectOperationException;
38 import com.intellij.util.ObjectUtils;
39 import com.intellij.util.io.ReadOnlyAttributeUtil;
40 import com.intellij.util.ui.UIUtil;
41 import org.jetbrains.annotations.NonNls;
42 import org.jetbrains.annotations.NotNull;
45 import java.io.IOException;
46 import java.io.UncheckedIOException;
47 import java.util.List;
49 public abstract class LightQuickFixTestCase extends LightDaemonAnalyzerTestCase {
50 @NonNls protected static final String BEFORE_PREFIX = "before";
51 @NonNls protected static final String AFTER_PREFIX = "after";
53 private static QuickFixTestCase myWrapper;
55 protected boolean shouldBeAvailableAfterExecution() {
59 private static void doTestFor(@NotNull String testName, @NotNull QuickFixTestCase quickFixTestCase) {
60 final String relativePath = ObjectUtils.notNull(quickFixTestCase.getBasePath(), "") + "/" + BEFORE_PREFIX + testName;
61 final String testFullPath = quickFixTestCase.getTestDataPath().replace(File.separatorChar, '/') + relativePath;
62 final File testFile = new File(testFullPath);
63 CommandProcessor.getInstance().executeCommand(quickFixTestCase.getProject(), () -> {
65 String contents = StringUtil.convertLineSeparators(FileUtil.loadFile(testFile, CharsetToolkit.UTF8_CHARSET));
66 quickFixTestCase.configureFromFileText(testFile.getName(), contents);
67 quickFixTestCase.bringRealEditorBack();
68 final ActionHint actionHint = quickFixTestCase.parseActionHintImpl(quickFixTestCase.getFile(), contents);
70 quickFixTestCase.beforeActionStarted(testName, contents);
73 myWrapper = quickFixTestCase;
74 quickFixTestCase.doAction(actionHint, testFullPath, testName);
78 quickFixTestCase.afterActionCompleted(testName, contents);
81 catch (FileComparisonFailure e){
91 protected void afterActionCompleted(final String testName, final String contents) {
94 protected void beforeActionStarted(final String testName, final String contents) {
97 public static void doAction(@NotNull ActionHint actionHint,
100 QuickFixTestCase quickFix) throws Exception {
101 IntentionAction action = actionHint.findAndCheck(quickFix.getAvailableActions(),
102 () -> "Test: "+testFullPath+"\nInfos: "+quickFix.doHighlighting());
103 if (action != null) {
104 String text = action.getText();
105 quickFix.invoke(action);
106 UIUtil.dispatchAllInvocationEvents();
107 UIUtil.dispatchAllInvocationEvents();
108 if (!quickFix.shouldBeAvailableAfterExecution()) {
109 final IntentionAction afterAction = quickFix.findActionWithText(text);
110 if (afterAction != null) {
111 fail("Action '" + text + "' is still available after its invocation in test " + testFullPath);
114 String expectedFilePath = ObjectUtils.notNull(quickFix.getBasePath(), "") + "/" + AFTER_PREFIX + testName;
115 quickFix.checkResultByFile("In file :" + expectedFilePath, expectedFilePath, false);
119 protected void doAction(@NotNull ActionHint actionHint, final String testFullPath, final String testName)
121 doAction(actionHint, testFullPath, testName, myWrapper);
124 protected void doAction(@NotNull String actionName) {
125 final List<IntentionAction> available = getAvailableActions();
126 final IntentionAction action = findActionWithText(available, actionName);
127 assertNotNull("Action '" + actionName + "' not found among " + available, action);
131 protected static void invoke(@NotNull IntentionAction action) throws IncorrectOperationException {
132 PsiFile file = getFile();
133 WriteAction.run(() -> {
135 // Test that action will automatically clear the read-only attribute if modification is necessary.
136 // If your test fails due to this, make sure that your quick-fix/intention has the following line:
137 // if (!FileModificationService.getInstance().prepareFileForWrite(file)) return;
138 ReadOnlyAttributeUtil.setReadOnlyAttribute(file.getVirtualFile(), true);
140 catch (IOException e) {
141 throw new UncheckedIOException(e);
144 ReadonlyStatusHandlerImpl handler = (ReadonlyStatusHandlerImpl)ReadonlyStatusHandler.getInstance(file.getProject());
145 handler.setClearReadOnlyInTests(true);
147 ApplicationManager.getApplication().invokeLater(() ->
148 ShowIntentionActionsHandler.chooseActionAndInvoke(file, getEditor(), action, action.getText()));
149 UIUtil.dispatchAllInvocationEvents();
152 handler.setClearReadOnlyInTests(false);
156 protected IntentionAction findActionAndCheck(@NotNull ActionHint hint, String testFullPath) {
157 return hint.findAndCheck(getAvailableActions(), () -> "Test: "+testFullPath);
160 protected IntentionAction findActionWithText(@NotNull String text) {
161 return findActionWithText(getAvailableActions(), text);
164 public static IntentionAction findActionWithText(@NotNull List<IntentionAction> actions, @NotNull String text) {
165 for (IntentionAction action : actions) {
166 if (text.equals(action.getText())) {
174 * @deprecated use {@link LightQuickFixParameterizedTestCase}
175 * to get separate tests for all data files in testData directory.
177 protected void doAllTests() {
178 doAllTests(createWrapper());
181 public static void doAllTests(QuickFixTestCase testCase) {
182 final File[] files = getBeforeTestFiles(testCase);
184 for (File file : files) {
185 final String testName = file.getName().substring(BEFORE_PREFIX.length());
186 doTestFor(testName, testCase);
191 public static File[] getBeforeTestFiles(@NotNull QuickFixTestCase testCase) {
192 assertNotNull("getBasePath() should not return null!", testCase.getBasePath());
194 final String testDirPath = testCase.getTestDataPath().replace(File.separatorChar, '/') + testCase.getBasePath();
195 File testDir = new File(testDirPath);
196 final File[] files = testDir.listFiles((dir, name) -> name.startsWith(BEFORE_PREFIX));
198 if (files == null || files.length == 0) {
199 fail("Test files not found in " + testDirPath);
204 protected void doSingleTest(@NotNull String fileSuffix) {
205 doTestFor(fileSuffix, createWrapper());
208 protected void doSingleTest(String fileSuffix, String testDataPath) {
209 doTestFor(fileSuffix, createWrapper(testDataPath));
213 protected QuickFixTestCase createWrapper() {
214 return createWrapper(null);
218 protected QuickFixTestCase createWrapper(final String testDataPath) {
219 return new QuickFixTestCase() {
220 public String myTestDataPath = testDataPath;
223 public String getBasePath() {
224 return LightQuickFixTestCase.this.getBasePath();
229 public String getTestDataPath() {
230 if (myTestDataPath == null) {
231 myTestDataPath = LightQuickFixTestCase.this.getTestDataPath();
233 return myTestDataPath;
238 public ActionHint parseActionHintImpl(@NotNull PsiFile file, @NotNull String contents) {
239 return ActionHint.parse(file, contents);
243 public void beforeActionStarted(@NotNull String testName, @NotNull String contents) {
244 LightQuickFixTestCase.this.beforeActionStarted(testName, contents);
248 public void afterActionCompleted(@NotNull String testName, @NotNull String contents) {
249 LightQuickFixTestCase.this.afterActionCompleted(testName, contents);
253 public void doAction(@NotNull ActionHint actionHint, @NotNull String testFullPath, @NotNull String testName) throws Exception {
254 LightQuickFixTestCase.this.doAction(actionHint, testFullPath, testName);
258 public void checkResultByFile(@NotNull String message, @NotNull String expectedFilePath, boolean ignoreTrailingSpaces) throws Exception {
259 LightQuickFixTestCase.this.checkResultByFile(message, expectedFilePath, ignoreTrailingSpaces);
263 public IntentionAction findActionWithText(@NotNull String text) {
264 return LightQuickFixTestCase.this.findActionWithText(text);
268 public boolean shouldBeAvailableAfterExecution() {
269 return LightQuickFixTestCase.this.shouldBeAvailableAfterExecution();
273 public void invoke(@NotNull IntentionAction action) {
274 LightQuickFixTestCase.invoke(action);
279 public List<HighlightInfo> doHighlighting() {
280 return LightQuickFixTestCase.this.doHighlighting();
285 public List<IntentionAction> getAvailableActions() {
286 return LightQuickFixTestCase.this.getAvailableActions();
290 public void configureFromFileText(@NotNull String name, @NotNull String contents) throws IOException {
291 LightPlatformCodeInsightTestCase.configureFromFileText(name, contents, true);
295 public PsiFile getFile() {
296 return LightPlatformCodeInsightTestCase.getFile();
300 public Project getProject() {
301 return LightPlatformTestCase.getProject();
305 public void bringRealEditorBack() {
306 LightPlatformCodeInsightTestCase.bringRealEditorBack();
311 protected List<IntentionAction> getAvailableActions() {
313 return getAvailableActions(getEditor(), getFile());
317 public static List<IntentionAction> getAvailableActions(@NotNull Editor editor, @NotNull PsiFile file) {
318 return CodeInsightTestFixtureImpl.getAvailableIntentions(editor, file);
321 @NonNls protected String getBasePath() {return null;}