diff --git a/idea/src/org/jetbrains/jet/lang/modules/JetModule.java b/idea/src/org/jetbrains/jet/lang/modules/JetModule.java new file mode 100644 index 00000000000..efcbb7c1d69 --- /dev/null +++ b/idea/src/org/jetbrains/jet/lang/modules/JetModule.java @@ -0,0 +1,10 @@ +package org.jetbrains.jet.lang.modules; + +import java.util.Collection; + +/** + * @author abreslav + */ +public interface JetModule extends NamespaceDomain { + Collection getImports(); +} diff --git a/idea/src/org/jetbrains/jet/lang/modules/MemberDomain.java b/idea/src/org/jetbrains/jet/lang/modules/MemberDomain.java new file mode 100644 index 00000000000..c6172cb7be4 --- /dev/null +++ b/idea/src/org/jetbrains/jet/lang/modules/MemberDomain.java @@ -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); +} diff --git a/idea/src/org/jetbrains/jet/lang/modules/NamespaceDomain.java b/idea/src/org/jetbrains/jet/lang/modules/NamespaceDomain.java new file mode 100644 index 00000000000..6a5934d620c --- /dev/null +++ b/idea/src/org/jetbrains/jet/lang/modules/NamespaceDomain.java @@ -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); +} diff --git a/idea/src/org/jetbrains/jet/lang/psi/JetReferenceExpression.java b/idea/src/org/jetbrains/jet/lang/psi/JetReferenceExpression.java index 00d1f2144b5..6cad14902e3 100644 --- a/idea/src/org/jetbrains/jet/lang/psi/JetReferenceExpression.java +++ b/idea/src/org/jetbrains/jet/lang/psi/JetReferenceExpression.java @@ -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); diff --git a/idea/src/org/jetbrains/jet/lang/psi/JetUserType.java b/idea/src/org/jetbrains/jet/lang/psi/JetUserType.java index a001cf39521..dac53a8f6c8 100644 --- a/idea/src/org/jetbrains/jet/lang/psi/JetUserType.java +++ b/idea/src/org/jetbrains/jet/lang/psi/JetUserType.java @@ -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 getTypeArguments() { - JetTypeArgumentList list = getTypeArgumentList(); - return list != null ? list.getArguments() : Collections.emptyList(); + public JetReferenceExpression getReferenceExpression() { + return (JetReferenceExpression) findChildByType(JetNodeTypes.REFERENCE_EXPRESSION); } } diff --git a/idea/src/org/jetbrains/jet/lang/resolve/JetModuleUtil.java b/idea/src/org/jetbrains/jet/lang/resolve/JetModuleUtil.java new file mode 100644 index 00000000000..412527a64d7 --- /dev/null +++ b/idea/src/org/jetbrains/jet/lang/resolve/JetModuleUtil.java @@ -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; + } +} diff --git a/idea/src/org/jetbrains/jet/lang/resolve/JetScope.java b/idea/src/org/jetbrains/jet/lang/resolve/JetScope.java new file mode 100644 index 00000000000..a6ecc924ca8 --- /dev/null +++ b/idea/src/org/jetbrains/jet/lang/resolve/JetScope.java @@ -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; + } + }; + +} diff --git a/idea/src/org/jetbrains/jet/lang/resolve/TypeResolver.java b/idea/src/org/jetbrains/jet/lang/resolve/TypeResolver.java new file mode 100644 index 00000000000..2d7222860be --- /dev/null +++ b/idea/src/org/jetbrains/jet/lang/resolve/TypeResolver.java @@ -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()); + } + +} diff --git a/idea/src/org/jetbrains/jet/lang/types/ClassDescriptor.java b/idea/src/org/jetbrains/jet/lang/types/ClassDescriptor.java index 8d51a62cbbc..73cf00cca8a 100644 --- a/idea/src/org/jetbrains/jet/lang/types/ClassDescriptor.java +++ b/idea/src/org/jetbrains/jet/lang/types/ClassDescriptor.java @@ -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 + } } diff --git a/idea/src/org/jetbrains/jet/lang/types/ExtensionDescriptor.java b/idea/src/org/jetbrains/jet/lang/types/ExtensionDescriptor.java new file mode 100644 index 00000000000..547fc89513b --- /dev/null +++ b/idea/src/org/jetbrains/jet/lang/types/ExtensionDescriptor.java @@ -0,0 +1,7 @@ +package org.jetbrains.jet.lang.types; + +/** + * @author abreslav + */ +public class ExtensionDescriptor { +} diff --git a/idea/src/org/jetbrains/jet/lang/types/JetTypeChecker.java b/idea/src/org/jetbrains/jet/lang/types/JetTypeChecker.java index 42f49248e8e..9c3832e6c47 100644 --- a/idea/src/org/jetbrains/jet/lang/types/JetTypeChecker.java +++ b/idea/src/org/jetbrains/jet/lang/types/JetTypeChecker.java @@ -64,7 +64,7 @@ public class JetTypeChecker { } public boolean isSubtypeOf(Type subtype, Type supertype) { - +// subtype.getConstructor().getSupertypes() return false; } } diff --git a/idea/src/org/jetbrains/jet/lang/types/MethodDescriptor.java b/idea/src/org/jetbrains/jet/lang/types/MethodDescriptor.java new file mode 100644 index 00000000000..6dd635bdae1 --- /dev/null +++ b/idea/src/org/jetbrains/jet/lang/types/MethodDescriptor.java @@ -0,0 +1,7 @@ +package org.jetbrains.jet.lang.types; + +/** + * @author abreslav + */ +public class MethodDescriptor { +} diff --git a/idea/src/org/jetbrains/jet/lang/types/NamespaceDescriptor.java b/idea/src/org/jetbrains/jet/lang/types/NamespaceDescriptor.java index 153f1426ef0..f625adc153b 100644 --- a/idea/src/org/jetbrains/jet/lang/types/NamespaceDescriptor.java +++ b/idea/src/org/jetbrains/jet/lang/types/NamespaceDescriptor.java @@ -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 + } } diff --git a/idea/src/org/jetbrains/jet/lang/types/PropertyDescriptor.java b/idea/src/org/jetbrains/jet/lang/types/PropertyDescriptor.java new file mode 100644 index 00000000000..de10e3328bf --- /dev/null +++ b/idea/src/org/jetbrains/jet/lang/types/PropertyDescriptor.java @@ -0,0 +1,7 @@ +package org.jetbrains.jet.lang.types; + +/** + * @author abreslav + */ +public class PropertyDescriptor { +} diff --git a/idea/tests/org/jetbrains/jet/types/JetTypeCheckerTest.java b/idea/tests/org/jetbrains/jet/types/JetTypeCheckerTest.java index f8e9c9977b0..c7cb1de5b47 100644 --- a/idea/tests/org/jetbrains/jet/types/JetTypeCheckerTest.java +++ b/idea/tests/org/jetbrains/jet/types/JetTypeCheckerTest.java @@ -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 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);