Merge branch 'master' of ssh://git.labs.intellij.net/jet
This commit is contained in:
+1
@@ -189,6 +189,7 @@ public class JavaDescriptorResolver {
|
|||||||
TypeParameterDescriptor typeParameterDescriptor = TypeParameterDescriptor.createForFurtherModification(
|
TypeParameterDescriptor typeParameterDescriptor = TypeParameterDescriptor.createForFurtherModification(
|
||||||
owner,
|
owner,
|
||||||
Collections.<AnnotationDescriptor>emptyList(), // TODO
|
Collections.<AnnotationDescriptor>emptyList(), // TODO
|
||||||
|
false,
|
||||||
Variance.INVARIANT,
|
Variance.INVARIANT,
|
||||||
typeParameter.getName(),
|
typeParameter.getName(),
|
||||||
typeParameter.getIndex()
|
typeParameter.getIndex()
|
||||||
|
|||||||
+13
-3
@@ -21,10 +21,11 @@ public class TypeParameterDescriptor extends DeclarationDescriptorImpl implement
|
|||||||
public static TypeParameterDescriptor createWithDefaultBound(
|
public static TypeParameterDescriptor createWithDefaultBound(
|
||||||
@NotNull DeclarationDescriptor containingDeclaration,
|
@NotNull DeclarationDescriptor containingDeclaration,
|
||||||
@NotNull List<AnnotationDescriptor> annotations,
|
@NotNull List<AnnotationDescriptor> annotations,
|
||||||
|
boolean reified,
|
||||||
@NotNull Variance variance,
|
@NotNull Variance variance,
|
||||||
@NotNull String name,
|
@NotNull String name,
|
||||||
int index) {
|
int index) {
|
||||||
TypeParameterDescriptor typeParameterDescriptor = createForFurtherModification(containingDeclaration, annotations, variance, name, index);
|
TypeParameterDescriptor typeParameterDescriptor = createForFurtherModification(containingDeclaration, annotations, reified, variance, name, index);
|
||||||
typeParameterDescriptor.addUpperBound(JetStandardClasses.getDefaultBound());
|
typeParameterDescriptor.addUpperBound(JetStandardClasses.getDefaultBound());
|
||||||
return typeParameterDescriptor;
|
return typeParameterDescriptor;
|
||||||
}
|
}
|
||||||
@@ -32,10 +33,11 @@ public class TypeParameterDescriptor extends DeclarationDescriptorImpl implement
|
|||||||
public static TypeParameterDescriptor createForFurtherModification(
|
public static TypeParameterDescriptor createForFurtherModification(
|
||||||
@NotNull DeclarationDescriptor containingDeclaration,
|
@NotNull DeclarationDescriptor containingDeclaration,
|
||||||
@NotNull List<AnnotationDescriptor> annotations,
|
@NotNull List<AnnotationDescriptor> annotations,
|
||||||
|
boolean reified,
|
||||||
@NotNull Variance variance,
|
@NotNull Variance variance,
|
||||||
@NotNull String name,
|
@NotNull String name,
|
||||||
int index) {
|
int index) {
|
||||||
return new TypeParameterDescriptor(containingDeclaration, annotations, variance, name, index);
|
return new TypeParameterDescriptor(containingDeclaration, annotations, reified, variance, name, index);
|
||||||
}
|
}
|
||||||
|
|
||||||
private final int index;
|
private final int index;
|
||||||
@@ -47,9 +49,12 @@ public class TypeParameterDescriptor extends DeclarationDescriptorImpl implement
|
|||||||
private final Set<JetType> classObjectUpperBounds = Sets.newLinkedHashSet();
|
private final Set<JetType> classObjectUpperBounds = Sets.newLinkedHashSet();
|
||||||
private JetType classObjectBoundsAsType;
|
private JetType classObjectBoundsAsType;
|
||||||
|
|
||||||
|
private final boolean reified;
|
||||||
|
|
||||||
private TypeParameterDescriptor(
|
private TypeParameterDescriptor(
|
||||||
@NotNull DeclarationDescriptor containingDeclaration,
|
@NotNull DeclarationDescriptor containingDeclaration,
|
||||||
@NotNull List<AnnotationDescriptor> annotations,
|
@NotNull List<AnnotationDescriptor> annotations,
|
||||||
|
boolean reified,
|
||||||
@NotNull Variance variance,
|
@NotNull Variance variance,
|
||||||
@NotNull String name,
|
@NotNull String name,
|
||||||
int index) {
|
int index) {
|
||||||
@@ -57,6 +62,7 @@ public class TypeParameterDescriptor extends DeclarationDescriptorImpl implement
|
|||||||
this.index = index;
|
this.index = index;
|
||||||
this.variance = variance;
|
this.variance = variance;
|
||||||
this.upperBounds = Sets.newLinkedHashSet();
|
this.upperBounds = Sets.newLinkedHashSet();
|
||||||
|
this.reified = reified;
|
||||||
// TODO: Should we actually pass the annotations on to the type constructor?
|
// TODO: Should we actually pass the annotations on to the type constructor?
|
||||||
this.typeConstructor = new TypeConstructorImpl(
|
this.typeConstructor = new TypeConstructorImpl(
|
||||||
this,
|
this,
|
||||||
@@ -67,6 +73,10 @@ public class TypeParameterDescriptor extends DeclarationDescriptorImpl implement
|
|||||||
upperBounds);
|
upperBounds);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isReified() {
|
||||||
|
return reified;
|
||||||
|
}
|
||||||
|
|
||||||
public Variance getVariance() {
|
public Variance getVariance() {
|
||||||
return variance;
|
return variance;
|
||||||
}
|
}
|
||||||
@@ -162,6 +172,6 @@ public class TypeParameterDescriptor extends DeclarationDescriptorImpl implement
|
|||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
public TypeParameterDescriptor copy(@NotNull DeclarationDescriptor newOwner) {
|
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
|
@NotNull
|
||||||
public List<JetClassInitializer> getAnonymousInitializers() {
|
public List<JetClassInitializer> getAnonymousInitializers() {
|
||||||
JetClassBody body = (JetClassBody) findChildByType(JetNodeTypes.CLASS_BODY);
|
JetClassBody body = getBody();
|
||||||
if (body == null) return Collections.emptyList();
|
if (body == null) return Collections.emptyList();
|
||||||
|
|
||||||
return body.getAnonymousInitializers();
|
return body.getAnonymousInitializers();
|
||||||
@@ -90,15 +90,20 @@ public class JetClass extends JetTypeParameterListOwner implements JetClassOrObj
|
|||||||
return (JetObjectDeclarationName) findChildByType(JetNodeTypes.OBJECT_DECLARATION_NAME);
|
return (JetObjectDeclarationName) findChildByType(JetNodeTypes.OBJECT_DECLARATION_NAME);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public JetClassBody getBody() {
|
||||||
|
return (JetClassBody) findChildByType(JetNodeTypes.CLASS_BODY);
|
||||||
|
}
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
public JetClassObject getClassObject() {
|
public JetClassObject getClassObject() {
|
||||||
JetClassBody body = (JetClassBody) findChildByType(JetNodeTypes.CLASS_BODY);
|
JetClassBody body = getBody();
|
||||||
if (body == null) return null;
|
if (body == null) return null;
|
||||||
return body.getClassObject();
|
return body.getClassObject();
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<JetProperty> getProperties() {
|
public List<JetProperty> getProperties() {
|
||||||
JetClassBody body = (JetClassBody) findChildByType(JetNodeTypes.CLASS_BODY);
|
JetClassBody body = getBody();
|
||||||
if (body == null) return Collections.emptyList();
|
if (body == null) return Collections.emptyList();
|
||||||
|
|
||||||
return body.getProperties();
|
return body.getProperties();
|
||||||
|
|||||||
@@ -1,10 +1,13 @@
|
|||||||
package org.jetbrains.jet.lang.psi;
|
package org.jetbrains.jet.lang.psi;
|
||||||
|
|
||||||
import com.intellij.lang.ASTNode;
|
import com.intellij.lang.ASTNode;
|
||||||
|
import com.intellij.psi.PsiElement;
|
||||||
|
import com.intellij.psi.tree.TokenSet;
|
||||||
import com.intellij.psi.util.PsiTreeUtil;
|
import com.intellij.psi.util.PsiTreeUtil;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
import org.jetbrains.jet.JetNodeTypes;
|
import org.jetbrains.jet.JetNodeTypes;
|
||||||
|
import org.jetbrains.jet.lexer.JetTokens;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
@@ -48,4 +51,9 @@ public class JetClassBody extends JetElement {
|
|||||||
public JetClassObject getClassObject() {
|
public JetClassObject getClassObject() {
|
||||||
return (JetClassObject) findChildByType(JetNodeTypes.CLASS_OBJECT);
|
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
|
@Nullable
|
||||||
JetObjectDeclarationName getNameAsDeclaration();
|
JetObjectDeclarationName getNameAsDeclaration();
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
JetClassBody getBody();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -69,10 +69,15 @@ public class JetObjectDeclaration extends JetNamedDeclaration implements JetClas
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public JetClassBody getBody() {
|
||||||
|
return (JetClassBody) findChildByType(JetNodeTypes.CLASS_BODY);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@NotNull
|
@NotNull
|
||||||
public List<JetDeclaration> getDeclarations() {
|
public List<JetDeclaration> getDeclarations() {
|
||||||
JetClassBody body = (JetClassBody) findChildByType(JetNodeTypes.CLASS_BODY);
|
JetClassBody body = getBody();
|
||||||
if (body == null) return Collections.emptyList();
|
if (body == null) return Collections.emptyList();
|
||||||
|
|
||||||
return body.getDeclarations();
|
return body.getDeclarations();
|
||||||
|
|||||||
@@ -54,7 +54,7 @@ public class JetPsiFactory {
|
|||||||
return createProperty(project, text);
|
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);
|
return createDeclaration(project, text, JetProperty.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -50,6 +50,7 @@ public class ClassDescriptorResolver {
|
|||||||
TypeParameterDescriptor typeParameterDescriptor = TypeParameterDescriptor.createForFurtherModification(
|
TypeParameterDescriptor typeParameterDescriptor = TypeParameterDescriptor.createForFurtherModification(
|
||||||
descriptor,
|
descriptor,
|
||||||
annotationResolver.createAnnotationStubs(typeParameter.getModifierList()),
|
annotationResolver.createAnnotationStubs(typeParameter.getModifierList()),
|
||||||
|
true,
|
||||||
typeParameter.getVariance(),
|
typeParameter.getVariance(),
|
||||||
JetPsiUtil.safeName(typeParameter.getName()),
|
JetPsiUtil.safeName(typeParameter.getName()),
|
||||||
index
|
index
|
||||||
@@ -313,6 +314,7 @@ public class ClassDescriptorResolver {
|
|||||||
TypeParameterDescriptor typeParameterDescriptor = TypeParameterDescriptor.createForFurtherModification(
|
TypeParameterDescriptor typeParameterDescriptor = TypeParameterDescriptor.createForFurtherModification(
|
||||||
containingDescriptor,
|
containingDescriptor,
|
||||||
annotationResolver.createAnnotationStubs(typeParameter.getModifierList()),
|
annotationResolver.createAnnotationStubs(typeParameter.getModifierList()),
|
||||||
|
true,
|
||||||
typeParameter.getVariance(),
|
typeParameter.getVariance(),
|
||||||
JetPsiUtil.safeName(typeParameter.getName()),
|
JetPsiUtil.safeName(typeParameter.getName()),
|
||||||
index
|
index
|
||||||
|
|||||||
@@ -103,66 +103,10 @@ public class OverrideResolver {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Check if everything that must be overridden, actually is
|
// 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
|
// More than one implementation or no implementations at all
|
||||||
Set<CallableMemberDescriptor> abstractNoImpl = Sets.newLinkedHashSet();
|
Set<CallableMemberDescriptor> abstractNoImpl = Sets.newLinkedHashSet();
|
||||||
Set<CallableMemberDescriptor> manyImpl = Sets.newLinkedHashSet();
|
Set<CallableMemberDescriptor> manyImpl = Sets.newLinkedHashSet();
|
||||||
for (CallableMemberDescriptor key : factoredMembers.keySet()) {
|
collectMissingImplementations(classDescriptor, abstractNoImpl, manyImpl);
|
||||||
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);
|
|
||||||
|
|
||||||
PsiElement nameIdentifier = klass;
|
PsiElement nameIdentifier = klass;
|
||||||
if (klass instanceof JetClass) {
|
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) {
|
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) {
|
||||||
|
|||||||
@@ -40,6 +40,7 @@ public class DescriptorSubstitutor {
|
|||||||
TypeParameterDescriptor substituted = TypeParameterDescriptor.createForFurtherModification(
|
TypeParameterDescriptor substituted = TypeParameterDescriptor.createForFurtherModification(
|
||||||
newContainingDeclaration,
|
newContainingDeclaration,
|
||||||
descriptor.getAnnotations(),
|
descriptor.getAnnotations(),
|
||||||
|
descriptor.isReified(),
|
||||||
descriptor.getVariance(),
|
descriptor.getVariance(),
|
||||||
descriptor.getName(),
|
descriptor.getName(),
|
||||||
descriptor.getIndex());
|
descriptor.getIndex());
|
||||||
|
|||||||
@@ -116,7 +116,7 @@ public class JetStandardClasses {
|
|||||||
parameters.add(TypeParameterDescriptor.createWithDefaultBound(
|
parameters.add(TypeParameterDescriptor.createWithDefaultBound(
|
||||||
classDescriptor,
|
classDescriptor,
|
||||||
Collections.<AnnotationDescriptor>emptyList(),
|
Collections.<AnnotationDescriptor>emptyList(),
|
||||||
Variance.OUT_VARIANCE, "T" + j, j));
|
true, Variance.OUT_VARIANCE, "T" + j, j));
|
||||||
}
|
}
|
||||||
TUPLE[i] = classDescriptor.initialize(
|
TUPLE[i] = classDescriptor.initialize(
|
||||||
true,
|
true,
|
||||||
@@ -159,7 +159,7 @@ public class JetStandardClasses {
|
|||||||
parameters.add(0, TypeParameterDescriptor.createWithDefaultBound(
|
parameters.add(0, TypeParameterDescriptor.createWithDefaultBound(
|
||||||
receiverFunction,
|
receiverFunction,
|
||||||
Collections.<AnnotationDescriptor>emptyList(),
|
Collections.<AnnotationDescriptor>emptyList(),
|
||||||
Variance.IN_VARIANCE, "T", 0));
|
true, Variance.IN_VARIANCE, "T", 0));
|
||||||
RECEIVER_FUNCTION[i] = receiverFunction.initialize(
|
RECEIVER_FUNCTION[i] = receiverFunction.initialize(
|
||||||
false,
|
false,
|
||||||
parameters,
|
parameters,
|
||||||
@@ -174,12 +174,12 @@ public class JetStandardClasses {
|
|||||||
parameters.add(TypeParameterDescriptor.createWithDefaultBound(
|
parameters.add(TypeParameterDescriptor.createWithDefaultBound(
|
||||||
function,
|
function,
|
||||||
Collections.<AnnotationDescriptor>emptyList(),
|
Collections.<AnnotationDescriptor>emptyList(),
|
||||||
Variance.IN_VARIANCE, "P" + j, j + 1));
|
true, Variance.IN_VARIANCE, "P" + j, j + 1));
|
||||||
}
|
}
|
||||||
parameters.add(TypeParameterDescriptor.createWithDefaultBound(
|
parameters.add(TypeParameterDescriptor.createWithDefaultBound(
|
||||||
function,
|
function,
|
||||||
Collections.<AnnotationDescriptor>emptyList(),
|
Collections.<AnnotationDescriptor>emptyList(),
|
||||||
Variance.OUT_VARIANCE, "R", parameterCount + 1));
|
true, Variance.OUT_VARIANCE, "R", parameterCount + 1));
|
||||||
return parameters;
|
return parameters;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -311,6 +311,9 @@ public class DescriptorRenderer implements Renderer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected void renderTypeParameter(TypeParameterDescriptor descriptor, StringBuilder builder) {
|
protected void renderTypeParameter(TypeParameterDescriptor descriptor, StringBuilder builder) {
|
||||||
|
if (!descriptor.isReified()) {
|
||||||
|
builder.append(renderKeyword("erased")).append(" ");
|
||||||
|
}
|
||||||
renderName(descriptor, builder);
|
renderName(descriptor, builder);
|
||||||
if (!descriptor.getUpperBounds().isEmpty()) {
|
if (!descriptor.getUpperBounds().isEmpty()) {
|
||||||
JetType bound = descriptor.getUpperBounds().iterator().next();
|
JetType bound = descriptor.getUpperBounds().iterator().next();
|
||||||
|
|||||||
@@ -54,5 +54,7 @@
|
|||||||
<fileTypeIndentOptionsProvider implementation="org.jetbrains.jet.plugin.formatter.JetIndentOptionsProvider"/>
|
<fileTypeIndentOptionsProvider implementation="org.jetbrains.jet.plugin.formatter.JetIndentOptionsProvider"/>
|
||||||
<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.overrideMethod language="jet" implementationClass="org.jetbrains.jet.plugin.codeInsight.OverrideMethodsHandler"/>
|
||||||
</extensions>
|
</extensions>
|
||||||
</idea-plugin>
|
</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 Indent myIndent;
|
||||||
private Wrap myWrap;
|
private Wrap myWrap;
|
||||||
private CodeStyleSettings mySettings;
|
private CodeStyleSettings mySettings;
|
||||||
|
private final SpacingBuilder mySpacingBuilder;
|
||||||
private List<Block> mySubBlocks;
|
private List<Block> mySubBlocks;
|
||||||
|
|
||||||
private static final TokenSet CODE_BLOCKS = TokenSet.create(
|
private static final TokenSet CODE_BLOCKS = TokenSet.create(
|
||||||
@@ -35,12 +36,14 @@ public class JetBlock implements ASTBlock {
|
|||||||
JetNodeTypes.THEN,
|
JetNodeTypes.THEN,
|
||||||
JetNodeTypes.ELSE);
|
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;
|
myNode = node;
|
||||||
myAlignment = alignment;
|
myAlignment = alignment;
|
||||||
myIndent = indent;
|
myIndent = indent;
|
||||||
myWrap = wrap;
|
myWrap = wrap;
|
||||||
mySettings = settings;
|
mySettings = settings;
|
||||||
|
mySpacingBuilder = spacingBuilder;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -110,7 +113,7 @@ public class JetBlock implements ASTBlock {
|
|||||||
childIndent = Indent.getNormalIndent();
|
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) {
|
private static Indent indentIfNotBrace(ASTNode child) {
|
||||||
@@ -120,8 +123,8 @@ public class JetBlock implements ASTBlock {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Spacing getSpacing(Block block, Block block1) {
|
public Spacing getSpacing(Block child1, Block child2) {
|
||||||
return null;
|
return mySpacingBuilder.getSpacing(this, child1, child2);
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
|
|||||||
@@ -1,15 +1,17 @@
|
|||||||
package org.jetbrains.jet.plugin.formatter;
|
package org.jetbrains.jet.plugin.formatter;
|
||||||
|
|
||||||
import com.intellij.formatting.FormattingModel;
|
import com.intellij.formatting.*;
|
||||||
import com.intellij.formatting.FormattingModelBuilder;
|
|
||||||
import com.intellij.formatting.FormattingModelProvider;
|
|
||||||
import com.intellij.formatting.Indent;
|
|
||||||
import com.intellij.lang.ASTNode;
|
import com.intellij.lang.ASTNode;
|
||||||
import com.intellij.openapi.util.TextRange;
|
import com.intellij.openapi.util.TextRange;
|
||||||
import com.intellij.psi.PsiElement;
|
import com.intellij.psi.PsiElement;
|
||||||
import com.intellij.psi.PsiFile;
|
import com.intellij.psi.PsiFile;
|
||||||
import com.intellij.psi.codeStyle.CodeStyleSettings;
|
import com.intellij.psi.codeStyle.CodeStyleSettings;
|
||||||
import org.jetbrains.annotations.NotNull;
|
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
|
* @author yole
|
||||||
@@ -18,10 +20,22 @@ public class JetFormattingModelBuilder implements FormattingModelBuilder {
|
|||||||
@NotNull
|
@NotNull
|
||||||
@Override
|
@Override
|
||||||
public FormattingModel createModel(PsiElement element, CodeStyleSettings settings) {
|
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);
|
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
|
@Override
|
||||||
public TextRange getRangeAffectingIndent(PsiFile psiFile, int i, ASTNode astNode) {
|
public TextRange getRangeAffectingIndent(PsiFile psiFile, int i, ASTNode astNode) {
|
||||||
return null;
|
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 junit.framework.TestSuite;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.jet.JetTestCaseBuilder;
|
import org.jetbrains.jet.JetTestCaseBuilder;
|
||||||
import org.jetbrains.jet.plugin.quickfix.PluginTestCaseBase;
|
import org.jetbrains.jet.plugin.PluginTestCaseBase;
|
||||||
|
|
||||||
import java.io.File;
|
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) {
|
||||||
|
}
|
||||||
|
}
|
||||||
+4
-1
@@ -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.Sdk;
|
||||||
import com.intellij.openapi.projectRoots.impl.JavaSdkImpl;
|
import com.intellij.openapi.projectRoots.impl.JavaSdkImpl;
|
||||||
@@ -8,6 +8,9 @@ import org.jetbrains.jet.JetTestCaseBuilder;
|
|||||||
* @author yole
|
* @author yole
|
||||||
*/
|
*/
|
||||||
public class PluginTestCaseBase {
|
public class PluginTestCaseBase {
|
||||||
|
private PluginTestCaseBase() {
|
||||||
|
}
|
||||||
|
|
||||||
public static String getTestDataPathBase() {
|
public static String getTestDataPathBase() {
|
||||||
return JetTestCaseBuilder.getHomeDirectory() + "/idea/testData";
|
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 junit.framework.TestSuite;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.jet.JetTestCaseBuilder;
|
import org.jetbrains.jet.JetTestCaseBuilder;
|
||||||
|
import org.jetbrains.jet.plugin.PluginTestCaseBase;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.FilenameFilter;
|
import java.io.FilenameFilter;
|
||||||
|
|||||||
@@ -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
|
||||||
@@ -66,4 +66,11 @@ class ModuleBuilder(val name: String): IModuleBuilder {
|
|||||||
override fun getModuleName(): String? = name
|
override fun getModuleName(): String? = name
|
||||||
override fun getJarName(): String? = _jarName
|
override fun getJarName(): String? = _jarName
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class ModuleBuilder2(name: String): ModuleBuilder(name) {
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user