Property tests for pattern matching

GitOrigin-RevId: a2c5cc39288e3ab4151d2639ef9957ea783c6180
This commit is contained in:
Tagir Valeev
2020-01-30 17:39:53 +07:00
committed by intellij-monorepo-bot
parent f7bb70d50b
commit e45be2b02e
3 changed files with 172 additions and 113 deletions

View File

@@ -0,0 +1,52 @@
// Copyright 2000-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package com.intellij.java.propertyBased;
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.testFramework.propertyBased.IntentionPolicy;
import com.intellij.testFramework.propertyBased.InvokeIntention;
import com.intellij.util.containers.ContainerUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jetCheck.Generator;
import java.util.Collection;
import java.util.List;
import java.util.function.Function;
public class InvokeIntentionAtElement extends InvokeIntention {
private final Function<? super PsiFile, ? extends Collection<PsiElement>> myExtractor;
public <T extends PsiElement> InvokeIntentionAtElement(@NotNull PsiFile file,
@NotNull IntentionPolicy policy,
@NotNull Class<T> elementClass,
@NotNull Function<? super T, ? extends PsiElement> adjuster) {
this(file, policy, f -> ContainerUtil.map(PsiTreeUtil.findChildrenOfType(f, elementClass), adjuster::apply));
}
public InvokeIntentionAtElement(@NotNull PsiFile file,
@NotNull IntentionPolicy policy,
@NotNull Function<? super PsiFile, ? extends Collection<PsiElement>> extractor) {
super(file, policy);
myExtractor = extractor;
}
@Override
protected int generateDocOffset(@NotNull Environment env, @Nullable String logMessage) {
Collection<PsiElement> children = myExtractor.apply(getFile());
if (children.isEmpty()) {
return super.generateDocOffset(env, logMessage);
}
List<Generator<Integer>> generators =
ContainerUtil.map(children, stmt -> {
TextRange range = stmt.getTextRange();
return Generator.integers(range.getStartOffset(),
range.getEndOffset()).noShrink();
});
return env.generateValue(Generator.anyOf(generators), logMessage);
}
}

View File

@@ -0,0 +1,120 @@
// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package com.intellij.java.propertyBased;
import com.intellij.openapi.application.PathManager;
import com.intellij.openapi.projectRoots.impl.JavaAwareProjectJdkTableImpl;
import com.intellij.openapi.util.RecursionManager;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.psi.*;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.psi.util.PsiUtil;
import com.intellij.testFramework.LightProjectDescriptor;
import com.intellij.testFramework.SkipSlowTestLocally;
import com.intellij.testFramework.fixtures.LightJavaCodeInsightFixtureTestCase;
import com.intellij.testFramework.propertyBased.*;
import com.siyeh.ig.psiutils.InstanceOfUtils;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jetCheck.Generator;
import org.jetbrains.jetCheck.PropertyChecker;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.function.Function;
import java.util.function.Supplier;
@SkipSlowTestLocally
public class JavaFeatureSpecificSanityTest extends LightJavaCodeInsightFixtureTestCase {
@NotNull
@Override
protected LightProjectDescriptor getProjectDescriptor() {
return JAVA_14;
}
@Override
protected void tearDown() throws Exception {
// remove jdk if it was created during highlighting to avoid leaks
try {
JavaAwareProjectJdkTableImpl.removeInternalJdkInTests();
}
catch (Throwable e) {
addSuppressedException(e);
}
finally {
super.tearDown();
}
}
public void testSwitchExpressionSpecific() {
MadTestingUtil.enableAllInspections(getProject());
RecursionManager.disableMissedCacheAssertions(getTestRootDisposable()); // IDEA-228814
Function<PsiFile, Generator<? extends MadTestingAction>> fileActions =
file -> {
InvokeIntention anyIntentionInSwitchRange = new InvokeIntentionAtElement(
file, new JavaIntentionPolicy(), PsiSwitchBlock.class, Function.identity());
InvokeIntention replaceToEnhancedSwitchIntention = new InvokeIntentionAtElement(file, new IntentionPolicy() {
@Override
protected boolean shouldSkipIntention(@NotNull String actionText) {
return !"Replace with 'switch' expression".equals(actionText) && !"Replace with enhanced 'switch' statement".equals(actionText);
}
}, PsiSwitchBlock.class, PsiSwitchBlock::getFirstChild);
return Generator.sampledFrom(anyIntentionInSwitchRange, replaceToEnhancedSwitchIntention, new StripTestDataMarkup(file));
};
PropertyChecker.checkScenarios(createChooser(fileActions, " switch"));
}
public void testPatternInstanceOfSpecific() {
MadTestingUtil.enableAllInspections(getProject());
RecursionManager.disableMissedCacheAssertions(getTestRootDisposable()); // IDEA-228814
Function<PsiFile, Generator<? extends MadTestingAction>> fileActions =
file -> {
InvokeIntention anyIntentionAroundInstanceOf = new InvokeIntentionAtElement(
file, new JavaIntentionPolicy(), PsiInstanceOfExpression.class, stmt -> {
PsiCodeBlock codeBlock = PsiTreeUtil.getParentOfType(stmt, PsiCodeBlock.class);
if (codeBlock != null) {
return codeBlock;
}
return stmt.getParent();
});
InvokeIntention replaceToPattern = new InvokeIntentionAtElement(file, new IntentionPolicy() {
@Override
protected boolean shouldSkipIntention(@NotNull String actionText) {
return !actionText.matches("Replace '.+' with pattern variable");
}
}, f -> {
Collection<PsiElement> targets = new ArrayList<>();
for (PsiTypeCastExpression cast : PsiTreeUtil.findChildrenOfType(f, PsiTypeCastExpression.class)) {
PsiInstanceOfExpression candidate = InstanceOfUtils.findPatternCandidate(cast);
if (candidate != null) {
PsiElement element = PsiUtil.skipParenthesizedExprUp(cast.getParent());
if (element instanceof PsiLocalVariable) {
targets.add(((PsiLocalVariable)element).getNameIdentifier());
}
}
}
return targets;
});
return Generator.sampledFrom(anyIntentionAroundInstanceOf, replaceToPattern, new StripTestDataMarkup(file));
};
PropertyChecker.checkScenarios(createChooser(fileActions, " instanceof"));
}
private Supplier<MadTestingAction> createChooser(Function<PsiFile, Generator<? extends MadTestingAction>> fileActions, String substring) {
return MadTestingUtil.actionsOnFileContents(myFixture, PathManager.getHomePath(), f -> {
try {
return f.getName().endsWith(".java") && FileUtil.loadFile(f).contains(substring);
}
catch (IOException e) {
return false;
}
}, fileActions);
}
}

