FIR IDE: Enable AddExclExclCallFix for UNSAFE_CALL,

UNSAFE_OPERATOR_CALL, UNSAFE_INFIX_CALL, ITERATOR_ON_NULLABLE,
ARGUMENT_TYPE_MISMATCH, RETURN_TYPE_MISMATCH.

TODO: Don't offer fix when target is known to be null (from data flow
analysis).
This commit is contained in:
Mark Punzalan
2021-04-25 21:39:25 +00:00
committed by Ilya Kirillov
parent 71a8d9c0bb
commit db82797f58
53 changed files with 311 additions and 42 deletions
@@ -103,6 +103,12 @@ class MainKtQuickFixRegistrar : KtQuickFixRegistrar() {
registerPsiQuickFixes(KtFirDiagnostic.UnnecessarySafeCall::class, ReplaceWithDotCallFix)
registerPsiQuickFixes(KtFirDiagnostic.UnnecessaryNotNullAssertion::class, RemoveExclExclCallFix)
registerApplicator(ReplaceCallFixFactories.unsafeCallFactory)
registerApplicator(AddExclExclCallFixFactories.unsafeCallFactory)
registerApplicator(AddExclExclCallFixFactories.unsafeInfixCallFactory)
registerApplicator(AddExclExclCallFixFactories.unsafeOperatorCallFactory)
registerApplicator(AddExclExclCallFixFactories.iteratorOnNullableFactory)
registerApplicator(TypeMismatchFactories.argumentTypeMismatchFactory)
registerApplicator(TypeMismatchFactories.returnTypeMismatchFactory)
// TODO: NON_EXHAUSTIVE_WHEN[_ON_SEALED_CLASS] will be replaced in future. We need to register the fix for those diagnostics as well
registerPsiQuickFixes(KtFirDiagnostic.NoElseInWhen::class, AddWhenElseBranchFix)
@@ -0,0 +1,96 @@
/*
* Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.idea.quickfix.fixes
import com.intellij.codeInsight.intention.IntentionAction
import com.intellij.psi.PsiElement
import org.jetbrains.kotlin.idea.fir.api.fixes.diagnosticFixFactory
import org.jetbrains.kotlin.idea.frontend.api.KtAnalysisSession
import org.jetbrains.kotlin.idea.frontend.api.fir.diagnostics.KtFirDiagnostic
import org.jetbrains.kotlin.idea.frontend.api.symbols.KtFunctionSymbol
import org.jetbrains.kotlin.idea.quickfix.AddExclExclCallFix
import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.util.OperatorNameConventions
object AddExclExclCallFixFactories {
val unsafeCallFactory = diagnosticFixFactory<KtFirDiagnostic.UnsafeCall> { diagnostic ->
getFixForUnsafeCall(diagnostic.psi)
}
val unsafeInfixCallFactory = diagnosticFixFactory<KtFirDiagnostic.UnsafeInfixCall> { diagnostic ->
getFixForUnsafeCall(diagnostic.psi)
}
val unsafeOperatorCallFactory = diagnosticFixFactory<KtFirDiagnostic.UnsafeOperatorCall> { diagnostic ->
getFixForUnsafeCall(diagnostic.psi)
}
private fun KtAnalysisSession.getFixForUnsafeCall(psi: PsiElement): List<IntentionAction> {
val (target, hasImplicitReceiver) = when (psi) {
// `foo.bar` -> `foo!!.bar`
is KtDotQualifiedExpression -> psi.receiverExpression to false
// `foo[bar]` -> `foo!![bar]`
is KtArrayAccessExpression -> psi.arrayExpression to false
is KtCallableReferenceExpression -> psi.lhs.let { lhs ->
if (lhs != null) {
// `foo::bar` -> `foo!!::bar`
lhs to false
} else {
// `::bar -> this!!::bar`
psi to true
}
}
// `bar` -> `this!!.bar`
is KtNameReferenceExpression -> psi to true
// `bar()` -> `this!!.bar()`
is KtCallExpression -> psi to true
// `-foo` -> `-foo!!`
// NOTE: Unsafe unary operator call is reported as UNSAFE_CALL, _not_ UNSAFE_OPERATOR_CALL
is KtUnaryExpression -> psi.baseExpression to false
is KtBinaryExpression -> {
val receiver = if (KtPsiUtil.isInOrNotInOperation(psi)) {
// `bar in foo` -> `bar in foo!!`
psi.right
} else {
// `foo + bar` -> `foo!! + bar` OR `foo infixFun bar` -> `foo!! infixFun bar`
psi.left
}
receiver to false
}
// UNSAFE_INFIX_CALL/UNSAFE_OPERATOR_CALL on KtBinaryExpression is reported on the child KtOperationReferenceExpression
is KtOperationReferenceExpression -> return getFixForUnsafeCall(psi.parent)
else -> return emptyList()
}
return listOfNotNull(target.asAddExclExclCallFix(hasImplicitReceiver = hasImplicitReceiver))
}
val iteratorOnNullableFactory = diagnosticFixFactory<KtFirDiagnostic.IteratorOnNullable> { diagnostic ->
val expression = diagnostic.psi as? KtExpression ?: return@diagnosticFixFactory emptyList()
val type = expression.getKtType()
if (!type.canBeNull) return@diagnosticFixFactory emptyList()
val typeScope = type.getTypeScope() ?: return@diagnosticFixFactory emptyList()
val hasValidIterator = typeScope.getCallableSymbols { it == OperatorNameConventions.ITERATOR }
.filter { it is KtFunctionSymbol && it.isOperator && it.valueParameters.isEmpty() }.singleOrNull() != null
if (hasValidIterator) {
listOfNotNull(expression.asAddExclExclCallFix())
} else {
emptyList()
}
}
}
internal fun PsiElement?.asAddExclExclCallFix(hasImplicitReceiver: Boolean = false) =
this?.let { AddExclExclCallFix(it, hasImplicitReceiver) } ?: null
@@ -0,0 +1,39 @@
/*
* Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.idea.quickfix.fixes
import com.intellij.codeInsight.intention.IntentionAction
import com.intellij.psi.PsiElement
import org.jetbrains.kotlin.idea.fir.api.fixes.diagnosticFixFactory
import org.jetbrains.kotlin.idea.frontend.api.KtAnalysisSession
import org.jetbrains.kotlin.idea.frontend.api.fir.diagnostics.KtFirDiagnostic
import org.jetbrains.kotlin.idea.frontend.api.types.KtType
import org.jetbrains.kotlin.idea.frontend.api.types.KtTypeNullability
object TypeMismatchFactories {
val argumentTypeMismatchFactory = diagnosticFixFactory<KtFirDiagnostic.ArgumentTypeMismatch> { diagnostic ->
getFixesForTypeMismatch(diagnostic.psi, diagnostic.expectedType, diagnostic.actualType)
}
val returnTypeMismatchFactory = diagnosticFixFactory<KtFirDiagnostic.ReturnTypeMismatch> { diagnostic ->
getFixesForTypeMismatch(diagnostic.psi, diagnostic.expectedType, diagnostic.actualType)
}
private fun KtAnalysisSession.getFixesForTypeMismatch(
psi: PsiElement,
expectedType: KtType,
actualType: KtType
): List<IntentionAction> {
// TODO: Add more fixes than just AddExclExclCallFix when available.
if (!expectedType.canBeNull && actualType.canBeNull) {
val nullableExpectedType = expectedType.withNullability(KtTypeNullability.NULLABLE)
if (actualType isSubTypeOf nullableExpectedType) {
return listOfNotNull(psi.asAddExclExclCallFix())
}
}
return emptyList()
}
}
@@ -264,6 +264,11 @@ public class HighLevelQuickFixTestGenerated extends AbstractHighLevelQuickFixTes
runTest("idea/testData/quickfix/addExclExclCall/implicitFunctionCall.kt");
}
@TestMetadata("infixCall.kt")
public void testInfixCall() throws Exception {
runTest("idea/testData/quickfix/addExclExclCall/infixCall.kt");
}
@TestMetadata("iterable.kt")
public void testIterable() throws Exception {
runTest("idea/testData/quickfix/addExclExclCall/iterable.kt");
@@ -299,6 +304,16 @@ public class HighLevelQuickFixTestGenerated extends AbstractHighLevelQuickFixTes
runTest("idea/testData/quickfix/addExclExclCall/operationIn.kt");
}
@TestMetadata("operationPlus.kt")
public void testOperationPlus() throws Exception {
runTest("idea/testData/quickfix/addExclExclCall/operationPlus.kt");
}
@TestMetadata("operationUnary.kt")
public void testOperationUnary() throws Exception {
runTest("idea/testData/quickfix/addExclExclCall/operationUnary.kt");
}
@TestMetadata("idea/testData/quickfix/addExclExclCall/typeMismatch")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
@@ -311,6 +326,11 @@ public class HighLevelQuickFixTestGenerated extends AbstractHighLevelQuickFixTes
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("idea/testData/quickfix/addExclExclCall/typeMismatch"), Pattern.compile("^([\\w\\-_]+)\\.kt$"), null, true);
}
@TestMetadata("argumentAfterNullCheck.kt")
public void testArgumentAfterNullCheck() throws Exception {
runTest("idea/testData/quickfix/addExclExclCall/typeMismatch/argumentAfterNullCheck.kt");
}
@TestMetadata("assignmentRValue.kt")
public void testAssignmentRValue() throws Exception {
runTest("idea/testData/quickfix/addExclExclCall/typeMismatch/assignmentRValue.kt");
@@ -326,6 +346,11 @@ public class HighLevelQuickFixTestGenerated extends AbstractHighLevelQuickFixTes
runTest("idea/testData/quickfix/addExclExclCall/typeMismatch/memberAccessInExtensionAsAssignmentRValue.kt");
}
@TestMetadata("nullArgument.kt")
public void testNullArgument() throws Exception {
runTest("idea/testData/quickfix/addExclExclCall/typeMismatch/nullArgument.kt");
}
@TestMetadata("qualifiedArgument.kt")
public void testQualifiedArgument() throws Exception {
runTest("idea/testData/quickfix/addExclExclCall/typeMismatch/qualifiedArgument.kt");
@@ -8,6 +8,7 @@ package org.jetbrains.kotlin.idea.frontend.api.components
import org.jetbrains.kotlin.idea.frontend.api.ValidityTokenOwner
import org.jetbrains.kotlin.idea.frontend.api.symbols.KtNamedClassOrObjectSymbol
import org.jetbrains.kotlin.idea.frontend.api.types.KtType
import org.jetbrains.kotlin.idea.frontend.api.types.KtTypeNullability
abstract class KtTypeProvider : KtAnalysisSessionComponent() {
abstract val builtinTypes: KtBuiltinTypes
@@ -15,6 +16,8 @@ abstract class KtTypeProvider : KtAnalysisSessionComponent() {
abstract fun approximateToSuperPublicDenotableType(type: KtType): KtType?
abstract fun buildSelfClassType(symbol: KtNamedClassOrObjectSymbol): KtType
abstract fun withNullability(type: KtType, newNullability: KtTypeNullability): KtType
}
interface KtTypeProviderMixIn : KtAnalysisSessionMixIn {
@@ -32,6 +35,9 @@ interface KtTypeProviderMixIn : KtAnalysisSessionMixIn {
fun KtNamedClassOrObjectSymbol.buildSelfClassType(): KtType =
analysisSession.typeProvider.buildSelfClassType(this)
fun KtType.withNullability(newNullability: KtTypeNullability): KtType =
analysisSession.typeProvider.withNullability(this, newNullability)
}
@Suppress("PropertyName")
@@ -6,25 +6,27 @@
package org.jetbrains.kotlin.idea.frontend.api.fir.components
import org.jetbrains.kotlin.fir.declarations.FirResolvePhase
import org.jetbrains.kotlin.fir.typeContext
import org.jetbrains.kotlin.fir.types.impl.ConeClassLikeTypeImpl
import org.jetbrains.kotlin.fir.types.impl.ConeTypeParameterTypeImpl
import org.jetbrains.kotlin.idea.frontend.api.tokens.ValidityToken
import org.jetbrains.kotlin.fir.types.withNullability
import org.jetbrains.kotlin.idea.frontend.api.components.KtBuiltinTypes
import org.jetbrains.kotlin.idea.frontend.api.components.KtTypeProvider
import org.jetbrains.kotlin.idea.frontend.api.fir.KtFirAnalysisSession
import org.jetbrains.kotlin.idea.frontend.api.fir.symbols.KtFirNamedClassOrObjectSymbol
import org.jetbrains.kotlin.idea.frontend.api.fir.types.KtFirType
import org.jetbrains.kotlin.idea.frontend.api.fir.types.PublicTypeApproximator
import org.jetbrains.kotlin.idea.frontend.api.symbols.KtClassOrObjectSymbol
import org.jetbrains.kotlin.idea.frontend.api.fir.utils.toConeNullability
import org.jetbrains.kotlin.idea.frontend.api.symbols.KtNamedClassOrObjectSymbol
import org.jetbrains.kotlin.idea.frontend.api.tokens.ValidityToken
import org.jetbrains.kotlin.idea.frontend.api.types.KtType
import org.jetbrains.kotlin.idea.frontend.api.types.KtTypeNullability
internal class KtFirTypeProvider(
override val analysisSession: KtFirAnalysisSession,
override val token: ValidityToken,
) : KtTypeProvider(), KtFirAnalysisSessionComponent {
override val builtinTypes: KtBuiltinTypes =
KtFirBuiltInTypes(analysisSession.firResolveState.rootModuleSession.builtinTypes, analysisSession.firSymbolBuilder, token)
override val builtinTypes: KtBuiltinTypes = KtFirBuiltInTypes(rootModuleSession.builtinTypes, firSymbolBuilder, token)
override fun approximateToSuperPublicDenotableType(type: KtType): KtType? {
require(type is KtFirType)
@@ -49,5 +51,10 @@ internal class KtFirTypeProvider(
}
return type.asKtType()
}
override fun withNullability(type: KtType, newNullability: KtTypeNullability): KtType {
require(type is KtFirType)
return type.coneType.withNullability(newNullability.toConeNullability(), rootModuleSession.typeContext).asKtType()
}
}
@@ -13,10 +13,12 @@ import org.jetbrains.kotlin.fir.expressions.FirExpression
import org.jetbrains.kotlin.fir.expressions.FirNamedArgumentExpression
import org.jetbrains.kotlin.fir.resolve.toSymbol
import org.jetbrains.kotlin.fir.types.ConeClassLikeType
import org.jetbrains.kotlin.fir.types.ConeNullability
import org.jetbrains.kotlin.fir.types.coneType
import org.jetbrains.kotlin.idea.frontend.api.symbols.markers.KtConstantValue
import org.jetbrains.kotlin.idea.frontend.api.symbols.markers.KtSimpleConstantValue
import org.jetbrains.kotlin.idea.frontend.api.symbols.markers.KtUnsupportedConstantValue
import org.jetbrains.kotlin.idea.frontend.api.types.KtTypeNullability
internal fun mapAnnotationParameters(annotationCall: FirAnnotationCall, session: FirSession): Map<String, FirExpression> {
@@ -55,3 +57,8 @@ internal fun FirExpression.convertConstantExpression(): KtConstantValue =
is FirConstExpression<*> -> convertConstantExpression()
else -> KtUnsupportedConstantValue
}
internal fun KtTypeNullability.toConeNullability() = when (this) {
KtTypeNullability.NULLABLE -> ConeNullability.NULLABLE
KtTypeNullability.NON_NULLABLE -> ConeNullability.NOT_NULL
}
@@ -5,4 +5,6 @@ class Foo {
fun test(foo: Foo?) {
val f = foo::f<caret>
}
}
// TODO: Enable when FIR reports UNSAFE_CALL for function reference on nullable (currently UNRESOLVED_REFERENCE)
/* IGNORE_FIR */
@@ -5,4 +5,6 @@ class Foo {
fun test(foo: Foo?) {
val f = foo!!::f
}
}
// TODO: Enable when FIR reports UNSAFE_CALL for function reference on nullable (currently UNRESOLVED_REFERENCE)
/* IGNORE_FIR */
@@ -9,4 +9,6 @@ class Bar {
fun test(foo: Foo?) {
val f = foo?.bar::f<caret>
}
}
// TODO: Enable when FIR reports UNSAFE_CALL for function reference on nullable (currently UNRESOLVED_REFERENCE)
/* IGNORE_FIR */
@@ -9,4 +9,6 @@ class Bar {
fun test(foo: Foo?) {
val f = foo?.bar!!::f
}
}
// TODO: Enable when FIR reports UNSAFE_CALL for function reference on nullable (currently UNRESOLVED_REFERENCE)
/* IGNORE_FIR */
@@ -5,4 +5,6 @@ class Foo {
fun Foo?.test() {
val f = ::f<caret>
}
}
// TODO: Enable when FIR reports UNSAFE_CALL for function reference on nullable (currently UNRESOLVED_REFERENCE)
/* IGNORE_FIR */
@@ -5,4 +5,6 @@ class Foo {
fun Foo?.test() {
val f = this!!::f
}
}
// TODO: Enable when FIR reports UNSAFE_CALL for function reference on nullable (currently UNRESOLVED_REFERENCE)
/* IGNORE_FIR */
+7
View File
@@ -0,0 +1,7 @@
// "Add non-null asserted (!!) call" "true"
infix fun Int.bar(i: Int) = this
fun foo(i: Int?) {
i <caret>bar 1
}
@@ -0,0 +1,7 @@
// "Add non-null asserted (!!) call" "true"
infix fun Int.bar(i: Int) = this
fun foo(i: Int?) {
i!! bar 1
}
@@ -0,0 +1,5 @@
// "Add non-null asserted (!!) call" "true"
fun foo(i: Int?) {
i <caret>+ 1
}
@@ -0,0 +1,5 @@
// "Add non-null asserted (!!) call" "true"
fun foo(i: Int?) {
i!! + 1
}
@@ -0,0 +1,5 @@
// "Add non-null asserted (!!) call" "true"
fun foo(i: Int?) {
<caret>-i
}
@@ -0,0 +1,5 @@
// "Add non-null asserted (!!) call" "true"
fun foo(i: Int?) {
-i!!
}
@@ -0,0 +1,18 @@
// "Add non-null asserted (!!) call" "false"
// ACTION: Add 'i =' to argument
// ACTION: Change parameter 'i' type of function 'other' to 'Int?'
// ACTION: Create function 'other'
// ACTION: Remove braces from 'if' statement
// ACTION: Surround with null check
// ACTION: Wrap with '?.let { ... }' call
// ERROR: Type mismatch: inferred type is Nothing? but Int was expected
fun test(i: Int?) {
if (i == null) {
other(<caret>i)
}
}
fun other(i: Int) {}
// TODO: Need data flow info from null check
/* IGNORE_FIR */
@@ -3,3 +3,5 @@ fun test() {
val s: String? = null
val z: String = <caret>s
}
// TODO: Enable when FIR reports TYPE_MISMATCH for assignments
/* IGNORE_FIR */
@@ -3,3 +3,5 @@ fun test() {
val s: String? = null
val z: String = s!!
}
// TODO: Enable when FIR reports TYPE_MISMATCH for assignments
/* IGNORE_FIR */
@@ -7,3 +7,5 @@ class C {
fun C.test() {
val z: String = <caret>s
}
// TODO: Enable when FIR reports TYPE_MISMATCH for assignments
/* IGNORE_FIR */
@@ -7,3 +7,5 @@ class C {
fun C.test() {
val z: String = s!!
}
// TODO: Enable when FIR reports TYPE_MISMATCH for assignments
/* IGNORE_FIR */
@@ -0,0 +1,10 @@
// "Add non-null asserted (!!) call" "false"
// ACTION: Add 'i =' to argument
// ACTION: Change parameter 'i' type of function 'other' to 'Int?'
// ACTION: Do not show hints for current method
// ERROR: Null can not be a value of a non-null type Int
fun test() {
other(<caret>null)
}
fun other(i: Int) {}
@@ -1,6 +1,8 @@
// "class org.jetbrains.kotlin.idea.quickfix.AddExclExclCallFix" "false"
// "Add non-null asserted (!!) call" "false"
// ACTION: Change parameter 's' type of function 'other' to 'String?'
// ACTION: Create function 'other'
// ACTION: Convert to also
// ACTION: Convert to apply
// ERROR: Type mismatch: inferred type is String? but Int was expected
fun test() {
val s: String? = ""
@@ -14,4 +14,5 @@ open class MyClass {
}
}
}
// TODO: Enable when FIR reports SMARTCAST_IMPOSSIBLE
/* IGNORE_FIR */
@@ -14,4 +14,5 @@ open class MyClass {
}
}
}
// TODO: Enable when FIR reports SMARTCAST_IMPOSSIBLE
/* IGNORE_FIR */
@@ -7,4 +7,3 @@ class SafeType {
fun safeB(p: SafeType?) {
val v = p <caret>+ 42
}
/* IGNORE_FIR */
@@ -7,4 +7,3 @@ class SafeType {
fun safeB(p: SafeType?) {
val v = p!! + 42
}
/* IGNORE_FIR */
@@ -7,4 +7,3 @@ class SafeType {
fun safeB(p: SafeType?) {
val v = p <caret>op 42
}
/* IGNORE_FIR */
@@ -7,4 +7,3 @@ class SafeType {
fun safeB(p: SafeType?) {
val v = p!! op 42
}
/* IGNORE_FIR */
@@ -3,4 +3,3 @@ fun <T: Collection<Int>?> foo(c: T) {
for (i in <caret>c) { }
}
/* IGNORE_FIR */
@@ -3,4 +3,3 @@ fun <T: Collection<Int>?> foo(c: T) {
for (i in c!!) { }
}
/* IGNORE_FIR */
@@ -4,4 +4,3 @@ fun foo() {
for (i in <caret>test) { }
}
/* IGNORE_FIR */
@@ -4,4 +4,3 @@ fun foo() {
for (i in <caret>test!!) { }
}
/* IGNORE_FIR */
@@ -7,4 +7,3 @@ class SafeType {
fun safeB(p: SafeType?) {
val v = <caret>-p
}
/* IGNORE_FIR */
@@ -7,4 +7,3 @@ class SafeType {
fun safeB(p: SafeType?) {
val v = -p!!
}
/* IGNORE_FIR */
@@ -1,4 +1,4 @@
// "class org.jetbrains.kotlin.idea.quickfix.AddExclExclCallFix" "false"
// "Add non-null asserted (!!) call" "false"
// ACTION: Replace with a 'forEach' function call
// ACTION: Surround with null check
// ERROR: Not nullable value required to call an 'iterator()' method on for-loop range
@@ -7,5 +7,3 @@ fun foo() {
val test: Some? = Some()
for (i in <caret>test) { }
}
/* IGNORE_FIR */
@@ -7,5 +7,3 @@ fun foo() {
val test: Some? = Some()
for (i in test!!) { }
}
/* IGNORE_FIR */
-1
View File
@@ -5,4 +5,3 @@ fun callMe(p: String) {}
fun callIt(p: Any) {
callMe(<caret>p as String?)
}
/* IGNORE_FIR */
-1
View File
@@ -5,4 +5,3 @@ fun callMe(p: String) {}
fun callIt(p: Any) {
callMe(<caret>(p as String?)!!)
}
/* IGNORE_FIR */
-2
View File
@@ -2,5 +2,3 @@
fun foo(a: Int?) {
a<caret>.plus(1)
}
/* IGNORE_FIR */
@@ -2,5 +2,3 @@
fun foo(a: Int?) {
a!!.plus(1)
}
/* IGNORE_FIR */
-2
View File
@@ -2,5 +2,3 @@
fun foo(a: Int?) {
a.<caret>plus(1)
}
/* IGNORE_FIR */
@@ -2,5 +2,3 @@
fun foo(a: Int?) {
a!!.plus(1)
}
/* IGNORE_FIR */
-1
View File
@@ -2,4 +2,3 @@
operator fun Int.get(row: Int, column: Int) = this
fun foo(arg: Int?) = arg<caret>[42, 13]
/* IGNORE_FIR */
@@ -2,4 +2,3 @@
operator fun Int.get(row: Int, column: Int) = this
fun foo(arg: Int?) = arg!![42, 13]
/* IGNORE_FIR */
-1
View File
@@ -2,4 +2,3 @@
operator fun Int.get(row: Int, column: Int) = if (row == column) this else null
fun foo(arg: Int) = arg[42, 13]<caret>.hashCode()
/* IGNORE_FIR */
@@ -2,4 +2,3 @@
operator fun Int.get(row: Int, column: Int) = if (row == column) this else null
fun foo(arg: Int) = arg[42, 13]!!.hashCode()
/* IGNORE_FIR */
@@ -677,6 +677,11 @@ public class QuickFixTestGenerated extends AbstractQuickFixTest {
runTest("idea/testData/quickfix/addExclExclCall/implicitFunctionCall.kt");
}
@TestMetadata("infixCall.kt")
public void testInfixCall() throws Exception {
runTest("idea/testData/quickfix/addExclExclCall/infixCall.kt");
}
@TestMetadata("iterable.kt")
public void testIterable() throws Exception {
runTest("idea/testData/quickfix/addExclExclCall/iterable.kt");
@@ -712,6 +717,16 @@ public class QuickFixTestGenerated extends AbstractQuickFixTest {
runTest("idea/testData/quickfix/addExclExclCall/operationIn.kt");
}
@TestMetadata("operationPlus.kt")
public void testOperationPlus() throws Exception {
runTest("idea/testData/quickfix/addExclExclCall/operationPlus.kt");
}
@TestMetadata("operationUnary.kt")
public void testOperationUnary() throws Exception {
runTest("idea/testData/quickfix/addExclExclCall/operationUnary.kt");
}
@TestMetadata("idea/testData/quickfix/addExclExclCall/typeMismatch")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
@@ -724,6 +739,11 @@ public class QuickFixTestGenerated extends AbstractQuickFixTest {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("idea/testData/quickfix/addExclExclCall/typeMismatch"), Pattern.compile("^([\\w\\-_]+)\\.kt$"), null, true);
}
@TestMetadata("argumentAfterNullCheck.kt")
public void testArgumentAfterNullCheck() throws Exception {
runTest("idea/testData/quickfix/addExclExclCall/typeMismatch/argumentAfterNullCheck.kt");
}
@TestMetadata("assignmentRValue.kt")
public void testAssignmentRValue() throws Exception {
runTest("idea/testData/quickfix/addExclExclCall/typeMismatch/assignmentRValue.kt");
@@ -739,6 +759,11 @@ public class QuickFixTestGenerated extends AbstractQuickFixTest {
runTest("idea/testData/quickfix/addExclExclCall/typeMismatch/memberAccessInExtensionAsAssignmentRValue.kt");
}
@TestMetadata("nullArgument.kt")
public void testNullArgument() throws Exception {
runTest("idea/testData/quickfix/addExclExclCall/typeMismatch/nullArgument.kt");
}
@TestMetadata("qualifiedArgument.kt")
public void testQualifiedArgument() throws Exception {
runTest("idea/testData/quickfix/addExclExclCall/typeMismatch/qualifiedArgument.kt");