Merge branch 'master' of ssh://git.labs.intellij.net/jet

This commit is contained in:
svtk
2011-11-04 22:54:34 +04:00
35 changed files with 626 additions and 82 deletions
@@ -189,6 +189,7 @@ public class JavaDescriptorResolver {
TypeParameterDescriptor typeParameterDescriptor = TypeParameterDescriptor.createForFurtherModification(
owner,
Collections.<AnnotationDescriptor>emptyList(), // TODO
false,
Variance.INVARIANT,
typeParameter.getName(),
typeParameter.getIndex()
@@ -21,10 +21,11 @@ public class TypeParameterDescriptor extends DeclarationDescriptorImpl implement
public static TypeParameterDescriptor createWithDefaultBound(
@NotNull DeclarationDescriptor containingDeclaration,
@NotNull List<AnnotationDescriptor> annotations,
boolean reified,
@NotNull Variance variance,
@NotNull String name,
int index) {
TypeParameterDescriptor typeParameterDescriptor = createForFurtherModification(containingDeclaration, annotations, variance, name, index);
TypeParameterDescriptor typeParameterDescriptor = createForFurtherModification(containingDeclaration, annotations, reified, variance, name, index);
typeParameterDescriptor.addUpperBound(JetStandardClasses.getDefaultBound());
return typeParameterDescriptor;
}
@@ -32,10 +33,11 @@ public class TypeParameterDescriptor extends DeclarationDescriptorImpl implement
public static TypeParameterDescriptor createForFurtherModification(
@NotNull DeclarationDescriptor containingDeclaration,
@NotNull List<AnnotationDescriptor> annotations,
boolean reified,
@NotNull Variance variance,
@NotNull String name,
int index) {
return new TypeParameterDescriptor(containingDeclaration, annotations, variance, name, index);
return new TypeParameterDescriptor(containingDeclaration, annotations, reified, variance, name, index);
}
private final int index;
@@ -47,9 +49,12 @@ public class TypeParameterDescriptor extends DeclarationDescriptorImpl implement
private final Set<JetType> classObjectUpperBounds = Sets.newLinkedHashSet();
private JetType classObjectBoundsAsType;
private final boolean reified;
private TypeParameterDescriptor(
@NotNull DeclarationDescriptor containingDeclaration,
@NotNull List<AnnotationDescriptor> annotations,
boolean reified,
@NotNull Variance variance,
@NotNull String name,
int index) {
@@ -57,6 +62,7 @@ public class TypeParameterDescriptor extends DeclarationDescriptorImpl implement
this.index = index;
this.variance = variance;
this.upperBounds = Sets.newLinkedHashSet();
this.reified = reified;
// TODO: Should we actually pass the annotations on to the type constructor?
this.typeConstructor = new TypeConstructorImpl(
this,
@@ -67,6 +73,10 @@ public class TypeParameterDescriptor extends DeclarationDescriptorImpl implement
upperBounds);
}
public boolean isReified() {
return reified;
}
public Variance getVariance() {
return variance;
}
@@ -162,6 +172,6 @@ public class TypeParameterDescriptor extends DeclarationDescriptorImpl implement
@NotNull
public TypeParameterDescriptor copy(@NotNull DeclarationDescriptor newOwner) {
return new TypeParameterDescriptor(newOwner, Lists.newArrayList(getAnnotations()), variance, getName(), index);
return new TypeParameterDescriptor(newOwner, Lists.newArrayList(getAnnotations()), reified, variance, getName(), index);
}
}
@@ -75,7 +75,7 @@ public class JetClass extends JetTypeParameterListOwner implements JetClassOrObj
@NotNull
public List<JetClassInitializer> getAnonymousInitializers() {
JetClassBody body = (JetClassBody) findChildByType(JetNodeTypes.CLASS_BODY);
JetClassBody body = getBody();
if (body == null) return Collections.emptyList();
return body.getAnonymousInitializers();
@@ -90,15 +90,20 @@ public class JetClass extends JetTypeParameterListOwner implements JetClassOrObj
return (JetObjectDeclarationName) findChildByType(JetNodeTypes.OBJECT_DECLARATION_NAME);
}
@Override
public JetClassBody getBody() {
return (JetClassBody) findChildByType(JetNodeTypes.CLASS_BODY);
}
@Nullable
public JetClassObject getClassObject() {
JetClassBody body = (JetClassBody) findChildByType(JetNodeTypes.CLASS_BODY);
JetClassBody body = getBody();
if (body == null) return null;
return body.getClassObject();
}
public List<JetProperty> getProperties() {
JetClassBody body = (JetClassBody) findChildByType(JetNodeTypes.CLASS_BODY);
JetClassBody body = getBody();
if (body == null) return Collections.emptyList();
return body.getProperties();
@@ -1,10 +1,13 @@
package org.jetbrains.jet.lang.psi;
import com.intellij.lang.ASTNode;
import com.intellij.psi.PsiElement;
import com.intellij.psi.tree.TokenSet;
import com.intellij.psi.util.PsiTreeUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.JetNodeTypes;
import org.jetbrains.jet.lexer.JetTokens;
import java.util.List;
@@ -48,4 +51,9 @@ public class JetClassBody extends JetElement {
public JetClassObject getClassObject() {
return (JetClassObject) findChildByType(JetNodeTypes.CLASS_OBJECT);
}
public PsiElement getRBrace() {
final ASTNode[] children = getNode().getChildren(TokenSet.create(JetTokens.RBRACE));
return children.length == 1 ? children[0].getPsi() : null;
}
}
@@ -32,4 +32,7 @@ public interface JetClassOrObject extends PsiElement {
@Nullable
JetObjectDeclarationName getNameAsDeclaration();
@Nullable
JetClassBody getBody();
}
@@ -69,10 +69,15 @@ public class JetObjectDeclaration extends JetNamedDeclaration implements JetClas
return true;
}
@Override
public JetClassBody getBody() {
return (JetClassBody) findChildByType(JetNodeTypes.CLASS_BODY);
}
@Override
@NotNull
public List<JetDeclaration> getDeclarations() {
JetClassBody body = (JetClassBody) findChildByType(JetNodeTypes.CLASS_BODY);
JetClassBody body = getBody();
if (body == null) return Collections.emptyList();
return body.getDeclarations();
@@ -54,7 +54,7 @@ public class JetPsiFactory {
return createProperty(project, text);
}
private static JetProperty createProperty(Project project, String text) {
public static JetProperty createProperty(Project project, String text) {
return createDeclaration(project, text, JetProperty.class);
}
@@ -50,6 +50,7 @@ public class ClassDescriptorResolver {
TypeParameterDescriptor typeParameterDescriptor = TypeParameterDescriptor.createForFurtherModification(
descriptor,
annotationResolver.createAnnotationStubs(typeParameter.getModifierList()),
true,
typeParameter.getVariance(),
JetPsiUtil.safeName(typeParameter.getName()),
index
@@ -313,6 +314,7 @@ public class ClassDescriptorResolver {
TypeParameterDescriptor typeParameterDescriptor = TypeParameterDescriptor.createForFurtherModification(
containingDescriptor,
annotationResolver.createAnnotationStubs(typeParameter.getModifierList()),
true,
typeParameter.getVariance(),
JetPsiUtil.safeName(typeParameter.getName()),
index
@@ -103,66 +103,10 @@ public class OverrideResolver {
}
// Check if everything that must be overridden, actually is
// Everything from supertypes
Map<CallableMemberDescriptor, CallableMemberDescriptor> implementedWithDelegationBy = Maps.newHashMap();
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);
}
}
}
// More than one implementation or no implementations at all
Set<CallableMemberDescriptor> abstractNoImpl = Sets.newLinkedHashSet();
Set<CallableMemberDescriptor> manyImpl = Sets.newLinkedHashSet();
for (CallableMemberDescriptor key : factoredMembers.keySet()) {
Collection<CallableMemberDescriptor> mutuallyOverridable = factoredMembers.get(key);
int implementationCount = 0;
for (CallableMemberDescriptor member : mutuallyOverridable) {
if (member.getModality() != Modality.ABSTRACT) {
implementationCount++;
}
}
if (implementationCount == 0) {
abstractNoImpl.addAll(mutuallyOverridable);
}
else if (implementationCount > 1) {
manyImpl.addAll(mutuallyOverridable);
}
}
// Members actually present (declared) in the class
Set<CallableMemberDescriptor> actuallyOverridden = Sets.newHashSet(implementedWithDelegationBy.keySet());
for (CallableMemberDescriptor member : classDescriptor.getCallableMembers()) {
actuallyOverridden.addAll(member.getOverriddenDescriptors());
}
// Those to be overridden that are actually not
abstractNoImpl.removeAll(actuallyOverridden);
manyImpl.removeAll(actuallyOverridden);
collectMissingImplementations(classDescriptor, abstractNoImpl, manyImpl);
PsiElement nameIdentifier = klass;
if (klass instanceof JetClass) {
@@ -216,6 +160,70 @@ public class OverrideResolver {
// }
}
public static void collectMissingImplementations(MutableClassDescriptor classDescriptor, Set<CallableMemberDescriptor> abstractNoImpl, Set<CallableMemberDescriptor> manyImpl) {
// Everything from supertypes
Map<CallableMemberDescriptor, CallableMemberDescriptor> implementedWithDelegationBy = Maps.newHashMap();
Multimap<CallableMemberDescriptor, CallableMemberDescriptor> factoredMembers = collectSuperMethods(classDescriptor);
for (CallableMemberDescriptor key : factoredMembers.keySet()) {
Collection<CallableMemberDescriptor> mutuallyOverridable = factoredMembers.get(key);
int implementationCount = 0;
for (CallableMemberDescriptor member : mutuallyOverridable) {
if (member.getModality() != Modality.ABSTRACT) {
implementationCount++;
}
}
if (implementationCount == 0) {
abstractNoImpl.addAll(mutuallyOverridable);
}
else if (implementationCount > 1) {
manyImpl.addAll(mutuallyOverridable);
}
}
// Members actually present (declared) in the class
Set<CallableMemberDescriptor> actuallyOverridden = Sets.newHashSet(implementedWithDelegationBy.keySet());
for (CallableMemberDescriptor member : classDescriptor.getCallableMembers()) {
actuallyOverridden.addAll(member.getOverriddenDescriptors());
}
// Those to be overridden that are actually not
abstractNoImpl.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) {
JetNamedDeclaration member = (JetNamedDeclaration) context.getTrace().get(BindingContext.DESCRIPTOR_TO_DECLARATION, declared);
if (member == null) {
@@ -40,6 +40,7 @@ public class DescriptorSubstitutor {
TypeParameterDescriptor substituted = TypeParameterDescriptor.createForFurtherModification(
newContainingDeclaration,
descriptor.getAnnotations(),
descriptor.isReified(),
descriptor.getVariance(),
descriptor.getName(),
descriptor.getIndex());
@@ -116,7 +116,7 @@ public class JetStandardClasses {
parameters.add(TypeParameterDescriptor.createWithDefaultBound(
classDescriptor,
Collections.<AnnotationDescriptor>emptyList(),
Variance.OUT_VARIANCE, "T" + j, j));
true, Variance.OUT_VARIANCE, "T" + j, j));
}
TUPLE[i] = classDescriptor.initialize(
true,
@@ -159,7 +159,7 @@ public class JetStandardClasses {
parameters.add(0, TypeParameterDescriptor.createWithDefaultBound(
receiverFunction,
Collections.<AnnotationDescriptor>emptyList(),
Variance.IN_VARIANCE, "T", 0));
true, Variance.IN_VARIANCE, "T", 0));
RECEIVER_FUNCTION[i] = receiverFunction.initialize(
false,
parameters,
@@ -174,12 +174,12 @@ public class JetStandardClasses {
parameters.add(TypeParameterDescriptor.createWithDefaultBound(
function,
Collections.<AnnotationDescriptor>emptyList(),
Variance.IN_VARIANCE, "P" + j, j + 1));
true, Variance.IN_VARIANCE, "P" + j, j + 1));
}
parameters.add(TypeParameterDescriptor.createWithDefaultBound(
function,
Collections.<AnnotationDescriptor>emptyList(),
Variance.OUT_VARIANCE, "R", parameterCount + 1));
true, Variance.OUT_VARIANCE, "R", parameterCount + 1));
return parameters;
}
@@ -311,6 +311,9 @@ public class DescriptorRenderer implements Renderer {
}
protected void renderTypeParameter(TypeParameterDescriptor descriptor, StringBuilder builder) {
if (!descriptor.isReified()) {
builder.append(renderKeyword("erased")).append(" ");
}
renderName(descriptor, builder);
if (!descriptor.getUpperBounds().isEmpty()) {
JetType bound = descriptor.getUpperBounds().iterator().next();
+2
View File
@@ -54,5 +54,7 @@
<fileTypeIndentOptionsProvider implementation="org.jetbrains.jet.plugin.formatter.JetIndentOptionsProvider"/>
<elementDescriptionProvider implementation="org.jetbrains.jet.plugin.findUsages.JetElementDescriptionProvider"/>
<debugger.positionManagerFactory implementation="org.jetbrains.jet.plugin.debugger.JetPositionManagerFactory"/>
<codeInsight.implementMethod language="jet" implementationClass="org.jetbrains.jet.plugin.codeInsight.ImplementMethodsHandler"/>
<codeInsight.overrideMethod language="jet" implementationClass="org.jetbrains.jet.plugin.codeInsight.OverrideMethodsHandler"/>
</extensions>
</idea-plugin>
@@ -0,0 +1,57 @@
package org.jetbrains.jet.plugin.codeInsight;
import com.intellij.codeInsight.generation.ClassMember;
import com.intellij.codeInsight.generation.MemberChooserObject;
import com.intellij.ui.SimpleColoredComponent;
import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor;
import org.jetbrains.jet.resolve.DescriptorRenderer;
import javax.swing.*;
/**
* @author yole
*/
public class DescriptorClassMember implements ClassMember {
private final DeclarationDescriptor myDescriptor;
public DescriptorClassMember(DeclarationDescriptor descriptor) {
myDescriptor = descriptor;
}
@Override
public MemberChooserObject getParentNodeDelegate() {
final DeclarationDescriptor parent = myDescriptor.getContainingDeclaration();
return new DescriptorClassMember(parent);
}
@Override
public void renderTreeNode(SimpleColoredComponent component, JTree tree) {
component.append(getText());
}
@Override
public String getText() {
return DescriptorRenderer.TEXT.render(myDescriptor);
}
public DeclarationDescriptor getDescriptor() {
return myDescriptor;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
DescriptorClassMember that = (DescriptorClassMember) o;
if (myDescriptor != null ? !myDescriptor.equals(that.myDescriptor) : that.myDescriptor != null) return false;
return true;
}
@Override
public int hashCode() {
return myDescriptor != null ? myDescriptor.hashCode() : 0;
}
}
@@ -0,0 +1,22 @@
package org.jetbrains.jet.plugin.codeInsight;
import com.google.common.collect.Sets;
import org.jetbrains.jet.lang.descriptors.*;
import org.jetbrains.jet.lang.resolve.OverrideResolver;
import java.util.Set;
/**
* @author yole
*/
public class ImplementMethodsHandler extends OverrideImplementMethodsHandler {
protected Set<CallableMemberDescriptor> collectMethodsToGenerate(MutableClassDescriptor descriptor) {
Set<CallableMemberDescriptor> missingImplementations = Sets.newLinkedHashSet();
OverrideResolver.collectMissingImplementations(descriptor, missingImplementations, missingImplementations);
return missingImplementations;
}
protected String getChooserTitle() {
return "Implement Members";
}
}
@@ -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,31 @@
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.HashSet;
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());
}
Set<CallableMemberDescriptor> result = new HashSet<CallableMemberDescriptor>();
for (CallableMemberDescriptor superMethod : superMethods) {
if (superMethod.getModality().isOverridable()) {
result.add(superMethod);
}
}
return result;
}
protected String getChooserTitle() {
return "Override Members";
}
}
@@ -24,6 +24,7 @@ public class JetBlock implements ASTBlock {
private Indent myIndent;
private Wrap myWrap;
private CodeStyleSettings mySettings;
private final SpacingBuilder mySpacingBuilder;
private List<Block> mySubBlocks;
private static final TokenSet CODE_BLOCKS = TokenSet.create(
@@ -35,12 +36,14 @@ public class JetBlock implements ASTBlock {
JetNodeTypes.THEN,
JetNodeTypes.ELSE);
public JetBlock(ASTNode node, Alignment alignment, Indent indent, Wrap wrap, CodeStyleSettings settings) {
public JetBlock(ASTNode node, Alignment alignment, Indent indent, Wrap wrap, CodeStyleSettings settings,
SpacingBuilder spacingBuilder) {
myNode = node;
myAlignment = alignment;
myIndent = indent;
myWrap = wrap;
mySettings = settings;
mySpacingBuilder = spacingBuilder;
}
@Override
@@ -110,7 +113,7 @@ public class JetBlock implements ASTBlock {
childIndent = Indent.getNormalIndent();
}
return new JetBlock(child, childAlignment, childIndent, wrap, mySettings);
return new JetBlock(child, childAlignment, childIndent, wrap, mySettings, mySpacingBuilder);
}
private static Indent indentIfNotBrace(ASTNode child) {
@@ -120,8 +123,8 @@ public class JetBlock implements ASTBlock {
}
@Override
public Spacing getSpacing(Block block, Block block1) {
return null;
public Spacing getSpacing(Block child1, Block child2) {
return mySpacingBuilder.getSpacing(this, child1, child2);
}
@NotNull
@@ -1,15 +1,17 @@
package org.jetbrains.jet.plugin.formatter;
import com.intellij.formatting.FormattingModel;
import com.intellij.formatting.FormattingModelBuilder;
import com.intellij.formatting.FormattingModelProvider;
import com.intellij.formatting.Indent;
import com.intellij.formatting.*;
import com.intellij.lang.ASTNode;
import com.intellij.openapi.util.TextRange;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiFile;
import com.intellij.psi.codeStyle.CodeStyleSettings;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.JetNodeTypes;
import org.jetbrains.jet.lexer.JetTokens;
import static org.jetbrains.jet.JetNodeTypes.*;
import static org.jetbrains.jet.lexer.JetTokens.*;
/**
* @author yole
@@ -18,10 +20,22 @@ public class JetFormattingModelBuilder implements FormattingModelBuilder {
@NotNull
@Override
public FormattingModel createModel(PsiElement element, CodeStyleSettings settings) {
final JetBlock block = new JetBlock(element.getNode(), null, Indent.getNoneIndent(), null, settings);
final JetBlock block = new JetBlock(element.getNode(), null, Indent.getNoneIndent(), null, settings,
createSpacingBuilder(settings));
return FormattingModelProvider.createFormattingModelForPsiFile(element.getContainingFile(), block, settings);
}
private static SpacingBuilder createSpacingBuilder(CodeStyleSettings settings) {
return new SpacingBuilder(settings)
.before(COMMA).spaceIf(settings.SPACE_BEFORE_COMMA)
.after(COMMA).spaceIf(settings.SPACE_AFTER_COMMA)
.around(EQ).spaceIf(settings.SPACE_AROUND_ASSIGNMENT_OPERATORS)
.beforeInside(BLOCK, FUN).spaceIf(settings.SPACE_BEFORE_METHOD_LBRACE)
.afterInside(LBRACE, BLOCK).lineBreakInCode()
.beforeInside(RBRACE, CLASS_BODY).lineBreakInCode()
.beforeInside(RBRACE, BLOCK).lineBreakInCode();
}
@Override
public TextRange getRangeAffectingIndent(PsiFile psiFile, int i, ASTNode astNode) {
return null;
@@ -0,0 +1,7 @@
trait G<T> {
fun foo(t : T) : T
}
class GC() : G<Int> {
<caret>
}
@@ -0,0 +1,10 @@
trait G<T> {
fun foo(t : T) : T
}
class GC() : G<Int> {
override fun foo(t: Int): Int {
return 0
}
}
@@ -0,0 +1,5 @@
import foo.Intf
class Impl(): Intf {
<caret>
}
@@ -0,0 +1,8 @@
import foo.Intf
class Impl(): Intf {
override fun getFooBar(): String? {
return null
}
}
@@ -0,0 +1,5 @@
package foo;
interface Intf {
String getFooBar();
}
@@ -0,0 +1,5 @@
import foo.Intf
class Impl(): Intf {
<caret>
}
@@ -0,0 +1,7 @@
import foo.Intf
class Impl(): Intf {
override fun fooBar(i: Int, s: Array<String?>?, foo: Any?) {
}
}
@@ -0,0 +1,5 @@
package foo;
interface Intf {
void fooBar(int i, String[] s, Object foo);
}
@@ -0,0 +1,7 @@
trait T {
val v : Int
}
class GC() : T {
<caret>
}
@@ -0,0 +1,8 @@
trait T {
val v : Int
}
class GC() : T {
override val v: Int = 0
}
@@ -6,7 +6,7 @@ import junit.framework.Test;
import junit.framework.TestSuite;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.JetTestCaseBuilder;
import org.jetbrains.jet.plugin.quickfix.PluginTestCaseBase;
import org.jetbrains.jet.plugin.PluginTestCaseBase;
import java.io.File;
@@ -0,0 +1,33 @@
package org.jetbrains.jet.plugin;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.module.ModuleType;
import com.intellij.openapi.module.StdModuleTypes;
import com.intellij.openapi.projectRoots.Sdk;
import com.intellij.openapi.roots.ContentEntry;
import com.intellij.openapi.roots.ModifiableRootModel;
import com.intellij.testFramework.LightProjectDescriptor;
/**
* @author yole
*/
public class JetLightProjectDescriptor implements LightProjectDescriptor {
private JetLightProjectDescriptor() {
}
public static final JetLightProjectDescriptor INSTANCE = new JetLightProjectDescriptor();
@Override
public ModuleType getModuleType() {
return StdModuleTypes.JAVA;
}
@Override
public Sdk getSdk() {
return PluginTestCaseBase.jdkFromIdeaHome();
}
@Override
public void configureModule(Module module, ModifiableRootModel model, ContentEntry contentEntry) {
}
}
@@ -1,4 +1,4 @@
package org.jetbrains.jet.plugin.quickfix;
package org.jetbrains.jet.plugin;
import com.intellij.openapi.projectRoots.Sdk;
import com.intellij.openapi.projectRoots.impl.JavaSdkImpl;
@@ -8,6 +8,9 @@ import org.jetbrains.jet.JetTestCaseBuilder;
* @author yole
*/
public class PluginTestCaseBase {
private PluginTestCaseBase() {
}
public static String getTestDataPathBase() {
return JetTestCaseBuilder.getHomeDirectory() + "/idea/testData";
}
@@ -0,0 +1,75 @@
package org.jetbrains.jet.plugin.codeInsight;
import com.intellij.openapi.application.Result;
import com.intellij.openapi.command.WriteCommandAction;
import com.intellij.psi.PsiElement;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.testFramework.LightProjectDescriptor;
import com.intellij.testFramework.fixtures.LightCodeInsightFixtureTestCase;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.descriptors.CallableMemberDescriptor;
import org.jetbrains.jet.lang.psi.JetClassOrObject;
import org.jetbrains.jet.plugin.JetLightProjectDescriptor;
import org.jetbrains.jet.plugin.PluginTestCaseBase;
import java.util.Set;
/**
* @author yole
*/
public class OverrideImplementTest extends LightCodeInsightFixtureTestCase {
@NotNull
@Override
protected LightProjectDescriptor getProjectDescriptor() {
return JetLightProjectDescriptor.INSTANCE;
}
@Override
public void setUp() throws Exception {
super.setUp();
myFixture.setTestDataPath(PluginTestCaseBase.getTestDataPathBase() + "/codeInsight/overrideImplement");
}
public void testJavaInterfaceMethod() {
doDirectoryTest();
}
public void testJavaParameters() {
doDirectoryTest();
}
public void testGenericMethod() {
doFileTest();
}
public void testProperty() {
doFileTest();
}
private void doFileTest() {
myFixture.configureByFile(getTestName(true) + ".kt");
doImplement();
myFixture.checkResultByFile(getTestName(true) + ".kt.after");
}
private void doDirectoryTest() {
myFixture.copyDirectoryToProject(getTestName(true), "");
myFixture.configureFromTempProjectFile("foo/Impl.kt");
doImplement();
myFixture.checkResultByFile(getTestName(true) + "/foo/Impl.kt.after");
}
private void doImplement() {
final PsiElement elementAtCaret = myFixture.getFile().findElementAt(myFixture.getEditor().getCaretModel().getOffset());
final JetClassOrObject classOrObject = PsiTreeUtil.getParentOfType(elementAtCaret, JetClassOrObject.class);
final Set<CallableMemberDescriptor> descriptors = new ImplementMethodsHandler().collectMethodsToGenerate(classOrObject);
assertEquals(1, descriptors.size());
new WriteCommandAction(myFixture.getProject(), myFixture.getFile()) {
@Override
protected void run(Result result) throws Throwable {
ImplementMethodsHandler.generateMethods(myFixture.getProject(), myFixture.getEditor(), classOrObject,
ImplementMethodsHandler.membersFromDescriptors(descriptors));
}
}.execute();
}
}
@@ -7,6 +7,7 @@ import junit.framework.Test;
import junit.framework.TestSuite;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.JetTestCaseBuilder;
import org.jetbrains.jet.plugin.PluginTestCaseBase;
import java.io.File;
import java.io.FilenameFilter;
+9 -2
View File
@@ -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 classpathRoots: ArrayList<String?> = ArrayList<String?>()
var _jarName: String? = null
@@ -66,4 +66,11 @@ class ModuleBuilder(val name: String): IModuleBuilder {
override fun getModuleName(): String? = name
override fun getJarName(): String? = _jarName
}
}
class ModuleBuilder2(name: String): ModuleBuilder(name) {
}
}