mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
[kotlin] Added quick fixes for warnings introduced in 1.6.20 or earlier
Registered quick fixes for warnings that are mostly related to Java nullability mismatch. ^KTIJ-20827 Fixed (cherry picked from commit 7d5bbcd3aa9b16a6a60bab0f1e3f7978622b7c49) GitOrigin-RevId: c79a1e985970792a932371e7c1b57354fa2575d5
This commit is contained in:
committed by
intellij-monorepo-bot
parent
5e91e7fb01
commit
3f52503ac3
@@ -55,6 +55,7 @@ fun getAddExclExclCallFix(element: PsiElement?, checkImplicitReceivers: Boolean
|
||||
is KtExpression -> {
|
||||
val parent = psiElement.parent
|
||||
val context = psiElement.analyze()
|
||||
|
||||
if (checkImplicitReceivers && psiElement.getResolvedCall(context)?.getImplicitReceiverValue() is ExtensionReceiver) {
|
||||
val expressionToReplace = parent as? KtCallExpression ?: parent as? KtCallableReferenceExpression ?: psiElement
|
||||
expressionToReplace.asFix(implicitReceiver = true)
|
||||
|
||||
@@ -247,6 +247,7 @@ class AddFunctionParametersFix(
|
||||
val element = DiagnosticFactory.cast(
|
||||
this,
|
||||
Errors.TYPE_MISMATCH,
|
||||
Errors.TYPE_MISMATCH_WARNING,
|
||||
Errors.CONSTANT_EXPECTED_TYPE_MISMATCH,
|
||||
Errors.NULL_FOR_NONNULL_TYPE,
|
||||
).psiElement
|
||||
|
||||
@@ -73,6 +73,10 @@ class AddGenericUpperBoundFix(
|
||||
val inferenceData = Errors.TYPE_INFERENCE_UPPER_BOUND_VIOLATED.cast(diagnostic).a
|
||||
createActionsByInferenceData(inferenceData)
|
||||
}
|
||||
ErrorsJvm.UPPER_BOUND_VIOLATED_BASED_ON_JAVA_ANNOTATIONS -> {
|
||||
val upperBoundViolated = ErrorsJvm.UPPER_BOUND_VIOLATED_BASED_ON_JAVA_ANNOTATIONS.cast(diagnostic)
|
||||
listOfNotNull(createAction(upperBoundViolated.b, upperBoundViolated.a))
|
||||
}
|
||||
else -> emptyList()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -69,6 +69,7 @@ class ChangeToLabeledReturnFix(
|
||||
Errors.RETURN_NOT_ALLOWED ->
|
||||
diagnostic.psiElement as? KtReturnExpression
|
||||
Errors.TYPE_MISMATCH,
|
||||
Errors.TYPE_MISMATCH_WARNING,
|
||||
Errors.CONSTANT_EXPECTED_TYPE_MISMATCH,
|
||||
Errors.NULL_FOR_NONNULL_TYPE ->
|
||||
getLambdaReturnExpression(diagnostic.psiElement, context)
|
||||
|
||||
@@ -24,6 +24,7 @@ import org.jetbrains.kotlin.psi.*
|
||||
import org.jetbrains.kotlin.psi.psiUtil.getStrictParentOfType
|
||||
import org.jetbrains.kotlin.resolve.BindingContext
|
||||
import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils
|
||||
import org.jetbrains.kotlin.resolve.jvm.diagnostics.ErrorsJvm
|
||||
import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode
|
||||
import org.jetbrains.kotlin.types.ErrorUtils
|
||||
import org.jetbrains.kotlin.types.KotlinType
|
||||
@@ -166,7 +167,14 @@ open class ChangeVariableTypeFix(element: KtCallableDeclaration, type: KotlinTyp
|
||||
if (binaryExpression.operationToken != KtTokens.EQ) return null
|
||||
val property = left.mainReference?.resolve() as? KtProperty ?: return null
|
||||
if (!property.isVar || property.typeReference != null || !property.initializer.isNullExpression()) return null
|
||||
return ChangeVariableTypeFix(property, Errors.TYPE_MISMATCH.cast(diagnostic).b.makeNullable())
|
||||
val actualType = when (diagnostic.factory) {
|
||||
Errors.TYPE_MISMATCH -> Errors.TYPE_MISMATCH.cast(diagnostic).b
|
||||
Errors.TYPE_MISMATCH_WARNING -> Errors.TYPE_MISMATCH_WARNING.cast(diagnostic).b
|
||||
ErrorsJvm.NULLABILITY_MISMATCH_BASED_ON_JAVA_ANNOTATIONS ->
|
||||
ErrorsJvm.NULLABILITY_MISMATCH_BASED_ON_JAVA_ANNOTATIONS.cast(diagnostic).b
|
||||
else -> null
|
||||
} ?: return null
|
||||
return ChangeVariableTypeFix(property, actualType.makeNullable())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+18
-3
@@ -5,12 +5,10 @@ package org.jetbrains.kotlin.idea.quickfix
|
||||
import com.intellij.codeInsight.intention.IntentionAction
|
||||
import com.intellij.openapi.diagnostic.Logger
|
||||
import com.intellij.psi.util.PsiTreeUtil
|
||||
import org.jetbrains.kotlin.backend.jvm.ir.psiElement
|
||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
||||
import org.jetbrains.kotlin.builtins.isKFunctionType
|
||||
import org.jetbrains.kotlin.config.LanguageFeature
|
||||
import org.jetbrains.kotlin.descriptors.CallableDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.DeclarationDescriptorWithSource
|
||||
import org.jetbrains.kotlin.diagnostics.Diagnostic
|
||||
import org.jetbrains.kotlin.diagnostics.Errors
|
||||
import org.jetbrains.kotlin.diagnostics.rendering.DefaultErrorMessages
|
||||
@@ -37,6 +35,7 @@ import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall
|
||||
import org.jetbrains.kotlin.resolve.constants.IntegerValueTypeConstant
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.module
|
||||
import org.jetbrains.kotlin.resolve.jvm.diagnostics.ErrorsJvm
|
||||
import org.jetbrains.kotlin.types.CommonSupertypes
|
||||
import org.jetbrains.kotlin.types.KotlinType
|
||||
import org.jetbrains.kotlin.types.TypeUtils
|
||||
@@ -69,6 +68,11 @@ class QuickFixFactoryForTypeMismatchError : KotlinIntentionActionsFactory() {
|
||||
expectedType = diagnosticWithParameters.a
|
||||
expressionType = diagnosticWithParameters.b
|
||||
}
|
||||
Errors.TYPE_MISMATCH_WARNING -> {
|
||||
val diagnosticWithParameters = Errors.TYPE_MISMATCH_WARNING.cast(diagnostic)
|
||||
expectedType = diagnosticWithParameters.a
|
||||
expressionType = diagnosticWithParameters.b
|
||||
}
|
||||
Errors.NULL_FOR_NONNULL_TYPE -> {
|
||||
val diagnosticWithParameters = Errors.NULL_FOR_NONNULL_TYPE.cast(diagnostic)
|
||||
expectedType = diagnosticWithParameters.a
|
||||
@@ -96,6 +100,11 @@ class QuickFixFactoryForTypeMismatchError : KotlinIntentionActionsFactory() {
|
||||
expressionType = signedConstantValue.getType(NO_EXPECTED_TYPE)
|
||||
} else return emptyList()
|
||||
}
|
||||
ErrorsJvm.NULLABILITY_MISMATCH_BASED_ON_JAVA_ANNOTATIONS -> {
|
||||
val diagnosticWithParameters = ErrorsJvm.NULLABILITY_MISMATCH_BASED_ON_JAVA_ANNOTATIONS.cast(diagnostic)
|
||||
expectedType = diagnosticWithParameters.a
|
||||
expressionType = diagnosticWithParameters.b
|
||||
}
|
||||
else -> {
|
||||
LOG.error("Unexpected diagnostic: " + DefaultErrorMessages.render(diagnostic))
|
||||
return emptyList()
|
||||
@@ -165,7 +174,13 @@ class QuickFixFactoryForTypeMismatchError : KotlinIntentionActionsFactory() {
|
||||
val nullableExpected = expectedType.makeNullable()
|
||||
if (expressionType.isSubtypeOf(nullableExpected)) {
|
||||
val targetExpression = diagnosticElement.getTopMostQualifiedForSelectorIfAny()
|
||||
getAddExclExclCallFix(targetExpression)?.let { actions.add(it) }
|
||||
// With implicit receivers (e.g., inside a scope function),
|
||||
// NULLABILITY_MISMATCH_BASED_ON_JAVA_ANNOTATIONS is reported on the callee, so we need
|
||||
// to explicitly check for nullable implicit receiver
|
||||
val checkCalleeExpression =
|
||||
diagnostic.factory == ErrorsJvm.NULLABILITY_MISMATCH_BASED_ON_JAVA_ANNOTATIONS &&
|
||||
targetExpression.parent?.safeAs<KtCallExpression>()?.calleeExpression == targetExpression
|
||||
getAddExclExclCallFix(targetExpression, checkCalleeExpression)?.let { actions.add(it) }
|
||||
if (expectedType.isBoolean()) {
|
||||
actions.add(AddEqEqTrueFix(targetExpression))
|
||||
}
|
||||
|
||||
@@ -163,6 +163,7 @@ class QuickFixRegistrar : QuickFixContributor {
|
||||
TOO_MANY_ARGUMENTS.registerFactory(ImportForMismatchingArgumentsFix)
|
||||
NO_VALUE_FOR_PARAMETER.registerFactory(ImportForMismatchingArgumentsFix)
|
||||
TYPE_MISMATCH.registerFactory(ImportForMismatchingArgumentsFix)
|
||||
TYPE_MISMATCH_WARNING.registerFactory(ImportForMismatchingArgumentsFix)
|
||||
CONSTANT_EXPECTED_TYPE_MISMATCH.registerFactory(ImportForMismatchingArgumentsFix)
|
||||
NAMED_PARAMETER_NOT_FOUND.registerFactory(ImportForMismatchingArgumentsFix)
|
||||
NONE_APPLICABLE.registerFactory(ImportForMismatchingArgumentsFix)
|
||||
@@ -245,6 +246,8 @@ class QuickFixRegistrar : QuickFixContributor {
|
||||
UNNECESSARY_SAFE_CALL.registerFactory(Fe10ReplaceWithDotCallFixFactory)
|
||||
UNSAFE_CALL.registerFactory(ReplaceWithSafeCallFixFactory)
|
||||
SAFE_CALL_WILL_CHANGE_NULLABILITY.registerFactory(Fe10ReplaceWithDotCallFixFactory)
|
||||
RECEIVER_NULLABILITY_MISMATCH_BASED_ON_JAVA_ANNOTATIONS.registerFactory(ReplaceWithSafeCallFixFactory)
|
||||
NULLABILITY_MISMATCH_BASED_ON_JAVA_ANNOTATIONS.registerFactory(ReplaceWithSafeCallFixFactory)
|
||||
|
||||
UNSAFE_CALL.registerFactory(SurroundWithNullCheckFix)
|
||||
UNSAFE_IMPLICIT_INVOKE_CALL.registerFactory(SurroundWithNullCheckFix)
|
||||
@@ -252,12 +255,18 @@ class QuickFixRegistrar : QuickFixContributor {
|
||||
UNSAFE_OPERATOR_CALL.registerFactory(SurroundWithNullCheckFix)
|
||||
ITERATOR_ON_NULLABLE.registerFactory(SurroundWithNullCheckFix.IteratorOnNullableFactory)
|
||||
TYPE_MISMATCH.registerFactory(SurroundWithNullCheckFix.TypeMismatchFactory)
|
||||
TYPE_MISMATCH_WARNING.registerFactory(SurroundWithNullCheckFix.TypeMismatchFactory)
|
||||
RECEIVER_NULLABILITY_MISMATCH_BASED_ON_JAVA_ANNOTATIONS.registerFactory(SurroundWithNullCheckFix)
|
||||
NULLABILITY_MISMATCH_BASED_ON_JAVA_ANNOTATIONS.registerFactory(SurroundWithNullCheckFix.TypeMismatchFactory)
|
||||
|
||||
UNSAFE_CALL.registerFactory(WrapWithSafeLetCallFix.UnsafeFactory)
|
||||
UNSAFE_IMPLICIT_INVOKE_CALL.registerFactory(WrapWithSafeLetCallFix.UnsafeFactory)
|
||||
UNSAFE_INFIX_CALL.registerFactory(WrapWithSafeLetCallFix.UnsafeFactory)
|
||||
UNSAFE_OPERATOR_CALL.registerFactory(WrapWithSafeLetCallFix.UnsafeFactory)
|
||||
TYPE_MISMATCH.registerFactory(WrapWithSafeLetCallFix.TypeMismatchFactory)
|
||||
TYPE_MISMATCH_WARNING.registerFactory(WrapWithSafeLetCallFix.TypeMismatchFactory)
|
||||
RECEIVER_NULLABILITY_MISMATCH_BASED_ON_JAVA_ANNOTATIONS.registerFactory(WrapWithSafeLetCallFix.UnsafeFactory)
|
||||
NULLABILITY_MISMATCH_BASED_ON_JAVA_ANNOTATIONS.registerFactory(WrapWithSafeLetCallFix.TypeMismatchFactory)
|
||||
|
||||
UNSAFE_CALL.registerFactory(UnsafeCallExclExclFixFactory)
|
||||
UNSAFE_INFIX_CALL.registerFactory(UnsafeCallExclExclFixFactory)
|
||||
@@ -268,6 +277,9 @@ class QuickFixRegistrar : QuickFixContributor {
|
||||
UNSAFE_CALL.registerFactory(ReplaceInfixOrOperatorCallFixFactory) // [] only
|
||||
UNSAFE_IMPLICIT_INVOKE_CALL.registerFactory(ReplaceInfixOrOperatorCallFixFactory)
|
||||
UNSAFE_CALL.registerFactory(ReplaceWithSafeCallForScopeFunctionFixFactory)
|
||||
RECEIVER_NULLABILITY_MISMATCH_BASED_ON_JAVA_ANNOTATIONS.registerFactory(UnsafeCallExclExclFixFactory)
|
||||
RECEIVER_NULLABILITY_MISMATCH_BASED_ON_JAVA_ANNOTATIONS.registerFactory(ReplaceInfixOrOperatorCallFixFactory)
|
||||
RECEIVER_NULLABILITY_MISMATCH_BASED_ON_JAVA_ANNOTATIONS.registerFactory(ReplaceWithSafeCallForScopeFunctionFixFactory)
|
||||
|
||||
AMBIGUOUS_ANONYMOUS_TYPE_INFERRED.registerActions(SpecifyTypeExplicitlyFix())
|
||||
PROPERTY_WITH_NO_TYPE_NO_INITIALIZER.registerActions(SpecifyTypeExplicitlyFix())
|
||||
@@ -315,6 +327,7 @@ class QuickFixRegistrar : QuickFixContributor {
|
||||
VAR_TYPE_MISMATCH_ON_OVERRIDE.registerFactory(changeVariableTypeFix)
|
||||
COMPONENT_FUNCTION_RETURN_TYPE_MISMATCH.registerFactory(ChangeVariableTypeFix.ComponentFunctionReturnTypeMismatchFactory)
|
||||
TYPE_MISMATCH.registerFactory(ChangeVariableTypeFix.VariableInitializedWithNullFactory)
|
||||
TYPE_MISMATCH_WARNING.registerFactory(ChangeVariableTypeFix.VariableInitializedWithNullFactory)
|
||||
|
||||
val changeFunctionReturnTypeFix = ChangeCallableReturnTypeFix.ChangingReturnTypeToUnitFactory
|
||||
RETURN_TYPE_MISMATCH.registerFactory(changeFunctionReturnTypeFix)
|
||||
@@ -334,6 +347,7 @@ class QuickFixRegistrar : QuickFixContributor {
|
||||
NO_VALUE_FOR_PARAMETER.registerFactory(ChangeFunctionSignatureFix)
|
||||
|
||||
TYPE_MISMATCH.registerFactory(AddFunctionParametersFix)
|
||||
TYPE_MISMATCH_WARNING.registerFactory(AddFunctionParametersFix)
|
||||
CONSTANT_EXPECTED_TYPE_MISMATCH.registerFactory(AddFunctionParametersFix)
|
||||
NULL_FOR_NONNULL_TYPE.registerFactory(AddFunctionParametersFix)
|
||||
|
||||
@@ -359,6 +373,7 @@ class QuickFixRegistrar : QuickFixContributor {
|
||||
NO_VALUE_FOR_PARAMETER.registerFactory(CreateBinaryOperationActionFactory)
|
||||
TOO_MANY_ARGUMENTS.registerFactory(CreateBinaryOperationActionFactory)
|
||||
TYPE_MISMATCH_ERRORS.forEach { it.registerFactory(CreateBinaryOperationActionFactory) }
|
||||
TYPE_MISMATCH_WARNING.registerFactory(CreateBinaryOperationActionFactory)
|
||||
|
||||
UNRESOLVED_REFERENCE_WRONG_RECEIVER.registerFactory(*CreateCallableFromCallActionFactory.INSTANCES)
|
||||
UNRESOLVED_REFERENCE.registerFactory(*CreateCallableFromCallActionFactory.INSTANCES)
|
||||
@@ -368,6 +383,7 @@ class QuickFixRegistrar : QuickFixContributor {
|
||||
EXPRESSION_EXPECTED_PACKAGE_FOUND.registerFactory(*CreateCallableFromCallActionFactory.INSTANCES)
|
||||
NONE_APPLICABLE.registerFactory(*CreateCallableFromCallActionFactory.INSTANCES)
|
||||
TYPE_MISMATCH.registerFactory(*CreateCallableFromCallActionFactory.FUNCTIONS)
|
||||
TYPE_MISMATCH_WARNING.registerFactory(*CreateCallableFromCallActionFactory.FUNCTIONS)
|
||||
|
||||
NO_VALUE_FOR_PARAMETER.registerFactory(CreateConstructorFromDelegationCallActionFactory)
|
||||
TOO_MANY_ARGUMENTS.registerFactory(CreateConstructorFromDelegationCallActionFactory)
|
||||
@@ -393,10 +409,12 @@ class QuickFixRegistrar : QuickFixContributor {
|
||||
|
||||
val factoryForTypeMismatchError = QuickFixFactoryForTypeMismatchError()
|
||||
TYPE_MISMATCH.registerFactory(factoryForTypeMismatchError)
|
||||
TYPE_MISMATCH_WARNING.registerFactory(factoryForTypeMismatchError)
|
||||
NULL_FOR_NONNULL_TYPE.registerFactory(factoryForTypeMismatchError)
|
||||
CONSTANT_EXPECTED_TYPE_MISMATCH.registerFactory(factoryForTypeMismatchError)
|
||||
TYPE_INFERENCE_EXPECTED_TYPE_MISMATCH.registerFactory(factoryForTypeMismatchError)
|
||||
SIGNED_CONSTANT_CONVERTED_TO_UNSIGNED.registerFactory(factoryForTypeMismatchError)
|
||||
NULLABILITY_MISMATCH_BASED_ON_JAVA_ANNOTATIONS.registerFactory(factoryForTypeMismatchError)
|
||||
|
||||
SMARTCAST_IMPOSSIBLE.registerFactory(SmartCastImpossibleExclExclFixFactory)
|
||||
SMARTCAST_IMPOSSIBLE.registerFactory(CastExpressionFix.SmartCastImpossibleFactory)
|
||||
@@ -408,8 +426,10 @@ class QuickFixRegistrar : QuickFixContributor {
|
||||
|
||||
NO_GET_METHOD.registerFactory(CreateGetFunctionActionFactory)
|
||||
TYPE_MISMATCH_ERRORS.forEach { it.registerFactory(CreateGetFunctionActionFactory) }
|
||||
TYPE_MISMATCH_WARNING.registerFactory(CreateGetFunctionActionFactory)
|
||||
NO_SET_METHOD.registerFactory(CreateSetFunctionActionFactory)
|
||||
TYPE_MISMATCH_ERRORS.forEach { it.registerFactory(CreateSetFunctionActionFactory) }
|
||||
TYPE_MISMATCH_WARNING.registerFactory(CreateSetFunctionActionFactory)
|
||||
HAS_NEXT_MISSING.registerFactory(CreateHasNextFunctionActionFactory)
|
||||
HAS_NEXT_FUNCTION_NONE_APPLICABLE.registerFactory(CreateHasNextFunctionActionFactory)
|
||||
NEXT_MISSING.registerFactory(CreateNextFunctionActionFactory)
|
||||
@@ -476,6 +496,7 @@ class QuickFixRegistrar : QuickFixContributor {
|
||||
|
||||
UPPER_BOUND_VIOLATED.registerFactory(AddGenericUpperBoundFix.Factory)
|
||||
TYPE_INFERENCE_UPPER_BOUND_VIOLATED.registerFactory(AddGenericUpperBoundFix.Factory)
|
||||
UPPER_BOUND_VIOLATED_BASED_ON_JAVA_ANNOTATIONS.registerFactory(AddGenericUpperBoundFix.Factory)
|
||||
|
||||
TYPE_INFERENCE_EXPECTED_TYPE_MISMATCH.registerFactory(ConvertClassToKClassFix)
|
||||
|
||||
@@ -583,6 +604,7 @@ class QuickFixRegistrar : QuickFixContributor {
|
||||
|
||||
RETURN_NOT_ALLOWED.registerFactory(ChangeToLabeledReturnFix)
|
||||
TYPE_MISMATCH.registerFactory(ChangeToLabeledReturnFix)
|
||||
TYPE_MISMATCH_WARNING.registerFactory(ChangeToLabeledReturnFix)
|
||||
CONSTANT_EXPECTED_TYPE_MISMATCH.registerFactory(ChangeToLabeledReturnFix)
|
||||
NULL_FOR_NONNULL_TYPE.registerFactory(ChangeToLabeledReturnFix)
|
||||
|
||||
@@ -637,6 +659,7 @@ class QuickFixRegistrar : QuickFixContributor {
|
||||
ASSIGN_OPERATOR_AMBIGUITY.registerFactory(AssignOperatorAmbiguityFactory)
|
||||
|
||||
TYPE_MISMATCH.registerFactory(SurroundWithLambdaFix)
|
||||
TYPE_MISMATCH_WARNING.registerFactory(SurroundWithLambdaFix)
|
||||
CONSTANT_EXPECTED_TYPE_MISMATCH.registerFactory(SurroundWithLambdaFix)
|
||||
|
||||
NO_SET_METHOD.registerFactory(ChangeToMutableCollectionFix)
|
||||
@@ -708,5 +731,7 @@ class QuickFixRegistrar : QuickFixContributor {
|
||||
WRONG_NULLABILITY_FOR_JAVA_OVERRIDE.registerFactory(MakeUpperBoundNonNullableFix)
|
||||
TYPE_MISMATCH.registerFactory(MakeUpperBoundNonNullableFix)
|
||||
NOTHING_TO_OVERRIDE.registerFactory(MakeUpperBoundNonNullableFix)
|
||||
|
||||
WRONG_NULLABILITY_FOR_JAVA_OVERRIDE.registerFactory(ChangeMemberFunctionSignatureFix)
|
||||
}
|
||||
}
|
||||
|
||||
+10
-3
@@ -3,6 +3,7 @@
|
||||
package org.jetbrains.kotlin.idea.quickfix
|
||||
|
||||
import com.intellij.codeInsight.intention.IntentionAction
|
||||
import com.intellij.psi.PsiElement
|
||||
import org.jetbrains.kotlin.diagnostics.Diagnostic
|
||||
import org.jetbrains.kotlin.diagnostics.Errors
|
||||
import org.jetbrains.kotlin.idea.caches.resolve.resolveToCall
|
||||
@@ -15,13 +16,19 @@ import org.jetbrains.kotlin.psi.KtQualifiedExpression
|
||||
import org.jetbrains.kotlin.resolve.calls.util.getImplicitReceiverValue
|
||||
import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode
|
||||
import org.jetbrains.kotlin.types.expressions.OperatorConventions
|
||||
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
|
||||
|
||||
object ReplaceInfixOrOperatorCallFixFactory : KotlinSingleIntentionActionFactory() {
|
||||
private fun findArrayAccessExpression(expression: PsiElement): KtArrayAccessExpression? {
|
||||
return expression.safeAs<KtArrayAccessExpression>() ?: expression.parent?.safeAs<KtArrayAccessExpression>()
|
||||
}
|
||||
|
||||
override fun createAction(diagnostic: Diagnostic): IntentionAction? {
|
||||
val expression = diagnostic.psiElement
|
||||
if (expression is KtArrayAccessExpression && diagnostic.factory != Errors.UNSAFE_IMPLICIT_INVOKE_CALL) {
|
||||
if (expression.arrayExpression == null) return null
|
||||
return ReplaceInfixOrOperatorCallFix(expression, expression.shouldHaveNotNullType())
|
||||
val arrayAccessExpression = findArrayAccessExpression(expression)
|
||||
if (arrayAccessExpression != null && diagnostic.factory != Errors.UNSAFE_IMPLICIT_INVOKE_CALL) {
|
||||
if (arrayAccessExpression.arrayExpression == null) return null
|
||||
return ReplaceInfixOrOperatorCallFix(arrayAccessExpression, arrayAccessExpression.shouldHaveNotNullType())
|
||||
}
|
||||
|
||||
when (val parent = expression.parent) {
|
||||
|
||||
@@ -51,6 +51,11 @@ class SurroundWithLambdaFix(
|
||||
expectedType = diagnosticWithParameters.a
|
||||
expressionType = diagnosticWithParameters.b
|
||||
}
|
||||
Errors.TYPE_MISMATCH_WARNING -> {
|
||||
val diagnosticWithParameters = Errors.TYPE_MISMATCH_WARNING.cast(diagnostic)
|
||||
expectedType = diagnosticWithParameters.a
|
||||
expressionType = diagnosticWithParameters.b
|
||||
}
|
||||
Errors.CONSTANT_EXPECTED_TYPE_MISMATCH -> {
|
||||
val context = (diagnostic.psiFile as KtFile).analyzeWithContent()
|
||||
val diagnosticWithParameters = Errors.CONSTANT_EXPECTED_TYPE_MISMATCH.cast(diagnostic)
|
||||
|
||||
+24
-4
@@ -22,8 +22,10 @@ import org.jetbrains.kotlin.psi.psiUtil.getLastParentOfTypeInRow
|
||||
import org.jetbrains.kotlin.psi.psiUtil.getParentOfType
|
||||
import org.jetbrains.kotlin.psi.psiUtil.getParentOfTypesAndPredicate
|
||||
import org.jetbrains.kotlin.resolve.bindingContextUtil.isUsedAsExpression
|
||||
import org.jetbrains.kotlin.resolve.jvm.diagnostics.ErrorsJvm
|
||||
import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode
|
||||
import org.jetbrains.kotlin.resolve.scopes.utils.findVariable
|
||||
import org.jetbrains.kotlin.types.KotlinType
|
||||
import org.jetbrains.kotlin.types.typeUtil.isNullabilityMismatch
|
||||
|
||||
class SurroundWithNullCheckFix(
|
||||
@@ -98,10 +100,28 @@ class SurroundWithNullCheckFix(
|
||||
}
|
||||
|
||||
object TypeMismatchFactory : KotlinSingleIntentionActionFactory() {
|
||||
|
||||
override fun createAction(diagnostic: Diagnostic): IntentionAction? {
|
||||
val typeMismatch = Errors.TYPE_MISMATCH.cast(diagnostic)
|
||||
val nullableExpression = typeMismatch.psiElement as? KtReferenceExpression ?: return null
|
||||
val nullableExpression = diagnostic.psiElement as? KtReferenceExpression ?: return null
|
||||
val expectedType: KotlinType
|
||||
val actualType: KotlinType
|
||||
when (diagnostic.factory) {
|
||||
Errors.TYPE_MISMATCH -> {
|
||||
val diagnosticWithParameters = Errors.TYPE_MISMATCH.cast(diagnostic)
|
||||
expectedType = diagnosticWithParameters.a
|
||||
actualType = diagnosticWithParameters.b
|
||||
}
|
||||
Errors.TYPE_MISMATCH_WARNING -> {
|
||||
val diagnosticWithParameters = Errors.TYPE_MISMATCH_WARNING.cast(diagnostic)
|
||||
expectedType = diagnosticWithParameters.a
|
||||
actualType = diagnosticWithParameters.b
|
||||
}
|
||||
ErrorsJvm.NULLABILITY_MISMATCH_BASED_ON_JAVA_ANNOTATIONS -> {
|
||||
val diagnosticWithParameters = ErrorsJvm.NULLABILITY_MISMATCH_BASED_ON_JAVA_ANNOTATIONS.cast(diagnostic)
|
||||
expectedType = diagnosticWithParameters.a
|
||||
actualType = diagnosticWithParameters.b
|
||||
}
|
||||
else -> return null
|
||||
}
|
||||
val root = when (val parent = nullableExpression.parent) {
|
||||
is KtValueArgument -> {
|
||||
val call = parent.getParentOfType<KtCallExpression>(true) ?: return null
|
||||
@@ -114,7 +134,7 @@ class SurroundWithNullCheckFix(
|
||||
else -> return null
|
||||
}
|
||||
if (root.parent !is KtBlockExpression) return null
|
||||
if (!isNullabilityMismatch(expected = typeMismatch.a, actual = typeMismatch.b)) return null
|
||||
if (!isNullabilityMismatch(expected = expectedType, actual = actualType)) return null
|
||||
if (!nullableExpression.isStableSimpleExpression()) return null
|
||||
return SurroundWithNullCheckFix(root, nullableExpression)
|
||||
}
|
||||
|
||||
+40
-4
@@ -16,6 +16,8 @@ import org.jetbrains.kotlin.idea.intentions.canBeReplacedWithInvokeCall
|
||||
import org.jetbrains.kotlin.psi.*
|
||||
import org.jetbrains.kotlin.psi.psiUtil.*
|
||||
import org.jetbrains.kotlin.resolve.calls.util.getParameterForArgument
|
||||
import org.jetbrains.kotlin.resolve.jvm.diagnostics.ErrorsJvm
|
||||
import org.jetbrains.kotlin.types.KotlinType
|
||||
import org.jetbrains.kotlin.types.isNullable
|
||||
import org.jetbrains.kotlin.types.typeUtil.isNullabilityMismatch
|
||||
|
||||
@@ -87,13 +89,47 @@ class WrapWithSafeLetCallFix(
|
||||
|
||||
object TypeMismatchFactory : KotlinSingleIntentionActionFactory() {
|
||||
override fun createAction(diagnostic: Diagnostic): IntentionAction? {
|
||||
val typeMismatch = Errors.TYPE_MISMATCH.cast(diagnostic)
|
||||
val argument = typeMismatch.psiElement.parent as? KtValueArgument ?: return null
|
||||
val element = diagnostic.psiElement as? KtExpression ?: return null
|
||||
val argument = element.parent as? KtValueArgument ?: return null
|
||||
val call = argument.getParentOfType<KtCallExpression>(true) ?: return null
|
||||
|
||||
if (!isNullabilityMismatch(expected = typeMismatch.a, actual = typeMismatch.b)) return null
|
||||
val expectedType: KotlinType
|
||||
val actualType: KotlinType
|
||||
when (diagnostic.factory) {
|
||||
Errors.TYPE_MISMATCH -> {
|
||||
val diagnosticWithParameters = Errors.TYPE_MISMATCH.cast(diagnostic)
|
||||
expectedType = diagnosticWithParameters.a
|
||||
actualType = diagnosticWithParameters.b
|
||||
}
|
||||
Errors.TYPE_MISMATCH_WARNING -> {
|
||||
val diagnosticWithParameters = Errors.TYPE_MISMATCH_WARNING.cast(diagnostic)
|
||||
expectedType = diagnosticWithParameters.a
|
||||
actualType = diagnosticWithParameters.b
|
||||
}
|
||||
ErrorsJvm.NULLABILITY_MISMATCH_BASED_ON_JAVA_ANNOTATIONS -> {
|
||||
val diagnosticWithParameters = ErrorsJvm.NULLABILITY_MISMATCH_BASED_ON_JAVA_ANNOTATIONS.cast(diagnostic)
|
||||
expectedType = diagnosticWithParameters.a
|
||||
actualType = diagnosticWithParameters.b
|
||||
}
|
||||
else -> return null
|
||||
}
|
||||
|
||||
return WrapWithSafeLetCallFix(call.getLastParentOfTypeInRow<KtQualifiedExpression>() ?: call, typeMismatch.psiElement)
|
||||
if (!isNullabilityMismatch(expected = expectedType, actual = actualType)) return null
|
||||
|
||||
return WrapWithSafeLetCallFix(call.getLastParentOfTypeInRow<KtQualifiedExpression>() ?: call, element)
|
||||
}
|
||||
}
|
||||
|
||||
object NullabilityMismatchBasedOnJavaAnnotationsFactory : KotlinSingleIntentionActionFactory() {
|
||||
override fun createAction(diagnostic: Diagnostic): IntentionAction? {
|
||||
val nullabilityMismatch = ErrorsJvm.NULLABILITY_MISMATCH_BASED_ON_JAVA_ANNOTATIONS.cast(diagnostic)
|
||||
val element = nullabilityMismatch.psiElement as? KtExpression ?: return null
|
||||
val argument = element.parent as? KtValueArgument ?: return null
|
||||
val call = argument.getParentOfType<KtCallExpression>(strict = true) ?: return null
|
||||
|
||||
if (!isNullabilityMismatch(expected = nullabilityMismatch.a, actual = nullabilityMismatch.b)) return null
|
||||
|
||||
return WrapWithSafeLetCallFix(call.getLastParentOfTypeInRow<KtQualifiedExpression>() ?: call, element)
|
||||
}
|
||||
}
|
||||
}
|
||||
+2
-1
@@ -67,7 +67,8 @@ sealed class CreateCallableFromCallActionFactory<E : KtExpression>(
|
||||
Errors.NONE_APPLICABLE ->
|
||||
if (diagElement is KtOperationReferenceExpression) null else diagElement.getNonStrictParentOfType<KtCallExpression>()
|
||||
|
||||
Errors.TYPE_MISMATCH -> (diagElement.parent as? KtValueArgument)?.getStrictParentOfType<KtCallExpression>()
|
||||
Errors.TYPE_MISMATCH,
|
||||
Errors.TYPE_MISMATCH_WARNING -> (diagElement.parent as? KtValueArgument)?.getStrictParentOfType<KtCallExpression>()
|
||||
|
||||
else -> throw AssertionError("Unexpected diagnostic: ${diagnostic.factory}")
|
||||
} as? KtExpression
|
||||
|
||||
+1
-1
@@ -16,7 +16,7 @@ abstract class CreateGetSetFunctionActionFactory(private val isGet: Boolean) :
|
||||
return when (diagnostic.factory) {
|
||||
Errors.NO_GET_METHOD -> if (isGet) Errors.NO_GET_METHOD.cast(diagnostic).psiElement else null
|
||||
Errors.NO_SET_METHOD -> if (!isGet) Errors.NO_SET_METHOD.cast(diagnostic).psiElement else null
|
||||
in Errors.TYPE_MISMATCH_ERRORS -> {
|
||||
in Errors.TYPE_MISMATCH_ERRORS, Errors.TYPE_MISMATCH_WARNING -> {
|
||||
val indicesNode = diagnostic.psiElement.parent as? KtContainerNode ?: return null
|
||||
if (indicesNode.node.elementType != KtNodeTypes.INDICES) return null
|
||||
val arrayAccess = indicesNode.parent as? KtArrayAccessExpression ?: return null
|
||||
|
||||
+196
@@ -32,6 +32,57 @@ public abstract class QuickFixMultiFileTestGenerated extends AbstractQuickFixMul
|
||||
}
|
||||
}
|
||||
|
||||
@RunWith(JUnit3RunnerWithInners.class)
|
||||
@TestMetadata("testData/quickfix/addExclExclCall")
|
||||
public static class AddExclExclCall extends AbstractQuickFixMultiFileTest {
|
||||
private void runTest(String testDataFilePath) throws Exception {
|
||||
KotlinTestUtils.runTest(this::doTestWithExtraFile, this, testDataFilePath);
|
||||
}
|
||||
|
||||
@TestMetadata("javaNullabilityMismatchWithImplicitReceiver.test")
|
||||
public void testJavaNullabilityMismatchWithImplicitReceiver() throws Exception {
|
||||
runTest("testData/quickfix/addExclExclCall/javaNullabilityMismatchWithImplicitReceiver.test");
|
||||
}
|
||||
|
||||
@TestMetadata("javaReceiverNullability1.test")
|
||||
public void testJavaReceiverNullability1() throws Exception {
|
||||
runTest("testData/quickfix/addExclExclCall/javaReceiverNullability1.test");
|
||||
}
|
||||
|
||||
@TestMetadata("javaReceiverNullability2.test")
|
||||
public void testJavaReceiverNullability2() throws Exception {
|
||||
runTest("testData/quickfix/addExclExclCall/javaReceiverNullability2.test");
|
||||
}
|
||||
|
||||
@TestMetadata("javaReceiverNullabilityInvoke.test")
|
||||
public void testJavaReceiverNullabilityInvoke() throws Exception {
|
||||
runTest("testData/quickfix/addExclExclCall/javaReceiverNullabilityInvoke.test");
|
||||
}
|
||||
|
||||
@TestMetadata("javaReceiverNullabilityProperty.test")
|
||||
public void testJavaReceiverNullabilityProperty() throws Exception {
|
||||
runTest("testData/quickfix/addExclExclCall/javaReceiverNullabilityProperty.test");
|
||||
}
|
||||
|
||||
@TestMetadata("javaReceiverNullabilityWithThisReceiver.test")
|
||||
public void testJavaReceiverNullabilityWithThisReceiver() throws Exception {
|
||||
runTest("testData/quickfix/addExclExclCall/javaReceiverNullabilityWithThisReceiver.test");
|
||||
}
|
||||
}
|
||||
|
||||
@RunWith(JUnit3RunnerWithInners.class)
|
||||
@TestMetadata("testData/quickfix/addGenericUpperBound")
|
||||
public static class AddGenericUpperBound extends AbstractQuickFixMultiFileTest {
|
||||
private void runTest(String testDataFilePath) throws Exception {
|
||||
KotlinTestUtils.runTest(this::doTestWithExtraFile, this, testDataFilePath);
|
||||
}
|
||||
|
||||
@TestMetadata("javaUpperBoundViolated.test")
|
||||
public void testJavaUpperBoundViolated() throws Exception {
|
||||
runTest("testData/quickfix/addGenericUpperBound/javaUpperBoundViolated.test");
|
||||
}
|
||||
}
|
||||
|
||||
@RunWith(JUnit3RunnerWithInners.class)
|
||||
@TestMetadata("testData/quickfix/addJvmDefault")
|
||||
public static class AddJvmDefault extends AbstractQuickFixMultiFileTest {
|
||||
@@ -1992,6 +2043,29 @@ public abstract class QuickFixMultiFileTestGenerated extends AbstractQuickFixMul
|
||||
runTest("testData/quickfix/override/nothingToOverride/twoPackages.before.Main.kt");
|
||||
}
|
||||
}
|
||||
|
||||
@RunWith(JUnit3RunnerWithInners.class)
|
||||
@TestMetadata("testData/quickfix/override/wrongNullabilityForJavaOverride")
|
||||
public static class WrongNullabilityForJavaOverride extends AbstractQuickFixMultiFileTest {
|
||||
private void runTest(String testDataFilePath) throws Exception {
|
||||
KotlinTestUtils.runTest(this::doTestWithExtraFile, this, testDataFilePath);
|
||||
}
|
||||
|
||||
@TestMetadata("makeArgumentNonNullable.test")
|
||||
public void testMakeArgumentNonNullable() throws Exception {
|
||||
runTest("testData/quickfix/override/wrongNullabilityForJavaOverride/makeArgumentNonNullable.test");
|
||||
}
|
||||
|
||||
@TestMetadata("makeArgumentNullable.test")
|
||||
public void testMakeArgumentNullable() throws Exception {
|
||||
runTest("testData/quickfix/override/wrongNullabilityForJavaOverride/makeArgumentNullable.test");
|
||||
}
|
||||
|
||||
@TestMetadata("makeReturnValueNonNullable.test")
|
||||
public void testMakeReturnValueNonNullable() throws Exception {
|
||||
runTest("testData/quickfix/override/wrongNullabilityForJavaOverride/makeReturnValueNonNullable.test");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@RunWith(JUnit3RunnerWithInners.class)
|
||||
@@ -2042,6 +2116,100 @@ public abstract class QuickFixMultiFileTestGenerated extends AbstractQuickFixMul
|
||||
}
|
||||
}
|
||||
|
||||
@RunWith(JUnit3RunnerWithInners.class)
|
||||
@TestMetadata("testData/quickfix/replaceWithSafeCall")
|
||||
public static class ReplaceWithSafeCall extends AbstractQuickFixMultiFileTest {
|
||||
private void runTest(String testDataFilePath) throws Exception {
|
||||
KotlinTestUtils.runTest(this::doTestWithExtraFile, this, testDataFilePath);
|
||||
}
|
||||
|
||||
@TestMetadata("javaNullabilityMismatchWithImplicitReceiver.test")
|
||||
public void testJavaNullabilityMismatchWithImplicitReceiver() throws Exception {
|
||||
runTest("testData/quickfix/replaceWithSafeCall/javaNullabilityMismatchWithImplicitReceiver.test");
|
||||
}
|
||||
|
||||
@TestMetadata("javaReceiverNullability1.test")
|
||||
public void testJavaReceiverNullability1() throws Exception {
|
||||
runTest("testData/quickfix/replaceWithSafeCall/javaReceiverNullability1.test");
|
||||
}
|
||||
|
||||
@TestMetadata("javaReceiverNullability2.test")
|
||||
public void testJavaReceiverNullability2() throws Exception {
|
||||
runTest("testData/quickfix/replaceWithSafeCall/javaReceiverNullability2.test");
|
||||
}
|
||||
|
||||
@TestMetadata("javaReceiverNullabilityArrayGet.test")
|
||||
public void testJavaReceiverNullabilityArrayGet() throws Exception {
|
||||
runTest("testData/quickfix/replaceWithSafeCall/javaReceiverNullabilityArrayGet.test");
|
||||
}
|
||||
|
||||
@TestMetadata("javaReceiverNullabilityArraySet.test")
|
||||
public void testJavaReceiverNullabilityArraySet() throws Exception {
|
||||
runTest("testData/quickfix/replaceWithSafeCall/javaReceiverNullabilityArraySet.test");
|
||||
}
|
||||
|
||||
@TestMetadata("javaReceiverNullabilityInfixPlus.test")
|
||||
public void testJavaReceiverNullabilityInfixPlus() throws Exception {
|
||||
runTest("testData/quickfix/replaceWithSafeCall/javaReceiverNullabilityInfixPlus.test");
|
||||
}
|
||||
|
||||
@TestMetadata("javaReceiverNullabilityInvoke.test")
|
||||
public void testJavaReceiverNullabilityInvoke() throws Exception {
|
||||
runTest("testData/quickfix/replaceWithSafeCall/javaReceiverNullabilityInvoke.test");
|
||||
}
|
||||
|
||||
@TestMetadata("javaReceiverNullabilityProperty.test")
|
||||
public void testJavaReceiverNullabilityProperty() throws Exception {
|
||||
runTest("testData/quickfix/replaceWithSafeCall/javaReceiverNullabilityProperty.test");
|
||||
}
|
||||
|
||||
@TestMetadata("javaReceiverNullabilityWithThisReceiver.test")
|
||||
public void testJavaReceiverNullabilityWithThisReceiver() throws Exception {
|
||||
runTest("testData/quickfix/replaceWithSafeCall/javaReceiverNullabilityWithThisReceiver.test");
|
||||
}
|
||||
}
|
||||
|
||||
@RunWith(JUnit3RunnerWithInners.class)
|
||||
@TestMetadata("testData/quickfix/replaceWithSafeCallForScopeFunction")
|
||||
public static class ReplaceWithSafeCallForScopeFunction extends AbstractQuickFixMultiFileTest {
|
||||
private void runTest(String testDataFilePath) throws Exception {
|
||||
KotlinTestUtils.runTest(this::doTestWithExtraFile, this, testDataFilePath);
|
||||
}
|
||||
|
||||
@TestMetadata("javaReceiverNullabilityAlso.test")
|
||||
public void testJavaReceiverNullabilityAlso() throws Exception {
|
||||
runTest("testData/quickfix/replaceWithSafeCallForScopeFunction/javaReceiverNullabilityAlso.test");
|
||||
}
|
||||
|
||||
@TestMetadata("javaReceiverNullabilityRunExplicitThis.test")
|
||||
public void testJavaReceiverNullabilityRunExplicitThis() throws Exception {
|
||||
runTest("testData/quickfix/replaceWithSafeCallForScopeFunction/javaReceiverNullabilityRunExplicitThis.test");
|
||||
}
|
||||
}
|
||||
|
||||
@RunWith(JUnit3RunnerWithInners.class)
|
||||
@TestMetadata("testData/quickfix/surroundWithNullCheck")
|
||||
public static class SurroundWithNullCheck extends AbstractQuickFixMultiFileTest {
|
||||
private void runTest(String testDataFilePath) throws Exception {
|
||||
KotlinTestUtils.runTest(this::doTestWithExtraFile, this, testDataFilePath);
|
||||
}
|
||||
|
||||
@TestMetadata("javaNullabilityArgument.test")
|
||||
public void testJavaNullabilityArgument() throws Exception {
|
||||
runTest("testData/quickfix/surroundWithNullCheck/javaNullabilityArgument.test");
|
||||
}
|
||||
|
||||
@TestMetadata("javaReceiverNullability.test")
|
||||
public void testJavaReceiverNullability() throws Exception {
|
||||
runTest("testData/quickfix/surroundWithNullCheck/javaReceiverNullability.test");
|
||||
}
|
||||
|
||||
@TestMetadata("javaReceiverNullabilityInvoke.test")
|
||||
public void testJavaReceiverNullabilityInvoke() throws Exception {
|
||||
runTest("testData/quickfix/surroundWithNullCheck/javaReceiverNullabilityInvoke.test");
|
||||
}
|
||||
}
|
||||
|
||||
@RunWith(JUnit3RunnerWithInners.class)
|
||||
@TestMetadata("testData/quickfix/typeImports")
|
||||
public static class TypeImports extends AbstractQuickFixMultiFileTest {
|
||||
@@ -2107,4 +2275,32 @@ public abstract class QuickFixMultiFileTestGenerated extends AbstractQuickFixMul
|
||||
runTest("testData/quickfix/when/addRemainingBranchesAnotherPackageAll.before.Main.kt");
|
||||
}
|
||||
}
|
||||
|
||||
@RunWith(JUnit3RunnerWithInners.class)
|
||||
@TestMetadata("testData/quickfix/wrapWithSafeLetCall")
|
||||
public static class WrapWithSafeLetCall extends AbstractQuickFixMultiFileTest {
|
||||
private void runTest(String testDataFilePath) throws Exception {
|
||||
KotlinTestUtils.runTest(this::doTestWithExtraFile, this, testDataFilePath);
|
||||
}
|
||||
|
||||
@TestMetadata("javaNullabilityMismatchArgument.test")
|
||||
public void testJavaNullabilityMismatchArgument() throws Exception {
|
||||
runTest("testData/quickfix/wrapWithSafeLetCall/javaNullabilityMismatchArgument.test");
|
||||
}
|
||||
|
||||
@TestMetadata("javaNullabilityMismatchArgument2.test")
|
||||
public void testJavaNullabilityMismatchArgument2() throws Exception {
|
||||
runTest("testData/quickfix/wrapWithSafeLetCall/javaNullabilityMismatchArgument2.test");
|
||||
}
|
||||
|
||||
@TestMetadata("javaReceiverNullabilityInvoke.test")
|
||||
public void testJavaReceiverNullabilityInvoke() throws Exception {
|
||||
runTest("testData/quickfix/wrapWithSafeLetCall/javaReceiverNullabilityInvoke.test");
|
||||
}
|
||||
|
||||
@TestMetadata("javaReceiverNullabilityInvoke2.test")
|
||||
public void testJavaReceiverNullabilityInvoke2() throws Exception {
|
||||
runTest("testData/quickfix/wrapWithSafeLetCall/javaReceiverNullabilityInvoke2.test");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+50
@@ -0,0 +1,50 @@
|
||||
// FILE: test.before.kt
|
||||
// "Add non-null asserted (!!) call" "true"
|
||||
// WITH_STDLIB
|
||||
package p;
|
||||
|
||||
fun test(x: Foo) {
|
||||
with (x.foo()) {
|
||||
this<caret>.bar()
|
||||
}
|
||||
}
|
||||
|
||||
// FILE: org/jspecify/nullness/Nullable.java
|
||||
package org.jspecify.nullness;
|
||||
|
||||
import static java.lang.annotation.ElementType.TYPE_USE;
|
||||
import static java.lang.annotation.RetentionPolicy.RUNTIME;
|
||||
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
@Target(TYPE_USE)
|
||||
@Retention(RUNTIME)
|
||||
public @interface Nullable {}
|
||||
|
||||
// FILE: p/A.java
|
||||
package p;
|
||||
|
||||
public class A {
|
||||
public void bar() {}
|
||||
}
|
||||
|
||||
// FILE: p/Foo.java
|
||||
package p;
|
||||
|
||||
import org.jspecify.nullness.Nullable;
|
||||
|
||||
public class Foo {
|
||||
public @Nullable A foo() { return null; }
|
||||
}
|
||||
|
||||
// FILE: test.after.kt
|
||||
// "Add non-null asserted (!!) call" "true"
|
||||
// WITH_STDLIB
|
||||
package p;
|
||||
|
||||
fun test(x: Foo) {
|
||||
with (x.foo()) {
|
||||
this<caret>!!.bar()
|
||||
}
|
||||
}
|
||||
+37
@@ -0,0 +1,37 @@
|
||||
// FILE: test.before.kt
|
||||
// "Add non-null asserted (!!) call" "true"
|
||||
package p;
|
||||
|
||||
fun test(x: Foo) {
|
||||
x.foo()<caret>.length
|
||||
}
|
||||
|
||||
// FILE: org/jspecify/nullness/Nullable.java
|
||||
package org.jspecify.nullness;
|
||||
|
||||
import static java.lang.annotation.ElementType.TYPE_USE;
|
||||
import static java.lang.annotation.RetentionPolicy.RUNTIME;
|
||||
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
@Target(TYPE_USE)
|
||||
@Retention(RUNTIME)
|
||||
public @interface Nullable {}
|
||||
|
||||
// FILE: p/Foo.java
|
||||
package p;
|
||||
|
||||
import org.jspecify.nullness.Nullable;
|
||||
|
||||
public class Foo {
|
||||
public @Nullable String foo() { return null; }
|
||||
}
|
||||
|
||||
// FILE: test.after.kt
|
||||
// "Add non-null asserted (!!) call" "true"
|
||||
package p;
|
||||
|
||||
fun test(x: Foo) {
|
||||
x.foo()<caret>!!.length
|
||||
}
|
||||
+46
@@ -0,0 +1,46 @@
|
||||
// FILE: test.before.kt
|
||||
// "Add non-null asserted (!!) call" "true"
|
||||
package p;
|
||||
|
||||
fun test(x: Foo) {
|
||||
val y = x.foo()
|
||||
y<caret>.bar()
|
||||
}
|
||||
|
||||
// FILE: org/jspecify/nullness/Nullable.java
|
||||
package org.jspecify.nullness;
|
||||
|
||||
import static java.lang.annotation.ElementType.TYPE_USE;
|
||||
import static java.lang.annotation.RetentionPolicy.RUNTIME;
|
||||
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
@Target(TYPE_USE)
|
||||
@Retention(RUNTIME)
|
||||
public @interface Nullable {}
|
||||
|
||||
// FILE: p/A.java
|
||||
package p;
|
||||
|
||||
public class A {
|
||||
public void bar() {}
|
||||
}
|
||||
|
||||
// FILE: p/Foo.java
|
||||
package p;
|
||||
|
||||
import org.jspecify.nullness.Nullable;
|
||||
|
||||
public class Foo {
|
||||
public @Nullable A foo() { return null; }
|
||||
}
|
||||
|
||||
// FILE: test.after.kt
|
||||
// "Add non-null asserted (!!) call" "true"
|
||||
package p;
|
||||
|
||||
fun test(x: Foo) {
|
||||
val y = x.foo()
|
||||
y<caret>!!.bar()
|
||||
}
|
||||
+46
@@ -0,0 +1,46 @@
|
||||
// FILE: test.before.kt
|
||||
// "Add non-null asserted (!!) call" "true"
|
||||
package p;
|
||||
|
||||
fun test(x: Foo) {
|
||||
val y = x.foo()
|
||||
<caret>y()
|
||||
}
|
||||
|
||||
// FILE: org/jspecify/nullness/Nullable.java
|
||||
package org.jspecify.nullness;
|
||||
|
||||
import static java.lang.annotation.ElementType.TYPE_USE;
|
||||
import static java.lang.annotation.RetentionPolicy.RUNTIME;
|
||||
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
@Target(TYPE_USE)
|
||||
@Retention(RUNTIME)
|
||||
public @interface Nullable {}
|
||||
|
||||
// FILE: p/A.java
|
||||
package p;
|
||||
|
||||
public class A {
|
||||
public void invoke();
|
||||
}
|
||||
|
||||
// FILE: p/Foo.java
|
||||
package p;
|
||||
|
||||
import org.jspecify.nullness.Nullable;
|
||||
|
||||
public class Foo {
|
||||
public @Nullable A foo() { return null; }
|
||||
}
|
||||
|
||||
// FILE: test.after.kt
|
||||
// "Add non-null asserted (!!) call" "true"
|
||||
package p;
|
||||
|
||||
fun test(x: Foo) {
|
||||
val y = x.foo()
|
||||
<caret>(y!!)()
|
||||
}
|
||||
+49
@@ -0,0 +1,49 @@
|
||||
// FILE: test.before.kt
|
||||
// "Add non-null asserted (!!) call" "true"
|
||||
package p;
|
||||
|
||||
fun test(x: Foo) {
|
||||
x.value<caret>.length
|
||||
}
|
||||
|
||||
// FILE: org/jspecify/nullness/Nullable.java
|
||||
package org.jspecify.nullness;
|
||||
|
||||
import static java.lang.annotation.ElementType.TYPE_USE;
|
||||
import static java.lang.annotation.RetentionPolicy.RUNTIME;
|
||||
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
@Target(TYPE_USE)
|
||||
@Retention(RUNTIME)
|
||||
public @interface Nullable {}
|
||||
|
||||
// FILE: p/Foo.java
|
||||
package p;
|
||||
|
||||
import org.jspecify.nullness.Nullable;
|
||||
|
||||
public class Foo {
|
||||
private @Nullable String value;
|
||||
|
||||
public Foo(@Nullable String value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
public @Nullable String getValue() {
|
||||
return this.value;
|
||||
}
|
||||
|
||||
public void setValue(@Nullable String value) {
|
||||
this.value = value;
|
||||
}
|
||||
}
|
||||
|
||||
// FILE: test.after.kt
|
||||
// "Add non-null asserted (!!) call" "true"
|
||||
package p;
|
||||
|
||||
fun test(x: Foo) {
|
||||
x.value<caret>!!.length
|
||||
}
|
||||
+50
@@ -0,0 +1,50 @@
|
||||
// FILE: test.before.kt
|
||||
// "Add non-null asserted (!!) call" "true"
|
||||
// WITH_STDLIB
|
||||
package p;
|
||||
|
||||
fun test(x: Foo) {
|
||||
with (x.foo()) {
|
||||
<caret>bar()
|
||||
}
|
||||
}
|
||||
|
||||
// FILE: org/jspecify/nullness/Nullable.java
|
||||
package org.jspecify.nullness;
|
||||
|
||||
import static java.lang.annotation.ElementType.TYPE_USE;
|
||||
import static java.lang.annotation.RetentionPolicy.RUNTIME;
|
||||
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
@Target(TYPE_USE)
|
||||
@Retention(RUNTIME)
|
||||
public @interface Nullable {}
|
||||
|
||||
// FILE: p/A.java
|
||||
package p;
|
||||
|
||||
public class A {
|
||||
public void bar() {}
|
||||
}
|
||||
|
||||
// FILE: p/Foo.java
|
||||
package p;
|
||||
|
||||
import org.jspecify.nullness.Nullable;
|
||||
|
||||
public class Foo {
|
||||
public @Nullable A foo() { return null; }
|
||||
}
|
||||
|
||||
// FILE: test.after.kt
|
||||
// "Add non-null asserted (!!) call" "true"
|
||||
// WITH_STDLIB
|
||||
package p;
|
||||
|
||||
fun test(x: Foo) {
|
||||
with (x.foo()) {
|
||||
<caret>this!!.bar()
|
||||
}
|
||||
}
|
||||
+35
@@ -0,0 +1,35 @@
|
||||
// FILE: test.before.kt
|
||||
// "Add 'kotlin.Any' as upper bound for T" "true"
|
||||
package p;
|
||||
|
||||
class Derived<T> : Base<<caret>T>() {}
|
||||
|
||||
// FILE: org/jspecify/nullness/NullMarked.java
|
||||
package org.jspecify.nullness;
|
||||
|
||||
import static java.lang.annotation.ElementType.MODULE;
|
||||
import static java.lang.annotation.ElementType.PACKAGE;
|
||||
import static java.lang.annotation.ElementType.TYPE;
|
||||
import static java.lang.annotation.RetentionPolicy.RUNTIME;
|
||||
|
||||
import java.lang.annotation.Documented;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
@Target({TYPE, PACKAGE, MODULE})
|
||||
@Retention(RUNTIME)
|
||||
public @interface NullMarked {}
|
||||
|
||||
// FILE: p/Base.java
|
||||
package p;
|
||||
|
||||
import org.jspecify.nullness.NullMarked;
|
||||
|
||||
@NullMarked
|
||||
public class Base<T> {}
|
||||
|
||||
// FILE: test.after.kt
|
||||
// "Add 'kotlin.Any' as upper bound for T" "true"
|
||||
package p;
|
||||
|
||||
class Derived<T : Any> : Base<<caret>T>() {}
|
||||
+59
@@ -0,0 +1,59 @@
|
||||
// FILE: test.before.kt
|
||||
// "Change function signature to 'fun foo(x: String): String'" "true"
|
||||
package p;
|
||||
|
||||
class Bar : Foo() {
|
||||
<caret>override fun foo(x: String?): String {
|
||||
return "bar"
|
||||
}
|
||||
}
|
||||
|
||||
// FILE: org/jspecify/nullness/NullMarked.java
|
||||
package org.jspecify.nullness;
|
||||
|
||||
import static java.lang.annotation.ElementType.MODULE;
|
||||
import static java.lang.annotation.ElementType.PACKAGE;
|
||||
import static java.lang.annotation.ElementType.TYPE;
|
||||
import static java.lang.annotation.RetentionPolicy.RUNTIME;
|
||||
|
||||
import java.lang.annotation.Documented;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
@Target({TYPE, PACKAGE, MODULE})
|
||||
@Retention(RUNTIME)
|
||||
public @interface NullMarked {}
|
||||
|
||||
// FILE: org/jspecify/nullness/Nullable.java
|
||||
package org.jspecify.nullness;
|
||||
|
||||
import static java.lang.annotation.ElementType.TYPE_USE;
|
||||
import static java.lang.annotation.RetentionPolicy.RUNTIME;
|
||||
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
@Target(TYPE_USE)
|
||||
@Retention(RUNTIME)
|
||||
public @interface Nullable {}
|
||||
|
||||
// FILE: p/Foo.java
|
||||
package p;
|
||||
|
||||
import org.jspecify.nullness.NullMarked;
|
||||
import org.jspecify.nullness.Nullable;
|
||||
|
||||
@NullMarked
|
||||
public class Foo {
|
||||
public String foo(String x) { return x; }
|
||||
}
|
||||
|
||||
// FILE: test.after.kt
|
||||
// "Change function signature to 'fun foo(x: String): String'" "true"
|
||||
package p;
|
||||
|
||||
class Bar : Foo() {
|
||||
<caret>override fun foo(x: String): String {
|
||||
return "bar"
|
||||
}
|
||||
}
|
||||
+59
@@ -0,0 +1,59 @@
|
||||
// FILE: test.before.kt
|
||||
// "Change function signature to 'fun foo(x: String?): String'" "true"
|
||||
package p;
|
||||
|
||||
class Bar : Foo() {
|
||||
<caret>override fun foo(x: String): String {
|
||||
return "bar"
|
||||
}
|
||||
}
|
||||
|
||||
// FILE: org/jspecify/nullness/NullMarked.java
|
||||
package org.jspecify.nullness;
|
||||
|
||||
import static java.lang.annotation.ElementType.MODULE;
|
||||
import static java.lang.annotation.ElementType.PACKAGE;
|
||||
import static java.lang.annotation.ElementType.TYPE;
|
||||
import static java.lang.annotation.RetentionPolicy.RUNTIME;
|
||||
|
||||
import java.lang.annotation.Documented;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
@Target({TYPE, PACKAGE, MODULE})
|
||||
@Retention(RUNTIME)
|
||||
public @interface NullMarked {}
|
||||
|
||||
// FILE: org/jspecify/nullness/Nullable.java
|
||||
package org.jspecify.nullness;
|
||||
|
||||
import static java.lang.annotation.ElementType.TYPE_USE;
|
||||
import static java.lang.annotation.RetentionPolicy.RUNTIME;
|
||||
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
@Target(TYPE_USE)
|
||||
@Retention(RUNTIME)
|
||||
public @interface Nullable {}
|
||||
|
||||
// FILE: p/Foo.java
|
||||
package p;
|
||||
|
||||
import org.jspecify.nullness.NullMarked;
|
||||
import org.jspecify.nullness.Nullable;
|
||||
|
||||
@NullMarked
|
||||
public class Foo {
|
||||
public String foo(@Nullable String x) { return x; }
|
||||
}
|
||||
|
||||
// FILE: test.after.kt
|
||||
// "Change function signature to 'fun foo(x: String?): String'" "true"
|
||||
package p;
|
||||
|
||||
class Bar : Foo() {
|
||||
<caret>override fun foo(x: String?): String {
|
||||
return "bar"
|
||||
}
|
||||
}
|
||||
+59
@@ -0,0 +1,59 @@
|
||||
// FILE: test.before.kt
|
||||
// "Change function signature to 'fun foo(x: String): String'" "true"
|
||||
package p;
|
||||
|
||||
class Bar : Foo() {
|
||||
<caret>override fun foo(x: String): String? {
|
||||
return "bar"
|
||||
}
|
||||
}
|
||||
|
||||
// FILE: org/jspecify/nullness/NullMarked.java
|
||||
package org.jspecify.nullness;
|
||||
|
||||
import static java.lang.annotation.ElementType.MODULE;
|
||||
import static java.lang.annotation.ElementType.PACKAGE;
|
||||
import static java.lang.annotation.ElementType.TYPE;
|
||||
import static java.lang.annotation.RetentionPolicy.RUNTIME;
|
||||
|
||||
import java.lang.annotation.Documented;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
@Target({TYPE, PACKAGE, MODULE})
|
||||
@Retention(RUNTIME)
|
||||
public @interface NullMarked {}
|
||||
|
||||
// FILE: org/jspecify/nullness/Nullable.java
|
||||
package org.jspecify.nullness;
|
||||
|
||||
import static java.lang.annotation.ElementType.TYPE_USE;
|
||||
import static java.lang.annotation.RetentionPolicy.RUNTIME;
|
||||
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
@Target(TYPE_USE)
|
||||
@Retention(RUNTIME)
|
||||
public @interface Nullable {}
|
||||
|
||||
// FILE: p/Foo.java
|
||||
package p;
|
||||
|
||||
import org.jspecify.nullness.NullMarked;
|
||||
import org.jspecify.nullness.Nullable;
|
||||
|
||||
@NullMarked
|
||||
public class Foo {
|
||||
public String foo(String x) { return x; }
|
||||
}
|
||||
|
||||
// FILE: test.after.kt
|
||||
// "Change function signature to 'fun foo(x: String): String'" "true"
|
||||
package p;
|
||||
|
||||
class Bar : Foo() {
|
||||
<caret>override fun foo(x: String): String {
|
||||
return "bar"
|
||||
}
|
||||
}
|
||||
+50
@@ -0,0 +1,50 @@
|
||||
// FILE: test.before.kt
|
||||
// "Replace with safe (this?.) call" "true"
|
||||
// WITH_STDLIB
|
||||
package p;
|
||||
|
||||
fun test(x: Foo) {
|
||||
with (x.foo()) {
|
||||
<caret>bar()
|
||||
}
|
||||
}
|
||||
|
||||
// FILE: org/jspecify/nullness/Nullable.java
|
||||
package org.jspecify.nullness;
|
||||
|
||||
import static java.lang.annotation.ElementType.TYPE_USE;
|
||||
import static java.lang.annotation.RetentionPolicy.RUNTIME;
|
||||
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
@Target(TYPE_USE)
|
||||
@Retention(RUNTIME)
|
||||
public @interface Nullable {}
|
||||
|
||||
// FILE: p/A.java
|
||||
package p;
|
||||
|
||||
public class A {
|
||||
public void bar() {}
|
||||
}
|
||||
|
||||
// FILE: p/Foo.java
|
||||
package p;
|
||||
|
||||
import org.jspecify.nullness.Nullable;
|
||||
|
||||
public class Foo {
|
||||
public @Nullable A foo() { return null; }
|
||||
}
|
||||
|
||||
// FILE: test.after.kt
|
||||
// "Replace with safe (this?.) call" "true"
|
||||
// WITH_STDLIB
|
||||
package p;
|
||||
|
||||
fun test(x: Foo) {
|
||||
with (x.foo()) {
|
||||
<caret>this?.bar()
|
||||
}
|
||||
}
|
||||
+37
@@ -0,0 +1,37 @@
|
||||
// FILE: test.before.kt
|
||||
// "Replace with safe (?.) call" "true"
|
||||
package p;
|
||||
|
||||
fun test(x: Foo) {
|
||||
x.foo()<caret>.length
|
||||
}
|
||||
|
||||
// FILE: org/jspecify/nullness/Nullable.java
|
||||
package org.jspecify.nullness;
|
||||
|
||||
import static java.lang.annotation.ElementType.TYPE_USE;
|
||||
import static java.lang.annotation.RetentionPolicy.RUNTIME;
|
||||
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
@Target(TYPE_USE)
|
||||
@Retention(RUNTIME)
|
||||
public @interface Nullable {}
|
||||
|
||||
// FILE: p/Foo.java
|
||||
package p;
|
||||
|
||||
import org.jspecify.nullness.Nullable;
|
||||
|
||||
public class Foo {
|
||||
public @Nullable String foo() { return null; }
|
||||
}
|
||||
|
||||
// FILE: test.after.kt
|
||||
// "Replace with safe (?.) call" "true"
|
||||
package p;
|
||||
|
||||
fun test(x: Foo) {
|
||||
x.foo()<caret>?.length
|
||||
}
|
||||
+46
@@ -0,0 +1,46 @@
|
||||
// FILE: test.before.kt
|
||||
// "Replace with safe (?.) call" "true"
|
||||
package p;
|
||||
|
||||
fun test(x: Foo) {
|
||||
val y = x.foo()
|
||||
y<caret>.bar()
|
||||
}
|
||||
|
||||
// FILE: org/jspecify/nullness/Nullable.java
|
||||
package org.jspecify.nullness;
|
||||
|
||||
import static java.lang.annotation.ElementType.TYPE_USE;
|
||||
import static java.lang.annotation.RetentionPolicy.RUNTIME;
|
||||
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
@Target(TYPE_USE)
|
||||
@Retention(RUNTIME)
|
||||
public @interface Nullable {}
|
||||
|
||||
// FILE: p/A.java
|
||||
package p;
|
||||
|
||||
public class A {
|
||||
public void bar() {}
|
||||
}
|
||||
|
||||
// FILE: p/Foo.java
|
||||
package p;
|
||||
|
||||
import org.jspecify.nullness.Nullable;
|
||||
|
||||
public class Foo {
|
||||
public @Nullable A foo() { return null; }
|
||||
}
|
||||
|
||||
// FILE: test.after.kt
|
||||
// "Replace with safe (?.) call" "true"
|
||||
package p;
|
||||
|
||||
fun test(x: Foo) {
|
||||
val y = x.foo()
|
||||
y<caret>?.bar()
|
||||
}
|
||||
+38
@@ -0,0 +1,38 @@
|
||||
// FILE: test.before.kt
|
||||
// "Replace with safe (?.) call" "true"
|
||||
package p;
|
||||
|
||||
fun test(x: Foo) {
|
||||
x.findAvailable()<caret>[1]
|
||||
}
|
||||
|
||||
// FILE: org/jspecify/nullness/Nullable.java
|
||||
package org.jspecify.nullness;
|
||||
|
||||
import static java.lang.annotation.ElementType.TYPE_USE;
|
||||
import static java.lang.annotation.RetentionPolicy.RUNTIME;
|
||||
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
@Target(TYPE_USE)
|
||||
@Retention(RUNTIME)
|
||||
public @interface Nullable {}
|
||||
|
||||
// FILE: p/Foo.java
|
||||
package p;
|
||||
|
||||
import org.jspecify.nullness.Nullable;
|
||||
|
||||
public class Foo {
|
||||
public int get(int index) { return 1; }
|
||||
public @Nullable Foo findAvailable() { return this; }
|
||||
}
|
||||
|
||||
// FILE: test.after.kt
|
||||
// "Replace with safe (?.) call" "true"
|
||||
package p;
|
||||
|
||||
fun test(x: Foo) {
|
||||
x.findAvailable()<caret>?.get(1)
|
||||
}
|
||||
+39
@@ -0,0 +1,39 @@
|
||||
// FILE: test.before.kt
|
||||
// "Replace with safe (?.) call" "true"
|
||||
package p;
|
||||
|
||||
fun test(x: Foo) {
|
||||
x.findAvailable()<caret>[1] = 2
|
||||
}
|
||||
|
||||
// FILE: org/jspecify/nullness/Nullable.java
|
||||
package org.jspecify.nullness;
|
||||
|
||||
import static java.lang.annotation.ElementType.TYPE_USE;
|
||||
import static java.lang.annotation.RetentionPolicy.RUNTIME;
|
||||
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
@Target(TYPE_USE)
|
||||
@Retention(RUNTIME)
|
||||
public @interface Nullable {}
|
||||
|
||||
// FILE: p/Foo.java
|
||||
package p;
|
||||
|
||||
import org.jspecify.nullness.Nullable;
|
||||
|
||||
public class Foo {
|
||||
public int get(int index) { return 1; }
|
||||
public void set(int index, int value) {}
|
||||
public @Nullable Foo findAvailable() { return this; }
|
||||
}
|
||||
|
||||
// FILE: test.after.kt
|
||||
// "Replace with safe (?.) call" "true"
|
||||
package p;
|
||||
|
||||
fun test(x: Foo) {
|
||||
x.findAvailable()<caret>?.set(1, 2)
|
||||
}
|
||||
+40
@@ -0,0 +1,40 @@
|
||||
// FILE: test.before.kt
|
||||
// "Replace with safe (?.) call" "true"
|
||||
package p;
|
||||
|
||||
fun test(x: Foo) {
|
||||
val y = x.findAvailable()
|
||||
val z = y<caret> + y
|
||||
}
|
||||
|
||||
// FILE: org/jspecify/nullness/Nullable.java
|
||||
package org.jspecify.nullness;
|
||||
|
||||
import static java.lang.annotation.ElementType.TYPE_USE;
|
||||
import static java.lang.annotation.RetentionPolicy.RUNTIME;
|
||||
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
@Target(TYPE_USE)
|
||||
@Retention(RUNTIME)
|
||||
public @interface Nullable {}
|
||||
|
||||
// FILE: p/Foo.java
|
||||
package p;
|
||||
|
||||
import org.jspecify.nullness.Nullable;
|
||||
|
||||
public class Foo {
|
||||
public @Nullable Foo plus(Foo other) { return this; }
|
||||
public @Nullable Foo findAvailable() { return this; }
|
||||
}
|
||||
|
||||
// FILE: test.after.kt
|
||||
// "Replace with safe (?.) call" "true"
|
||||
package p;
|
||||
|
||||
fun test(x: Foo) {
|
||||
val y = x.findAvailable()
|
||||
val z = y<caret>?.plus(y)
|
||||
}
|
||||
+40
@@ -0,0 +1,40 @@
|
||||
// FILE: test.before.kt
|
||||
// "Replace with safe (?.) call" "true"
|
||||
package p;
|
||||
|
||||
fun test(x: Foo) {
|
||||
val y = x.findAvailable()
|
||||
val z = y<caret>()
|
||||
}
|
||||
|
||||
// FILE: org/jspecify/nullness/Nullable.java
|
||||
package org.jspecify.nullness;
|
||||
|
||||
import static java.lang.annotation.ElementType.TYPE_USE;
|
||||
import static java.lang.annotation.RetentionPolicy.RUNTIME;
|
||||
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
@Target(TYPE_USE)
|
||||
@Retention(RUNTIME)
|
||||
public @interface Nullable {}
|
||||
|
||||
// FILE: p/Foo.java
|
||||
package p;
|
||||
|
||||
import org.jspecify.nullness.Nullable;
|
||||
|
||||
public class Foo {
|
||||
public void invoke() {}
|
||||
public @Nullable Foo findAvailable() { return this; }
|
||||
}
|
||||
|
||||
// FILE: test.after.kt
|
||||
// "Replace with safe (?.) call" "true"
|
||||
package p;
|
||||
|
||||
fun test(x: Foo) {
|
||||
val y = x.findAvailable()
|
||||
val z = y<caret>?.invoke()
|
||||
}
|
||||
+49
@@ -0,0 +1,49 @@
|
||||
// FILE: test.before.kt
|
||||
// "Replace with safe (?.) call" "true"
|
||||
package p;
|
||||
|
||||
fun test(x: Foo) {
|
||||
x.value<caret>.length
|
||||
}
|
||||
|
||||
// FILE: org/jspecify/nullness/Nullable.java
|
||||
package org.jspecify.nullness;
|
||||
|
||||
import static java.lang.annotation.ElementType.TYPE_USE;
|
||||
import static java.lang.annotation.RetentionPolicy.RUNTIME;
|
||||
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
@Target(TYPE_USE)
|
||||
@Retention(RUNTIME)
|
||||
public @interface Nullable {}
|
||||
|
||||
// FILE: p/Foo.java
|
||||
package p;
|
||||
|
||||
import org.jspecify.nullness.Nullable;
|
||||
|
||||
public class Foo {
|
||||
private @Nullable String value;
|
||||
|
||||
public Foo(@Nullable String value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
public @Nullable String getValue() {
|
||||
return this.value;
|
||||
}
|
||||
|
||||
public void setValue(@Nullable String value) {
|
||||
this.value = value;
|
||||
}
|
||||
}
|
||||
|
||||
// FILE: test.after.kt
|
||||
// "Replace with safe (?.) call" "true"
|
||||
package p;
|
||||
|
||||
fun test(x: Foo) {
|
||||
x.value<caret>?.length
|
||||
}
|
||||
+50
@@ -0,0 +1,50 @@
|
||||
// FILE: test.before.kt
|
||||
// "Replace with safe (?.) call" "true"
|
||||
// WITH_STDLIB
|
||||
package p;
|
||||
|
||||
fun test(x: Foo) {
|
||||
with (x.foo()) {
|
||||
this<caret>.bar()
|
||||
}
|
||||
}
|
||||
|
||||
// FILE: org/jspecify/nullness/Nullable.java
|
||||
package org.jspecify.nullness;
|
||||
|
||||
import static java.lang.annotation.ElementType.TYPE_USE;
|
||||
import static java.lang.annotation.RetentionPolicy.RUNTIME;
|
||||
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
@Target(TYPE_USE)
|
||||
@Retention(RUNTIME)
|
||||
public @interface Nullable {}
|
||||
|
||||
// FILE: p/A.java
|
||||
package p;
|
||||
|
||||
public class A {
|
||||
public void bar() {}
|
||||
}
|
||||
|
||||
// FILE: p/Foo.java
|
||||
package p;
|
||||
|
||||
import org.jspecify.nullness.Nullable;
|
||||
|
||||
public class Foo {
|
||||
public @Nullable A foo() { return null; }
|
||||
}
|
||||
|
||||
// FILE: test.after.kt
|
||||
// "Replace with safe (?.) call" "true"
|
||||
// WITH_STDLIB
|
||||
package p;
|
||||
|
||||
fun test(x: Foo) {
|
||||
with (x.foo()) {
|
||||
this<caret>?.bar()
|
||||
}
|
||||
}
|
||||
+44
@@ -0,0 +1,44 @@
|
||||
// FILE: test.before.kt
|
||||
// "Replace scope function with safe (?.) call" "true"
|
||||
// WITH_STDLIB
|
||||
package p;
|
||||
|
||||
fun test(x: Foo) {
|
||||
x.findAvailable().also {
|
||||
it<caret>.foo()
|
||||
}
|
||||
}
|
||||
|
||||
// FILE: org/jspecify/nullness/Nullable.java
|
||||
package org.jspecify.nullness;
|
||||
|
||||
import static java.lang.annotation.ElementType.TYPE_USE;
|
||||
import static java.lang.annotation.RetentionPolicy.RUNTIME;
|
||||
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
@Target(TYPE_USE)
|
||||
@Retention(RUNTIME)
|
||||
public @interface Nullable {}
|
||||
|
||||
// FILE: p/Foo.java
|
||||
package p;
|
||||
|
||||
import org.jspecify.nullness.Nullable;
|
||||
|
||||
public class Foo {
|
||||
public void foo() {}
|
||||
public @Nullable Foo findAvailable() { return this; }
|
||||
}
|
||||
|
||||
// FILE: test.after.kt
|
||||
// "Replace scope function with safe (?.) call" "true"
|
||||
// WITH_STDLIB
|
||||
package p;
|
||||
|
||||
fun test(x: Foo) {
|
||||
x.findAvailable()?.also {
|
||||
it<caret>.foo()
|
||||
}
|
||||
}
|
||||
+44
@@ -0,0 +1,44 @@
|
||||
// FILE: test.before.kt
|
||||
// "Replace scope function with safe (?.) call" "true"
|
||||
// WITH_STDLIB
|
||||
package p;
|
||||
|
||||
fun test(x: Foo) {
|
||||
x.findAvailable().run {
|
||||
this<caret>.foo()
|
||||
}
|
||||
}
|
||||
|
||||
// FILE: org/jspecify/nullness/Nullable.java
|
||||
package org.jspecify.nullness;
|
||||
|
||||
import static java.lang.annotation.ElementType.TYPE_USE;
|
||||
import static java.lang.annotation.RetentionPolicy.RUNTIME;
|
||||
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
@Target(TYPE_USE)
|
||||
@Retention(RUNTIME)
|
||||
public @interface Nullable {}
|
||||
|
||||
// FILE: p/Foo.java
|
||||
package p;
|
||||
|
||||
import org.jspecify.nullness.Nullable;
|
||||
|
||||
public class Foo {
|
||||
public void foo() {}
|
||||
public @Nullable Foo findAvailable() { return this; }
|
||||
}
|
||||
|
||||
// FILE: test.after.kt
|
||||
// "Replace scope function with safe (?.) call" "true"
|
||||
// WITH_STDLIB
|
||||
package p;
|
||||
|
||||
fun test(x: Foo) {
|
||||
x.findAvailable()?.run {
|
||||
this<caret>.foo()
|
||||
}
|
||||
}
|
||||
+52
@@ -0,0 +1,52 @@
|
||||
// FILE: test.before.kt
|
||||
// "Surround with null check" "true"
|
||||
package p;
|
||||
|
||||
fun f(x: A) {}
|
||||
|
||||
fun test(x: Foo) {
|
||||
val y = x.foo()
|
||||
f(y<caret>)
|
||||
}
|
||||
|
||||
// FILE: org/jspecify/nullness/Nullable.java
|
||||
package org.jspecify.nullness;
|
||||
|
||||
import static java.lang.annotation.ElementType.TYPE_USE;
|
||||
import static java.lang.annotation.RetentionPolicy.RUNTIME;
|
||||
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
@Target(TYPE_USE)
|
||||
@Retention(RUNTIME)
|
||||
public @interface Nullable {}
|
||||
|
||||
// FILE: p/A.java
|
||||
package p;
|
||||
|
||||
public class A {
|
||||
public void bar() {}
|
||||
}
|
||||
|
||||
// FILE: p/Foo.java
|
||||
package p;
|
||||
|
||||
import org.jspecify.nullness.Nullable;
|
||||
|
||||
public class Foo {
|
||||
public @Nullable A foo() { return null; }
|
||||
}
|
||||
|
||||
// FILE: test.after.kt
|
||||
// "Surround with null check" "true"
|
||||
package p;
|
||||
|
||||
fun f(x: A) {}
|
||||
|
||||
fun test(x: Foo) {
|
||||
val y = x.foo()
|
||||
if <caret>(y != null) {
|
||||
f(y)
|
||||
}
|
||||
}
|
||||
+48
@@ -0,0 +1,48 @@
|
||||
// FILE: test.before.kt
|
||||
// "Surround with null check" "true"
|
||||
package p;
|
||||
|
||||
fun test(x: Foo) {
|
||||
val y = x.foo()
|
||||
y<caret>.bar()
|
||||
}
|
||||
|
||||
// FILE: org/jspecify/nullness/Nullable.java
|
||||
package org.jspecify.nullness;
|
||||
|
||||
import static java.lang.annotation.ElementType.TYPE_USE;
|
||||
import static java.lang.annotation.RetentionPolicy.RUNTIME;
|
||||
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
@Target(TYPE_USE)
|
||||
@Retention(RUNTIME)
|
||||
public @interface Nullable {}
|
||||
|
||||
// FILE: p/A.java
|
||||
package p;
|
||||
|
||||
public class A {
|
||||
public void bar() {}
|
||||
}
|
||||
|
||||
// FILE: p/Foo.java
|
||||
package p;
|
||||
|
||||
import org.jspecify.nullness.Nullable;
|
||||
|
||||
public class Foo {
|
||||
public @Nullable A foo() { return null; }
|
||||
}
|
||||
|
||||
// FILE: test.after.kt
|
||||
// "Surround with null check" "true"
|
||||
package p;
|
||||
|
||||
fun test(x: Foo) {
|
||||
val y = x.foo()
|
||||
i<caret>f (y != null) {
|
||||
y.bar()
|
||||
}
|
||||
}
|
||||
+48
@@ -0,0 +1,48 @@
|
||||
// FILE: test.before.kt
|
||||
// "Surround with null check" "true"
|
||||
package p;
|
||||
|
||||
fun test(x: Foo) {
|
||||
val y = x.foo()
|
||||
y<caret>()
|
||||
}
|
||||
|
||||
// FILE: org/jspecify/nullness/Nullable.java
|
||||
package org.jspecify.nullness;
|
||||
|
||||
import static java.lang.annotation.ElementType.TYPE_USE;
|
||||
import static java.lang.annotation.RetentionPolicy.RUNTIME;
|
||||
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
@Target(TYPE_USE)
|
||||
@Retention(RUNTIME)
|
||||
public @interface Nullable {}
|
||||
|
||||
// FILE: p/A.java
|
||||
package p;
|
||||
|
||||
public class A {
|
||||
public void invoke();
|
||||
}
|
||||
|
||||
// FILE: p/Foo.java
|
||||
package p;
|
||||
|
||||
import org.jspecify.nullness.Nullable;
|
||||
|
||||
public class Foo {
|
||||
public @Nullable A foo() { return null; }
|
||||
}
|
||||
|
||||
// FILE: test.after.kt
|
||||
// "Surround with null check" "true"
|
||||
package p;
|
||||
|
||||
fun test(x: Foo) {
|
||||
val y = x.foo()
|
||||
i<caret>f (y != null) {
|
||||
y()
|
||||
}
|
||||
}
|
||||
+48
@@ -0,0 +1,48 @@
|
||||
// FILE: test.before.kt
|
||||
// "Wrap with '?.let { ... }' call" "true"
|
||||
package p;
|
||||
|
||||
fun f(x: A) {}
|
||||
|
||||
fun test(x: Foo) {
|
||||
f(<caret>x.foo())
|
||||
}
|
||||
|
||||
// FILE: org/jspecify/nullness/Nullable.java
|
||||
package org.jspecify.nullness;
|
||||
|
||||
import static java.lang.annotation.ElementType.TYPE_USE;
|
||||
import static java.lang.annotation.RetentionPolicy.RUNTIME;
|
||||
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
@Target(TYPE_USE)
|
||||
@Retention(RUNTIME)
|
||||
public @interface Nullable {}
|
||||
|
||||
// FILE: p/A.java
|
||||
package p;
|
||||
|
||||
public class A {
|
||||
public void bar();
|
||||
}
|
||||
|
||||
// FILE: p/Foo.java
|
||||
package p;
|
||||
|
||||
import org.jspecify.nullness.Nullable;
|
||||
|
||||
public class Foo {
|
||||
public @Nullable A foo() { return null; }
|
||||
}
|
||||
|
||||
// FILE: test.after.kt
|
||||
// "Wrap with '?.let { ... }' call" "true"
|
||||
package p;
|
||||
|
||||
fun f(x: A) {}
|
||||
|
||||
fun test(x: Foo) {
|
||||
x.<caret>foo()?.let { f(it) }
|
||||
}
|
||||
+50
@@ -0,0 +1,50 @@
|
||||
// FILE: test.before.kt
|
||||
// "Wrap with '?.let { ... }' call" "true"
|
||||
package p;
|
||||
|
||||
fun f(x: A) {}
|
||||
|
||||
fun test(x: Foo) {
|
||||
val a = x.foo()
|
||||
f(<caret>a)
|
||||
}
|
||||
|
||||
// FILE: org/jspecify/nullness/Nullable.java
|
||||
package org.jspecify.nullness;
|
||||
|
||||
import static java.lang.annotation.ElementType.TYPE_USE;
|
||||
import static java.lang.annotation.RetentionPolicy.RUNTIME;
|
||||
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
@Target(TYPE_USE)
|
||||
@Retention(RUNTIME)
|
||||
public @interface Nullable {}
|
||||
|
||||
// FILE: p/A.java
|
||||
package p;
|
||||
|
||||
public class A {
|
||||
public void bar();
|
||||
}
|
||||
|
||||
// FILE: p/Foo.java
|
||||
package p;
|
||||
|
||||
import org.jspecify.nullness.Nullable;
|
||||
|
||||
public class Foo {
|
||||
public @Nullable A foo() { return null; }
|
||||
}
|
||||
|
||||
// FILE: test.after.kt
|
||||
// "Wrap with '?.let { ... }' call" "true"
|
||||
package p;
|
||||
|
||||
fun f(x: A) {}
|
||||
|
||||
fun test(x: Foo) {
|
||||
val a = x.foo()
|
||||
a<caret>?.let { f(it) }
|
||||
}
|
||||
+46
@@ -0,0 +1,46 @@
|
||||
// FILE: test.before.kt
|
||||
// "Wrap with '?.let { ... }' call" "true"
|
||||
package p;
|
||||
|
||||
fun test(x: Foo) {
|
||||
val y = x.foo()
|
||||
y<caret>()
|
||||
}
|
||||
|
||||
// FILE: org/jspecify/nullness/Nullable.java
|
||||
package org.jspecify.nullness;
|
||||
|
||||
import static java.lang.annotation.ElementType.TYPE_USE;
|
||||
import static java.lang.annotation.RetentionPolicy.RUNTIME;
|
||||
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
@Target(TYPE_USE)
|
||||
@Retention(RUNTIME)
|
||||
public @interface Nullable {}
|
||||
|
||||
// FILE: p/A.java
|
||||
package p;
|
||||
|
||||
public class A {
|
||||
public void invoke();
|
||||
}
|
||||
|
||||
// FILE: p/Foo.java
|
||||
package p;
|
||||
|
||||
import org.jspecify.nullness.Nullable;
|
||||
|
||||
public class Foo {
|
||||
public @Nullable A foo() { return null; }
|
||||
}
|
||||
|
||||
// FILE: test.after.kt
|
||||
// "Wrap with '?.let { ... }' call" "true"
|
||||
package p;
|
||||
|
||||
fun test(x: Foo) {
|
||||
val y = x.foo()
|
||||
y<caret>?.let { it() }
|
||||
}
|
||||
+44
@@ -0,0 +1,44 @@
|
||||
// FILE: test.before.kt
|
||||
// "Wrap with '?.let { ... }' call" "true"
|
||||
package p;
|
||||
|
||||
fun test(x: Foo) {
|
||||
<caret>x.foo()()
|
||||
}
|
||||
|
||||
// FILE: org/jspecify/nullness/Nullable.java
|
||||
package org.jspecify.nullness;
|
||||
|
||||
import static java.lang.annotation.ElementType.TYPE_USE;
|
||||
import static java.lang.annotation.RetentionPolicy.RUNTIME;
|
||||
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
@Target(TYPE_USE)
|
||||
@Retention(RUNTIME)
|
||||
public @interface Nullable {}
|
||||
|
||||
// FILE: p/A.java
|
||||
package p;
|
||||
|
||||
public class A {
|
||||
public void invoke();
|
||||
}
|
||||
|
||||
// FILE: p/Foo.java
|
||||
package p;
|
||||
|
||||
import org.jspecify.nullness.Nullable;
|
||||
|
||||
public class Foo {
|
||||
public @Nullable A foo() { return null; }
|
||||
}
|
||||
|
||||
// FILE: test.after.kt
|
||||
// "Wrap with '?.let { ... }' call" "true"
|
||||
package p;
|
||||
|
||||
fun test(x: Foo) {
|
||||
<caret>x.foo()?.let { it() }
|
||||
}
|
||||
Reference in New Issue
Block a user