TopDown analysis for method bodies

This commit is contained in:
Andrey Breslav
2011-02-28 14:34:03 +03:00
parent 248ed385d5
commit 4e0b6deda5
10 changed files with 98 additions and 37 deletions
@@ -18,7 +18,12 @@ public class OverloadResolver {
private OverloadResolver() {}
@NotNull
public OverloadDomain getOverloadDomain(@Nullable Type receiverType, @NotNull JetScope outerScope, @NotNull String name) {
public OverloadDomain getOverloadDomain(Type receiverType, @NotNull JetScope outerScope, @NotNull String name) {
return getOverloadDomain(TypeCheckerTrace.DUMMY, receiverType, outerScope, name);
}
@NotNull
public OverloadDomain getOverloadDomain(@NotNull TypeCheckerTrace trace, @Nullable Type receiverType, @NotNull JetScope outerScope, @NotNull String name) {
// TODO : extension lookup
JetScope scope = receiverType == null ? outerScope : receiverType.getMemberScope();
@@ -30,7 +35,7 @@ public class OverloadResolver {
return new OverloadDomain() {
@Override
public Type getReturnTypeForPositionedArguments(@NotNull List<Type> typeArguments, @NotNull List<Type> positionedValueArgumentTypes) {
public Type getReturnTypeForPositionedArguments(@NotNull final List<Type> typeArguments, @NotNull List<Type> positionedValueArgumentTypes) {
Collection<FunctionDescriptor> possiblyApplicableFunctions = functionGroup.getPossiblyApplicableFunctions(typeArguments, positionedValueArgumentTypes);
if (possiblyApplicableFunctions.isEmpty()) {
return null;
@@ -5,10 +5,7 @@ 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;
import org.jetbrains.jet.lang.types.*;
/**
* @author abreslav
@@ -16,16 +13,16 @@ import org.jetbrains.jet.lang.types.ValueParameterDescriptor;
public class ResolveUtil {
@Nullable
private static <T extends JetElement> T getDeclarationElement(Object o) {
if (o instanceof DeclarationDescriptor) {
if (o instanceof DeclarationDescriptorImpl) {
@SuppressWarnings({"unchecked", "UnnecessaryLocalVariable"})
T psiElement = ((DeclarationDescriptor<T>) o).getPsiElement();
T psiElement = ((DeclarationDescriptorImpl<T>) o).getPsiElement();
return psiElement;
}
return null;
}
@Nullable
private static <T extends JetElement> T getDeclarationElement(DeclarationDescriptor<T> descriptor) {
private static <T extends JetElement> T getDeclarationElement(DeclarationDescriptorImpl<T> descriptor) {
return descriptor.getPsiElement();
}
@@ -36,7 +33,7 @@ public class ResolveUtil {
@Nullable
public static JetParameter getJetParameter(ValueParameterDescriptor parameterDescriptor) {
return getDeclarationElement(parameterDescriptor);
return (JetParameter) getDeclarationElement(parameterDescriptor);
}
@Nullable
@@ -15,13 +15,15 @@ public class TopDownAnalyzer {
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>();
private Map<JetExpression, Type> expressionTypes = new HashMap<JetExpression, Type>();
private Map<JetReferenceExpression,DeclarationDescriptor> resolutionResults = new HashMap<JetReferenceExpression, DeclarationDescriptor>();
public BindingContext process(@NotNull JetScope outerScope, @NotNull List<JetDeclaration> declarations) {
WritableScope toplevelScope = new WritableScope(outerScope);
collectTypeDeclarators(toplevelScope, declarations);
resolveTypeDeclarations();
collectBehaviorDeclarators(toplevelScope, declarations);
resolveBehaviorDeclarations();
resolveBehaviorDeclarationBodies();
return new BindingContext() {
@Override
@@ -36,7 +38,7 @@ public class TopDownAnalyzer {
@Override
public FunctionDescriptor getFunctionDescriptor(JetFunction declaration) {
throw new UnsupportedOperationException(); // TODO
return functions.get(declaration);
}
@Override
@@ -46,12 +48,12 @@ public class TopDownAnalyzer {
@Override
public Type getExpressionType(JetExpression expression) {
throw new UnsupportedOperationException(); // TODO
return expressionTypes.get(expression);
}
@Override
public DeclarationDescriptor resolve(JetReferenceExpression referenceExpression) {
throw new UnsupportedOperationException(); // TODO
return resolutionResults.get(referenceExpression);
}
};
}
@@ -166,7 +168,7 @@ public class TopDownAnalyzer {
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
private void resolveBehaviorDeclarations() {
private void resolveBehaviorDeclarationBodies() {
for (Map.Entry<JetFunction, FunctionDescriptor> entry : functions.entrySet()) {
JetFunction function = entry.getKey();
FunctionDescriptor descriptor = entry.getValue();
@@ -174,8 +176,30 @@ public class TopDownAnalyzer {
WritableScope declaringScope = declaringScopes.get(function);
assert declaringScope != null;
WritableScope parameterScope = new WritableScope(declaringScope);
for (TypeParameterDescriptor typeParameter : descriptor.getTypeParameters()) {
parameterScope.addTypeParameterDescriptor(typeParameter);
}
for (ValueParameterDescriptor valueParameterDescriptor : descriptor.getUnsubstitutedValueParameters()) {
parameterScope.addPropertyDescriptor(valueParameterDescriptor);
}
resolveExpression(parameterScope, function.getBodyExpression(), true);
}
}
private void resolveExpression(@NotNull JetScope scope, JetExpression expression, boolean preferBlock) {
new JetTypeChecker(new TypeCheckerTrace() {
@Override
public void recordExpressionType(JetExpression expression, Type type) {
expressionTypes.put(expression, type);
}
@Override
public void recordResolutionResult(JetReferenceExpression expression, DeclarationDescriptor descriptor) {
resolutionResults.put(expression, descriptor);
}
}).getType(scope, expression, preferBlock);
}
}
@@ -1,10 +1,7 @@
package org.jetbrains.jet.lang.types;
import org.jetbrains.jet.lang.psi.JetElement;
/**
* @author abreslav
*/
public interface DeclarationDescriptor<T extends JetElement> {
T getPsiElement();
public interface DeclarationDescriptor extends Annotated, Named {
}
@@ -7,7 +7,7 @@ import java.util.List;
/**
* @author abreslav
*/
public abstract class DeclarationDescriptorImpl<T extends JetElement> extends AnnotatedImpl implements Named, DeclarationDescriptor<T> {
public abstract class DeclarationDescriptorImpl<T extends JetElement> extends AnnotatedImpl implements Named, DeclarationDescriptor {
private final String name;
private final T psiElement;
@@ -23,7 +23,6 @@ public abstract class DeclarationDescriptorImpl<T extends JetElement> extends An
return name;
}
@Override
public T getPsiElement() {
return psiElement;
}
@@ -14,22 +14,28 @@ import java.util.*;
* @author abreslav
*/
public class JetTypeChecker {
public static final JetTypeChecker INSTANCE = new JetTypeChecker();
public static final JetTypeChecker INSTANCE = new JetTypeChecker(TypeCheckerTrace.DUMMY);
private final TypeCheckerTrace trace;
public JetTypeChecker(TypeCheckerTrace trace) {
this.trace = trace;
}
/*
: "new" constructorInvocation
: "new" constructorInvocation
: objectLiteral
: objectLiteral
: SimpleName
: SimpleName
: "typeof" "(" expression ")"
: "typeof" "(" expression ")"
: functionLiteral
: functionLiteral
: declaration
: "namespace" // for the root namespace
*/
: declaration
: "namespace" // for the root namespace
*/
public Type getType(@NotNull final JetScope scope, @NotNull JetExpression expression, final boolean preferBlock) {
final Type[] result = new Type[1];
expression.accept(new JetVisitor() {
@@ -38,6 +44,7 @@ public class JetTypeChecker {
// TODO : other members
// TODO : type substitutions???
PropertyDescriptor property = scope.getProperty(expression.getReferencedName());
trace.recordResolutionResult(expression, property);
if (property != null) {
result[0] = property.getType();
}
@@ -321,6 +328,7 @@ public class JetTypeChecker {
throw new IllegalArgumentException("Unsupported element: " + elem);
}
});
trace.recordExpressionType(expression, result[0]);
return result[0];
}
@@ -1,8 +1,10 @@
package org.jetbrains.jet.lang.types;
import org.jetbrains.jet.lang.psi.JetDeclaration;
/**
* @author abreslav
*/
public interface PropertyDescriptor extends Annotated, Named {
public interface PropertyDescriptor extends DeclarationDescriptor {
Type getType();
}
@@ -0,0 +1,24 @@
package org.jetbrains.jet.lang.types;
import org.jetbrains.jet.lang.psi.JetExpression;
import org.jetbrains.jet.lang.psi.JetReferenceExpression;
/**
* @author abreslav
*/
public interface TypeCheckerTrace {
TypeCheckerTrace DUMMY = new TypeCheckerTrace() {
@Override
public void recordExpressionType(JetExpression expression, Type type) {
}
@Override
public void recordResolutionResult(JetReferenceExpression expression, DeclarationDescriptor descriptor) {
}
};
void recordExpressionType(JetExpression expression, Type type);
void recordResolutionResult(JetReferenceExpression expression, DeclarationDescriptor descriptor);
}
+1
View File
@@ -3,6 +3,7 @@ class A {
}
fun foo(a : Int) = a
fun foo() : Int = 1
fun foo1() : B = new B()
}
@@ -3,10 +3,7 @@ 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.psi.*;
import org.jetbrains.jet.lang.resolve.*;
import org.jetbrains.jet.lang.types.*;
import org.jetbrains.jet.parsing.JetParsingTest;
@@ -35,8 +32,8 @@ public class JetResolveTest extends LightDaemonAnalyzerTestCase {
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);
JetClass classADecl = (JetClass) declarations.get(0);
ClassDescriptor classA = bindingContext.getClassDescriptor(classADecl);
assertNotNull(classA);
JetScope membersOfA = classA.getMemberScope(Collections.<TypeProjection>emptyList());
@@ -54,6 +51,13 @@ public class JetResolveTest extends LightDaemonAnalyzerTestCase {
Type foo1Type = overloadsForFoo1.getReturnTypeForPositionedArguments(Collections.<Type>emptyList(), Collections.<Type>emptyList());
assertEquals(new TypeImpl(classB), foo1Type);
JetFunction fooDecl = (JetFunction) classADecl.getDeclarations().get(1);
Type expressionType = bindingContext.getExpressionType(fooDecl.getBodyExpression());
assertEquals(JetStandardClasses.getIntType(), expressionType);
DeclarationDescriptor resolve = bindingContext.resolve((JetReferenceExpression) fooDecl.getBodyExpression());
assertSame(bindingContext.getFunctionDescriptor(fooDecl).getUnsubstitutedValueParameters().get(0), resolve);
JetClass classCDecl = (JetClass) declarations.get(1);
ClassDescriptor classC = bindingContext.getClassDescriptor(classCDecl);
assertNotNull(classC);