From 64f26ad09283f9a282ddc427100b1ac4e74767c5 Mon Sep 17 00:00:00 2001 From: peter Date: Tue, 18 Jul 2017 10:31:33 +0200 Subject: [PATCH] mad testing: extract java-specific code, check stubs more frequently --- .../ApplyRandomIntentionsTest.java | 4 +- .../CompletionConsistencyTest.java | 2 +- .../java/propertyBased/CompletionPolicy.java | 65 +++++++++++++ .../java/propertyBased/DeleteRange.java | 2 +- .../java/propertyBased/IntentionPolicy.java | 32 +++++++ .../java/propertyBased/InvokeCompletion.java | 95 +++++-------------- .../java/propertyBased/InvokeIntention.java | 61 +++--------- .../JavaCodeInsightSanityTest.java | 4 +- .../propertyBased/JavaCompletionPolicy.java | 58 +++++++++++ .../propertyBased/JavaIntentionPolicy.java | 46 +++++++++ .../propertyBased/RehighlightAllEditors.java | 2 + 11 files changed, 245 insertions(+), 126 deletions(-) create mode 100644 java/java-tests/testSrc/com/intellij/java/propertyBased/CompletionPolicy.java create mode 100644 java/java-tests/testSrc/com/intellij/java/propertyBased/IntentionPolicy.java create mode 100644 java/java-tests/testSrc/com/intellij/java/propertyBased/JavaCompletionPolicy.java create mode 100644 java/java-tests/testSrc/com/intellij/java/propertyBased/JavaIntentionPolicy.java diff --git a/java/java-tests/testSrc/com/intellij/java/propertyBased/ApplyRandomIntentionsTest.java b/java/java-tests/testSrc/com/intellij/java/propertyBased/ApplyRandomIntentionsTest.java index 687fcb92effb..b9dfc27a0378 100644 --- a/java/java-tests/testSrc/com/intellij/java/propertyBased/ApplyRandomIntentionsTest.java +++ b/java/java-tests/testSrc/com/intellij/java/propertyBased/ApplyRandomIntentionsTest.java @@ -47,7 +47,7 @@ public class ApplyRandomIntentionsTest extends AbstractApplyAndRevertTestCase { AtomicLong rebuildStamp = new AtomicLong(); CheckerSettings settings = CheckerSettings.DEFAULT_SETTINGS.withIterationCount(30); - Generator genIntention = psiJavaFiles().flatMap(InvokeIntention::randomIntentions); + Generator 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 allActions = Generator.frequency(2, InvokeIntention.randomIntentions(file), + Generator 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()); diff --git a/java/java-tests/testSrc/com/intellij/java/propertyBased/CompletionConsistencyTest.java b/java/java-tests/testSrc/com/intellij/java/propertyBased/CompletionConsistencyTest.java index 4be791c4e17a..fb6a36a84173 100644 --- a/java/java-tests/testSrc/com/intellij/java/propertyBased/CompletionConsistencyTest.java +++ b/java/java-tests/testSrc/com/intellij/java/propertyBased/CompletionConsistencyTest.java @@ -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; }); diff --git a/java/java-tests/testSrc/com/intellij/java/propertyBased/CompletionPolicy.java b/java/java-tests/testSrc/com/intellij/java/propertyBased/CompletionPolicy.java new file mode 100644 index 000000000000..ac3b901bee15 --- /dev/null +++ b/java/java-tests/testSrc/com/intellij/java/propertyBased/CompletionPolicy.java @@ -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; + } +} diff --git a/java/java-tests/testSrc/com/intellij/java/propertyBased/DeleteRange.java b/java/java-tests/testSrc/com/intellij/java/propertyBased/DeleteRange.java index 828839a83bdf..155b7a45d436 100644 --- a/java/java-tests/testSrc/com/intellij/java/propertyBased/DeleteRange.java +++ b/java/java-tests/testSrc/com/intellij/java/propertyBased/DeleteRange.java @@ -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; diff --git a/java/java-tests/testSrc/com/intellij/java/propertyBased/IntentionPolicy.java b/java/java-tests/testSrc/com/intellij/java/propertyBased/IntentionPolicy.java new file mode 100644 index 000000000000..a8667867051e --- /dev/null +++ b/java/java-tests/testSrc/com/intellij/java/propertyBased/IntentionPolicy.java @@ -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; + } +} diff --git a/java/java-tests/testSrc/com/intellij/java/propertyBased/InvokeCompletion.java b/java/java-tests/testSrc/com/intellij/java/propertyBased/InvokeCompletion.java index b994802ecdbd..fae29f93af6d 100644 --- a/java/java-tests/testSrc/com/intellij/java/propertyBased/InvokeCompletion.java +++ b/java/java-tests/testSrc/com/intellij/java/propertyBased/InvokeCompletion.java @@ -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 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 completions(PsiFile psiFile) { - Document document = psiFile.getViewProvider().getDocument(); + static Generator 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); }); } } diff --git a/java/java-tests/testSrc/com/intellij/java/propertyBased/InvokeIntention.java b/java/java-tests/testSrc/com/intellij/java/propertyBased/InvokeIntention.java index 5a10301a7a92..f5c9433ba121 100644 --- a/java/java-tests/testSrc/com/intellij/java/propertyBased/InvokeIntention.java +++ b/java/java-tests/testSrc/com/intellij/java/propertyBased/InvokeIntention.java @@ -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 randomIntentions(@NotNull PsiFile psiFile) { + static Generator 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 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 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"); - } - } diff --git a/java/java-tests/testSrc/com/intellij/java/propertyBased/JavaCodeInsightSanityTest.java b/java/java-tests/testSrc/com/intellij/java/propertyBased/JavaCodeInsightSanityTest.java index 14264e8f761c..cc7a053163d7 100644 --- a/java/java-tests/testSrc/com/intellij/java/propertyBased/JavaCodeInsightSanityTest.java +++ b/java/java-tests/testSrc/com/intellij/java/propertyBased/JavaCodeInsightSanityTest.java @@ -45,8 +45,8 @@ public class JavaCodeInsightSanityTest extends LightPlatformCodeInsightFixtureTe public void testRandomActivity() { AbstractApplyAndRevertTestCase.enableAllInspections(getProject(), getTestRootDisposable()); Function> 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); } diff --git a/java/java-tests/testSrc/com/intellij/java/propertyBased/JavaCompletionPolicy.java b/java/java-tests/testSrc/com/intellij/java/propertyBased/JavaCompletionPolicy.java new file mode 100644 index 000000000000..daefa0af22b4 --- /dev/null +++ b/java/java-tests/testSrc/com/intellij/java/propertyBased/JavaCompletionPolicy.java @@ -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; + } + +} diff --git a/java/java-tests/testSrc/com/intellij/java/propertyBased/JavaIntentionPolicy.java b/java/java-tests/testSrc/com/intellij/java/propertyBased/JavaIntentionPolicy.java new file mode 100644 index 000000000000..5af52294427e --- /dev/null +++ b/java/java-tests/testSrc/com/intellij/java/propertyBased/JavaIntentionPolicy.java @@ -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"); + } +} diff --git a/java/java-tests/testSrc/com/intellij/java/propertyBased/RehighlightAllEditors.java b/java/java-tests/testSrc/com/intellij/java/propertyBased/RehighlightAllEditors.java index 2fe64988e026..1d43e0dd5a1e 100644 --- a/java/java-tests/testSrc/com/intellij/java/propertyBased/RehighlightAllEditors.java +++ b/java/java-tests/testSrc/com/intellij/java/propertyBased/RehighlightAllEditors.java @@ -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 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); } }