mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
[Kotlin] Added additional tests for the settings of HasPlatformTypeInspection
KTIJ-22908 GitOrigin-RevId: ceaff50e361cad9e7117ceb1ee891215b56abcc6
This commit is contained in:
committed by
intellij-monorepo-bot
parent
be8cdd32f8
commit
624b012c49
+24
-27
@@ -1,6 +1,7 @@
|
||||
// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
package org.jetbrains.kotlin.idea.k2.codeinsight.inspections
|
||||
|
||||
import com.intellij.codeInsight.intention.IntentionAction
|
||||
import com.intellij.codeInspection.IntentionWrapper
|
||||
import com.intellij.codeInspection.ProblemsHolder
|
||||
import com.intellij.codeInspection.options.OptPane.checkbox
|
||||
@@ -39,11 +40,10 @@ class HasPlatformTypeInspection(
|
||||
}
|
||||
}
|
||||
|
||||
context(KaSession)
|
||||
private fun KaType.isFlexibleRecursive(): Boolean {
|
||||
if (hasFlexibleNullability) return true
|
||||
val classType = this as? KaClassType ?: return false
|
||||
return classType.typeArguments.any { it !is KaStarTypeProjection && it.type?.isFlexibleRecursive() == true }
|
||||
private fun KaSession.isFlexibleRecursive(type: KaType): Boolean {
|
||||
if (type.hasFlexibleNullability) return true
|
||||
val classType = type as? KaClassType ?: return false
|
||||
return classType.typeArguments.any { arg -> arg !is KaStarTypeProjection && arg.type?.let { isFlexibleRecursive(it) } == true }
|
||||
}
|
||||
|
||||
private val publicApiVisibilities = setOf(
|
||||
@@ -51,9 +51,10 @@ class HasPlatformTypeInspection(
|
||||
KaSymbolVisibility.PROTECTED,
|
||||
)
|
||||
|
||||
context(KaSession)
|
||||
private fun dangerousFlexibleTypeOrNull(
|
||||
declaration: KtCallableDeclaration, publicAPIOnly: Boolean, reportPlatformArguments: Boolean
|
||||
private fun KaSession.dangerousFlexibleTypeOrNull(
|
||||
declaration: KtCallableDeclaration,
|
||||
publicAPIOnly: Boolean,
|
||||
reportPlatformArguments: Boolean
|
||||
): KaType? {
|
||||
when (declaration) {
|
||||
is KtFunction -> if (declaration.isLocal || declaration.hasDeclaredReturnType()) return null
|
||||
@@ -65,7 +66,7 @@ class HasPlatformTypeInspection(
|
||||
val type = declaration.returnType
|
||||
if (type is KaDynamicType) return null
|
||||
if (reportPlatformArguments) {
|
||||
if (!type.isFlexibleRecursive()) return null
|
||||
if (!isFlexibleRecursive(type)) return null
|
||||
} else {
|
||||
if (!type.hasFlexibleNullability) return null
|
||||
}
|
||||
@@ -73,31 +74,27 @@ class HasPlatformTypeInspection(
|
||||
return type
|
||||
}
|
||||
|
||||
context(KaSession)
|
||||
fun checkForPlatformType(element: KtCallableDeclaration, nameIdentifier: PsiElement, holder: ProblemsHolder) {
|
||||
private fun KaSession.checkForPlatformType(element: KtCallableDeclaration, nameIdentifier: PsiElement, holder: ProblemsHolder) {
|
||||
val dangerousFlexibleType = dangerousFlexibleTypeOrNull(element, publicAPIOnly, reportPlatformArguments) ?: return
|
||||
val fixes = mutableListOf<IntentionAction>(
|
||||
SpecifyExplicitTypeQuickFix(element, CallableReturnTypeUpdaterUtils.getTypeInfo(element))
|
||||
)
|
||||
|
||||
if (dangerousFlexibleType.canBeNull) {
|
||||
val nonNullableType = dangerousFlexibleType.withNullability(KaTypeNullability.NON_NULLABLE)
|
||||
val expression = element.node.findChildByType(KtTokens.EQ)?.psi?.getNextSiblingIgnoringWhitespaceAndComments()
|
||||
if (expression != null &&
|
||||
(!reportPlatformArguments || !nonNullableType.isFlexibleRecursive())
|
||||
) {
|
||||
holder.registerProblem(
|
||||
nameIdentifier,
|
||||
KotlinBundle.message(
|
||||
"declaration.has.type.inferred.from.a.platform.call.which.can.lead.to.unchecked.nullability.issues"
|
||||
),
|
||||
IntentionWrapper(AddExclExclCallFix(expression)),
|
||||
IntentionWrapper(
|
||||
SpecifyExplicitTypeQuickFix(
|
||||
element,
|
||||
CallableReturnTypeUpdaterUtils.getTypeInfo(element)
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
// Only add this fix if it can actually fully resolve the problem
|
||||
if (expression != null && (!reportPlatformArguments || !isFlexibleRecursive(nonNullableType))) {
|
||||
fixes.add(AddExclExclCallFix(expression))
|
||||
}
|
||||
}
|
||||
|
||||
holder.registerProblem(
|
||||
nameIdentifier,
|
||||
KotlinBundle.message("declaration.has.type.inferred.from.a.platform.call.which.can.lead.to.unchecked.nullability.issues"),
|
||||
*fixes.map { action -> IntentionWrapper(action) }.toTypedArray()
|
||||
)
|
||||
}
|
||||
|
||||
override fun getOptionsPane() = pane(
|
||||
|
||||
+69
@@ -7641,6 +7641,11 @@ public abstract class K2LocalInspectionTestGenerated extends AbstractK2LocalInsp
|
||||
KotlinTestUtils.runTest(this::doTest, this, testDataFilePath);
|
||||
}
|
||||
|
||||
@TestMetadata("array.kt")
|
||||
public void testArray() throws Exception {
|
||||
runTest("testData/inspectionsLocal/hasPlatformType/array.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("extensionOnDynamic.kt")
|
||||
public void testExtensionOnDynamic() throws Exception {
|
||||
runTest("testData/inspectionsLocal/hasPlatformType/extensionOnDynamic.kt");
|
||||
@@ -7656,6 +7661,11 @@ public abstract class K2LocalInspectionTestGenerated extends AbstractK2LocalInsp
|
||||
runTest("testData/inspectionsLocal/hasPlatformType/functionExclExcl.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("internalFunction.kt")
|
||||
public void testInternalFunction() throws Exception {
|
||||
runTest("testData/inspectionsLocal/hasPlatformType/internalFunction.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("localClassFunction.kt")
|
||||
public void testLocalClassFunction() throws Exception {
|
||||
runTest("testData/inspectionsLocal/hasPlatformType/localClassFunction.kt");
|
||||
@@ -7712,6 +7722,65 @@ public abstract class K2LocalInspectionTestGenerated extends AbstractK2LocalInsp
|
||||
}
|
||||
}
|
||||
|
||||
@RunWith(JUnit3RunnerWithInners.class)
|
||||
@TestMetadata("testData/inspectionsLocal/hasPlatformTypeWithSettings")
|
||||
public static class HasPlatformTypeWithSettings extends AbstractK2LocalInspectionTest {
|
||||
@java.lang.Override
|
||||
@org.jetbrains.annotations.NotNull
|
||||
public final KotlinPluginMode getPluginMode() {
|
||||
return KotlinPluginMode.K2;
|
||||
}
|
||||
|
||||
private void runTest(String testDataFilePath) throws Exception {
|
||||
KotlinTestUtils.runTest(this::doTest, this, testDataFilePath);
|
||||
}
|
||||
|
||||
@TestMetadata("array.kt")
|
||||
public void testArray() throws Exception {
|
||||
runTest("testData/inspectionsLocal/hasPlatformTypeWithSettings/array.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("internalFunction.kt")
|
||||
public void testInternalFunction() throws Exception {
|
||||
runTest("testData/inspectionsLocal/hasPlatformTypeWithSettings/internalFunction.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("localFunction.kt")
|
||||
public void testLocalFunction() throws Exception {
|
||||
runTest("testData/inspectionsLocal/hasPlatformTypeWithSettings/localFunction.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("nullableArrayNoExclExcl.kt")
|
||||
public void testNullableArrayNoExclExcl() throws Exception {
|
||||
runTest("testData/inspectionsLocal/hasPlatformTypeWithSettings/nullableArrayNoExclExcl.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("privateFunction.kt")
|
||||
public void testPrivateFunction() throws Exception {
|
||||
runTest("testData/inspectionsLocal/hasPlatformTypeWithSettings/privateFunction.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("property.kt")
|
||||
public void testProperty() throws Exception {
|
||||
runTest("testData/inspectionsLocal/hasPlatformTypeWithSettings/property.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("propertyExclExcl.kt")
|
||||
public void testPropertyExclExcl() throws Exception {
|
||||
runTest("testData/inspectionsLocal/hasPlatformTypeWithSettings/propertyExclExcl.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("protectedFunction.kt")
|
||||
public void testProtectedFunction() throws Exception {
|
||||
runTest("testData/inspectionsLocal/hasPlatformTypeWithSettings/protectedFunction.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("recursiveGeneric.kt")
|
||||
public void testRecursiveGeneric() throws Exception {
|
||||
runTest("testData/inspectionsLocal/hasPlatformTypeWithSettings/recursiveGeneric.kt");
|
||||
}
|
||||
}
|
||||
|
||||
@RunWith(JUnit3RunnerWithInners.class)
|
||||
@TestMetadata("testData/inspectionsLocal/kotlinOptionsToCompilerOptions")
|
||||
public static class KotlinOptionsToCompilerOptions extends AbstractK2LocalInspectionTest {
|
||||
|
||||
+4
@@ -0,0 +1,4 @@
|
||||
// WITH_STDLIB
|
||||
// PROBLEM: none
|
||||
|
||||
val test<caret> = arrayOf<java.lang.String.valueOf(1)>
|
||||
+4
@@ -0,0 +1,4 @@
|
||||
// WITH_STDLIB
|
||||
// PROBLEM: none
|
||||
|
||||
internal fun foo<caret>() = java.lang.String.valueOf(1)
|
||||
+1
@@ -0,0 +1 @@
|
||||
org.jetbrains.kotlin.idea.k2.codeinsight.inspections.HasPlatformTypeInspection
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
// WITH_STDLIB
|
||||
|
||||
val test<caret> = arrayOf(java.lang.String.valueOf(1))
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
// WITH_STDLIB
|
||||
|
||||
val test: Array<String?> = arrayOf(java.lang.String.valueOf(1))
|
||||
+4
@@ -0,0 +1,4 @@
|
||||
// WITH_STDLIB
|
||||
// FIX: Specify return type explicitly
|
||||
|
||||
internal fun foo<caret>() = java.lang.String.valueOf(1)
|
||||
+4
@@ -0,0 +1,4 @@
|
||||
// WITH_STDLIB
|
||||
// FIX: Specify return type explicitly
|
||||
|
||||
internal fun foo(): String = java.lang.String.valueOf(1)
|
||||
+6
@@ -0,0 +1,6 @@
|
||||
// WITH_STDLIB
|
||||
// PROBLEM: none
|
||||
|
||||
fun foo() {
|
||||
fun bar<caret>() = java.lang.String.valueOf(2)
|
||||
}
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
// WITH_STDLIB
|
||||
|
||||
val test<caret> = arrayOf(java.lang.String.valueOf(1)).takeIf { it.isEmpty() }
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
// WITH_STDLIB
|
||||
|
||||
val test: Array<String?>? = arrayOf(java.lang.String.valueOf(1)).takeIf { it.isEmpty() }
|
||||
+4
@@ -0,0 +1,4 @@
|
||||
// WITH_STDLIB
|
||||
// FIX: Specify return type explicitly
|
||||
|
||||
private fun foo<caret>() = java.lang.String.valueOf(1)
|
||||
+4
@@ -0,0 +1,4 @@
|
||||
// WITH_STDLIB
|
||||
// FIX: Specify return type explicitly
|
||||
|
||||
private fun foo(): String = java.lang.String.valueOf(1)
|
||||
+4
@@ -0,0 +1,4 @@
|
||||
// WITH_STDLIB
|
||||
// FIX: Specify type explicitly
|
||||
|
||||
val foo<caret> = java.lang.String.valueOf(1)
|
||||
+4
@@ -0,0 +1,4 @@
|
||||
// WITH_STDLIB
|
||||
// FIX: Specify type explicitly
|
||||
|
||||
val foo: String = java.lang.String.valueOf(1)
|
||||
+4
@@ -0,0 +1,4 @@
|
||||
// WITH_STDLIB
|
||||
// FIX: Add non-null asserted (java.lang.String.valueOf(1)!!) call
|
||||
|
||||
val foo<caret> = java.lang.String.valueOf(1)
|
||||
+4
@@ -0,0 +1,4 @@
|
||||
// WITH_STDLIB
|
||||
// FIX: Add non-null asserted (java.lang.String.valueOf(1)!!) call
|
||||
|
||||
val foo = java.lang.String.valueOf(1)!!
|
||||
+6
@@ -0,0 +1,6 @@
|
||||
// WITH_STDLIB
|
||||
// FIX: Specify return type explicitly
|
||||
|
||||
open class My {
|
||||
protected fun foo<caret>() = java.lang.String.valueOf(3)
|
||||
}
|
||||
+6
@@ -0,0 +1,6 @@
|
||||
// WITH_STDLIB
|
||||
// FIX: Specify return type explicitly
|
||||
|
||||
open class My {
|
||||
protected fun foo(): String = java.lang.String.valueOf(3)
|
||||
}
|
||||
+8
@@ -0,0 +1,8 @@
|
||||
// WITH_STDLIB
|
||||
// PROBLEM: none
|
||||
interface Rec<R, out T: Rec<R, T>> {
|
||||
fun t(): T
|
||||
}
|
||||
interface Super {
|
||||
fun foo<caret>(p: Rec<*, *>) = p.t()
|
||||
}
|
||||
+4
@@ -0,0 +1,4 @@
|
||||
<inspection_tool class="HasPlatformTypeInspection">
|
||||
<option name="publicAPIOnly" value="false" />
|
||||
<option name="reportPlatformArguments" value="true" />
|
||||
</inspection_tool>
|
||||
Reference in New Issue
Block a user