Initial stub version of resolve for types
This commit is contained in:
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user