Add quickfix for setting explicit public visibility for diagnostic reported in API mode
This commit is contained in:
@@ -207,9 +207,9 @@ public interface Errors {
|
||||
DiagnosticFactory2<PsiElement, KtModifierKeywordToken, String> DEPRECATED_MODIFIER_FOR_TARGET = DiagnosticFactory2.create(WARNING);
|
||||
DiagnosticFactory2<PsiElement, KtModifierKeywordToken, KtModifierKeywordToken> DEPRECATED_MODIFIER = DiagnosticFactory2.create(WARNING);
|
||||
DiagnosticFactory2<PsiElement, KtModifierKeywordToken, String> REDUNDANT_MODIFIER_FOR_TARGET = DiagnosticFactory2.create(WARNING);
|
||||
DiagnosticFactory0<PsiElement> NO_EXPLICIT_VISIBILITY_IN_API_MODE = DiagnosticFactory0.create(ERROR);
|
||||
DiagnosticFactory1<PsiElement, DeclarationDescriptor> NO_EXPLICIT_VISIBILITY_IN_API_MODE = DiagnosticFactory1.create(ERROR);
|
||||
DiagnosticFactory0<PsiElement> NO_EXPLICIT_RETURN_TYPE_IN_API_MODE = DiagnosticFactory0.create(ERROR);
|
||||
DiagnosticFactory0<PsiElement> NO_EXPLICIT_VISIBILITY_IN_API_MODE_MIGRATION = DiagnosticFactory0.create(WARNING);
|
||||
DiagnosticFactory1<PsiElement, DeclarationDescriptor> NO_EXPLICIT_VISIBILITY_IN_API_MODE_MIGRATION = DiagnosticFactory1.create(WARNING);
|
||||
DiagnosticFactory0<PsiElement> NO_EXPLICIT_RETURN_TYPE_IN_API_MODE_MIGRATION = DiagnosticFactory0.create(WARNING);
|
||||
DiagnosticFactory2<PsiElement, KtModifierKeywordToken, String> WRONG_MODIFIER_CONTAINING_DECLARATION = DiagnosticFactory2.create(ERROR);
|
||||
DiagnosticFactory2<PsiElement, KtModifierKeywordToken, String> DEPRECATED_MODIFIER_CONTAINING_DECLARATION = DiagnosticFactory2.create(WARNING);
|
||||
|
||||
+2
-2
@@ -119,9 +119,9 @@ public class DefaultErrorMessages {
|
||||
MAP.put(DEPRECATED_MODIFIER_FOR_TARGET, "Modifier ''{0}'' is deprecated for ''{1}''", TO_STRING, TO_STRING);
|
||||
MAP.put(DEPRECATED_MODIFIER, "Modifier ''{0}'' is deprecated, use ''{1}'' instead", TO_STRING, TO_STRING);
|
||||
MAP.put(REDUNDANT_MODIFIER_FOR_TARGET, "Modifier ''{0}'' is redundant for ''{1}''", TO_STRING, TO_STRING);
|
||||
MAP.put(NO_EXPLICIT_VISIBILITY_IN_API_MODE, "This declaration is effectively public API and API mode is on, but no visibility is specified");
|
||||
MAP.put(NO_EXPLICIT_VISIBILITY_IN_API_MODE, "Declaration ''{0}'' is effectively public API and API mode is on, but no visibility is specified", NAME);
|
||||
MAP.put(NO_EXPLICIT_RETURN_TYPE_IN_API_MODE, "This declaration is effectively public API and API mode is on, but no explicit return type is specified");
|
||||
MAP.put(NO_EXPLICIT_VISIBILITY_IN_API_MODE_MIGRATION, "This declaration is effectively public API and API mode is on, but no visibility is specified");
|
||||
MAP.put(NO_EXPLICIT_VISIBILITY_IN_API_MODE_MIGRATION, "Declaration ''{0}'' is effectively public API and API mode is on, but no visibility is specified", NAME);
|
||||
MAP.put(NO_EXPLICIT_RETURN_TYPE_IN_API_MODE_MIGRATION, "This declaration is effectively public API and API mode is on, but no explicit return type is specified");
|
||||
MAP.put(WRONG_MODIFIER_CONTAINING_DECLARATION, "Modifier ''{0}'' is not applicable inside ''{1}''", TO_STRING, TO_STRING);
|
||||
MAP.put(DEPRECATED_MODIFIER_CONTAINING_DECLARATION, "Modifier ''{0}'' is deprecated inside ''{1}''", TO_STRING, TO_STRING);
|
||||
|
||||
+16
-29
@@ -5,12 +5,10 @@
|
||||
|
||||
package org.jetbrains.kotlin.resolve.checkers
|
||||
|
||||
import com.intellij.psi.PsiElement
|
||||
import org.jetbrains.kotlin.config.AnalysisFlags
|
||||
import org.jetbrains.kotlin.config.ApiMode
|
||||
import org.jetbrains.kotlin.config.LanguageVersionSettings
|
||||
import org.jetbrains.kotlin.descriptors.*
|
||||
import org.jetbrains.kotlin.diagnostics.DiagnosticFactory0
|
||||
import org.jetbrains.kotlin.diagnostics.Errors
|
||||
import org.jetbrains.kotlin.diagnostics.reportDiagnosticOnce
|
||||
import org.jetbrains.kotlin.lexer.KtModifierKeywordToken
|
||||
@@ -35,19 +33,19 @@ class ApiModeDeclarationChecker : DeclarationChecker {
|
||||
private fun checkVisibilityModifier(
|
||||
state: ApiMode,
|
||||
declaration: KtDeclaration,
|
||||
descriptor: DeclarationDescriptor,
|
||||
descriptor: DeclarationDescriptorWithVisibility,
|
||||
context: DeclarationCheckerContext
|
||||
) {
|
||||
val modifier = declaration.visibilityModifier()?.node?.elementType as? KtModifierKeywordToken
|
||||
if (modifier != null) return
|
||||
|
||||
if (excludeForDiagnostic(descriptor)) return
|
||||
context.selectDiagnosticAndReport(
|
||||
declaration,
|
||||
state,
|
||||
Errors.NO_EXPLICIT_VISIBILITY_IN_API_MODE,
|
||||
Errors.NO_EXPLICIT_VISIBILITY_IN_API_MODE_MIGRATION
|
||||
)
|
||||
val diagnostic =
|
||||
if (state == ApiMode.ENABLED)
|
||||
Errors.NO_EXPLICIT_VISIBILITY_IN_API_MODE.on(declaration, descriptor)
|
||||
else
|
||||
Errors.NO_EXPLICIT_VISIBILITY_IN_API_MODE_MIGRATION.on(declaration, descriptor)
|
||||
context.trace.reportDiagnosticOnce(diagnostic)
|
||||
}
|
||||
|
||||
private fun checkExplicitReturnType(
|
||||
@@ -65,26 +63,15 @@ class ApiModeDeclarationChecker : DeclarationChecker {
|
||||
checkForInternal = false,
|
||||
checkForPrivate = false
|
||||
)
|
||||
if (shouldReport) context.selectDiagnosticAndReport(
|
||||
declaration,
|
||||
state,
|
||||
Errors.NO_EXPLICIT_RETURN_TYPE_IN_API_MODE,
|
||||
Errors.NO_EXPLICIT_RETURN_TYPE_IN_API_MODE_MIGRATION
|
||||
)
|
||||
}
|
||||
|
||||
private fun DeclarationCheckerContext.selectDiagnosticAndReport(
|
||||
on: KtDeclaration,
|
||||
state: ApiMode,
|
||||
ifError: DiagnosticFactory0<PsiElement>,
|
||||
ifWarning: DiagnosticFactory0<PsiElement>
|
||||
) {
|
||||
val diagnostic =
|
||||
if (state == ApiMode.ENABLED)
|
||||
ifError.on(on)
|
||||
else
|
||||
ifWarning.on(on)
|
||||
trace.reportDiagnosticOnce(diagnostic)
|
||||
if (shouldReport) {
|
||||
val diagnostic =
|
||||
if (state == ApiMode.ENABLED)
|
||||
Errors.NO_EXPLICIT_RETURN_TYPE_IN_API_MODE.on(declaration)
|
||||
else
|
||||
Errors.NO_EXPLICIT_RETURN_TYPE_IN_API_MODE_MIGRATION
|
||||
.on(declaration)
|
||||
context.trace.reportDiagnosticOnce(diagnostic)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -288,9 +288,8 @@ fun KtDeclaration.toDescriptor(): DeclarationDescriptor? {
|
||||
return descriptor
|
||||
}
|
||||
|
||||
//TODO: code style option whether to insert redundant 'public' keyword or not
|
||||
fun KtModifierListOwner.setVisibility(visibilityModifier: KtModifierKeywordToken) {
|
||||
if (this is KtDeclaration) {
|
||||
fun KtModifierListOwner.setVisibility(visibilityModifier: KtModifierKeywordToken, addImplicitVisibilityModifier: Boolean = false) {
|
||||
if (this is KtDeclaration && !addImplicitVisibilityModifier) {
|
||||
val defaultVisibilityKeyword = implicitVisibility()
|
||||
|
||||
if (visibilityModifier == defaultVisibilityKeyword) {
|
||||
|
||||
@@ -20,9 +20,12 @@ import com.intellij.codeInsight.intention.HighPriorityAction
|
||||
import com.intellij.codeInsight.intention.IntentionAction
|
||||
import com.intellij.openapi.editor.Editor
|
||||
import com.intellij.openapi.project.Project
|
||||
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.DeclarationDescriptorWithVisibility
|
||||
import org.jetbrains.kotlin.descriptors.Visibilities
|
||||
import org.jetbrains.kotlin.descriptors.Visibility
|
||||
import org.jetbrains.kotlin.diagnostics.Diagnostic
|
||||
import org.jetbrains.kotlin.diagnostics.DiagnosticFactory1
|
||||
import org.jetbrains.kotlin.idea.core.canBeInternal
|
||||
import org.jetbrains.kotlin.idea.core.canBePrivate
|
||||
import org.jetbrains.kotlin.idea.core.canBeProtected
|
||||
@@ -42,7 +45,8 @@ import org.jetbrains.kotlin.resolve.ExposedVisibilityChecker
|
||||
open class ChangeVisibilityFix(
|
||||
element: KtModifierListOwner,
|
||||
private val elementName: String,
|
||||
private val visibilityModifier: KtModifierKeywordToken
|
||||
private val visibilityModifier: KtModifierKeywordToken,
|
||||
private val addImplicitVisibilityModifier: Boolean = false
|
||||
) : KotlinQuickFixAction<KtModifierListOwner>(element) {
|
||||
|
||||
override fun getText() = "Make '$elementName' $visibilityModifier"
|
||||
@@ -52,9 +56,9 @@ open class ChangeVisibilityFix(
|
||||
val pointer = element?.createSmartPointer()
|
||||
val originalElement = pointer?.element
|
||||
if (originalElement is KtDeclaration) {
|
||||
originalElement.runOnExpectAndAllActuals(useOnSelf = true) { it.setVisibility(visibilityModifier) }
|
||||
originalElement.runOnExpectAndAllActuals(useOnSelf = true) { it.setVisibility(visibilityModifier, addImplicitVisibilityModifier) }
|
||||
} else {
|
||||
originalElement?.setVisibility(visibilityModifier)
|
||||
originalElement?.setVisibility(visibilityModifier, addImplicitVisibilityModifier)
|
||||
}
|
||||
|
||||
val propertyAccessor = pointer?.element as? KtPropertyAccessor
|
||||
@@ -112,4 +116,21 @@ open class ChangeVisibilityFix(
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
object SetExplicitVisibilityFactory : KotlinIntentionActionsFactory() {
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
override fun doCreateActions(diagnostic: Diagnostic): List<IntentionAction> {
|
||||
val factory = diagnostic.factory as DiagnosticFactory1<*, DeclarationDescriptor>
|
||||
val descriptor = factory.cast(diagnostic).a as? DeclarationDescriptorWithVisibility ?: return emptyList()
|
||||
val element = diagnostic.psiElement as? KtModifierListOwner ?: return emptyList()
|
||||
return listOf(
|
||||
ChangeVisibilityFix(
|
||||
element,
|
||||
descriptor.name.asString(),
|
||||
KtTokens.PUBLIC_KEYWORD,
|
||||
addImplicitVisibilityModifier = true
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -151,6 +151,8 @@ class QuickFixRegistrar : QuickFixContributor {
|
||||
FORBIDDEN_BINARY_MOD.registerFactory(removeModifierFactory)
|
||||
FORBIDDEN_BINARY_MOD.registerFactory(RenameModToRemFix.Factory)
|
||||
|
||||
NO_EXPLICIT_VISIBILITY_IN_API_MODE.registerFactory(ChangeVisibilityFix.SetExplicitVisibilityFactory)
|
||||
NO_EXPLICIT_VISIBILITY_IN_API_MODE_MIGRATION.registerFactory(ChangeVisibilityFix.SetExplicitVisibilityFactory)
|
||||
NO_EXPLICIT_RETURN_TYPE_IN_API_MODE.registerActions(SpecifyTypeExplicitlyFix())
|
||||
NO_EXPLICIT_RETURN_TYPE_IN_API_MODE_MIGRATION.registerActions(SpecifyTypeExplicitlyFix())
|
||||
|
||||
|
||||
Reference in New Issue
Block a user