Merge remote branch 'origin/master'

This commit is contained in:
Andrey Breslav
2011-09-28 14:15:41 +04:00
39 changed files with 468 additions and 91 deletions
@@ -1,13 +1,12 @@
package org.jetbrains.jet.codegen;
import com.intellij.psi.PsiClass;
import com.intellij.psi.PsiElement;
import org.jetbrains.jet.lang.descriptors.ClassDescriptor;
import org.jetbrains.jet.lang.descriptors.ClassKind;
import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor;
import org.jetbrains.jet.lang.psi.JetClass;
import org.jetbrains.jet.lang.resolve.BindingContext;
import org.jetbrains.jet.lang.descriptors.TypeParameterDescriptor;
import org.jetbrains.jet.lang.types.JetType;
import org.jetbrains.jet.lang.types.TypeProjection;
import org.objectweb.asm.Type;
/**
* @author abreslav
@@ -54,4 +53,8 @@ public class CodegenUtil {
}
return (ClassDescriptor) outerDescriptor;
}
public static Type arrayElementType(Type type) {
return Type.getType(type.getDescriptor().substring(1));
}
}
@@ -378,8 +378,8 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
gen(expression.getLoopRange(), loopRangeType); // array
v.load(myIndexVar, Type.INT_TYPE);
v.aload(loopRangeType.getElementType());
StackValue.onStack(loopRangeType.getElementType()).put(asmParamType, v);
v.aload(CodegenUtil.arrayElementType(loopRangeType));
StackValue.onStack(CodegenUtil.arrayElementType(loopRangeType)).put(asmParamType, v);
v.store(lookupLocal(parameterDescriptor), asmParamType);
}
@@ -1683,12 +1683,23 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
}
private void generateNewArray(JetCallExpression expression, Type type) {
JetType arrayType = bindingContext.get(BindingContext.EXPRESSION_TYPE, expression);
List<? extends ValueArgument> args = expression.getValueArguments();
if (args.size() != 1) {
throw new CompilationException("array constructor requires one value argument");
}
gen(args.get(0).getArgumentExpression(), Type.INT_TYPE);
v.newarray(type.getElementType());
JetType elementType = typeMapper.getGenericsElementType(arrayType);
if(elementType != null) {
generateTypeInfo(elementType);
v.invokestatic("jet/typeinfo/TypeInfo", "newArray", "(ILjet/typeinfo/TypeInfo;)[Ljava/lang/Object;");
v.checkcast(type);
}
else {
v.newarray(CodegenUtil.arrayElementType(type));
}
}
@Override
@@ -1698,7 +1709,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
gen(array, arrayType);
generateArrayIndex(expression);
if (arrayType.getSort() == Type.ARRAY) {
final Type elementType = arrayType.getElementType();
final Type elementType = CodegenUtil.arrayElementType(arrayType);
return StackValue.arrayElement(elementType);
}
else {
@@ -670,4 +670,20 @@ public class JetTypeMapper {
public String isKnownTypeInfo(JetType jetType) {
return knowTypes.get(jetType);
}
public boolean isGenericsArray(JetType type) {
DeclarationDescriptor declarationDescriptor = type.getConstructor().getDeclarationDescriptor();
if(declarationDescriptor instanceof TypeParameterDescriptor)
return true;
if(standardLibrary.getArray().equals(declarationDescriptor))
return isGenericsArray(type.getArguments().get(0).getType());
return false;
}
public JetType getGenericsElementType(JetType arrayType) {
JetType type = arrayType.getArguments().get(0).getType();
return isGenericsArray(type) ? type : null;
}
}
@@ -152,7 +152,7 @@ public class NamespaceCodegen {
v.aconst(jvmType);
v.iconst(jetType.isNullable() ? 1 : 0);
List<TypeProjection> arguments = jetType.getArguments();
if (arguments.size() > 0) {
if (arguments.size() > 0 && !(jvmType.getSort() == Type.ARRAY && jvmType.getElementType().getSort() != Type.OBJECT)) {
v.iconst(arguments.size());
v.newarray(JetTypeMapper.TYPE_TYPEINFOPROJECTION);
@@ -186,7 +186,7 @@ public abstract class StackValue {
else
v.iconst(0);
}
else if (type.getSort() == Type.OBJECT && this.type.equals(JetTypeMapper.TYPE_OBJECT)) {
else if (type.getSort() == Type.OBJECT && this.type.equals(JetTypeMapper.TYPE_OBJECT) || type.getSort() == Type.ARRAY) {
v.checkcast(type);
}
else if (type.getSort() == Type.OBJECT) {
@@ -431,6 +431,7 @@ public abstract class StackValue {
@Override
public void put(Type type, InstructionAdapter v) {
v.aload(type); // assumes array and index are on the stack
coerce(type, v);
}
@Override
@@ -1,6 +1,6 @@
package org.jetbrains.jet.lang.diagnostics;
import org.jetbrains.jet.lang.psi.JetModifierListOwner;
import org.jetbrains.jet.lang.psi.JetClass;
import org.jetbrains.jet.lang.types.JetType;
import org.jetbrains.jet.lexer.JetKeywordToken;
@@ -9,6 +9,6 @@ import org.jetbrains.jet.lexer.JetKeywordToken;
*/
public interface DiagnosticParameters {
DiagnosticParameter<JetKeywordToken> MODIFIER = new DiagnosticParameterImpl<JetKeywordToken>("MODIFIER");
DiagnosticParameter<JetModifierListOwner> CLASS = new DiagnosticParameterImpl<JetModifierListOwner>("CLASS");
DiagnosticParameter<JetClass> CLASS = new DiagnosticParameterImpl<JetClass>("CLASS");
DiagnosticParameter<JetType> TYPE = new DiagnosticParameterImpl<JetType>("TYPE");
}
@@ -7,14 +7,14 @@ import org.jetbrains.annotations.NotNull;
/**
* @author svtk
*/
public class DiagnosticWithParametersFactory<T extends PsiElement, A> extends PsiElementOnlyDiagnosticFactory1<T, A> {
public static <T extends PsiElement, A> DiagnosticWithParametersFactory<T, A> create(Severity severity, String messageStub, DiagnosticParameter<A> diagnosticParameter) {
return new DiagnosticWithParametersFactory<T, A>(severity, messageStub, diagnosticParameter);
public class DiagnosticWithParameterFactory<T extends PsiElement, A> extends PsiElementOnlyDiagnosticFactory1<T, A> {
public static <T extends PsiElement, A> DiagnosticWithParameterFactory<T, A> create(Severity severity, String messageStub, DiagnosticParameter<A> diagnosticParameter) {
return new DiagnosticWithParameterFactory<T, A>(severity, messageStub, diagnosticParameter);
}
private final DiagnosticParameter<A> diagnosticParameter;
protected DiagnosticWithParametersFactory(Severity severity, String message, DiagnosticParameter<A> diagnosticParameter) {
protected DiagnosticWithParameterFactory(Severity severity, String message, DiagnosticParameter<A> diagnosticParameter) {
super(severity, message);
this.diagnosticParameter = diagnosticParameter;
}
@@ -88,25 +88,25 @@ public interface Errors {
SimpleDiagnosticFactory FUNCTION_WITH_NO_TYPE_NO_BODY = SimpleDiagnosticFactory.create(ERROR, "This function must either declare a return type or have a body element");
SimplePsiElementOnlyDiagnosticFactory<JetModifierListOwner> ABSTRACT_PROPERTY_IN_PRIMARY_CONSTRUCTOR_PARAMETERS = SimplePsiElementOnlyDiagnosticFactory.create(ERROR, "This property cannot be declared abstract");
SimplePsiElementOnlyDiagnosticFactory<JetModifierListOwner> ABSTRACT_PROPERTY_NOT_IN_CLASS = SimplePsiElementOnlyDiagnosticFactory.create(ERROR, "A property may be abstract only when defined in a class or trait");
DiagnosticWithParametersFactory<JetProperty, JetType> ABSTRACT_PROPERTY_WITH_INITIALIZER = DiagnosticWithParametersFactory.create(ERROR, "Property with initializer cannot be abstract", DiagnosticParameters.TYPE);
DiagnosticWithParametersFactory<JetProperty, JetType> ABSTRACT_PROPERTY_WITH_GETTER = DiagnosticWithParametersFactory.create(ERROR, "Property with getter implementation cannot be abstract", DiagnosticParameters.TYPE);
DiagnosticWithParametersFactory<JetProperty, JetType> ABSTRACT_PROPERTY_WITH_SETTER = DiagnosticWithParametersFactory.create(ERROR, "Property with setter implementation cannot be abstract", DiagnosticParameters.TYPE);
DiagnosticWithParameterFactory<JetProperty, JetType> ABSTRACT_PROPERTY_WITH_INITIALIZER = DiagnosticWithParameterFactory.create(ERROR, "Property with initializer cannot be abstract", DiagnosticParameters.TYPE);
DiagnosticWithParameterFactory<JetProperty, JetType> ABSTRACT_PROPERTY_WITH_GETTER = DiagnosticWithParameterFactory.create(ERROR, "Property with getter implementation cannot be abstract", DiagnosticParameters.TYPE);
DiagnosticWithParameterFactory<JetProperty, JetType> ABSTRACT_PROPERTY_WITH_SETTER = DiagnosticWithParameterFactory.create(ERROR, "Property with setter implementation cannot be abstract", DiagnosticParameters.TYPE);
SimpleDiagnosticFactory BACKING_FIELD_IN_TRAIT = SimpleDiagnosticFactory.create(ERROR, "Property in a trait cannot have a backing field");
SimpleDiagnosticFactory MUST_BE_INITIALIZED = SimpleDiagnosticFactory.create(ERROR, "Property must be initialized");
SimplePsiElementOnlyDiagnosticFactory<JetModifierListOwner> MUST_BE_INITIALIZED_OR_BE_ABSTRACT = SimplePsiElementOnlyDiagnosticFactory.create(ERROR, "Property must be initialized or be abstract");
DiagnosticWithParametersFactory<JetProperty, JetType> PROPERTY_INITIALIZER_IN_TRAIT = DiagnosticWithParametersFactory.create(ERROR, "Property initializers are not allowed in traits", DiagnosticParameters.TYPE);
DiagnosticWithParameterFactory<JetProperty, JetType> PROPERTY_INITIALIZER_IN_TRAIT = DiagnosticWithParameterFactory.create(ERROR, "Property initializers are not allowed in traits", DiagnosticParameters.TYPE);
SimpleDiagnosticFactory PROPERTY_INITIALIZER_NO_BACKING_FIELD = SimpleDiagnosticFactory.create(ERROR, "Initializer is not allowed here because this property has no backing field");
SimpleDiagnosticFactory PROPERTY_INITIALIZER_NO_PRIMARY_CONSTRUCTOR = SimpleDiagnosticFactory.create(ERROR, "Property initializers are not allowed when no primary constructor is present");
DiagnosticWithParameterFactory<JetProperty, JetClass> PROPERTY_INITIALIZER_NO_PRIMARY_CONSTRUCTOR = DiagnosticWithParameterFactory.create(ERROR, "Property initializers are not allowed when no primary constructor is present", DiagnosticParameters.CLASS);
SimplePsiElementOnlyDiagnosticFactory<JetModifierListOwner> REDUNDANT_ABSTRACT = SimplePsiElementOnlyDiagnosticFactory.create(WARNING, "Abstract modifier is redundant in traits");
PsiElementOnlyDiagnosticFactory3<JetModifierListOwner, String, ClassDescriptor, JetModifierListOwner> ABSTRACT_PROPERTY_IN_NON_ABSTRACT_CLASS = new PsiElementOnlyDiagnosticFactory3<JetModifierListOwner, String, ClassDescriptor, JetModifierListOwner>(ERROR, "Abstract property {0} in non-abstract class {1}") {
PsiElementOnlyDiagnosticFactory3<JetModifierListOwner, String, ClassDescriptor, JetClass> ABSTRACT_PROPERTY_IN_NON_ABSTRACT_CLASS = new PsiElementOnlyDiagnosticFactory3<JetModifierListOwner, String, ClassDescriptor, JetClass>(ERROR, "Abstract property {0} in non-abstract class {1}") {
@NotNull
protected DiagnosticWithPsiElement<JetModifierListOwner> on(@NotNull JetModifierListOwner elementToBlame, @NotNull TextRange textRangeToMark, @NotNull String s, @NotNull ClassDescriptor classDescriptor, @NotNull JetModifierListOwner aClass) {
protected DiagnosticWithPsiElement<JetModifierListOwner> on(@NotNull JetModifierListOwner elementToBlame, @NotNull TextRange textRangeToMark, @NotNull String s, @NotNull ClassDescriptor classDescriptor, @NotNull JetClass aClass) {
return super.on(elementToBlame, textRangeToMark, s, classDescriptor, aClass).add(DiagnosticParameters.CLASS, aClass);
}
};
PsiElementOnlyDiagnosticFactory3<JetFunctionOrPropertyAccessor, String, ClassDescriptor, JetModifierListOwner> ABSTRACT_FUNCTION_IN_NON_ABSTRACT_CLASS = new PsiElementOnlyDiagnosticFactory3<JetFunctionOrPropertyAccessor, String, ClassDescriptor, JetModifierListOwner>(ERROR, "Abstract function {0} in non-abstract class {1}") {
PsiElementOnlyDiagnosticFactory3<JetFunctionOrPropertyAccessor, String, ClassDescriptor, JetClass> ABSTRACT_FUNCTION_IN_NON_ABSTRACT_CLASS = new PsiElementOnlyDiagnosticFactory3<JetFunctionOrPropertyAccessor, String, ClassDescriptor, JetClass>(ERROR, "Abstract function {0} in non-abstract class {1}") {
@NotNull
public DiagnosticWithPsiElement<JetFunctionOrPropertyAccessor> on(@NotNull JetFunctionOrPropertyAccessor elementToBlame, @NotNull ASTNode nodeToMark, @NotNull String s, @NotNull ClassDescriptor classDescriptor, @NotNull JetModifierListOwner modifierListOwner) {
public DiagnosticWithPsiElement<JetFunctionOrPropertyAccessor> on(@NotNull JetFunctionOrPropertyAccessor elementToBlame, @NotNull ASTNode nodeToMark, @NotNull String s, @NotNull ClassDescriptor classDescriptor, @NotNull JetClass modifierListOwner) {
return super.on(elementToBlame, nodeToMark, s, classDescriptor, modifierListOwner).add(DiagnosticParameters.CLASS, modifierListOwner);
}
};
@@ -125,7 +125,7 @@ public interface Errors {
SimpleDiagnosticFactory INITIALIZER_WITH_NO_ARGUMENTS = SimpleDiagnosticFactory.create(ERROR, "Constructor arguments required");
SimpleDiagnosticFactory MANY_CALLS_TO_THIS = SimpleDiagnosticFactory.create(ERROR, "Only one call to 'this(...)' is allowed");
PsiElementOnlyDiagnosticFactory1<JetModifierListOwner, CallableMemberDescriptor> NOTHING_TO_OVERRIDE = PsiElementOnlyDiagnosticFactory1.create(ERROR, "{0} overrides nothing", DescriptorRenderer.TEXT);
ParameterizedDiagnosticFactory1<PropertyDescriptor> PRIMARY_CONSTRUCTOR_MISSING_STATEFUL_PROPERTY = ParameterizedDiagnosticFactory1.create(ERROR, "This class must have a primary constructor, because property {0} has a backing field");
PsiElementOnlyDiagnosticFactory1<JetClass, PropertyDescriptor> PRIMARY_CONSTRUCTOR_MISSING_STATEFUL_PROPERTY = PsiElementOnlyDiagnosticFactory1.create(ERROR, "This class must have a primary constructor, because property {0} has a backing field");
ParameterizedDiagnosticFactory1<JetClassOrObject> PRIMARY_CONSTRUCTOR_MISSING_SUPER_CONSTRUCTOR_CALL = new ParameterizedDiagnosticFactory1<JetClassOrObject>(ERROR, "Class {0} must have a constructor in order to be able to initialize supertypes") {
@Override
protected String makeMessageFor(@NotNull JetClassOrObject argument) {
@@ -162,8 +162,8 @@ public interface Errors {
SimplePsiElementOnlyDiagnosticFactory<JetBinaryExpressionWithTypeRHS> USELESS_CAST_STATIC_ASSERT_IS_FINE = SimplePsiElementOnlyDiagnosticFactory.create(WARNING, "No cast needed, use ':' instead");
SimplePsiElementOnlyDiagnosticFactory<JetBinaryExpressionWithTypeRHS> USELESS_CAST = SimplePsiElementOnlyDiagnosticFactory.create(WARNING, "No cast needed");
SimpleDiagnosticFactory CAST_NEVER_SUCCEEDS = SimpleDiagnosticFactory.create(WARNING, "This cast can never succeed");
DiagnosticWithParametersFactory<JetPropertyAccessor, JetType> WRONG_SETTER_PARAMETER_TYPE = DiagnosticWithParametersFactory.create(ERROR, "Setter parameter type must be equal to the type of the property, i.e. {0}", DiagnosticParameters.TYPE);
DiagnosticWithParametersFactory<JetPropertyAccessor, JetType> WRONG_GETTER_RETURN_TYPE = DiagnosticWithParametersFactory.create(ERROR, "Getter return type must be equal to the type of the property, i.e. {0}", DiagnosticParameters.TYPE);
DiagnosticWithParameterFactory<JetPropertyAccessor, JetType> WRONG_SETTER_PARAMETER_TYPE = DiagnosticWithParameterFactory.create(ERROR, "Setter parameter type must be equal to the type of the property, i.e. {0}", DiagnosticParameters.TYPE);
DiagnosticWithParameterFactory<JetPropertyAccessor, JetType> WRONG_GETTER_RETURN_TYPE = DiagnosticWithParameterFactory.create(ERROR, "Getter return type must be equal to the type of the property, i.e. {0}", DiagnosticParameters.TYPE);
ParameterizedDiagnosticFactory1<ClassifierDescriptor> NO_CLASS_OBJECT = ParameterizedDiagnosticFactory1.create(ERROR, "Classifier {0} does not have a class object", NAME);
SimpleDiagnosticFactory NO_GENERICS_IN_SUPERTYPE_SPECIFIER = SimpleDiagnosticFactory.create(ERROR, "Generic arguments of the base type must be specified");
@@ -1,6 +1,7 @@
package org.jetbrains.jet.lang.psi;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Pair;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiFileFactory;
import com.intellij.util.LocalTimeCounter;
@@ -24,9 +25,10 @@ public class JetPsiFactory {
return property.getPropertyTypeRef();
}
public static PsiElement[] createColon(Project project) {
//the pair contains the first and the last elements of a range
public static Pair<PsiElement, PsiElement> createColon(Project project) {
JetProperty property = createProperty(project, "val x : Int");
return new PsiElement[] { property.findElementAt(5), property.findElementAt(6), property.findElementAt(7) };
return Pair.create(property.findElementAt(5), property.findElementAt(7));
}
public static PsiElement createWhiteSpace(Project project) {
@@ -38,11 +40,6 @@ public class JetPsiFactory {
return property.findElementAt(3);
}
// public static PsiElement createEndOfLine(Project project) {
// JetNamedFunction function = createFunction(project, "fun f { \n }");
// return function.findElementAt(8);
// }
public static JetClass createClass(Project project, String text) {
return createDeclaration(project, text, JetClass.class);
}
@@ -99,4 +96,9 @@ public class JetPsiFactory {
JetNamespace namespace = createNamespace(project, "import " + classPath);
return namespace.getImportDirectives().iterator().next();
}
public static PsiElement createPrimaryConstructor(Project project) {
JetClass aClass = createClass(project, "class A()");
return aClass.findElementAt(7).getParent();
}
}
@@ -95,7 +95,7 @@ public class BodyResolver {
if (nameIdentifier != null) {
// context.getTrace().getErrorHandler().genericError(nameIdentifier.getNode(),
// "This class must have a primary constructor, because property " + propertyDescriptor.getName() + " has a backing field");
context.getTrace().report(PRIMARY_CONSTRUCTOR_MISSING_STATEFUL_PROPERTY.on(nameIdentifier, propertyDescriptor));
context.getTrace().report(PRIMARY_CONSTRUCTOR_MISSING_STATEFUL_PROPERTY.on(jetClass, nameIdentifier, propertyDescriptor));
}
break;
}
@@ -526,6 +526,9 @@ public class BodyResolver {
if (propertyDescriptor.getModality() == Modality.ABSTRACT) {
JetType returnType = propertyDescriptor.getReturnType();
if (returnType instanceof DeferredType) {
returnType = ((DeferredType) returnType).getActualType();
}
JetExpression initializer = property.getInitializer();
if (initializer != null) {
@@ -575,7 +578,11 @@ public class BodyResolver {
}
if (inTrait) {
// context.getTrace().getErrorHandler().genericError(initializer.getNode(), "Property initializers are not allowed in traits");
context.getTrace().report(PROPERTY_INITIALIZER_IN_TRAIT.on(property, initializer, propertyDescriptor.getReturnType()));
JetType returnType = propertyDescriptor.getReturnType();
if (returnType instanceof DeferredType) {
returnType = ((DeferredType) returnType).getActualType();
}
context.getTrace().report(PROPERTY_INITIALIZER_IN_TRAIT.on(property, initializer, returnType));
}
else if (!backingFieldRequired) {
// context.getTrace().getErrorHandler().genericError(initializer.getNode(), "Initializer is not allowed here because this property has no backing field");
@@ -583,7 +590,10 @@ public class BodyResolver {
}
else if (classDescriptor != null && classDescriptor.getUnsubstitutedPrimaryConstructor() == null) {
// context.getTrace().getErrorHandler().genericError(initializer.getNode(), "Property initializers are not allowed when no primary constructor is present");
context.getTrace().report(PROPERTY_INITIALIZER_NO_PRIMARY_CONSTRUCTOR.on(initializer));
PsiElement classElement = context.getTrace().get(BindingContext.DESCRIPTOR_TO_DECLARATION, classDescriptor);
assert classElement instanceof JetClass;
context.getTrace().report(PROPERTY_INITIALIZER_NO_PRIMARY_CONSTRUCTOR.on(property, initializer, (JetClass) classElement));
}
}
@@ -690,10 +700,10 @@ public class BodyResolver {
boolean inTrait = classDescriptor.getKind() == ClassKind.TRAIT;
boolean inEnum = classDescriptor.getKind() == ClassKind.ENUM_CLASS;
boolean inAbstractClass = classDescriptor.getModality() == Modality.ABSTRACT;
PsiElement classElement = context.getTrace().get(BindingContext.DESCRIPTOR_TO_DECLARATION, classDescriptor);
assert classElement instanceof JetModifierListOwner;
if (hasAbstractModifier && !inAbstractClass && !inTrait && !inEnum) {
context.getTrace().report(ABSTRACT_FUNCTION_IN_NON_ABSTRACT_CLASS.on(functionOrPropertyAccessor, abstractNode, functionDescriptor.getName(), classDescriptor, (JetModifierListOwner) classElement));
PsiElement classElement = context.getTrace().get(BindingContext.DESCRIPTOR_TO_DECLARATION, classDescriptor);
assert classElement instanceof JetClass;
context.getTrace().report(ABSTRACT_FUNCTION_IN_NON_ABSTRACT_CLASS.on(functionOrPropertyAccessor, abstractNode, functionDescriptor.getName(), classDescriptor, (JetClass) classElement));
}
if (hasAbstractModifier && inTrait && !isPropertyAccessor) {
context.getTrace().report(REDUNDANT_ABSTRACT.on(functionOrPropertyAccessor, abstractNode));
@@ -177,7 +177,7 @@ public class ErrorUtils {
}
public static boolean isError(@NotNull DeclarationDescriptor candidate) {
return candidate.getContainingDeclaration() == getErrorClass();
return candidate.getContainingDeclaration() == getErrorClass() || candidate == ERROR_MODULE;
}
private static class ErrorTypeImpl implements JetType {