'Suppress warnings' as quick fix options

If no quick fix is available a special intention is shown
This commit is contained in:
Andrey Breslav
2013-09-22 19:24:46 +04:00
parent b379ab3ebd
commit a13b66c58e
79 changed files with 879 additions and 9 deletions
@@ -22,13 +22,10 @@ import com.intellij.psi.util.PsiTreeUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.JetNodeTypes;
import org.jetbrains.jet.lexer.JetTokens;
import java.util.List;
import static org.jetbrains.jet.lexer.JetTokens.EQ;
import static org.jetbrains.jet.lexer.JetTokens.VAL_KEYWORD;
import static org.jetbrains.jet.lexer.JetTokens.VAR_KEYWORD;
import static org.jetbrains.jet.lexer.JetTokens.*;
public class JetMultiDeclaration extends JetDeclarationImpl {
public JetMultiDeclaration(@NotNull ASTNode node) {
@@ -58,4 +55,9 @@ public class JetMultiDeclaration extends JetDeclarationImpl {
}
return PsiTreeUtil.getNextSiblingOfType(eqNode.getPsi(), JetExpression.class);
}
@Nullable
public ASTNode getValOrVarNode() {
return getNode().findChildByType(TokenSet.create(VAL_KEYWORD, VAR_KEYWORD));
}
}
@@ -197,11 +197,22 @@ public class JetPsiFactory {
}
public static JetModifierList createModifierList(Project project, JetKeywordToken modifier) {
String text = modifier.getValue() + " val x";
JetProperty property = createProperty(project, text);
return createModifierList(project, modifier.getValue());
}
public static JetModifierList createModifierList(Project project, String text) {
JetProperty property = createProperty(project, text + " val x");
return property.getModifierList();
}
@NotNull
public static JetAnnotation createAnnotation(Project project, String text) {
JetProperty property = createProperty(project, text + " val x");
JetModifierList modifierList = property.getModifierList();
assert modifierList != null;
return modifierList.getAnnotations().get(0);
}
public static JetModifierList createConstructorModifierList(Project project, JetKeywordToken modifier) {
JetClass aClass = createClass(project, "class C " + modifier.getValue() + " (){}");
return aClass.getPrimaryConstructorModifierList();
@@ -1003,4 +1003,22 @@ public class JetPsiUtil {
return new StringBuilder(inFileParent.getText()).insert(inFileParentOffset, "<caret>").toString();
}
@Nullable
public static JetModifierList replaceModifierList(@NotNull JetModifierListOwner owner, @Nullable JetModifierList modifierList) {
JetModifierList oldModifierList = owner.getModifierList();
if (modifierList == null) {
if (oldModifierList != null) oldModifierList.delete();
return null;
}
else {
if (oldModifierList == null) {
PsiElement firstChild = owner.getFirstChild();
return (JetModifierList) owner.addBefore(modifierList, firstChild);
}
else {
return (JetModifierList) oldModifierList.replace(modifierList);
}
}
}
}
@@ -278,4 +278,7 @@ find.what.derived.classes.checkbox=&Derived classes
convert.to.extension=Convert to extension
replace.by.reconstructed.type.family.name=Replace by Reconstructed Type
replace.by.reconstructed.type=Replace by ''{0}''
replace.by.reconstructed.type=Replace by ''{0}''
suppress.warnings.family=Suppress Warnings
suppress.warning.for=Suppress ''{0}'' for {1} {2}
@@ -17,6 +17,7 @@
package org.jetbrains.jet.plugin.highlighter;
import com.google.common.collect.Sets;
import com.intellij.codeInsight.intention.EmptyIntentionAction;
import com.intellij.codeInsight.intention.IntentionAction;
import com.intellij.codeInspection.ProblemHighlightType;
import com.intellij.lang.annotation.Annotation;
@@ -225,6 +226,17 @@ public class JetPsiChecker implements Annotator {
annotation.registerFix(action);
}
// Making warnings suppressable
if (diagnostic.getSeverity() == Severity.WARNING) {
annotation.setProblemGroup(new KotlinSuppressableWarningProblemGroup(diagnostic.getFactory()));
List<Annotation.QuickFixInfo> fixes = annotation.getQuickFixes();
if (fixes == null || fixes.isEmpty()) {
// if there are no quick fixes we need to register an EmptyIntentionAction to enable 'suppress' actions
annotation.registerFix(new EmptyIntentionAction(diagnostic.getFactory().getName()));
}
}
return annotation;
}
@@ -0,0 +1,101 @@
/*
* Copyright 2010-2013 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 org.jetbrains.jet.plugin.highlighter
import com.intellij.codeInspection.SuppressableProblemGroup
import com.intellij.psi.PsiElement
import com.intellij.codeInspection.SuppressIntentionAction
import org.jetbrains.jet.lang.diagnostics.Severity
import java.util.Collections
import org.jetbrains.jet.plugin.quickfix.KotlinSuppressIntentionAction
import org.jetbrains.jet.lang.psi.*
import org.jetbrains.jet.plugin.quickfix.DeclarationKind
import org.jetbrains.jet.lang.diagnostics.DiagnosticFactory
import com.intellij.psi.util.PsiTreeUtil
class KotlinSuppressableWarningProblemGroup(
private val diagnosticFactory: DiagnosticFactory
) : SuppressableProblemGroup {
{
assert (diagnosticFactory.getSeverity() == Severity.WARNING)
}
override fun getProblemName() = diagnosticFactory.getName()
override fun getSuppressActions(element: PsiElement?): Array<SuppressIntentionAction> {
if (element == null)
return SuppressIntentionAction.EMPTY_ARRAY
val actions = createSuppressWarningActions(element, diagnosticFactory)
return actions.toArray(Array<SuppressIntentionAction?>(actions.size) {null}) as Array<SuppressIntentionAction>
}
}
fun createSuppressWarningActions(element: PsiElement, diagnosticFactory: DiagnosticFactory): List<SuppressIntentionAction> {
if (diagnosticFactory.getSeverity() != Severity.WARNING)
return Collections.emptyList()
val actions = arrayListOf<SuppressIntentionAction>()
var current: PsiElement? = element
while (current != null) {
if (current is JetDeclaration) {
val declaration = current as JetDeclaration
val kind = DeclarationKindDetector.detect(declaration)
if (kind != null) {
actions.add(KotlinSuppressIntentionAction(declaration, diagnosticFactory, kind))
}
}
current = current?.getParent()
}
return actions
}
private object DeclarationKindDetector : JetVisitor<DeclarationKind?, Unit?>() {
fun detect(declaration: JetDeclaration) = declaration.accept(this, null)
override fun visitDeclaration(d: JetDeclaration, _: Unit?) = null
override fun visitClass(d: JetClass, _: Unit?) = detect(d, if (d.isTrait()) "trait" else "class")
override fun visitClassObject(d: JetClassObject, _: Unit?) = detect(d, "class object",
name = "of " + PsiTreeUtil.getParentOfType(d, javaClass<JetClass>())?.getName())
override fun visitNamedFunction(d: JetNamedFunction, _: Unit?) = detect(d, "fun")
override fun visitProperty(d: JetProperty, _: Unit?) = detect(d, d.getValOrVarNode().getText()!!)
override fun visitMultiDeclaration(d: JetMultiDeclaration, _: Unit?) = detect(d, d.getValOrVarNode()?.getText() ?: "val",
name = d.getEntries().map { it.getName() }.makeString(", ", "(", ")"))
override fun visitTypeParameter(d: JetTypeParameter, _: Unit?) = detect(d, "type parameter", newLineNeeded = false)
override fun visitEnumEntry(d: JetEnumEntry, _: Unit?) = detect(d, "enum entry")
override fun visitParameter(d: JetParameter, _: Unit?) = detect(d, "parameter", newLineNeeded = false)
override fun visitObjectDeclaration(d: JetObjectDeclaration, _: Unit?): DeclarationKind? {
if (d.getParent() is JetClassObject) return null
return detect(d, "object")
}
private fun detect(declaration: JetDeclaration, kind: String, name: String = declaration.getName() ?: "<null>", newLineNeeded: Boolean = true)
= DeclarationKind(kind, name, newLineNeeded)
}
@@ -0,0 +1,104 @@
/*
* Copyright 2010-2013 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 org.jetbrains.jet.plugin.quickfix
import com.intellij.codeInsight.intention.IntentionAction
import com.intellij.openapi.editor.Editor
import com.intellij.openapi.project.Project
import com.intellij.psi.PsiElement
import org.jetbrains.jet.lang.diagnostics.DiagnosticFactory
import org.jetbrains.jet.lang.diagnostics.Diagnostic
import org.jetbrains.jet.lang.diagnostics.Severity
import org.jetbrains.jet.lang.psi.*
import org.jetbrains.jet.plugin.JetBundle
import java.util.Collections
import org.jetbrains.jet.plugin.project.AnalyzerFacadeWithCache
import org.jetbrains.jet.lang.resolve.BindingContext
import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns
import com.intellij.codeInspection.SuppressIntentionAction
public class KotlinSuppressIntentionAction(
private val suppressAt: JetDeclaration,
private val diagnosticFactory: DiagnosticFactory,
private val kind: DeclarationKind
) : SuppressIntentionAction() {
override fun getFamilyName() = JetBundle.message("suppress.warnings.family")
override fun getText() = JetBundle.message("suppress.warning.for", diagnosticFactory.getName(), kind.kind, kind.name)
override fun isAvailable(project: Project, editor: Editor?, element: PsiElement) = element.isValid()
override fun invoke(project: Project, editor: Editor?, element: PsiElement) {
val id = "\"${diagnosticFactory.getName()}\""
val modifierList = suppressAt.getModifierList()
if (modifierList == null) {
// create a modifier list from scratch
val newModifierList = JetPsiFactory.createModifierList(project, "[suppress($id)]")
val replaced = JetPsiUtil.replaceModifierList(suppressAt, newModifierList)
val whiteSpace = project.createWhiteSpace(kind)
suppressAt.addAfter(whiteSpace, replaced)
}
else {
val entry = findSuppressAnnotation(modifierList)
if (entry == null) {
val newAnnotation = JetPsiFactory.createAnnotation(project, "[suppress($id)]")
val addedAnnotation = modifierList.addBefore(newAnnotation, modifierList.getFirstChild())
val whiteSpace = project.createWhiteSpace(kind)
modifierList.addAfter(whiteSpace, addedAnnotation)
}
else {
// add new arguments to an existing entry
val args = entry.getValueArgumentList()
val newArgList = JetPsiFactory.createCallArguments(project, "($id)")
if (args == null) {
// new argument list
entry.addAfter(newArgList, entry.getLastChild())
}
else if (args.getArguments().isEmpty()) {
// replace '()' with a new argument list
args.replace(newArgList)
}
else {
val rightParen = args.getRightParenthesis()
args.addBefore(JetPsiFactory.createComma(project), rightParen)
args.addBefore(JetPsiFactory.createWhiteSpace(project), rightParen)
args.addBefore(newArgList.getArguments()[0], rightParen)
}
}
}
}
private fun findSuppressAnnotation(modifierList: JetModifierList): JetAnnotationEntry? {
val suppressAnnotationClass = KotlinBuiltIns.getInstance().getSuppressAnnotationClass()
val context = AnalyzerFacadeWithCache.getContextForElement(modifierList)
for (entry in modifierList.getAnnotationEntries()) {
val annotationDescriptor = context.get(BindingContext.ANNOTATION, entry)
if (annotationDescriptor != null && suppressAnnotationClass.getTypeConstructor() == annotationDescriptor.getType().getConstructor()) {
return entry
}
}
return null
}
}
public class DeclarationKind(val kind: String, val name: String, val newLineNeeded: Boolean)
private fun Project.createWhiteSpace(kind: DeclarationKind): PsiElement =
if (kind.newLineNeeded)
JetPsiFactory.createNewLine(this)
else
JetPsiFactory.createWhiteSpace(this)
@@ -0,0 +1,3 @@
// "Suppress 'REDUNDANT_NULLABLE' for parameter p" "true"
fun foo([suppress("REDUNDANT_NULLABLE")] vararg p: String?<caret>?) = null
@@ -0,0 +1,5 @@
// "Suppress 'REDUNDANT_NULLABLE' for fun foo" "true"
[suppress("REDUNDANT_NULLABLE")]
public
fun foo(): String?<caret>? = null
@@ -0,0 +1,4 @@
// "Suppress 'REDUNDANT_NULLABLE' for fun foo" "true"
[suppress("REDUNDANT_NULLABLE")]
public fun foo(): String?<caret>? = null
@@ -0,0 +1,4 @@
// "Suppress 'REDUNDANT_NULLABLE' for fun foo" "true"
[suppress("REDUNDANT_NULLABLE")]
fun foo(): String?<caret>? = null
@@ -0,0 +1,4 @@
// "Suppress 'REDUNDANT_NULLABLE' for fun foo" "true"
[suppress("FOO", "REDUNDANT_NULLABLE")]
fun foo(): String?<caret>? = null
@@ -0,0 +1,4 @@
// "Suppress 'REDUNDANT_NULLABLE' for fun foo" "true"
[suppress("REDUNDANT_NULLABLE")]
fun foo(): String?<caret>? = null
@@ -0,0 +1,4 @@
// "Suppress 'REDUNDANT_NULLABLE' for fun foo" "true"
[suppress("REDUNDANT_NULLABLE")]
fun foo(): String?<caret>? = null
@@ -0,0 +1,4 @@
// "Suppress 'REDUNDANT_NULLABLE' for fun foo" "true"
suppress("REDUNDANT_NULLABLE")
fun foo(): String?<caret>? = null
@@ -0,0 +1,3 @@
// "Suppress 'REDUNDANT_NULLABLE' for fun foo" "true"
[suppress("REDUNDANT_NULLABLE")] fun foo(): String?<caret>? = null
@@ -0,0 +1,3 @@
// "Suppress 'REDUNDANT_NULLABLE' for fun foo" "true"
suppress("REDUNDANT_NULLABLE") fun foo(): String?<caret>? = null
@@ -0,0 +1,6 @@
// "Suppress 'REDUNDANT_NULLABLE' for fun foo" "true"
[suppress("REDUNDANT_NULLABLE")]
[ann] fun foo(): String?<caret>? = null
annotation class ann
@@ -0,0 +1,6 @@
// "Suppress 'REDUNDANT_NULLABLE' for fun foo" "true"
[suppress("REDUNDANT_NULLABLE")]
ann fun foo(): String?<caret>? = null
annotation class ann
@@ -0,0 +1,3 @@
// "Suppress 'REDUNDANT_NULLABLE' for parameter p" "true"
fun foo(vararg p: String?<caret>?) = null
@@ -0,0 +1,4 @@
// "Suppress 'REDUNDANT_NULLABLE' for fun foo" "true"
public
fun foo(): String?<caret>? = null
@@ -0,0 +1,3 @@
// "Suppress 'REDUNDANT_NULLABLE' for fun foo" "true"
public fun foo(): String?<caret>? = null
@@ -0,0 +1,3 @@
// "Suppress 'REDUNDANT_NULLABLE' for fun foo" "true"
fun foo(): String?<caret>? = null
@@ -0,0 +1,4 @@
// "Suppress 'REDUNDANT_NULLABLE' for fun foo" "true"
[suppress("FOO")]
fun foo(): String?<caret>? = null
@@ -0,0 +1,4 @@
// "Suppress 'REDUNDANT_NULLABLE' for fun foo" "true"
[suppress()]
fun foo(): String?<caret>? = null
@@ -0,0 +1,4 @@
// "Suppress 'REDUNDANT_NULLABLE' for fun foo" "true"
[suppress]
fun foo(): String?<caret>? = null
@@ -0,0 +1,4 @@
// "Suppress 'REDUNDANT_NULLABLE' for fun foo" "true"
suppress
fun foo(): String?<caret>? = null
@@ -0,0 +1,3 @@
// "Suppress 'REDUNDANT_NULLABLE' for fun foo" "true"
[suppress] fun foo(): String?<caret>? = null
@@ -0,0 +1,3 @@
// "Suppress 'REDUNDANT_NULLABLE' for fun foo" "true"
suppress fun foo(): String?<caret>? = null
@@ -0,0 +1,5 @@
// "Suppress 'REDUNDANT_NULLABLE' for fun foo" "true"
[ann] fun foo(): String?<caret>? = null
annotation class ann
@@ -0,0 +1,5 @@
// "Suppress 'REDUNDANT_NULLABLE' for fun foo" "true"
ann fun foo(): String?<caret>? = null
annotation class ann
@@ -0,0 +1,6 @@
// "Suppress 'REDUNDANT_NULLABLE' for fun local" "true"
fun foo() {
[suppress("REDUNDANT_NULLABLE")]
fun local(): String?<caret>? = null
}
@@ -0,0 +1,6 @@
// "Suppress 'REDUNDANT_NULLABLE' for fun foo" "true"
[suppress("REDUNDANT_NULLABLE")]
fun foo() {
fun local(): String?<caret>? = null
}
@@ -0,0 +1,6 @@
// "Suppress 'REDUNDANT_NULLABLE' for fun foo" "true"
[suppress("REDUNDANT_NULLABLE")]
fun foo() {
val a: String?<caret>? = null
}
@@ -0,0 +1,6 @@
// "Suppress 'REDUNDANT_NULLABLE' for val a" "true"
fun foo() {
[suppress("REDUNDANT_NULLABLE")]
val a: String?<caret>? = null
}
@@ -0,0 +1,8 @@
// "Suppress 'REDUNDANT_NULLABLE' for fun foo" "true"
class C {
class D {
[suppress("REDUNDANT_NULLABLE")]
fun foo(): String?<caret>? = null
}
}
@@ -0,0 +1,8 @@
// "Suppress 'REDUNDANT_NULLABLE' for class D" "true"
class C {
[suppress("REDUNDANT_NULLABLE")]
class D {
fun foo(): String?<caret>? = null
}
}
@@ -0,0 +1,8 @@
// "Suppress 'REDUNDANT_NULLABLE' for class C" "true"
[suppress("REDUNDANT_NULLABLE")]
class C {
class D {
fun foo(): String?<caret>? = null
}
}
@@ -0,0 +1,6 @@
// "Suppress 'REDUNDANT_NULLABLE' for class C" "true"
[suppress("REDUNDANT_NULLABLE")]
class C {
fun foo(): String?<caret>? = null
}
@@ -0,0 +1,6 @@
// "Suppress 'REDUNDANT_NULLABLE' for fun foo" "true"
class C {
[suppress("REDUNDANT_NULLABLE")]
fun foo(): String?<caret>? = null
}
@@ -0,0 +1,5 @@
// "Suppress 'REDUNDANT_NULLABLE' for fun local" "true"
fun foo() {
fun local(): String?<caret>? = null
}
@@ -0,0 +1,5 @@
// "Suppress 'REDUNDANT_NULLABLE' for fun foo" "true"
fun foo() {
fun local(): String?<caret>? = null
}
@@ -0,0 +1,5 @@
// "Suppress 'REDUNDANT_NULLABLE' for fun foo" "true"
fun foo() {
val a: String?<caret>? = null
}
@@ -0,0 +1,5 @@
// "Suppress 'REDUNDANT_NULLABLE' for val a" "true"
fun foo() {
val a: String?<caret>? = null
}
@@ -0,0 +1,7 @@
// "Suppress 'REDUNDANT_NULLABLE' for fun foo" "true"
class C {
class D {
fun foo(): String?<caret>? = null
}
}
@@ -0,0 +1,7 @@
// "Suppress 'REDUNDANT_NULLABLE' for class D" "true"
class C {
class D {
fun foo(): String?<caret>? = null
}
}
@@ -0,0 +1,7 @@
// "Suppress 'REDUNDANT_NULLABLE' for class C" "true"
class C {
class D {
fun foo(): String?<caret>? = null
}
}
@@ -0,0 +1,5 @@
// "Suppress 'REDUNDANT_NULLABLE' for class C" "true"
class C {
fun foo(): String?<caret>? = null
}
@@ -0,0 +1,5 @@
// "Suppress 'REDUNDANT_NULLABLE' for fun foo" "true"
class C {
fun foo(): String?<caret>? = null
}
@@ -0,0 +1,4 @@
// "Suppress 'REDUNDANT_NULLABLE' for fun foo" "false"
[suppress("REDUNDANT_NULLABLE")]
fun foo(): String?<caret>? = null
@@ -0,0 +1,6 @@
// "Suppress 'REDUNDANT_NULLABLE' for class C" "true"
[suppress("REDUNDANT_NULLABLE")]
class C {
var foo: String?<caret>? = null
}
@@ -0,0 +1,8 @@
// "Suppress 'REDUNDANT_NULLABLE' for class object of C" "true"
class C {
[suppress("REDUNDANT_NULLABLE")]
class object {
var foo: String?<caret>? = null
}
}
@@ -0,0 +1,8 @@
// "Suppress 'REDUNDANT_NULLABLE' for enum entry A" "true"
enum class E {
[suppress("REDUNDANT_NULLABLE")]
A {
fun foo(): String?? = null
}
}
@@ -0,0 +1,4 @@
// "Suppress 'REDUNDANT_NULLABLE' for fun foo" "true"
[suppress("REDUNDANT_NULLABLE")]
fun foo(): String?<caret>? = null
@@ -0,0 +1,8 @@
// "Suppress 'REDUNDANT_NULLABLE' for val (a, b)" "true"
fun foo() {
[suppress("REDUNDANT_NULLABLE")]
val (a, b) = Pair<String?<caret>?, String>("", "")
}
data class Pair<A, B>(val a: A, val b: B)
@@ -0,0 +1,8 @@
// "Suppress 'REDUNDANT_NULLABLE' for var (a, b)" "true"
fun foo() {
[suppress("REDUNDANT_NULLABLE")]
var (a, b) = Pair<String?<caret>?, String>("", "")
}
data class Pair<A, B>(val a: A, val b: B)
@@ -0,0 +1,6 @@
// "Suppress 'REDUNDANT_NULLABLE' for object C" "true"
[suppress("REDUNDANT_NULLABLE")]
object C {
var foo: String?<caret>? = null
}
@@ -0,0 +1,3 @@
// "Suppress 'REDUNDANT_NULLABLE' for parameter p" "true"
fun foo([suppress("REDUNDANT_NULLABLE")] p: String?<caret>?) = null
@@ -0,0 +1,6 @@
// "Suppress 'REDUNDANT_NULLABLE' for trait C" "true"
[suppress("REDUNDANT_NULLABLE")]
trait C {
var foo: String?<caret>?
}
@@ -0,0 +1,4 @@
// "Suppress 'REDUNDANT_NULLABLE' for val foo" "true"
[suppress("REDUNDANT_NULLABLE")]
val foo: String?<caret>? = null
@@ -0,0 +1,4 @@
// "Suppress 'REDUNDANT_NULLABLE' for var foo" "true"
[suppress("REDUNDANT_NULLABLE")]
var foo: String?<caret>? = null
@@ -0,0 +1,5 @@
// "Suppress 'REDUNDANT_NULLABLE' for class C" "true"
class C {
var foo: String?<caret>? = null
}
@@ -0,0 +1,7 @@
// "Suppress 'REDUNDANT_NULLABLE' for class object of C" "true"
class C {
class object {
var foo: String?<caret>? = null
}
}
@@ -0,0 +1,7 @@
// "Suppress 'REDUNDANT_NULLABLE' for enum entry A" "true"
enum class E {
A {
fun foo(): String?? = null
}
}
@@ -0,0 +1,3 @@
// "Suppress 'REDUNDANT_NULLABLE' for fun foo" "true"
fun foo(): String?<caret>? = null
@@ -0,0 +1,7 @@
// "Suppress 'REDUNDANT_NULLABLE' for val (a, b)" "true"
fun foo() {
val (a, b) = Pair<String?<caret>?, String>("", "")
}
data class Pair<A, B>(val a: A, val b: B)
@@ -0,0 +1,7 @@
// "Suppress 'REDUNDANT_NULLABLE' for var (a, b)" "true"
fun foo() {
var (a, b) = Pair<String?<caret>?, String>("", "")
}
data class Pair<A, B>(val a: A, val b: B)
@@ -0,0 +1,5 @@
// "Suppress 'REDUNDANT_NULLABLE' for object C" "true"
object C {
var foo: String?<caret>? = null
}
@@ -0,0 +1,3 @@
// "Suppress 'REDUNDANT_NULLABLE' for parameter p" "true"
fun foo(p: String?<caret>?) = null
@@ -0,0 +1,5 @@
// "Suppress 'REDUNDANT_NULLABLE' for trait C" "true"
trait C {
var foo: String?<caret>?
}
@@ -0,0 +1,3 @@
// "Suppress 'REDUNDANT_NULLABLE' for val foo" "true"
val foo: String?<caret>? = null
@@ -0,0 +1,3 @@
// "Suppress 'REDUNDANT_NULLABLE' for var foo" "true"
var foo: String?<caret>? = null
@@ -0,0 +1,6 @@
// "Suppress 'REDUNDANT_NULLABLE' for fun foo" "true"
// ERROR: An integer literal does not conform to the expected type jet.String
// ERROR: An integer literal does not conform to the expected type jet.String
[suppress(1, "REDUNDANT_NULLABLE")]
fun foo(): String?<caret>? = null
@@ -0,0 +1,5 @@
// "Suppress 'REDUNDANT_NULLABLE' for fun foo" "true"
// ERROR: Unresolved reference: ann
[suppress("REDUNDANT_NULLABLE")]
[ann] fun foo(): String?<caret>? = null
@@ -0,0 +1,6 @@
// "Suppress 'REDUNDANT_NULLABLE' for fun foo" "true"
// ERROR: An integer literal does not conform to the expected type jet.String
// ERROR: An integer literal does not conform to the expected type jet.String
[suppress(1)]
fun foo(): String?<caret>? = null
@@ -0,0 +1,4 @@
// "Suppress 'REDUNDANT_NULLABLE' for fun foo" "true"
// ERROR: Unresolved reference: ann
[ann] fun foo(): String?<caret>? = null
@@ -16,13 +16,18 @@
package org.jetbrains.jet.plugin.quickfix;
import com.intellij.codeInsight.daemon.impl.HighlightInfo;
import com.intellij.codeInsight.daemon.quickFix.LightQuickFixTestCase;
import com.intellij.codeInsight.intention.IntentionAction;
import com.intellij.codeInspection.SuppressIntentionAction;
import com.intellij.codeInspection.SuppressableProblemGroup;
import com.intellij.ide.startup.impl.StartupManagerImpl;
import com.intellij.lang.annotation.ProblemGroup;
import com.intellij.openapi.projectRoots.JavaSdk;
import com.intellij.openapi.projectRoots.Sdk;
import com.intellij.openapi.startup.StartupManager;
import com.intellij.openapi.util.Pair;
import com.intellij.psi.PsiElement;
import org.apache.commons.lang.SystemUtils;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.psi.JetFile;
@@ -71,6 +76,28 @@ public abstract class AbstractQuickFixTest extends LightQuickFixTestCase {
QuickFixActionsUtils.checkForUnexpectedErrors((JetFile) getFile());
}
@Override
protected IntentionAction findActionWithText(String text) {
IntentionAction intention = super.findActionWithText(text);
if (intention != null) return intention;
// Support warning suppression
for (HighlightInfo highlight : doHighlighting()) {
ProblemGroup group = highlight.getProblemGroup();
if (group instanceof SuppressableProblemGroup) {
SuppressableProblemGroup problemGroup = (SuppressableProblemGroup) group;
PsiElement at = getFile().findElementAt(highlight.getActualStartOffset());
SuppressIntentionAction[] actions = problemGroup.getSuppressActions(at);
for (SuppressIntentionAction action : actions) {
if (action.getText().equals(text)) {
return action;
}
}
}
}
return null;
}
@Override
protected String getBasePath() {
return getClass().getAnnotation(TestMetadata.class).value();
@@ -31,7 +31,7 @@ import org.jetbrains.jet.plugin.quickfix.AbstractQuickFixMultiFileTest;
/** This class is generated by {@link org.jetbrains.jet.generators.tests.GenerateTests}. DO NOT MODIFY MANUALLY */
@SuppressWarnings("all")
@TestMetadata("idea/testData/quickfix")
@InnerTestClasses({QuickFixMultiFileTestGenerated.AddStarProjections.class, QuickFixMultiFileTestGenerated.AutoImports.class, QuickFixMultiFileTestGenerated.CreateFromUsage.class, QuickFixMultiFileTestGenerated.Modifiers.class, QuickFixMultiFileTestGenerated.Nullables.class, QuickFixMultiFileTestGenerated.Override.class, QuickFixMultiFileTestGenerated.TypeImports.class, QuickFixMultiFileTestGenerated.TypeMismatch.class, QuickFixMultiFileTestGenerated.Variables.class})
@InnerTestClasses({QuickFixMultiFileTestGenerated.AddStarProjections.class, QuickFixMultiFileTestGenerated.AutoImports.class, QuickFixMultiFileTestGenerated.CreateFromUsage.class, QuickFixMultiFileTestGenerated.Modifiers.class, QuickFixMultiFileTestGenerated.Nullables.class, QuickFixMultiFileTestGenerated.Override.class, QuickFixMultiFileTestGenerated.Suppress.class, QuickFixMultiFileTestGenerated.TypeImports.class, QuickFixMultiFileTestGenerated.TypeMismatch.class, QuickFixMultiFileTestGenerated.Variables.class})
public class QuickFixMultiFileTestGenerated extends AbstractQuickFixMultiFileTest {
public void testAllFilesPresentInQuickfix() throws Exception {
JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), "org.jetbrains.jet.generators.tests.GenerateTests", new File("idea/testData/quickfix"), Pattern.compile("^(\\w+)\\.before\\.Main\\.kt$"), true);
@@ -249,6 +249,20 @@ public class QuickFixMultiFileTestGenerated extends AbstractQuickFixMultiFileTes
}
}
@TestMetadata("idea/testData/quickfix/suppress")
@InnerTestClasses({})
public static class Suppress extends AbstractQuickFixMultiFileTest {
public void testAllFilesPresentInSuppress() throws Exception {
JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), "org.jetbrains.jet.generators.tests.GenerateTests", new File("idea/testData/quickfix/suppress"), Pattern.compile("^(\\w+)\\.before\\.Main\\.kt$"), true);
}
public static Test innerSuite() {
TestSuite suite = new TestSuite("Suppress");
suite.addTestSuite(Suppress.class);
return suite;
}
}
@TestMetadata("idea/testData/quickfix/typeImports")
public static class TypeImports extends AbstractQuickFixMultiFileTest {
public void testAllFilesPresentInTypeImports() throws Exception {
@@ -299,6 +313,7 @@ public class QuickFixMultiFileTestGenerated extends AbstractQuickFixMultiFileTes
suite.addTest(Modifiers.innerSuite());
suite.addTest(Nullables.innerSuite());
suite.addTest(Override.innerSuite());
suite.addTest(Suppress.innerSuite());
suite.addTestSuite(TypeImports.class);
suite.addTest(TypeMismatch.innerSuite());
suite.addTest(Variables.innerSuite());
@@ -31,7 +31,7 @@ import org.jetbrains.jet.plugin.quickfix.AbstractQuickFixTest;
/** This class is generated by {@link org.jetbrains.jet.generators.tests.GenerateTests}. DO NOT MODIFY MANUALLY */
@SuppressWarnings("all")
@TestMetadata("idea/testData/quickfix")
@InnerTestClasses({QuickFixTestGenerated.Abstract.class, QuickFixTestGenerated.AddStarProjections.class, QuickFixTestGenerated.AutoImports.class, QuickFixTestGenerated.ChangeSignature.class, QuickFixTestGenerated.CheckArguments.class, QuickFixTestGenerated.CreateFromUsage.class, QuickFixTestGenerated.Expressions.class, QuickFixTestGenerated.Migration.class, QuickFixTestGenerated.Modifiers.class, QuickFixTestGenerated.Nullables.class, QuickFixTestGenerated.Override.class, QuickFixTestGenerated.PlatformClasses.class, QuickFixTestGenerated.Supercalls.class, QuickFixTestGenerated.SupertypeInitialization.class, QuickFixTestGenerated.TypeAddition.class, QuickFixTestGenerated.TypeImports.class, QuickFixTestGenerated.TypeMismatch.class, QuickFixTestGenerated.TypeProjection.class, QuickFixTestGenerated.UselessImports.class, QuickFixTestGenerated.Variables.class, QuickFixTestGenerated.When.class})
@InnerTestClasses({QuickFixTestGenerated.Abstract.class, QuickFixTestGenerated.AddStarProjections.class, QuickFixTestGenerated.AutoImports.class, QuickFixTestGenerated.ChangeSignature.class, QuickFixTestGenerated.CheckArguments.class, QuickFixTestGenerated.CreateFromUsage.class, QuickFixTestGenerated.Expressions.class, QuickFixTestGenerated.Migration.class, QuickFixTestGenerated.Modifiers.class, QuickFixTestGenerated.Nullables.class, QuickFixTestGenerated.Override.class, QuickFixTestGenerated.PlatformClasses.class, QuickFixTestGenerated.Supercalls.class, QuickFixTestGenerated.SupertypeInitialization.class, QuickFixTestGenerated.Suppress.class, QuickFixTestGenerated.TypeAddition.class, QuickFixTestGenerated.TypeImports.class, QuickFixTestGenerated.TypeMismatch.class, QuickFixTestGenerated.TypeProjection.class, QuickFixTestGenerated.UselessImports.class, QuickFixTestGenerated.Variables.class, QuickFixTestGenerated.When.class})
public class QuickFixTestGenerated extends AbstractQuickFixTest {
public void testAllFilesPresentInQuickfix() throws Exception {
JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), "org.jetbrains.jet.generators.tests.GenerateTests", new File("idea/testData/quickfix"), Pattern.compile("^before(\\w+)\\.kt$"), true);
@@ -1371,6 +1371,231 @@ public class QuickFixTestGenerated extends AbstractQuickFixTest {
}
@TestMetadata("idea/testData/quickfix/suppress")
@InnerTestClasses({Suppress.AnnotationPosition.class, Suppress.Availability.class, Suppress.DeclarationKinds.class, Suppress.ErrorRecovery.class})
public static class Suppress extends AbstractQuickFixTest {
public void testAllFilesPresentInSuppress() throws Exception {
JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), "org.jetbrains.jet.generators.tests.GenerateTests", new File("idea/testData/quickfix/suppress"), Pattern.compile("^before(\\w+)\\.kt$"), true);
}
@TestMetadata("idea/testData/quickfix/suppress/annotationPosition")
public static class AnnotationPosition extends AbstractQuickFixTest {
public void testAllFilesPresentInAnnotationPosition() throws Exception {
JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), "org.jetbrains.jet.generators.tests.GenerateTests", new File("idea/testData/quickfix/suppress/annotationPosition"), Pattern.compile("^before(\\w+)\\.kt$"), true);
}
@TestMetadata("beforeParamWithModifier.kt")
public void testParamWithModifier() throws Exception {
doTest("idea/testData/quickfix/suppress/annotationPosition/beforeParamWithModifier.kt");
}
@TestMetadata("beforeTopLevelFunctionModifierOnThePreviousLine.kt")
public void testTopLevelFunctionModifierOnThePreviousLine() throws Exception {
doTest("idea/testData/quickfix/suppress/annotationPosition/beforeTopLevelFunctionModifierOnThePreviousLine.kt");
}
@TestMetadata("beforeTopLevelFunctionModifierOnTheSameLine.kt")
public void testTopLevelFunctionModifierOnTheSameLine() throws Exception {
doTest("idea/testData/quickfix/suppress/annotationPosition/beforeTopLevelFunctionModifierOnTheSameLine.kt");
}
@TestMetadata("beforeTopLevelFunctionNoModifiers.kt")
public void testTopLevelFunctionNoModifiers() throws Exception {
doTest("idea/testData/quickfix/suppress/annotationPosition/beforeTopLevelFunctionNoModifiers.kt");
}
@TestMetadata("beforeTopLevelFunctionSuppressAnotherPreviousLine.kt")
public void testTopLevelFunctionSuppressAnotherPreviousLine() throws Exception {
doTest("idea/testData/quickfix/suppress/annotationPosition/beforeTopLevelFunctionSuppressAnotherPreviousLine.kt");
}
@TestMetadata("beforeTopLevelFunctionSuppressEmptyArgsPreviousLine.kt")
public void testTopLevelFunctionSuppressEmptyArgsPreviousLine() throws Exception {
doTest("idea/testData/quickfix/suppress/annotationPosition/beforeTopLevelFunctionSuppressEmptyArgsPreviousLine.kt");
}
@TestMetadata("beforeTopLevelFunctionSuppressNoArgsPreviousLine.kt")
public void testTopLevelFunctionSuppressNoArgsPreviousLine() throws Exception {
doTest("idea/testData/quickfix/suppress/annotationPosition/beforeTopLevelFunctionSuppressNoArgsPreviousLine.kt");
}
@TestMetadata("beforeTopLevelFunctionSuppressNoArgsPreviousLineBare.kt")
public void testTopLevelFunctionSuppressNoArgsPreviousLineBare() throws Exception {
doTest("idea/testData/quickfix/suppress/annotationPosition/beforeTopLevelFunctionSuppressNoArgsPreviousLineBare.kt");
}
@TestMetadata("beforeTopLevelFunctionSuppressNoArgsTheSameLine.kt")
public void testTopLevelFunctionSuppressNoArgsTheSameLine() throws Exception {
doTest("idea/testData/quickfix/suppress/annotationPosition/beforeTopLevelFunctionSuppressNoArgsTheSameLine.kt");
}
@TestMetadata("beforeTopLevelFunctionSuppressNoArgsTheSameLineBare.kt")
public void testTopLevelFunctionSuppressNoArgsTheSameLineBare() throws Exception {
doTest("idea/testData/quickfix/suppress/annotationPosition/beforeTopLevelFunctionSuppressNoArgsTheSameLineBare.kt");
}
@TestMetadata("beforeTopLevelFunctionUnrelatedAnnotation.kt")
public void testTopLevelFunctionUnrelatedAnnotation() throws Exception {
doTest("idea/testData/quickfix/suppress/annotationPosition/beforeTopLevelFunctionUnrelatedAnnotation.kt");
}
@TestMetadata("beforeTopLevelFunctionUnrelatedAnnotationBare.kt")
public void testTopLevelFunctionUnrelatedAnnotationBare() throws Exception {
doTest("idea/testData/quickfix/suppress/annotationPosition/beforeTopLevelFunctionUnrelatedAnnotationBare.kt");
}
}
@TestMetadata("idea/testData/quickfix/suppress/availability")
public static class Availability extends AbstractQuickFixTest {
public void testAllFilesPresentInAvailability() throws Exception {
JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), "org.jetbrains.jet.generators.tests.GenerateTests", new File("idea/testData/quickfix/suppress/availability"), Pattern.compile("^before(\\w+)\\.kt$"), true);
}
@TestMetadata("beforeLocalFunSuppressForLocal.kt")
public void testLocalFunSuppressForLocal() throws Exception {
doTest("idea/testData/quickfix/suppress/availability/beforeLocalFunSuppressForLocal.kt");
}
@TestMetadata("beforeLocalFunSuppressForOuter.kt")
public void testLocalFunSuppressForOuter() throws Exception {
doTest("idea/testData/quickfix/suppress/availability/beforeLocalFunSuppressForOuter.kt");
}
@TestMetadata("beforeLocalValSuppressForFun.kt")
public void testLocalValSuppressForFun() throws Exception {
doTest("idea/testData/quickfix/suppress/availability/beforeLocalValSuppressForFun.kt");
}
@TestMetadata("beforeLocalValSuppressForVal.kt")
public void testLocalValSuppressForVal() throws Exception {
doTest("idea/testData/quickfix/suppress/availability/beforeLocalValSuppressForVal.kt");
}
@TestMetadata("beforeMemberOfNestedSuppressForMember.kt")
public void testMemberOfNestedSuppressForMember() throws Exception {
doTest("idea/testData/quickfix/suppress/availability/beforeMemberOfNestedSuppressForMember.kt");
}
@TestMetadata("beforeMemberOfNestedSuppressForNested.kt")
public void testMemberOfNestedSuppressForNested() throws Exception {
doTest("idea/testData/quickfix/suppress/availability/beforeMemberOfNestedSuppressForNested.kt");
}
@TestMetadata("beforeMemberOfNestedSuppressForOuter.kt")
public void testMemberOfNestedSuppressForOuter() throws Exception {
doTest("idea/testData/quickfix/suppress/availability/beforeMemberOfNestedSuppressForOuter.kt");
}
@TestMetadata("beforeMemberSuppressForClass.kt")
public void testMemberSuppressForClass() throws Exception {
doTest("idea/testData/quickfix/suppress/availability/beforeMemberSuppressForClass.kt");
}
@TestMetadata("beforeMemberSuppressForMember.kt")
public void testMemberSuppressForMember() throws Exception {
doTest("idea/testData/quickfix/suppress/availability/beforeMemberSuppressForMember.kt");
}
@TestMetadata("beforeTopLevelFunctionAlreadySuppressed.kt")
public void testTopLevelFunctionAlreadySuppressed() throws Exception {
doTest("idea/testData/quickfix/suppress/availability/beforeTopLevelFunctionAlreadySuppressed.kt");
}
}
@TestMetadata("idea/testData/quickfix/suppress/declarationKinds")
public static class DeclarationKinds extends AbstractQuickFixTest {
public void testAllFilesPresentInDeclarationKinds() throws Exception {
JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), "org.jetbrains.jet.generators.tests.GenerateTests", new File("idea/testData/quickfix/suppress/declarationKinds"), Pattern.compile("^before(\\w+)\\.kt$"), true);
}
@TestMetadata("beforeClass.kt")
public void testClass() throws Exception {
doTest("idea/testData/quickfix/suppress/declarationKinds/beforeClass.kt");
}
@TestMetadata("beforeClassObject.kt")
public void testClassObject() throws Exception {
doTest("idea/testData/quickfix/suppress/declarationKinds/beforeClassObject.kt");
}
@TestMetadata("beforeEnumEntry.kt")
public void testEnumEntry() throws Exception {
doTest("idea/testData/quickfix/suppress/declarationKinds/beforeEnumEntry.kt");
}
@TestMetadata("beforeFun.kt")
public void testFun() throws Exception {
doTest("idea/testData/quickfix/suppress/declarationKinds/beforeFun.kt");
}
@TestMetadata("beforeMultiVal.kt")
public void testMultiVal() throws Exception {
doTest("idea/testData/quickfix/suppress/declarationKinds/beforeMultiVal.kt");
}
@TestMetadata("beforeMultiVar.kt")
public void testMultiVar() throws Exception {
doTest("idea/testData/quickfix/suppress/declarationKinds/beforeMultiVar.kt");
}
@TestMetadata("beforeObject.kt")
public void testObject() throws Exception {
doTest("idea/testData/quickfix/suppress/declarationKinds/beforeObject.kt");
}
@TestMetadata("beforeParam.kt")
public void testParam() throws Exception {
doTest("idea/testData/quickfix/suppress/declarationKinds/beforeParam.kt");
}
@TestMetadata("beforeTrait.kt")
public void testTrait() throws Exception {
doTest("idea/testData/quickfix/suppress/declarationKinds/beforeTrait.kt");
}
@TestMetadata("beforeVal.kt")
public void testVal() throws Exception {
doTest("idea/testData/quickfix/suppress/declarationKinds/beforeVal.kt");
}
@TestMetadata("beforeVar.kt")
public void testVar() throws Exception {
doTest("idea/testData/quickfix/suppress/declarationKinds/beforeVar.kt");
}
}
@TestMetadata("idea/testData/quickfix/suppress/errorRecovery")
public static class ErrorRecovery extends AbstractQuickFixTest {
public void testAllFilesPresentInErrorRecovery() throws Exception {
JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), "org.jetbrains.jet.generators.tests.GenerateTests", new File("idea/testData/quickfix/suppress/errorRecovery"), Pattern.compile("^before(\\w+)\\.kt$"), true);
}
@TestMetadata("beforeNonStringInSuppress.kt")
public void testNonStringInSuppress() throws Exception {
doTest("idea/testData/quickfix/suppress/errorRecovery/beforeNonStringInSuppress.kt");
}
@TestMetadata("beforeUnresolvedAnnotation.kt")
public void testUnresolvedAnnotation() throws Exception {
doTest("idea/testData/quickfix/suppress/errorRecovery/beforeUnresolvedAnnotation.kt");
}
}
public static Test innerSuite() {
TestSuite suite = new TestSuite("Suppress");
suite.addTestSuite(Suppress.class);
suite.addTestSuite(AnnotationPosition.class);
suite.addTestSuite(Availability.class);
suite.addTestSuite(DeclarationKinds.class);
suite.addTestSuite(ErrorRecovery.class);
return suite;
}
}
@TestMetadata("idea/testData/quickfix/typeAddition")
public static class TypeAddition extends AbstractQuickFixTest {
public void testAllFilesPresentInTypeAddition() throws Exception {
@@ -2012,6 +2237,7 @@ public class QuickFixTestGenerated extends AbstractQuickFixTest {
suite.addTestSuite(PlatformClasses.class);
suite.addTestSuite(Supercalls.class);
suite.addTestSuite(SupertypeInitialization.class);
suite.addTest(Suppress.innerSuite());
suite.addTestSuite(TypeAddition.class);
suite.addTestSuite(TypeImports.class);
suite.addTest(TypeMismatch.innerSuite());