Working on the type model
This commit is contained in:
@@ -1,10 +1,13 @@
|
||||
package org.jetbrains.jet.lang.annotations;
|
||||
|
||||
import com.intellij.lang.annotation.AnnotationHolder;
|
||||
import com.intellij.lang.annotation.AnnotationSession;
|
||||
import com.intellij.lang.annotation.Annotator;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.jet.lang.psi.JetProperty;
|
||||
import org.jetbrains.jet.lang.psi.*;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author abreslav
|
||||
@@ -13,9 +16,48 @@ public class JetPsiChecker implements Annotator {
|
||||
|
||||
@Override
|
||||
public void annotate(@NotNull PsiElement element, @NotNull AnnotationHolder holder) {
|
||||
if (element instanceof JetProperty) {
|
||||
JetProperty property = (JetProperty) element;
|
||||
holder.createErrorAnnotation(property.getNameIdentifier(), "Specify either type or value");
|
||||
if (element instanceof JetFile) {
|
||||
// JetProperty property = (JetProperty) element;
|
||||
// holder.createErrorAnnotation(property.getNameIdentifier(), "Specify either type or value");
|
||||
JetFile file = (JetFile) element;
|
||||
String path = file.getProject().getBaseDir().getPath();
|
||||
System.out.println("Path: " + path);
|
||||
JetNamespace rootNamespace = file.getRootNamespace();
|
||||
List<JetDeclaration> declarations = rootNamespace.getDeclarations();
|
||||
|
||||
for (JetDeclaration declaration : declarations) {
|
||||
declaration.accept(new JetVisitor() {
|
||||
@Override
|
||||
public void visitClass(JetClass klass) {
|
||||
print("class ");
|
||||
print(klass.getName());
|
||||
println("{");
|
||||
for (JetDeclaration decl : klass.getDeclarations()) {
|
||||
decl.accept(this);
|
||||
}
|
||||
print("}");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitProperty(JetProperty property) {
|
||||
JetTypeReference propertyTypeRef = property.getPropertyTypeRef();
|
||||
String name = property.getName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitFunction(JetFunction fun) {
|
||||
super.visitFunction(fun); //To change body of overridden methods use File | Settings | File Templates.
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void print(Object o) {
|
||||
System.out.print(o);
|
||||
}
|
||||
|
||||
private void println(Object o) {
|
||||
System.out.println(o);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,13 +13,23 @@ import java.util.List;
|
||||
* @author max
|
||||
*/
|
||||
public class JetChangeUtil {
|
||||
public static JetExpression createExpression(Project project, String text) {
|
||||
JetProperty property = createProperty(project, "val x = " + text);
|
||||
return property.getInitializer();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static JetFile createFile(Project project, String text) {
|
||||
return (JetFile) PsiFileFactory.getInstance(project).createFileFromText("dummy.jet", JetFileType.INSTANCE, text, LocalTimeCounter.currentTime(), true);
|
||||
}
|
||||
|
||||
public static JetProperty createProperty(Project project, String name, String type) {
|
||||
JetFile file = createFile(project, "val " + name + (type != null ? ":" + type : ""));
|
||||
String text = "val " + name + (type != null ? ":" + type : "");
|
||||
return createProperty(project, text);
|
||||
}
|
||||
|
||||
private static JetProperty createProperty(Project project, String text) {
|
||||
JetFile file = createFile(project, text);
|
||||
JetNamespace rootNamespace = file.getRootNamespace();
|
||||
List<JetDeclaration> dcls = rootNamespace.getDeclarations();
|
||||
assert dcls.size() == 1;
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
package org.jetbrains.jet.lang.psi;
|
||||
|
||||
import com.intellij.lang.ASTNode;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.tree.IElementType;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.jet.JetNodeTypes;
|
||||
@@ -79,4 +81,9 @@ public class JetProperty extends JetNamedDeclaration {
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public JetExpression getInitializer() {
|
||||
PsiElement eq = findChildByType(JetTokens.EQ);
|
||||
return PsiTreeUtil.getNextSiblingOfType(eq, JetExpression.class);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,7 +19,7 @@ public class JetTupleExpression extends JetExpression {
|
||||
visitor.visitTupleExpression(this);
|
||||
}
|
||||
|
||||
public List<JetExpression> getComponents() {
|
||||
public List<JetExpression> getEntries() {
|
||||
return PsiTreeUtil.getChildrenOfTypeAsList(this, JetExpression.class);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@ import com.intellij.lang.ASTNode;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.jet.JetNodeTypes;
|
||||
import org.jetbrains.jet.lang.types.Variance;
|
||||
import org.jetbrains.jet.lexer.JetTokens;
|
||||
|
||||
/**
|
||||
|
||||
@@ -19,7 +19,7 @@ public class JetVisitor extends PsiElementVisitor {
|
||||
}
|
||||
|
||||
public void visitClass(JetClass klass) {
|
||||
visitDeclaration(klass);
|
||||
visitNamedDeclaration(klass);
|
||||
}
|
||||
|
||||
public void visitClassObject(JetClassObject classObject) {
|
||||
@@ -31,19 +31,19 @@ public class JetVisitor extends PsiElementVisitor {
|
||||
}
|
||||
|
||||
public void visitExtension(JetExtension extension) {
|
||||
visitDeclaration(extension);
|
||||
visitNamedDeclaration(extension);
|
||||
}
|
||||
|
||||
public void visitFunction(JetFunction fun) {
|
||||
visitDeclaration(fun);
|
||||
visitNamedDeclaration(fun);
|
||||
}
|
||||
|
||||
public void visitProperty(JetProperty property) {
|
||||
visitDeclaration(property);
|
||||
visitNamedDeclaration(property);
|
||||
}
|
||||
|
||||
public void visitTypedef(JetTypedef typedef) {
|
||||
visitDeclaration(typedef);
|
||||
visitNamedDeclaration(typedef);
|
||||
}
|
||||
|
||||
public void visitJetFile(JetFile file) {
|
||||
@@ -79,7 +79,7 @@ public class JetVisitor extends PsiElementVisitor {
|
||||
}
|
||||
|
||||
public void visitTypeParameter(JetTypeParameter parameter) {
|
||||
visitDeclaration(parameter);
|
||||
visitNamedDeclaration(parameter);
|
||||
}
|
||||
|
||||
public void visitEnumEntry(JetEnumEntry enumEntry) {
|
||||
@@ -91,7 +91,7 @@ public class JetVisitor extends PsiElementVisitor {
|
||||
}
|
||||
|
||||
public void visitParameter(JetParameter parameter) {
|
||||
visitDeclaration(parameter);
|
||||
visitNamedDeclaration(parameter);
|
||||
}
|
||||
|
||||
public void visitDelegationSpecifierList(JetDelegationSpecifierList list) {
|
||||
@@ -317,4 +317,8 @@ public class JetVisitor extends PsiElementVisitor {
|
||||
public void visitMatchBlock(JetMatchBlock block) {
|
||||
visitJetElement(block);
|
||||
}
|
||||
|
||||
public void visitNamedDeclaration(JetNamedDeclaration declaration) {
|
||||
visitJetElement(declaration);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,10 +0,0 @@
|
||||
package org.jetbrains.jet.lang.psi;
|
||||
|
||||
/**
|
||||
* @author max
|
||||
*/
|
||||
public enum Variance {
|
||||
INVARIANT,
|
||||
IN_VARIANCE,
|
||||
OUT_VARIANCE
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
package org.jetbrains.jet.lang.types;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author abreslav
|
||||
*/
|
||||
public interface Annotated {
|
||||
List<Annotation> getAnnotations();
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
package org.jetbrains.jet.lang.types;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author abreslav
|
||||
*/
|
||||
public abstract class AnnotatedImpl implements Annotated {
|
||||
private final List<Annotation> annotations;
|
||||
|
||||
public AnnotatedImpl(List<Annotation> annotations) {
|
||||
this.annotations = annotations;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Annotation> getAnnotations() {
|
||||
return annotations;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
package org.jetbrains.jet.lang.types;
|
||||
|
||||
/**
|
||||
* @author abreslav
|
||||
*/
|
||||
public interface Annotation {
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
package org.jetbrains.jet.lang.types;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author abreslav
|
||||
*/
|
||||
public class ClassDescriptor extends MemberDescriptorImpl {
|
||||
private final TypeConstructor typeConstructor;
|
||||
|
||||
public ClassDescriptor(
|
||||
List<Annotation> annotations,
|
||||
String name, List<TypeParameterDescriptor> typeParameters, Collection<Type> superclasses) {
|
||||
super(annotations, name);
|
||||
this.typeConstructor = new TypeConstructor(annotations, name, typeParameters, superclasses);
|
||||
}
|
||||
|
||||
public ClassDescriptor(String name) {
|
||||
this(Collections.<Annotation>emptyList(),
|
||||
name, Collections.<TypeParameterDescriptor>emptyList(),
|
||||
Collections.<Type>singleton(JetStandardTypes.getAny()));
|
||||
}
|
||||
|
||||
public TypeConstructor getTypeConstructor() {
|
||||
return typeConstructor;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
package org.jetbrains.jet.lang.types;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author abreslav
|
||||
*/
|
||||
public class ClassType extends TypeImpl {
|
||||
private final ClassDescriptor classDescriptor;
|
||||
|
||||
public ClassType(List<Annotation> annotations, ClassDescriptor classDescriptor, List<TypeProjection> arguments) {
|
||||
super(annotations, classDescriptor.getTypeConstructor(), arguments);
|
||||
assert classDescriptor.getTypeConstructor().getParameters().size() == arguments.size();
|
||||
|
||||
this.classDescriptor = classDescriptor;
|
||||
}
|
||||
|
||||
public ClassType(ClassDescriptor classDescriptor) {
|
||||
this(Collections.<Annotation>emptyList(), classDescriptor, Collections.<TypeProjection>emptyList());
|
||||
assert classDescriptor.getTypeConstructor().getParameters().size() == 0;
|
||||
}
|
||||
|
||||
public ClassDescriptor getClassDescriptor() {
|
||||
return classDescriptor;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<MemberDescriptor> getMembers() {
|
||||
throw new UnsupportedOperationException(); // TODO
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
package org.jetbrains.jet.lang.types;
|
||||
|
||||
import java.util.Collections;
|
||||
|
||||
/**
|
||||
* @author abreslav
|
||||
*/
|
||||
public class JetStandardClasses {
|
||||
private static final ClassDescriptor ANY = new ClassDescriptor(
|
||||
Collections.<Annotation>emptyList(),
|
||||
"Any",
|
||||
Collections.<TypeParameterDescriptor>emptyList(),
|
||||
Collections.<Type>emptySet()
|
||||
);
|
||||
|
||||
private static final ClassDescriptor BYTE = new ClassDescriptor("Byte");
|
||||
private static final ClassDescriptor CHAR = new ClassDescriptor("Char");
|
||||
private static final ClassDescriptor SHORT = new ClassDescriptor("Short");
|
||||
private static final ClassDescriptor INT = new ClassDescriptor("Int");
|
||||
private static final ClassDescriptor LONG = new ClassDescriptor("Long");
|
||||
private static final ClassDescriptor FLOAT = new ClassDescriptor("Float");
|
||||
private static final ClassDescriptor DOUBLE = new ClassDescriptor("Double");
|
||||
private static final ClassDescriptor BOOLEAN = new ClassDescriptor("Boolean");
|
||||
private static final ClassDescriptor STRING = new ClassDescriptor("String");
|
||||
|
||||
public static ClassDescriptor getAny() {
|
||||
return ANY;
|
||||
}
|
||||
|
||||
public static ClassDescriptor getByte() {
|
||||
return BYTE;
|
||||
}
|
||||
|
||||
public static ClassDescriptor getChar() {
|
||||
return CHAR;
|
||||
}
|
||||
|
||||
public static ClassDescriptor getShort() {
|
||||
return SHORT;
|
||||
}
|
||||
|
||||
public static ClassDescriptor getInt() {
|
||||
return INT;
|
||||
}
|
||||
|
||||
public static ClassDescriptor getLong() {
|
||||
return LONG;
|
||||
}
|
||||
|
||||
public static ClassDescriptor getFloat() {
|
||||
return FLOAT;
|
||||
}
|
||||
|
||||
public static ClassDescriptor getDouble() {
|
||||
return DOUBLE;
|
||||
}
|
||||
|
||||
public static ClassDescriptor getBoolean() {
|
||||
return BOOLEAN;
|
||||
}
|
||||
|
||||
public static ClassDescriptor getString() {
|
||||
return STRING;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
package org.jetbrains.jet.lang.types;
|
||||
|
||||
import java.util.Collections;
|
||||
|
||||
/**
|
||||
* @author abreslav
|
||||
*/
|
||||
public class JetStandardTypes {
|
||||
private static final ClassType ANY_TYPE = new ClassType(JetStandardClasses.getAny());
|
||||
private static final ClassType BYTE = new ClassType(JetStandardClasses.getByte());
|
||||
private static final ClassType CHAR = new ClassType(JetStandardClasses.getChar());
|
||||
private static final ClassType SHORT = new ClassType(JetStandardClasses.getShort());
|
||||
private static final ClassType INT = new ClassType(JetStandardClasses.getInt());
|
||||
private static final ClassType LONG = new ClassType(JetStandardClasses.getLong());
|
||||
private static final ClassType FLOAT = new ClassType(JetStandardClasses.getFloat());
|
||||
private static final ClassType DOUBLE = new ClassType(JetStandardClasses.getDouble());
|
||||
private static final ClassType BOOLEAN = new ClassType(JetStandardClasses.getBoolean());
|
||||
private static final ClassType STRING = new ClassType(JetStandardClasses.getString());
|
||||
private static final TupleType UNIT = TupleType.UNIT;
|
||||
|
||||
public static ClassType getInt() {
|
||||
return INT;
|
||||
}
|
||||
|
||||
public static ClassType getLong() {
|
||||
return LONG;
|
||||
}
|
||||
|
||||
public static ClassType getDouble() {
|
||||
return DOUBLE;
|
||||
}
|
||||
|
||||
public static ClassType getFloat() {
|
||||
return FLOAT;
|
||||
}
|
||||
|
||||
public static ClassType getChar() {
|
||||
return CHAR;
|
||||
}
|
||||
|
||||
public static ClassType getBoolean() {
|
||||
return BOOLEAN;
|
||||
}
|
||||
|
||||
public static ClassType getString() {
|
||||
return STRING;
|
||||
}
|
||||
|
||||
public static ClassType getByte() {
|
||||
return BYTE;
|
||||
}
|
||||
|
||||
public static ClassType getShort() {
|
||||
return SHORT;
|
||||
}
|
||||
|
||||
public static TupleType getUnit() {
|
||||
return UNIT;
|
||||
}
|
||||
|
||||
public static Type getAny() {
|
||||
return ANY_TYPE;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
package org.jetbrains.jet.lang.types;
|
||||
|
||||
import com.intellij.psi.tree.IElementType;
|
||||
import org.jetbrains.jet.JetNodeTypes;
|
||||
import org.jetbrains.jet.lang.psi.*;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author abreslav
|
||||
*/
|
||||
public class JetTypeChecker {
|
||||
public Type getType(JetExpression expression) {
|
||||
final Type[] result = new Type[1];
|
||||
expression.accept(new JetVisitor() {
|
||||
@Override
|
||||
public void visitConstantExpression(JetConstantExpression expression) {
|
||||
IElementType elementType = expression.getNode().getElementType();
|
||||
if (elementType == JetNodeTypes.INTEGER_CONSTANT) {
|
||||
result[0] = JetStandardTypes.getInt();
|
||||
} else if (elementType == JetNodeTypes.LONG_CONSTANT) {
|
||||
result[0] = JetStandardTypes.getLong();
|
||||
} else if (elementType == JetNodeTypes.FLOAT_CONSTANT) {
|
||||
String text = expression.getText();
|
||||
assert text.length() > 0;
|
||||
char lastChar = text.charAt(text.length() - 1);
|
||||
if (lastChar == 'f' || lastChar == 'F') {
|
||||
result[0] = JetStandardTypes.getFloat();
|
||||
} else {
|
||||
result[0] = JetStandardTypes.getDouble();
|
||||
}
|
||||
} else if (elementType == JetNodeTypes.BOOLEAN_CONSTANT) {
|
||||
result[0] = JetStandardTypes.getBoolean();
|
||||
} else if (elementType == JetNodeTypes.CHARACTER_CONSTANT) {
|
||||
result[0] = JetStandardTypes.getChar();
|
||||
} else if (elementType == JetNodeTypes.STRING_CONSTANT) {
|
||||
result[0] = JetStandardTypes.getString();
|
||||
} else {
|
||||
throw new IllegalArgumentException("Unsupported constant: " + expression);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitTupleExpression(JetTupleExpression expression) {
|
||||
List<JetExpression> entries = expression.getEntries();
|
||||
List<Type> types = new ArrayList<Type>();
|
||||
for (JetExpression entry : entries) {
|
||||
types.add(getType(entry));
|
||||
}
|
||||
result[0] = TupleType.getTupleType(types);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitJetElement(JetElement elem) {
|
||||
throw new IllegalArgumentException("Unsupported element: " + elem);
|
||||
}
|
||||
});
|
||||
return result[0];
|
||||
}
|
||||
|
||||
public boolean isConvertibleTo(JetExpression expression, Type type) {
|
||||
return false; //To change body of created methods use File | Settings | File Templates.
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
package org.jetbrains.jet.lang.types;
|
||||
|
||||
/**
|
||||
* @author abreslav
|
||||
*/
|
||||
public interface MemberDescriptor {
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
package org.jetbrains.jet.lang.types;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author abreslav
|
||||
*/
|
||||
public abstract class MemberDescriptorImpl extends NamedAnnotatedImpl {
|
||||
public MemberDescriptorImpl(List<Annotation> annotations, String name) {
|
||||
super(annotations, name);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
package org.jetbrains.jet.lang.types;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author abreslav
|
||||
*/
|
||||
public abstract class NamedAnnotatedImpl extends AnnotatedImpl {
|
||||
|
||||
private final String name;
|
||||
|
||||
public NamedAnnotatedImpl(List<Annotation> annotations, String name) {
|
||||
super(annotations);
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
package org.jetbrains.jet.lang.types;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* @author abreslav
|
||||
*/
|
||||
public class NothingType extends TypeImpl {
|
||||
|
||||
public static final TypeConstructor NOTHING = new TypeConstructor(
|
||||
Collections.<Annotation>emptyList(),
|
||||
"Nothing",
|
||||
Collections.<TypeParameterDescriptor>emptyList(),
|
||||
new AbstractCollection<Type>() {
|
||||
|
||||
@Override
|
||||
public boolean contains(Object o) {
|
||||
return o instanceof Type;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterator<Type> iterator() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int size() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
});
|
||||
|
||||
// TODO: annotations seem wrong here
|
||||
public NothingType(List<Annotation> annotations) {
|
||||
super(annotations, NOTHING, Collections.<TypeProjection>emptyList());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<MemberDescriptor> getMembers() {
|
||||
return Collections.emptySet();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
package org.jetbrains.jet.lang.types;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author abreslav
|
||||
*/
|
||||
public class ParameterDescriptor extends AnnotatedImpl {
|
||||
private final Type type;
|
||||
private final String name;
|
||||
|
||||
public ParameterDescriptor(List<Annotation> annotations, Type type, String name) {
|
||||
super(annotations);
|
||||
this.type = type;
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public Type getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,82 @@
|
||||
package org.jetbrains.jet.lang.types;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author abreslav
|
||||
*/
|
||||
public class TupleType extends TypeImpl {
|
||||
|
||||
public static final int TUPLE_COUNT = 22;
|
||||
private static final TypeConstructor[] TUPLE = new TypeConstructor[TUPLE_COUNT];
|
||||
|
||||
public static final TupleType UNIT = new TupleType(Collections.<Annotation>emptyList(), Collections.<Type>emptyList());
|
||||
|
||||
static {
|
||||
for (int i = 0; i < TUPLE_COUNT; i++) {
|
||||
List<TypeParameterDescriptor> parameters = new ArrayList<TypeParameterDescriptor>();
|
||||
for (int j = 0; j < i; j++) {
|
||||
parameters.add(new TypeParameterDescriptor(
|
||||
Collections.<Annotation>emptyList(),
|
||||
"T" + j,
|
||||
Variance.OUT_VARIANCE,
|
||||
Collections.<Type>emptySet()));
|
||||
}
|
||||
TUPLE[i] = new TypeConstructor(
|
||||
Collections.<Annotation>emptyList(),
|
||||
"Tuple" + i,
|
||||
parameters,
|
||||
Collections.singleton(JetStandardTypes.getAny()));
|
||||
}
|
||||
}
|
||||
|
||||
public static TupleType getTupleType(List<Annotation> annotations, List<Type> arguments) {
|
||||
if (annotations.isEmpty() && arguments.isEmpty()) {
|
||||
return UNIT;
|
||||
}
|
||||
return new TupleType(annotations, arguments);
|
||||
}
|
||||
|
||||
|
||||
public static TupleType getTupleType(List<Type> arguments) {
|
||||
return getTupleType(Collections.<Annotation>emptyList(), arguments);
|
||||
}
|
||||
|
||||
public static TupleType getLabeledTupleType(List<Annotation> annotations, List<ParameterDescriptor> arguments) {
|
||||
return getTupleType(annotations, toTypes(arguments));
|
||||
}
|
||||
|
||||
|
||||
public static TupleType getLabeledTupleType(List<ParameterDescriptor> arguments) {
|
||||
return getLabeledTupleType(Collections.<Annotation>emptyList(), arguments);
|
||||
}
|
||||
|
||||
|
||||
private TupleType(List<Annotation> annotations, List<Type> arguments) {
|
||||
super(annotations, TUPLE[arguments.size()], toProjections(arguments));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<MemberDescriptor> getMembers() {
|
||||
throw new UnsupportedOperationException("Not implemented"); // TODO
|
||||
}
|
||||
|
||||
private static List<TypeProjection> toProjections(List<Type> arguments) {
|
||||
List<TypeProjection> result = new ArrayList<TypeProjection>();
|
||||
for (Type argument : arguments) {
|
||||
result.add(new TypeProjection(Variance.OUT_VARIANCE, argument));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private static List<Type> toTypes(List<ParameterDescriptor> labeledEntries) {
|
||||
List<Type> result = new ArrayList<Type>();
|
||||
for (ParameterDescriptor entry : labeledEntries) {
|
||||
result.add(entry.getType());
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
package org.jetbrains.jet.lang.types;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author abreslav
|
||||
*/
|
||||
public interface Type extends Annotated {
|
||||
TypeConstructor getConstructor();
|
||||
List<TypeProjection> getArguments();
|
||||
|
||||
Collection<MemberDescriptor> getMembers();
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
package org.jetbrains.jet.lang.types;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author abreslav
|
||||
*/
|
||||
public class TypeConstructor extends AnnotatedImpl {
|
||||
private final List<TypeParameterDescriptor> parameters;
|
||||
private final Collection<Type> supertypes;
|
||||
private final String debugName;
|
||||
|
||||
public TypeConstructor(List<Annotation> annotations, String debugName, List<TypeParameterDescriptor> parameters, Collection<Type> supertypes) {
|
||||
super(annotations);
|
||||
this.debugName = debugName;
|
||||
this.parameters = parameters;
|
||||
this.supertypes = supertypes;
|
||||
}
|
||||
|
||||
public List<TypeParameterDescriptor> getParameters() {
|
||||
return parameters;
|
||||
}
|
||||
|
||||
public Collection<Type> getSupertypes() {
|
||||
return supertypes;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return debugName;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
package org.jetbrains.jet.lang.types;
|
||||
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author abreslav
|
||||
*/
|
||||
public abstract class TypeImpl extends AnnotatedImpl implements Type {
|
||||
|
||||
private final TypeConstructor constructor;
|
||||
private final List<TypeProjection> arguments;
|
||||
|
||||
public TypeImpl(List<Annotation> annotations, TypeConstructor constructor, List<TypeProjection> arguments) {
|
||||
super(annotations);
|
||||
this.constructor = constructor;
|
||||
this.arguments = arguments;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TypeConstructor getConstructor() {
|
||||
return constructor;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<TypeProjection> getArguments() {
|
||||
return arguments;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return constructor + (arguments.isEmpty() ? "" : "<" + argumentsToString() + ">");
|
||||
}
|
||||
|
||||
private StringBuilder argumentsToString() {
|
||||
StringBuilder stringBuilder = new StringBuilder();
|
||||
for (Iterator<TypeProjection> iterator = arguments.iterator(); iterator.hasNext();) {
|
||||
TypeProjection argument = iterator.next();
|
||||
stringBuilder.append(argument);
|
||||
if (iterator.hasNext()) {
|
||||
stringBuilder.append(", ");
|
||||
}
|
||||
}
|
||||
return stringBuilder;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
package org.jetbrains.jet.lang.types;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author abreslav
|
||||
*/
|
||||
public class TypeParameterDescriptor extends NamedAnnotatedImpl {
|
||||
private final Variance variance;
|
||||
private final Collection<Type> upperBounds;
|
||||
private final TypeConstructor typeConstructor;
|
||||
|
||||
public TypeParameterDescriptor(List<Annotation> annotations, String name, Variance variance, Collection<Type> upperBounds) {
|
||||
super(annotations, name);
|
||||
this.variance = variance;
|
||||
this.upperBounds = upperBounds;
|
||||
// TODO: Should we actually pass the annotations on to the type constructor?
|
||||
this.typeConstructor = new TypeConstructor(
|
||||
annotations,
|
||||
name,
|
||||
Collections.<TypeParameterDescriptor>emptyList(),
|
||||
upperBounds);
|
||||
}
|
||||
|
||||
public Variance getVariance() {
|
||||
return variance;
|
||||
}
|
||||
|
||||
public Collection<Type> getUpperBounds() {
|
||||
return upperBounds;
|
||||
}
|
||||
|
||||
public TypeConstructor getTypeConstructor() {
|
||||
return typeConstructor;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
package org.jetbrains.jet.lang.types;
|
||||
|
||||
/**
|
||||
* @author abreslav
|
||||
*/
|
||||
public class TypeProjection {
|
||||
private final Variance projection;
|
||||
private final Type type;
|
||||
|
||||
public TypeProjection(Variance projection, Type type) {
|
||||
this.projection = projection;
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
public Variance getProjection() {
|
||||
return projection;
|
||||
}
|
||||
|
||||
public Type getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return projection + " " + type;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
package org.jetbrains.jet.lang.types;
|
||||
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author abreslav
|
||||
*/
|
||||
public class TypeVariable extends TypeImpl {
|
||||
|
||||
|
||||
public TypeVariable(List<Annotation> annotations, TypeParameterDescriptor typeParameter) {
|
||||
super(annotations, typeParameter.getTypeConstructor(), Collections.<TypeProjection>emptyList());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<MemberDescriptor> getMembers() {
|
||||
throw new javax.help.UnsupportedOperationException(); // TODO
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
package org.jetbrains.jet.lang.types;
|
||||
|
||||
/**
|
||||
* @author max
|
||||
*/
|
||||
public enum Variance {
|
||||
INVARIANT(""),
|
||||
IN_VARIANCE("in"),
|
||||
OUT_VARIANCE("out");
|
||||
|
||||
private final String label;
|
||||
|
||||
Variance(String label) {
|
||||
this.label = label;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return label;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,82 @@
|
||||
package org.jetbrains.jet.parsing;
|
||||
|
||||
import com.intellij.codeInsight.daemon.LightDaemonAnalyzerTestCase;
|
||||
import com.intellij.openapi.application.PathManager;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import org.jetbrains.jet.lang.psi.JetChangeUtil;
|
||||
import org.jetbrains.jet.lang.psi.JetExpression;
|
||||
import org.jetbrains.jet.lang.types.JetStandardTypes;
|
||||
import org.jetbrains.jet.lang.types.Type;
|
||||
import org.jetbrains.jet.lang.types.JetTypeChecker;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
/**
|
||||
* @author abreslav
|
||||
*/
|
||||
public class JetTypeCheckerTest extends LightDaemonAnalyzerTestCase {
|
||||
|
||||
@Override
|
||||
protected String getTestDataPath() {
|
||||
return getHomeDirectory() + "/idea/testData";
|
||||
}
|
||||
|
||||
private static String getHomeDirectory() {
|
||||
return new File(PathManager.getResourceRoot(JetParsingTest.class, "/org/jetbrains/jet/parsing/JetParsingTest.class")).getParentFile().getParentFile().getParent();
|
||||
}
|
||||
|
||||
public void testConstants() throws Exception {
|
||||
assertType("1", JetStandardTypes.getInt());
|
||||
assertType("0x1", JetStandardTypes.getInt());
|
||||
assertType("0X1", JetStandardTypes.getInt());
|
||||
assertType("0b1", JetStandardTypes.getInt());
|
||||
assertType("0B1", JetStandardTypes.getInt());
|
||||
|
||||
assertType("1l", JetStandardTypes.getLong());
|
||||
assertType("1L", JetStandardTypes.getLong());
|
||||
|
||||
assertType("1.0", JetStandardTypes.getDouble());
|
||||
assertType("1.0d", JetStandardTypes.getDouble());
|
||||
assertType("1.0D", JetStandardTypes.getDouble());
|
||||
assertType("0x1.fffffffffffffp1023", JetStandardTypes.getDouble());
|
||||
|
||||
assertType("1.0f", JetStandardTypes.getFloat());
|
||||
assertType("1.0F", JetStandardTypes.getFloat());
|
||||
assertType("0x1.fffffffffffffp1023f", JetStandardTypes.getFloat());
|
||||
|
||||
assertType("true", JetStandardTypes.getBoolean());
|
||||
assertType("false", JetStandardTypes.getBoolean());
|
||||
|
||||
assertType("'d'", JetStandardTypes.getChar());
|
||||
|
||||
assertType("\"d\"", JetStandardTypes.getString());
|
||||
assertType("\"\"\"d\"\"\"", JetStandardTypes.getString());
|
||||
|
||||
assertType("()", JetStandardTypes.getUnit());
|
||||
}
|
||||
|
||||
public void testImplicitConversions() throws Exception {
|
||||
assertConvertibleTo("1", JetStandardTypes.getByte());
|
||||
}
|
||||
|
||||
private 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) {
|
||||
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) {
|
||||
Project project = getProject();
|
||||
JetExpression jetExpression = JetChangeUtil.createExpression(project, expression);
|
||||
Type type = new JetTypeChecker().getType(jetExpression);
|
||||
assertEquals(type, expectedType);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user