Improve remove/specify type intentions in Explicit API mode
Do not suggest to remove type for public declarations #KT-38915 Fixed Do not show intention to specify type when corresponding quickfix is available #KT-39026 Fixed
This commit is contained in:
+16
@@ -7,6 +7,7 @@ package org.jetbrains.kotlin.resolve.checkers
|
||||
|
||||
import org.jetbrains.kotlin.config.AnalysisFlags
|
||||
import org.jetbrains.kotlin.config.ExplicitApiMode
|
||||
import org.jetbrains.kotlin.config.LanguageVersionSettings
|
||||
import org.jetbrains.kotlin.descriptors.*
|
||||
import org.jetbrains.kotlin.diagnostics.Errors
|
||||
import org.jetbrains.kotlin.diagnostics.reportDiagnosticOnce
|
||||
@@ -122,5 +123,20 @@ class ExplicitApiDeclarationChecker : DeclarationChecker {
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
fun publicReturnTypeShouldBePresentInApiMode(
|
||||
element: KtCallableDeclaration,
|
||||
languageVersionSettings: LanguageVersionSettings,
|
||||
descriptor: DeclarationDescriptor?
|
||||
): Boolean {
|
||||
val isInApiMode = languageVersionSettings.getFlag(AnalysisFlags.explicitApiMode) != ExplicitApiMode.DISABLED
|
||||
return isInApiMode && returnTypeRequired(
|
||||
element,
|
||||
descriptor,
|
||||
checkForPublicApi = true,
|
||||
checkForInternal = false,
|
||||
checkForPrivate = false
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,6 +10,8 @@ import com.intellij.openapi.editor.Editor
|
||||
import com.intellij.openapi.util.TextRange
|
||||
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
|
||||
import org.jetbrains.kotlin.idea.KotlinBundle
|
||||
import org.jetbrains.kotlin.idea.caches.resolve.resolveToDescriptorIfAny
|
||||
import org.jetbrains.kotlin.idea.project.languageVersionSettings
|
||||
import org.jetbrains.kotlin.idea.refactoring.addTypeArgumentsIfNeeded
|
||||
import org.jetbrains.kotlin.idea.refactoring.getQualifiedTypeArgumentList
|
||||
import org.jetbrains.kotlin.idea.references.mainReference
|
||||
@@ -18,6 +20,7 @@ import org.jetbrains.kotlin.lexer.KtTokens
|
||||
import org.jetbrains.kotlin.psi.*
|
||||
import org.jetbrains.kotlin.psi.psiUtil.endOffset
|
||||
import org.jetbrains.kotlin.psi.psiUtil.startOffset
|
||||
import org.jetbrains.kotlin.resolve.checkers.ExplicitApiDeclarationChecker
|
||||
import org.jetbrains.kotlin.types.typeUtil.isUnit
|
||||
|
||||
class RemoveExplicitTypeIntention : SelfTargetingRangeIntention<KtCallableDeclaration>(
|
||||
@@ -56,6 +59,12 @@ class RemoveExplicitTypeIntention : SelfTargetingRangeIntention<KtCallableDeclar
|
||||
|
||||
val initializer = (element as? KtDeclarationWithInitializer)?.initializer
|
||||
|
||||
if (ExplicitApiDeclarationChecker.publicReturnTypeShouldBePresentInApiMode(
|
||||
element,
|
||||
element.languageVersionSettings,
|
||||
element.resolveToDescriptorIfAny()
|
||||
)
|
||||
) return null
|
||||
if (!redundantTypeSpecification(element.typeReference, initializer)) return null
|
||||
|
||||
return when {
|
||||
@@ -92,4 +101,4 @@ class RemoveExplicitTypeIntention : SelfTargetingRangeIntention<KtCallableDeclar
|
||||
}
|
||||
}
|
||||
|
||||
internal val KtParameter.isSetterParameter: Boolean get() = (parent.parent as? KtPropertyAccessor)?.isSetter ?: false
|
||||
internal val KtParameter.isSetterParameter: Boolean get() = (parent.parent as? KtPropertyAccessor)?.isSetter ?: false
|
||||
|
||||
@@ -23,6 +23,7 @@ import org.jetbrains.kotlin.idea.caches.resolve.resolveToDescriptorIfAny
|
||||
import org.jetbrains.kotlin.idea.core.ShortenReferences
|
||||
import org.jetbrains.kotlin.idea.core.setType
|
||||
import org.jetbrains.kotlin.idea.core.unquote
|
||||
import org.jetbrains.kotlin.idea.project.languageVersionSettings
|
||||
import org.jetbrains.kotlin.idea.util.IdeDescriptorRenderers
|
||||
import org.jetbrains.kotlin.idea.util.application.runWriteAction
|
||||
import org.jetbrains.kotlin.idea.util.getResolutionScope
|
||||
@@ -42,6 +43,14 @@ class SpecifyTypeExplicitlyIntention : SelfTargetingRangeIntention<KtCallableDec
|
||||
), HighPriorityAction {
|
||||
override fun applicabilityRange(element: KtCallableDeclaration): TextRange? {
|
||||
if (!ExplicitApiDeclarationChecker.returnTypeCheckIsApplicable(element)) return null
|
||||
// If ApiMode is on, then this intention duplicates corresponding quickfix for compiler error
|
||||
// and we disable it here.
|
||||
if (ExplicitApiDeclarationChecker.publicReturnTypeShouldBePresentInApiMode(
|
||||
element,
|
||||
element.languageVersionSettings,
|
||||
element.resolveToDescriptorIfAny()
|
||||
)
|
||||
) return null
|
||||
setTextGetter(
|
||||
if (element is KtFunction)
|
||||
KotlinBundle.lazyMessage("specify.return.type.explicitly")
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
org.jetbrains.kotlin.idea.intentions.RemoveExplicitTypeIntention
|
||||
@@ -0,0 +1,4 @@
|
||||
// COMPILER_ARGUMENTS: -Xexplicit-api=strict
|
||||
// IS_APPLICABLE: true
|
||||
|
||||
internal fun foo(): <caret>Int = 42
|
||||
+4
@@ -0,0 +1,4 @@
|
||||
// COMPILER_ARGUMENTS: -Xexplicit-api=strict
|
||||
// IS_APPLICABLE: true
|
||||
|
||||
internal fun foo() = 42
|
||||
@@ -0,0 +1,4 @@
|
||||
// COMPILER_ARGUMENTS: -Xexplicit-api=strict
|
||||
// IS_APPLICABLE: false
|
||||
|
||||
public fun foo(): <caret>Int = 42
|
||||
@@ -14417,6 +14417,29 @@ public class IntentionTestGenerated extends AbstractIntentionTest {
|
||||
}
|
||||
}
|
||||
|
||||
@TestMetadata("idea/testData/intentions/removeExplicitTypeWithApiMode")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
@RunWith(JUnit3RunnerWithInners.class)
|
||||
public static class RemoveExplicitTypeWithApiMode extends AbstractIntentionTest {
|
||||
private void runTest(String testDataFilePath) throws Exception {
|
||||
KotlinTestUtils.runTest(this::doTest, this, testDataFilePath);
|
||||
}
|
||||
|
||||
public void testAllFilesPresentInRemoveExplicitTypeWithApiMode() throws Exception {
|
||||
KotlinTestUtils.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("idea/testData/intentions/removeExplicitTypeWithApiMode"), Pattern.compile("^([\\w\\-_]+)\\.(kt|kts)$"), null, true);
|
||||
}
|
||||
|
||||
@TestMetadata("nonPublicFunction.kt")
|
||||
public void testNonPublicFunction() throws Exception {
|
||||
runTest("idea/testData/intentions/removeExplicitTypeWithApiMode/nonPublicFunction.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("publicFunction.kt")
|
||||
public void testPublicFunction() throws Exception {
|
||||
runTest("idea/testData/intentions/removeExplicitTypeWithApiMode/publicFunction.kt");
|
||||
}
|
||||
}
|
||||
|
||||
@TestMetadata("idea/testData/intentions/removeForLoopIndices")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
@RunWith(JUnit3RunnerWithInners.class)
|
||||
|
||||
Reference in New Issue
Block a user