mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
mad testing: extract java-specific code, check stubs more frequently
This commit is contained in:
+2
-2
@@ -47,7 +47,7 @@ public class ApplyRandomIntentionsTest extends AbstractApplyAndRevertTestCase {
|
||||
AtomicLong rebuildStamp = new AtomicLong();
|
||||
|
||||
CheckerSettings settings = CheckerSettings.DEFAULT_SETTINGS.withIterationCount(30);
|
||||
Generator<InvokeIntention> genIntention = psiJavaFiles().flatMap(InvokeIntention::randomIntentions);
|
||||
Generator<InvokeIntention> genIntention = psiJavaFiles().flatMap(file -> InvokeIntention.randomIntentions(file, new JavaIntentionPolicy()));
|
||||
PropertyChecker.forAll(settings, Generator.listsOf(genIntention.noShrink()), list -> {
|
||||
long startModCount = tracker.getModificationCount();
|
||||
if (rebuildStamp.getAndSet(startModCount) != startModCount) {
|
||||
@@ -74,7 +74,7 @@ public class ApplyRandomIntentionsTest extends AbstractApplyAndRevertTestCase {
|
||||
Generator.constant(new DeleteForeachInitializers(file)),
|
||||
Generator.constant(new DeleteSecondArgument(file)),
|
||||
Generator.constant(new MakeAllMethodsVoid(file)));
|
||||
Generator<MadTestingAction> allActions = Generator.frequency(2, InvokeIntention.randomIntentions(file),
|
||||
Generator<MadTestingAction> allActions = Generator.frequency(2, InvokeIntention.randomIntentions(file, new JavaIntentionPolicy()),
|
||||
1, Generator.constant(new RehighlightAllEditors(myProject)),
|
||||
1, mutation);
|
||||
return Generator.listsOf(IntDistribution.uniform(0, 5), allActions.noShrink());
|
||||
|
||||
+1
-1
@@ -31,7 +31,7 @@ public class CompletionConsistencyTest extends AbstractApplyAndRevertTestCase {
|
||||
CheckerSettings settings = CheckerSettings.DEFAULT_SETTINGS;
|
||||
PropertyChecker.forAll(settings.withIterationCount(20), psiJavaFiles(), file -> {
|
||||
System.out.println("for file: " + file.getVirtualFile().getPresentableUrl());
|
||||
PropertyChecker.forAll(settings.withIterationCount(10), Generator.listsOf(InvokeCompletion.completions(file)), list -> {
|
||||
PropertyChecker.forAll(settings.withIterationCount(10), Generator.listsOf(InvokeCompletion.completions(file, new JavaCompletionPolicy())), list -> {
|
||||
changeAndRevert(myProject, () -> MadTestingAction.runActions(list));
|
||||
return true;
|
||||
});
|
||||
|
||||
@@ -0,0 +1,65 @@
|
||||
/*
|
||||
* 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.editor.Editor;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
/**
|
||||
* @author peter
|
||||
*/
|
||||
public abstract class CompletionPolicy {
|
||||
|
||||
/**
|
||||
* @return the lookup string of an element that should be suggested in the given position
|
||||
*/
|
||||
public String getExpectedVariant(Editor editor, PsiFile file) {
|
||||
PsiElement leaf = file.findElementAt(editor.getCaretModel().getOffset());
|
||||
PsiReference ref = file.findReferenceAt(editor.getCaretModel().getOffset());
|
||||
PsiElement refTarget = ref == null ? null : ref.resolve();
|
||||
if (leaf == null) {
|
||||
return null;
|
||||
}
|
||||
String leafText = leaf.getText();
|
||||
if (leafText.isEmpty() ||
|
||||
!Character.isLetter(leafText.charAt(0)) ||
|
||||
leaf instanceof PsiWhiteSpace ||
|
||||
PsiTreeUtil.getParentOfType(leaf, PsiComment.class, false) != null) {
|
||||
return null;
|
||||
}
|
||||
if (ref != null) {
|
||||
if (refTarget == null || !shouldSuggestReferenceText(ref)) return null;
|
||||
}
|
||||
else {
|
||||
if (!SyntaxTraverser.psiTraverser(file).filter(PsiErrorElement.class).isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
if (!shouldSuggestNonReferenceLeafText(leaf)) return null;
|
||||
}
|
||||
return leafText;
|
||||
|
||||
}
|
||||
|
||||
protected boolean shouldSuggestNonReferenceLeafText(@NotNull PsiElement leaf) {
|
||||
return true;
|
||||
}
|
||||
|
||||
protected boolean shouldSuggestReferenceText(@NotNull PsiReference ref) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -29,7 +29,7 @@ import java.util.Objects;
|
||||
class DeleteRange extends ActionOnRange {
|
||||
private final PsiFile myFile;
|
||||
|
||||
private DeleteRange(PsiFile file, int startOffset, int endOffset) {
|
||||
DeleteRange(PsiFile file, int startOffset, int endOffset) {
|
||||
super(file.getViewProvider().getDocument(), startOffset, endOffset);
|
||||
assert myMarker.getDocument().getTextLength() == file.getTextLength() : file + " " + myMarker.getDocument();
|
||||
myFile = file;
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
/*
|
||||
* 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.intention.IntentionAction;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
/**
|
||||
* @author peter
|
||||
*/
|
||||
public class IntentionPolicy {
|
||||
public boolean mayInvokeIntention(@NotNull IntentionAction action) {
|
||||
return action.startInWriteAction() && !shouldSkipIntention(action.getText());
|
||||
}
|
||||
|
||||
protected boolean shouldSkipIntention(@NotNull String actionText) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -23,7 +23,6 @@ import com.intellij.codeInsight.lookup.LookupEx;
|
||||
import com.intellij.codeInsight.lookup.LookupManager;
|
||||
import com.intellij.codeInsight.lookup.impl.LookupImpl;
|
||||
import com.intellij.openapi.Disposable;
|
||||
import com.intellij.openapi.editor.Document;
|
||||
import com.intellij.openapi.editor.Editor;
|
||||
import com.intellij.openapi.fileEditor.FileEditorManager;
|
||||
import com.intellij.openapi.fileEditor.OpenFileDescriptor;
|
||||
@@ -31,15 +30,13 @@ import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.Disposer;
|
||||
import com.intellij.openapi.util.registry.Registry;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
import com.intellij.psi.util.PsiUtil;
|
||||
import com.intellij.psi.PsiDocumentManager;
|
||||
import com.intellij.psi.PsiFile;
|
||||
import com.intellij.testFramework.PsiTestUtil;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import com.intellij.util.ui.UIUtil;
|
||||
import junit.framework.TestCase;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import slowCheck.Generator;
|
||||
import slowCheck.IntDistribution;
|
||||
|
||||
@@ -52,25 +49,26 @@ import java.util.Set;
|
||||
* @author peter
|
||||
*/
|
||||
class InvokeCompletion extends ActionOnRange {
|
||||
final int itemIndexRaw;
|
||||
LookupElement selectedItem;
|
||||
final char completionChar;
|
||||
private final int myItemIndexRaw;
|
||||
private LookupElement mySelectedItem;
|
||||
private final char myCompletionChar;
|
||||
private final PsiFile myFile;
|
||||
private final CompletionPolicy myPolicy;
|
||||
private final String myConstructorArgs;
|
||||
|
||||
InvokeCompletion(Document document, int offset, int itemIndexRaw, char completionChar, PsiFile file) {
|
||||
super(document, offset, offset);
|
||||
this.itemIndexRaw = itemIndexRaw;
|
||||
this.completionChar = completionChar;
|
||||
InvokeCompletion(PsiFile file, int offset, int itemIndexRaw, char completionChar, CompletionPolicy policy) {
|
||||
super(file.getViewProvider().getDocument(), offset, offset);
|
||||
this.myItemIndexRaw = itemIndexRaw;
|
||||
this.myCompletionChar = completionChar;
|
||||
myFile = file;
|
||||
myPolicy = policy;
|
||||
myConstructorArgs = "_, " + offset + ", " + itemIndexRaw + ", '" + StringUtil.escapeStringCharacters(String.valueOf(completionChar)) + "', _";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "CompletionInvocation{" +
|
||||
"offset=" + getStartOffset() +
|
||||
", selectedItem=" + selectedItem + "(" + itemIndexRaw + ")" +
|
||||
", completionChar=" + StringUtil.escapeStringCharacters(String.valueOf(completionChar)) +
|
||||
'}';
|
||||
return "InvokeCompletion(" + myConstructorArgs + ")" +
|
||||
"{" + myFile.getVirtualFile().getPath() + ", offset=" + getStartOffset() + ", selected=" + mySelectedItem + '}';
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -89,6 +87,7 @@ class InvokeCompletion extends ActionOnRange {
|
||||
Disposable raiseCompletionLimit = Disposer.newDisposable();
|
||||
Registry.get("ide.completion.variant.limit").setValue(100_000, raiseCompletionLimit);
|
||||
try {
|
||||
PsiTestUtil.checkPsiStructureWithCommit(myFile, PsiTestUtil::checkStubsMatchText);
|
||||
performCompletion(editor);
|
||||
PsiTestUtil.checkPsiStructureWithCommit(myFile, PsiTestUtil::checkStubsMatchText);
|
||||
}
|
||||
@@ -101,7 +100,7 @@ class InvokeCompletion extends ActionOnRange {
|
||||
}
|
||||
|
||||
private void performCompletion(Editor editor) {
|
||||
String expectedVariant = getExpectedVariant(editor, myFile);
|
||||
String expectedVariant = myPolicy.getExpectedVariant(editor, myFile);
|
||||
|
||||
new CodeCompletionHandlerBase(CompletionType.BASIC).invokeCompletion(myFile.getProject(), editor);
|
||||
|
||||
@@ -119,9 +118,9 @@ class InvokeCompletion extends ActionOnRange {
|
||||
|
||||
checkNoDuplicates(items);
|
||||
|
||||
LookupElement item = items.get(itemIndexRaw % items.size());
|
||||
selectedItem = item;
|
||||
((LookupImpl)lookup).finishLookup(completionChar, item);
|
||||
LookupElement item = items.get(myItemIndexRaw % items.size());
|
||||
mySelectedItem = item;
|
||||
((LookupImpl)lookup).finishLookup(myCompletionChar, item);
|
||||
}
|
||||
|
||||
private static void checkNoDuplicates(List<LookupElement> items) {
|
||||
@@ -138,61 +137,13 @@ class InvokeCompletion extends ActionOnRange {
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static String getExpectedVariant(Editor editor, PsiFile file) {
|
||||
PsiElement leaf = file.findElementAt(editor.getCaretModel().getOffset());
|
||||
PsiReference ref = file.findReferenceAt(editor.getCaretModel().getOffset());
|
||||
PsiElement refTarget = ref == null ? null : ref.resolve();
|
||||
if (leaf == null) {
|
||||
return null;
|
||||
}
|
||||
String leafText = leaf.getText();
|
||||
if (leafText.isEmpty() ||
|
||||
!Character.isLetter(leafText.charAt(0)) ||
|
||||
leaf instanceof PsiWhiteSpace ||
|
||||
PsiTreeUtil.getParentOfType(leaf, PsiComment.class, false) != null) {
|
||||
return null;
|
||||
}
|
||||
if (ref != null) {
|
||||
if (refTarget == null) return null;
|
||||
if (ref instanceof PsiJavaCodeReferenceElement && !shouldSuggestJavaTarget((PsiJavaCodeReferenceElement)ref)) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (!SyntaxTraverser.psiTraverser(file).filter(PsiErrorElement.class).isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
if (leaf instanceof PsiIdentifier) return null; // it's not a ref, just some name
|
||||
if (leaf instanceof PsiKeyword) {
|
||||
if (leaf.getParent() instanceof PsiClassObjectAccessExpression &&
|
||||
PsiUtil.resolveClassInType(((PsiClassObjectAccessExpression)leaf.getParent()).getType()) == null) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
if (leaf.textMatches(PsiKeyword.TRUE) || leaf.textMatches(PsiKeyword.FALSE)) {
|
||||
return null; // boolean literal presence depends on expected types, which can be missing in red files
|
||||
}
|
||||
}
|
||||
return leafText;
|
||||
}
|
||||
|
||||
private static boolean shouldSuggestJavaTarget(PsiJavaCodeReferenceElement ref) {
|
||||
if (PsiTreeUtil.getParentOfType(ref, PsiPackageStatement.class) == null) return false;
|
||||
|
||||
PsiElement target = ref.resolve();
|
||||
if (!ref.isQualified() && target instanceof PsiPackage) return false;
|
||||
return target != null;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
static Generator<InvokeCompletion> completions(PsiFile psiFile) {
|
||||
Document document = psiFile.getViewProvider().getDocument();
|
||||
static Generator<InvokeCompletion> completions(PsiFile psiFile, CompletionPolicy policy) {
|
||||
return Generator.from(data -> {
|
||||
int offset = data.drawInt(IntDistribution.uniform(0, document.getTextLength()));
|
||||
int offset = data.drawInt(IntDistribution.uniform(0, psiFile.getViewProvider().getDocument().getTextLength()));
|
||||
int itemIndex = data.drawInt(IntDistribution.uniform(0, 100));
|
||||
char c = Generator.sampledFrom('\n', '\t', '\r', ' ', '.', '(').generateUnstructured(data);
|
||||
return new InvokeCompletion(document, offset, itemIndex, c, psiFile);
|
||||
return new InvokeCompletion(psiFile, offset, itemIndex, c, policy);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,7 +18,6 @@ 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.application.ReadAction;
|
||||
import com.intellij.openapi.editor.Document;
|
||||
import com.intellij.openapi.editor.Editor;
|
||||
import com.intellij.openapi.fileEditor.FileEditorManager;
|
||||
@@ -26,7 +25,6 @@ import com.intellij.openapi.fileEditor.OpenFileDescriptor;
|
||||
import com.intellij.psi.PsiDocumentManager;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiFile;
|
||||
import com.intellij.psi.PsiInvalidElementAccessException;
|
||||
import com.intellij.testFramework.PsiTestUtil;
|
||||
import com.intellij.testFramework.fixtures.impl.CodeInsightTestFixtureImpl;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
@@ -39,42 +37,32 @@ import java.util.List;
|
||||
class InvokeIntention extends ActionOnRange {
|
||||
private final PsiFile myFile;
|
||||
private final int myIntentionIndex;
|
||||
private IntentionAction myIntentionAction;
|
||||
private final IntentionPolicy myPolicy;
|
||||
private final String myConstructorArgs;
|
||||
private String myInvocationLog = "not invoked";
|
||||
|
||||
private InvokeIntention(PsiFile file, int offset, int intentionIndex) {
|
||||
InvokeIntention(PsiFile file, int offset, int intentionIndex, IntentionPolicy policy) {
|
||||
super(file.getViewProvider().getDocument(), offset, offset);
|
||||
myFile = file;
|
||||
myIntentionIndex = intentionIndex;
|
||||
myPolicy = policy;
|
||||
myConstructorArgs = "_ , " + offset + ", " + intentionIndex + ", _";
|
||||
}
|
||||
|
||||
@NotNull
|
||||
static Generator<InvokeIntention> randomIntentions(@NotNull PsiFile psiFile) {
|
||||
static Generator<InvokeIntention> randomIntentions(@NotNull PsiFile psiFile, @NotNull IntentionPolicy policy) {
|
||||
return Generator.zipWith(Generator.integers(0, psiFile.getTextLength()), Generator.integers(0, 100),
|
||||
(offset, index) -> new InvokeIntention(psiFile, offset, index)).noShrink();
|
||||
(offset, index) -> new InvokeIntention(psiFile, offset, index, policy)).noShrink();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "InvokeIntention[" + myFile.getVirtualFile().getPath() + ", offset " + getStartOffset() +
|
||||
", invoke '" + ReadAction.compute(() -> getIntentionText()) + "']";
|
||||
}
|
||||
|
||||
private String getIntentionText() {
|
||||
if (myIntentionAction == null) {
|
||||
return "index " + String.valueOf(myIntentionIndex);
|
||||
}
|
||||
|
||||
String name = null;
|
||||
try {
|
||||
name = myIntentionAction.getText();
|
||||
}
|
||||
catch (PsiInvalidElementAccessException ignore) {
|
||||
}
|
||||
return name == null ? myIntentionAction.toString() : name;
|
||||
return "InvokeIntention(" + myConstructorArgs + "){" + myFile.getVirtualFile().getPath() + "," + myInvocationLog + "}";
|
||||
}
|
||||
|
||||
public void performAction() {
|
||||
int offset = getStartOffset();
|
||||
myInvocationLog = "offset " + offset;
|
||||
if (offset < 0) return;
|
||||
|
||||
Editor editor = FileEditorManager.getInstance(myFile.getProject()).openTextEditor(new OpenFileDescriptor(myFile.getProject(), myFile.getVirtualFile(), offset), true);
|
||||
@@ -82,8 +70,9 @@ class InvokeIntention extends ActionOnRange {
|
||||
List<HighlightInfo> infos = RehighlightAllEditors.highlightEditor(editor, myFile.getProject());
|
||||
boolean hasErrors = infos.stream().anyMatch(i -> i.getSeverity() == HighlightSeverity.ERROR);
|
||||
|
||||
IntentionAction intention = myIntentionAction = getRandomIntention(editor);
|
||||
IntentionAction intention = getRandomIntention(editor);
|
||||
if (intention == null) return;
|
||||
myInvocationLog += ", invoke '" + intention.getText() + "'";
|
||||
|
||||
Document changedDocument = getDocumentToBeChanged(intention);
|
||||
String textBefore = changedDocument == null ? null : changedDocument.getText();
|
||||
@@ -116,31 +105,7 @@ class InvokeIntention extends ActionOnRange {
|
||||
@Nullable
|
||||
private IntentionAction getRandomIntention(Editor editor) {
|
||||
List<IntentionAction> actions = ContainerUtil.filter(CodeInsightTestFixtureImpl.getAvailableIntentions(editor, myFile),
|
||||
action -> action.startInWriteAction() &&
|
||||
!shouldSkipIntention(action.getText()));
|
||||
myPolicy::mayInvokeIntention);
|
||||
return actions.isEmpty() ? null : actions.get(myIntentionIndex % actions.size());
|
||||
}
|
||||
|
||||
private static boolean shouldSkipIntention(String actionText) {
|
||||
return actionText.startsWith("Flip") ||
|
||||
actionText.startsWith("Attach annotations") || // changes project model
|
||||
actionText.startsWith("Convert to string literal") || // can produce uncompilable code by design
|
||||
actionText.startsWith("Optimize imports") || // https://youtrack.jetbrains.com/issue/IDEA-173801
|
||||
actionText.startsWith("Make method default") ||
|
||||
actionText.startsWith("Convert to project line separators") || // changes VFS, not document
|
||||
actionText.contains("to custom tags") || // changes only inspection settings
|
||||
actionText.contains("to 'Ignore if annotated by' list") || // changes only inspection settings
|
||||
actionText.startsWith("Allow these suppressions") || // changes only inspection settings
|
||||
actionText.startsWith("Typo: Change to...") || // doesn't change file text (starts live template)
|
||||
actionText.startsWith("Change class type parameter") || // doesn't change file text (starts live template)
|
||||
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");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+2
-2
@@ -45,8 +45,8 @@ public class JavaCodeInsightSanityTest extends LightPlatformCodeInsightFixtureTe
|
||||
public void testRandomActivity() {
|
||||
AbstractApplyAndRevertTestCase.enableAllInspections(getProject(), getTestRootDisposable());
|
||||
Function<PsiFile, Generator<? extends MadTestingAction>> fileActions = file ->
|
||||
Generator.anyOf(InvokeIntention.randomIntentions(file),
|
||||
InvokeCompletion.completions(file),
|
||||
Generator.anyOf(InvokeIntention.randomIntentions(file, new JavaIntentionPolicy()),
|
||||
InvokeCompletion.completions(file, new JavaCompletionPolicy()),
|
||||
DeleteRange.psiRangeDeletions(file));
|
||||
PropertyChecker.forAll(actionsOnJavaFiles(fileActions), FileWithActions::runActions);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,58 @@
|
||||
/*
|
||||
* 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 com.intellij.psi.util.PsiUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
/**
|
||||
* @author peter
|
||||
*/
|
||||
class JavaCompletionPolicy extends CompletionPolicy {
|
||||
@Override
|
||||
protected boolean shouldSuggestReferenceText(@NotNull PsiReference ref) {
|
||||
if (ref instanceof PsiJavaCodeReferenceElement && !shouldSuggestJavaTarget((PsiJavaCodeReferenceElement)ref)) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private static boolean shouldSuggestJavaTarget(PsiJavaCodeReferenceElement ref) {
|
||||
if (PsiTreeUtil.getParentOfType(ref, PsiPackageStatement.class) == null) return false;
|
||||
|
||||
PsiElement target = ref.resolve();
|
||||
if (!ref.isQualified() && target instanceof PsiPackage) return false;
|
||||
return target != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean shouldSuggestNonReferenceLeafText(@NotNull PsiElement leaf) {
|
||||
if (leaf instanceof PsiIdentifier) return false; // name of some element
|
||||
if (leaf instanceof PsiKeyword) {
|
||||
if (leaf.getParent() instanceof PsiClassObjectAccessExpression &&
|
||||
PsiUtil.resolveClassInType(((PsiClassObjectAccessExpression)leaf.getParent()).getType()) == null) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (leaf.textMatches(PsiKeyword.TRUE) || leaf.textMatches(PsiKeyword.FALSE)) {
|
||||
return false; // boolean literal presence depends on expected types, which can be missing in red files
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
* 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 org.jetbrains.annotations.NotNull;
|
||||
|
||||
/**
|
||||
* @author peter
|
||||
*/
|
||||
public class JavaIntentionPolicy extends IntentionPolicy {
|
||||
@Override
|
||||
protected boolean shouldSkipIntention(@NotNull String actionText) {
|
||||
return actionText.startsWith("Flip") ||
|
||||
actionText.startsWith("Attach annotations") || // changes project model
|
||||
actionText.startsWith("Convert to string literal") || // can produce uncompilable code by design
|
||||
actionText.startsWith("Optimize imports") || // https://youtrack.jetbrains.com/issue/IDEA-173801
|
||||
actionText.startsWith("Make method default") ||
|
||||
actionText.startsWith("Convert to project line separators") || // changes VFS, not document
|
||||
actionText.contains("to custom tags") || // changes only inspection settings
|
||||
actionText.contains("to 'Ignore if annotated by' list") || // changes only inspection settings
|
||||
actionText.startsWith("Allow these suppressions") || // changes only inspection settings
|
||||
actionText.startsWith("Typo: Change to...") || // doesn't change file text (starts live template)
|
||||
actionText.startsWith("Change class type parameter") || // doesn't change file text (starts live template)
|
||||
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");
|
||||
}
|
||||
}
|
||||
@@ -23,6 +23,7 @@ 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.PsiTestUtil;
|
||||
import com.intellij.testFramework.fixtures.impl.CodeInsightTestFixtureImpl;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
@@ -56,6 +57,7 @@ class RehighlightAllEditors implements MadTestingAction {
|
||||
static List<HighlightInfo> highlightEditor(Editor editor, Project project) {
|
||||
PsiDocumentManager.getInstance(project).commitAllDocuments();
|
||||
PsiFile file = PsiDocumentManager.getInstance(project).getPsiFile(editor.getDocument());
|
||||
PsiTestUtil.checkStubsMatchText(file);
|
||||
return CodeInsightTestFixtureImpl.instantiateAndRun(file, editor, new int[0], false);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user