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, String> DEPRECATED_MODIFIER_FOR_TARGET = DiagnosticFactory2.create(WARNING);
|
||||||
DiagnosticFactory2<PsiElement, KtModifierKeywordToken, KtModifierKeywordToken> DEPRECATED_MODIFIER = DiagnosticFactory2.create(WARNING);
|
DiagnosticFactory2<PsiElement, KtModifierKeywordToken, KtModifierKeywordToken> DEPRECATED_MODIFIER = DiagnosticFactory2.create(WARNING);
|
||||||
DiagnosticFactory2<PsiElement, KtModifierKeywordToken, String> REDUNDANT_MODIFIER_FOR_TARGET = 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_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);
|
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> WRONG_MODIFIER_CONTAINING_DECLARATION = DiagnosticFactory2.create(ERROR);
|
||||||
DiagnosticFactory2<PsiElement, KtModifierKeywordToken, String> DEPRECATED_MODIFIER_CONTAINING_DECLARATION = DiagnosticFactory2.create(WARNING);
|
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_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(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(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_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(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(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);
|
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
|
package org.jetbrains.kotlin.resolve.checkers
|
||||||
|
|
||||||
import com.intellij.psi.PsiElement
|
|
||||||
import org.jetbrains.kotlin.config.AnalysisFlags
|
import org.jetbrains.kotlin.config.AnalysisFlags
|
||||||
import org.jetbrains.kotlin.config.ApiMode
|
import org.jetbrains.kotlin.config.ApiMode
|
||||||
import org.jetbrains.kotlin.config.LanguageVersionSettings
|
import org.jetbrains.kotlin.config.LanguageVersionSettings
|
||||||
import org.jetbrains.kotlin.descriptors.*
|
import org.jetbrains.kotlin.descriptors.*
|
||||||
import org.jetbrains.kotlin.diagnostics.DiagnosticFactory0
|
|
||||||
import org.jetbrains.kotlin.diagnostics.Errors
|
import org.jetbrains.kotlin.diagnostics.Errors
|
||||||
import org.jetbrains.kotlin.diagnostics.reportDiagnosticOnce
|
import org.jetbrains.kotlin.diagnostics.reportDiagnosticOnce
|
||||||
import org.jetbrains.kotlin.lexer.KtModifierKeywordToken
|
import org.jetbrains.kotlin.lexer.KtModifierKeywordToken
|
||||||
@@ -35,19 +33,19 @@ class ApiModeDeclarationChecker : DeclarationChecker {
|
|||||||
private fun checkVisibilityModifier(
|
private fun checkVisibilityModifier(
|
||||||
state: ApiMode,
|
state: ApiMode,
|
||||||
declaration: KtDeclaration,
|
declaration: KtDeclaration,
|
||||||
descriptor: DeclarationDescriptor,
|
descriptor: DeclarationDescriptorWithVisibility,
|
||||||
context: DeclarationCheckerContext
|
context: DeclarationCheckerContext
|
||||||
) {
|
) {
|
||||||
val modifier = declaration.visibilityModifier()?.node?.elementType as? KtModifierKeywordToken
|
val modifier = declaration.visibilityModifier()?.node?.elementType as? KtModifierKeywordToken
|
||||||
if (modifier != null) return
|
if (modifier != null) return
|
||||||
|
|
||||||
if (excludeForDiagnostic(descriptor)) return
|
if (excludeForDiagnostic(descriptor)) return
|
||||||
context.selectDiagnosticAndReport(
|
val diagnostic =
|
||||||
declaration,
|
if (state == ApiMode.ENABLED)
|
||||||
state,
|
Errors.NO_EXPLICIT_VISIBILITY_IN_API_MODE.on(declaration, descriptor)
|
||||||
Errors.NO_EXPLICIT_VISIBILITY_IN_API_MODE,
|
else
|
||||||
Errors.NO_EXPLICIT_VISIBILITY_IN_API_MODE_MIGRATION
|
Errors.NO_EXPLICIT_VISIBILITY_IN_API_MODE_MIGRATION.on(declaration, descriptor)
|
||||||
)
|
context.trace.reportDiagnosticOnce(diagnostic)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun checkExplicitReturnType(
|
private fun checkExplicitReturnType(
|
||||||
@@ -65,26 +63,15 @@ class ApiModeDeclarationChecker : DeclarationChecker {
|
|||||||
checkForInternal = false,
|
checkForInternal = false,
|
||||||
checkForPrivate = false
|
checkForPrivate = false
|
||||||
)
|
)
|
||||||
if (shouldReport) context.selectDiagnosticAndReport(
|
if (shouldReport) {
|
||||||
declaration,
|
val diagnostic =
|
||||||
state,
|
if (state == ApiMode.ENABLED)
|
||||||
Errors.NO_EXPLICIT_RETURN_TYPE_IN_API_MODE,
|
Errors.NO_EXPLICIT_RETURN_TYPE_IN_API_MODE.on(declaration)
|
||||||
Errors.NO_EXPLICIT_RETURN_TYPE_IN_API_MODE_MIGRATION
|
else
|
||||||
)
|
Errors.NO_EXPLICIT_RETURN_TYPE_IN_API_MODE_MIGRATION
|
||||||
}
|
.on(declaration)
|
||||||
|
context.trace.reportDiagnosticOnce(diagnostic)
|
||||||
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)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -288,9 +288,8 @@ fun KtDeclaration.toDescriptor(): DeclarationDescriptor? {
|
|||||||
return descriptor
|
return descriptor
|
||||||
}
|
}
|
||||||
|
|
||||||
//TODO: code style option whether to insert redundant 'public' keyword or not
|
fun KtModifierListOwner.setVisibility(visibilityModifier: KtModifierKeywordToken, addImplicitVisibilityModifier: Boolean = false) {
|
||||||
fun KtModifierListOwner.setVisibility(visibilityModifier: KtModifierKeywordToken) {
|
if (this is KtDeclaration && !addImplicitVisibilityModifier) {
|
||||||
if (this is KtDeclaration) {
|
|
||||||
val defaultVisibilityKeyword = implicitVisibility()
|
val defaultVisibilityKeyword = implicitVisibility()
|
||||||
|
|
||||||
if (visibilityModifier == defaultVisibilityKeyword) {
|
if (visibilityModifier == defaultVisibilityKeyword) {
|
||||||
|
|||||||
@@ -20,9 +20,12 @@ import com.intellij.codeInsight.intention.HighPriorityAction
|
|||||||
import com.intellij.codeInsight.intention.IntentionAction
|
import com.intellij.codeInsight.intention.IntentionAction
|
||||||
import com.intellij.openapi.editor.Editor
|
import com.intellij.openapi.editor.Editor
|
||||||
import com.intellij.openapi.project.Project
|
import com.intellij.openapi.project.Project
|
||||||
|
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
|
||||||
import org.jetbrains.kotlin.descriptors.DeclarationDescriptorWithVisibility
|
import org.jetbrains.kotlin.descriptors.DeclarationDescriptorWithVisibility
|
||||||
import org.jetbrains.kotlin.descriptors.Visibilities
|
import org.jetbrains.kotlin.descriptors.Visibilities
|
||||||
import org.jetbrains.kotlin.descriptors.Visibility
|
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.canBeInternal
|
||||||
import org.jetbrains.kotlin.idea.core.canBePrivate
|
import org.jetbrains.kotlin.idea.core.canBePrivate
|
||||||
import org.jetbrains.kotlin.idea.core.canBeProtected
|
import org.jetbrains.kotlin.idea.core.canBeProtected
|
||||||
@@ -42,7 +45,8 @@ import org.jetbrains.kotlin.resolve.ExposedVisibilityChecker
|
|||||||
open class ChangeVisibilityFix(
|
open class ChangeVisibilityFix(
|
||||||
element: KtModifierListOwner,
|
element: KtModifierListOwner,
|
||||||
private val elementName: String,
|
private val elementName: String,
|
||||||
private val visibilityModifier: KtModifierKeywordToken
|
private val visibilityModifier: KtModifierKeywordToken,
|
||||||
|
private val addImplicitVisibilityModifier: Boolean = false
|
||||||
) : KotlinQuickFixAction<KtModifierListOwner>(element) {
|
) : KotlinQuickFixAction<KtModifierListOwner>(element) {
|
||||||
|
|
||||||
override fun getText() = "Make '$elementName' $visibilityModifier"
|
override fun getText() = "Make '$elementName' $visibilityModifier"
|
||||||
@@ -52,9 +56,9 @@ open class ChangeVisibilityFix(
|
|||||||
val pointer = element?.createSmartPointer()
|
val pointer = element?.createSmartPointer()
|
||||||
val originalElement = pointer?.element
|
val originalElement = pointer?.element
|
||||||
if (originalElement is KtDeclaration) {
|
if (originalElement is KtDeclaration) {
|
||||||
originalElement.runOnExpectAndAllActuals(useOnSelf = true) { it.setVisibility(visibilityModifier) }
|
originalElement.runOnExpectAndAllActuals(useOnSelf = true) { it.setVisibility(visibilityModifier, addImplicitVisibilityModifier) }
|
||||||
} else {
|
} else {
|
||||||
originalElement?.setVisibility(visibilityModifier)
|
originalElement?.setVisibility(visibilityModifier, addImplicitVisibilityModifier)
|
||||||
}
|
}
|
||||||
|
|
||||||
val propertyAccessor = pointer?.element as? KtPropertyAccessor
|
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(removeModifierFactory)
|
||||||
FORBIDDEN_BINARY_MOD.registerFactory(RenameModToRemFix.Factory)
|
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.registerActions(SpecifyTypeExplicitlyFix())
|
||||||
NO_EXPLICIT_RETURN_TYPE_IN_API_MODE_MIGRATION.registerActions(SpecifyTypeExplicitlyFix())
|
NO_EXPLICIT_RETURN_TYPE_IN_API_MODE_MIGRATION.registerActions(SpecifyTypeExplicitlyFix())
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user