Fixing issues after code review
This commit is contained in:
+42
-15
@@ -20,10 +20,14 @@ import com.intellij.codeInsight.intention.HighPriorityAction
|
||||
import com.intellij.openapi.editor.Editor
|
||||
import com.intellij.openapi.util.TextRange
|
||||
import com.intellij.psi.PsiElement
|
||||
import org.jetbrains.kotlin.descriptors.*
|
||||
import org.jetbrains.kotlin.idea.caches.resolve.analyze
|
||||
import org.jetbrains.kotlin.idea.caches.resolve.resolveToDescriptor
|
||||
import org.jetbrains.kotlin.lexer.JetModifierKeywordToken
|
||||
import org.jetbrains.kotlin.lexer.JetTokens
|
||||
import org.jetbrains.kotlin.psi.*
|
||||
import org.jetbrains.kotlin.psi.psiUtil.startOffset
|
||||
import org.jetbrains.kotlin.resolve.BindingContext
|
||||
|
||||
public open class ChangeVisibilityModifierIntention protected(
|
||||
val modifier: JetModifierKeywordToken
|
||||
@@ -32,19 +36,33 @@ public open class ChangeVisibilityModifierIntention protected(
|
||||
override fun applicabilityRange(element: JetDeclaration): TextRange? {
|
||||
val modifierList = element.getModifierList()
|
||||
if (modifierList?.hasModifier(modifier) ?: false) return null
|
||||
if (modifierList?.hasModifier(JetTokens.OVERRIDE_KEYWORD) ?: false) return null
|
||||
|
||||
// val descriptor = element.resolveToDescriptor() as? DeclarationDescriptorWithVisibility ?: return null
|
||||
val bindingContext = element.analyze()
|
||||
var descriptor = (if (element is JetPrimaryConstructor) //TODO: temporary code
|
||||
((element.getParent() as JetClass).resolveToDescriptor() as ClassDescriptor).getUnsubstitutedPrimaryConstructor()
|
||||
else
|
||||
bindingContext[BindingContext.DECLARATION_TO_DESCRIPTOR, element]) as? DeclarationDescriptorWithVisibility ?: return null
|
||||
if (descriptor is ValueParameterDescriptor) {
|
||||
descriptor = bindingContext[BindingContext.VALUE_PARAMETER_AS_PROPERTY, descriptor] ?: return null
|
||||
}
|
||||
val targetVisibility = modifier.toVisibility()
|
||||
if (descriptor.getVisibility() == targetVisibility) return null
|
||||
|
||||
if (modifierList?.hasModifier(JetTokens.OVERRIDE_KEYWORD) ?: false) {
|
||||
val callableDescriptor = descriptor as? CallableDescriptor ?: return null
|
||||
// cannot make visibility less than (or non-comparable with) any of the supers
|
||||
if (callableDescriptor.getOverriddenDescriptors().any { val c = Visibilities.compare(it.getVisibility(), targetVisibility); c == null || c > 0 }) return null
|
||||
}
|
||||
|
||||
setText(defaultText)
|
||||
|
||||
val modifierToChange = modifierToChange(element)
|
||||
if (modifierToChange != null) {
|
||||
return modifierToChange.getTextRange()
|
||||
val modifierElement = element.visibilityModifier()
|
||||
if (modifierElement != null) {
|
||||
return modifierElement.getTextRange()
|
||||
}
|
||||
|
||||
val defaultRange = canAddVisibilityModifier(element) ?: return null
|
||||
|
||||
val defaultVisibility = if (element is JetPrimaryConstructor) JetTokens.PUBLIC_KEYWORD else JetTokens.INTERNAL_KEYWORD
|
||||
if (modifier == defaultVisibility) return null
|
||||
val defaultRange = noModifierYetApplicabilityRange(element) ?: return null
|
||||
|
||||
if (element is JetPrimaryConstructor && defaultRange.isEmpty()) {
|
||||
setText("Make primary constructor ${modifier.getValue()}") // otherwise it may be confusing
|
||||
@@ -57,30 +75,39 @@ public open class ChangeVisibilityModifierIntention protected(
|
||||
}
|
||||
|
||||
override fun applyTo(element: JetDeclaration, editor: Editor) {
|
||||
val modifierToChange = modifierToChange(element)
|
||||
val modifierToChange = element.visibilityModifier()
|
||||
if (modifierToChange != null) {
|
||||
val newModifier = JetPsiFactory(element).createModifierList(modifier).getModifier(modifier)!!
|
||||
modifierToChange.replace(newModifier)
|
||||
modifierToChange.replace(JetPsiFactory(element).createModifier(modifier))
|
||||
}
|
||||
else {
|
||||
element.addModifier(modifier)
|
||||
}
|
||||
}
|
||||
|
||||
private fun modifierToChange(element: JetDeclaration): PsiElement? {
|
||||
val modifierList = element.getModifierList() ?: return null
|
||||
private fun JetDeclaration.visibilityModifier(): PsiElement? {
|
||||
val modifierList = getModifierList() ?: return null
|
||||
return JetTokens.VISIBILITY_MODIFIERS.getTypes()
|
||||
.asSequence()
|
||||
.map { modifierList.getModifier(it as JetModifierKeywordToken) }
|
||||
.firstOrNull { it != null } ?: return null
|
||||
}
|
||||
|
||||
private fun canAddVisibilityModifier(declaration: JetDeclaration): TextRange? {
|
||||
private fun JetModifierKeywordToken.toVisibility(): Visibility {
|
||||
return when (this) {
|
||||
JetTokens.PUBLIC_KEYWORD -> Visibilities.PUBLIC
|
||||
JetTokens.PRIVATE_KEYWORD -> Visibilities.PRIVATE
|
||||
JetTokens.PROTECTED_KEYWORD -> Visibilities.PROTECTED
|
||||
JetTokens.INTERNAL_KEYWORD -> Visibilities.INTERNAL
|
||||
else -> throw IllegalArgumentException("Unknown visibility modifier:$this")
|
||||
}
|
||||
}
|
||||
|
||||
private fun noModifierYetApplicabilityRange(declaration: JetDeclaration): TextRange? {
|
||||
if (JetPsiUtil.isLocal(declaration)) return null
|
||||
return when (declaration) {
|
||||
is JetNamedFunction -> declaration.getFunKeyword()?.getTextRange()
|
||||
is JetProperty -> declaration.getValOrVarNode().getTextRange()
|
||||
is JetClass -> declaration.getClassOrTraitKeyword()?.getTextRange()
|
||||
is JetClass -> declaration.getClassOrInterfaceKeyword()?.getTextRange()
|
||||
is JetObjectDeclaration -> declaration.getObjectKeyword().getTextRange()
|
||||
is JetPrimaryConstructor -> declaration.getValueParameterList()?.let { TextRange.from(it.startOffset, 0) } //TODO: use constructor keyword if exist
|
||||
is JetSecondaryConstructor -> declaration.getConstructorKeyword().getTextRange()
|
||||
|
||||
@@ -114,6 +114,7 @@ public object SuperClassNotInitialized : JetIntentionActionsFactory() {
|
||||
}
|
||||
|
||||
override fun getText(): String {
|
||||
// TODO: not too long
|
||||
return "Add constructor parameters from " +
|
||||
superConstructor.getContainingDeclaration().getName().asString() +
|
||||
superConstructor.getValueParameters().map { DescriptorRenderer.SHORT_NAMES_IN_TYPES.renderType(it.getType()) }.joinToString(", ", "(", ")")
|
||||
@@ -132,7 +133,9 @@ public object SuperClassNotInitialized : JetIntentionActionsFactory() {
|
||||
val parametersToAdd = ArrayList<JetParameter>()
|
||||
for (parameter in superParameters) {
|
||||
val name = renderer.renderName(parameter.getName())
|
||||
parameterNames.add(name)
|
||||
val varargElementType = parameter.getVarargElementType()
|
||||
|
||||
parameterNames.add(if (varargElementType != null) "*$name" else name)
|
||||
|
||||
val nameString = parameter.getName().asString()
|
||||
val existingParameter = oldParameters.firstOrNull { it.getName() == nameString }
|
||||
@@ -141,7 +144,10 @@ public object SuperClassNotInitialized : JetIntentionActionsFactory() {
|
||||
if (type.isSubtypeOf(parameter.getType())) continue // use existing parameter
|
||||
}
|
||||
|
||||
val parameterText = name + ":" + renderer.renderType(parameter.getType())
|
||||
val parameterText = if (varargElementType != null)
|
||||
"vararg " + name + ":" + renderer.renderType(varargElementType)
|
||||
else
|
||||
name + ":" + renderer.renderType(parameter.getType())
|
||||
parametersToAdd.add(factory.createParameter(parameterText))
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user