View File

@@ -1,113 +0,0 @@
// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package com.intellij.java.propertyBased;
import com.intellij.openapi.application.PathManager;
import com.intellij.openapi.projectRoots.impl.JavaAwareProjectJdkTableImpl;
import com.intellij.openapi.util.RecursionManager;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiFile;
import com.intellij.psi.PsiSwitchBlock;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.testFramework.LightProjectDescriptor;
import com.intellij.testFramework.SkipSlowTestLocally;
import com.intellij.testFramework.fixtures.LightJavaCodeInsightFixtureTestCase;
import com.intellij.testFramework.propertyBased.*;
import com.intellij.util.containers.ContainerUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jetCheck.Generator;
import org.jetbrains.jetCheck.PropertyChecker;
import java.io.IOException;
import java.util.Collection;
import java.util.List;
import java.util.function.Function;
import java.util.function.Supplier;
@SkipSlowTestLocally
public class JavaSwitchExpressionSanityTest extends LightJavaCodeInsightFixtureTestCase {
@NotNull
@Override
protected LightProjectDescriptor getProjectDescriptor() {
return JAVA_13;
}
@Override
protected void tearDown() throws Exception {
// remove jdk if it was created during highlighting to avoid leaks
try {
JavaAwareProjectJdkTableImpl.removeInternalJdkInTests();
}
catch (Throwable e) {
addSuppressedException(e);
}
finally {
super.tearDown();
}
}
public void testIntentionsAroundSwitch() {
MadTestingUtil.enableAllInspections(getProject(), "BoundedWildcard"); // IDEA-194460
RecursionManager.disableMissedCacheAssertions(getTestRootDisposable()); // IDEA-228814
Function<PsiFile, Generator<? extends MadTestingAction>> fileActions =
file -> {
InvokeIntentionAroundSwitch anyIntentionInSwitchRange = new InvokeIntentionAroundSwitch(file, new JavaIntentionPolicy() {
@Override
protected boolean shouldSkipByFamilyName(@NotNull String familyName) {
return super.shouldSkipByFamilyName(familyName);
}
});
InvokeIntentionAroundSwitch replaceToEnhancedSwitchIntention = new InvokeIntentionAroundSwitch(file, new IntentionPolicy() {
@Override
protected boolean shouldSkipIntention(@NotNull String actionText) {
return !"Replace with 'switch' expression".equals(actionText) && !"Replace with enhanced 'switch' statement".equals(actionText);
}
}) {
@Override
protected PsiElement getRangeElement(PsiSwitchBlock stmt) {
return stmt.getFirstChild();
}
};
return Generator.sampledFrom(anyIntentionInSwitchRange, replaceToEnhancedSwitchIntention, new StripTestDataMarkup(file));
};
Supplier<MadTestingAction> fileChooser = MadTestingUtil.actionsOnFileContents(myFixture, PathManager.getHomePath(), f -> {
try {
return f.getName().endsWith(".java") && FileUtil.loadFile(f).contains(" switch");
}
catch (IOException e) {
return false;
}
}, fileActions);
PropertyChecker.checkScenarios(fileChooser);
}
private static class InvokeIntentionAroundSwitch extends InvokeIntention {
InvokeIntentionAroundSwitch(PsiFile file, final IntentionPolicy policy) {
super(file, policy);
}
@Override
protected int generateDocOffset(@NotNull Environment env, @Nullable String logMessage) {
Collection<PsiSwitchBlock> children = PsiTreeUtil.findChildrenOfType(getFile(), PsiSwitchBlock.class);
if (children.isEmpty()) {
return super.generateDocOffset(env, logMessage);
}
List<Generator<Integer>> generators =
ContainerUtil.map(children, stmt ->
Generator.integers(getRangeElement(stmt).getTextRange().getStartOffset(),
getRangeElement(stmt).getTextRange().getEndOffset()).noShrink());
return env.generateValue(Generator.anyOf(generators), logMessage);
}
protected PsiElement getRangeElement(PsiSwitchBlock stmt) {
return stmt;
}
}
}