Initial stub version of resolve for types

This commit is contained in:
Andrey Breslav
2011-01-24 22:10:25 +03:00
parent 62d6ad271a
commit 1ce2ed87b5
15 changed files with 297 additions and 45 deletions
@@ -0,0 +1,10 @@
package org.jetbrains.jet.lang.modules;
import java.util.Collection;
/**
* @author abreslav
*/
public interface JetModule extends NamespaceDomain {
Collection<JetModule> getImports();
}
@@ -0,0 +1,24 @@
package org.jetbrains.jet.lang.modules;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.types.ClassDescriptor;
import org.jetbrains.jet.lang.types.ExtensionDescriptor;
import org.jetbrains.jet.lang.types.MethodDescriptor;
import org.jetbrains.jet.lang.types.PropertyDescriptor;
/**
* @author abreslav
*/
public interface MemberDomain {
@Nullable
MethodDescriptor getMethods(String name);
@Nullable
ClassDescriptor getClass(String name);
@Nullable
PropertyDescriptor getProperty(String name);
@Nullable
ExtensionDescriptor getExtension(String name);
}
@@ -0,0 +1,12 @@
package org.jetbrains.jet.lang.modules;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.types.NamespaceDescriptor;
/**
* @author abreslav
*/
public interface NamespaceDomain {
@Nullable
NamespaceDescriptor getNamespace(String namespaceName);
}
@@ -2,6 +2,8 @@ package org.jetbrains.jet.lang.psi;
import com.intellij.lang.ASTNode;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lexer.JetTokens;
/**
* @author max
@@ -11,6 +13,19 @@ public class JetReferenceExpression extends JetExpression {
super(node);
}
public boolean isAbsoluteInRootNamespace() {
return findChildByType(JetTokens.NAMESPACE_KEYWORD) != null;
}
@Nullable
public JetReferenceExpression getQualifier() {
return findChildByClass(JetReferenceExpression.class);
}
public String getReferencedName() {
return getNode().findChildByType(JetTokens.IDENTIFIER).getText();
}
@Override
public void accept(JetVisitor visitor) {
visitor.visitReferenceExpression(this);
@@ -2,12 +2,7 @@ package org.jetbrains.jet.lang.psi;
import com.intellij.lang.ASTNode;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.JetNodeTypes;
import org.jetbrains.jet.lexer.JetTokens;
import java.util.Collections;
import java.util.List;
/**
* @author max
@@ -22,34 +17,7 @@ public class JetUserType extends JetTypeElement {
visitor.visitUserType(this);
}
public boolean isAbsoluteInRootNamespace() {
return findChildByType(JetTokens.NAMESPACE_KEYWORD) != null;
}
@Nullable
public JetUserType getQualifierType() {
return (JetUserType) findChildByType(JetNodeTypes.USER_TYPE);
}
@Nullable @IfNotParsed
public ASTNode getTypeNameNode() {
return getNode().findChildByType(JetNodeTypes.REFERENCE_EXPRESSION);
}
@Nullable @IfNotParsed
public String getReferencedName() {
ASTNode nameNode = getTypeNameNode();
return nameNode != null ? nameNode.getText() : null;
}
@Nullable
public JetTypeArgumentList getTypeArgumentList() {
return (JetTypeArgumentList) findChildByType(JetNodeTypes.TYPE_ARGUMENT_LIST);
}
@NotNull
public List<JetTypeReference> getTypeArguments() {
JetTypeArgumentList list = getTypeArgumentList();
return list != null ? list.getArguments() : Collections.<JetTypeReference>emptyList();
public JetReferenceExpression getReferenceExpression() {
return (JetReferenceExpression) findChildByType(JetNodeTypes.REFERENCE_EXPRESSION);
}
}
@@ -0,0 +1,14 @@
package org.jetbrains.jet.lang.resolve;
import org.jetbrains.jet.lang.psi.JetElement;
import org.jetbrains.jet.lang.psi.JetReferenceExpression;
/**
* @author abreslav
*/
public class JetModuleUtil {
public static JetScope getRootNamespaceScope(JetElement expression) {
// TODO: this is a stub: at least the modules' root namespaces must be indexed here
return JetScope.EMPTY;
}
}
@@ -0,0 +1,40 @@
package org.jetbrains.jet.lang.resolve;
import org.jetbrains.jet.lang.modules.MemberDomain;
import org.jetbrains.jet.lang.modules.NamespaceDomain;
import org.jetbrains.jet.lang.types.*;
/**
* @author abreslav
*/
public interface JetScope extends NamespaceDomain, MemberDomain {
JetScope EMPTY = new JetScopeImpl() {};
abstract class JetScopeImpl implements JetScope {
@Override
public MethodDescriptor getMethods(String name) {
return null;
}
@Override
public ClassDescriptor getClass(String name) {
return null;
}
@Override
public PropertyDescriptor getProperty(String name) {
return null;
}
@Override
public ExtensionDescriptor getExtension(String name) {
return null;
}
@Override
public NamespaceDescriptor getNamespace(String namespaceName) {
return null;
}
};
}
@@ -0,0 +1,70 @@
package org.jetbrains.jet.lang.resolve;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.modules.MemberDomain;
import org.jetbrains.jet.lang.psi.JetReferenceExpression;
import org.jetbrains.jet.lang.psi.JetUserType;
import org.jetbrains.jet.lang.types.ClassDescriptor;
import org.jetbrains.jet.lang.types.NamespaceDescriptor;
/**
* @author abreslav
*/
public class TypeResolver {
public static final TypeResolver INSTANCE = new TypeResolver();
private TypeResolver() {}
@Nullable
public ClassDescriptor resolveClass(JetScope scope, JetUserType userType) {
return resolveClass(scope, userType.getReferenceExpression());
}
@Nullable
private ClassDescriptor resolveClass(JetScope scope, JetReferenceExpression expression) {
if (expression.isAbsoluteInRootNamespace()) {
return resolveClass(JetModuleUtil.getRootNamespaceScope(expression), expression);
}
JetReferenceExpression qualifier = expression.getQualifier();
if (qualifier != null) {
// TODO: this is slow. The faster way would be to start with the first item in the quilified name
// TODO: priorities: class of namespace first?
MemberDomain domain = resolveClass(scope, qualifier);
if (domain == null) {
domain = resolveNamespace(scope, qualifier);
}
if (domain != null) {
return domain.getClass(expression.getReferencedName());
}
return null;
}
assert qualifier == null;
return scope.getClass(expression.getReferencedName());
}
@Nullable
private NamespaceDescriptor resolveNamespace(JetScope scope, JetReferenceExpression expression) {
if (expression.isAbsoluteInRootNamespace()) {
return resolveNamespace(JetModuleUtil.getRootNamespaceScope(expression), expression);
}
JetReferenceExpression qualifier = expression.getQualifier();
if (qualifier != null) {
NamespaceDescriptor domain = resolveNamespace(scope, qualifier);
if (domain == null) {
return null;
}
return domain.getNamespace(expression.getReferencedName());
}
assert qualifier == null;
return scope.getNamespace(expression.getReferencedName());
}
}
@@ -1,5 +1,7 @@
package org.jetbrains.jet.lang.types;
import org.jetbrains.jet.lang.modules.MemberDomain;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
@@ -7,7 +9,7 @@ import java.util.List;
/**
* @author abreslav
*/
public class ClassDescriptor extends MemberDescriptorImpl {
public class ClassDescriptor extends MemberDescriptorImpl implements MemberDomain {
private final TypeConstructor typeConstructor;
public ClassDescriptor(
@@ -26,4 +28,23 @@ public class ClassDescriptor extends MemberDescriptorImpl {
public TypeConstructor getTypeConstructor() {
return typeConstructor;
}
public ClassDescriptor getClass(String referencedName) {
throw new UnsupportedOperationException(); // TODO
}
@Override
public MethodDescriptor getMethods(String name) {
throw new UnsupportedOperationException(); // TODO
}
@Override
public PropertyDescriptor getProperty(String name) {
throw new UnsupportedOperationException(); // TODO
}
@Override
public ExtensionDescriptor getExtension(String name) {
throw new UnsupportedOperationException(); // TODO
}
}
@@ -0,0 +1,7 @@
package org.jetbrains.jet.lang.types;
/**
* @author abreslav
*/
public class ExtensionDescriptor {
}
@@ -64,7 +64,7 @@ public class JetTypeChecker {
}
public boolean isSubtypeOf(Type subtype, Type supertype) {
// subtype.getConstructor().getSupertypes()
return false;
}
}
@@ -0,0 +1,7 @@
package org.jetbrains.jet.lang.types;
/**
* @author abreslav
*/
public class MethodDescriptor {
}
@@ -1,7 +1,34 @@
package org.jetbrains.jet.lang.types;
import org.jetbrains.jet.lang.modules.MemberDomain;
import org.jetbrains.jet.lang.modules.NamespaceDomain;
/**
* @author abreslav
*/
public class NamespaceDescriptor {
public class NamespaceDescriptor implements NamespaceDomain, MemberDomain {
@Override
public ClassDescriptor getClass(String name) {
throw new UnsupportedOperationException(); // TODO
}
@Override
public MethodDescriptor getMethods(String name) {
throw new UnsupportedOperationException(); // TODO
}
@Override
public PropertyDescriptor getProperty(String name) {
throw new UnsupportedOperationException(); // TODO
}
@Override
public ExtensionDescriptor getExtension(String name) {
throw new UnsupportedOperationException(); // TODO
}
@Override
public NamespaceDescriptor getNamespace(String namespaceName) {
throw new UnsupportedOperationException(); // TODO
}
}
@@ -0,0 +1,7 @@
package org.jetbrains.jet.lang.types;
/**
* @author abreslav
*/
public class PropertyDescriptor {
}
@@ -4,9 +4,9 @@ import com.intellij.codeInsight.daemon.LightDaemonAnalyzerTestCase;
import com.intellij.openapi.application.PathManager;
import com.intellij.openapi.project.Project;
import org.jetbrains.jet.lang.psi.*;
import org.jetbrains.jet.lang.types.JetStandardTypes;
import org.jetbrains.jet.lang.types.JetTypeChecker;
import org.jetbrains.jet.lang.types.Type;
import org.jetbrains.jet.lang.resolve.JetScope;
import org.jetbrains.jet.lang.resolve.TypeResolver;
import org.jetbrains.jet.lang.types.*;
import org.jetbrains.jet.parsing.JetParsingTest;
import java.io.File;
@@ -17,6 +17,30 @@ import java.util.List;
*/
public class JetTypeCheckerTest extends LightDaemonAnalyzerTestCase {
private static final JetScope BASIC_SCOPE = new JetScope.JetScopeImpl() {
@Override
public ClassDescriptor getClass(String name) {
if ("Int".equals(name)) {
return JetStandardClasses.getInt();
} else if ("Boolean".equals(name)) {
return JetStandardClasses.getInt();
} else if ("Byte".equals(name)) {
return JetStandardClasses.getInt();
} else if ("Char".equals(name)) {
return JetStandardClasses.getInt();
} else if ("Short".equals(name)) {
return JetStandardClasses.getInt();
} else if ("Long".equals(name)) {
return JetStandardClasses.getInt();
} else if ("Float".equals(name)) {
return JetStandardClasses.getInt();
} else if ("Double".equals(name)) {
return JetStandardClasses.getInt();
}
return null;
}
};
@Override
protected String getTestDataPath() {
return getHomeDirectory() + "/idea/testData";
@@ -111,30 +135,36 @@ public class JetTypeCheckerTest extends LightDaemonAnalyzerTestCase {
JetTypeElement typeElement = typeNode.getTypeElement();
List<JetTypeReference> typeArguments = typeNode.getTypeArguments();
typeElement.accept(new JetVisitor());
final Type[] result = new Type[1];
typeElement.accept(new JetVisitor() {
@Override
public void visitUserType(JetUserType type) {
result[0] = new ClassType(TypeResolver.INSTANCE.resolveClass(BASIC_SCOPE, type));
}
});
throw new UnsupportedOperationException(); // TODO
return result[0];
}
public void testImplicitConversions() throws Exception {
assertConvertibleTo("1", JetStandardTypes.getByte());
}
private void assertConvertibleTo(String expression, Type type) {
private static void assertConvertibleTo(String expression, Type type) {
JetExpression jetExpression = JetChangeUtil.createExpression(getProject(), expression);
assertTrue(
expression + " must be convertible to " + type,
new JetTypeChecker().isConvertibleTo(jetExpression, type));
}
private void assertNotConvertibleTo(String expression, Type type) {
private static void assertNotConvertibleTo(String expression, Type type) {
JetExpression jetExpression = JetChangeUtil.createExpression(getProject(), expression);
assertFalse(
expression + " must not be convertible to " + type,
new JetTypeChecker().isConvertibleTo(jetExpression, type));
}
private void assertType(String expression, Type expectedType) {
private static void assertType(String expression, Type expectedType) {
Project project = getProject();
JetExpression jetExpression = JetChangeUtil.createExpression(project, expression);
Type type = new JetTypeChecker().getType(jetExpression);