TopDown analysis for method bodies
This commit is contained in:
@@ -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);
|
||||
}
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user