Converted to Kotlin
This commit is contained in:
@@ -1,160 +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.actions;
|
|
||||||
|
|
||||||
import com.intellij.codeInsight.hint.QuestionAction;
|
|
||||||
import com.intellij.openapi.application.ApplicationManager;
|
|
||||||
import com.intellij.openapi.command.CommandProcessor;
|
|
||||||
import com.intellij.openapi.editor.Editor;
|
|
||||||
import com.intellij.openapi.project.Project;
|
|
||||||
import com.intellij.openapi.ui.popup.JBPopupFactory;
|
|
||||||
import com.intellij.openapi.ui.popup.ListPopupStep;
|
|
||||||
import com.intellij.openapi.ui.popup.PopupStep;
|
|
||||||
import com.intellij.openapi.ui.popup.util.BaseListPopupStep;
|
|
||||||
import com.intellij.psi.PsiDocumentManager;
|
|
||||||
import com.intellij.psi.PsiElement;
|
|
||||||
import com.intellij.util.PlatformIcons;
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns;
|
|
||||||
import org.jetbrains.kotlin.descriptors.ClassDescriptor;
|
|
||||||
import org.jetbrains.kotlin.descriptors.ClassKind;
|
|
||||||
import org.jetbrains.kotlin.descriptors.FunctionDescriptor;
|
|
||||||
import org.jetbrains.kotlin.descriptors.Modality;
|
|
||||||
import org.jetbrains.kotlin.idea.JetBundle;
|
|
||||||
import org.jetbrains.kotlin.idea.codeInsight.DescriptorToSourceUtilsIde;
|
|
||||||
import org.jetbrains.kotlin.idea.util.IdeDescriptorRenderers;
|
|
||||||
import org.jetbrains.kotlin.idea.util.ShortenReferences;
|
|
||||||
import org.jetbrains.kotlin.psi.*;
|
|
||||||
import org.jetbrains.kotlin.types.JetType;
|
|
||||||
|
|
||||||
import javax.swing.*;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Changes method signature to one of provided signatures.
|
|
||||||
* Based on {@link KotlinAddImportAction}
|
|
||||||
*/
|
|
||||||
public class JetAddFunctionToClassifierAction implements QuestionAction {
|
|
||||||
private final List<FunctionDescriptor> functionsToAdd;
|
|
||||||
private final Project project;
|
|
||||||
private final Editor editor;
|
|
||||||
|
|
||||||
public JetAddFunctionToClassifierAction(
|
|
||||||
@NotNull Project project,
|
|
||||||
@NotNull Editor editor,
|
|
||||||
@NotNull List<FunctionDescriptor> functionsToAdd
|
|
||||||
) {
|
|
||||||
this.project = project;
|
|
||||||
this.editor = editor;
|
|
||||||
this.functionsToAdd = new ArrayList<FunctionDescriptor>(functionsToAdd);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void addFunction(
|
|
||||||
@NotNull Project project,
|
|
||||||
@NotNull final ClassDescriptor typeDescriptor,
|
|
||||||
@NotNull final FunctionDescriptor functionDescriptor
|
|
||||||
) {
|
|
||||||
final String signatureString = IdeDescriptorRenderers.SOURCE_CODE.render(functionDescriptor);
|
|
||||||
|
|
||||||
PsiDocumentManager.getInstance(project).commitAllDocuments();
|
|
||||||
|
|
||||||
final JetClass classifierDeclaration = (JetClass) DescriptorToSourceUtilsIde.INSTANCE$.getAnyDeclaration(project, typeDescriptor);
|
|
||||||
CommandProcessor.getInstance().executeCommand(project, new Runnable() {
|
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
ApplicationManager.getApplication().runWriteAction(new Runnable() {
|
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
JetPsiFactory psiFactory = JetPsiFactoryKt.JetPsiFactory(classifierDeclaration);
|
|
||||||
JetClassBody body = classifierDeclaration.getOrCreateBody();
|
|
||||||
|
|
||||||
String functionBody = "";
|
|
||||||
if (typeDescriptor.getKind() != ClassKind.INTERFACE && functionDescriptor.getModality() != Modality.ABSTRACT) {
|
|
||||||
functionBody = "{}";
|
|
||||||
JetType returnType = functionDescriptor.getReturnType();
|
|
||||||
if (returnType == null || !KotlinBuiltIns.isUnit(returnType)) {
|
|
||||||
functionBody = "{ throw UnsupportedOperationException() }";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
JetNamedFunction functionElement = psiFactory.createFunction(signatureString + functionBody);
|
|
||||||
PsiElement anchor = body.getRBrace();
|
|
||||||
JetNamedFunction insertedFunctionElement = (JetNamedFunction) body.addBefore(functionElement, anchor);
|
|
||||||
|
|
||||||
ShortenReferences.DEFAULT.process(insertedFunctionElement);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}, JetBundle.message("add.function.to.type.action"), null);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean execute() {
|
|
||||||
if (functionsToAdd.isEmpty()) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (functionsToAdd.size() == 1 || !editor.getComponent().isShowing()) {
|
|
||||||
addFunction(functionsToAdd.get(0));
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
chooseFunctionAndAdd();
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void chooseFunctionAndAdd() {
|
|
||||||
JBPopupFactory.getInstance().createListPopup(getFunctionPopup()).showInBestPositionFor(editor);
|
|
||||||
}
|
|
||||||
|
|
||||||
private ListPopupStep getFunctionPopup() {
|
|
||||||
return new BaseListPopupStep<FunctionDescriptor>(
|
|
||||||
JetBundle.message("add.function.to.type.action.type.chooser"), functionsToAdd) {
|
|
||||||
@Override
|
|
||||||
public boolean isAutoSelectionEnabled() {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public PopupStep onChosen(FunctionDescriptor selectedValue, boolean finalChoice) {
|
|
||||||
if (finalChoice) {
|
|
||||||
addFunction(selectedValue);
|
|
||||||
}
|
|
||||||
return FINAL_CHOICE;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Icon getIconFor(FunctionDescriptor aValue) {
|
|
||||||
return PlatformIcons.FUNCTION_ICON;
|
|
||||||
}
|
|
||||||
|
|
||||||
@NotNull
|
|
||||||
@Override
|
|
||||||
public String getTextFor(FunctionDescriptor functionDescriptor) {
|
|
||||||
ClassDescriptor type = (ClassDescriptor) functionDescriptor.getContainingDeclaration();
|
|
||||||
return JetBundle.message("add.function.to.type.action.single",
|
|
||||||
IdeDescriptorRenderers.SOURCE_CODE_SHORT_NAMES_IN_TYPES.render(functionDescriptor),
|
|
||||||
type.getName().toString());
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
private void addFunction(FunctionDescriptor functionToAdd) {
|
|
||||||
addFunction(project, (ClassDescriptor) functionToAdd.getContainingDeclaration(), functionToAdd);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,142 @@
|
|||||||
|
/*
|
||||||
|
* 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.actions
|
||||||
|
|
||||||
|
import com.intellij.codeInsight.hint.QuestionAction
|
||||||
|
import com.intellij.openapi.application.ApplicationManager
|
||||||
|
import com.intellij.openapi.command.CommandProcessor
|
||||||
|
import com.intellij.openapi.editor.Editor
|
||||||
|
import com.intellij.openapi.project.Project
|
||||||
|
import com.intellij.openapi.ui.popup.JBPopupFactory
|
||||||
|
import com.intellij.openapi.ui.popup.ListPopupStep
|
||||||
|
import com.intellij.openapi.ui.popup.PopupStep
|
||||||
|
import com.intellij.openapi.ui.popup.util.BaseListPopupStep
|
||||||
|
import com.intellij.psi.PsiDocumentManager
|
||||||
|
import com.intellij.util.PlatformIcons
|
||||||
|
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
||||||
|
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
||||||
|
import org.jetbrains.kotlin.descriptors.ClassKind
|
||||||
|
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
|
||||||
|
import org.jetbrains.kotlin.descriptors.Modality
|
||||||
|
import org.jetbrains.kotlin.idea.JetBundle
|
||||||
|
import org.jetbrains.kotlin.idea.codeInsight.DescriptorToSourceUtilsIde
|
||||||
|
import org.jetbrains.kotlin.idea.util.IdeDescriptorRenderers
|
||||||
|
import org.jetbrains.kotlin.idea.util.ShortenReferences
|
||||||
|
import org.jetbrains.kotlin.psi.JetClass
|
||||||
|
import org.jetbrains.kotlin.psi.JetNamedFunction
|
||||||
|
import org.jetbrains.kotlin.psi.JetPsiFactory
|
||||||
|
import java.util.*
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Changes method signature to one of provided signatures.
|
||||||
|
* Based on [KotlinAddImportAction]
|
||||||
|
*/
|
||||||
|
class JetAddFunctionToClassifierAction(
|
||||||
|
private val project: Project,
|
||||||
|
private val editor: Editor?,
|
||||||
|
functionsToAdd: List<FunctionDescriptor>
|
||||||
|
) : QuestionAction {
|
||||||
|
private val functionsToAdd: List<FunctionDescriptor>
|
||||||
|
|
||||||
|
init {
|
||||||
|
this.functionsToAdd = ArrayList(functionsToAdd)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun addFunction(
|
||||||
|
project: Project,
|
||||||
|
typeDescriptor: ClassDescriptor,
|
||||||
|
functionDescriptor: FunctionDescriptor
|
||||||
|
) {
|
||||||
|
val signatureString = IdeDescriptorRenderers.SOURCE_CODE.render(functionDescriptor)
|
||||||
|
|
||||||
|
PsiDocumentManager.getInstance(project).commitAllDocuments()
|
||||||
|
|
||||||
|
val classifierDeclaration = DescriptorToSourceUtilsIde.getAnyDeclaration(project, typeDescriptor) as JetClass
|
||||||
|
CommandProcessor.getInstance().executeCommand(project, object : Runnable {
|
||||||
|
override fun run() {
|
||||||
|
ApplicationManager.getApplication().runWriteAction(object : Runnable {
|
||||||
|
override fun run() {
|
||||||
|
val psiFactory = JetPsiFactory(classifierDeclaration)
|
||||||
|
val body = classifierDeclaration.getOrCreateBody()
|
||||||
|
|
||||||
|
var functionBody = ""
|
||||||
|
if (typeDescriptor.kind != ClassKind.INTERFACE && functionDescriptor.modality != Modality.ABSTRACT) {
|
||||||
|
functionBody = "{}"
|
||||||
|
val returnType = functionDescriptor.returnType
|
||||||
|
if (returnType == null || !KotlinBuiltIns.isUnit(returnType)) {
|
||||||
|
functionBody = "{ throw UnsupportedOperationException() }"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
val functionElement = psiFactory.createFunction(signatureString + functionBody)
|
||||||
|
val anchor = body.rBrace
|
||||||
|
val insertedFunctionElement = body.addBefore(functionElement, anchor) as JetNamedFunction
|
||||||
|
|
||||||
|
ShortenReferences.DEFAULT.process(insertedFunctionElement)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}, JetBundle.message("add.function.to.type.action"), null)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun execute(): Boolean {
|
||||||
|
if (functionsToAdd.isEmpty()) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
if (functionsToAdd.size == 1 || editor == null || !editor.component.isShowing) {
|
||||||
|
addFunction(functionsToAdd.get(0))
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
chooseFunctionAndAdd()
|
||||||
|
}
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun chooseFunctionAndAdd() {
|
||||||
|
JBPopupFactory.getInstance().createListPopup(functionPopup).showInBestPositionFor(editor!!)
|
||||||
|
}
|
||||||
|
|
||||||
|
private val functionPopup: ListPopupStep<*>
|
||||||
|
get() {
|
||||||
|
return object : BaseListPopupStep<FunctionDescriptor>(JetBundle.message("add.function.to.type.action.type.chooser"), functionsToAdd) {
|
||||||
|
override fun isAutoSelectionEnabled(): Boolean {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onChosen(selectedValue: FunctionDescriptor, finalChoice: Boolean): PopupStep<Any>? {
|
||||||
|
if (finalChoice) {
|
||||||
|
addFunction(selectedValue)
|
||||||
|
}
|
||||||
|
return PopupStep.FINAL_CHOICE
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getIconFor(aValue: FunctionDescriptor) = PlatformIcons.FUNCTION_ICON
|
||||||
|
|
||||||
|
override fun getTextFor(functionDescriptor: FunctionDescriptor): String {
|
||||||
|
val type = functionDescriptor.containingDeclaration as ClassDescriptor
|
||||||
|
return JetBundle.message("add.function.to.type.action.single",
|
||||||
|
IdeDescriptorRenderers.SOURCE_CODE_SHORT_NAMES_IN_TYPES.render(functionDescriptor),
|
||||||
|
type.name.toString())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun addFunction(functionToAdd: FunctionDescriptor) {
|
||||||
|
addFunction(project, functionToAdd.containingDeclaration as ClassDescriptor, functionToAdd)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,167 +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.google.common.collect.Lists;
|
|
||||||
import com.intellij.codeInsight.intention.IntentionAction;
|
|
||||||
import com.intellij.openapi.command.CommandProcessor;
|
|
||||||
import com.intellij.openapi.editor.Editor;
|
|
||||||
import com.intellij.openapi.project.Project;
|
|
||||||
import com.intellij.psi.PsiFile;
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
import org.jetbrains.annotations.Nullable;
|
|
||||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns;
|
|
||||||
import org.jetbrains.kotlin.descriptors.*;
|
|
||||||
import org.jetbrains.kotlin.diagnostics.Diagnostic;
|
|
||||||
import org.jetbrains.kotlin.idea.JetBundle;
|
|
||||||
import org.jetbrains.kotlin.idea.actions.JetAddFunctionToClassifierAction;
|
|
||||||
import org.jetbrains.kotlin.idea.caches.resolve.ResolutionUtils;
|
|
||||||
import org.jetbrains.kotlin.idea.core.quickfix.QuickFixUtil;
|
|
||||||
import org.jetbrains.kotlin.idea.util.IdeDescriptorRenderers;
|
|
||||||
import org.jetbrains.kotlin.psi.JetFile;
|
|
||||||
import org.jetbrains.kotlin.psi.JetNamedFunction;
|
|
||||||
import org.jetbrains.kotlin.resolve.DescriptorUtils;
|
|
||||||
import org.jetbrains.kotlin.types.JetType;
|
|
||||||
import org.jetbrains.kotlin.types.TypeUtils;
|
|
||||||
import org.jetbrains.kotlin.types.checker.JetTypeChecker;
|
|
||||||
|
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.Comparator;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
public class AddFunctionToSupertypeFix extends JetHintAction<JetNamedFunction> {
|
|
||||||
private final List<FunctionDescriptor> functionsToAdd;
|
|
||||||
|
|
||||||
public AddFunctionToSupertypeFix(JetNamedFunction element) {
|
|
||||||
super(element);
|
|
||||||
functionsToAdd = generateFunctionsToAdd(element);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static List<FunctionDescriptor> generateFunctionsToAdd(JetNamedFunction functionElement) {
|
|
||||||
FunctionDescriptor functionDescriptor = (FunctionDescriptor) ResolutionUtils.resolveToDescriptor(functionElement);
|
|
||||||
|
|
||||||
DeclarationDescriptor containingDeclaration = functionDescriptor.getContainingDeclaration();
|
|
||||||
if (!(containingDeclaration instanceof ClassDescriptor)) return Collections.emptyList();
|
|
||||||
|
|
||||||
List<FunctionDescriptor> functions = Lists.newArrayList();
|
|
||||||
ClassDescriptor classDescriptor = (ClassDescriptor) containingDeclaration;
|
|
||||||
// TODO: filter out impossible supertypes (for example when argument's type isn't visible in a superclass).
|
|
||||||
for (ClassDescriptor supertypeDescriptor : getSupertypes(classDescriptor)) {
|
|
||||||
if (KotlinBuiltIns.isAnyOrNullableAny(supertypeDescriptor.getDefaultType())) continue;
|
|
||||||
functions.add(generateFunctionSignatureForType(functionDescriptor, supertypeDescriptor));
|
|
||||||
}
|
|
||||||
return functions;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static List<ClassDescriptor> getSupertypes(ClassDescriptor classDescriptor) {
|
|
||||||
List<JetType> supertypes = Lists.newArrayList(TypeUtils.getAllSupertypes(classDescriptor.getDefaultType()));
|
|
||||||
Collections.sort(supertypes, new Comparator<JetType>() {
|
|
||||||
@Override
|
|
||||||
public int compare(JetType o1, JetType o2) {
|
|
||||||
if (o1.equals(o2)) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
if (JetTypeChecker.DEFAULT.isSubtypeOf(o1, o2)) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
if (JetTypeChecker.DEFAULT.isSubtypeOf(o2, o1)) {
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
return o1.toString().compareTo(o2.toString());
|
|
||||||
}
|
|
||||||
});
|
|
||||||
List<ClassDescriptor> supertypesDescriptors = Lists.newArrayList();
|
|
||||||
for (JetType supertype : supertypes) {
|
|
||||||
supertypesDescriptors.add(DescriptorUtils.getClassDescriptorForType(supertype));
|
|
||||||
}
|
|
||||||
return supertypesDescriptors;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static FunctionDescriptor generateFunctionSignatureForType(
|
|
||||||
FunctionDescriptor functionDescriptor,
|
|
||||||
ClassDescriptor typeDescriptor
|
|
||||||
) {
|
|
||||||
// TODO: support for generics.
|
|
||||||
Modality modality = typeDescriptor.getModality();
|
|
||||||
if (typeDescriptor.getKind() == ClassKind.INTERFACE) {
|
|
||||||
modality = Modality.OPEN;
|
|
||||||
}
|
|
||||||
return functionDescriptor.copy(
|
|
||||||
typeDescriptor,
|
|
||||||
modality,
|
|
||||||
functionDescriptor.getVisibility(),
|
|
||||||
CallableMemberDescriptor.Kind.DECLARATION,
|
|
||||||
/* copyOverrides = */ false);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isAvailable(@NotNull Project project, Editor editor, PsiFile file) {
|
|
||||||
return super.isAvailable(project, editor, file) && !functionsToAdd.isEmpty();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean showHint(Editor editor) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@NotNull
|
|
||||||
@Override
|
|
||||||
public String getText() {
|
|
||||||
if (functionsToAdd.size() == 1) {
|
|
||||||
FunctionDescriptor newFunction = functionsToAdd.get(0);
|
|
||||||
ClassDescriptor supertype = (ClassDescriptor) newFunction.getContainingDeclaration();
|
|
||||||
return JetBundle.message("add.function.to.type.action.single",
|
|
||||||
IdeDescriptorRenderers.SOURCE_CODE_SHORT_NAMES_IN_TYPES.render(newFunction),
|
|
||||||
supertype.getName().toString());
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
return JetBundle.message("add.function.to.supertype.action.multiple");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@NotNull
|
|
||||||
@Override
|
|
||||||
public String getFamilyName() {
|
|
||||||
return JetBundle.message("add.function.to.supertype.family");
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void invoke(@NotNull final Project project, final Editor editor, final JetFile file) {
|
|
||||||
CommandProcessor.getInstance().runUndoTransparentAction(new Runnable() {
|
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
createAction(project, editor, file).execute();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
@NotNull
|
|
||||||
private JetAddFunctionToClassifierAction createAction(Project project, Editor editor, JetFile file) {
|
|
||||||
return new JetAddFunctionToClassifierAction(project, editor, functionsToAdd);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static JetIntentionActionsFactory createFactory() {
|
|
||||||
return new JetSingleIntentionActionFactory() {
|
|
||||||
@Nullable
|
|
||||||
@Override
|
|
||||||
public IntentionAction createAction(Diagnostic diagnostic) {
|
|
||||||
JetNamedFunction function = QuickFixUtil.getParentElementOfType(diagnostic, JetNamedFunction.class);
|
|
||||||
return function == null ? null : new AddFunctionToSupertypeFix(function);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,141 @@
|
|||||||
|
/*
|
||||||
|
* 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.google.common.collect.Lists
|
||||||
|
import com.intellij.codeInsight.intention.IntentionAction
|
||||||
|
import com.intellij.openapi.command.CommandProcessor
|
||||||
|
import com.intellij.openapi.editor.Editor
|
||||||
|
import com.intellij.openapi.project.Project
|
||||||
|
import com.intellij.psi.PsiFile
|
||||||
|
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
||||||
|
import org.jetbrains.kotlin.descriptors.*
|
||||||
|
import org.jetbrains.kotlin.diagnostics.Diagnostic
|
||||||
|
import org.jetbrains.kotlin.idea.JetBundle
|
||||||
|
import org.jetbrains.kotlin.idea.actions.JetAddFunctionToClassifierAction
|
||||||
|
import org.jetbrains.kotlin.idea.caches.resolve.resolveToDescriptor
|
||||||
|
import org.jetbrains.kotlin.idea.core.quickfix.QuickFixUtil
|
||||||
|
import org.jetbrains.kotlin.idea.util.IdeDescriptorRenderers
|
||||||
|
import org.jetbrains.kotlin.psi.JetFile
|
||||||
|
import org.jetbrains.kotlin.psi.JetNamedFunction
|
||||||
|
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
||||||
|
import org.jetbrains.kotlin.types.JetType
|
||||||
|
import org.jetbrains.kotlin.types.TypeUtils
|
||||||
|
import org.jetbrains.kotlin.types.checker.JetTypeChecker
|
||||||
|
import java.util.*
|
||||||
|
|
||||||
|
class AddFunctionToSupertypeFix(element: JetNamedFunction) : JetHintAction<JetNamedFunction>(element) {
|
||||||
|
private val functionsToAdd: List<FunctionDescriptor> = generateFunctionsToAdd(element)
|
||||||
|
|
||||||
|
override fun isAvailable(project: Project, editor: Editor?, file: PsiFile): Boolean {
|
||||||
|
return super.isAvailable(project, editor, file) && !functionsToAdd.isEmpty()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun showHint(editor: Editor) = false
|
||||||
|
|
||||||
|
override fun getText(): String {
|
||||||
|
if (functionsToAdd.size == 1) {
|
||||||
|
val newFunction = functionsToAdd.get(0)
|
||||||
|
val supertype = newFunction.containingDeclaration as ClassDescriptor
|
||||||
|
return JetBundle.message("add.function.to.type.action.single",
|
||||||
|
IdeDescriptorRenderers.SOURCE_CODE_SHORT_NAMES_IN_TYPES.render(newFunction),
|
||||||
|
supertype.name.toString())
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return JetBundle.message("add.function.to.supertype.action.multiple")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getFamilyName() = JetBundle.message("add.function.to.supertype.family")
|
||||||
|
|
||||||
|
override fun invoke(project: Project, editor: Editor?, file: JetFile) {
|
||||||
|
CommandProcessor.getInstance().runUndoTransparentAction(object : Runnable {
|
||||||
|
override fun run() {
|
||||||
|
createAction(project, editor).execute()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun createAction(project: Project, editor: Editor?): JetAddFunctionToClassifierAction {
|
||||||
|
return JetAddFunctionToClassifierAction(project, editor, functionsToAdd)
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
|
||||||
|
private fun generateFunctionsToAdd(functionElement: JetNamedFunction): List<FunctionDescriptor> {
|
||||||
|
val functionDescriptor = functionElement.resolveToDescriptor() as FunctionDescriptor
|
||||||
|
|
||||||
|
val containingClass = functionDescriptor.containingDeclaration as? ClassDescriptor ?: return emptyList()
|
||||||
|
|
||||||
|
val functions = ArrayList<FunctionDescriptor>()
|
||||||
|
// TODO: filter out impossible supertypes (for example when argument's type isn't visible in a superclass).
|
||||||
|
for (supertypeDescriptor in getSupertypes(containingClass)) {
|
||||||
|
if (KotlinBuiltIns.isAnyOrNullableAny(supertypeDescriptor.defaultType)) continue
|
||||||
|
functions.add(generateFunctionSignatureForType(functionDescriptor, supertypeDescriptor))
|
||||||
|
}
|
||||||
|
return functions
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun getSupertypes(classDescriptor: ClassDescriptor): List<ClassDescriptor> {
|
||||||
|
val supertypes = Lists.newArrayList(TypeUtils.getAllSupertypes(classDescriptor.defaultType))
|
||||||
|
Collections.sort(supertypes, object : Comparator<JetType> {
|
||||||
|
override fun compare(o1: JetType, o2: JetType): Int {
|
||||||
|
if (o1 == o2) {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
if (JetTypeChecker.DEFAULT.isSubtypeOf(o1, o2)) {
|
||||||
|
return -1
|
||||||
|
}
|
||||||
|
if (JetTypeChecker.DEFAULT.isSubtypeOf(o2, o1)) {
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
return o1.toString().compareTo(o2.toString())
|
||||||
|
}
|
||||||
|
})
|
||||||
|
val supertypesDescriptors = Lists.newArrayList<ClassDescriptor>()
|
||||||
|
for (supertype in supertypes) {
|
||||||
|
supertypesDescriptors.add(DescriptorUtils.getClassDescriptorForType(supertype))
|
||||||
|
}
|
||||||
|
return supertypesDescriptors
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun generateFunctionSignatureForType(
|
||||||
|
functionDescriptor: FunctionDescriptor,
|
||||||
|
typeDescriptor: ClassDescriptor): FunctionDescriptor {
|
||||||
|
// TODO: support for generics.
|
||||||
|
var modality = typeDescriptor.modality
|
||||||
|
if (typeDescriptor.kind == ClassKind.INTERFACE) {
|
||||||
|
modality = Modality.OPEN
|
||||||
|
}
|
||||||
|
return functionDescriptor.copy(
|
||||||
|
typeDescriptor,
|
||||||
|
modality,
|
||||||
|
functionDescriptor.visibility,
|
||||||
|
CallableMemberDescriptor.Kind.DECLARATION,
|
||||||
|
/* copyOverrides = */ false)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun createFactory(): JetIntentionActionsFactory {
|
||||||
|
return object : JetSingleIntentionActionFactory() {
|
||||||
|
public override fun createAction(diagnostic: Diagnostic): IntentionAction? {
|
||||||
|
val function = QuickFixUtil.getParentElementOfType(diagnostic, JetNamedFunction::class.java)
|
||||||
|
return if (function == null) null else AddFunctionToSupertypeFix(function)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user