TopDown analysis for declarations

This commit is contained in:
Andrey Breslav
2011-02-28 13:57:47 +03:00
parent a24c33f81b
commit 248ed385d5
30 changed files with 698 additions and 115 deletions
+3 -2
View File
@@ -1,7 +1,8 @@
namespace jet.lang
virtual class Comparable<T> {
fun compareTo(other : T) : Int
class Array<T> {
fun get(index : Int) : T
fun set(index : Int, value : T) : Unit
}
class Boolean {
@@ -4,9 +4,10 @@ import com.intellij.lang.annotation.AnnotationHolder;
import com.intellij.lang.annotation.Annotator;
import com.intellij.psi.PsiElement;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.psi.*;
import java.util.List;
import org.jetbrains.jet.lang.psi.JetFile;
import org.jetbrains.jet.lang.resolve.FileContentsResolver;
import org.jetbrains.jet.lang.resolve.JetScope;
import org.jetbrains.jet.lang.types.JetStandardClasses;
/**
* @author abreslav
@@ -16,47 +17,8 @@ public class JetPsiChecker implements Annotator {
@Override
public void annotate(@NotNull PsiElement element, @NotNull AnnotationHolder holder) {
if (element instanceof JetFile) {
// JetProperty property = (JetProperty) element;
// holder.createErrorAnnotation(property.getNameIdentifier(), "Specify either type or value");
JetFile file = (JetFile) element;
String path = file.getProject().getBaseDir().getPath();
println("Path: " + path);
JetNamespace rootNamespace = file.getRootNamespace();
List<JetDeclaration> declarations = rootNamespace.getDeclarations();
for (JetDeclaration declaration : declarations) {
declaration.accept(new JetVisitor() {
@Override
public void visitClass(JetClass klass) {
print("class ");
print(klass.getName());
println("{");
for (JetDeclaration decl : klass.getDeclarations()) {
decl.accept(this);
}
print("}");
}
@Override
public void visitProperty(JetProperty property) {
JetTypeReference propertyTypeRef = property.getPropertyTypeRef();
String name = property.getName();
}
@Override
public void visitFunction(JetFunction function) {
super.visitFunction(function); //To change body of overridden methods use File | Settings | File Templates.
}
});
}
JetScope jetScope = FileContentsResolver.INSTANCE.resolveFileContents(JetStandardClasses.STANDARD_CLASSES, file);
}
}
private void print(Object o) {
// System.out.print(o);
}
private void println(Object o) {
// System.out.println(o);
}
}
@@ -0,0 +1,17 @@
package org.jetbrains.jet.lang.resolve;
import org.jetbrains.jet.lang.psi.*;
import org.jetbrains.jet.lang.types.*;
/**
* @author abreslav
*/
public interface BindingContext {
NamespaceDescriptor getNamespaceDescriptor(JetNamespace declaration);
ClassDescriptor getClassDescriptor(JetClass declaration);
FunctionDescriptor getFunctionDescriptor(JetFunction declaration);
PropertyDescriptor getPropertyDescriptor(JetProperty declaration);
Type getExpressionType(JetExpression expression);
DeclarationDescriptor resolve(JetReferenceExpression referenceExpression);
}
@@ -33,6 +33,7 @@ public class ClassDescriptorResolver {
WritableScope members = resolveMembers(classElement, typeParameters, scope, parameterScope, superclasses);
return new ClassDescriptorImpl(
classElement,
AttributeResolver.INSTANCE.resolveAttributes(classElement.getModifierList()),
!open,
classElement.getName(),
@@ -42,6 +43,31 @@ public class ClassDescriptorResolver {
);
}
@Nullable
public void resolveMutableClassDescriptor(@NotNull JetScope scope, @NotNull JetClass classElement, @NotNull MutableClassDescriptor descriptor) {
WritableScope parameterScope = new WritableScope(scope);
// This call has side-effects on the parameterScope (fills it in)
List<TypeParameterDescriptor> typeParameters
= resolveTypeParameters(parameterScope, classElement.getTypeParameters());
List<JetDelegationSpecifier> delegationSpecifiers = classElement.getDelegationSpecifiers();
// TODO : assuming that the hierarchy is acyclic
Collection<? extends Type> superclasses = delegationSpecifiers.isEmpty()
? Collections.singleton(JetStandardClasses.getAnyType())
: resolveTypes(parameterScope, delegationSpecifiers);
boolean open = classElement.hasModifier(JetTokens.OPEN_KEYWORD);
descriptor.setTypeConstructor(
new TypeConstructor(
AttributeResolver.INSTANCE.resolveAttributes(classElement.getModifierList()),
!open,
classElement.getName(),
typeParameters,
superclasses)
);
}
private WritableScope resolveMembers(
final JetClass classElement,
List<TypeParameterDescriptor> typeParameters,
@@ -104,6 +130,7 @@ public class ClassDescriptorResolver {
}
return new FunctionDescriptorImpl(
function,
AttributeResolver.INSTANCE.resolveAttributes(function.getModifierList()),
function.getName(),
typeParameterDescriptors,
@@ -120,6 +147,7 @@ public class ClassDescriptorResolver {
assert typeReference != null : "Parameters without type annotations are not supported"; // TODO
ValueParameterDescriptor valueParameterDescriptor = new ValueParameterDescriptorImpl(
valueParameter,
AttributeResolver.INSTANCE.resolveAttributes(valueParameter.getModifierList()),
valueParameter.getName(),
TypeResolver.INSTANCE.resolveType(parameterScope, typeReference),
@@ -147,6 +175,7 @@ public class ClassDescriptorResolver {
private static TypeParameterDescriptor resolveTypeParameter(WritableScope extensibleScope, JetTypeParameter typeParameter) {
JetTypeReference extendsBound = typeParameter.getExtendsBound();
TypeParameterDescriptor typeParameterDescriptor = new TypeParameterDescriptor(
typeParameter,
AttributeResolver.INSTANCE.resolveAttributes(typeParameter.getModifierList()),
typeParameter.getVariance(),
typeParameter.getName(),
@@ -177,6 +206,7 @@ public class ClassDescriptorResolver {
@NotNull
public PropertyDescriptor resolvePropertyDescriptor(@NotNull JetScope scope, @NotNull JetParameter parameter) {
return new PropertyDescriptorImpl(
parameter,
AttributeResolver.INSTANCE.resolveAttributes(parameter.getModifierList()),
parameter.getName(),
TypeResolver.INSTANCE.resolveType(scope, parameter.getTypeReference()));
@@ -197,6 +227,7 @@ public class ClassDescriptorResolver {
}
return new PropertyDescriptorImpl(
property,
AttributeResolver.INSTANCE.resolveAttributes(property.getModifierList()),
property.getName(),
type);
@@ -78,6 +78,9 @@ public class LazyClassDescriptor implements ClassDescriptor {
unsubstitutedMemberScope = new LazyScope(getTypeParameterScope(), declaration.getDeclarations());
}
List<TypeParameterDescriptor> parameters = getTypeConstructor().getParameters();
if (parameters.isEmpty()) {
return unsubstitutedMemberScope;
}
Map<TypeConstructor,TypeProjection> substitutionContext = TypeSubstitutor.INSTANCE.buildSubstitutionContext(parameters, typeArguments);
return new SubstitutingScope(unsubstitutedMemberScope, substitutionContext);
}
@@ -0,0 +1,52 @@
package org.jetbrains.jet.lang.resolve;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.types.Attribute;
import org.jetbrains.jet.lang.types.ClassDescriptor;
import org.jetbrains.jet.lang.types.TypeConstructor;
import org.jetbrains.jet.lang.types.TypeProjection;
import java.util.List;
import java.util.Map;
/**
* @author abreslav
*/
public class LazySubstitutingClassDescriptor implements ClassDescriptor {
private final ClassDescriptor original;
private final Map<TypeConstructor,TypeProjection> substitutionContext;
public LazySubstitutingClassDescriptor(ClassDescriptor descriptor, Map<TypeConstructor, TypeProjection> substitutionContext) {
this.original = descriptor;
this.substitutionContext = substitutionContext;
}
@NotNull
@Override
public TypeConstructor getTypeConstructor() {
if (substitutionContext.isEmpty()) {
return original.getTypeConstructor();
}
throw new UnsupportedOperationException(); // TODO
}
@Override
public JetScope getMemberScope(List<TypeProjection> typeArguments) {
JetScope memberScope = original.getMemberScope(typeArguments);
if (substitutionContext.isEmpty()) {
return memberScope;
}
return new SubstitutingScope(memberScope, substitutionContext);
}
@Override
public List<Attribute> getAttributes() {
throw new UnsupportedOperationException(); // TODO
}
@Override
public String getName() {
return original.getName();
}
}
@@ -0,0 +1,40 @@
package org.jetbrains.jet.lang.resolve;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.types.*;
import java.util.List;
import java.util.Map;
/**
* @author abreslav
*/
public class MutableClassDescriptor extends MutableDeclarationDescriptor implements ClassDescriptor {
private final WritableScope unsubstitutedMemberScope;
private TypeConstructor typeConstructor;
public MutableClassDescriptor(@NotNull JetScope outerScope) {
this.unsubstitutedMemberScope = new WritableScope(outerScope);
}
@NotNull
@Override
public TypeConstructor getTypeConstructor() {
return typeConstructor;
}
public void setTypeConstructor(@NotNull TypeConstructor typeConstructor) {
this.typeConstructor = typeConstructor;
}
@Override
public JetScope getMemberScope(List<TypeProjection> typeArguments) {
List<TypeParameterDescriptor> typeParameters = getTypeConstructor().getParameters();
Map<TypeConstructor,TypeProjection> substitutionContext = TypeSubstitutor.INSTANCE.buildSubstitutionContext(typeParameters, typeArguments);
return new SubstitutingScope(unsubstitutedMemberScope, substitutionContext);
}
public WritableScope getUnsubstitutedMemberScope() {
return unsubstitutedMemberScope;
}
}
@@ -0,0 +1,28 @@
package org.jetbrains.jet.lang.resolve;
import org.jetbrains.jet.lang.types.Annotated;
import org.jetbrains.jet.lang.types.Attribute;
import org.jetbrains.jet.lang.types.Named;
import java.util.List;
/**
* @author abreslav
*/
public class MutableDeclarationDescriptor implements Annotated, Named {
private String name;
@Override
public List<Attribute> getAttributes() {
throw new UnsupportedOperationException(); // TODO
}
@Override
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
@@ -0,0 +1,32 @@
package org.jetbrains.jet.lang.resolve;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.types.FunctionDescriptor;
import org.jetbrains.jet.lang.types.Type;
import org.jetbrains.jet.lang.types.TypeParameterDescriptor;
import org.jetbrains.jet.lang.types.ValueParameterDescriptor;
import java.util.List;
/**
* @author abreslav
*/
public class MutableFunctionDescriptor extends MutableDeclarationDescriptor implements FunctionDescriptor {
@NotNull
@Override
public List<TypeParameterDescriptor> getTypeParameters() {
throw new UnsupportedOperationException(); // TODO
}
@NotNull
@Override
public List<ValueParameterDescriptor> getUnsubstitutedValueParameters() {
throw new UnsupportedOperationException(); // TODO
}
@NotNull
@Override
public Type getUnsubstitutedReturnType() {
throw new UnsupportedOperationException(); // TODO
}
}
@@ -0,0 +1,46 @@
package org.jetbrains.jet.lang.resolve;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.psi.JetElement;
import org.jetbrains.jet.lang.psi.JetFunction;
import org.jetbrains.jet.lang.psi.JetParameter;
import org.jetbrains.jet.lang.psi.JetTypeParameter;
import org.jetbrains.jet.lang.types.DeclarationDescriptor;
import org.jetbrains.jet.lang.types.FunctionDescriptor;
import org.jetbrains.jet.lang.types.TypeParameterDescriptor;
import org.jetbrains.jet.lang.types.ValueParameterDescriptor;
/**
* @author abreslav
*/
public class ResolveUtil {
@Nullable
private static <T extends JetElement> T getDeclarationElement(Object o) {
if (o instanceof DeclarationDescriptor) {
@SuppressWarnings({"unchecked", "UnnecessaryLocalVariable"})
T psiElement = ((DeclarationDescriptor<T>) o).getPsiElement();
return psiElement;
}
return null;
}
@Nullable
private static <T extends JetElement> T getDeclarationElement(DeclarationDescriptor<T> descriptor) {
return descriptor.getPsiElement();
}
@Nullable
public static JetTypeParameter getJetTypeParameter(TypeParameterDescriptor parameterDescriptor) {
return getDeclarationElement(parameterDescriptor);
}
@Nullable
public static JetParameter getJetParameter(ValueParameterDescriptor parameterDescriptor) {
return getDeclarationElement(parameterDescriptor);
}
@Nullable
public static JetFunction getJetFunction(FunctionDescriptor functionDescriptor) {
return getDeclarationElement(functionDescriptor);
}
}
@@ -29,7 +29,11 @@ public class SubstitutingScope implements JetScope {
@Override
public ClassDescriptor getClass(String name) {
throw new UnsupportedOperationException(); // TODO
ClassDescriptor descriptor = workerScope.getClass(name);
if (descriptor == null) {
return null;
}
return new LazySubstitutingClassDescriptor(descriptor, substitutionContext);
}
@Override
@@ -0,0 +1,181 @@
package org.jetbrains.jet.lang.resolve;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.psi.*;
import org.jetbrains.jet.lang.types.*;
import java.util.*;
/**
* @author abreslav
*/
public class TopDownAnalyzer {
private final WritableBindingContext context = new WritableBindingContext();
private final Map<JetClass, MutableClassDescriptor> classes = new LinkedHashMap<JetClass, MutableClassDescriptor>();
private final Map<JetFunction, FunctionDescriptor> functions = new HashMap<JetFunction, FunctionDescriptor>();
private final Map<JetDeclaration, WritableScope> declaringScopes = new HashMap<JetDeclaration, WritableScope>();
public BindingContext process(@NotNull JetScope outerScope, @NotNull List<JetDeclaration> declarations) {
WritableScope toplevelScope = new WritableScope(outerScope);
collectTypeDeclarators(toplevelScope, declarations);
resolveTypeDeclarations();
collectBehaviorDeclarators(toplevelScope, declarations);
resolveBehaviorDeclarations();
return new BindingContext() {
@Override
public NamespaceDescriptor getNamespaceDescriptor(JetNamespace declaration) {
throw new UnsupportedOperationException(); // TODO
}
@Override
public ClassDescriptor getClassDescriptor(JetClass declaration) {
return classes.get(declaration);
}
@Override
public FunctionDescriptor getFunctionDescriptor(JetFunction declaration) {
throw new UnsupportedOperationException(); // TODO
}
@Override
public PropertyDescriptor getPropertyDescriptor(JetProperty declaration) {
throw new UnsupportedOperationException(); // TODO
}
@Override
public Type getExpressionType(JetExpression expression) {
throw new UnsupportedOperationException(); // TODO
}
@Override
public DeclarationDescriptor resolve(JetReferenceExpression referenceExpression) {
throw new UnsupportedOperationException(); // TODO
}
};
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
private void collectTypeDeclarators(
@NotNull final WritableScope declaringScope,
List<JetDeclaration> declarations) {
for (JetDeclaration declaration : declarations) {
declaration.accept(new JetVisitor() {
@Override
public void visitClass(JetClass klass) {
WritableScope classScope = processClass(declaringScope, klass);
collectTypeDeclarators(classScope, klass.getDeclarations());
}
@Override
public void visitTypedef(JetTypedef typedef) {
processTypeDef(typedef);
}
@Override
public void visitDeclaration(JetDeclaration dcl) {
throw new UnsupportedOperationException(); // TODO
}
});
}
}
private WritableScope processClass(@NotNull WritableScope declaringScope, JetClass klass) {
MutableClassDescriptor mutableClassDescriptor = new MutableClassDescriptor(declaringScope);
mutableClassDescriptor.setName(klass.getName());
declaringScope.addClassDescriptor(mutableClassDescriptor);
classes.put(klass, mutableClassDescriptor);
declaringScopes.put(klass, declaringScope);
return mutableClassDescriptor.getUnsubstitutedMemberScope();
}
private void processExtension(JetExtension extension) {
throw new UnsupportedOperationException(); // TODO
}
private void processTypeDef(JetTypedef typedef) {
throw new UnsupportedOperationException(); // TODO
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
private void resolveTypeDeclarations() {
for (Map.Entry<JetClass, MutableClassDescriptor> entry : classes.entrySet()) {
JetClass jetClass = entry.getKey();
MutableClassDescriptor descriptor = entry.getValue();
ClassDescriptorResolver.INSTANCE.resolveMutableClassDescriptor(declaringScopes.get(jetClass), jetClass, descriptor);
}
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
private void collectBehaviorDeclarators(@NotNull final WritableScope declaringScope, List<JetDeclaration> declarations) {
for (JetDeclaration declaration : declarations) {
declaration.accept(new JetVisitor() {
@Override
public void visitClass(JetClass klass) {
collectBehaviorDeclarators(classes.get(klass).getUnsubstitutedMemberScope(), klass.getDeclarations());
}
@Override
public void visitClassObject(JetClassObject classObject) {
processClassObject(classObject);
collectBehaviorDeclarators(declaringScope, classObject.getObject().getDeclarations());
}
@Override
public void visitNamespace(JetNamespace namespace) {
collectBehaviorDeclarators(declaringScope, namespace.getDeclarations());
}
@Override
public void visitFunction(JetFunction function) {
processFunction(declaringScope, function);
}
@Override
public void visitProperty(JetProperty property) {
processProperty(declaringScope, property);
}
@Override
public void visitDeclaration(JetDeclaration dcl) {
throw new UnsupportedOperationException(); // TODO
}
});
}
}
private void processFunction(@NotNull WritableScope declaringScope, JetFunction function) {
declaringScopes.put(function, declaringScope);
FunctionDescriptor descriptor = ClassDescriptorResolver.INSTANCE.resolveFunctionDescriptor(declaringScope, function);
declaringScope.addFunctionDescriptor(descriptor);
functions.put(function, descriptor);
}
private void processProperty(JetScope declaringScope, JetProperty property) {
throw new UnsupportedOperationException(); // TODO
}
private void processClassObject(JetClassObject classObject) {
throw new UnsupportedOperationException(); // TODO
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
private void resolveBehaviorDeclarations() {
for (Map.Entry<JetFunction, FunctionDescriptor> entry : functions.entrySet()) {
JetFunction function = entry.getKey();
FunctionDescriptor descriptor = entry.getValue();
WritableScope declaringScope = declaringScopes.get(function);
assert declaringScope != null;
}
}
}
@@ -0,0 +1,39 @@
package org.jetbrains.jet.lang.resolve;
import org.jetbrains.jet.lang.psi.*;
import org.jetbrains.jet.lang.types.*;
/**
* @author abreslav
*/
public class WritableBindingContext implements BindingContext {
@Override
public NamespaceDescriptor getNamespaceDescriptor(JetNamespace declaration) {
throw new UnsupportedOperationException(); // TODO
}
@Override
public ClassDescriptor getClassDescriptor(JetClass declaration) {
throw new UnsupportedOperationException(); // TODO
}
@Override
public FunctionDescriptor getFunctionDescriptor(JetFunction declaration) {
throw new UnsupportedOperationException(); // TODO
}
@Override
public PropertyDescriptor getPropertyDescriptor(JetProperty declaration) {
throw new UnsupportedOperationException(); // TODO
}
@Override
public Type getExpressionType(JetExpression expression) {
throw new UnsupportedOperationException(); // TODO
}
@Override
public DeclarationDescriptor resolve(JetReferenceExpression referenceExpression) {
throw new UnsupportedOperationException(); // TODO
}
}
@@ -19,6 +19,8 @@ public class WritableScope extends JetScopeAdapter {
private Map<String, TypeParameterDescriptor> typeParameterDescriptors;
@Nullable
private Map<String, ClassDescriptor> classDescriptors;
@Nullable
private Type thisType;
public WritableScope(JetScope scope) {
super(scope);
@@ -139,7 +141,10 @@ public class WritableScope extends JetScopeAdapter {
@NotNull
@Override
public Type getThisType() {
return super.getThisType(); // TODO
if (thisType == null) {
return super.getThisType();
}
return thisType;
}
@Override
@@ -151,4 +156,11 @@ public class WritableScope extends JetScopeAdapter {
public ExtensionDescriptor getExtension(String name) {
return super.getExtension(name); // TODO
}
public void setThisType(Type thisType) {
if (this.thisType != null) {
throw new UnsupportedOperationException("Receiver redeclared");
}
this.thisType = thisType;
}
}
@@ -1,6 +1,7 @@
package org.jetbrains.jet.lang.types;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.psi.JetClass;
import org.jetbrains.jet.lang.resolve.JetScope;
import org.jetbrains.jet.lang.resolve.SubstitutingScope;
@@ -12,21 +13,22 @@ import java.util.Map;
/**
* @author abreslav
*/
public class ClassDescriptorImpl extends MemberDescriptorImpl implements ClassDescriptor {
public class ClassDescriptorImpl extends DeclarationDescriptorImpl<JetClass> implements ClassDescriptor {
private final TypeConstructor typeConstructor;
private final JetScope memberDeclarations;
public ClassDescriptorImpl(
JetClass psiElement,
List<Attribute> attributes, boolean sealed,
String name, List<TypeParameterDescriptor> typeParameters,
Collection<? extends Type> superclasses, JetScope memberDeclarations) {
super(attributes, name);
super(psiElement, attributes, name);
this.typeConstructor = new TypeConstructor(attributes, sealed, name, typeParameters, superclasses);
this.memberDeclarations = memberDeclarations;
}
public ClassDescriptorImpl(String name, JetScope memberDeclarations) {
this(Collections.<Attribute>emptyList(), true,
this(null, Collections.<Attribute>emptyList(), true,
name, Collections.<TypeParameterDescriptor>emptyList(),
Collections.<Type>singleton(JetStandardClasses.getAnyType()), memberDeclarations);
}
@@ -39,6 +41,9 @@ public class ClassDescriptorImpl extends MemberDescriptorImpl implements ClassDe
@Override
public JetScope getMemberScope(List<TypeProjection> typeArguments) {
if (typeConstructor.getParameters().isEmpty()) {
return memberDeclarations;
}
Map<TypeConstructor,TypeProjection> substitutionContext = TypeSubstitutor.INSTANCE.buildSubstitutionContext(typeConstructor.getParameters(), typeArguments);
return new SubstitutingScope(memberDeclarations, substitutionContext);
}
@@ -0,0 +1,10 @@
package org.jetbrains.jet.lang.types;
import org.jetbrains.jet.lang.psi.JetElement;
/**
* @author abreslav
*/
public interface DeclarationDescriptor<T extends JetElement> {
T getPsiElement();
}
@@ -0,0 +1,30 @@
package org.jetbrains.jet.lang.types;
import org.jetbrains.jet.lang.psi.JetElement;
import java.util.List;
/**
* @author abreslav
*/
public abstract class DeclarationDescriptorImpl<T extends JetElement> extends AnnotatedImpl implements Named, DeclarationDescriptor<T> {
private final String name;
private final T psiElement;
public DeclarationDescriptorImpl(T psiElement, List<Attribute> attributes, String name) {
super(attributes);
this.name = name;
this.psiElement = psiElement;
}
@Override
public String getName() {
return name;
}
@Override
public T getPsiElement() {
return psiElement;
}
}
@@ -1,13 +1,14 @@
package org.jetbrains.jet.lang.types;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.psi.JetFunction;
import java.util.*;
/**
* @author abreslav
*/
public class FunctionDescriptorImpl extends MemberDescriptorImpl implements FunctionDescriptor {
public class FunctionDescriptorImpl extends DeclarationDescriptorImpl<JetFunction> implements FunctionDescriptor {
@NotNull
private final List<TypeParameterDescriptor> typeParameters;
@NotNull
@@ -16,12 +17,13 @@ public class FunctionDescriptorImpl extends MemberDescriptorImpl implements Func
private final Type unsubstitutedReturnType;
public FunctionDescriptorImpl(
JetFunction psiElement,
@NotNull List<Attribute> attributes,
String name,
@NotNull List<TypeParameterDescriptor> typeParameters,
@NotNull List<ValueParameterDescriptor> unsubstitutedValueParameters,
@NotNull Type unsubstitutedReturnType) {
super(attributes, name);
super(psiElement, attributes, name);
this.typeParameters = typeParameters;
this.unsubstitutedValueParameters = unsubstitutedValueParameters;
this.unsubstitutedReturnType = unsubstitutedReturnType;
@@ -1,6 +1,7 @@
package org.jetbrains.jet.lang.types;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.resolve.ResolveUtil;
import java.util.*;
@@ -44,6 +45,7 @@ public class FunctionDescriptorUtil {
for (ValueParameterDescriptor unsubstitutedValueParameter : functionDescriptor.getUnsubstitutedValueParameters()) {
// TODO : Lazy?
result.add(new ValueParameterDescriptorImpl(
ResolveUtil.getJetParameter(unsubstitutedValueParameter),
unsubstitutedValueParameter.getAttributes(),
unsubstitutedValueParameter.getName(),
TypeSubstitutor.INSTANCE.substitute(context, unsubstitutedValueParameter.getType(), Variance.IN_VARIANCE),
@@ -76,6 +78,7 @@ public class FunctionDescriptorUtil {
@NotNull
public static FunctionDescriptor substituteFunctionDescriptor(@NotNull List<Type> typeArguments, @NotNull FunctionDescriptor functionDescriptor) {
return new FunctionDescriptorImpl(
ResolveUtil.getJetFunction(functionDescriptor),
// TODO : substitute
functionDescriptor.getAttributes(),
functionDescriptor.getName(),
@@ -24,7 +24,13 @@ import java.util.*;
*/
public class JetStandardClasses {
private JetStandardClasses() {
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
private static ClassDescriptor NOTHING_CLASS = new ClassDescriptorImpl(
null,
Collections.<Attribute>emptyList(),
true,
"Nothing",
@@ -46,8 +52,8 @@ public class JetStandardClasses {
}
}, JetScope.EMPTY
);
private static final Type NOTHING_TYPE = new TypeImpl(getNothing());
private static final Type NULLABLE_NOTHING_TYPE = new TypeImpl(
Collections.<Attribute>emptyList(),
getNothing().getTypeConstructor(),
@@ -58,6 +64,7 @@ public class JetStandardClasses {
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
private static final ClassDescriptor ANY = new ClassDescriptorImpl(
null,
Collections.<Attribute>emptyList(),
false,
"Any",
@@ -65,8 +72,8 @@ public class JetStandardClasses {
Collections.<Type>emptySet(),
JetScope.EMPTY
);
private static final Type ANY_TYPE = new TypeImpl(ANY.getTypeConstructor(), JetScope.EMPTY);
private static final Type NULLABLE_ANY_TYPE = TypeUtils.makeNullable(ANY_TYPE);
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
@@ -77,16 +84,19 @@ public class JetStandardClasses {
public static final int TUPLE_COUNT = 22;
private static final ClassDescriptor[] TUPLE = new ClassDescriptor[TUPLE_COUNT];
static {
for (int i = 0; i < TUPLE_COUNT; i++) {
List<TypeParameterDescriptor> parameters = new ArrayList<TypeParameterDescriptor>();
for (int j = 0; j < i; j++) {
parameters.add(new TypeParameterDescriptor(
null,
Collections.<Attribute>emptyList(),
Variance.OUT_VARIANCE, "T" + j,
Collections.singleton(getNullableAnyType())));
}
TUPLE[i] = new ClassDescriptorImpl(
null,
Collections.<Attribute>emptyList(),
true,
"Tuple" + i,
@@ -99,6 +109,7 @@ public class JetStandardClasses {
public static final int FUNCTION_COUNT = 22;
private static final ClassDescriptor[] FUNCTION = new ClassDescriptor[FUNCTION_COUNT];
private static final ClassDescriptor[] RECEIVER_FUNCTION = new ClassDescriptor[FUNCTION_COUNT];
static {
@@ -106,25 +117,30 @@ public class JetStandardClasses {
List<TypeParameterDescriptor> parameters = new ArrayList<TypeParameterDescriptor>();
for (int j = 0; j < i; j++) {
parameters.add(new TypeParameterDescriptor(
null,
Collections.<Attribute>emptyList(),
Variance.IN_VARIANCE, "P" + j,
Collections.singleton(getNullableAnyType())));
}
parameters.add(new TypeParameterDescriptor(
null,
Collections.<Attribute>emptyList(),
Variance.OUT_VARIANCE, "R",
Collections.singleton(getNullableAnyType())));
FUNCTION[i] = new ClassDescriptorImpl(
null,
Collections.<Attribute>emptyList(),
false,
"Function" + i,
parameters,
Collections.singleton(getAnyType()), STUB);
parameters.add(0, new TypeParameterDescriptor(
null,
Collections.<Attribute>emptyList(),
Variance.IN_VARIANCE, "T",
Collections.singleton(getNullableAnyType())));
RECEIVER_FUNCTION[i] = new ClassDescriptorImpl(
null,
Collections.<Attribute>emptyList(),
false,
"ReceiverFunction" + i,
@@ -136,6 +152,7 @@ public class JetStandardClasses {
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
private static final JetScope PREDEFINED_SCOPE;
static {
WritableScope writableScope = new WritableScope(JetScope.EMPTY);
PREDEFINED_SCOPE = writableScope;
@@ -156,6 +173,7 @@ public class JetStandardClasses {
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
private static final JetScope LIBRARY_SCOPE;
static {
// TODO : review
Project project = ProjectManager.getInstance().getDefaultProject();
@@ -172,7 +190,6 @@ public class JetStandardClasses {
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
@NotNull
private static final ClassDescriptor BYTE = LIBRARY_SCOPE.getClass("Byte");
@NotNull
@@ -189,9 +206,9 @@ public class JetStandardClasses {
private static final ClassDescriptor DOUBLE = LIBRARY_SCOPE.getClass("Double");
@NotNull
private static final ClassDescriptor BOOLEAN = LIBRARY_SCOPE.getClass("Boolean");
@NotNull
private static final ClassDescriptor STRING = LIBRARY_SCOPE.getClass("String");
private static final Type BYTE_TYPE = new TypeImpl(getByte());
private static final Type CHAR_TYPE = new TypeImpl(getChar());
private static final Type SHORT_TYPE = new TypeImpl(getShort());
@@ -201,12 +218,14 @@ public class JetStandardClasses {
private static final Type DOUBLE_TYPE = new TypeImpl(getDouble());
private static final Type BOOLEAN_TYPE = new TypeImpl(getBoolean());
private static final Type STRING_TYPE = new TypeImpl(getString());
private static final Type UNIT_TYPE = new TypeImpl(getTuple(0));
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
@NotNull
public static final JetScope STANDARD_CLASSES;
static {
WritableScope writableScope = new WritableScope(LIBRARY_SCOPE);
STANDARD_CLASSES = writableScope;
@@ -236,6 +255,8 @@ public class JetStandardClasses {
}
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
@NotNull
public static ClassDescriptor getAny() {
return ANY;
@@ -76,22 +76,12 @@ public class JetTypeChecker {
if (returnTypeRef != null) {
returnType = TypeResolver.INSTANCE.resolveType(scope, returnTypeRef);
} else {
returnType = getBlockReturnedType(new JetScopeAdapter(scope) {
@NotNull
@Override
public Type getThisType() {
return receiverType;
}
@Override
public PropertyDescriptor getProperty(String name) {
PropertyDescriptor propertyDescriptor = parameterDescriptors.get(name);
if (propertyDescriptor == null) {
return super.getProperty(name);
}
return propertyDescriptor;
}
}, body);
WritableScope writableScope = new WritableScope(scope);
for (PropertyDescriptor propertyDescriptor : parameterDescriptors.values()) {
writableScope.addPropertyDescriptor(propertyDescriptor);
}
writableScope.setThisType(receiverType);
returnType = getBlockReturnedType(writableScope, body);
}
result[0] = JetStandardClasses.getFunctionType(null, receiverTypeRef == null ? null : receiverType, parameterTypes, returnType);
}
@@ -1,7 +1,7 @@
package org.jetbrains.jet.lang.types;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.types.*;
import org.jetbrains.jet.lang.resolve.ResolveUtil;
import java.util.ArrayList;
import java.util.List;
@@ -26,6 +26,7 @@ public class LazySubstitutingFunctionDescriptor implements FunctionDescriptor {
for (TypeParameterDescriptor parameterDescriptor : functionDescriptor.getTypeParameters()) {
// TODO : lazy?
result.add(new TypeParameterDescriptor(
ResolveUtil.getJetTypeParameter(parameterDescriptor),
parameterDescriptor.getAttributes(),
parameterDescriptor.getVariance(),
parameterDescriptor.getName(),
@@ -40,6 +41,7 @@ public class LazySubstitutingFunctionDescriptor implements FunctionDescriptor {
List<ValueParameterDescriptor> result = new ArrayList<ValueParameterDescriptor>();
for (ValueParameterDescriptor parameterDescriptor : functionDescriptor.getUnsubstitutedValueParameters()) {
result.add(new ValueParameterDescriptorImpl(
ResolveUtil.getJetParameter(parameterDescriptor),
parameterDescriptor.getAttributes(),
parameterDescriptor.getName(),
TypeSubstitutor.INSTANCE.substitute(substitutionContext, parameterDescriptor.getType(), Variance.IN_VARIANCE),
@@ -1,12 +0,0 @@
package org.jetbrains.jet.lang.types;
import java.util.List;
/**
* @author abreslav
*/
public abstract class MemberDescriptorImpl extends NamedAnnotatedImpl {
public MemberDescriptorImpl(List<Attribute> attributes, String name) {
super(attributes, name);
}
}
@@ -1,21 +0,0 @@
package org.jetbrains.jet.lang.types;
import java.util.List;
/**
* @author abreslav
*/
public abstract class NamedAnnotatedImpl extends AnnotatedImpl implements Named {
private final String name;
public NamedAnnotatedImpl(List<Attribute> attributes, String name) {
super(attributes);
this.name = name;
}
@Override
public String getName() {
return name;
}
}
@@ -1,15 +1,18 @@
package org.jetbrains.jet.lang.types;
import org.jetbrains.jet.lang.psi.JetDeclaration;
import org.jetbrains.jet.lang.psi.JetProperty;
import java.util.List;
/**
* @author abreslav
*/
public class PropertyDescriptorImpl extends MemberDescriptorImpl implements PropertyDescriptor {
public class PropertyDescriptorImpl extends DeclarationDescriptorImpl<JetDeclaration> implements PropertyDescriptor {
private Type type;
public PropertyDescriptorImpl(List<Attribute> attributes, String name, Type type) {
super(attributes, name);
public PropertyDescriptorImpl(JetDeclaration psiElement, List<Attribute> attributes, String name, Type type) {
super(psiElement, attributes, name);
this.type = type;
}
@@ -1,5 +1,7 @@
package org.jetbrains.jet.lang.types;
import org.jetbrains.jet.lang.psi.JetTypeParameter;
import java.util.Collections;
import java.util.List;
import java.util.Set;
@@ -7,13 +9,13 @@ import java.util.Set;
/**
* @author abreslav
*/
public class TypeParameterDescriptor extends NamedAnnotatedImpl {
public class TypeParameterDescriptor extends DeclarationDescriptorImpl<JetTypeParameter> {
private final Variance variance;
private final Set<Type> upperBounds;
private final TypeConstructor typeConstructor;
public TypeParameterDescriptor(List<Attribute> attributes, Variance variance, String name, Set<Type> upperBounds) {
super(attributes, name);
public TypeParameterDescriptor(JetTypeParameter psiElement, List<Attribute> attributes, Variance variance, String name, Set<Type> upperBounds) {
super(psiElement, attributes, name);
this.variance = variance;
this.upperBounds = upperBounds;
// TODO: Should we actually pass the attributes on to the type constructor?
@@ -26,7 +28,7 @@ public class TypeParameterDescriptor extends NamedAnnotatedImpl {
}
public TypeParameterDescriptor(List<Attribute> attributes, Variance variance, String name) {
this(attributes, variance, name, Collections.singleton(JetStandardClasses.getNullableAnyType()));
this(null, attributes, variance, name, Collections.singleton(JetStandardClasses.getNullableAnyType()));
}
public Variance getVariance() {
@@ -1,5 +1,7 @@
package org.jetbrains.jet.lang.types;
import org.jetbrains.jet.lang.psi.JetParameter;
import java.util.List;
/**
@@ -9,8 +11,8 @@ public class ValueParameterDescriptorImpl extends PropertyDescriptorImpl impleme
private final boolean hasDefaultValue;
private final boolean isVararg;
public ValueParameterDescriptorImpl(List<Attribute> attributes, String name, Type type, boolean hasDefaultValue, boolean isVararg) {
super(attributes, name, type);
public ValueParameterDescriptorImpl(JetParameter psiElement, List<Attribute> attributes, String name, Type type, boolean hasDefaultValue, boolean isVararg) {
super(psiElement, attributes, name, type);
this.hasDefaultValue = hasDefaultValue;
this.isVararg = isVararg;
}
+14
View File
@@ -0,0 +1,14 @@
class A {
class B {
}
fun foo() : Int = 1
fun foo1() : B = new B()
}
class C : A {
class B : C {
}
}
@@ -0,0 +1,71 @@
package org.jetbrains.jet.resolve;
import com.intellij.codeInsight.daemon.LightDaemonAnalyzerTestCase;
import com.intellij.openapi.application.PathManager;
import com.intellij.openapi.util.io.FileUtil;
import org.jetbrains.jet.lang.psi.JetChangeUtil;
import org.jetbrains.jet.lang.psi.JetClass;
import org.jetbrains.jet.lang.psi.JetDeclaration;
import org.jetbrains.jet.lang.psi.JetFile;
import org.jetbrains.jet.lang.resolve.*;
import org.jetbrains.jet.lang.types.*;
import org.jetbrains.jet.parsing.JetParsingTest;
import java.io.File;
import java.io.FileReader;
import java.util.Collections;
import java.util.List;
/**
* @author abreslav
*/
public class JetResolveTest extends LightDaemonAnalyzerTestCase {
@Override
protected String getTestDataPath() {
return getHomeDirectory() + "/idea/testData";
}
private static String getHomeDirectory() {
return new File(PathManager.getResourceRoot(JetParsingTest.class, "/org/jetbrains/jet/parsing/JetParsingTest.class")).getParentFile().getParentFile().getParent();
}
public void testBasic() throws Exception {
JetFile jetFile = JetChangeUtil.createFile(getProject(), FileUtil.loadTextAndClose(new FileReader(getTestDataPath() + "/resolve/Basic.jet")));
List<JetDeclaration> declarations = jetFile.getRootNamespace().getDeclarations();
BindingContext bindingContext = new TopDownAnalyzer().process(JetStandardClasses.STANDARD_CLASSES, declarations);
JetDeclaration declaration = declarations.get(0);
ClassDescriptor classA = bindingContext.getClassDescriptor((JetClass) declaration);
assertNotNull(classA);
JetScope membersOfA = classA.getMemberScope(Collections.<TypeProjection>emptyList());
ClassDescriptor classB = membersOfA.getClass("B");
assertNotNull(classB);
FunctionGroup foo = membersOfA.getFunctionGroup("foo");
assertFalse(foo.isEmpty());
OverloadDomain overloadsForFoo = OverloadResolver.INSTANCE.getOverloadDomain(null, membersOfA, "foo");
Type fooType = overloadsForFoo.getReturnTypeForPositionedArguments(Collections.<Type>emptyList(), Collections.<Type>emptyList());
assertEquals(JetStandardClasses.getIntType(), fooType);
OverloadDomain overloadsForFoo1 = OverloadResolver.INSTANCE.getOverloadDomain(null, membersOfA, "foo1");
Type foo1Type = overloadsForFoo1.getReturnTypeForPositionedArguments(Collections.<Type>emptyList(), Collections.<Type>emptyList());
assertEquals(new TypeImpl(classB), foo1Type);
JetClass classCDecl = (JetClass) declarations.get(1);
ClassDescriptor classC = bindingContext.getClassDescriptor(classCDecl);
assertNotNull(classC);
assertEquals(1, classC.getTypeConstructor().getSupertypes().size());
assertEquals(classA.getTypeConstructor(), classC.getTypeConstructor().getSupertypes().iterator().next().getConstructor());
JetScope cScope = classC.getMemberScope(Collections.<TypeProjection>emptyList());
ClassDescriptor classC_B = cScope.getClass("B");
assertNotNull(classC_B);
assertNotSame(classC_B, classB);
assertEquals(classC.getTypeConstructor(), classC_B.getTypeConstructor().getSupertypes().iterator().next().getConstructor());
}
}
@@ -360,6 +360,19 @@ public class JetTypeCheckerTest extends LightDaemonAnalyzerTestCase {
assertType("'1'.plus(1)", "Int");
assertType("'1'.plus('1')", "Char");
// assertType("(1:Short).plus(1d)", "Double");
// assertType("(1:Short).plus(1f)", "Float");
// assertType("(1:Short).plus(1L)", "Long");
// assertType("(1:Short).plus(1)", "Int");
// assertType("(1:Short).plus(1:Short)", "Short");
//
// assertType("(1:Byte).plus(1d)", "Double");
// assertType("(1:Byte).plus(1f)", "Float");
// assertType("(1:Byte).plus(1L)", "Long");
// assertType("(1:Byte).plus(1)", "Int");
// assertType("(1:Byte).plus(1:Short)", "Short");
// assertType("(1:Byte).plus(1:Byte)", "Byte");
assertType("\"1\".plus(1d)", "String");
assertType("\"1\".plus(1f)", "String");
assertType("\"1\".plus(1L)", "String");