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:
committed by
Ilya Kirillov
parent
71a8d9c0bb
commit
db82797f58
@@ -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)
|
||||
|
||||
+96
@@ -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()
|
||||
}
|
||||
}
|
||||
Generated
+25
@@ -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");
|
||||
|
||||
+6
@@ -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")
|
||||
|
||||
+11
-4
@@ -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()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+7
@@ -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 */
|
||||
|
||||
@@ -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!!
|
||||
}
|
||||
+18
@@ -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 */
|
||||
|
||||
Vendored
+2
@@ -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 */
|
||||
|
||||
+2
@@ -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) {}
|
||||
Vendored
+3
-1
@@ -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? = ""
|
||||
|
||||
+2
-1
@@ -14,4 +14,5 @@ open class MyClass {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: Enable when FIR reports SMARTCAST_IMPOSSIBLE
|
||||
/* IGNORE_FIR */
|
||||
|
||||
+2
-1
@@ -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 */
|
||||
-1
@@ -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
-1
@@ -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 */
|
||||
-2
@@ -7,5 +7,3 @@ fun foo() {
|
||||
val test: Some? = Some()
|
||||
for (i in test!!) { }
|
||||
}
|
||||
|
||||
/* IGNORE_FIR */
|
||||
@@ -5,4 +5,3 @@ fun callMe(p: String) {}
|
||||
fun callIt(p: Any) {
|
||||
callMe(<caret>p as String?)
|
||||
}
|
||||
/* IGNORE_FIR */
|
||||
@@ -5,4 +5,3 @@ fun callMe(p: String) {}
|
||||
fun callIt(p: Any) {
|
||||
callMe(<caret>(p as String?)!!)
|
||||
}
|
||||
/* IGNORE_FIR */
|
||||
@@ -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,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,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 */
|
||||
@@ -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");
|
||||
|
||||
Reference in New Issue
Block a user