MakeOveriddenMembersOpen: J2K, cleanup, de-i18n

This commit is contained in:
Dmitry Jemerov
2015-09-17 15:36:31 +02:00
parent 1fee5c23e0
commit 33d70b1a57
3 changed files with 82 additions and 124 deletions
@@ -14,7 +14,6 @@ add.init.keyword.in.whole.project=Add 'init' keyword in whole project
add.init.keyword.in.whole.project.modal.title=Adding 'init' keyword in whole project add.init.keyword.in.whole.project.modal.title=Adding 'init' keyword in whole project
add.init.keyword.in.whole.project.family=Add 'init' keyword in whole project add.init.keyword.in.whole.project.family=Add 'init' keyword in whole project
insert.delegation.call=Insert ''{0}()'' call insert.delegation.call=Insert ''{0}()'' call
make.element.in.classifiers.open=Make ''{0}'' in {1} open
make.class.annotation.class=Make ''{0}'' an annotation class make.class.annotation.class=Make ''{0}'' an annotation class
make.class.annotation.class.family=Make Class an Annotation Class make.class.annotation.class.family=Make Class an Annotation Class
add.star.projections=Add ''{0}'' add.star.projections=Add ''{0}''
@@ -14,149 +14,108 @@
* limitations under the License. * limitations under the License.
*/ */
package org.jetbrains.kotlin.idea.quickfix; package org.jetbrains.kotlin.idea.quickfix
import com.google.common.collect.Sets; 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 com.intellij.psi.PsiFile
import com.intellij.openapi.util.Condition; import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor
import com.intellij.psi.PsiElement; import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor.Kind.DECLARATION
import com.intellij.psi.PsiFile; import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor.Kind.DELEGATION
import com.intellij.util.IncorrectOperationException; import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor.Kind.FAKE_OVERRIDE
import com.intellij.util.containers.ContainerUtil; import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor.Kind.SYNTHESIZED
import org.jetbrains.annotations.NotNull; import org.jetbrains.kotlin.diagnostics.Diagnostic
import org.jetbrains.annotations.Nullable; import org.jetbrains.kotlin.idea.caches.resolve.resolveToDescriptor
import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor; import org.jetbrains.kotlin.idea.core.quickfix.QuickFixUtil
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor; import org.jetbrains.kotlin.lexer.JetTokens.OPEN_KEYWORD
import org.jetbrains.kotlin.diagnostics.Diagnostic; import org.jetbrains.kotlin.psi.JetCallableDeclaration
import org.jetbrains.kotlin.idea.JetBundle; import org.jetbrains.kotlin.psi.JetDeclaration
import org.jetbrains.kotlin.idea.caches.resolve.ResolutionUtils; import org.jetbrains.kotlin.psi.JetFile
import org.jetbrains.kotlin.idea.core.quickfix.QuickFixUtil; import org.jetbrains.kotlin.psi.psiUtil.getNonStrictParentOfType
import org.jetbrains.kotlin.psi.JetCallableDeclaration; import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils
import org.jetbrains.kotlin.psi.JetDeclaration; import java.util.*
import org.jetbrains.kotlin.psi.JetFile;
import java.util.*; public class MakeOverriddenMemberOpenFix(declaration: JetDeclaration) : JetIntentionAction<JetDeclaration>(declaration) {
private val overriddenNonOverridableMembers = ArrayList<JetCallableDeclaration>()
private val containingDeclarationsNames = ArrayList<String>()
import static org.jetbrains.kotlin.descriptors.CallableMemberDescriptor.Kind.*; override fun isAvailable(project: Project, editor: Editor, file: PsiFile): Boolean {
import static org.jetbrains.kotlin.lexer.JetTokens.OPEN_KEYWORD; if (!super.isAvailable(project, editor, file) || file !is JetFile) {
import static org.jetbrains.kotlin.resolve.DescriptorToSourceUtils.descriptorToDeclaration; return false
public class MakeOverriddenMemberOpenFix extends JetIntentionAction<JetDeclaration> {
private final List<JetCallableDeclaration> overriddenNonOverridableMembers = new ArrayList<JetCallableDeclaration>();
private final List<String> containingDeclarationsNames = new ArrayList<String>();
public MakeOverriddenMemberOpenFix(@NotNull JetDeclaration declaration) {
super(declaration);
}
@Override
public boolean isAvailable(@NotNull Project project, Editor editor, PsiFile file) {
if (!super.isAvailable(project, editor, file) || !(file instanceof JetFile)) {
return false;
} }
// When running single test 'isAvailable()' is invoked multiple times, so we need to clear lists. // When running single test 'isAvailable()' is invoked multiple times, so we need to clear lists.
overriddenNonOverridableMembers.clear(); overriddenNonOverridableMembers.clear()
containingDeclarationsNames.clear(); containingDeclarationsNames.clear()
DeclarationDescriptor descriptor = ResolutionUtils.resolveToDescriptor(element); val descriptor = element.resolveToDescriptor()
if (!(descriptor instanceof CallableMemberDescriptor)) return false; if (descriptor !is CallableMemberDescriptor) return false
for (CallableMemberDescriptor overriddenDescriptor : getAllDeclaredNonOverridableOverriddenDescriptors( for (overriddenDescriptor in getAllDeclaredNonOverridableOverriddenDescriptors(
(CallableMemberDescriptor) descriptor)) { descriptor)) {
assert overriddenDescriptor.getKind() == DECLARATION : "Can only be applied to declarations."; assert(overriddenDescriptor.kind == DECLARATION) { "Can only be applied to declarations." }
PsiElement overriddenMember = descriptorToDeclaration(overriddenDescriptor); val overriddenMember = DescriptorToSourceUtils.descriptorToDeclaration(overriddenDescriptor)
if (overriddenMember == null || !QuickFixUtil.canModifyElement(overriddenMember) || !(overriddenMember instanceof JetCallableDeclaration)) { if (overriddenMember == null || !QuickFixUtil.canModifyElement(overriddenMember) || overriddenMember !is JetCallableDeclaration) {
return false; return false
} }
String containingDeclarationName = overriddenDescriptor.getContainingDeclaration().getName().asString(); val containingDeclarationName = overriddenDescriptor.containingDeclaration.name.asString()
overriddenNonOverridableMembers.add((JetCallableDeclaration) overriddenMember); overriddenNonOverridableMembers.add(overriddenMember)
containingDeclarationsNames.add(containingDeclarationName); containingDeclarationsNames.add(containingDeclarationName)
} }
return overriddenNonOverridableMembers.size() > 0; return overriddenNonOverridableMembers.size() > 0
} }
@NotNull override fun getText(): String {
private static Collection<CallableMemberDescriptor> getAllDeclaredNonOverridableOverriddenDescriptors(
@NotNull CallableMemberDescriptor callableMemberDescriptor
) {
Set<CallableMemberDescriptor> result = Sets.newHashSet();
Collection<CallableMemberDescriptor>
nonOverridableOverriddenDescriptors = retainNonOverridableMembers(callableMemberDescriptor.getOverriddenDescriptors());
for (CallableMemberDescriptor overriddenDescriptor : nonOverridableOverriddenDescriptors) {
CallableMemberDescriptor.Kind kind = overriddenDescriptor.getKind();
if (kind == DECLARATION) {
result.add(overriddenDescriptor);
}
else if (kind == FAKE_OVERRIDE || kind == DELEGATION) {
result.addAll(getAllDeclaredNonOverridableOverriddenDescriptors(overriddenDescriptor));
}
else if (kind == SYNTHESIZED) {
// do nothing, final synthesized members can't be made open
}
else {
throw new UnsupportedOperationException("Unexpected callable kind " + kind);
}
}
return result;
}
@NotNull
private static Collection<CallableMemberDescriptor> retainNonOverridableMembers(
@NotNull Collection<? extends CallableMemberDescriptor> callableMemberDescriptors
) {
return ContainerUtil.filter(callableMemberDescriptors, new Condition<CallableMemberDescriptor>() {
@Override
public boolean value(CallableMemberDescriptor descriptor) {
return !descriptor.getModality().isOverridable();
}
});
}
@NotNull
@Override
public String getText() {
if (overriddenNonOverridableMembers.size() == 1) { if (overriddenNonOverridableMembers.size() == 1) {
return JetBundle.message("make.element.modifier", containingDeclarationsNames.get(0) + "." + element.getName(), OPEN_KEYWORD); val name = containingDeclarationsNames.get(0) + "." + element.name
return "Make $name $OPEN_KEYWORD"
} }
StringBuilder declarations = new StringBuilder(); Collections.sort(containingDeclarationsNames)
Collections.sort(containingDeclarationsNames); val declarations = containingDeclarationsNames.subList(0, containingDeclarationsNames.size()-1).join(", ") + " and " +
for (int i = 0; i < containingDeclarationsNames.size() - 2; i++) { containingDeclarationsNames.last()
declarations.append(containingDeclarationsNames.get(i)); return "Make '${element.name}' in $declarations open"
declarations.append(", ");
}
declarations.append(containingDeclarationsNames.get(containingDeclarationsNames.size() - 2));
declarations.append(" and ");
declarations.append(containingDeclarationsNames.get(containingDeclarationsNames.size() - 1));
return JetBundle.message("make.element.in.classifiers.open", element.getName(), declarations.toString());
} }
@NotNull override fun getFamilyName(): String = "Add Modifier"
@Override
public String getFamilyName() {
return JetBundle.message("add.modifier.family");
}
@Override override fun invoke(project: Project, editor: Editor?, file: JetFile) {
public void invoke(@NotNull Project project, Editor editor, JetFile file) throws IncorrectOperationException { for (overriddenMember in overriddenNonOverridableMembers) {
for (JetCallableDeclaration overriddenMember : overriddenNonOverridableMembers) { overriddenMember.addModifier(OPEN_KEYWORD)
overriddenMember.addModifier(OPEN_KEYWORD);
} }
} }
@NotNull companion object : JetSingleIntentionActionFactory() {
public static JetSingleIntentionActionFactory createFactory() {
return new JetSingleIntentionActionFactory() { private fun getAllDeclaredNonOverridableOverriddenDescriptors(
@Nullable callableMemberDescriptor: CallableMemberDescriptor): Collection<CallableMemberDescriptor> {
@Override val result = hashSetOf<CallableMemberDescriptor>()
public IntentionAction createAction(@NotNull Diagnostic diagnostic) { val nonOverridableOverriddenDescriptors = retainNonOverridableMembers(callableMemberDescriptor.overriddenDescriptors)
JetDeclaration declaration = QuickFixUtil.getParentElementOfType(diagnostic, JetDeclaration.class); for (overriddenDescriptor in nonOverridableOverriddenDescriptors) {
assert declaration != null; when (overriddenDescriptor.kind) {
return new MakeOverriddenMemberOpenFix(declaration); DECLARATION ->
result.add(overriddenDescriptor)
FAKE_OVERRIDE, DELEGATION ->
result.addAll(getAllDeclaredNonOverridableOverriddenDescriptors(overriddenDescriptor))
SYNTHESIZED -> {} /* do nothing */
else -> throw UnsupportedOperationException("Unexpected callable kind ${overriddenDescriptor.kind}")
}
} }
}; return result
}
private fun retainNonOverridableMembers(
callableMemberDescriptors: Collection<CallableMemberDescriptor>): Collection<CallableMemberDescriptor> {
return callableMemberDescriptors.filter { !it.modality.isOverridable }
}
override fun createAction(diagnostic: Diagnostic): IntentionAction? {
val declaration = diagnostic.psiElement.getNonStrictParentOfType<JetDeclaration>()!!
return MakeOverriddenMemberOpenFix(declaration)
}
} }
} }
@@ -196,7 +196,7 @@ public class QuickFixRegistrar : QuickFixContributor {
FINAL_SUPERTYPE.registerFactory(addOpenModifierToClassDeclarationFix) FINAL_SUPERTYPE.registerFactory(addOpenModifierToClassDeclarationFix)
FINAL_UPPER_BOUND.registerFactory(addOpenModifierToClassDeclarationFix) FINAL_UPPER_BOUND.registerFactory(addOpenModifierToClassDeclarationFix)
OVERRIDING_FINAL_MEMBER.registerFactory(MakeOverriddenMemberOpenFix.createFactory()) OVERRIDING_FINAL_MEMBER.registerFactory(MakeOverriddenMemberOpenFix)
PARAMETER_NAME_CHANGED_ON_OVERRIDE.registerFactory(RenameParameterToMatchOverriddenMethodFix.createFactory()) PARAMETER_NAME_CHANGED_ON_OVERRIDE.registerFactory(RenameParameterToMatchOverriddenMethodFix.createFactory())