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.WriteAction;
23 import com.intellij.openapi.command.CommandProcessor;
24 import com.intellij.openapi.editor.Editor;
25 import com.intellij.openapi.project.Project;
26 import com.intellij.openapi.util.io.FileUtil;
27 import com.intellij.openapi.util.text.StringUtil;
28 import com.intellij.openapi.vcs.readOnlyHandler.ReadonlyStatusHandlerImpl;
29 import com.intellij.openapi.vfs.CharsetToolkit;
30 import com.intellij.openapi.vfs.ReadonlyStatusHandler;
31 import com.intellij.psi.PsiFile;
32 import com.intellij.rt.execution.junit.FileComparisonFailure;
33 import com.intellij.testFramework.LightPlatformCodeInsightTestCase;
34 import com.intellij.testFramework.LightPlatformTestCase;
35 import com.intellij.testFramework.fixtures.impl.CodeInsightTestFixtureImpl;
36 import com.intellij.util.IncorrectOperationException;
37 import com.intellij.util.ObjectUtils;
38 import com.intellij.util.io.ReadOnlyAttributeUtil;
39 import com.intellij.util.ui.UIUtil;
40 import org.jetbrains.annotations.NonNls;
41 import org.jetbrains.annotations.NotNull;
44 import java.io.IOException;
45 import java.io.UncheckedIOException;
46 import java.util.List;
48 public abstract class LightQuickFixTestCase extends LightDaemonAnalyzerTestCase {
49 @NonNls protected static final String BEFORE_PREFIX = "before";
50 @NonNls protected static final String AFTER_PREFIX = "after";
52 private static QuickFixTestCase myWrapper;
54 protected boolean shouldBeAvailableAfterExecution() {
59 protected ActionHint parseActionHintImpl(@NotNull PsiFile file, @NotNull String contents) {
60 return ActionHint.parse(file, contents);
63 private static void doTestFor(final String testName, final QuickFixTestCase quickFixTestCase) {
64 final String relativePath = ObjectUtils.notNull(quickFixTestCase.getBasePath(), "") + "/" + BEFORE_PREFIX + testName;
65 final String testFullPath = quickFixTestCase.getTestDataPath().replace(File.separatorChar, '/') + relativePath;
66 final File testFile = new File(testFullPath);
67 CommandProcessor.getInstance().executeCommand(quickFixTestCase.getProject(), () -> {
69 String contents = StringUtil.convertLineSeparators(FileUtil.loadFile(testFile, CharsetToolkit.UTF8_CHARSET));
70 quickFixTestCase.configureFromFileText(testFile.getName(), contents);
71 quickFixTestCase.bringRealEditorBack();
72 final ActionHint actionHint = quickFixTestCase.parseActionHintImpl(quickFixTestCase.getFile(), contents);
74 quickFixTestCase.beforeActionStarted(testName, contents);
77 myWrapper = quickFixTestCase;
78 quickFixTestCase.doAction(actionHint, testFullPath, testName);
82 quickFixTestCase.afterActionCompleted(testName, contents);
85 catch (FileComparisonFailure e){
95 protected void afterActionCompleted(final String testName, final String contents) {
98 protected void beforeActionStarted(final String testName, final String contents) {
101 public static void doAction(@NotNull ActionHint actionHint,
104 QuickFixTestCase quickFix) throws Exception {
105 IntentionAction action = actionHint.findAndCheck(quickFix.getAvailableActions(),
106 () -> "Test: "+testFullPath+"\nInfos: "+quickFix.doHighlighting());
107 if (action != null) {
108 String text = action.getText();
109 quickFix.invoke(action);
110 UIUtil.dispatchAllInvocationEvents();
111 UIUtil.dispatchAllInvocationEvents();
112 if (!quickFix.shouldBeAvailableAfterExecution()) {
113 final IntentionAction afterAction = quickFix.findActionWithText(text);
114 if (afterAction != null) {
115 fail("Action '" + text + "' is still available after its invocation in test " + testFullPath);
118 String expectedFilePath = ObjectUtils.notNull(quickFix.getBasePath(), "") + "/" + AFTER_PREFIX + testName;
119 quickFix.checkResultByFile("In file :" + expectedFilePath, expectedFilePath, false);
123 protected void doAction(@NotNull ActionHint actionHint, final String testFullPath, final String testName)
125 doAction(actionHint, testFullPath, testName, myWrapper);
128 protected void doAction(@NotNull String actionName) {
129 final List<IntentionAction> available = getAvailableActions();
130 final IntentionAction action = findActionWithText(available, actionName);
131 assertNotNull("Action '" + actionName + "' not found among " + available, action);
135 protected static void invoke(@NotNull IntentionAction action) throws IncorrectOperationException {
136 PsiFile file = getFile();
137 WriteAction.run(() -> {
139 // Test that action will automatically clear the read-only attribute if modification is necessary.
140 // If your test fails due to this, make sure that your quick-fix/intention has the following line:
141 // if (!FileModificationService.getInstance().prepareFileForWrite(file)) return;
142 ReadOnlyAttributeUtil.setReadOnlyAttribute(file.getVirtualFile(), true);
144 catch (IOException e) {
145 throw new UncheckedIOException(e);
148 ReadonlyStatusHandlerImpl handler = (ReadonlyStatusHandlerImpl)ReadonlyStatusHandler.getInstance(file.getProject());
149 handler.setClearReadOnlyInTests(true);
151 ShowIntentionActionsHandler.chooseActionAndInvoke(file, getEditor(), action, action.getText());
152 UIUtil.dispatchAllInvocationEvents();
155 handler.setClearReadOnlyInTests(false);
159 protected IntentionAction findActionAndCheck(@NotNull ActionHint hint, String testFullPath) {
160 return hint.findAndCheck(getAvailableActions(), () -> "Test: "+testFullPath);
163 protected IntentionAction findActionWithText(@NotNull String text) {
164 return findActionWithText(getAvailableActions(), text);
167 public static IntentionAction findActionWithText(@NotNull List<IntentionAction> actions, @NotNull String text) {
168 for (IntentionAction action : actions) {
169 if (text.equals(action.getText())) {
177 * @deprecated use {@link LightQuickFixParameterizedTestCase}
178 * to get separate tests for all data files in testData directory.
180 protected void doAllTests() {
181 doAllTests(createWrapper());
184 public static void doAllTests(QuickFixTestCase testCase) {
185 final File[] files = getBeforeTestFiles(testCase);
187 for (File file : files) {
188 final String testName = file.getName().substring(BEFORE_PREFIX.length());
189 doTestFor(testName, testCase);
194 public static File[] getBeforeTestFiles(@NotNull QuickFixTestCase testCase) {
195 assertNotNull("getBasePath() should not return null!", testCase.getBasePath());
197 final String testDirPath = testCase.getTestDataPath().replace(File.separatorChar, '/') + testCase.getBasePath();
198 File testDir = new File(testDirPath);
199 final File[] files = testDir.listFiles((dir, name) -> name.startsWith(BEFORE_PREFIX));
201 if (files == null || files.length == 0) {
202 fail("Test files not found in " + testDirPath);
207 protected void doSingleTest(String fileSuffix) {
208 doTestFor(fileSuffix, createWrapper());
211 protected void doSingleTest(String fileSuffix, String testDataPath) {
212 doTestFor(fileSuffix, createWrapper(testDataPath));
215 protected QuickFixTestCase createWrapper() {
216 return createWrapper(null);
219 protected QuickFixTestCase createWrapper(final String testDataPath) {
220 return new QuickFixTestCase() {
221 public String myTestDataPath = testDataPath;
224 public String getBasePath() {
225 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 LightQuickFixTestCase.this.parseActionHintImpl(file, contents);
243 public void beforeActionStarted(String testName, String contents) {
244 LightQuickFixTestCase.this.beforeActionStarted(testName, contents);
248 public void afterActionCompleted(String testName, String contents) {
249 LightQuickFixTestCase.this.afterActionCompleted(testName, contents);
253 public void doAction(ActionHint actionHint, String testFullPath, String testName) throws Exception {
254 LightQuickFixTestCase.this.doAction(actionHint, testFullPath, testName);
258 public void checkResultByFile(String s, @NotNull String expectedFilePath, boolean b) throws Exception {
259 LightQuickFixTestCase.this.checkResultByFile(s, expectedFilePath, b);
263 public IntentionAction findActionWithText(String text) {
264 return LightQuickFixTestCase.this.findActionWithText(text);
268 public boolean shouldBeAvailableAfterExecution() {
269 return LightQuickFixTestCase.this.shouldBeAvailableAfterExecution();
273 public void invoke(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(String name, 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());
316 public static List<IntentionAction> getAvailableActions(@NotNull Editor editor, @NotNull PsiFile file) {
317 return CodeInsightTestFixtureImpl.getAvailableIntentions(editor, file);
320 @NonNls protected String getBasePath() {return null;}