override methods initial
This commit is contained in:
@@ -163,32 +163,7 @@ public class OverrideResolver {
|
|||||||
public static void collectMissingImplementations(MutableClassDescriptor classDescriptor, Set<CallableMemberDescriptor> abstractNoImpl, Set<CallableMemberDescriptor> manyImpl) {
|
public static void collectMissingImplementations(MutableClassDescriptor classDescriptor, Set<CallableMemberDescriptor> abstractNoImpl, Set<CallableMemberDescriptor> manyImpl) {
|
||||||
// Everything from supertypes
|
// Everything from supertypes
|
||||||
Map<CallableMemberDescriptor, CallableMemberDescriptor> implementedWithDelegationBy = Maps.newHashMap();
|
Map<CallableMemberDescriptor, CallableMemberDescriptor> implementedWithDelegationBy = Maps.newHashMap();
|
||||||
Set<CallableMemberDescriptor> inheritedFunctions = Sets.newLinkedHashSet();
|
Multimap<CallableMemberDescriptor, CallableMemberDescriptor> factoredMembers = collectSuperMethods(classDescriptor);
|
||||||
for (JetType supertype : classDescriptor.getSupertypes()) {
|
|
||||||
for (DeclarationDescriptor descriptor : supertype.getMemberScope().getAllDescriptors()) {
|
|
||||||
if (descriptor instanceof CallableMemberDescriptor) {
|
|
||||||
CallableMemberDescriptor memberDescriptor = (CallableMemberDescriptor) descriptor;
|
|
||||||
inheritedFunctions.add(memberDescriptor);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Only those actually inherited
|
|
||||||
Set<CallableMemberDescriptor> filteredMembers = OverridingUtil.filterOverrides(inheritedFunctions);
|
|
||||||
|
|
||||||
// Group members with "the same" signature
|
|
||||||
Multimap<CallableMemberDescriptor, CallableMemberDescriptor> factoredMembers = CommonSuppliers.newLinkedHashSetHashSetMultimap();
|
|
||||||
for (CallableMemberDescriptor one : filteredMembers) {
|
|
||||||
if (factoredMembers.values().contains(one)) continue;
|
|
||||||
for (CallableMemberDescriptor another : filteredMembers) {
|
|
||||||
// if (one == another) continue;
|
|
||||||
factoredMembers.put(one, one);
|
|
||||||
if (OverridingUtil.isOverridableBy(one, another).isSuccess()
|
|
||||||
|| OverridingUtil.isOverridableBy(another, one).isSuccess()) {
|
|
||||||
factoredMembers.put(one, another);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (CallableMemberDescriptor key : factoredMembers.keySet()) {
|
for (CallableMemberDescriptor key : factoredMembers.keySet()) {
|
||||||
Collection<CallableMemberDescriptor> mutuallyOverridable = factoredMembers.get(key);
|
Collection<CallableMemberDescriptor> mutuallyOverridable = factoredMembers.get(key);
|
||||||
@@ -219,6 +194,36 @@ public class OverrideResolver {
|
|||||||
manyImpl.removeAll(actuallyOverridden);
|
manyImpl.removeAll(actuallyOverridden);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static Multimap<CallableMemberDescriptor, CallableMemberDescriptor> collectSuperMethods(MutableClassDescriptor classDescriptor) {
|
||||||
|
Set<CallableMemberDescriptor> inheritedFunctions = Sets.newLinkedHashSet();
|
||||||
|
for (JetType supertype : classDescriptor.getSupertypes()) {
|
||||||
|
for (DeclarationDescriptor descriptor : supertype.getMemberScope().getAllDescriptors()) {
|
||||||
|
if (descriptor instanceof CallableMemberDescriptor) {
|
||||||
|
CallableMemberDescriptor memberDescriptor = (CallableMemberDescriptor) descriptor;
|
||||||
|
inheritedFunctions.add(memberDescriptor);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Only those actually inherited
|
||||||
|
Set<CallableMemberDescriptor> filteredMembers = OverridingUtil.filterOverrides(inheritedFunctions);
|
||||||
|
|
||||||
|
// Group members with "the same" signature
|
||||||
|
Multimap<CallableMemberDescriptor, CallableMemberDescriptor> factoredMembers = CommonSuppliers.newLinkedHashSetHashSetMultimap();
|
||||||
|
for (CallableMemberDescriptor one : filteredMembers) {
|
||||||
|
if (factoredMembers.values().contains(one)) continue;
|
||||||
|
for (CallableMemberDescriptor another : filteredMembers) {
|
||||||
|
// if (one == another) continue;
|
||||||
|
factoredMembers.put(one, one);
|
||||||
|
if (OverridingUtil.isOverridableBy(one, another).isSuccess()
|
||||||
|
|| OverridingUtil.isOverridableBy(another, one).isSuccess()) {
|
||||||
|
factoredMembers.put(one, another);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return factoredMembers;
|
||||||
|
}
|
||||||
|
|
||||||
private void checkOverride(CallableMemberDescriptor declared) {
|
private void checkOverride(CallableMemberDescriptor declared) {
|
||||||
JetNamedDeclaration member = (JetNamedDeclaration) context.getTrace().get(BindingContext.DESCRIPTOR_TO_DECLARATION, declared);
|
JetNamedDeclaration member = (JetNamedDeclaration) context.getTrace().get(BindingContext.DESCRIPTOR_TO_DECLARATION, declared);
|
||||||
if (member == null) {
|
if (member == null) {
|
||||||
|
|||||||
@@ -55,5 +55,6 @@
|
|||||||
<elementDescriptionProvider implementation="org.jetbrains.jet.plugin.findUsages.JetElementDescriptionProvider"/>
|
<elementDescriptionProvider implementation="org.jetbrains.jet.plugin.findUsages.JetElementDescriptionProvider"/>
|
||||||
<debugger.positionManagerFactory implementation="org.jetbrains.jet.plugin.debugger.JetPositionManagerFactory"/>
|
<debugger.positionManagerFactory implementation="org.jetbrains.jet.plugin.debugger.JetPositionManagerFactory"/>
|
||||||
<codeInsight.implementMethod language="jet" implementationClass="org.jetbrains.jet.plugin.codeInsight.ImplementMethodsHandler"/>
|
<codeInsight.implementMethod language="jet" implementationClass="org.jetbrains.jet.plugin.codeInsight.ImplementMethodsHandler"/>
|
||||||
|
<codeInsight.overrideMethod language="jet" implementationClass="org.jetbrains.jet.plugin.codeInsight.OverrideMethodsHandler"/>
|
||||||
</extensions>
|
</extensions>
|
||||||
</idea-plugin>
|
</idea-plugin>
|
||||||
|
|||||||
@@ -1,182 +1,22 @@
|
|||||||
package org.jetbrains.jet.plugin.codeInsight;
|
package org.jetbrains.jet.plugin.codeInsight;
|
||||||
|
|
||||||
import com.google.common.collect.Sets;
|
import com.google.common.collect.Sets;
|
||||||
import com.intellij.codeInsight.hint.HintManager;
|
|
||||||
import com.intellij.ide.util.MemberChooser;
|
|
||||||
import com.intellij.lang.LanguageCodeInsightActionHandler;
|
|
||||||
import com.intellij.openapi.application.Result;
|
|
||||||
import com.intellij.openapi.command.WriteCommandAction;
|
|
||||||
import com.intellij.openapi.editor.Editor;
|
|
||||||
import com.intellij.openapi.project.Project;
|
|
||||||
import com.intellij.openapi.ui.DialogWrapper;
|
|
||||||
import com.intellij.psi.PsiElement;
|
|
||||||
import com.intellij.psi.PsiFile;
|
|
||||||
import com.intellij.psi.util.PsiTreeUtil;
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
import org.jetbrains.jet.lang.descriptors.*;
|
import org.jetbrains.jet.lang.descriptors.*;
|
||||||
import org.jetbrains.jet.lang.psi.*;
|
|
||||||
import org.jetbrains.jet.lang.resolve.BindingContext;
|
|
||||||
import org.jetbrains.jet.lang.resolve.OverrideResolver;
|
import org.jetbrains.jet.lang.resolve.OverrideResolver;
|
||||||
import org.jetbrains.jet.lang.types.JetStandardLibrary;
|
|
||||||
import org.jetbrains.jet.lang.types.JetType;
|
|
||||||
import org.jetbrains.jet.plugin.compiler.WholeProjectAnalyzerFacade;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author yole
|
* @author yole
|
||||||
*/
|
*/
|
||||||
public class ImplementMethodsHandler implements LanguageCodeInsightActionHandler {
|
public class ImplementMethodsHandler extends OverrideImplementMethodsHandler {
|
||||||
@Override
|
protected Set<CallableMemberDescriptor> collectMethodsToGenerate(MutableClassDescriptor descriptor) {
|
||||||
public boolean isValidFor(Editor editor, PsiFile file) {
|
|
||||||
if (!(file instanceof JetFile)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
final PsiElement elementAtCaret = file.findElementAt(editor.getCaretModel().getOffset());
|
|
||||||
final JetClassOrObject classOrObject = PsiTreeUtil.getParentOfType(elementAtCaret, JetClassOrObject.class);
|
|
||||||
return classOrObject != null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void invoke(@NotNull final Project project, @NotNull final Editor editor, @NotNull PsiFile file) {
|
|
||||||
final PsiElement elementAtCaret = file.findElementAt(editor.getCaretModel().getOffset());
|
|
||||||
final JetClassOrObject classOrObject = PsiTreeUtil.getParentOfType(elementAtCaret, JetClassOrObject.class);
|
|
||||||
Set<CallableMemberDescriptor> missingImplementations = collectMethodsToImplement(classOrObject);
|
|
||||||
if (missingImplementations.isEmpty()) {
|
|
||||||
HintManager.getInstance().showErrorHint(editor, "No methods to implement have been found");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
List<DescriptorClassMember> members = membersFromDescriptors(missingImplementations);
|
|
||||||
final MemberChooser<DescriptorClassMember> chooser = showOverrideImplementChooser(project,
|
|
||||||
members.toArray(new DescriptorClassMember[members.size()]));
|
|
||||||
if (chooser == null) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
final List<DescriptorClassMember> selectedElements = chooser.getSelectedElements();
|
|
||||||
if (selectedElements == null || selectedElements.isEmpty()) return;
|
|
||||||
|
|
||||||
new WriteCommandAction(project, file) {
|
|
||||||
protected void run(final Result result) throws Throwable {
|
|
||||||
overrideOrImplementMethodsInRightPlace(project, editor, classOrObject, selectedElements);
|
|
||||||
}
|
|
||||||
}.execute();
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
public static List<DescriptorClassMember> membersFromDescriptors(Set<CallableMemberDescriptor> missingImplementations) {
|
|
||||||
List<DescriptorClassMember> members = new ArrayList<DescriptorClassMember>();
|
|
||||||
for (CallableMemberDescriptor memberDescriptor : missingImplementations) {
|
|
||||||
members.add(new DescriptorClassMember(memberDescriptor));
|
|
||||||
}
|
|
||||||
return members;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static Set<CallableMemberDescriptor> collectMethodsToImplement(JetClassOrObject classOrObject) {
|
|
||||||
BindingContext bindingContext = WholeProjectAnalyzerFacade.analyzeProjectWithCacheOnAFile((JetFile) classOrObject.getContainingFile());
|
|
||||||
final DeclarationDescriptor descriptor = bindingContext.get(BindingContext.DECLARATION_TO_DESCRIPTOR, classOrObject);
|
|
||||||
Set<CallableMemberDescriptor> missingImplementations = Sets.newLinkedHashSet();
|
Set<CallableMemberDescriptor> missingImplementations = Sets.newLinkedHashSet();
|
||||||
if (descriptor instanceof MutableClassDescriptor) {
|
OverrideResolver.collectMissingImplementations(descriptor, missingImplementations, missingImplementations);
|
||||||
OverrideResolver.collectMissingImplementations((MutableClassDescriptor) descriptor,
|
|
||||||
missingImplementations, missingImplementations);
|
|
||||||
}
|
|
||||||
return missingImplementations;
|
return missingImplementations;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void overrideOrImplementMethodsInRightPlace(Project project, Editor editor, JetClassOrObject classOrObject, List<DescriptorClassMember> selectedElements) {
|
protected String getChooserTitle() {
|
||||||
final JetClassBody body = classOrObject.getBody();
|
return "Implement Members";
|
||||||
if (body == null) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
for (DescriptorClassMember selectedElement : selectedElements) {
|
|
||||||
final DeclarationDescriptor descriptor = selectedElement.getDescriptor();
|
|
||||||
if (descriptor instanceof FunctionDescriptor) {
|
|
||||||
JetElement target = overrideFunction(project, (FunctionDescriptor) descriptor);
|
|
||||||
body.addBefore(target, body.getRBrace());
|
|
||||||
}
|
|
||||||
else if (descriptor instanceof PropertyDescriptor) {
|
|
||||||
JetElement target = overrideProperty(project, (PropertyDescriptor) descriptor);
|
|
||||||
body.addBefore(target, body.getRBrace());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static JetElement overrideProperty(Project project, PropertyDescriptor descriptor) {
|
|
||||||
StringBuilder bodyBuilder = new StringBuilder("override ");
|
|
||||||
if (descriptor.isVar()) {
|
|
||||||
bodyBuilder.append("var ");
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
bodyBuilder.append("val ");
|
|
||||||
}
|
|
||||||
bodyBuilder.append(descriptor.getName()).append(": ").append(descriptor.getOutType());
|
|
||||||
String initializer = defaultInitializer(descriptor.getOutType(), JetStandardLibrary.getJetStandardLibrary(project));
|
|
||||||
if (initializer != null) {
|
|
||||||
bodyBuilder.append("=").append(initializer);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
bodyBuilder.append("= ?");
|
|
||||||
}
|
|
||||||
return JetPsiFactory.createProperty(project, bodyBuilder.toString());
|
|
||||||
}
|
|
||||||
|
|
||||||
private static JetElement overrideFunction(Project project, FunctionDescriptor descriptor) {
|
|
||||||
StringBuilder bodyBuilder = new StringBuilder("override fun ");
|
|
||||||
bodyBuilder.append(descriptor.getName());
|
|
||||||
bodyBuilder.append("(");
|
|
||||||
boolean first = true;
|
|
||||||
for (ValueParameterDescriptor parameterDescriptor : descriptor.getValueParameters()) {
|
|
||||||
if (!first) {
|
|
||||||
bodyBuilder.append(",");
|
|
||||||
}
|
|
||||||
first = false;
|
|
||||||
bodyBuilder.append(parameterDescriptor.getName());
|
|
||||||
bodyBuilder.append(": ");
|
|
||||||
bodyBuilder.append(parameterDescriptor.getOutType().toString());
|
|
||||||
}
|
|
||||||
bodyBuilder.append(")");
|
|
||||||
final JetType returnType = descriptor.getReturnType();
|
|
||||||
final JetStandardLibrary stdlib = JetStandardLibrary.getJetStandardLibrary(project);
|
|
||||||
if (!returnType.equals(stdlib.getTuple0Type())) {
|
|
||||||
bodyBuilder.append(": ").append(returnType.toString());
|
|
||||||
}
|
|
||||||
bodyBuilder.append("{");
|
|
||||||
final String initializer = defaultInitializer(returnType, stdlib);
|
|
||||||
if (initializer != null) {
|
|
||||||
bodyBuilder.append("return " ).append(initializer);
|
|
||||||
}
|
|
||||||
bodyBuilder.append("}");
|
|
||||||
return JetPsiFactory.createFunction(project, bodyBuilder.toString());
|
|
||||||
}
|
|
||||||
|
|
||||||
private static String defaultInitializer(JetType returnType, JetStandardLibrary stdlib) {
|
|
||||||
if (returnType.isNullable()) {
|
|
||||||
return "null";
|
|
||||||
}
|
|
||||||
else if (returnType.equals(stdlib.getIntType()) || returnType.equals(stdlib.getLongType()) ||
|
|
||||||
returnType.equals(stdlib.getShortType()) || returnType.equals(stdlib.getByteType()) ||
|
|
||||||
returnType.equals(stdlib.getFloatType()) || returnType.equals(stdlib.getDoubleType())) {
|
|
||||||
return "0";
|
|
||||||
}
|
|
||||||
else if (returnType.equals(stdlib.getBooleanType())) {
|
|
||||||
return "false";
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static MemberChooser<DescriptorClassMember> showOverrideImplementChooser(Project project,
|
|
||||||
DescriptorClassMember[] members) {
|
|
||||||
final MemberChooser<DescriptorClassMember> chooser = new MemberChooser<DescriptorClassMember>(members, true, true, project);
|
|
||||||
chooser.setTitle("Implement Members");
|
|
||||||
chooser.show();
|
|
||||||
if (chooser.getExitCode() != DialogWrapper.OK_EXIT_CODE) return null;
|
|
||||||
return chooser;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean startInWriteAction() {
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,183 @@
|
|||||||
|
package org.jetbrains.jet.plugin.codeInsight;
|
||||||
|
|
||||||
|
import com.intellij.codeInsight.hint.HintManager;
|
||||||
|
import com.intellij.ide.util.MemberChooser;
|
||||||
|
import com.intellij.lang.LanguageCodeInsightActionHandler;
|
||||||
|
import com.intellij.openapi.application.Result;
|
||||||
|
import com.intellij.openapi.command.WriteCommandAction;
|
||||||
|
import com.intellij.openapi.editor.Editor;
|
||||||
|
import com.intellij.openapi.project.Project;
|
||||||
|
import com.intellij.openapi.ui.DialogWrapper;
|
||||||
|
import com.intellij.psi.PsiElement;
|
||||||
|
import com.intellij.psi.PsiFile;
|
||||||
|
import com.intellij.psi.util.PsiTreeUtil;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.jetbrains.jet.lang.descriptors.*;
|
||||||
|
import org.jetbrains.jet.lang.psi.*;
|
||||||
|
import org.jetbrains.jet.lang.resolve.BindingContext;
|
||||||
|
import org.jetbrains.jet.lang.types.JetStandardLibrary;
|
||||||
|
import org.jetbrains.jet.lang.types.JetType;
|
||||||
|
import org.jetbrains.jet.plugin.compiler.WholeProjectAnalyzerFacade;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author yole
|
||||||
|
*/
|
||||||
|
public abstract class OverrideImplementMethodsHandler implements LanguageCodeInsightActionHandler {
|
||||||
|
public static List<DescriptorClassMember> membersFromDescriptors(Set<CallableMemberDescriptor> missingImplementations) {
|
||||||
|
List<DescriptorClassMember> members = new ArrayList<DescriptorClassMember>();
|
||||||
|
for (CallableMemberDescriptor memberDescriptor : missingImplementations) {
|
||||||
|
members.add(new DescriptorClassMember(memberDescriptor));
|
||||||
|
}
|
||||||
|
return members;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Set<CallableMemberDescriptor> collectMethodsToGenerate(JetClassOrObject classOrObject) {
|
||||||
|
BindingContext bindingContext = WholeProjectAnalyzerFacade.analyzeProjectWithCacheOnAFile((JetFile) classOrObject.getContainingFile());
|
||||||
|
final DeclarationDescriptor descriptor = bindingContext.get(BindingContext.DECLARATION_TO_DESCRIPTOR, classOrObject);
|
||||||
|
if (descriptor instanceof MutableClassDescriptor) {
|
||||||
|
return collectMethodsToGenerate((MutableClassDescriptor) descriptor);
|
||||||
|
}
|
||||||
|
return Collections.emptySet();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected abstract Set<CallableMemberDescriptor> collectMethodsToGenerate(MutableClassDescriptor descriptor);
|
||||||
|
|
||||||
|
public static void generateMethods(Project project, Editor editor, JetClassOrObject classOrObject, List<DescriptorClassMember> selectedElements) {
|
||||||
|
final JetClassBody body = classOrObject.getBody();
|
||||||
|
if (body == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
for (DescriptorClassMember selectedElement : selectedElements) {
|
||||||
|
final DeclarationDescriptor descriptor = selectedElement.getDescriptor();
|
||||||
|
if (descriptor instanceof FunctionDescriptor) {
|
||||||
|
JetElement target = overrideFunction(project, (FunctionDescriptor) descriptor);
|
||||||
|
body.addBefore(target, body.getRBrace());
|
||||||
|
}
|
||||||
|
else if (descriptor instanceof PropertyDescriptor) {
|
||||||
|
JetElement target = overrideProperty(project, (PropertyDescriptor) descriptor);
|
||||||
|
body.addBefore(target, body.getRBrace());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static JetElement overrideProperty(Project project, PropertyDescriptor descriptor) {
|
||||||
|
StringBuilder bodyBuilder = new StringBuilder("override ");
|
||||||
|
if (descriptor.isVar()) {
|
||||||
|
bodyBuilder.append("var ");
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
bodyBuilder.append("val ");
|
||||||
|
}
|
||||||
|
bodyBuilder.append(descriptor.getName()).append(": ").append(descriptor.getOutType());
|
||||||
|
String initializer = defaultInitializer(descriptor.getOutType(), JetStandardLibrary.getJetStandardLibrary(project));
|
||||||
|
if (initializer != null) {
|
||||||
|
bodyBuilder.append("=").append(initializer);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
bodyBuilder.append("= ?");
|
||||||
|
}
|
||||||
|
return JetPsiFactory.createProperty(project, bodyBuilder.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
private static JetElement overrideFunction(Project project, FunctionDescriptor descriptor) {
|
||||||
|
StringBuilder bodyBuilder = new StringBuilder("override fun ");
|
||||||
|
bodyBuilder.append(descriptor.getName());
|
||||||
|
bodyBuilder.append("(");
|
||||||
|
boolean first = true;
|
||||||
|
for (ValueParameterDescriptor parameterDescriptor : descriptor.getValueParameters()) {
|
||||||
|
if (!first) {
|
||||||
|
bodyBuilder.append(",");
|
||||||
|
}
|
||||||
|
first = false;
|
||||||
|
bodyBuilder.append(parameterDescriptor.getName());
|
||||||
|
bodyBuilder.append(": ");
|
||||||
|
bodyBuilder.append(parameterDescriptor.getOutType().toString());
|
||||||
|
}
|
||||||
|
bodyBuilder.append(")");
|
||||||
|
final JetType returnType = descriptor.getReturnType();
|
||||||
|
final JetStandardLibrary stdlib = JetStandardLibrary.getJetStandardLibrary(project);
|
||||||
|
if (!returnType.equals(stdlib.getTuple0Type())) {
|
||||||
|
bodyBuilder.append(": ").append(returnType.toString());
|
||||||
|
}
|
||||||
|
bodyBuilder.append("{");
|
||||||
|
final String initializer = defaultInitializer(returnType, stdlib);
|
||||||
|
if (initializer != null) {
|
||||||
|
bodyBuilder.append("return " ).append(initializer);
|
||||||
|
}
|
||||||
|
bodyBuilder.append("}");
|
||||||
|
return JetPsiFactory.createFunction(project, bodyBuilder.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String defaultInitializer(JetType returnType, JetStandardLibrary stdlib) {
|
||||||
|
if (returnType.isNullable()) {
|
||||||
|
return "null";
|
||||||
|
}
|
||||||
|
else if (returnType.equals(stdlib.getIntType()) || returnType.equals(stdlib.getLongType()) ||
|
||||||
|
returnType.equals(stdlib.getShortType()) || returnType.equals(stdlib.getByteType()) ||
|
||||||
|
returnType.equals(stdlib.getFloatType()) || returnType.equals(stdlib.getDoubleType())) {
|
||||||
|
return "0";
|
||||||
|
}
|
||||||
|
else if (returnType.equals(stdlib.getBooleanType())) {
|
||||||
|
return "false";
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private MemberChooser<DescriptorClassMember> showOverrideImplementChooser(Project project,
|
||||||
|
DescriptorClassMember[] members) {
|
||||||
|
final MemberChooser<DescriptorClassMember> chooser = new MemberChooser<DescriptorClassMember>(members, true, true, project);
|
||||||
|
chooser.setTitle(getChooserTitle());
|
||||||
|
chooser.show();
|
||||||
|
if (chooser.getExitCode() != DialogWrapper.OK_EXIT_CODE) return null;
|
||||||
|
return chooser;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected abstract String getChooserTitle();
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isValidFor(Editor editor, PsiFile file) {
|
||||||
|
if (!(file instanceof JetFile)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
final PsiElement elementAtCaret = file.findElementAt(editor.getCaretModel().getOffset());
|
||||||
|
final JetClassOrObject classOrObject = PsiTreeUtil.getParentOfType(elementAtCaret, JetClassOrObject.class);
|
||||||
|
return classOrObject != null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void invoke(@NotNull final Project project, @NotNull final Editor editor, @NotNull PsiFile file) {
|
||||||
|
final PsiElement elementAtCaret = file.findElementAt(editor.getCaretModel().getOffset());
|
||||||
|
final JetClassOrObject classOrObject = PsiTreeUtil.getParentOfType(elementAtCaret, JetClassOrObject.class);
|
||||||
|
Set<CallableMemberDescriptor> missingImplementations = collectMethodsToGenerate(classOrObject);
|
||||||
|
if (missingImplementations.isEmpty()) {
|
||||||
|
HintManager.getInstance().showErrorHint(editor, "No methods to implement have been found");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
List<DescriptorClassMember> members = membersFromDescriptors(missingImplementations);
|
||||||
|
final MemberChooser<DescriptorClassMember> chooser = showOverrideImplementChooser(project,
|
||||||
|
members.toArray(new DescriptorClassMember[members.size()]));
|
||||||
|
if (chooser == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
final List<DescriptorClassMember> selectedElements = chooser.getSelectedElements();
|
||||||
|
if (selectedElements == null || selectedElements.isEmpty()) return;
|
||||||
|
|
||||||
|
new WriteCommandAction(project, file) {
|
||||||
|
protected void run(final Result result) throws Throwable {
|
||||||
|
generateMethods(project, editor, classOrObject, selectedElements);
|
||||||
|
}
|
||||||
|
}.execute();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean startInWriteAction() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
package org.jetbrains.jet.plugin.codeInsight;
|
||||||
|
|
||||||
|
import org.jetbrains.jet.lang.descriptors.CallableMemberDescriptor;
|
||||||
|
import org.jetbrains.jet.lang.descriptors.MutableClassDescriptor;
|
||||||
|
import org.jetbrains.jet.lang.resolve.OverrideResolver;
|
||||||
|
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author yole
|
||||||
|
*/
|
||||||
|
public class OverrideMethodsHandler extends OverrideImplementMethodsHandler {
|
||||||
|
protected Set<CallableMemberDescriptor> collectMethodsToGenerate(MutableClassDescriptor descriptor) {
|
||||||
|
final Set<CallableMemberDescriptor> superMethods = OverrideResolver.collectSuperMethods(descriptor).keySet();
|
||||||
|
for (CallableMemberDescriptor member : descriptor.getCallableMembers()) {
|
||||||
|
superMethods.removeAll(member.getOverriddenDescriptors());
|
||||||
|
}
|
||||||
|
return superMethods;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected String getChooserTitle() {
|
||||||
|
return "Override Members";
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -62,13 +62,13 @@ public class OverrideImplementTest extends LightCodeInsightFixtureTestCase {
|
|||||||
private void doImplement() {
|
private void doImplement() {
|
||||||
final PsiElement elementAtCaret = myFixture.getFile().findElementAt(myFixture.getEditor().getCaretModel().getOffset());
|
final PsiElement elementAtCaret = myFixture.getFile().findElementAt(myFixture.getEditor().getCaretModel().getOffset());
|
||||||
final JetClassOrObject classOrObject = PsiTreeUtil.getParentOfType(elementAtCaret, JetClassOrObject.class);
|
final JetClassOrObject classOrObject = PsiTreeUtil.getParentOfType(elementAtCaret, JetClassOrObject.class);
|
||||||
final Set<CallableMemberDescriptor> descriptors = ImplementMethodsHandler.collectMethodsToImplement(classOrObject);
|
final Set<CallableMemberDescriptor> descriptors = new ImplementMethodsHandler().collectMethodsToGenerate(classOrObject);
|
||||||
assertEquals(1, descriptors.size());
|
assertEquals(1, descriptors.size());
|
||||||
new WriteCommandAction(myFixture.getProject(), myFixture.getFile()) {
|
new WriteCommandAction(myFixture.getProject(), myFixture.getFile()) {
|
||||||
@Override
|
@Override
|
||||||
protected void run(Result result) throws Throwable {
|
protected void run(Result result) throws Throwable {
|
||||||
ImplementMethodsHandler.overrideOrImplementMethodsInRightPlace(myFixture.getProject(), myFixture.getEditor(), classOrObject,
|
ImplementMethodsHandler.generateMethods(myFixture.getProject(), myFixture.getEditor(), classOrObject,
|
||||||
ImplementMethodsHandler.membersFromDescriptors(descriptors));
|
ImplementMethodsHandler.membersFromDescriptors(descriptors));
|
||||||
}
|
}
|
||||||
}.execute();
|
}.execute();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -35,7 +35,7 @@ class JarBuilder(val parent: ModuleBuilder) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class ModuleBuilder(val name: String): IModuleBuilder {
|
open class ModuleBuilder(val name: String): IModuleBuilder {
|
||||||
val sourceFiles: ArrayList<String?> = ArrayList<String?>()
|
val sourceFiles: ArrayList<String?> = ArrayList<String?>()
|
||||||
val classpathRoots: ArrayList<String?> = ArrayList<String?>()
|
val classpathRoots: ArrayList<String?> = ArrayList<String?>()
|
||||||
var _jarName: String? = null
|
var _jarName: String? = null
|
||||||
@@ -67,4 +67,10 @@ class ModuleBuilder(val name: String): IModuleBuilder {
|
|||||||
override fun getJarName(): String? = _jarName
|
override fun getJarName(): String? = _jarName
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class ModuleBuilder2(name: String): ModuleBuilder(name) {
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user