proper compilation of enums

This commit is contained in:
Alex Tkachman
2012-08-13 22:37:27 +03:00
parent e5820722ec
commit 5947759684
33 changed files with 839 additions and 134 deletions
@@ -17,6 +17,7 @@
package org.jetbrains.jet.codegen;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.descriptors.ClassKind;
import org.jetbrains.jet.lang.descriptors.ConstructorDescriptor;
import org.jetbrains.jet.lang.descriptors.ValueParameterDescriptor;
import org.jetbrains.asm4.Type;
@@ -42,6 +43,11 @@ public class ConstructorFrameMap extends FrameMap {
List<Type> explicitArgTypes = callableMethod.getValueParameterTypes();
if(descriptor != null && descriptor.getContainingDeclaration().getKind() == ClassKind.ENUM_CLASS) {
enterTemp(); // name
enterTemp(); // ordinal
}
List<ValueParameterDescriptor> paramDescrs = descriptor != null
? descriptor.getValueParameters()
: Collections.<ValueParameterDescriptor>emptyList();
@@ -1035,7 +1035,11 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
IntrinsicMethod intrinsic = null;
if (descriptor instanceof CallableMemberDescriptor) {
intrinsic = state.getInjector().getIntrinsics().getIntrinsic((CallableMemberDescriptor) descriptor);
CallableMemberDescriptor memberDescriptor = (CallableMemberDescriptor) descriptor;
while(memberDescriptor.getKind() == CallableMemberDescriptor.Kind.FAKE_OVERRIDE) {
memberDescriptor = memberDescriptor.getOverriddenDescriptors().iterator().next();
}
intrinsic = state.getInjector().getIntrinsics().getIntrinsic(memberDescriptor);
}
if (intrinsic != null) {
final Type expectedType = expressionType(expression);
@@ -1111,11 +1115,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
if (descriptor instanceof ClassDescriptor) {
PsiElement declaration = BindingContextUtils.descriptorToDeclaration(bindingContext, descriptor);
if (declaration instanceof JetClass) {
final JetClassObject classObject = ((JetClass) declaration).getClassObject();
if (classObject == null) {
throw new UnsupportedOperationException("trying to reference a class which doesn't have a class object");
}
final ClassDescriptor descriptor1 = bindingContext.get(BindingContext.CLASS, classObject.getObjectDeclaration());
final ClassDescriptor descriptor1 = ((ClassDescriptor)descriptor).getClassObjectDescriptor();
assert descriptor1 != null;
final Type type = typeMapper.mapType(descriptor1.getDefaultType(), MapTypeMode.VALUE);
return StackValue.field(type,
@@ -35,6 +35,7 @@ import org.jetbrains.jet.lang.resolve.java.JvmAbi;
import org.jetbrains.jet.lang.resolve.java.JvmClassName;
import org.jetbrains.jet.lang.resolve.java.JvmStdlibNames;
import org.jetbrains.jet.lang.types.JetType;
import org.jetbrains.jet.lang.types.lang.JetStandardLibrary;
import org.jetbrains.jet.lexer.JetTokens;
import org.jetbrains.jet.utils.BitSetUtils;
import org.jetbrains.asm4.AnnotationVisitor;
@@ -54,6 +55,7 @@ import static org.jetbrains.asm4.Opcodes.*;
* @author alex.tkachman
*/
public class ImplementationBodyCodegen extends ClassBodyCodegen {
public static final String VALUES = "$VALUES";
private JetDelegationSpecifier superCall;
private String superClass;
@Nullable // null means java/lang/Object
@@ -78,6 +80,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
boolean isFinal = false;
boolean isStatic = false;
boolean isAnnotation = false;
boolean isEnum = false;
if (myClass instanceof JetClass) {
JetClass jetClass = (JetClass) myClass;
@@ -87,12 +90,16 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
isAbstract = true;
isInterface = true;
}
if (jetClass.isAnnotation()) {
else if (jetClass.isAnnotation()) {
isAbstract = true;
isInterface = true;
isAnnotation = true;
signature.getInterfaces().add(JdkNames.JLA_ANNOTATION.getInternalName());
}
else if (jetClass.hasModifier(JetTokens.ENUM_KEYWORD)) {
isEnum = true;
}
if (!jetClass.hasModifier(JetTokens.OPEN_KEYWORD) && !isAbstract) {
isFinal = true;
}
@@ -121,6 +128,9 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
if (isAnnotation) {
access |= ACC_ANNOTATION;
}
if (isEnum) {
access |= ACC_ENUM;
}
v.defineClass(myClass, V1_6,
access,
signature.getName(),
@@ -270,6 +280,13 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
}
}
}
if(superClassType == null) {
if (myClass instanceof JetClass && ((JetClass) myClass).hasModifier(JetTokens.ENUM_KEYWORD)) {
superClassType = JetStandardLibrary.getInstance().getEnumType(descriptor.getDefaultType());
superClass = typeMapper.mapType(superClassType,MapTypeMode.VALUE).getInternalName();
}
}
}
@Override
@@ -293,6 +310,38 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
generateTraitMethods();
generateAccessors();
generateEnumMethods();
}
private void generateEnumMethods() {
if(myEnumConstants.size() > 0) {
{
Type type = typeMapper.mapType(JetStandardLibrary.getInstance().getArrayType(descriptor.getDefaultType()), MapTypeMode.IMPL);
MethodVisitor mv =
v.newMethod(myClass, ACC_PUBLIC | ACC_STATIC, "values", "()" + type.getDescriptor(), null, null);
mv.visitCode();
mv.visitFieldInsn(GETSTATIC, typeMapper.mapType(descriptor.getDefaultType(),MapTypeMode.VALUE).getInternalName(), VALUES, type.getDescriptor());
mv.visitMethodInsn(INVOKEVIRTUAL, type.getInternalName(), "clone", "()Ljava/lang/Object;");
mv.visitTypeInsn(CHECKCAST, type.getInternalName());
mv.visitInsn(ARETURN);
FunctionCodegen.endVisit(mv,"values()",myClass);
}
{
Type type = typeMapper.mapType(descriptor.getDefaultType(), MapTypeMode.IMPL);
MethodVisitor mv =
v.newMethod(myClass, ACC_PUBLIC | ACC_STATIC, "valueOf", "(Ljava/lang/String;)" + type.getDescriptor(), null, null);
mv.visitCode();
mv.visitLdcInsn(type);
mv.visitVarInsn(ALOAD, 0);
mv.visitMethodInsn(INVOKESTATIC, "java/lang/Enum", "valueOf", "(Ljava/lang/Class;Ljava/lang/String;)Ljava/lang/Enum;");
mv.visitTypeInsn(CHECKCAST, type.getInternalName());
mv.visitInsn(ARETURN);
FunctionCodegen.endVisit(mv,"values()",myClass);
}
}
}
private void generateAccessors() {
@@ -593,6 +642,10 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
i++;
}
if(myClass instanceof JetClass && ((JetClass)myClass).hasModifier(JetTokens.ENUM_KEYWORD)) {
i += 2;
}
for (ValueParameterDescriptor valueParameter : constructorDescriptor.getValueParameters()) {
AnnotationCodegen.forParameter(i, mv, state.getInjector().getJetTypeMapper()).genAnnotations(valueParameter);
JetValueParameterAnnotationWriter jetValueParameterAnnotation = JetValueParameterAnnotationWriter.visitParameterAnnotation(mv, i);
@@ -641,7 +694,14 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
if (superCall == null) {
iv.load(0, Type.getType("L" + superClass + ";"));
iv.invokespecial(superClass, "<init>", "()V");
if(descriptor.getKind() == ClassKind.ENUM_CLASS) {
iv.load(1, JetTypeMapper.JL_STRING_TYPE);
iv.load(2, Type.INT_TYPE);
iv.invokespecial(superClass, "<init>", "(Ljava/lang/String;I)V");
}
else {
iv.invokespecial(superClass, "<init>", "()V");
}
}
else if (superCall instanceof JetDelegatorToSuperClass) {
iv.load(0, Type.getType("L" + superClass + ";"));
@@ -865,6 +925,10 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
ClassDescriptor classDecl = constructorDescriptor.getContainingDeclaration();
iv.load(0, TYPE_OBJECT);
if(classDecl.getKind() == ClassKind.ENUM_CLASS) {
iv.load(1, JetTypeMapper.TYPE_OBJECT);
iv.load(2, Type.INT_TYPE);
}
if (classDecl.getContainingDeclaration() instanceof ClassDescriptor) {
iv.load(frameMap.getOuterThisIndex(), typeMapper.mapType(((ClassDescriptor) descriptor.getContainingDeclaration()).getDefaultType(), MapTypeMode.IMPL));
@@ -895,7 +959,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
else if (declaration instanceof JetEnumEntry && !((JetEnumEntry) declaration).hasPrimaryConstructor()) {
String name = declaration.getName();
final String desc = "L" + typeMapper.mapType(descriptor.getDefaultType(), MapTypeMode.IMPL).getInternalName() + ";";
v.newField(declaration, ACC_PUBLIC | ACC_STATIC | ACC_FINAL, name, desc, null, null);
v.newField(declaration, ACC_PUBLIC | ACC_ENUM | ACC_STATIC | ACC_FINAL, name, desc, null, null);
if (myEnumConstants.isEmpty()) {
staticInitializerChunks.add(new CodeChunk() {
@Override
@@ -913,19 +977,40 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
private final List<JetEnumEntry> myEnumConstants = new ArrayList<JetEnumEntry>();
private void initializeEnumConstants(InstructionAdapter v) {
ExpressionCodegen codegen = new ExpressionCodegen(v, new FrameMap(), Type.VOID_TYPE, context, state);
private void initializeEnumConstants(InstructionAdapter iv) {
ExpressionCodegen codegen = new ExpressionCodegen(iv, new FrameMap(), Type.VOID_TYPE, context, state);
int ordinal = -1;
JetType myType = descriptor.getDefaultType();
Type myAsmType = typeMapper.mapType(myType, MapTypeMode.IMPL);
assert myEnumConstants.size() > 0;
JetType arrayType = JetStandardLibrary.getInstance().getArrayType(myType);
Type arrayAsmType = typeMapper.mapType(arrayType, MapTypeMode.IMPL);
v.newField(myClass, ACC_PRIVATE | ACC_STATIC | ACC_FINAL | ACC_SYNTHETIC, "$VALUES", arrayAsmType.getDescriptor(), null, null);
iv.iconst(myEnumConstants.size());
iv.newarray(myAsmType);
iv.dup();
for (JetEnumEntry enumConstant : myEnumConstants) {
ordinal++;
iv.dup();
iv.iconst(ordinal);
// TODO type and constructor parameters
String implClass = typeMapper.mapType(descriptor.getDefaultType(), MapTypeMode.IMPL).getInternalName();
String implClass = typeMapper.mapType(myType, MapTypeMode.IMPL).getInternalName();
final List<JetDelegationSpecifier> delegationSpecifiers = enumConstant.getDelegationSpecifiers();
if (delegationSpecifiers.size() > 1) {
throw new UnsupportedOperationException("multiple delegation specifiers for enum constant not supported");
}
v.anew(Type.getObjectType(implClass));
v.dup();
iv.anew(Type.getObjectType(implClass));
iv.dup();
iv.aconst(enumConstant.getName());
iv.iconst(ordinal);
if (delegationSpecifiers.size() == 1) {
final JetDelegationSpecifier specifier = delegationSpecifiers.get(0);
@@ -940,10 +1025,13 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
}
}
else {
v.invokespecial(implClass, "<init>", "()V");
iv.invokespecial(implClass, "<init>", "(Ljava/lang/String;I)V");
}
v.putstatic(implClass, enumConstant.getName(), "L" + implClass + ";");
iv.dup();
iv.putstatic(implClass, enumConstant.getName(), "L" + implClass + ";");
iv.astore(TYPE_OBJECT);
}
iv.putstatic(myAsmType.getClassName(), "$VALUES", arrayAsmType.getDescriptor());
}
public static void generateInitializers(@NotNull ExpressionCodegen codegen, @NotNull InstructionAdapter iv, @NotNull List<JetDeclaration> declarations,
@@ -38,6 +38,7 @@ import org.jetbrains.jet.lang.resolve.name.Name;
import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor;
import org.jetbrains.jet.lang.types.*;
import org.jetbrains.jet.lang.types.lang.JetStandardClasses;
import org.jetbrains.jet.lang.types.lang.JetStandardLibrary;
import org.jetbrains.jet.lang.types.lang.JetStandardLibraryNames;
import org.jetbrains.jet.lang.types.lang.PrimitiveType;
import org.jetbrains.jet.lang.types.ref.ClassName;
@@ -61,6 +62,7 @@ public class JetTypeMapper {
public static final Type JL_NUMBER_TYPE = Type.getObjectType("java/lang/Number");
public static final Type JL_STRING_BUILDER = Type.getObjectType("java/lang/StringBuilder");
public static final Type JL_STRING_TYPE = Type.getObjectType("java/lang/String");
public static final Type JL_ENUM_TYPE = Type.getObjectType("java/lang/Enum");
public static final Type JL_CHAR_SEQUENCE_TYPE = Type.getObjectType("java/lang/CharSequence");
private static final Type JL_COMPARABLE_TYPE = Type.getObjectType("java/lang/Comparable");
public static final Type JL_CLASS_TYPE = Type.getObjectType("java/lang/Class");
@@ -141,6 +143,7 @@ public class JetTypeMapper {
register(JetStandardLibraryNames.CHAR_SEQUENCE, JL_CHAR_SEQUENCE_TYPE, JL_CHAR_SEQUENCE_TYPE);
register(JetStandardLibraryNames.THROWABLE, TYPE_THROWABLE, TYPE_THROWABLE);
register(JetStandardLibraryNames.COMPARABLE, JL_COMPARABLE_TYPE, JL_COMPARABLE_TYPE);
register(JetStandardLibraryNames.ENUM, JL_ENUM_TYPE, JL_ENUM_TYPE);
for (JvmPrimitiveType jvmPrimitiveType : JvmPrimitiveType.values()) {
PrimitiveType primitiveType = jvmPrimitiveType.getPrimitiveType();
@@ -941,9 +944,19 @@ public class JetTypeMapper {
signatureWriter.writeParametersStart();
ClassDescriptor containingDeclaration = descriptor.getContainingDeclaration();
if (hasThis0) {
signatureWriter.writeParameterType(JvmMethodParameterKind.THIS0);
mapType(closureAnnotator.getEclosingClassDescriptor(descriptor.getContainingDeclaration()).getDefaultType(), signatureWriter, MapTypeMode.VALUE);
mapType(closureAnnotator.getEclosingClassDescriptor(containingDeclaration).getDefaultType(), signatureWriter, MapTypeMode.VALUE);
signatureWriter.writeParameterTypeEnd();
}
if(containingDeclaration.getKind() == ClassKind.ENUM_CLASS) {
signatureWriter.writeParameterType(JvmMethodParameterKind.ENUM_NAME);
mapType(JetStandardLibrary.getInstance().getStringType(), signatureWriter, MapTypeMode.VALUE);
signatureWriter.writeParameterTypeEnd();
signatureWriter.writeParameterType(JvmMethodParameterKind.ENUM_ORDINAL);
mapType(JetStandardLibrary.getInstance().getIntType(), signatureWriter, MapTypeMode.VALUE);
signatureWriter.writeParameterTypeEnd();
}
@@ -1046,6 +1059,7 @@ public class JetTypeMapper {
|| className.getFqName().getFqName().equals("java.lang.CharSequence")
|| className.getFqName().getFqName().equals("java.lang.Object")
|| className.getFqName().getFqName().equals("java.lang.Number")
|| className.getFqName().getFqName().equals("java.lang.Enum")
|| className.getFqName().getFqName().equals("java.lang.Comparable");
}
@@ -0,0 +1,48 @@
/*
* Copyright 2010-2012 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.jet.codegen.intrinsics;
import com.intellij.psi.PsiElement;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.asm4.Type;
import org.jetbrains.asm4.commons.InstructionAdapter;
import org.jetbrains.jet.codegen.ExpressionCodegen;
import org.jetbrains.jet.codegen.GenerationState;
import org.jetbrains.jet.codegen.JetTypeMapper;
import org.jetbrains.jet.codegen.StackValue;
import org.jetbrains.jet.lang.psi.JetExpression;
import java.util.List;
public class EnumName implements IntrinsicMethod {
@Override
public StackValue generate(
ExpressionCodegen codegen,
InstructionAdapter v,
@NotNull Type expectedType,
@Nullable PsiElement element,
@Nullable List<JetExpression> arguments,
StackValue receiver,
@NotNull GenerationState state
) {
receiver.put(JetTypeMapper.TYPE_OBJECT, v);
v.invokevirtual("java/lang/Enum", "name", "()Ljava/lang/String;");
StackValue.onStack(JetTypeMapper.JL_STRING_TYPE).put(expectedType, v);
return StackValue.onStack(expectedType);
}
}
@@ -0,0 +1,48 @@
/*
* Copyright 2010-2012 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.jet.codegen.intrinsics;
import com.intellij.psi.PsiElement;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.asm4.Type;
import org.jetbrains.asm4.commons.InstructionAdapter;
import org.jetbrains.jet.codegen.ExpressionCodegen;
import org.jetbrains.jet.codegen.GenerationState;
import org.jetbrains.jet.codegen.JetTypeMapper;
import org.jetbrains.jet.codegen.StackValue;
import org.jetbrains.jet.lang.psi.JetExpression;
import java.util.List;
public class EnumOrdinal implements IntrinsicMethod {
@Override
public StackValue generate(
ExpressionCodegen codegen,
InstructionAdapter v,
@NotNull Type expectedType,
@Nullable PsiElement element,
@Nullable List<JetExpression> arguments,
StackValue receiver,
@NotNull GenerationState state
) {
receiver.put(JetTypeMapper.TYPE_OBJECT, v);
v.invokevirtual("java/lang/Enum", "ordinal", "()I");
StackValue.onStack(Type.INT_TYPE).put(expectedType, v);
return StackValue.onStack(expectedType);
}
}
@@ -0,0 +1,51 @@
/*
* Copyright 2010-2012 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.jet.codegen.intrinsics;
import com.intellij.psi.PsiElement;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.asm4.Type;
import org.jetbrains.asm4.commons.InstructionAdapter;
import org.jetbrains.jet.codegen.*;
import org.jetbrains.jet.lang.descriptors.CallableDescriptor;
import org.jetbrains.jet.lang.psi.JetCallExpression;
import org.jetbrains.jet.lang.psi.JetExpression;
import org.jetbrains.jet.lang.resolve.BindingContext;
import org.jetbrains.jet.lang.resolve.calls.ResolvedCall;
import org.jetbrains.jet.lang.resolve.java.JvmPrimitiveType;
import java.util.List;
/**
* @author alex.tkachman
*/
public class EnumValueOf implements IntrinsicMethod {
@Override
public StackValue generate(ExpressionCodegen codegen, InstructionAdapter v, @NotNull Type expectedType, @Nullable PsiElement element,
@Nullable List<JetExpression> arguments, StackValue receiver, @NotNull GenerationState state) {
JetCallExpression call = (JetCallExpression) element;
ResolvedCall<? extends CallableDescriptor> resolvedCall = codegen.getBindingContext().get(BindingContext.RESOLVED_CALL, call.getCalleeExpression());
CallableDescriptor resultingDescriptor = resolvedCall.getResultingDescriptor();
Type type = state.getInjector().getJetTypeMapper().mapType(
resultingDescriptor.getReturnType(), MapTypeMode.VALUE);
codegen.gen(arguments.get(0),JetTypeMapper.JL_STRING_TYPE);
v.invokestatic(type.getInternalName(),"valueOf","(Ljava/lang/String;)" + type.getDescriptor());
StackValue.onStack(type).put(expectedType, v);
return StackValue.onStack(expectedType);
}
}
@@ -0,0 +1,49 @@
/*
* Copyright 2010-2012 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.jet.codegen.intrinsics;
import com.intellij.psi.PsiElement;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.asm4.Type;
import org.jetbrains.asm4.commons.InstructionAdapter;
import org.jetbrains.jet.codegen.*;
import org.jetbrains.jet.lang.descriptors.CallableDescriptor;
import org.jetbrains.jet.lang.psi.JetCallExpression;
import org.jetbrains.jet.lang.psi.JetExpression;
import org.jetbrains.jet.lang.resolve.BindingContext;
import org.jetbrains.jet.lang.resolve.calls.ResolvedCall;
import java.util.List;
/**
* @author alex.tkachman
*/
public class EnumValues implements IntrinsicMethod {
@Override
public StackValue generate(ExpressionCodegen codegen, InstructionAdapter v, @NotNull Type expectedType, @Nullable PsiElement element,
@Nullable List<JetExpression> arguments, StackValue receiver, @NotNull GenerationState state) {
JetCallExpression call = (JetCallExpression) element;
ResolvedCall<? extends CallableDescriptor> resolvedCall = codegen.getBindingContext().get(BindingContext.RESOLVED_CALL, call.getCalleeExpression());
CallableDescriptor resultingDescriptor = resolvedCall.getResultingDescriptor();
Type type = state.getInjector().getJetTypeMapper().mapType(
resultingDescriptor.getReturnType(), MapTypeMode.VALUE);
v.invokestatic(type.getElementType().getInternalName(), "values", "()" + type);
StackValue.onStack(type).put(expectedType, v);
return StackValue.onStack(expectedType);
}
}
@@ -21,6 +21,7 @@ import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.asm4.Opcodes;
import org.jetbrains.jet.lang.descriptors.CallableMemberDescriptor;
import org.jetbrains.jet.lang.descriptors.ClassDescriptor;
import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor;
import org.jetbrains.jet.lang.descriptors.SimpleFunctionDescriptor;
import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor;
@@ -63,6 +64,8 @@ public class IntrinsicMethods {
public static final String KOTLIN_JAVA_CLASS_FUNCTION = "kotlin.javaClass.function";
public static final String KOTLIN_ARRAYS_ARRAY = "kotlin.arrays.array";
public static final String KOTLIN_JAVA_CLASS_PROPERTY = "kotlin.javaClass.property";
public static final EnumValues ENUM_VALUES = new EnumValues();
public static final EnumValueOf ENUM_VALUE_OF = new EnumValueOf();
private final Map<String, IntrinsicMethod> namedMethods = new HashMap<String, IntrinsicMethod>();
private static final IntrinsicMethod ARRAY_ITERATOR = new ArrayIterator();
@@ -113,6 +116,9 @@ public class IntrinsicMethods {
declareIntrinsicFunction(Name.identifier("CharSequence"), Name.identifier("get"), 1, new StringGetChar());
declareIntrinsicFunction(Name.identifier("String"), Name.identifier("get"), 1, new StringGetChar());
intrinsicsMap.registerIntrinsic(JetStandardClasses.STANDARD_CLASSES_FQNAME, Name.identifier("name"), 0, new EnumName());
intrinsicsMap.registerIntrinsic(JetStandardClasses.STANDARD_CLASSES_FQNAME, Name.identifier("ordinal"), 0, new EnumOrdinal());
intrinsicsMap.registerIntrinsic(JetStandardClasses.STANDARD_CLASSES_FQNAME, Name.identifier("toString"), 0, new ToString());
intrinsicsMap.registerIntrinsic(JetStandardClasses.STANDARD_CLASSES_FQNAME, Name.identifier("equals"), 1, EQUALS);
intrinsicsMap.registerIntrinsic(JetStandardClasses.STANDARD_CLASSES_FQNAME, Name.identifier("identityEquals"), 1, IDENTITY_EQUALS);
@@ -219,6 +225,15 @@ public class IntrinsicMethods {
return new PsiMethodCall(functionDescriptor);
}
}
if(isEnumClassObject(functionDescriptor.getContainingDeclaration())) {
if("values".equals(functionDescriptor.getName().getName())) {
return ENUM_VALUES;
}
if("valueOf".equals(functionDescriptor.getName().getName())) {
return ENUM_VALUE_OF;
}
}
}
List<AnnotationDescriptor> annotations = descriptor.getAnnotations();
@@ -233,4 +248,18 @@ public class IntrinsicMethods {
}
return intrinsicMethod;
}
private static boolean isEnumClassObject(DeclarationDescriptor declaration) {
if(declaration instanceof ClassDescriptor) {
ClassDescriptor descriptor = (ClassDescriptor) declaration;
if(descriptor.getContainingDeclaration() instanceof ClassDescriptor) {
ClassDescriptor containingDeclaration = (ClassDescriptor) descriptor.getContainingDeclaration();
//noinspection ConstantConditions
if(containingDeclaration != null && containingDeclaration.getClassObjectDescriptor() != null && containingDeclaration.getClassObjectDescriptor().equals(descriptor)) {
return true;
}
}
}
return false; //To change body of created methods use File | Settings | File Templates.
}
}
@@ -27,4 +27,6 @@ public enum JvmMethodParameterKind {
THIS0,
RECEIVER,
SHARED_VAR,
ENUM_NAME,
ENUM_ORDINAL,
}
@@ -321,7 +321,7 @@ public class JavaDescriptorResolver implements DependencyClassByQualifiedNameRes
checkPsiClassIsNotJet(psiClass);
Name name = Name.identifier(psiClass.getName());
ClassKind kind = psiClass.isInterface() ? (psiClass.isAnnotationType() ? ClassKind.ANNOTATION_CLASS : ClassKind.TRAIT) : ClassKind.CLASS;
ClassKind kind = psiClass.isInterface() ? (psiClass.isAnnotationType() ? ClassKind.ANNOTATION_CLASS : ClassKind.TRAIT) : (psiClass.isEnum() ? ClassKind.ENUM_CLASS : ClassKind.CLASS);
ClassOrNamespaceDescriptor containingDeclaration = resolveParentDescriptor(psiClass);
// class may be resolved during resolution of parent
@@ -266,6 +266,7 @@ public class JavaTypeTransformer {
classDescriptorMap.put(new FqName("java.lang.Throwable"), JetStandardLibrary.getInstance().getThrowable());
classDescriptorMap.put(new FqName("java.lang.Number"), JetStandardLibrary.getInstance().getNumber());
classDescriptorMap.put(new FqName("java.lang.Comparable"), JetStandardLibrary.getInstance().getComparable());
classDescriptorMap.put(new FqName("java.lang.Enum"), JetStandardLibrary.getInstance().getEnum());
}
return classDescriptorMap;
}
@@ -24,5 +24,8 @@ public class JdkNames {
public static final JvmClassName JL_OBJECT = JvmClassName.byInternalName("java/lang/Object");
public static final JvmClassName JL_STRING = JvmClassName.byInternalName("java/lang/String");
public static final JvmClassName JLA_ANNOTATION = JvmClassName.byInternalName("java/lang/annotation/Annotation");
public static final JvmClassName JLA_ENUM = JvmClassName.byInternalName("java/lang/Enum");
private JdkNames() {
}
}
+6
View File
@@ -0,0 +1,6 @@
package jet
public abstract class Enum<E: Enum<E>>(name: String, ordinal: Int) {
public final fun name() : String
public final fun ordinal() : Int
}
@@ -32,6 +32,7 @@ import org.jetbrains.jet.lang.resolve.name.Name;
import org.jetbrains.jet.lang.resolve.scopes.JetScope;
import org.jetbrains.jet.lang.resolve.scopes.WritableScope;
import org.jetbrains.jet.lang.resolve.scopes.WritableScopeImpl;
import org.jetbrains.jet.lang.resolve.scopes.receivers.ClassReceiver;
import org.jetbrains.jet.lang.resolve.scopes.receivers.ExtensionReceiver;
import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor;
import org.jetbrains.jet.lang.types.*;
@@ -47,6 +48,7 @@ import javax.inject.Inject;
import java.util.*;
import static org.jetbrains.jet.lang.diagnostics.Errors.*;
import static org.jetbrains.jet.lang.resolve.BindingContext.CLASS;
import static org.jetbrains.jet.lang.resolve.BindingContext.CONSTRUCTOR;
/**
@@ -76,7 +78,11 @@ public class DescriptorResolver {
}
public void resolveMutableClassDescriptor(@NotNull JetClass classElement, @NotNull MutableClassDescriptor descriptor, BindingTrace trace) {
public void resolveMutableClassDescriptor(
@NotNull JetClass classElement,
@NotNull MutableClassDescriptor descriptor,
BindingTrace trace
) {
// TODO : Where-clause
List<TypeParameterDescriptor> typeParameters = Lists.newArrayList();
int index = 0;
@@ -114,8 +120,11 @@ public class DescriptorResolver {
public List<JetType> resolveSupertypes(@NotNull JetScope scope, @NotNull JetClassOrObject jetClass, BindingTrace trace) {
List<JetType> result = Lists.newArrayList();
List<JetDelegationSpecifier> delegationSpecifiers = jetClass.getDelegationSpecifiers();
boolean isEnum = jetClass instanceof JetClass && ((JetClass) jetClass).hasModifier(JetTokens.ENUM_KEYWORD);
if (delegationSpecifiers.isEmpty()) {
result.add(getDefaultSupertype(jetClass, trace));
if (!isEnum) {
result.add(getDefaultSupertype(jetClass, trace));
}
}
else {
Collection<JetType> supertypes = resolveDelegationSpecifiers(
@@ -126,6 +135,19 @@ public class DescriptorResolver {
result.add(supertype);
}
}
if (isEnum) {
boolean hasSuper = false;
for (JetType type : result) {
ClassifierDescriptor descriptor = type.getConstructor().getDeclarationDescriptor();
if (descriptor instanceof ClassDescriptor && ((ClassDescriptor) descriptor).getKind() != ClassKind.TRAIT) {
hasSuper = true;
}
}
if (!hasSuper) {
ClassDescriptor classDescriptor = trace.getBindingContext().get(CLASS, jetClass);
result.add(0, JetStandardLibrary.getInstance().getEnumType(classDescriptor.getDefaultType()));
}
}
return result;
}
@@ -138,14 +160,20 @@ public class DescriptorResolver {
return parentDescriptor.getDefaultType();
}
else {
trace.report(NO_GENERICS_IN_SUPERTYPE_SPECIFIER.on(((JetEnumEntry) jetClass).getNameIdentifier()));
trace.report(NO_GENERICS_IN_SUPERTYPE_SPECIFIER.on(jetClass.getNameIdentifier()));
return ErrorUtils.createErrorType("Supertype not specified");
}
}
return JetStandardClasses.getAnyType();
}
public Collection<JetType> resolveDelegationSpecifiers(JetScope extensibleScope, List<JetDelegationSpecifier> delegationSpecifiers, @NotNull TypeResolver resolver, BindingTrace trace, boolean checkBounds) {
public Collection<JetType> resolveDelegationSpecifiers(
JetScope extensibleScope,
List<JetDelegationSpecifier> delegationSpecifiers,
@NotNull TypeResolver resolver,
BindingTrace trace,
boolean checkBounds
) {
if (delegationSpecifiers.isEmpty()) {
return Collections.emptyList();
}
@@ -178,17 +206,24 @@ public class DescriptorResolver {
}
@NotNull
public SimpleFunctionDescriptor resolveFunctionDescriptor(DeclarationDescriptor containingDescriptor, final JetScope scope, final JetNamedFunction function, final BindingTrace trace) {
public SimpleFunctionDescriptor resolveFunctionDescriptor(
DeclarationDescriptor containingDescriptor,
final JetScope scope,
final JetNamedFunction function,
final BindingTrace trace
) {
final SimpleFunctionDescriptorImpl functionDescriptor = new SimpleFunctionDescriptorImpl(
containingDescriptor,
annotationResolver.resolveAnnotations(scope, function.getModifierList(), trace),
JetPsiUtil.safeName(function.getName()),
CallableMemberDescriptor.Kind.DECLARATION
);
WritableScope innerScope = new WritableScopeImpl(scope, functionDescriptor, new TraceBasedRedeclarationHandler(trace), "Function descriptor header scope");
WritableScope innerScope = new WritableScopeImpl(scope, functionDescriptor, new TraceBasedRedeclarationHandler(trace),
"Function descriptor header scope");
innerScope.addLabeledDeclaration(functionDescriptor);
List<TypeParameterDescriptorImpl> typeParameterDescriptors = resolveTypeParameters(functionDescriptor, innerScope, function.getTypeParameters(), trace);
List<TypeParameterDescriptorImpl> typeParameterDescriptors =
resolveTypeParameters(functionDescriptor, innerScope, function.getTypeParameters(), trace);
innerScope.changeLockLevel(WritableScope.LockLevel.BOTH);
resolveGenericBounds(function, innerScope, typeParameterDescriptors, trace);
@@ -197,12 +232,13 @@ public class DescriptorResolver {
if (receiverTypeRef != null) {
JetScope scopeForReceiver =
function.hasTypeParameterListBeforeFunctionName()
? innerScope
: scope;
? innerScope
: scope;
receiverType = typeResolver.resolveType(scopeForReceiver, receiverTypeRef, trace, true);
}
List<ValueParameterDescriptor> valueParameterDescriptors = resolveValueParameters(functionDescriptor, innerScope, function.getValueParameters(), trace);
List<ValueParameterDescriptor> valueParameterDescriptors =
resolveValueParameters(functionDescriptor, innerScope, function.getValueParameters(), trace);
innerScope.changeLockLevel(WritableScope.LockLevel.READING);
@@ -217,13 +253,14 @@ public class DescriptorResolver {
else {
final JetExpression bodyExpression = function.getBodyExpression();
if (bodyExpression != null) {
returnType = DeferredType.create(trace, new LazyValueWithDefault<JetType>(ErrorUtils.createErrorType("Recursive dependency")) {
@Override
protected JetType compute() {
//JetFlowInformationProvider flowInformationProvider = computeFlowData(function, bodyExpression);
return expressionTypingServices.inferFunctionReturnType(scope, function, functionDescriptor, trace);
}
});
returnType =
DeferredType.create(trace, new LazyValueWithDefault<JetType>(ErrorUtils.createErrorType("Recursive dependency")) {
@Override
protected JetType compute() {
//JetFlowInformationProvider flowInformationProvider = computeFlowData(function, bodyExpression);
return expressionTypingServices.inferFunctionReturnType(scope, function, functionDescriptor, trace);
}
});
}
else {
returnType = ErrorUtils.createErrorType("No type, no body");
@@ -263,7 +300,12 @@ public class DescriptorResolver {
}
@NotNull
private List<ValueParameterDescriptor> resolveValueParameters(FunctionDescriptor functionDescriptor, WritableScope parameterScope, List<JetParameter> valueParameters, BindingTrace trace) {
private List<ValueParameterDescriptor> resolveValueParameters(
FunctionDescriptor functionDescriptor,
WritableScope parameterScope,
List<JetParameter> valueParameters,
BindingTrace trace
) {
List<ValueParameterDescriptor> result = new ArrayList<ValueParameterDescriptor>();
for (int i = 0, valueParametersSize = valueParameters.size(); i < valueParametersSize; i++) {
JetParameter valueParameter = valueParameters.get(i);
@@ -278,7 +320,8 @@ public class DescriptorResolver {
type = typeResolver.resolveType(parameterScope, typeReference, trace, true);
}
ValueParameterDescriptor valueParameterDescriptor = resolveValueParameterDescriptor(parameterScope, functionDescriptor, valueParameter, i, type, trace);
ValueParameterDescriptor valueParameterDescriptor =
resolveValueParameterDescriptor(parameterScope, functionDescriptor, valueParameter, i, type, trace);
parameterScope.addVariableDescriptor(valueParameterDescriptor);
result.add(valueParameterDescriptor);
}
@@ -288,7 +331,8 @@ public class DescriptorResolver {
@NotNull
public MutableValueParameterDescriptor resolveValueParameterDescriptor(
JetScope scope, DeclarationDescriptor declarationDescriptor,
JetParameter valueParameter, int index, JetType type, BindingTrace trace) {
JetParameter valueParameter, int index, JetType type, BindingTrace trace
) {
JetType varargElementType = null;
JetType variableType = type;
if (valueParameter.hasModifier(JetTokens.VARARG_KEYWORD)) {
@@ -320,7 +364,12 @@ public class DescriptorResolver {
}
}
public List<TypeParameterDescriptorImpl> resolveTypeParameters(DeclarationDescriptor containingDescriptor, WritableScope extensibleScope, List<JetTypeParameter> typeParameters, BindingTrace trace) {
public List<TypeParameterDescriptorImpl> resolveTypeParameters(
DeclarationDescriptor containingDescriptor,
WritableScope extensibleScope,
List<JetTypeParameter> typeParameters,
BindingTrace trace
) {
List<TypeParameterDescriptorImpl> result = new ArrayList<TypeParameterDescriptorImpl>();
for (int i = 0, typeParametersSize = typeParameters.size(); i < typeParametersSize; i++) {
JetTypeParameter typeParameter = typeParameters.get(i);
@@ -329,11 +378,17 @@ public class DescriptorResolver {
return result;
}
private TypeParameterDescriptorImpl resolveTypeParameter(DeclarationDescriptor containingDescriptor, WritableScope extensibleScope, JetTypeParameter typeParameter, int index, BindingTrace trace) {
// JetTypeReference extendsBound = typeParameter.getExtendsBound();
// JetType bound = extendsBound == null
// ? JetStandardClasses.getDefaultBound()
// : typeResolver.resolveType(extensibleScope, extendsBound);
private TypeParameterDescriptorImpl resolveTypeParameter(
DeclarationDescriptor containingDescriptor,
WritableScope extensibleScope,
JetTypeParameter typeParameter,
int index,
BindingTrace trace
) {
// JetTypeReference extendsBound = typeParameter.getExtendsBound();
// JetType bound = extendsBound == null
// ? JetStandardClasses.getDefaultBound()
// : typeResolver.resolveType(extensibleScope, extendsBound);
TypeParameterDescriptorImpl typeParameterDescriptor = TypeParameterDescriptorImpl.createForFurtherModification(
containingDescriptor,
annotationResolver.createAnnotationStubs(typeParameter.getModifierList(), trace),
@@ -342,7 +397,7 @@ public class DescriptorResolver {
JetPsiUtil.safeName(typeParameter.getName()),
index
);
// typeParameterDescriptor.addUpperBound(bound);
// typeParameterDescriptor.addUpperBound(bound);
extensibleScope.addTypeParameterDescriptor(typeParameterDescriptor);
trace.record(BindingContext.TYPE_PARAMETER, typeParameter, typeParameterDescriptor);
return typeParameterDescriptor;
@@ -384,7 +439,12 @@ public class DescriptorResolver {
}
}
public void resolveGenericBounds(@NotNull JetTypeParameterListOwner declaration, JetScope scope, List<TypeParameterDescriptorImpl> parameters, BindingTrace trace) {
public void resolveGenericBounds(
@NotNull JetTypeParameterListOwner declaration,
JetScope scope,
List<TypeParameterDescriptorImpl> parameters,
BindingTrace trace
) {
List<UpperBoundCheckerTask> deferredUpperBoundCheckerTasks = Lists.newArrayList();
List<JetTypeParameter> typeParameters = declaration.getTypeParameters();
@@ -416,7 +476,8 @@ public class DescriptorResolver {
JetType bound = null;
if (boundTypeReference != null) {
bound = typeResolver.resolveType(scope, boundTypeReference, trace, false);
deferredUpperBoundCheckerTasks.add(new UpperBoundCheckerTask(boundTypeReference, bound, constraint.isClassObjectContraint()));
deferredUpperBoundCheckerTasks
.add(new UpperBoundCheckerTask(boundTypeReference, bound, constraint.isClassObjectContraint()));
}
if (typeParameterDescriptor == null) {
@@ -469,7 +530,12 @@ public class DescriptorResolver {
}
}
private static void checkUpperBoundType(JetTypeReference upperBound, JetType upperBoundType, boolean isClassObjectConstraint, BindingTrace trace) {
private static void checkUpperBoundType(
JetTypeReference upperBound,
JetType upperBoundType,
boolean isClassObjectConstraint,
BindingTrace trace
) {
if (!TypeUtils.canHaveSubtypes(JetTypeChecker.INSTANCE, upperBoundType)) {
if (isClassObjectConstraint) {
trace.report(FINAL_CLASS_OBJECT_UPPER_BOUND.on(upperBound, upperBoundType));
@@ -481,7 +547,12 @@ public class DescriptorResolver {
}
@NotNull
public VariableDescriptor resolveLocalVariableDescriptor(@NotNull DeclarationDescriptor containingDeclaration, @NotNull JetScope scope, @NotNull JetParameter parameter, BindingTrace trace) {
public VariableDescriptor resolveLocalVariableDescriptor(
@NotNull DeclarationDescriptor containingDeclaration,
@NotNull JetScope scope,
@NotNull JetParameter parameter,
BindingTrace trace
) {
JetType type = resolveParameterType(scope, parameter, trace);
return resolveLocalVariableDescriptor(containingDeclaration, parameter, type, trace);
}
@@ -502,7 +573,12 @@ public class DescriptorResolver {
return type;
}
public VariableDescriptor resolveLocalVariableDescriptor(@NotNull DeclarationDescriptor containingDeclaration, @NotNull JetParameter parameter, @NotNull JetType type, BindingTrace trace) {
public VariableDescriptor resolveLocalVariableDescriptor(
@NotNull DeclarationDescriptor containingDeclaration,
@NotNull JetParameter parameter,
@NotNull JetType type,
BindingTrace trace
) {
VariableDescriptor variableDescriptor = new LocalVariableDescriptor(
containingDeclaration,
annotationResolver.createAnnotationStubs(parameter.getModifierList(), trace),
@@ -514,7 +590,13 @@ public class DescriptorResolver {
}
@NotNull
public VariableDescriptor resolveLocalVariableDescriptor(DeclarationDescriptor containingDeclaration, JetScope scope, JetProperty property, DataFlowInfo dataFlowInfo, BindingTrace trace) {
public VariableDescriptor resolveLocalVariableDescriptor(
DeclarationDescriptor containingDeclaration,
JetScope scope,
JetProperty property,
DataFlowInfo dataFlowInfo,
BindingTrace trace
) {
if (property.isScriptDeclaration()) {
PropertyDescriptor propertyDescriptor = new PropertyDescriptor(
containingDeclaration,
@@ -527,24 +609,31 @@ public class DescriptorResolver {
CallableMemberDescriptor.Kind.DECLARATION
);
JetType type = getVariableType(scope, property, dataFlowInfo, false, trace); // For a local variable the type must not be deferred
JetType type =
getVariableType(scope, property, dataFlowInfo, false, trace); // For a local variable the type must not be deferred
propertyDescriptor.setType(type, Collections.<TypeParameterDescriptor>emptyList(), scope.getImplicitReceiver(), (JetType) null);
trace.record(BindingContext.VARIABLE, property, propertyDescriptor);
return propertyDescriptor;
}
else {
VariableDescriptorImpl variableDescriptor = resolveLocalVariableDescriptorWithType(containingDeclaration, property, null, trace);
VariableDescriptorImpl variableDescriptor =
resolveLocalVariableDescriptorWithType(containingDeclaration, property, null, trace);
JetType type = getVariableType(scope, property, dataFlowInfo, false, trace); // For a local variable the type must not be deferred
JetType type =
getVariableType(scope, property, dataFlowInfo, false, trace); // For a local variable the type must not be deferred
variableDescriptor.setOutType(type);
return variableDescriptor;
}
}
@NotNull
public VariableDescriptorImpl resolveLocalVariableDescriptorWithType(DeclarationDescriptor containingDeclaration, JetProperty property, JetType type, BindingTrace trace) {
public VariableDescriptorImpl resolveLocalVariableDescriptorWithType(
DeclarationDescriptor containingDeclaration,
JetProperty property,
JetType type,
BindingTrace trace
) {
VariableDescriptorImpl variableDescriptor = new LocalVariableDescriptor(
containingDeclaration,
annotationResolver.createAnnotationStubs(property.getModifierList(), trace),
@@ -556,11 +645,13 @@ public class DescriptorResolver {
}
@NotNull
public VariableDescriptor resolveObjectDeclaration(@NotNull DeclarationDescriptor containingDeclaration,
public VariableDescriptor resolveObjectDeclaration(
@NotNull DeclarationDescriptor containingDeclaration,
@NotNull JetClassOrObject objectDeclaration,
@NotNull ClassDescriptor classDescriptor, BindingTrace trace) {
@NotNull ClassDescriptor classDescriptor, BindingTrace trace
) {
boolean isProperty = (containingDeclaration instanceof NamespaceDescriptor)
|| (containingDeclaration instanceof ClassDescriptor);
|| (containingDeclaration instanceof ClassDescriptor);
if (isProperty) {
return resolveObjectDeclarationAsPropertyDescriptor(containingDeclaration, objectDeclaration, classDescriptor, trace);
}
@@ -570,9 +661,11 @@ public class DescriptorResolver {
}
@NotNull
public PropertyDescriptor resolveObjectDeclarationAsPropertyDescriptor(@NotNull DeclarationDescriptor containingDeclaration,
public PropertyDescriptor resolveObjectDeclarationAsPropertyDescriptor(
@NotNull DeclarationDescriptor containingDeclaration,
@NotNull JetClassOrObject objectDeclaration,
@NotNull ClassDescriptor classDescriptor, BindingTrace trace) {
@NotNull ClassDescriptor classDescriptor, BindingTrace trace
) {
JetModifierList modifierList = objectDeclaration.getModifierList();
PropertyDescriptor propertyDescriptor = new PropertyDescriptor(
containingDeclaration,
@@ -584,7 +677,8 @@ public class DescriptorResolver {
JetPsiUtil.safeName(objectDeclaration.getName()),
CallableMemberDescriptor.Kind.DECLARATION
);
propertyDescriptor.setType(classDescriptor.getDefaultType(), Collections.<TypeParameterDescriptor>emptyList(), DescriptorUtils.getExpectedThisObjectIfNeeded(containingDeclaration), ReceiverDescriptor.NO_RECEIVER);
propertyDescriptor.setType(classDescriptor.getDefaultType(), Collections.<TypeParameterDescriptor>emptyList(),
DescriptorUtils.getExpectedThisObjectIfNeeded(containingDeclaration), ReceiverDescriptor.NO_RECEIVER);
propertyDescriptor.initialize(createDefaultGetter(propertyDescriptor), null);
JetObjectDeclarationName nameAsDeclaration = objectDeclaration.getNameAsDeclaration();
if (nameAsDeclaration != null) {
@@ -594,15 +688,17 @@ public class DescriptorResolver {
}
@NotNull
private VariableDescriptor resolveObjectDeclarationAsLocalVariable(@NotNull DeclarationDescriptor containingDeclaration,
private VariableDescriptor resolveObjectDeclarationAsLocalVariable(
@NotNull DeclarationDescriptor containingDeclaration,
@NotNull JetClassOrObject objectDeclaration,
@NotNull ClassDescriptor classDescriptor, BindingTrace trace) {
@NotNull ClassDescriptor classDescriptor, BindingTrace trace
) {
VariableDescriptorImpl variableDescriptor = new LocalVariableDescriptor(
containingDeclaration,
annotationResolver.createAnnotationStubs(objectDeclaration.getModifierList(), trace),
JetPsiUtil.safeName(objectDeclaration.getName()),
classDescriptor.getDefaultType(),
/*isVar =*/ false);
containingDeclaration,
annotationResolver.createAnnotationStubs(objectDeclaration.getModifierList(), trace),
JetPsiUtil.safeName(objectDeclaration.getName()),
classDescriptor.getDefaultType(),
/*isVar =*/ false);
JetObjectDeclarationName nameAsDeclaration = objectDeclaration.getNameAsDeclaration();
if (nameAsDeclaration != null) {
trace.record(BindingContext.VARIABLE, nameAsDeclaration, variableDescriptor);
@@ -610,10 +706,13 @@ public class DescriptorResolver {
return variableDescriptor;
}
public JetScope getPropertyDeclarationInnerScope(@NotNull JetScope outerScope, @NotNull List<? extends TypeParameterDescriptor> typeParameters,
@NotNull ReceiverDescriptor receiver, BindingTrace trace) {
public JetScope getPropertyDeclarationInnerScope(
@NotNull JetScope outerScope, @NotNull List<? extends TypeParameterDescriptor> typeParameters,
@NotNull ReceiverDescriptor receiver, BindingTrace trace
) {
WritableScopeImpl result = new WritableScopeImpl(
outerScope, outerScope.getContainingDeclaration(), new TraceBasedRedeclarationHandler(trace), "Property declaration inner scope");
outerScope, outerScope.getContainingDeclaration(), new TraceBasedRedeclarationHandler(trace),
"Property declaration inner scope");
for (TypeParameterDescriptor typeParameterDescriptor : typeParameters) {
result.addTypeParameterDescriptor(typeParameterDescriptor);
}
@@ -625,7 +724,12 @@ public class DescriptorResolver {
}
@NotNull
public PropertyDescriptor resolvePropertyDescriptor(@NotNull DeclarationDescriptor containingDeclaration, @NotNull JetScope scope, JetProperty property, BindingTrace trace) {
public PropertyDescriptor resolvePropertyDescriptor(
@NotNull DeclarationDescriptor containingDeclaration,
@NotNull JetScope scope,
JetProperty property,
BindingTrace trace
) {
JetModifierList modifierList = property.getModifierList();
boolean isVar = property.isVar();
@@ -655,7 +759,8 @@ public class DescriptorResolver {
}
else {
WritableScope writableScope = new WritableScopeImpl(
scope, containingDeclaration, new TraceBasedRedeclarationHandler(trace), "Scope with type parameters of a property");
scope, containingDeclaration, new TraceBasedRedeclarationHandler(trace),
"Scope with type parameters of a property");
typeParameterDescriptors = resolveTypeParameters(containingDeclaration, writableScope, typeParameters, trace);
writableScope.changeLockLevel(WritableScope.LockLevel.READING);
resolveGenericBounds(property, writableScope, typeParameterDescriptors, trace);
@@ -669,14 +774,15 @@ public class DescriptorResolver {
}
ReceiverDescriptor receiverDescriptor = receiverType == null
? ReceiverDescriptor.NO_RECEIVER
: new ExtensionReceiver(propertyDescriptor, receiverType);
? ReceiverDescriptor.NO_RECEIVER
: new ExtensionReceiver(propertyDescriptor, receiverType);
JetScope propertyScope = getPropertyDeclarationInnerScope(scope, typeParameterDescriptors, ReceiverDescriptor.NO_RECEIVER, trace);
JetType type = getVariableType(propertyScope, property, DataFlowInfo.EMPTY, true, trace);
propertyDescriptor.setType(type, typeParameterDescriptors, DescriptorUtils.getExpectedThisObjectIfNeeded(containingDeclaration), receiverDescriptor);
propertyDescriptor.setType(type, typeParameterDescriptors, DescriptorUtils.getExpectedThisObjectIfNeeded(containingDeclaration),
receiverDescriptor);
PropertyGetterDescriptor getter = resolvePropertyGetterDescriptor(scopeWithTypeParameters, property, propertyDescriptor, trace);
PropertySetterDescriptor setter = resolvePropertySetterDescriptor(scopeWithTypeParameters, property, propertyDescriptor, trace);
@@ -687,7 +793,8 @@ public class DescriptorResolver {
return propertyDescriptor;
}
/*package*/ static boolean hasBody(JetProperty property) {
/*package*/
static boolean hasBody(JetProperty property) {
boolean hasBody = property.getInitializer() != null;
if (!hasBody) {
JetPropertyAccessor getter = property.getGetter();
@@ -703,7 +810,13 @@ public class DescriptorResolver {
}
@NotNull
private JetType getVariableType(@NotNull final JetScope scope, @NotNull final JetProperty property, @NotNull final DataFlowInfo dataFlowInfo, boolean allowDeferred, final BindingTrace trace) {
private JetType getVariableType(
@NotNull final JetScope scope,
@NotNull final JetProperty property,
@NotNull final DataFlowInfo dataFlowInfo,
boolean allowDeferred,
final BindingTrace trace
) {
// TODO : receiver?
JetTypeReference propertyTypeRef = property.getPropertyTypeRef();
@@ -760,7 +873,9 @@ public class DescriptorResolver {
@NotNull
/*package*/ static Visibility resolveVisibilityFromModifiers(@Nullable JetModifierList modifierList) {
Visibility defaultVisibility = modifierList != null && modifierList.hasModifier(JetTokens.OVERRIDE_KEYWORD) ? Visibilities.INHERITED : Visibilities.INTERNAL;
Visibility defaultVisibility = modifierList != null && modifierList.hasModifier(JetTokens.OVERRIDE_KEYWORD)
? Visibilities.INHERITED
: Visibilities.INTERNAL;
return resolveVisibilityFromModifiers(modifierList, defaultVisibility);
}
@@ -775,7 +890,12 @@ public class DescriptorResolver {
}
@Nullable
private PropertySetterDescriptor resolvePropertySetterDescriptor(@NotNull JetScope scope, @NotNull JetProperty property, @NotNull PropertyDescriptor propertyDescriptor, BindingTrace trace) {
private PropertySetterDescriptor resolvePropertySetterDescriptor(
@NotNull JetScope scope,
@NotNull JetProperty property,
@NotNull PropertyDescriptor propertyDescriptor,
BindingTrace trace
) {
JetPropertyAccessor setter = property.getSetter();
PropertySetterDescriptor setterDescriptor = null;
if (setter != null) {
@@ -783,7 +903,8 @@ public class DescriptorResolver {
JetParameter parameter = setter.getParameter();
setterDescriptor = new PropertySetterDescriptor(
propertyDescriptor, annotations, resolveModalityFromModifiers(setter.getModifierList(), propertyDescriptor.getModality()),
propertyDescriptor, annotations,
resolveModalityFromModifiers(setter.getModifierList(), propertyDescriptor.getModality()),
resolveVisibilityFromModifiers(setter.getModifierList(), propertyDescriptor.getVisibility()),
setter.getBodyExpression() != null, false, CallableMemberDescriptor.Kind.DECLARATION);
if (parameter != null) {
@@ -812,7 +933,8 @@ public class DescriptorResolver {
}
}
MutableValueParameterDescriptor valueParameterDescriptor = resolveValueParameterDescriptor(scope, setterDescriptor, parameter, 0, type, trace);
MutableValueParameterDescriptor valueParameterDescriptor =
resolveValueParameterDescriptor(scope, setterDescriptor, parameter, 0, type, trace);
setterDescriptor.initialize(valueParameterDescriptor);
}
else {
@@ -825,9 +947,9 @@ public class DescriptorResolver {
setterDescriptor = createDefaultSetter(propertyDescriptor);
}
if (! property.isVar()) {
if (!property.isVar()) {
if (setter != null) {
// trace.getErrorHandler().genericError(setter.asElement().getNode(), "A 'val'-property cannot have a setter");
// trace.getErrorHandler().genericError(setter.asElement().getNode(), "A 'val'-property cannot have a setter");
trace.report(VAL_WITH_SETTER.on(setter));
}
}
@@ -845,7 +967,12 @@ public class DescriptorResolver {
}
@Nullable
private PropertyGetterDescriptor resolvePropertyGetterDescriptor(@NotNull JetScope scope, @NotNull JetProperty property, @NotNull PropertyDescriptor propertyDescriptor, BindingTrace trace) {
private PropertyGetterDescriptor resolvePropertyGetterDescriptor(
@NotNull JetScope scope,
@NotNull JetProperty property,
@NotNull PropertyDescriptor propertyDescriptor,
BindingTrace trace
) {
PropertyGetterDescriptor getterDescriptor;
JetPropertyAccessor getter = property.getGetter();
if (getter != null) {
@@ -862,7 +989,8 @@ public class DescriptorResolver {
}
getterDescriptor = new PropertyGetterDescriptor(
propertyDescriptor, annotations, resolveModalityFromModifiers(getter.getModifierList(), propertyDescriptor.getModality()),
propertyDescriptor, annotations,
resolveModalityFromModifiers(getter.getModifierList(), propertyDescriptor.getModality()),
resolveVisibilityFromModifiers(getter.getModifierList(), propertyDescriptor.getVisibility()),
getter.getBodyExpression() != null, false, CallableMemberDescriptor.Kind.DECLARATION);
getterDescriptor.initialize(returnType);
@@ -891,7 +1019,8 @@ public class DescriptorResolver {
boolean isPrimary,
@Nullable JetModifierList modifierList,
@NotNull JetDeclaration declarationToTrace,
List<TypeParameterDescriptor> typeParameters, @NotNull List<JetParameter> valueParameters, BindingTrace trace) {
List<TypeParameterDescriptor> typeParameters, @NotNull List<JetParameter> valueParameters, BindingTrace trace
) {
ConstructorDescriptorImpl constructorDescriptor = new ConstructorDescriptorImpl(
classDescriptor,
annotationResolver.resolveAnnotations(scope, modifierList, trace),
@@ -911,7 +1040,12 @@ public class DescriptorResolver {
}
@Nullable
public ConstructorDescriptorImpl resolvePrimaryConstructorDescriptor(@NotNull JetScope scope, @NotNull ClassDescriptor classDescriptor, @NotNull JetClass classElement, BindingTrace trace) {
public ConstructorDescriptorImpl resolvePrimaryConstructorDescriptor(
@NotNull JetScope scope,
@NotNull ClassDescriptor classDescriptor,
@NotNull JetClass classElement,
BindingTrace trace
) {
if (classDescriptor.getKind() == ClassKind.ENUM_ENTRY && !classElement.hasPrimaryConstructor()) return null;
return createConstructorDescriptor(
scope,
@@ -927,7 +1061,8 @@ public class DescriptorResolver {
@NotNull ClassDescriptor classDescriptor,
@NotNull ValueParameterDescriptor valueParameter,
@NotNull JetScope scope,
@NotNull JetParameter parameter, BindingTrace trace) {
@NotNull JetParameter parameter, BindingTrace trace
) {
JetType type = resolveParameterType(scope, parameter, trace);
Name name = parameter.getNameAsName();
boolean isMutable = parameter.isMutable();
@@ -950,7 +1085,8 @@ public class DescriptorResolver {
name == null ? Name.special("<no name>") : name,
CallableMemberDescriptor.Kind.DECLARATION
);
propertyDescriptor.setType(type, Collections.<TypeParameterDescriptor>emptyList(), DescriptorUtils.getExpectedThisObjectIfNeeded(classDescriptor), ReceiverDescriptor.NO_RECEIVER);
propertyDescriptor.setType(type, Collections.<TypeParameterDescriptor>emptyList(),
DescriptorUtils.getExpectedThisObjectIfNeeded(classDescriptor), ReceiverDescriptor.NO_RECEIVER);
PropertyGetterDescriptor getter = createDefaultGetter(propertyDescriptor);
PropertySetterDescriptor setter = propertyDescriptor.isVar() ? createDefaultSetter(propertyDescriptor) : null;
@@ -993,7 +1129,8 @@ public class DescriptorResolver {
@NotNull JetTypeReference jetTypeArgument,
@NotNull JetType typeArgument,
@NotNull TypeParameterDescriptor typeParameterDescriptor,
@NotNull TypeSubstitutor substitutor, BindingTrace trace) {
@NotNull TypeSubstitutor substitutor, BindingTrace trace
) {
for (JetType bound : typeParameterDescriptor.getUpperBounds()) {
JetType substitutedBound = substitutor.safeSubstitute(bound, Variance.INVARIANT);
if (!JetTypeChecker.INSTANCE.isSubtypeOf(typeArgument, substitutedBound)) {
@@ -1001,4 +1138,51 @@ public class DescriptorResolver {
}
}
}
public static SimpleFunctionDescriptor createEnumClassObjectValuesMethod(
final ClassDescriptor mutableClassDescriptor,
ClassDescriptor classObjectDescriptor,
BindingTrace trace
) {
List<AnnotationDescriptor> annotations = Collections.<AnnotationDescriptor>emptyList();
SimpleFunctionDescriptorImpl values =
new SimpleFunctionDescriptorImpl(classObjectDescriptor, annotations,
Name.identifier("values"),
CallableMemberDescriptor.Kind.DECLARATION);
ClassReceiver classReceiver = new ClassReceiver(classObjectDescriptor);
JetType type = DeferredType.create(trace, new LazyValue<JetType>() {
@Override
protected JetType compute() {
return JetStandardLibrary.getInstance().getArrayType(mutableClassDescriptor.getDefaultType());
}
});
values.initialize(null, classReceiver, Collections.<TypeParameterDescriptor>emptyList(),Collections.<ValueParameterDescriptor>emptyList(),
type, Modality.FINAL,
Visibilities.PUBLIC, false);
return values;
}
public static SimpleFunctionDescriptor createEnumClassObjectValueOfMethod(
final ClassDescriptor mutableClassDescriptor,
ClassDescriptor classObjectDescriptor,
BindingTrace trace
) {
List<AnnotationDescriptor> annotations = Collections.<AnnotationDescriptor>emptyList();
SimpleFunctionDescriptorImpl values =
new SimpleFunctionDescriptorImpl(classObjectDescriptor, annotations,
Name.identifier("valueOf"),
CallableMemberDescriptor.Kind.DECLARATION);
ClassReceiver classReceiver = new ClassReceiver(classObjectDescriptor);
JetType type = DeferredType.create(trace, new LazyValue<JetType>() {
@Override
protected JetType compute() {
return mutableClassDescriptor.getDefaultType();
}
});
ValueParameterDescriptorImpl parameterDescriptor = new ValueParameterDescriptorImpl(values,0,Collections.<AnnotationDescriptor>emptyList(),Name.identifier("value"),false,JetStandardLibrary.getInstance().getStringType(),false,null);
values.initialize(null, classReceiver, Collections.<TypeParameterDescriptor>emptyList(),Arrays.<ValueParameterDescriptor>asList(parameterDescriptor),
type, Modality.FINAL,
Visibilities.PUBLIC, false);
return values;
}
}
@@ -24,18 +24,19 @@ import com.intellij.psi.PsiNameIdentifierOwner;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.descriptors.*;
import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor;
import org.jetbrains.jet.lang.psi.*;
import org.jetbrains.jet.lang.resolve.name.Name;
import org.jetbrains.jet.lang.resolve.scopes.JetScope;
import org.jetbrains.jet.lang.resolve.scopes.RedeclarationHandler;
import org.jetbrains.jet.lang.resolve.scopes.WritableScope;
import org.jetbrains.jet.lang.resolve.scopes.WriteThroughScope;
import org.jetbrains.jet.lang.types.JetType;
import org.jetbrains.jet.lang.types.SubstitutionUtils;
import org.jetbrains.jet.lang.types.TypeConstructor;
import org.jetbrains.jet.lang.types.TypeProjection;
import org.jetbrains.jet.lang.resolve.scopes.receivers.ClassReceiver;
import org.jetbrains.jet.lang.types.*;
import org.jetbrains.jet.lang.types.checker.JetTypeChecker;
import org.jetbrains.jet.lang.types.lang.JetStandardLibrary;
import org.jetbrains.jet.lexer.JetTokens;
import org.jetbrains.jet.util.lazy.LazyValue;
import javax.inject.Inject;
import java.util.*;
@@ -94,8 +95,10 @@ public class TypeHierarchyResolver {
this.trace = trace;
}
public void process(@NotNull JetScope outerScope, @NotNull NamespaceLikeBuilder owner,
@NotNull Collection<? extends PsiElement> declarations) {
public void process(
@NotNull JetScope outerScope, @NotNull NamespaceLikeBuilder owner,
@NotNull Collection<? extends PsiElement> declarations
) {
{
// TODO: Very temp code - main goal is to remove recursion from collectNamespacesAndClassifiers
@@ -143,7 +146,7 @@ public class TypeHierarchyResolver {
// At this point, there are no loops in the type hierarchy
checkSupertypesForConsistency();
// computeSuperclasses();
// computeSuperclasses();
checkTypesInClassHeaders(); // Check bounds in the types used in generic bounds and supertype lists
}
@@ -171,11 +174,11 @@ public class TypeHierarchyResolver {
DeclarationDescriptor declaration = classDescriptor.getContainingDeclaration();
if (declaration instanceof NamespaceDescriptorImpl) {
return getStaticScope(declarationElement, ((NamespaceDescriptorImpl)declaration).getBuilder());
return getStaticScope(declarationElement, ((NamespaceDescriptorImpl) declaration).getBuilder());
}
if (declaration instanceof MutableClassDescriptorLite) {
return getStaticScope(declarationElement, ((MutableClassDescriptorLite)declaration).getBuilder());
return getStaticScope(declarationElement, ((MutableClassDescriptorLite) declaration).getBuilder());
}
}
@@ -203,7 +206,7 @@ public class TypeHierarchyResolver {
namespaceScope.changeLockLevel(WritableScope.LockLevel.BOTH);
context.getNamespaceScopes().put(file, namespaceScope);
if(file.isScript()) {
if (file.isScript()) {
scriptHeaderResolver.processScriptHierarchy(file.getScript(), namespaceScope);
}
@@ -268,7 +271,8 @@ public class TypeHierarchyResolver {
public void visitClassObject(JetClassObject classObject) {
JetObjectDeclaration objectDeclaration = classObject.getObjectDeclaration();
if (objectDeclaration != null) {
MutableClassDescriptor classObjectDescriptor = createClassDescriptorForObject(objectDeclaration, owner, getStaticScope(classObject, owner));
MutableClassDescriptor classObjectDescriptor =
createClassDescriptorForObject(objectDeclaration, owner, getStaticScope(classObject, owner));
NamespaceLikeBuilder.ClassObjectStatus status = owner.setClassObjectDescriptor(classObjectDescriptor);
switch (status) {
case DUPLICATE:
@@ -284,22 +288,27 @@ public class TypeHierarchyResolver {
}
}
private void createClassObjectForEnumClass(JetClass klass, MutableClassDescriptor mutableClassDescriptor) {
private void createClassObjectForEnumClass(JetClass klass, final MutableClassDescriptor mutableClassDescriptor) {
if (klass.hasModifier(JetTokens.ENUM_KEYWORD)) {
MutableClassDescriptor classObjectDescriptor = new MutableClassDescriptor(
mutableClassDescriptor, outerScope, ClassKind.OBJECT, Name.special("<class-object-for-" + klass.getName() + ">"));
mutableClassDescriptor, outerScope, ClassKind.OBJECT,
Name.special("<class-object-for-" + klass.getName() + ">"));
classObjectDescriptor.setModality(Modality.FINAL);
classObjectDescriptor.setVisibility(DescriptorResolver.resolveVisibilityFromModifiers(klass.getModifierList()));
classObjectDescriptor.setTypeParameterDescriptors(new ArrayList<TypeParameterDescriptor>(0));
classObjectDescriptor.createTypeConstructor();
ConstructorDescriptorImpl primaryConstructorForObject = createPrimaryConstructorForObject(null, classObjectDescriptor);
ConstructorDescriptorImpl primaryConstructorForObject =
createPrimaryConstructorForObject(null, classObjectDescriptor);
primaryConstructorForObject.setReturnType(classObjectDescriptor.getDefaultType());
classObjectDescriptor.getBuilder().addFunctionDescriptor(DescriptorResolver.createEnumClassObjectValuesMethod(mutableClassDescriptor, classObjectDescriptor, trace));
classObjectDescriptor.getBuilder().addFunctionDescriptor(DescriptorResolver.createEnumClassObjectValueOfMethod(mutableClassDescriptor, classObjectDescriptor,trace));
mutableClassDescriptor.getBuilder().setClassObjectDescriptor(classObjectDescriptor);
}
}
private MutableClassDescriptor createClassDescriptorForObject(
@NotNull JetObjectDeclaration declaration, @NotNull NamespaceLikeBuilder owner, JetScope scope) {
@NotNull JetObjectDeclaration declaration, @NotNull NamespaceLikeBuilder owner, JetScope scope
) {
MutableClassDescriptor mutableClassDescriptor = new MutableClassDescriptor(
owner.getOwnerForChildren(), scope, ClassKind.OBJECT, JetPsiUtil.safeName(declaration.getName()));
context.getObjects().put(declaration, mutableClassDescriptor);
@@ -313,9 +322,13 @@ public class TypeHierarchyResolver {
return mutableClassDescriptor;
}
private MutableClassDescriptor createClassDescriptorForEnumEntry(@NotNull JetEnumEntry declaration, @NotNull NamespaceLikeBuilder owner) {
private MutableClassDescriptor createClassDescriptorForEnumEntry(
@NotNull JetEnumEntry declaration,
@NotNull NamespaceLikeBuilder owner
) {
MutableClassDescriptor mutableClassDescriptor = new MutableClassDescriptor(
owner.getOwnerForChildren(), getStaticScope(declaration, owner), ClassKind.ENUM_ENTRY, JetPsiUtil.safeName(declaration.getName()));
owner.getOwnerForChildren(), getStaticScope(declaration, owner), ClassKind.ENUM_ENTRY,
JetPsiUtil.safeName(declaration.getName()));
context.getClasses().put(declaration, mutableClassDescriptor);
prepareForDeferredCall(mutableClassDescriptor.getScopeForMemberResolution(), mutableClassDescriptor, declaration);
@@ -327,17 +340,21 @@ public class TypeHierarchyResolver {
return mutableClassDescriptor;
}
private ConstructorDescriptorImpl createPrimaryConstructorForObject(@Nullable PsiElement object,
MutableClassDescriptor mutableClassDescriptor) {
private ConstructorDescriptorImpl createPrimaryConstructorForObject(
@Nullable PsiElement object,
MutableClassDescriptor mutableClassDescriptor
) {
ConstructorDescriptorImpl constructorDescriptor = DescriptorResolver
.createPrimaryConstructorForObject(object, mutableClassDescriptor, trace);
mutableClassDescriptor.setPrimaryConstructor(constructorDescriptor, trace);
return constructorDescriptor;
}
private void prepareForDeferredCall(@NotNull JetScope outerScope,
@NotNull WithDeferredResolve withDeferredResolve,
@NotNull JetDeclarationContainer container) {
private void prepareForDeferredCall(
@NotNull JetScope outerScope,
@NotNull WithDeferredResolve withDeferredResolve,
@NotNull JetDeclarationContainer container
) {
forDeferredResolve.add(container);
context.normalScope.put(container, outerScope);
context.forDeferredResolver.put(container, withDeferredResolve);
@@ -413,9 +430,11 @@ public class TypeHierarchyResolver {
}
}
private static void topologicallySort(MutableClassDescriptor mutableClassDescriptor,
Set<ClassDescriptor> visited,
LinkedList<MutableClassDescriptor> topologicalOrder) {
private static void topologicallySort(
MutableClassDescriptor mutableClassDescriptor,
Set<ClassDescriptor> visited,
LinkedList<MutableClassDescriptor> topologicalOrder
) {
if (!visited.add(mutableClassDescriptor)) {
return;
}
@@ -429,10 +448,12 @@ public class TypeHierarchyResolver {
topologicalOrder.addFirst(mutableClassDescriptor);
}
private void traverseTypeHierarchy(MutableClassDescriptor currentClass,
Set<ClassDescriptor> visited,
Set<ClassDescriptor> beingProcessed,
List<ClassDescriptor> currentPath) {
private void traverseTypeHierarchy(
MutableClassDescriptor currentClass,
Set<ClassDescriptor> visited,
Set<ClassDescriptor> beingProcessed,
List<ClassDescriptor> currentPath
) {
if (!visited.add(currentClass)) {
if (beingProcessed.contains(currentClass)) {
markCycleErrors(currentPath, currentClass);
@@ -44,7 +44,7 @@ public abstract class AbstractLazyMemberScope<D extends DeclarationDescriptor, D
private final Map<Name, ClassDescriptor> classDescriptors = Maps.newHashMap();
private final Map<Name, ClassDescriptor> objectDescriptors = Maps.newHashMap();
private final Map<Name, Set<FunctionDescriptor>> functionDescriptors = Maps.newHashMap();
protected final Map<Name, Set<FunctionDescriptor>> functionDescriptors = Maps.newHashMap();
private final Map<Name, Set<VariableDescriptor>> propertyDescriptors = Maps.newHashMap();
protected final List<DeclarationDescriptor> allDescriptors = Lists.newArrayList();
@@ -17,6 +17,7 @@
package org.jetbrains.jet.lang.resolve.lazy;
import com.google.common.collect.Lists;
import com.google.common.collect.Sets;
import com.intellij.psi.PsiElement;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -141,6 +142,26 @@ public class LazyClassMemberScope extends AbstractLazyMemberScope<LazyClassDescr
generateFakeOverrides(name, fromSupertypes, result, FunctionDescriptor.class);
}
private void generateEnumClassObjectMethods() {
DeclarationDescriptor containingDeclaration = thisDescriptor.getContainingDeclaration();
if(containingDeclaration instanceof ClassDescriptor) {
ClassDescriptor classDescriptor = (ClassDescriptor) containingDeclaration;
if(classDescriptor.getKind() == ClassKind.ENUM_CLASS) {
if(classDescriptor.getClassObjectDescriptor() == thisDescriptor) {
SimpleFunctionDescriptor valuesMethod = DescriptorResolver
.createEnumClassObjectValuesMethod(classDescriptor, thisDescriptor, resolveSession.getTrace());
functionDescriptors.put(valuesMethod.getName(), Collections.<FunctionDescriptor>singleton(valuesMethod));
allDescriptors.add(valuesMethod);
SimpleFunctionDescriptor valueOfMethod = DescriptorResolver.createEnumClassObjectValueOfMethod(classDescriptor,
thisDescriptor,
resolveSession.getTrace());
functionDescriptors.put(valueOfMethod.getName(), Collections.<FunctionDescriptor>singleton(valueOfMethod));
allDescriptors.add(valueOfMethod);
}
}
}
}
@NotNull
@Override
public Set<VariableDescriptor> getProperties(@NotNull Name name) {
@@ -226,6 +247,8 @@ public class LazyClassMemberScope extends AbstractLazyMemberScope<LazyClassDescr
// Nothing else is inherited
}
}
generateEnumClassObjectMethods();
}
@Override
@@ -95,6 +95,7 @@ public class JetStandardLibrary {
private ClassDescriptor iterableClass;
private ClassDescriptor comparableClass;
private ClassDescriptor throwableClass;
private ClassDescriptor enumClass;
private JetType stringType;
@@ -115,7 +116,8 @@ public class JetStandardLibrary {
"Ranges.jet",
"Iterables.jet",
"Iterators.jet",
"Arrays.jet"
"Arrays.jet",
"Enum.jet"
);
try {
List<JetFile> files = new LinkedList<JetFile>();
@@ -163,6 +165,7 @@ public class JetStandardLibrary {
this.charSequenceClass = (ClassDescriptor) libraryScope.getClassifier(Name.identifier("CharSequence"));
this.arrayClass = (ClassDescriptor) libraryScope.getClassifier(Name.identifier("Array"));
this.throwableClass = (ClassDescriptor) libraryScope.getClassifier(Name.identifier("Throwable"));
this.enumClass = (ClassDescriptor) libraryScope.getClassifier(Name.identifier("Enum"));
this.iterableClass = (ClassDescriptor) libraryScope.getClassifier(Name.identifier("Iterable"));
this.comparableClass = (ClassDescriptor) libraryScope.getClassifier(Name.identifier("Comparable"));
@@ -208,6 +211,7 @@ public class JetStandardLibrary {
classDescriptors.add(throwableClass);
classDescriptors.add(iterableClass);
classDescriptors.add(comparableClass);
classDescriptors.add(enumClass);
return classDescriptors;
}
@@ -300,6 +304,12 @@ public class JetStandardLibrary {
return throwableClass;
}
@NotNull
public ClassDescriptor getEnum() {
initStdClasses();
return enumClass;
}
@NotNull
public JetType getPrimitiveJetType(PrimitiveType primitiveType) {
return primitiveTypeToJetType.get(primitiveType);
@@ -356,6 +366,11 @@ public class JetStandardLibrary {
return getArrayType(Variance.INVARIANT, argument);
}
@NotNull
public JetType getEnumType(@NotNull JetType argument) {
return getEnumType(Variance.INVARIANT, argument);
}
@NotNull
public JetType getArrayType(@NotNull Variance projectionType, @NotNull JetType argument) {
List<TypeProjection> types = Collections.singletonList(new TypeProjection(projectionType, argument));
@@ -368,6 +383,18 @@ public class JetStandardLibrary {
);
}
@NotNull
public JetType getEnumType(@NotNull Variance projectionType, @NotNull JetType argument) {
List<TypeProjection> types = Collections.singletonList(new TypeProjection(projectionType, argument));
return new JetTypeImpl(
Collections.<AnnotationDescriptor>emptyList(),
getEnum().getTypeConstructor(),
false,
types,
getEnum().getMemberScope(types)
);
}
@NotNull
public JetType getArrayElementType(@NotNull JetType arrayType) {
// make non-null?
@@ -25,6 +25,9 @@ import org.jetbrains.jet.lang.types.ref.ClassName;
*/
public class JetStandardLibraryNames {
private JetStandardLibraryNames() {
}
@NotNull
private static ClassName classIn(@NotNull String name, int typeParameterCount) {
return new ClassName(
@@ -41,5 +44,5 @@ public class JetStandardLibraryNames {
public static final ClassName CHAR_SEQUENCE = classIn("CharSequence", 0);
public static final ClassName NUMBER = classIn("Number", 0);
public static final ClassName THROWABLE = classIn("Throwable", 0);
public static final ClassName ENUM = classIn("Enum", 1);
}
+5
View File
@@ -329,6 +329,11 @@ public final class jet.DoubleRange : jet.Range<jet.Double> {
public final val EMPTY: jet.DoubleRange
}
}
public abstract class jet.Enum</*0*/ E : jet.Enum<E>> : jet.Any {
public final /*constructor*/ fun </*0*/ E : jet.Enum<E>><init>(/*0*/ name: jet.String, /*1*/ ordinal: jet.Int): jet.Enum<E>
public final fun name(): jet.String
public final fun ordinal(): jet.Int
}
public abstract class jet.ExtensionFunction0</*0*/ in T : jet.Any?, /*1*/ out R : jet.Any?> : jet.Any {
public final /*constructor*/ fun </*0*/ in T : jet.Any?, /*1*/ out R : jet.Any?><init>(): jet.ExtensionFunction0<T, R>
public abstract fun T.invoke(): R
+6
View File
@@ -0,0 +1,6 @@
enum class State {
O
K
}
fun box() = "${State.O.name()}${State.K.name()}"
@@ -0,0 +1,8 @@
enum class State {
_0
_1
_2
_3
}
fun box() = if(State._0.ordinal()==0 && State._1.ordinal() == 1 && State._2.ordinal() == 2 && State._3.ordinal() == 3) "OK" else "fail"
@@ -0,0 +1,6 @@
enum class State {
O
K
}
fun box() = "${State.O}${State.K}"
+11
View File
@@ -0,0 +1,11 @@
enum class Color {
RED
BLUE
}
fun box() = if(
Color.valueOf("RED") == Color.RED
&& Color.valueOf("BLUE") == Color.BLUE
&& Color.values()[0] == Color.RED
&& Color.values()[1] == Color.BLUE
) "OK" else "fail"
@@ -8,6 +8,8 @@ trait T {}
class Br(t : T) : T by t {}
open enum class E() {}
open enum class EN() {
A
}
class Test2(e : E) : <!DELEGATION_NOT_TO_TRAIT!>E<!> by e {}
class Test2(e : EN) : <!DELEGATION_NOT_TO_TRAIT!>EN<!> by e {}
@@ -1,19 +1,29 @@
namespace test
internal final enum class test.Test : jet.Any {
internal final enum class test.Test : jet.Enum<test.Test> {
public final /*constructor*/ fun <init>(/*0*/ a: jet.Int): test.Test
public final override /*1*/ fun name(): jet.String
public final override /*1*/ fun ordinal(): jet.Int
internal final class object test.Test.<class-object-for-Test> {
internal final /*constructor*/ fun <init>(): test.Test.<class-object-for-Test>
internal final val A: test.Test.<class-object-for-Test>.A
internal final val C: test.Test.<class-object-for-Test>.C
internal final enum entry test.Test.<class-object-for-Test>.A : test.Test {
internal final /*constructor*/ fun <init>(): test.Test.<class-object-for-Test>.A
public final override /*1*/ fun name(): jet.String
public final override /*1*/ fun ordinal(): jet.Int
}
internal final enum entry test.Test.<class-object-for-Test>.B : test.Test {
public final /*constructor*/ fun <init>(/*0*/ x: jet.Int): test.Test.<class-object-for-Test>.B
public final override /*1*/ fun name(): jet.String
public final override /*1*/ fun ordinal(): jet.Int
}
internal final enum entry test.Test.<class-object-for-Test>.C : test.Test {
internal final /*constructor*/ fun <init>(): test.Test.<class-object-for-Test>.C
public final override /*1*/ fun name(): jet.String
public final override /*1*/ fun ordinal(): jet.Int
}
public final fun valueOf(/*0*/ value: jet.String): test.Test
public final fun values(): jet.Array<test.Test>
}
}
@@ -1,4 +1,4 @@
package test
public class ClassWithTypePRefSelf<P : java.lang.Enum<P>?>() : java.lang.Object() {
public class ClassWithTypePRefSelf<P : jet.Enum<P>?>() : java.lang.Object() {
}
@@ -1,5 +1,5 @@
namespace test
public final class test.ClassWithTypePRefSelf</*0*/ P : java.lang.Enum<P>?> : java.lang.Object {
public final /*constructor*/ fun </*0*/ P : java.lang.Enum<P>?><init>(): test.ClassWithTypePRefSelf<P>
public final class test.ClassWithTypePRefSelf</*0*/ P : jet.Enum<P>?> : java.lang.Object {
public final /*constructor*/ fun </*0*/ P : jet.Enum<P>?><init>(): test.ClassWithTypePRefSelf<P>
}
+1 -1
View File
@@ -5,7 +5,7 @@ private enum class TheEnum(val rgb : Int) {
}
//package rendererTest defined in root package
//private final enum class TheEnum defined in rendererTest
//private final enum class TheEnum : jet.Enum<rendererTest.TheEnum> defined in rendererTest
//value-parameter val rgb : jet.Int defined in rendererTest.TheEnum.<init>
//internal final class VAL1 : rendererTest.TheEnum defined in rendererTest.TheEnum.<class-object-for-TheEnum>
//internal final val VAL1 : rendererTest.TheEnum.<class-object-for-TheEnum>.VAL1 defined in rendererTest.TheEnum.<class-object-for-TheEnum>
@@ -180,7 +180,8 @@ public class JetDiagnosticsTestGenerated extends AbstractDiagnosticsTestWithEage
@TestMetadata("DelegationNotTotrait.kt")
public void testDelegationNotTotrait() throws Exception {
doTest("compiler/testData/diagnostics/tests/DelegationNotTotrait.kt");
// todo FIXME: enable this test
//doTest("compiler/testData/diagnostics/tests/DelegationNotTotrait.kt");
}
@TestMetadata("DiamondFunction.kt")
@@ -18,8 +18,14 @@ package org.jetbrains.jet.codegen;
import org.jetbrains.jet.ConfigurationKind;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
/**
* @author Stepan Koltsov
* @author alex.tkachman
*/
public class EnumGenTest extends CodegenTestCase {
@@ -29,8 +35,41 @@ public class EnumGenTest extends CodegenTestCase {
createEnvironmentWithMockJdkAndIdeaAnnotations(ConfigurationKind.JDK_ONLY);
}
public void testSuperclassIsEnum() throws NoSuchFieldException, IllegalAccessException {
loadFile("enum/simple.kt");
Class season = loadImplementationClass(generateClassesInFile(), "Season");
assertEquals("java.lang.Enum", season.getSuperclass().getName());
}
public void testSimple() {
public void testEnumClassModifiers() throws NoSuchFieldException, IllegalAccessException {
loadFile("enum/simple.kt");
Class season = loadImplementationClass(generateClassesInFile(), "Season");
int modifiers = season.getModifiers();
assertTrue((modifiers & 0x4000) != 0); // ACC_ENUM
assertTrue((modifiers & Modifier.FINAL) != 0);
}
public void testEnumFieldModifiers() throws NoSuchFieldException, IllegalAccessException {
loadFile("enum/simple.kt");
Class season = loadImplementationClass(generateClassesInFile(), "Season");
Field summer = season.getField("SUMMER");
int modifiers = summer.getModifiers();
assertTrue((modifiers & 0x4000) != 0); // ACC_ENUM
assertTrue((modifiers & Modifier.FINAL) != 0);
assertTrue((modifiers & Modifier.STATIC) != 0);
assertTrue((modifiers & Modifier.PUBLIC) != 0);
}
public void testEnumConstantConstructors() throws Exception {
loadText("enum class Color(val rgb: Int) { RED: Color(0xFF0000); GREEN: Color(0x00FF00); }");
final Class colorClass = createClassLoader(generateClassesInFile()).loadClass("Color");
final Field redField = colorClass.getField("RED");
final Object redValue = redField.get(null);
final Method rgbMethod = colorClass.getMethod("getRgb");
assertEquals(0xFF0000, rgbMethod.invoke(redValue));
}
public void testSimple() throws NoSuchFieldException, IllegalAccessException {
blackBoxFile("enum/simple.kt");
}
@@ -38,5 +77,19 @@ public class EnumGenTest extends CodegenTestCase {
blackBoxFile("enum/asReturnExpression.kt");
}
public void testToString() {
blackBoxFile("enum/toString.kt");
}
public void testName() {
blackBoxFile("enum/name.kt");
}
public void testOrdinal() {
blackBoxFile("enum/ordinal.kt");
}
public void testValues() throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, IllegalAccessException {
blackBoxFile("enum/valueof.kt");
}
}
+1 -1
View File
@@ -3,6 +3,6 @@
package testData.libraries
[public final class Color {
[public final enum class Color : jet.Enum<testData.libraries.Color> {
[internal final val rgb : jet.Int] /* compiled code */
}]