diff --git a/idea/src/org/jetbrains/kotlin/idea/quickfix/ChangeVisibilityFix.kt b/idea/src/org/jetbrains/kotlin/idea/quickfix/ChangeVisibilityFix.kt new file mode 100644 index 00000000000..bef1207cfaa --- /dev/null +++ b/idea/src/org/jetbrains/kotlin/idea/quickfix/ChangeVisibilityFix.kt @@ -0,0 +1,79 @@ +/* + * Copyright 2010-2016 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jetbrains.kotlin.idea.quickfix + +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 com.intellij.psi.PsiFile +import org.jetbrains.kotlin.descriptors.DeclarationDescriptorWithVisibility +import org.jetbrains.kotlin.descriptors.Visibilities +import org.jetbrains.kotlin.descriptors.Visibility +import org.jetbrains.kotlin.idea.core.canBeProtected +import org.jetbrains.kotlin.idea.core.setVisibility +import org.jetbrains.kotlin.lexer.KtModifierKeywordToken +import org.jetbrains.kotlin.lexer.KtTokens +import org.jetbrains.kotlin.psi.KtFile +import org.jetbrains.kotlin.psi.KtModifierListOwner +import org.jetbrains.kotlin.resolve.ExposedVisibilityChecker + +open class ChangeVisibilityFix( + element: KtModifierListOwner, + protected val elementName: String, + protected val visibilityModifier: KtModifierKeywordToken +) : KotlinQuickFixAction(element) { + + override fun getText() = "Make $elementName $visibilityModifier" + override fun getFamilyName() = "Make $visibilityModifier" + + override fun invoke(project: Project, editor: Editor?, file: KtFile) { + element.setVisibility(visibilityModifier) + } + + protected class ChangeToPublicFix(element: KtModifierListOwner, elementName: String) : + ChangeVisibilityFix(element, elementName, KtTokens.PUBLIC_KEYWORD), HighPriorityAction + + protected class ChangeToProtectedFix(element: KtModifierListOwner, elementName: String) : + ChangeVisibilityFix(element, elementName, KtTokens.PROTECTED_KEYWORD) { + + override fun isAvailable(project: Project, editor: Editor?, file: PsiFile) = + super.isAvailable(project, editor, file) && element.canBeProtected() + } + + protected class ChangeToInternalFix(element: KtModifierListOwner, elementName: String) : + ChangeVisibilityFix(element, elementName, KtTokens.INTERNAL_KEYWORD) + + companion object { + fun create( + declaration: KtModifierListOwner, + descriptor: DeclarationDescriptorWithVisibility, + targetVisibility: Visibility + ) : IntentionAction? { + if (!ExposedVisibilityChecker().checkDeclarationWithVisibility(declaration, descriptor, targetVisibility)) return null + + val name = descriptor.name.asString() + + return when (targetVisibility) { + Visibilities.INTERNAL -> ChangeToInternalFix(declaration, name) + Visibilities.PROTECTED -> ChangeToProtectedFix(declaration, name) + Visibilities.PUBLIC -> ChangeToPublicFix(declaration, name) + else -> null + } + } + } +} \ No newline at end of file diff --git a/idea/src/org/jetbrains/kotlin/idea/quickfix/IncreaseExposedVisibilityFactory.kt b/idea/src/org/jetbrains/kotlin/idea/quickfix/IncreaseExposedVisibilityFactory.kt new file mode 100644 index 00000000000..4566f08222d --- /dev/null +++ b/idea/src/org/jetbrains/kotlin/idea/quickfix/IncreaseExposedVisibilityFactory.kt @@ -0,0 +1,53 @@ +/* + * Copyright 2010-2016 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jetbrains.kotlin.idea.quickfix + +import com.intellij.codeInsight.intention.IntentionAction +import org.jetbrains.kotlin.descriptors.DeclarationDescriptorWithVisibility +import org.jetbrains.kotlin.descriptors.DescriptorWithRelation +import org.jetbrains.kotlin.descriptors.EffectiveVisibility +import org.jetbrains.kotlin.descriptors.EffectiveVisibility.Permissiveness.LESS +import org.jetbrains.kotlin.descriptors.Visibilities.PROTECTED +import org.jetbrains.kotlin.descriptors.Visibilities.PUBLIC +import org.jetbrains.kotlin.diagnostics.Diagnostic +import org.jetbrains.kotlin.diagnostics.DiagnosticFactory3 +import org.jetbrains.kotlin.psi.KtDeclaration +import org.jetbrains.kotlin.psi.KtModifierListOwner +import org.jetbrains.kotlin.psi.psiUtil.getParentOfType +import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils + +object IncreaseExposedVisibilityFactory : KotlinSingleIntentionActionFactory() { + override fun createAction(diagnostic: Diagnostic): IntentionAction? { + @Suppress("UNCHECKED_CAST") + val factory = diagnostic.factory as DiagnosticFactory3<*, EffectiveVisibility, DescriptorWithRelation, EffectiveVisibility> + val exposedDiagnostic = factory.cast(diagnostic) + val exposedDescriptor = exposedDiagnostic.b.descriptor as? DeclarationDescriptorWithVisibility ?: return null + val exposedDeclaration = DescriptorToSourceUtils.getSourceFromDescriptor(exposedDescriptor) as? KtModifierListOwner ?: return null + val exposedVisibility = exposedDiagnostic.c + val exposingVisibility = exposedDiagnostic.a + val boundVisibility = when (exposedVisibility.relation(exposingVisibility)) { + LESS -> exposingVisibility.toVisibility() + else -> PUBLIC + } + val exposingDeclaration = diagnostic.psiElement.getParentOfType(true) + val targetVisibility = when (boundVisibility) { + PROTECTED -> if (exposedDeclaration.parent == exposingDeclaration?.parent) PROTECTED else PUBLIC + else -> boundVisibility + } + return ChangeVisibilityFix.create(exposedDeclaration, exposedDescriptor, targetVisibility) + } +} \ No newline at end of file diff --git a/idea/src/org/jetbrains/kotlin/idea/quickfix/IncreaseVisibilityFix.kt b/idea/src/org/jetbrains/kotlin/idea/quickfix/IncreaseVisibilityFix.kt deleted file mode 100644 index 34eccecf09c..00000000000 --- a/idea/src/org/jetbrains/kotlin/idea/quickfix/IncreaseVisibilityFix.kt +++ /dev/null @@ -1,129 +0,0 @@ -/* - * Copyright 2010-2015 JetBrains s.r.o. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.jetbrains.kotlin.idea.quickfix - -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 com.intellij.psi.PsiFile -import org.jetbrains.kotlin.descriptors.* -import org.jetbrains.kotlin.descriptors.EffectiveVisibility.Permissiveness.LESS -import org.jetbrains.kotlin.descriptors.Visibilities.* -import org.jetbrains.kotlin.diagnostics.Diagnostic -import org.jetbrains.kotlin.diagnostics.DiagnosticFactory3 -import org.jetbrains.kotlin.idea.caches.resolve.analyze -import org.jetbrains.kotlin.idea.core.canBeProtected -import org.jetbrains.kotlin.lexer.KtModifierKeywordToken -import org.jetbrains.kotlin.psi.KtElement -import org.jetbrains.kotlin.psi.KtFile -import org.jetbrains.kotlin.psi.KtModifierListOwner -import org.jetbrains.kotlin.resolve.BindingContext -import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils -import org.jetbrains.kotlin.resolve.DescriptorUtils -import org.jetbrains.kotlin.resolve.ExposedVisibilityChecker -import org.jetbrains.kotlin.resolve.descriptorUtil.module -import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode -import org.jetbrains.kotlin.idea.core.setVisibility -import org.jetbrains.kotlin.lexer.KtTokens.* -import org.jetbrains.kotlin.psi.KtDeclaration -import org.jetbrains.kotlin.psi.psiUtil.getParentOfType - -open class IncreaseVisibilityFix( - element: KtModifierListOwner, - private val elementName: String, - private val visibilityModifier: KtModifierKeywordToken -) : KotlinQuickFixAction(element), CleanupFix { - - override fun getText() = "Make $elementName $visibilityModifier" - override fun getFamilyName() = "Make $visibilityModifier" - - override fun invoke(project: Project, editor: Editor?, file: KtFile) { - element.setVisibility(visibilityModifier) - } - - class IncreaseToPublicFix(element: KtModifierListOwner, elementName: String) : - IncreaseVisibilityFix(element, elementName, PUBLIC_KEYWORD), HighPriorityAction - - class IncreaseToProtectedFix(element: KtModifierListOwner, elementName: String) : - IncreaseVisibilityFix(element, elementName, PROTECTED_KEYWORD) { - - override fun isAvailable(project: Project, editor: Editor?, file: PsiFile) = - super.isAvailable(project, editor, file) && element.canBeProtected() - } - - class IncreaseToInternalFix(element: KtModifierListOwner, elementName: String) : - IncreaseVisibilityFix(element, elementName, INTERNAL_KEYWORD) - - companion object : KotlinSingleIntentionActionFactory() { - - private fun create( - declaration: KtModifierListOwner, - descriptor: DeclarationDescriptorWithVisibility, - targetVisibility: Visibility - ) : IntentionAction? { - if (!ExposedVisibilityChecker().checkDeclarationWithVisibility(declaration, descriptor, targetVisibility)) return null - - val name = descriptor.name.asString() - - return when (targetVisibility) { - INTERNAL -> IncreaseToInternalFix(declaration, name) - PROTECTED -> IncreaseToProtectedFix(declaration, name) - PUBLIC -> IncreaseToPublicFix(declaration, name) - else -> null - } - } - - override fun createAction(diagnostic: Diagnostic): IntentionAction? { - val element = diagnostic.psiElement as? KtElement ?: return null - val context = element.analyze(BodyResolveMode.PARTIAL) - val usageModule = context.get(BindingContext.FILE_TO_PACKAGE_FRAGMENT, element.getContainingKtFile())?.module - - @Suppress("UNCHECKED_CAST") - val factory = diagnostic.factory as DiagnosticFactory3<*, DeclarationDescriptor, *, DeclarationDescriptor> - val descriptor = factory.cast(diagnostic).c as? DeclarationDescriptorWithVisibility ?: return null - val declaration = DescriptorToSourceUtils.getSourceFromDescriptor(descriptor) as? KtModifierListOwner ?: return null - - val module = DescriptorUtils.getContainingModule(descriptor) - val targetVisibility = if (module != usageModule || descriptor.visibility != PRIVATE) PUBLIC else INTERNAL - - return create(declaration, descriptor, targetVisibility) - } - } - - object Exposed : KotlinSingleIntentionActionFactory() { - override fun createAction(diagnostic: Diagnostic): IntentionAction? { - @Suppress("UNCHECKED_CAST") - val factory = diagnostic.factory as DiagnosticFactory3<*, EffectiveVisibility, DescriptorWithRelation, EffectiveVisibility> - val exposedDiagnostic = factory.cast(diagnostic) - val exposedDescriptor = exposedDiagnostic.b.descriptor as? DeclarationDescriptorWithVisibility ?: return null - val exposedDeclaration = DescriptorToSourceUtils.getSourceFromDescriptor(exposedDescriptor) as? KtModifierListOwner ?: return null - val exposedVisibility = exposedDiagnostic.c - val exposingVisibility = exposedDiagnostic.a - val boundVisibility = when (exposedVisibility.relation(exposingVisibility)) { - LESS -> exposingVisibility.toVisibility() - else -> PUBLIC - } - val exposingDeclaration = diagnostic.psiElement.getParentOfType(true) - val targetVisibility = when (boundVisibility) { - PROTECTED -> if (exposedDeclaration.parent == exposingDeclaration?.parent) PROTECTED else PUBLIC - else -> boundVisibility - } - return create(exposedDeclaration, exposedDescriptor, targetVisibility) - } - } -} diff --git a/idea/src/org/jetbrains/kotlin/idea/quickfix/MakeVisibleFactory.kt b/idea/src/org/jetbrains/kotlin/idea/quickfix/MakeVisibleFactory.kt new file mode 100644 index 00000000000..0d374a6fbcf --- /dev/null +++ b/idea/src/org/jetbrains/kotlin/idea/quickfix/MakeVisibleFactory.kt @@ -0,0 +1,52 @@ +/* + * Copyright 2010-2016 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jetbrains.kotlin.idea.quickfix + +import com.intellij.codeInsight.intention.IntentionAction +import org.jetbrains.kotlin.descriptors.DeclarationDescriptor +import org.jetbrains.kotlin.descriptors.DeclarationDescriptorWithVisibility +import org.jetbrains.kotlin.descriptors.Visibilities +import org.jetbrains.kotlin.descriptors.Visibilities.* +import org.jetbrains.kotlin.diagnostics.Diagnostic +import org.jetbrains.kotlin.diagnostics.DiagnosticFactory3 +import org.jetbrains.kotlin.idea.caches.resolve.analyze +import org.jetbrains.kotlin.psi.KtElement +import org.jetbrains.kotlin.psi.KtModifierListOwner +import org.jetbrains.kotlin.resolve.BindingContext +import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils +import org.jetbrains.kotlin.resolve.DescriptorUtils +import org.jetbrains.kotlin.resolve.descriptorUtil.module +import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode + +object MakeVisibleFactory : KotlinSingleIntentionActionFactory() { + + override fun createAction(diagnostic: Diagnostic): IntentionAction? { + val element = diagnostic.psiElement as? KtElement ?: return null + val context = element.analyze(BodyResolveMode.PARTIAL) + val usageModule = context.get(BindingContext.FILE_TO_PACKAGE_FRAGMENT, element.getContainingKtFile())?.module + + @Suppress("UNCHECKED_CAST") + val factory = diagnostic.factory as DiagnosticFactory3<*, DeclarationDescriptor, *, DeclarationDescriptor> + val descriptor = factory.cast(diagnostic).c as? DeclarationDescriptorWithVisibility ?: return null + val declaration = DescriptorToSourceUtils.getSourceFromDescriptor(descriptor) as? KtModifierListOwner ?: return null + + val module = DescriptorUtils.getContainingModule(descriptor) + val targetVisibility = if (module != usageModule || descriptor.visibility != PRIVATE) PUBLIC else INTERNAL + + return ChangeVisibilityFix.create(declaration, descriptor, targetVisibility) + } +} \ No newline at end of file diff --git a/idea/src/org/jetbrains/kotlin/idea/quickfix/QuickFixRegistrar.kt b/idea/src/org/jetbrains/kotlin/idea/quickfix/QuickFixRegistrar.kt index 4cf56023a84..6626f22e783 100644 --- a/idea/src/org/jetbrains/kotlin/idea/quickfix/QuickFixRegistrar.kt +++ b/idea/src/org/jetbrains/kotlin/idea/quickfix/QuickFixRegistrar.kt @@ -149,17 +149,17 @@ class QuickFixRegistrar : QuickFixContributor { CANNOT_CHANGE_ACCESS_PRIVILEGE.registerFactory(ChangeVisibilityModifierFix) CANNOT_WEAKEN_ACCESS_PRIVILEGE.registerFactory(ChangeVisibilityModifierFix) - INVISIBLE_REFERENCE.registerFactory(IncreaseVisibilityFix) - INVISIBLE_MEMBER.registerFactory(IncreaseVisibilityFix) - INVISIBLE_SETTER.registerFactory(IncreaseVisibilityFix) + INVISIBLE_REFERENCE.registerFactory(MakeVisibleFactory) + INVISIBLE_MEMBER.registerFactory(MakeVisibleFactory) + INVISIBLE_SETTER.registerFactory(MakeVisibleFactory) - EXPOSED_FUNCTION_RETURN_TYPE.registerFactory(IncreaseVisibilityFix.Exposed) - EXPOSED_PARAMETER_TYPE.registerFactory(IncreaseVisibilityFix.Exposed) - EXPOSED_PROPERTY_TYPE.registerFactory(IncreaseVisibilityFix.Exposed) - EXPOSED_RECEIVER_TYPE.registerFactory(IncreaseVisibilityFix.Exposed) - EXPOSED_SUPER_CLASS.registerFactory(IncreaseVisibilityFix.Exposed) - EXPOSED_SUPER_INTERFACE.registerFactory(IncreaseVisibilityFix.Exposed) - EXPOSED_TYPE_PARAMETER_BOUND.registerFactory(IncreaseVisibilityFix.Exposed) + EXPOSED_FUNCTION_RETURN_TYPE.registerFactory(IncreaseExposedVisibilityFactory) + EXPOSED_PARAMETER_TYPE.registerFactory(IncreaseExposedVisibilityFactory) + EXPOSED_PROPERTY_TYPE.registerFactory(IncreaseExposedVisibilityFactory) + EXPOSED_RECEIVER_TYPE.registerFactory(IncreaseExposedVisibilityFactory) + EXPOSED_SUPER_CLASS.registerFactory(IncreaseExposedVisibilityFactory) + EXPOSED_SUPER_INTERFACE.registerFactory(IncreaseExposedVisibilityFactory) + EXPOSED_TYPE_PARAMETER_BOUND.registerFactory(IncreaseExposedVisibilityFactory) REDUNDANT_NULLABLE.registerFactory(RemoveNullableFix.Factory(RemoveNullableFix.NullableKind.REDUNDANT)) NULLABLE_SUPERTYPE.registerFactory(RemoveNullableFix.Factory(RemoveNullableFix.NullableKind.SUPERTYPE))