Support 'suppress for statement' quick fix

#KT-3319 Fixed
This commit is contained in:
Andrey Breslav
2013-09-23 00:20:30 +04:00
parent 5b9d10d74e
commit fc70a65f99
94 changed files with 1064 additions and 40 deletions
@@ -0,0 +1,73 @@
/*
* 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.lang.psi;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.psi.tree.IElementType;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.parsing.JetExpressionParsing;
import java.util.HashMap;
import java.util.Map;
import static org.jetbrains.jet.lang.parsing.JetExpressionParsing.Precedence.*;
public class JetPsiPrecedences {
private static final Logger LOG = Logger.getInstance(JetPsiPrecedences.class);
private static final Map<IElementType, Integer> precedence;
static {
Map<IElementType, Integer> builder = new HashMap<IElementType, Integer>();
JetExpressionParsing.Precedence[] records = values();
for (int i = 0; i < records.length; i++) {
for (IElementType elementType : records[i].getOperations().getTypes()) {
builder.put(elementType, i);
}
}
precedence = builder;
}
public static final int PRECEDENCE_OF_ATOMIC_EXPRESSION = -1;
public static final int PRECEDENCE_OF_PREFIX_EXPRESSION = PREFIX.ordinal();
public static final int PRECEDENCE_OF_POSTFIX_EXPRESSION = POSTFIX.ordinal();
public static int getPrecedence(@NotNull JetExpression expression) {
if (expression instanceof JetAnnotatedExpression || expression instanceof JetPrefixExpression) {
return PRECEDENCE_OF_PREFIX_EXPRESSION;
}
if (expression instanceof JetPostfixExpression) {
return PRECEDENCE_OF_POSTFIX_EXPRESSION;
}
if (expression instanceof JetOperationExpression) {
JetOperationExpression operationExpression = (JetOperationExpression) expression;
IElementType operation = operationExpression.getOperationReference().getReferencedNameElementType();
Integer precedenceNumber = precedence.get(operation);
if (precedenceNumber == null) {
LOG.error("No precedence for operation: " + operation);
return precedence.size(); // lowest
}
return precedenceNumber;
}
return PRECEDENCE_OF_ATOMIC_EXPRESSION; // Atomic expression
}
}
@@ -23,7 +23,7 @@ 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.plugin.quickfix.AnnotationHostKind
import org.jetbrains.jet.lang.diagnostics.DiagnosticFactory
import com.intellij.psi.util.PsiTreeUtil
@@ -53,6 +53,7 @@ fun createSuppressWarningActions(element: PsiElement, diagnosticFactory: Diagnos
val actions = arrayListOf<SuppressIntentionAction>()
var current: PsiElement? = element
var suppressAtStatementAllowed = true
while (current != null) {
if (current is JetDeclaration) {
val declaration = current as JetDeclaration
@@ -60,6 +61,16 @@ fun createSuppressWarningActions(element: PsiElement, diagnosticFactory: Diagnos
if (kind != null) {
actions.add(KotlinSuppressIntentionAction(declaration, diagnosticFactory, kind))
}
suppressAtStatementAllowed = false
}
else if (current is JetExpression && suppressAtStatementAllowed) {
// Add suppress action at first statement
if ((current as PsiElement).getParent() is JetBlockExpression) {
val expression = current as JetExpression
actions.add(KotlinSuppressIntentionAction(expression, diagnosticFactory,
AnnotationHostKind("statement", "", true)))
suppressAtStatementAllowed = false
}
}
current = current?.getParent()
@@ -67,7 +78,7 @@ fun createSuppressWarningActions(element: PsiElement, diagnosticFactory: Diagnos
return actions
}
private object DeclarationKindDetector : JetVisitor<DeclarationKind?, Unit?>() {
private object DeclarationKindDetector : JetVisitor<AnnotationHostKind?, Unit?>() {
fun detect(declaration: JetDeclaration) = declaration.accept(this, null)
@@ -91,11 +102,12 @@ private object DeclarationKindDetector : JetVisitor<DeclarationKind?, Unit?>() {
override fun visitParameter(d: JetParameter, _: Unit?) = detect(d, "parameter", newLineNeeded = false)
override fun visitObjectDeclaration(d: JetObjectDeclaration, _: Unit?): DeclarationKind? {
override fun visitObjectDeclaration(d: JetObjectDeclaration, _: Unit?): AnnotationHostKind? {
if (d.getParent() is JetClassObject) return null
if (d.getParent() is JetObjectLiteralExpression) 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)
private fun detect(declaration: JetDeclaration, kind: String, name: String = declaration.getName() ?: "<anonymous>", newLineNeeded: Boolean = true)
= AnnotationHostKind(kind, name, newLineNeeded)
}
@@ -16,25 +16,22 @@
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
import org.jetbrains.jet.lang.psi.JetPsiPrecedences.*
public class KotlinSuppressIntentionAction(
private val suppressAt: JetDeclaration,
private val suppressAt: JetExpression,
private val diagnosticFactory: DiagnosticFactory,
private val kind: DeclarationKind
private val kind: AnnotationHostKind
) : SuppressIntentionAction() {
override fun getFamilyName() = JetBundle.message("suppress.warnings.family")
@@ -44,49 +41,103 @@ public class KotlinSuppressIntentionAction(
override fun invoke(project: Project, editor: Editor?, element: PsiElement) {
val id = "\"${diagnosticFactory.getName()}\""
if (suppressAt is JetModifierListOwner) {
suppressAtModifierListOwner(suppressAt, id)
}
else if (suppressAt is JetAnnotatedExpression) {
suppressAtAnnotatedExpression(CaretBox(suppressAt, editor), id)
}
else if (suppressAt is JetExpression) {
suppressAtExpression(CaretBox(suppressAt, editor), id)
}
}
private fun suppressAtModifierListOwner(suppressAt: JetModifierListOwner, id: String) {
val project = suppressAt.getProject()
val modifierList = suppressAt.getModifierList()
if (modifierList == null) {
// create a modifier list from scratch
val newModifierList = JetPsiFactory.createModifierList(project, "[suppress($id)]")
val newModifierList = JetPsiFactory.createModifierList(project, suppressAnnotationText(id))
val replaced = JetPsiUtil.replaceModifierList(suppressAt, newModifierList)
val whiteSpace = project.createWhiteSpace(kind)
suppressAt.addAfter(whiteSpace, replaced)
}
else {
val entry = findSuppressAnnotation(modifierList)
val entry = findSuppressAnnotation(suppressAt)
if (entry == null) {
val newAnnotation = JetPsiFactory.createAnnotation(project, "[suppress($id)]")
// no [suppress] annotation
val newAnnotation = JetPsiFactory.createAnnotation(project, suppressAnnotationText(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)
}
// already annotated with [suppress]
addArgumentToSuppressAnnotation(entry, id)
}
}
}
private fun findSuppressAnnotation(modifierList: JetModifierList): JetAnnotationEntry? {
private fun suppressAtAnnotatedExpression(suppressAt: CaretBox<JetAnnotatedExpression>, id: String) {
val entry = findSuppressAnnotation(suppressAt.expression)
if (entry != null) {
// already annotated with [suppress]
addArgumentToSuppressAnnotation(entry, id)
}
else {
suppressAtExpression(suppressAt, id)
}
}
private fun suppressAtExpression(caretBox: CaretBox<JetExpression>, id: String) {
val suppressAt = caretBox.expression
assert(suppressAt !is JetDeclaration, "Declarations should have been checked for above")
val project = suppressAt.getProject()
val parentheses = getPrecedence(suppressAt) > PRECEDENCE_OF_PREFIX_EXPRESSION
val placeholderText = "PLACEHOLDER_ID"
val inner = if (parentheses) "($placeholderText)" else placeholderText
val annotatedExpression = JetPsiFactory.createExpression(project, suppressAnnotationText(id) + "\n" + inner)
val copy = suppressAt.copy()!!
val afterReplace = suppressAt.replace(annotatedExpression) as JetAnnotatedExpression
val toReplace = afterReplace.findElementAt(afterReplace.getTextLength() - 2)!!
assert (toReplace.getText() == placeholderText)
val result = toReplace.replace(copy)!!
caretBox.positionCaretInCopy(result)
}
private fun addArgumentToSuppressAnnotation(entry: JetAnnotationEntry, id: String) {
val project = entry.getProject()
// 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 suppressAnnotationText(id: String) = "[suppress($id)]"
private fun findSuppressAnnotation(annotated: JetAnnotated): JetAnnotationEntry? {
val suppressAnnotationClass = KotlinBuiltIns.getInstance().getSuppressAnnotationClass()
val context = AnalyzerFacadeWithCache.getContextForElement(modifierList)
for (entry in modifierList.getAnnotationEntries()) {
val context = AnalyzerFacadeWithCache.getContextForElement(annotated)
for (entry in annotated.getAnnotationEntries()) {
val annotationDescriptor = context.get(BindingContext.ANNOTATION, entry)
if (annotationDescriptor != null && suppressAnnotationClass.getTypeConstructor() == annotationDescriptor.getType().getConstructor()) {
return entry
@@ -96,9 +147,21 @@ public class KotlinSuppressIntentionAction(
}
}
public class DeclarationKind(val kind: String, val name: String, val newLineNeeded: Boolean)
private fun Project.createWhiteSpace(kind: DeclarationKind): PsiElement =
public class AnnotationHostKind(val kind: String, val name: String, val newLineNeeded: Boolean)
private fun Project.createWhiteSpace(kind: AnnotationHostKind): PsiElement =
if (kind.newLineNeeded)
JetPsiFactory.createNewLine(this)
else
JetPsiFactory.createWhiteSpace(this)
JetPsiFactory.createWhiteSpace(this)
private class CaretBox<out E: JetExpression>(
val expression: E,
private val editor: Editor?
) {
private val offsetInExpression: Int = (editor?.getCaretModel()?.getOffset() ?: 0) - expression.getTextRange()!!.getStartOffset()
fun positionCaretInCopy(copy: PsiElement) {
if (editor == null) return
editor.getCaretModel().moveToOffset(copy.getTextOffset() + offsetInExpression)
}
}
@@ -0,0 +1,6 @@
// "Suppress 'UNNECESSARY_NOT_NULL_ASSERTION' for statement " "true"
fun foo() {
[suppress("UNNECESSARY_NOT_NULL_ASSERTION")]
(false<caret>!! && true)
}
@@ -0,0 +1,8 @@
// "Suppress 'UNNECESSARY_NOT_NULL_ASSERTION' for statement " "true"
fun foo() {
[suppress("UNNECESSARY_NOT_NULL_ASSERTION")]
[ann] ""<caret>!!
}
annotation class ann
@@ -0,0 +1,7 @@
// "Suppress 'UNNECESSARY_NOT_NULL_ASSERTION' for statement " "true"
fun foo() {
[suppress("Foo", "UNNECESSARY_NOT_NULL_ASSERTION")] ""<caret>!!
}
annotation class ann
@@ -0,0 +1,6 @@
// "Suppress 'UNNECESSARY_NOT_NULL_ASSERTION' for statement " "true"
fun foo(a: Array<Int>) {
[suppress("UNNECESSARY_NOT_NULL_ASSERTION")]
a[1<caret>!!]
}
@@ -0,0 +1,6 @@
// "Suppress 'UNNECESSARY_NOT_NULL_ASSERTION' for statement " "true"
fun foo() {
[suppress("UNNECESSARY_NOT_NULL_ASSERTION")]
(""<caret>!! as String)
}
@@ -0,0 +1,6 @@
// "Suppress 'UNNECESSARY_NOT_NULL_ASSERTION' for statement " "true"
fun foo() {
[suppress("UNNECESSARY_NOT_NULL_ASSERTION")]
(""<caret>!! as? String)
}
@@ -0,0 +1,7 @@
// "Suppress 'UNNECESSARY_NOT_NULL_ASSERTION' for statement " "true"
fun foo() {
var x = 0
[suppress("UNNECESSARY_NOT_NULL_ASSERTION")]
(x = 1<caret>!!)
}
@@ -0,0 +1,8 @@
// "Suppress 'REDUNDANT_NULLABLE' for statement " "true"
fun foo() {
[suppress("REDUNDANT_NULLABLE")]
call("": String?<caret>?)
}
fun call(s: String?) {}
@@ -0,0 +1,6 @@
// "Suppress 'UNNECESSARY_NOT_NULL_ASSERTION' for statement " "true"
fun foo() {
[suppress("UNNECESSARY_NOT_NULL_ASSERTION")]
(""<caret>!! : String)
}
@@ -0,0 +1,7 @@
// "Suppress 'UNNECESSARY_NOT_NULL_ASSERTION' for statement " "true"
fun foo() {
[suppress("UNNECESSARY_NOT_NULL_ASSERTION")]
do {}
while (true<caret>!!)
}
@@ -0,0 +1,10 @@
// "Suppress 'UNNECESSARY_NOT_NULL_ASSERTION' for statement " "true"
fun foo(a: C) {
[suppress("UNNECESSARY_NOT_NULL_ASSERTION")]
a.foo(""<caret>!!)
}
class C {
fun foo(a: Any) {}
}
@@ -0,0 +1,6 @@
// "Suppress 'UNNECESSARY_NOT_NULL_ASSERTION' for statement " "true"
fun foo() {
[suppress("UNNECESSARY_NOT_NULL_ASSERTION")]
(1<caret>!! ?: 0)
}
@@ -0,0 +1,6 @@
// "Suppress 'UNNECESSARY_NOT_NULL_ASSERTION' for statement " "true"
fun foo() {
[suppress("UNNECESSARY_NOT_NULL_ASSERTION")]
(1<caret>!! == 2)
}
@@ -0,0 +1,8 @@
// "Suppress 'UNNECESSARY_NOT_NULL_ASSERTION' for statement " "true"
fun foo() {
[suppress("UNNECESSARY_NOT_NULL_ASSERTION")]
for (i in list()<caret>!!) {}
}
fun list(): List<Int> = throw Exception()
@@ -0,0 +1,6 @@
// "Suppress 'UNNECESSARY_NOT_NULL_ASSERTION' for statement " "true"
fun foo() {
[suppress("UNNECESSARY_NOT_NULL_ASSERTION")]
if (true<caret>!!) {}
}
@@ -0,0 +1,6 @@
// "Suppress 'UNNECESSARY_NOT_NULL_ASSERTION' for statement " "true"
fun foo() {
[suppress("UNNECESSARY_NOT_NULL_ASSERTION")]
(1<caret>!! in (1..2))
}
@@ -0,0 +1,6 @@
// "Suppress 'UNNECESSARY_NOT_NULL_ASSERTION' for statement " "true"
fun foo() {
[suppress("UNNECESSARY_NOT_NULL_ASSERTION")]
(1<caret>!! plus 2)
}
@@ -0,0 +1,6 @@
// "Suppress 'UNNECESSARY_NOT_NULL_ASSERTION' for statement " "true"
fun foo() {
[suppress("UNNECESSARY_NOT_NULL_ASSERTION")]
(""<caret>!! is String)
}
@@ -0,0 +1,6 @@
// "Suppress 'UNNECESSARY_NOT_NULL_ASSERTION' for statement " "true"
fun foo() {
[suppress("UNNECESSARY_NOT_NULL_ASSERTION")]
@label""<caret>!!
}
@@ -0,0 +1,6 @@
// "Suppress 'UNNECESSARY_NOT_NULL_ASSERTION' for statement " "true"
fun foo() {
[suppress("UNNECESSARY_NOT_NULL_ASSERTION")]
(1<caret>!! < 2)
}
@@ -0,0 +1,6 @@
// "Suppress 'UNNECESSARY_NOT_NULL_ASSERTION' for statement " "true"
fun foo() {
[suppress("UNNECESSARY_NOT_NULL_ASSERTION")]
(1<caret>!! * 2)
}
@@ -0,0 +1,6 @@
// "Suppress 'UNNECESSARY_NOT_NULL_ASSERTION' for statement " "true"
fun foo() {
[suppress("UNNECESSARY_NOT_NULL_ASSERTION")]
(false<caret>!! || true)
}
@@ -0,0 +1,6 @@
// "Suppress 'UNNECESSARY_NOT_NULL_ASSERTION' for statement " "true"
fun foo() {
[suppress("UNNECESSARY_NOT_NULL_ASSERTION")]
(""<caret>!!)
}
@@ -0,0 +1,6 @@
// "Suppress 'UNNECESSARY_NOT_NULL_ASSERTION' for statement " "true"
fun foo() {
[suppress("UNNECESSARY_NOT_NULL_ASSERTION")]
(1<caret>!! + 2)
}
@@ -0,0 +1,6 @@
// "Suppress 'UNNECESSARY_NOT_NULL_ASSERTION' for statement " "true"
fun foo() {
[suppress("UNNECESSARY_NOT_NULL_ASSERTION")]
""<caret>!!
}
@@ -0,0 +1,11 @@
// "Suppress 'REDUNDANT_NULLABLE' for statement " "true"
fun foo() {
var v = Box<String?>()
[suppress("REDUNDANT_NULLABLE")]
(v: Box<String?<caret>?>)++
}
class Box<T> {
fun inc() = this
}
@@ -0,0 +1,11 @@
// "Suppress 'REDUNDANT_NULLABLE' for statement " "true"
fun foo() {
var v = Box<String?>()
[suppress("REDUNDANT_NULLABLE")]
++(v: Box<String?<caret>?>)
}
class Box<T> {
fun inc() = this
}
@@ -0,0 +1,6 @@
// "Suppress 'UNNECESSARY_NOT_NULL_ASSERTION' for statement " "true"
fun foo() {
[suppress("UNNECESSARY_NOT_NULL_ASSERTION")]
(1<caret>!! .. 2)
}
@@ -0,0 +1,6 @@
// "Suppress 'UNNECESSARY_NOT_NULL_ASSERTION' for statement " "true"
fun foo(): Any {
[suppress("UNNECESSARY_NOT_NULL_ASSERTION")]
return ""<caret>!!
}
@@ -0,0 +1,10 @@
// "Suppress 'UNNECESSARY_NOT_NULL_ASSERTION' for statement " "true"
fun foo(a: C) {
[suppress("UNNECESSARY_NOT_NULL_ASSERTION")]
a?.foo(""<caret>!!)
}
class C {
fun foo(a: Any) {}
}
@@ -0,0 +1,8 @@
// "Suppress 'UNUSED_EXPRESSION' for statement " "true"
fun foo() {
[suppress("UNUSED_EXPRESSION")]
a
}
val a = 1
@@ -0,0 +1,6 @@
// "Suppress 'UNNECESSARY_NOT_NULL_ASSERTION' for statement " "true"
fun foo() {
[suppress("UNNECESSARY_NOT_NULL_ASSERTION")]
"${""<caret>!!}"
}
@@ -0,0 +1,6 @@
// "Suppress 'UNNECESSARY_NOT_NULL_ASSERTION' for statement " "true"
fun foo(): Any {
[suppress("UNNECESSARY_NOT_NULL_ASSERTION")]
throw Exception(""<caret>!!)
}
@@ -0,0 +1,11 @@
// "Suppress 'UNNECESSARY_NOT_NULL_ASSERTION' for statement " "true"
fun foo() {
try {
[suppress("UNNECESSARY_NOT_NULL_ASSERTION")]
""<caret>!!
}
finally {
}
}
@@ -0,0 +1,8 @@
// "Suppress 'UNNECESSARY_NOT_NULL_ASSERTION' for statement " "true"
fun foo(a: Any) {
[suppress("UNNECESSARY_NOT_NULL_ASSERTION")]
when (a) {
""<caret>!! -> {}
}
}
@@ -0,0 +1,8 @@
// "Suppress 'UNNECESSARY_NOT_NULL_ASSERTION' for statement " "true"
fun foo() {
[suppress("UNNECESSARY_NOT_NULL_ASSERTION")]
when (1) {
in 1<caret>!!..2 -> {}
}
}
@@ -0,0 +1,8 @@
// "Suppress 'REDUNDANT_NULLABLE' for statement " "true"
fun foo() {
[suppress("REDUNDANT_NULLABLE")]
when ("") {
is Any?<caret>? -> {}
}
}
@@ -0,0 +1,8 @@
// "Suppress 'UNNECESSARY_NOT_NULL_ASSERTION' for statement " "true"
fun foo() {
[suppress("UNNECESSARY_NOT_NULL_ASSERTION")]
when (""<caret>!!) {
is Any -> {}
}
}
@@ -0,0 +1,6 @@
// "Suppress 'UNNECESSARY_NOT_NULL_ASSERTION' for statement " "true"
fun foo() {
[suppress("UNNECESSARY_NOT_NULL_ASSERTION")]
while (true<caret>!!) {}
}
@@ -0,0 +1,5 @@
// "Suppress 'UNNECESSARY_NOT_NULL_ASSERTION' for statement " "true"
fun foo() {
false<caret>!! && true
}
@@ -0,0 +1,7 @@
// "Suppress 'UNNECESSARY_NOT_NULL_ASSERTION' for statement " "true"
fun foo() {
[ann] ""<caret>!!
}
annotation class ann
@@ -0,0 +1,7 @@
// "Suppress 'UNNECESSARY_NOT_NULL_ASSERTION' for statement " "true"
fun foo() {
[suppress("Foo")] ""<caret>!!
}
annotation class ann
@@ -0,0 +1,5 @@
// "Suppress 'UNNECESSARY_NOT_NULL_ASSERTION' for statement " "true"
fun foo(a: Array<Int>) {
a[1<caret>!!]
}
@@ -0,0 +1,5 @@
// "Suppress 'UNNECESSARY_NOT_NULL_ASSERTION' for statement " "true"
fun foo() {
""<caret>!! as String
}
@@ -0,0 +1,5 @@
// "Suppress 'UNNECESSARY_NOT_NULL_ASSERTION' for statement " "true"
fun foo() {
""<caret>!! as? String
}
@@ -0,0 +1,6 @@
// "Suppress 'UNNECESSARY_NOT_NULL_ASSERTION' for statement " "true"
fun foo() {
var x = 0
x = 1<caret>!!
}
@@ -0,0 +1,7 @@
// "Suppress 'REDUNDANT_NULLABLE' for statement " "true"
fun foo() {
call("": String?<caret>?)
}
fun call(s: String?) {}
@@ -0,0 +1,5 @@
// "Suppress 'UNNECESSARY_NOT_NULL_ASSERTION' for statement " "true"
fun foo() {
""<caret>!! : String
}
@@ -0,0 +1,6 @@
// "Suppress 'UNNECESSARY_NOT_NULL_ASSERTION' for statement " "true"
fun foo() {
do {}
while (true<caret>!!)
}
@@ -0,0 +1,9 @@
// "Suppress 'UNNECESSARY_NOT_NULL_ASSERTION' for statement " "true"
fun foo(a: C) {
a.foo(""<caret>!!)
}
class C {
fun foo(a: Any) {}
}
@@ -0,0 +1,5 @@
// "Suppress 'UNNECESSARY_NOT_NULL_ASSERTION' for statement " "true"
fun foo() {
1<caret>!! ?: 0
}
@@ -0,0 +1,5 @@
// "Suppress 'UNNECESSARY_NOT_NULL_ASSERTION' for statement " "true"
fun foo() {
1<caret>!! == 2
}
@@ -0,0 +1,7 @@
// "Suppress 'UNNECESSARY_NOT_NULL_ASSERTION' for statement " "true"
fun foo() {
for (i in list()<caret>!!) {}
}
fun list(): List<Int> = throw Exception()
@@ -0,0 +1,5 @@
// "Suppress 'UNNECESSARY_NOT_NULL_ASSERTION' for statement " "true"
fun foo() {
if (true<caret>!!) {}
}
@@ -0,0 +1,5 @@
// "Suppress 'UNNECESSARY_NOT_NULL_ASSERTION' for statement " "true"
fun foo() {
1<caret>!! in (1..2)
}
@@ -0,0 +1,5 @@
// "Suppress 'UNNECESSARY_NOT_NULL_ASSERTION' for statement " "true"
fun foo() {
1<caret>!! plus 2
}
@@ -0,0 +1,5 @@
// "Suppress 'UNNECESSARY_NOT_NULL_ASSERTION' for statement " "true"
fun foo() {
""<caret>!! is String
}
@@ -0,0 +1,5 @@
// "Suppress 'UNNECESSARY_NOT_NULL_ASSERTION' for statement " "true"
fun foo() {
@label""<caret>!!
}
@@ -0,0 +1,5 @@
// "Suppress 'UNNECESSARY_NOT_NULL_ASSERTION' for statement " "true"
fun foo() {
1<caret>!! < 2
}
@@ -0,0 +1,5 @@
// "Suppress 'UNNECESSARY_NOT_NULL_ASSERTION' for statement " "true"
fun foo() {
1<caret>!! * 2
}
@@ -0,0 +1,5 @@
// "Suppress 'UNNECESSARY_NOT_NULL_ASSERTION' for statement " "true"
fun foo() {
false<caret>!! || true
}
@@ -0,0 +1,5 @@
// "Suppress 'UNNECESSARY_NOT_NULL_ASSERTION' for statement " "true"
fun foo() {
(""<caret>!!)
}
@@ -0,0 +1,5 @@
// "Suppress 'UNNECESSARY_NOT_NULL_ASSERTION' for statement " "true"
fun foo() {
1<caret>!! + 2
}
@@ -0,0 +1,5 @@
// "Suppress 'UNNECESSARY_NOT_NULL_ASSERTION' for statement " "true"
fun foo() {
""<caret>!!
}
@@ -0,0 +1,10 @@
// "Suppress 'REDUNDANT_NULLABLE' for statement " "true"
fun foo() {
var v = Box<String?>()
(v: Box<String?<caret>?>)++
}
class Box<T> {
fun inc() = this
}
@@ -0,0 +1,10 @@
// "Suppress 'REDUNDANT_NULLABLE' for statement " "true"
fun foo() {
var v = Box<String?>()
++(v: Box<String?<caret>?>)
}
class Box<T> {
fun inc() = this
}
@@ -0,0 +1,5 @@
// "Suppress 'UNNECESSARY_NOT_NULL_ASSERTION' for statement " "true"
fun foo() {
1<caret>!! .. 2
}
@@ -0,0 +1,5 @@
// "Suppress 'UNNECESSARY_NOT_NULL_ASSERTION' for statement " "true"
fun foo(): Any {
return ""<caret>!!
}
@@ -0,0 +1,9 @@
// "Suppress 'UNNECESSARY_NOT_NULL_ASSERTION' for statement " "true"
fun foo(a: C) {
a?.foo(""<caret>!!)
}
class C {
fun foo(a: Any) {}
}
@@ -0,0 +1,7 @@
// "Suppress 'UNUSED_EXPRESSION' for statement " "true"
fun foo() {
a
}
val a = 1
@@ -0,0 +1,5 @@
// "Suppress 'UNNECESSARY_NOT_NULL_ASSERTION' for statement " "true"
fun foo() {
"${""<caret>!!}"
}
@@ -0,0 +1,5 @@
// "Suppress 'UNNECESSARY_NOT_NULL_ASSERTION' for statement " "true"
fun foo(): Any {
throw Exception(""<caret>!!)
}
@@ -0,0 +1,10 @@
// "Suppress 'UNNECESSARY_NOT_NULL_ASSERTION' for statement " "true"
fun foo() {
try {
""<caret>!!
}
finally {
}
}
@@ -0,0 +1,7 @@
// "Suppress 'UNNECESSARY_NOT_NULL_ASSERTION' for statement " "true"
fun foo(a: Any) {
when (a) {
""<caret>!! -> {}
}
}
@@ -0,0 +1,7 @@
// "Suppress 'UNNECESSARY_NOT_NULL_ASSERTION' for statement " "true"
fun foo() {
when (1) {
in 1<caret>!!..2 -> {}
}
}
@@ -0,0 +1,7 @@
// "Suppress 'REDUNDANT_NULLABLE' for statement " "true"
fun foo() {
when ("") {
is Any?<caret>? -> {}
}
}
@@ -0,0 +1,7 @@
// "Suppress 'UNNECESSARY_NOT_NULL_ASSERTION' for statement " "true"
fun foo() {
when (""<caret>!!) {
is Any -> {}
}
}
@@ -0,0 +1,5 @@
// "Suppress 'UNNECESSARY_NOT_NULL_ASSERTION' for statement " "true"
fun foo() {
while (true<caret>!!) {}
}
@@ -0,0 +1,5 @@
// "Suppress 'UNNECESSARY_NOT_NULL_ASSERTION' for statement " "false"
// ACTION: Remove unnecessary non-null assertion (!!)
[suppress("FOO"<caret>!!)]
fun foo() {}
@@ -0,0 +1,5 @@
// "Suppress 'UNNECESSARY_NOT_NULL_ASSERTION' for statement " "false"
// ACTION: Remove unnecessary non-null assertion (!!)
open class Base(s: String)
class Child: Base(""<caret>!!)
@@ -0,0 +1,4 @@
// "Suppress 'UNNECESSARY_NOT_NULL_ASSERTION' for statement " "false"
// ACTION: Remove unnecessary non-null assertion (!!)
fun foo(s: String = ""<caret>!!) {}
@@ -0,0 +1,4 @@
// "Suppress 'UNNECESSARY_NOT_NULL_ASSERTION' for statement " "false"
// ACTION: Remove unnecessary non-null assertion (!!)
fun foo() = ""<caret>!!
@@ -0,0 +1,9 @@
// "Suppress 'UNNECESSARY_NOT_NULL_ASSERTION' for statement " "false"
// ACTION: Disable 'Split Property Declaration'
// ACTION: Edit intention settings
// ACTION: Remove unnecessary non-null assertion (!!)
// ACTION: Split property declaration
fun foo() {
val bar = ""<caret>!!
}
@@ -0,0 +1,4 @@
// "Suppress 'REDUNDANT_NULLABLE' for statement " "false"
// ACTION: Remove redundant '?'
fun foo(s: String?<caret>?) {}
@@ -0,0 +1,10 @@
// "Suppress 'REDUNDANT_NULLABLE' for statement " "false"
// ACTION: Remove redundant '?'
fun foo() {
any {
(x: String?<caret>?) ->
}
}
fun any(a: Any?) {}
@@ -0,0 +1,4 @@
// "Suppress 'UNNECESSARY_NOT_NULL_ASSERTION' for statement " "false"
// ACTION: Remove unnecessary non-null assertion (!!)
val foo = ""<caret>!!
@@ -0,0 +1,10 @@
// "Suppress 'UNNECESSARY_NOT_NULL_ASSERTION' for object <anonymous>" "false"
// ACTION: Remove unnecessary non-null assertion (!!)
fun foo() {
object : Base(""<caret>!!) {
}
}
open class Base(s: Any)
@@ -0,0 +1,13 @@
// "Suppress 'UNNECESSARY_NOT_NULL_ASSERTION' for object <anonymous>" "false"
// ACTION: Disable 'Split Property Declaration'
// ACTION: Edit intention settings
// ACTION: Remove unnecessary non-null assertion (!!)
// ACTION: Split property declaration
fun foo() {
val a = object : Base(""<caret>!!) {
}
}
open class Base(s: Any)
@@ -0,0 +1,5 @@
// "Suppress 'REDUNDANT_NULLABLE' for statement " "false"
// ACTION: Remove redundant '?'
open class Base<T>
class Child: Base<String?<caret>?>()
@@ -250,15 +250,30 @@ public class QuickFixMultiFileTestGenerated extends AbstractQuickFixMultiFileTes
}
@TestMetadata("idea/testData/quickfix/suppress")
@InnerTestClasses({})
@InnerTestClasses({Suppress.ForStatement.class})
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);
}
@TestMetadata("idea/testData/quickfix/suppress/forStatement")
@InnerTestClasses({})
public static class ForStatement extends AbstractQuickFixMultiFileTest {
public void testAllFilesPresentInForStatement() throws Exception {
JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), "org.jetbrains.jet.generators.tests.GenerateTests", new File("idea/testData/quickfix/suppress/forStatement"), Pattern.compile("^(\\w+)\\.before\\.Main\\.kt$"), true);
}
public static Test innerSuite() {
TestSuite suite = new TestSuite("ForStatement");
suite.addTestSuite(ForStatement.class);
return suite;
}
}
public static Test innerSuite() {
TestSuite suite = new TestSuite("Suppress");
suite.addTestSuite(Suppress.class);
suite.addTest(ForStatement.innerSuite());
return suite;
}
}
@@ -1372,7 +1372,7 @@ public class QuickFixTestGenerated extends AbstractQuickFixTest {
}
@TestMetadata("idea/testData/quickfix/suppress")
@InnerTestClasses({Suppress.AnnotationPosition.class, Suppress.Availability.class, Suppress.DeclarationKinds.class, Suppress.ErrorRecovery.class})
@InnerTestClasses({Suppress.AnnotationPosition.class, Suppress.Availability.class, Suppress.DeclarationKinds.class, Suppress.ErrorRecovery.class, Suppress.ForStatement.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);
@@ -1585,6 +1585,279 @@ public class QuickFixTestGenerated extends AbstractQuickFixTest {
}
@TestMetadata("idea/testData/quickfix/suppress/forStatement")
@InnerTestClasses({ForStatement.Unavailable.class})
public static class ForStatement extends AbstractQuickFixTest {
public void testAllFilesPresentInForStatement() throws Exception {
JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), "org.jetbrains.jet.generators.tests.GenerateTests", new File("idea/testData/quickfix/suppress/forStatement"), Pattern.compile("^before(\\w+)\\.kt$"), true);
}
@TestMetadata("beforeAndAnd.kt")
public void testAndAnd() throws Exception {
doTest("idea/testData/quickfix/suppress/forStatement/beforeAndAnd.kt");
}
@TestMetadata("beforeAnnotatedExpr.kt")
public void testAnnotatedExpr() throws Exception {
doTest("idea/testData/quickfix/suppress/forStatement/beforeAnnotatedExpr.kt");
}
@TestMetadata("beforeAnnotatedExprWithSuppress.kt")
public void testAnnotatedExprWithSuppress() throws Exception {
doTest("idea/testData/quickfix/suppress/forStatement/beforeAnnotatedExprWithSuppress.kt");
}
@TestMetadata("beforeArrayRead.kt")
public void testArrayRead() throws Exception {
doTest("idea/testData/quickfix/suppress/forStatement/beforeArrayRead.kt");
}
@TestMetadata("beforeAs.kt")
public void testAs() throws Exception {
doTest("idea/testData/quickfix/suppress/forStatement/beforeAs.kt");
}
@TestMetadata("beforeAsSafe.kt")
public void testAsSafe() throws Exception {
doTest("idea/testData/quickfix/suppress/forStatement/beforeAsSafe.kt");
}
@TestMetadata("beforeAssign.kt")
public void testAssign() throws Exception {
doTest("idea/testData/quickfix/suppress/forStatement/beforeAssign.kt");
}
@TestMetadata("beforeCall.kt")
public void testCall() throws Exception {
doTest("idea/testData/quickfix/suppress/forStatement/beforeCall.kt");
}
@TestMetadata("beforeColon.kt")
public void testColon() throws Exception {
doTest("idea/testData/quickfix/suppress/forStatement/beforeColon.kt");
}
@TestMetadata("beforeDoWhile.kt")
public void testDoWhile() throws Exception {
doTest("idea/testData/quickfix/suppress/forStatement/beforeDoWhile.kt");
}
@TestMetadata("beforeDotQualified.kt")
public void testDotQualified() throws Exception {
doTest("idea/testData/quickfix/suppress/forStatement/beforeDotQualified.kt");
}
@TestMetadata("beforeElvis.kt")
public void testElvis() throws Exception {
doTest("idea/testData/quickfix/suppress/forStatement/beforeElvis.kt");
}
@TestMetadata("beforeEqEq.kt")
public void testEqEq() throws Exception {
doTest("idea/testData/quickfix/suppress/forStatement/beforeEqEq.kt");
}
@TestMetadata("beforeFor.kt")
public void testFor() throws Exception {
doTest("idea/testData/quickfix/suppress/forStatement/beforeFor.kt");
}
@TestMetadata("beforeIf.kt")
public void testIf() throws Exception {
doTest("idea/testData/quickfix/suppress/forStatement/beforeIf.kt");
}
@TestMetadata("beforeIn.kt")
public void testIn() throws Exception {
doTest("idea/testData/quickfix/suppress/forStatement/beforeIn.kt");
}
@TestMetadata("beforeInfix.kt")
public void testInfix() throws Exception {
doTest("idea/testData/quickfix/suppress/forStatement/beforeInfix.kt");
}
@TestMetadata("beforeIs.kt")
public void testIs() throws Exception {
doTest("idea/testData/quickfix/suppress/forStatement/beforeIs.kt");
}
@TestMetadata("beforeLabeled.kt")
public void testLabeled() throws Exception {
doTest("idea/testData/quickfix/suppress/forStatement/beforeLabeled.kt");
}
@TestMetadata("beforeLess.kt")
public void testLess() throws Exception {
doTest("idea/testData/quickfix/suppress/forStatement/beforeLess.kt");
}
@TestMetadata("beforeMul.kt")
public void testMul() throws Exception {
doTest("idea/testData/quickfix/suppress/forStatement/beforeMul.kt");
}
@TestMetadata("beforeOrOr.kt")
public void testOrOr() throws Exception {
doTest("idea/testData/quickfix/suppress/forStatement/beforeOrOr.kt");
}
@TestMetadata("beforeParenthesized.kt")
public void testParenthesized() throws Exception {
doTest("idea/testData/quickfix/suppress/forStatement/beforeParenthesized.kt");
}
@TestMetadata("beforePlus.kt")
public void testPlus() throws Exception {
doTest("idea/testData/quickfix/suppress/forStatement/beforePlus.kt");
}
@TestMetadata("beforePostfix.kt")
public void testPostfix() throws Exception {
doTest("idea/testData/quickfix/suppress/forStatement/beforePostfix.kt");
}
@TestMetadata("beforePostfixPlusPlus.kt")
public void testPostfixPlusPlus() throws Exception {
doTest("idea/testData/quickfix/suppress/forStatement/beforePostfixPlusPlus.kt");
}
@TestMetadata("beforePrefixPlusPlus.kt")
public void testPrefixPlusPlus() throws Exception {
doTest("idea/testData/quickfix/suppress/forStatement/beforePrefixPlusPlus.kt");
}
@TestMetadata("beforeRange.kt")
public void testRange() throws Exception {
doTest("idea/testData/quickfix/suppress/forStatement/beforeRange.kt");
}
@TestMetadata("beforeReturn.kt")
public void testReturn() throws Exception {
doTest("idea/testData/quickfix/suppress/forStatement/beforeReturn.kt");
}
@TestMetadata("beforeSafeQualified.kt")
public void testSafeQualified() throws Exception {
doTest("idea/testData/quickfix/suppress/forStatement/beforeSafeQualified.kt");
}
@TestMetadata("beforeSimpleName.kt")
public void testSimpleName() throws Exception {
doTest("idea/testData/quickfix/suppress/forStatement/beforeSimpleName.kt");
}
@TestMetadata("beforeStringTemplate.kt")
public void testStringTemplate() throws Exception {
doTest("idea/testData/quickfix/suppress/forStatement/beforeStringTemplate.kt");
}
@TestMetadata("beforeThrow.kt")
public void testThrow() throws Exception {
doTest("idea/testData/quickfix/suppress/forStatement/beforeThrow.kt");
}
@TestMetadata("beforeTry.kt")
public void testTry() throws Exception {
doTest("idea/testData/quickfix/suppress/forStatement/beforeTry.kt");
}
@TestMetadata("beforeWhenExpressionEntry.kt")
public void testWhenExpressionEntry() throws Exception {
doTest("idea/testData/quickfix/suppress/forStatement/beforeWhenExpressionEntry.kt");
}
@TestMetadata("beforeWhenInEntry.kt")
public void testWhenInEntry() throws Exception {
doTest("idea/testData/quickfix/suppress/forStatement/beforeWhenInEntry.kt");
}
@TestMetadata("beforeWhenIsEntry.kt")
public void testWhenIsEntry() throws Exception {
doTest("idea/testData/quickfix/suppress/forStatement/beforeWhenIsEntry.kt");
}
@TestMetadata("beforeWhenSubject.kt")
public void testWhenSubject() throws Exception {
doTest("idea/testData/quickfix/suppress/forStatement/beforeWhenSubject.kt");
}
@TestMetadata("beforeWhile.kt")
public void testWhile() throws Exception {
doTest("idea/testData/quickfix/suppress/forStatement/beforeWhile.kt");
}
@TestMetadata("idea/testData/quickfix/suppress/forStatement/unavailable")
public static class Unavailable extends AbstractQuickFixTest {
public void testAllFilesPresentInUnavailable() throws Exception {
JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), "org.jetbrains.jet.generators.tests.GenerateTests", new File("idea/testData/quickfix/suppress/forStatement/unavailable"), Pattern.compile("^before(\\w+)\\.kt$"), true);
}
@TestMetadata("beforeInAnnotationArgument.kt")
public void testInAnnotationArgument() throws Exception {
doTest("idea/testData/quickfix/suppress/forStatement/unavailable/beforeInAnnotationArgument.kt");
}
@TestMetadata("beforeInClassHeader.kt")
public void testInClassHeader() throws Exception {
doTest("idea/testData/quickfix/suppress/forStatement/unavailable/beforeInClassHeader.kt");
}
@TestMetadata("beforeInDefaultArgument.kt")
public void testInDefaultArgument() throws Exception {
doTest("idea/testData/quickfix/suppress/forStatement/unavailable/beforeInDefaultArgument.kt");
}
@TestMetadata("beforeInExpressionBody.kt")
public void testInExpressionBody() throws Exception {
doTest("idea/testData/quickfix/suppress/forStatement/unavailable/beforeInExpressionBody.kt");
}
@TestMetadata("beforeInLocalValInitializer.kt")
public void testInLocalValInitializer() throws Exception {
doTest("idea/testData/quickfix/suppress/forStatement/unavailable/beforeInLocalValInitializer.kt");
}
@TestMetadata("beforeInParameterType.kt")
public void testInParameterType() throws Exception {
doTest("idea/testData/quickfix/suppress/forStatement/unavailable/beforeInParameterType.kt");
}
@TestMetadata("beforeInParameterTypeInFunctionLiteral.kt")
public void testInParameterTypeInFunctionLiteral() throws Exception {
doTest("idea/testData/quickfix/suppress/forStatement/unavailable/beforeInParameterTypeInFunctionLiteral.kt");
}
@TestMetadata("beforeInPropertyInitializer.kt")
public void testInPropertyInitializer() throws Exception {
doTest("idea/testData/quickfix/suppress/forStatement/unavailable/beforeInPropertyInitializer.kt");
}
@TestMetadata("beforeObjectLiteral.kt")
public void testObjectLiteral() throws Exception {
doTest("idea/testData/quickfix/suppress/forStatement/unavailable/beforeObjectLiteral.kt");
}
@TestMetadata("beforeObjectLiteralInsideExpression.kt")
public void testObjectLiteralInsideExpression() throws Exception {
doTest("idea/testData/quickfix/suppress/forStatement/unavailable/beforeObjectLiteralInsideExpression.kt");
}
@TestMetadata("beforeSupretype.kt")
public void testSupretype() throws Exception {
doTest("idea/testData/quickfix/suppress/forStatement/unavailable/beforeSupretype.kt");
}
}
public static Test innerSuite() {
TestSuite suite = new TestSuite("ForStatement");
suite.addTestSuite(ForStatement.class);
suite.addTestSuite(Unavailable.class);
return suite;
}
}
public static Test innerSuite() {
TestSuite suite = new TestSuite("Suppress");
suite.addTestSuite(Suppress.class);
@@ -1592,6 +1865,7 @@ public class QuickFixTestGenerated extends AbstractQuickFixTest {
suite.addTestSuite(Availability.class);
suite.addTestSuite(DeclarationKinds.class);
suite.addTestSuite(ErrorRecovery.class);
suite.addTest(ForStatement.innerSuite());
return suite;
}
}