ApplyRandomIntentionsTest: perform mutations as random actions in a single test in different files

This commit is contained in:
peter
2017-07-04 14:03:15 +02:00
parent 958a020c90
commit 4d636b291d
12 changed files with 499 additions and 144 deletions
@@ -18,6 +18,7 @@ package com.intellij.java.propertyBased;
import com.intellij.codeInspection.ex.InspectionProfileImpl;
import com.intellij.history.Label;
import com.intellij.history.LocalHistory;
import com.intellij.history.LocalHistoryException;
import com.intellij.ide.impl.ProjectUtil;
import com.intellij.openapi.Disposable;
import com.intellij.openapi.application.Application;
@@ -33,6 +34,7 @@ import com.intellij.openapi.editor.EditorFactory;
import com.intellij.openapi.editor.event.DocumentEvent;
import com.intellij.openapi.editor.event.DocumentListener;
import com.intellij.openapi.fileEditor.FileDocumentManager;
import com.intellij.openapi.fileEditor.ex.FileEditorManagerEx;
import com.intellij.openapi.module.ModuleManager;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.project.ProjectManager;
@@ -43,19 +45,20 @@ import com.intellij.openapi.util.Disposer;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.PsiDocumentManager;
import com.intellij.psi.PsiJavaFile;
import com.intellij.psi.PsiManager;
import com.intellij.psi.impl.source.PostprocessReformattingAspect;
import com.intellij.psi.search.FilenameIndex;
import com.intellij.psi.search.GlobalSearchScope;
import com.intellij.testFramework.CompilerTester;
import com.intellij.testFramework.PlatformTestCase;
import com.intellij.testFramework.TestDataProvider;
import com.intellij.testFramework.UsefulTestCase;
import com.intellij.testFramework.*;
import com.intellij.util.ThrowableRunnable;
import com.intellij.util.containers.ContainerUtil;
import slowCheck.Generator;
import java.io.File;
import java.util.ArrayList;
import java.util.List;
import java.util.function.Consumer;
import java.util.stream.Collectors;
public abstract class AbstractApplyAndRevertTestCase extends PlatformTestCase {
@@ -73,18 +76,28 @@ public abstract class AbstractApplyAndRevertTestCase extends PlatformTestCase {
return Generator.sampledFrom(allFiles);
}
protected Generator<PsiJavaFile> psiJavaFiles() {
return javaFiles().map(vf -> (PsiJavaFile)PsiManager.getInstance(myProject).findFile(vf));
}
protected static void restrictChangesToDocument(Document document, Runnable r) {
watchDocumentChanges(r::run, event -> {
Document changed = event.getDocument();
if (changed != document) {
VirtualFile file = FileDocumentManager.getInstance().getFile(changed);
if (file != null && file.isInLocalFileSystem()) {
throw new AssertionError("Unexpected document change: " + changed);
}
}
});
}
private static <E extends Throwable> void watchDocumentChanges(ThrowableRunnable<E> r, final Consumer<DocumentEvent> eventHandler) throws E {
Disposable disposable = Disposer.newDisposable();
EditorFactory.getInstance().getEventMulticaster().addDocumentListener(new DocumentListener() {
@Override
public void beforeDocumentChange(DocumentEvent event) {
Document changed = event.getDocument();
if (changed != document) {
VirtualFile file = FileDocumentManager.getInstance().getFile(changed);
if (file != null && file.isInLocalFileSystem()) {
throw new AssertionError("Unexpected document change: " + changed);
}
}
public void documentChanged(DocumentEvent event) {
eventHandler.accept(event);
}
}, disposable);
try {
@@ -96,24 +109,50 @@ public abstract class AbstractApplyAndRevertTestCase extends PlatformTestCase {
protected void changeAndRevert(Runnable r) {
Label label = LocalHistory.getInstance().putUserLabel(myProject, "changeAndRevert");
boolean failed = false;
try {
r.run();
}
catch (Throwable e) {
failed = true;
throw e;
}
finally {
restoreEverything(label, failed);
}
}
private void restoreEverything(Label label, boolean failed) {
try {
WriteAction.run(() -> {
try {
PostprocessReformattingAspect.getInstance(myProject).doPostponedFormatting();
FileDocumentManager.getInstance().saveAllDocuments();
label.revert(myProject, myProject.getBaseDir());
PsiDocumentManager.getInstance(myProject).commitAllDocuments();
assertEmpty(PsiDocumentManager.getInstance(myProject).getUncommittedDocuments());
assertEmpty(FileDocumentManager.getInstance().getUnsavedDocuments());
}
catch (Throwable e) {
e.printStackTrace();
}
PsiDocumentManager documentManager = PsiDocumentManager.getInstance(myProject);
new RunAll(
() -> PostprocessReformattingAspect.getInstance(myProject).doPostponedFormatting(),
() -> FileEditorManagerEx.getInstanceEx(myProject).closeAllFiles(),
() -> FileDocumentManager.getInstance().saveAllDocuments(),
() -> revertVfs(label, documentManager),
() -> documentManager.commitAllDocuments(),
() -> assertEmpty(documentManager.getUncommittedDocuments()),
() -> assertEmpty(FileDocumentManager.getInstance().getUnsavedDocuments())
).run();
});
}
catch (Throwable e) {
if (failed) {
LOG.info("Exceptions while restoring state", e);
} else {
throw e;
}
}
}
private void revertVfs(Label label, PsiDocumentManager documentManager) throws LocalHistoryException {
watchDocumentChanges(() -> label.revert(myProject, myProject.getBaseDir()),
__ -> {
if (documentManager.getUncommittedDocuments().length > 3) {
documentManager.commitAllDocuments();
}
});
}
@Override
@@ -17,6 +17,7 @@ package com.intellij.java.propertyBased;
import com.intellij.openapi.editor.Document;
import com.intellij.openapi.editor.RangeMarker;
import com.intellij.openapi.util.Segment;
import com.intellij.openapi.util.TextRange;
import org.jetbrains.annotations.Nullable;
@@ -24,7 +25,7 @@ import org.jetbrains.annotations.Nullable;
* @author peter
*/
class ActionOnRange {
private final RangeMarker myMarker;
protected final RangeMarker myMarker;
private TextRange finalRange;
ActionOnRange(Document document, int start, int end) {
@@ -36,6 +37,10 @@ class ActionOnRange {
return range == null ? -1 : range.getStartOffset();
}
Segment getCurrentRange() {
return finalRange == null ? myMarker : finalRange;
}
@Nullable
TextRange getFinalRange() {
if (finalRange == null) {
@@ -0,0 +1,38 @@
/*
* Copyright 2000-2017 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.java.propertyBased;
import com.intellij.psi.JavaPsiFacade;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiFile;
import com.intellij.psi.PsiMethodCallExpression;
import com.intellij.psi.util.PsiTreeUtil;
class AddNullArgument extends FilePsiMutation {
AddNullArgument(PsiFile file) {
super(file);
}
@Override
protected void performMutation() {
PsiTreeUtil.findChildrenOfType(myFile, PsiMethodCallExpression.class).stream()
.filter(PsiElement::isValid)
.filter(call -> call.getArgumentList().getExpressions().length > 1)
.forEach(call -> call.getArgumentList().add(
JavaPsiFacade.getElementFactory(myFile.getProject()).createExpressionFromText("null", call)));
}
}
@@ -15,18 +15,20 @@
*/
package com.intellij.java.propertyBased;
import com.intellij.openapi.command.WriteCommandAction;
import com.intellij.psi.*;
import com.intellij.psi.PsiDocumentManager;
import com.intellij.psi.PsiManager;
import com.intellij.psi.impl.PsiDocumentManagerImpl;
import com.intellij.psi.util.PsiModificationTracker;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.testFramework.SkipSlowTestLocally;
import com.intellij.util.SystemProperties;
import org.jetbrains.annotations.Nullable;
import slowCheck.*;
import com.intellij.util.containers.ContainerUtil;
import slowCheck.CheckerSettings;
import slowCheck.Generator;
import slowCheck.IntDistribution;
import slowCheck.PropertyChecker;
import java.util.Objects;
import java.util.List;
import java.util.concurrent.atomic.AtomicLong;
import java.util.function.Consumer;
@SkipSlowTestLocally
public class ApplyRandomIntentionsTest extends AbstractApplyAndRevertTestCase {
@@ -34,109 +36,18 @@ public class ApplyRandomIntentionsTest extends AbstractApplyAndRevertTestCase {
@Override
public void setUp() throws Exception {
super.setUp();
((PsiDocumentManagerImpl)PsiDocumentManager.getInstance(myProject)).disableBackgroundCommit(getTestRootDisposable());
}
public void testIntentionsInDifferentFiles() throws Throwable {
initCompiler();
}
public void testOpenFilesAndRevert() throws Throwable {
doOpenFilesAndRevert(null);
}
public void testOpenFilesAndRevertDeleteForeachInitializers() throws Throwable {
doOpenFilesAndRevert(psiFile -> {
WriteCommandAction.runWriteCommandAction(myProject, () -> PsiTreeUtil.findChildrenOfType(psiFile, PsiForStatement.class).stream()
.limit(20)
.forEach(stmt -> stmt.getInitialization().delete()));
});
}
public void testOpenFilesAndRevertDeleteSecondArgument() throws Throwable {
doOpenFilesAndRevert(psiFile -> {
WriteCommandAction.runWriteCommandAction(myProject, () -> PsiTreeUtil.findChildrenOfType(psiFile, PsiCallExpression.class)
.stream()
.filter(PsiElement::isValid)
.map(PsiCall::getArgumentList)
.filter(Objects::nonNull)
.filter(argList -> argList.getExpressions().length > 1)
.limit(20)
.forEach(argList -> {
if (!argList.isValid()) return;
PsiExpression arg = argList.getExpressions()[1];
if (!arg.isValid()) return;
arg.delete();
}));
});
}
public void testOpenFilesAndRevertAddNullArgument() throws Throwable {
doOpenFilesAndRevert(psiFile -> {
WriteCommandAction.runWriteCommandAction(myProject,
() -> PsiTreeUtil.findChildrenOfType(psiFile, PsiMethodCallExpression.class).stream()
.filter(PsiElement::isValid)
.filter(call -> call.getArgumentList().getExpressions().length > 1)
.forEach(call -> call.getArgumentList().add(JavaPsiFacade.getElementFactory(myProject).createExpressionFromText("null", call))));
});
}
public void testMakeAllMethodsVoid() throws Throwable {
doOpenFilesAndRevert(psiFile -> {
WriteCommandAction.runWriteCommandAction(myProject,
() -> PsiTreeUtil.findChildrenOfType(psiFile, PsiMethod.class).stream()
.filter(method -> method.getReturnTypeElement() != null)
.forEach(method -> method.getReturnTypeElement().replace(JavaPsiFacade.getElementFactory(myProject).createTypeElement(PsiType.VOID))));
});
}
private void doOpenFilesAndRevert(@Nullable Consumer<PsiFile> mutation) throws Throwable {
PsiManager psiManager = PsiManager.getInstance(myProject);
CheckerSettings settings = CheckerSettings.DEFAULT_SETTINGS;
PropertyChecker.forAll(settings.withIterationCount(10), javaFiles(), file -> {
if (mutation == null) {
checkCompiles(myCompilerTester.rebuild());
}
PsiFile psiFile = psiManager.findFile(file);
if (psiFile == null) return false;
Generator<InvokeIntention> genInvocation = Generator.from(data -> InvokeIntention.generate(psiFile, data)).noShrink();
PropertyChecker.forAll(settings.withIterationCount(20), Generator.nonEmptyLists(genInvocation), list -> {
PsiDocumentManager documentManager = PsiDocumentManager.getInstance(myProject);
changeAndRevert(() -> {
if (mutation != null) {
mutation.accept(psiFile);
}
documentManager.commitAllDocuments();
long modCount = psiManager.getModificationTracker().getModificationCount();
for (InvokeIntention invocation : list) {
String textBefore = psiFile.getText();
try {
invocation.invokeIntention();
}
catch (Throwable e) {
LOG.debug("File " + file.getName() + " text before applying " + invocation + ":\n" + textBefore);
throw e;
}
}
if (mutation == null && modCount != psiManager.getModificationTracker().getModificationCount()) {
checkCompiles(myCompilerTester.make());
}
});
return true;
});
return true;
});
}
public void testModificationsInDifferentFiles() throws Throwable {
PsiManager psiManager = PsiManager.getInstance(myProject);
PsiModificationTracker tracker = psiManager.getModificationTracker();
PsiModificationTracker tracker = PsiManager.getInstance(myProject).getModificationTracker();
AtomicLong rebuildStamp = new AtomicLong();
CheckerSettings settings = CheckerSettings.DEFAULT_SETTINGS.withIterationCount(30);
Generator<InvokeIntention> genIntention =
Generator.from(data -> InvokeIntention.generate(psiManager.findFile(javaFiles().generateValue(data)), data));
Generator<InvokeIntention> genIntention = psiJavaFiles().flatMap(
file -> Generator.from(data -> InvokeIntention.generate(file, data)));
PropertyChecker.forAll(settings, Generator.listsOf(genIntention.noShrink()), list -> {
long startModCount = tracker.getModificationCount();
if (rebuildStamp.getAndSet(startModCount) != startModCount) {
@@ -144,9 +55,8 @@ public class ApplyRandomIntentionsTest extends AbstractApplyAndRevertTestCase {
}
changeAndRevert(() -> {
for (InvokeIntention invocation : list) {
invocation.invokeIntention();
}
MadTestingAction.runActions(list, myProject);
if (tracker.getModificationCount() != startModCount) {
checkCompiles(myCompilerTester.make());
}
@@ -155,6 +65,30 @@ public class ApplyRandomIntentionsTest extends AbstractApplyAndRevertTestCase {
});
}
public void testIntentionsAndModificationsInDifferentFiles() throws Throwable {
CheckerSettings settings = CheckerSettings.DEFAULT_SETTINGS.withIterationCount(50);
Generator<List<MadTestingAction>> genActionGroup = psiJavaFiles().flatMap(
file -> {
Generator<MadTestingAction> mutation = Generator.anyOf(DeleteRange.deletePsiRange(file),
Generator.constant(new AddNullArgument(file)),
Generator.constant(new DeleteForeachInitializers(file)),
Generator.constant(new DeleteSecondArgument(file)),
Generator.constant(new MakeAllMethodsVoid(file)));
Generator<MadTestingAction> allActions = Generator.frequency(2, Generator.from(data -> InvokeIntention.generate(file, data)),
1, Generator.constant(new RehighlightAllEditors(myProject)),
1, mutation);
return Generator.listsOf(IntDistribution.uniform(0, 5), allActions.noShrink());
});
PropertyChecker.forAll(settings, Generator.listsOf(genActionGroup).map(ContainerUtil::flatten), list -> {
changeAndRevert(() -> {
//System.out.println(list);
MadTestingAction.runActions(list, myProject);
});
return true;
});
}
@Override
protected String getTestDataPath() {
return SystemProperties.getUserHome() + "/IdeaProjects/univocity-parsers";
@@ -0,0 +1,39 @@
/*
* Copyright 2000-2017 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.java.propertyBased;
import com.intellij.psi.PsiFile;
import com.intellij.psi.PsiForStatement;
import com.intellij.psi.util.PsiTreeUtil;
import java.util.Objects;
class DeleteForeachInitializers extends FilePsiMutation {
DeleteForeachInitializers(PsiFile file) {
super(file);
}
@Override
protected void performMutation() {
PsiTreeUtil.findChildrenOfType(myFile, PsiForStatement.class).stream()
.limit(20)
.map(stmt -> stmt.getInitialization())
.filter(Objects::nonNull)
.forEach(stmt -> stmt.delete());
}
}
@@ -0,0 +1,71 @@
/*
* Copyright 2000-2017 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.java.propertyBased;
import com.intellij.openapi.command.WriteCommandAction;
import com.intellij.openapi.util.TextRange;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiFile;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.psi.util.PsiUtilCore;
import com.intellij.testFramework.PsiTestUtil;
import org.jetbrains.annotations.NotNull;
import slowCheck.Generator;
import slowCheck.IntDistribution;
import java.util.Objects;
class DeleteRange extends ActionOnRange implements MadTestingAction {
private final PsiFile myFile;
private DeleteRange(PsiFile file, int startOffset, int endOffset) {
super(file.getViewProvider().getDocument(), startOffset, endOffset);
assert myMarker.getDocument().getTextLength() == file.getTextLength();
myFile = file;
}
static Generator<DeleteRange> deletePsiRange(@NotNull PsiFile psiFile) {
return Generator.from(data -> {
if (psiFile.getTextLength() == 0) return new DeleteRange(psiFile, 0, 0);
int startOffset = Generator.integers(0, psiFile.getTextLength() - 1).generateValue(data);
PsiElement start = psiFile.findElementAt(startOffset);
PsiElement end = psiFile.findElementAt(startOffset + data.drawInt(IntDistribution.geometric(10)));
if (start == null || end == null) return null;
PsiElement commonParent = PsiTreeUtil.findCommonParent(start, end);
return new DeleteRange(psiFile,
commonParent.getTextRange().getStartOffset(),
commonParent.getTextRange().getEndOffset());
}).suchThat(Objects::nonNull);
}
@Override
public String toString() {
return "DeleteRange: " + myFile.getVirtualFile().getPath() + " " + getCurrentRange();
}
public void performAction() {
TextRange range = getFinalRange();
if (range == null) return;
WriteCommandAction.runWriteCommandAction(myFile.getProject(), () -> myFile.getViewProvider().getDocument()
.deleteString(range.getStartOffset(), range.getEndOffset()));
PsiUtilCore.ensureValid(myFile);
PsiTestUtil.checkStubsMatchText(myFile);
}
}
@@ -0,0 +1,44 @@
/*
* Copyright 2000-2017 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.java.propertyBased;
import com.intellij.psi.*;
import com.intellij.psi.util.PsiTreeUtil;
import java.util.Objects;
class DeleteSecondArgument extends FilePsiMutation {
DeleteSecondArgument(PsiFile file) {
super(file);
}
@Override
protected void performMutation() {
PsiTreeUtil.findChildrenOfType(myFile, PsiCallExpression.class)
.stream()
.filter(PsiElement::isValid)
.map(PsiCall::getArgumentList)
.filter(Objects::nonNull)
.filter(argList -> argList.getExpressions().length > 1)
.limit(20)
.forEach(argList -> {
if (!argList.isValid()) return;
PsiExpression arg = argList.getExpressions()[1];
if (!arg.isValid()) return;
arg.delete();
});
}
}
@@ -0,0 +1,44 @@
/*
* Copyright 2000-2017 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.java.propertyBased;
import com.intellij.openapi.command.WriteCommandAction;
import com.intellij.psi.PsiFile;
import com.intellij.testFramework.PsiTestUtil;
/**
* @author peter
*/
abstract class FilePsiMutation implements MadTestingAction {
protected final PsiFile myFile;
FilePsiMutation(PsiFile file) {
myFile = file;
}
@Override
public String toString() {
return getClass().getSimpleName() + "[" + myFile.getVirtualFile().getPath() + "]";
}
@Override
public void performAction() {
WriteCommandAction.runWriteCommandAction(myFile.getProject(), this::performMutation);
PsiTestUtil.checkStubsMatchText(myFile);
}
protected abstract void performMutation();
}
@@ -15,7 +15,9 @@
*/
package com.intellij.java.propertyBased;
import com.intellij.codeInsight.daemon.impl.HighlightInfo;
import com.intellij.codeInsight.intention.IntentionAction;
import com.intellij.lang.annotation.HighlightSeverity;
import com.intellij.openapi.editor.Document;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.fileEditor.FileEditorManager;
@@ -33,7 +35,7 @@ import slowCheck.Generator;
import java.util.List;
class InvokeIntention extends ActionOnRange {
class InvokeIntention extends ActionOnRange implements MadTestingAction {
private final PsiFile myFile;
private final int myIntentionIndex;
private IntentionAction myIntentionAction;
@@ -57,24 +59,23 @@ class InvokeIntention extends ActionOnRange {
if (name == null) {
name = myIntentionAction.toString();
}
return "Intention: " + myFile.getVirtualFile().getPath() + ", offset " + getStartOffset() + ", invoke " + name;
return "InvokeIntention[" + myFile.getVirtualFile().getPath() + ", offset " + getStartOffset() + ", invoke '" + name + "']";
}
void invokeIntention() {
public void performAction() {
int offset = getStartOffset();
if (offset < 0) return;
Editor editor = FileEditorManager.getInstance(myFile.getProject()).openTextEditor(new OpenFileDescriptor(myFile.getProject(), myFile.getVirtualFile(), offset), true);
CodeInsightTestFixtureImpl.instantiateAndRun(myFile, editor, new int[0], false);
List<HighlightInfo> infos = RehighlightAllEditors.highlightEditor(editor, myFile.getProject());
boolean hasErrors = infos.stream().anyMatch(i -> i.getSeverity() == HighlightSeverity.ERROR);
IntentionAction intention = myIntentionAction = getRandomIntention(editor);
if (intention == null) return;
System.out.println("apply " + this);
String currentFileText = myFile.getText();
Document changedDocument = getDocumentToBeChanged(intention);
String textBefore = changedDocument == null ? null : changedDocument.getText();
Runnable r = () -> CodeInsightTestFixtureImpl.invokeIntention(intention, myFile, editor, intention.getText());
if (changedDocument != null) {
@@ -87,8 +88,8 @@ class InvokeIntention extends ActionOnRange {
PsiDocumentManager.getInstance(myFile.getProject()).isDocumentBlockedByPsi(changedDocument)) {
throw new AssertionError("Document is left blocked by PSI");
}
if (myFile.textMatches(currentFileText)) {
throw new AssertionError("No change was performed: " + currentFileText);
if (!hasErrors && textBefore != null && textBefore.equals(changedDocument.getText())) {
throw new AssertionError("No change was performed in " + changedDocument + "\n" + textBefore);
}
PsiTestUtil.checkStubsMatchText(myFile);
@@ -114,8 +115,6 @@ class InvokeIntention extends ActionOnRange {
actionText.startsWith("Attach annotations") ||
actionText.startsWith("Convert to string literal") ||
actionText.startsWith("Optimize imports") || // https://youtrack.jetbrains.com/issue/IDEA-173801
actionText.startsWith("Move assignment to field declaration") || // https://youtrack.jetbrains.com/issue/IDEA-174956
actionText.startsWith("Add on demand static import") || // https://youtrack.jetbrains.com/issue/IDEA-174965
actionText.startsWith("Make method default") ||
actionText.contains("to custom tags") || // changes only inspection settings
actionText.startsWith("Typo: Change to...") || // doesn't change file text (starts live template)
@@ -123,6 +122,10 @@ class InvokeIntention extends ActionOnRange {
actionText.startsWith("Rename reference") || // doesn't change file text (starts live template)
actionText.startsWith("Detail exceptions") || // can produce uncompilable code if 'catch' section contains 'instanceof's
actionText.startsWith("Insert call to super method") || // super method can declare checked exceptions, unexpected at this point
actionText.startsWith("Add qualifier") || // in javadoc; displays a popup which isn't allowed in tests
actionText.startsWith("Cast to ") || // produces uncompilable code by design
actionText.startsWith("Unwrap 'else' branch (changes semantics)") || // might produce code with final variables are initialized several times
actionText.startsWith("Create missing 'switch' branches") || // if all existing branches do 'return something', we don't automatically generate compilable code for new branches
actionText.startsWith("Unimplement");
}
@@ -0,0 +1,42 @@
/*
* Copyright 2000-2017 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.java.propertyBased;
import com.intellij.openapi.fileEditor.FileDocumentManager;
import com.intellij.openapi.project.Project;
import com.intellij.psi.PsiDocumentManager;
import java.util.List;
/**
* @author peter
*/
interface MadTestingAction {
void performAction();
static void runActions(List<? extends MadTestingAction> list, Project project) {
for (int i = 0; i < list.size(); i++) {
MadTestingAction action = list.get(i);
if (i > 0 && action == list.get(i - 1)) continue;
FileDocumentManager.getInstance().saveAllDocuments();
PsiDocumentManager.getInstance(project).commitAllDocuments();
action.performAction();
}
}
}
@@ -0,0 +1,36 @@
/*
* Copyright 2000-2017 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.java.propertyBased;
import com.intellij.psi.JavaPsiFacade;
import com.intellij.psi.PsiFile;
import com.intellij.psi.PsiMethod;
import com.intellij.psi.PsiType;
import com.intellij.psi.util.PsiTreeUtil;
class MakeAllMethodsVoid extends FilePsiMutation {
MakeAllMethodsVoid(PsiFile file) {
super(file);
}
@Override
protected void performMutation() {
PsiTreeUtil.findChildrenOfType(myFile, PsiMethod.class).stream()
.filter(method -> method.getReturnTypeElement() != null)
.forEach(method -> method.getReturnTypeElement().replace(JavaPsiFacade.getElementFactory(myFile.getProject()).createTypeElement(PsiType.VOID)));
}
}
@@ -0,0 +1,60 @@
/*
* Copyright 2000-2017 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.java.propertyBased;
import com.intellij.codeInsight.daemon.impl.HighlightInfo;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.fileEditor.FileEditor;
import com.intellij.openapi.fileEditor.FileEditorManager;
import com.intellij.openapi.fileEditor.TextEditor;
import com.intellij.openapi.project.Project;
import com.intellij.psi.PsiDocumentManager;
import com.intellij.psi.PsiFile;
import com.intellij.testFramework.fixtures.impl.CodeInsightTestFixtureImpl;
import org.jetbrains.annotations.NotNull;
import java.util.List;
/**
* @author peter
*/
class RehighlightAllEditors implements MadTestingAction {
private final Project myProject;
RehighlightAllEditors(Project project) {
myProject = project;
}
@Override
public void performAction() {
for (FileEditor editor : FileEditorManager.getInstance(myProject).getAllEditors()) {
if (editor instanceof TextEditor) {
highlightEditor(((TextEditor)editor).getEditor(), myProject);
}
}
}
@Override
public String toString() {
return "RehighlightAllEditors";
}
@NotNull
static List<HighlightInfo> highlightEditor(Editor editor, Project project) {
PsiFile file = PsiDocumentManager.getInstance(project).getPsiFile(editor.getDocument());
return CodeInsightTestFixtureImpl.instantiateAndRun(file, editor, new int[0], false);
}
}