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() {
58 private static void doTestFor(@NotNull String testName, @NotNull QuickFixTestCase quickFixTestCase) {
59 final String relativePath = ObjectUtils.notNull(quickFixTestCase.getBasePath(), "") + "/" + BEFORE_PREFIX + testName;
60 final String testFullPath = quickFixTestCase.getTestDataPath().replace(File.separatorChar, '/') + relativePath;
61 final File testFile = new File(testFullPath);
62 CommandProcessor.getInstance().executeCommand(quickFixTestCase.getProject(), () -> {
64 String contents = StringUtil.convertLineSeparators(FileUtil.loadFile(testFile, CharsetToolkit.UTF8_CHARSET));
65 quickFixTestCase.configureFromFileText(testFile.getName(), contents);
66 quickFixTestCase.bringRealEditorBack();
67 final ActionHint actionHint = quickFixTestCase.parseActionHintImpl(quickFixTestCase.getFile(), contents);
69 quickFixTestCase.beforeActionStarted(testName, contents);
72 myWrapper = quickFixTestCase;
73 quickFixTestCase.doAction(actionHint, testFullPath, testName);
77 quickFixTestCase.afterActionCompleted(testName, contents);
80 catch (FileComparisonFailure e){
90 protected void afterActionCompleted(final String testName, final String contents) {
93 protected void beforeActionStarted(final String testName, final String contents) {
96 public static void doAction(@NotNull ActionHint actionHint,
99 QuickFixTestCase quickFix) throws Exception {
100 IntentionAction action = actionHint.findAndCheck(quickFix.getAvailableActions(),
101 () -> "Test: "+testFullPath+"\nInfos: "+quickFix.doHighlighting());
102 if (action != null) {
103 String text = action.getText();
104 quickFix.invoke(action);
105 UIUtil.dispatchAllInvocationEvents();
106 UIUtil.dispatchAllInvocationEvents();
107 if (!quickFix.shouldBeAvailableAfterExecution()) {
108 final IntentionAction afterAction = quickFix.findActionWithText(text);
109 if (afterAction != null) {
110 fail("Action '" + text + "' is still available after its invocation in test " + testFullPath);
113 String expectedFilePath = ObjectUtils.notNull(quickFix.getBasePath(), "") + "/" + AFTER_PREFIX + testName;
114 quickFix.checkResultByFile("In file :" + expectedFilePath, expectedFilePath, false);
118 protected void doAction(@NotNull ActionHint actionHint, final String testFullPath, final String testName)
120 doAction(actionHint, testFullPath, testName, myWrapper);
123 protected void doAction(@NotNull String actionName) {
124 final List<IntentionAction> available = getAvailableActions();
125 final IntentionAction action = findActionWithText(available, actionName);
126 assertNotNull("Action '" + actionName + "' not found among " + available, action);
130 protected static void invoke(@NotNull IntentionAction action) throws IncorrectOperationException {
131 PsiFile file = getFile();
132 WriteAction.run(() -> {
134 // Test that action will automatically clear the read-only attribute if modification is necessary.
135 // If your test fails due to this, make sure that your quick-fix/intention has the following line:
136 // if (!FileModificationService.getInstance().prepareFileForWrite(file)) return;
137 ReadOnlyAttributeUtil.setReadOnlyAttribute(file.getVirtualFile(), true);
139 catch (IOException e) {
140 throw new UncheckedIOException(e);
143 ReadonlyStatusHandlerImpl handler = (ReadonlyStatusHandlerImpl)ReadonlyStatusHandler.getInstance(file.getProject());
144 handler.setClearReadOnlyInTests(true);
146 ShowIntentionActionsHandler.chooseActionAndInvoke(file, getEditor(), action, action.getText());
147 UIUtil.dispatchAllInvocationEvents();
150 handler.setClearReadOnlyInTests(false);
154 protected IntentionAction findActionAndCheck(@NotNull ActionHint hint, String testFullPath) {
155 return hint.findAndCheck(getAvailableActions(), () -> "Test: "+testFullPath);
158 protected IntentionAction findActionWithText(@NotNull String text) {
159 return findActionWithText(getAvailableActions(), text);
162 public static IntentionAction findActionWithText(@NotNull List<IntentionAction> actions, @NotNull String text) {
163 for (IntentionAction action : actions) {
164 if (text.equals(action.getText())) {
172 * @deprecated use {@link LightQuickFixParameterizedTestCase}
173 * to get separate tests for all data files in testData directory.
175 protected void doAllTests() {
176 doAllTests(createWrapper());
179 public static void doAllTests(QuickFixTestCase testCase) {
180 final File[] files = getBeforeTestFiles(testCase);
182 for (File file : files) {
183 final String testName = file.getName().substring(BEFORE_PREFIX.length());
184 doTestFor(testName, testCase);
189 public static File[] getBeforeTestFiles(@NotNull QuickFixTestCase testCase) {
190 assertNotNull("getBasePath() should not return null!", testCase.getBasePath());
192 final String testDirPath = testCase.getTestDataPath().replace(File.separatorChar, '/') + testCase.getBasePath();
193 File testDir = new File(testDirPath);
194 final File[] files = testDir.listFiles((dir, name) -> name.startsWith(BEFORE_PREFIX));
196 if (files == null || files.length == 0) {
197 fail("Test files not found in " + testDirPath);
202 protected void doSingleTest(@NotNull String fileSuffix) {
203 doTestFor(fileSuffix, createWrapper());
206 protected void doSingleTest(String fileSuffix, String testDataPath) {
207 doTestFor(fileSuffix, createWrapper(testDataPath));
211 protected QuickFixTestCase createWrapper() {
212 return createWrapper(null);
216 protected QuickFixTestCase createWrapper(final String testDataPath) {
217 return new QuickFixTestCase() {
218 public String myTestDataPath = testDataPath;
221 public String getBasePath() {
222 return LightQuickFixTestCase.this.getBasePath();
227 public String getTestDataPath() {
228 if (myTestDataPath == null) {
229 myTestDataPath = LightQuickFixTestCase.this.getTestDataPath();
231 return myTestDataPath;
236 public ActionHint parseActionHintImpl(@NotNull PsiFile file, @NotNull String contents) {
237 return ActionHint.parse(file, contents);
241 public void beforeActionStarted(@NotNull String testName, @NotNull String contents) {
242 LightQuickFixTestCase.this.beforeActionStarted(testName, contents);
246 public void afterActionCompleted(@NotNull String testName, @NotNull String contents) {
247 LightQuickFixTestCase.this.afterActionCompleted(testName, contents);
251 public void doAction(@NotNull ActionHint actionHint, @NotNull String testFullPath, @NotNull String testName) throws Exception {
252 LightQuickFixTestCase.this.doAction(actionHint, testFullPath, testName);
256 public void checkResultByFile(@NotNull String message, @NotNull String expectedFilePath, boolean ignoreTrailingSpaces) throws Exception {
257 LightQuickFixTestCase.this.checkResultByFile(message, expectedFilePath, ignoreTrailingSpaces);
261 public IntentionAction findActionWithText(@NotNull String text) {
262 return LightQuickFixTestCase.this.findActionWithText(text);
266 public boolean shouldBeAvailableAfterExecution() {
267 return LightQuickFixTestCase.this.shouldBeAvailableAfterExecution();
271 public void invoke(@NotNull IntentionAction action) {
272 LightQuickFixTestCase.invoke(action);
277 public List<HighlightInfo> doHighlighting() {
278 return LightQuickFixTestCase.this.doHighlighting();
283 public List<IntentionAction> getAvailableActions() {
284 return LightQuickFixTestCase.this.getAvailableActions();
288 public void configureFromFileText(@NotNull String name, @NotNull String contents) throws IOException {
289 LightPlatformCodeInsightTestCase.configureFromFileText(name, contents, true);
293 public PsiFile getFile() {
294 return LightPlatformCodeInsightTestCase.getFile();
298 public Project getProject() {
299 return LightPlatformTestCase.getProject();
303 public void bringRealEditorBack() {
304 LightPlatformCodeInsightTestCase.bringRealEditorBack();
309 protected List<IntentionAction> getAvailableActions() {
311 return getAvailableActions(getEditor(), getFile());
315 public static List<IntentionAction> getAvailableActions(@NotNull Editor editor, @NotNull PsiFile file) {
316 return CodeInsightTestFixtureImpl.getAvailableIntentions(editor, file);
319 @NonNls protected String getBasePath() {return null;}