Merge branch 'master' of github.com:JetBrains/kotlin

This commit is contained in:
James Strachan
2012-09-21 15:24:02 +01:00
458 changed files with 8450 additions and 5705 deletions
@@ -122,6 +122,8 @@ public class SpecialFiles {
excludedFiles.add("kt1779.kt"); // Bug KT-2202 - private fun tryToComputeNext() in AbstractIterator.kt excludedFiles.add("kt1779.kt"); // Bug KT-2202 - private fun tryToComputeNext() in AbstractIterator.kt
excludedFiles.add("kt344.jet"); // Bug KT-2251 excludedFiles.add("kt344.jet"); // Bug KT-2251
excludedFiles.add("kt529.kt"); // Bug excludedFiles.add("kt529.kt"); // Bug
excludedFiles.add("noClassObjectForJavaClass.kt");
} }
private SpecialFiles() { private SpecialFiles() {
@@ -36,6 +36,7 @@ import org.jetbrains.jet.lang.resolve.scopes.JetScope;
import org.jetbrains.jet.lang.resolve.scopes.JetScopeUtils; import org.jetbrains.jet.lang.resolve.scopes.JetScopeUtils;
import org.jetbrains.jet.lang.resolve.scopes.receivers.ExpressionReceiver; import org.jetbrains.jet.lang.resolve.scopes.receivers.ExpressionReceiver;
import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor; import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor;
import org.jetbrains.jet.lang.types.ErrorUtils;
import org.jetbrains.jet.lang.types.JetType; import org.jetbrains.jet.lang.types.JetType;
import org.jetbrains.jet.lang.types.NamespaceType; import org.jetbrains.jet.lang.types.NamespaceType;
import org.jetbrains.jet.lang.types.expressions.ExpressionTypingUtils; import org.jetbrains.jet.lang.types.expressions.ExpressionTypingUtils;
@@ -61,7 +62,7 @@ public final class TipsManager {
JetScope resolutionScope = context.get(BindingContext.RESOLUTION_SCOPE, expression); JetScope resolutionScope = context.get(BindingContext.RESOLUTION_SCOPE, expression);
JetType expressionType = context.get(BindingContext.EXPRESSION_TYPE, receiverExpression); JetType expressionType = context.get(BindingContext.EXPRESSION_TYPE, receiverExpression);
if (expressionType != null && resolutionScope != null) { if (expressionType != null && resolutionScope != null && !ErrorUtils.isErrorType(expressionType)) {
if (!(expressionType instanceof NamespaceType)) { if (!(expressionType instanceof NamespaceType)) {
ExpressionReceiver receiverDescriptor = new ExpressionReceiver(receiverExpression, expressionType); ExpressionReceiver receiverDescriptor = new ExpressionReceiver(receiverExpression, expressionType);
Set<DeclarationDescriptor> descriptors = new HashSet<DeclarationDescriptor>(); Set<DeclarationDescriptor> descriptors = new HashSet<DeclarationDescriptor>();
@@ -0,0 +1,420 @@
/*
* 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;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Sets;
import com.intellij.openapi.util.Pair;
import com.intellij.psi.tree.IElementType;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.asm4.Label;
import org.jetbrains.asm4.MethodVisitor;
import org.jetbrains.asm4.Type;
import org.jetbrains.asm4.commons.InstructionAdapter;
import org.jetbrains.jet.codegen.binding.CalculatedClosure;
import org.jetbrains.jet.codegen.state.JetTypeMapper;
import org.jetbrains.jet.lang.descriptors.*;
import org.jetbrains.jet.lang.resolve.java.AsmTypeConstants;
import org.jetbrains.jet.lang.resolve.java.JavaDescriptorResolver;
import org.jetbrains.jet.lang.resolve.java.JvmAbi;
import org.jetbrains.jet.lang.resolve.java.JvmPrimitiveType;
import org.jetbrains.jet.lang.types.lang.JetStandardLibrary;
import org.jetbrains.jet.lexer.JetTokens;
import java.util.List;
import java.util.Map;
import java.util.Set;
import static org.jetbrains.asm4.Opcodes.*;
import static org.jetbrains.jet.codegen.CodegenUtil.isInterface;
import static org.jetbrains.jet.lang.resolve.DescriptorUtils.isClassObject;
import static org.jetbrains.jet.lang.resolve.java.AsmTypeConstants.JAVA_STRING_TYPE;
/**
* @author alex.tkachman
*/
public class AsmUtil {
private static final Set<ClassDescriptor> PRIMITIVE_NUMBER_CLASSES = Sets.newHashSet(
JetStandardLibrary.getInstance().getByte(),
JetStandardLibrary.getInstance().getShort(),
JetStandardLibrary.getInstance().getInt(),
JetStandardLibrary.getInstance().getLong(),
JetStandardLibrary.getInstance().getFloat(),
JetStandardLibrary.getInstance().getDouble(),
JetStandardLibrary.getInstance().getChar()
);
private static final int NO_FLAG_LOCAL = 0;
private static final int NO_FLAG_PACKAGE_PRIVATE = 0;
@NotNull
private static final Map<Visibility, Integer> visibilityToAccessFlag = ImmutableMap.<Visibility, Integer>builder()
.put(Visibilities.PRIVATE, ACC_PRIVATE)
.put(Visibilities.PROTECTED, ACC_PROTECTED)
.put(Visibilities.PUBLIC, ACC_PUBLIC)
.put(Visibilities.INTERNAL, ACC_PUBLIC)
.put(Visibilities.LOCAL, NO_FLAG_LOCAL)
.put(JavaDescriptorResolver.PACKAGE_VISIBILITY, NO_FLAG_PACKAGE_PRIVATE)
.build();
public static final String RECEIVER$0 = "receiver$0";
public static final String THIS$0 = "this$0";
private static final String STUB_EXCEPTION = "java/lang/RuntimeException";
private static final String STUB_EXCEPTION_MESSAGE = "Stubs are for compiler only, do not add them to runtime classpath";
private AsmUtil() {
}
public static Type boxType(Type asmType) {
JvmPrimitiveType jvmPrimitiveType = JvmPrimitiveType.getByAsmType(asmType);
if (jvmPrimitiveType != null) {
return jvmPrimitiveType.getWrapper().getAsmType();
}
else {
return asmType;
}
}
public static boolean isIntPrimitive(Type type) {
return type == Type.INT_TYPE || type == Type.SHORT_TYPE || type == Type.BYTE_TYPE || type == Type.CHAR_TYPE;
}
public static boolean isNumberPrimitive(Type type) {
return isIntPrimitive(type) || type == Type.FLOAT_TYPE || type == Type.DOUBLE_TYPE || type == Type.LONG_TYPE;
}
public static boolean isPrimitive(Type type) {
return type.getSort() != Type.OBJECT && type.getSort() != Type.ARRAY;
}
public static boolean isPrimitiveNumberClassDescriptor(DeclarationDescriptor descriptor) {
if (!(descriptor instanceof ClassDescriptor)) {
return false;
}
return PRIMITIVE_NUMBER_CLASSES.contains(descriptor);
}
public static Type correctElementType(Type type) {
String internalName = type.getInternalName();
assert internalName.charAt(0) == '[';
return Type.getType(internalName.substring(1));
}
public static Type unboxType(final Type type) {
JvmPrimitiveType jvmPrimitiveType = JvmPrimitiveType.getByWrapperAsmType(type);
if (jvmPrimitiveType != null) {
return jvmPrimitiveType.getAsmType();
}
else {
throw new UnsupportedOperationException("Unboxing: " + type);
}
}
//TODO: move mapping logic to front-end java
public static int getVisibilityAccessFlag(@NotNull MemberDescriptor descriptor) {
Integer specialCase = specialCaseVisibility(descriptor);
if (specialCase != null) {
return specialCase;
}
Integer defaultMapping = visibilityToAccessFlag.get(descriptor.getVisibility());
if (defaultMapping == null) {
throw new IllegalStateException(descriptor.getVisibility() + " is not a valid visibility in backend.");
}
return defaultMapping;
}
@Nullable
private static Integer specialCaseVisibility(@NotNull MemberDescriptor memberDescriptor) {
DeclarationDescriptor containingDeclaration = memberDescriptor.getContainingDeclaration();
if (isInterface(containingDeclaration)) {
return ACC_PUBLIC;
}
Visibility memberVisibility = memberDescriptor.getVisibility();
if (memberVisibility != Visibilities.PRIVATE) {
return null;
}
if (isClassObject(containingDeclaration)) {
return NO_FLAG_PACKAGE_PRIVATE;
}
if (memberDescriptor instanceof ConstructorDescriptor) {
ClassKind kind = ((ClassDescriptor) containingDeclaration).getKind();
if (kind == ClassKind.OBJECT) {
//TODO: should be NO_FLAG_PACKAGE_PRIVATE
// see http://youtrack.jetbrains.com/issue/KT-2700
return ACC_PUBLIC;
}
else if (kind == ClassKind.ENUM_ENTRY) {
return NO_FLAG_PACKAGE_PRIVATE;
}
else if (kind == ClassKind.ENUM_CLASS) {
//TODO: should be ACC_PRIVATE
// see http://youtrack.jetbrains.com/issue/KT-2680
return ACC_PROTECTED;
}
}
if (containingDeclaration instanceof NamespaceDescriptor) {
return ACC_PUBLIC;
}
return null;
}
private static Type stringValueOfOrStringBuilderAppendType(Type type) {
final int sort = type.getSort();
return sort == Type.OBJECT || sort == Type.ARRAY
? AsmTypeConstants.OBJECT_TYPE
: sort == Type.BYTE || sort == Type.SHORT ? Type.INT_TYPE : type;
}
public static void genThrow(MethodVisitor mv, String exception, String message) {
InstructionAdapter iv = new InstructionAdapter(mv);
iv.anew(Type.getObjectType(exception));
iv.dup();
iv.aconst(message);
iv.invokespecial(exception, "<init>", "(Ljava/lang/String;)V");
iv.athrow();
}
public static void genMethodThrow(MethodVisitor mv, String exception, String message) {
mv.visitCode();
genThrow(mv, exception, message);
mv.visitMaxs(-1, -1);
mv.visitEnd();
}
public static void genClosureFields(CalculatedClosure closure, ClassBuilder v, JetTypeMapper typeMapper) {
final ClassifierDescriptor captureThis = closure.getCaptureThis();
final int access = ACC_PUBLIC | ACC_SYNTHETIC | ACC_FINAL;
if (captureThis != null) {
v.newField(null, access, THIS$0, typeMapper.mapType(captureThis).getDescriptor(), null,
null);
}
final ClassifierDescriptor captureReceiver = closure.getCaptureReceiver();
if (captureReceiver != null) {
v.newField(null, access, RECEIVER$0, typeMapper.mapType(captureReceiver).getDescriptor(),
null, null);
}
final List<Pair<String, Type>> fields = closure.getRecordedFields();
for (Pair<String, Type> field : fields) {
v.newField(null, access, field.first, field.second.getDescriptor(), null, null);
}
}
public static void genInitSingletonField(Type classAsmType, InstructionAdapter iv) {
iv.anew(classAsmType);
iv.dup();
iv.invokespecial(classAsmType.getInternalName(), "<init>", "()V");
iv.putstatic(classAsmType.getInternalName(), JvmAbi.INSTANCE_FIELD, classAsmType.getDescriptor());
}
public static void genStringBuilderConstructor(InstructionAdapter v) {
v.visitTypeInsn(NEW, "java/lang/StringBuilder");
v.dup();
v.invokespecial("java/lang/StringBuilder", "<init>", "()V");
}
public static void genInvokeAppendMethod(InstructionAdapter v, Type type) {
type = stringValueOfOrStringBuilderAppendType(type);
v.invokevirtual("java/lang/StringBuilder", "append", "(" + type.getDescriptor() + ")Ljava/lang/StringBuilder;");
}
public static StackValue genToString(InstructionAdapter v, StackValue receiver) {
final Type type = stringValueOfOrStringBuilderAppendType(receiver.type);
receiver.put(type, v);
v.invokestatic("java/lang/String", "valueOf", "(" + type.getDescriptor() + ")Ljava/lang/String;");
return StackValue.onStack(JAVA_STRING_TYPE);
}
static void genHashCode(MethodVisitor mv, InstructionAdapter iv, Type type) {
if (type.getSort() == Type.ARRAY) {
final Type elementType = correctElementType(type);
if (elementType.getSort() == Type.OBJECT || elementType.getSort() == Type.ARRAY) {
iv.invokestatic("java/util/Arrays", "hashCode", "([Ljava/lang/Object;)I");
}
else {
iv.invokestatic("java/util/Arrays", "hashCode", "(" + type.getDescriptor() + ")I");
}
}
else if (type.getSort() == Type.OBJECT) {
iv.invokevirtual("java/lang/Object", "hashCode", "()I");
}
else if (type.getSort() == Type.LONG) {
genLongHashCode(mv, iv);
}
else if (type.getSort() == Type.DOUBLE) {
iv.invokestatic("java/lang/Double", "doubleToLongBits", "(D)J");
genLongHashCode(mv, iv);
}
else if (type.getSort() == Type.FLOAT) {
iv.invokestatic("java/lang/Float", "floatToIntBits", "(F)I");
}
else if (type.getSort() == Type.BOOLEAN) {
Label end = new Label();
iv.dup();
iv.ifeq(end);
iv.pop();
iv.iconst(1);
iv.mark(end);
}
else { // byte short char int
// do nothing
}
}
private static void genLongHashCode(MethodVisitor mv, InstructionAdapter iv) {
iv.dup2();
iv.iconst(32);
iv.ushr(Type.LONG_TYPE);
iv.xor(Type.LONG_TYPE);
mv.visitInsn(L2I);
}
static StackValue compareExpressionsOnStack(InstructionAdapter v, IElementType opToken, Type operandType) {
if (operandType.getSort() == Type.OBJECT) {
v.invokeinterface("java/lang/Comparable", "compareTo", "(Ljava/lang/Object;)I");
v.iconst(0);
operandType = Type.INT_TYPE;
}
return StackValue.cmp(opToken, operandType);
}
static StackValue genNullSafeEquals(
InstructionAdapter v,
IElementType opToken,
boolean leftNullable,
boolean rightNullable
) {
if (!leftNullable) {
v.invokevirtual("java/lang/Object", "equals", "(Ljava/lang/Object;)Z");
if (opToken == JetTokens.EXCLEQ) {
genInvertBoolean(v);
}
}
else {
if (rightNullable) {
v.dup2(); // left right left right
Label rightNull = new Label();
v.ifnull(rightNull);
Label leftNull = new Label();
v.ifnull(leftNull);
v.invokevirtual("java/lang/Object", "equals", "(Ljava/lang/Object;)Z");
if (opToken == JetTokens.EXCLEQ || opToken == JetTokens.EXCLEQEQEQ) {
genInvertBoolean(v);
}
Label end = new Label();
v.goTo(end);
v.mark(rightNull);
// left right left
Label bothNull = new Label();
v.ifnull(bothNull);
v.mark(leftNull);
v.pop2();
v.iconst(opToken == JetTokens.EXCLEQ || opToken == JetTokens.EXCLEQEQEQ ? 1 : 0);
v.goTo(end);
v.mark(bothNull);
v.pop2();
v.iconst(opToken == JetTokens.EXCLEQ || opToken == JetTokens.EXCLEQEQEQ ? 0 : 1);
v.mark(end);
}
else {
v.dup2(); // left right left right
v.pop();
Label leftNull = new Label();
v.ifnull(leftNull);
v.invokevirtual("java/lang/Object", "equals", "(Ljava/lang/Object;)Z");
if (opToken == JetTokens.EXCLEQ || opToken == JetTokens.EXCLEQEQEQ) {
genInvertBoolean(v);
}
Label end = new Label();
v.goTo(end);
// left right
v.mark(leftNull);
v.pop2();
v.iconst(opToken == JetTokens.EXCLEQ ? 1 : 0);
v.mark(end);
}
}
return StackValue.onStack(Type.BOOLEAN_TYPE);
}
static void genInvertBoolean(InstructionAdapter v) {
v.iconst(1);
v.xor(Type.INT_TYPE);
}
public static StackValue genEqualsForExpressionsOnStack(
InstructionAdapter v,
IElementType opToken,
Type leftType,
Type rightType,
boolean leftNullable,
boolean rightNullable
) {
if ((isNumberPrimitive(leftType) || leftType.getSort() == Type.BOOLEAN) && leftType == rightType) {
return compareExpressionsOnStack(v, opToken, leftType);
}
else {
if (opToken == JetTokens.EQEQEQ || opToken == JetTokens.EXCLEQEQEQ) {
return StackValue.cmp(opToken, leftType);
}
else {
return genNullSafeEquals(v, opToken, leftNullable, rightNullable);
}
}
}
public static Type genIncrement(Type expectedType, int myDelta, InstructionAdapter v) {
if (expectedType == Type.LONG_TYPE) {
//noinspection UnnecessaryBoxing
v.lconst(myDelta);
}
else if (expectedType == Type.FLOAT_TYPE) {
//noinspection UnnecessaryBoxing
v.fconst(myDelta);
}
else if (expectedType == Type.DOUBLE_TYPE) {
//noinspection UnnecessaryBoxing
v.dconst(myDelta);
}
else {
v.iconst(myDelta);
expectedType = Type.INT_TYPE;
}
v.add(expectedType);
return expectedType;
}
public static Type genNegate(Type expectedType, InstructionAdapter v) {
if (expectedType == Type.BYTE_TYPE || expectedType == Type.SHORT_TYPE || expectedType == Type.CHAR_TYPE) {
expectedType = Type.INT_TYPE;
}
v.neg(expectedType);
return expectedType;
}
public static void genStubThrow(MethodVisitor mv) {
genThrow(mv, STUB_EXCEPTION, STUB_EXCEPTION_MESSAGE);
}
public static void genStubCode(MethodVisitor mv) {
genMethodThrow(mv, STUB_EXCEPTION, STUB_EXCEPTION_MESSAGE);
}
}
@@ -22,7 +22,6 @@ import org.jetbrains.asm4.Type;
import org.jetbrains.asm4.commons.InstructionAdapter; import org.jetbrains.asm4.commons.InstructionAdapter;
import org.jetbrains.jet.codegen.context.CodegenContext; import org.jetbrains.jet.codegen.context.CodegenContext;
import org.jetbrains.jet.codegen.state.GenerationState; import org.jetbrains.jet.codegen.state.GenerationState;
import org.jetbrains.jet.codegen.state.GenerationStateAware;
import org.jetbrains.jet.lang.descriptors.ClassDescriptor; import org.jetbrains.jet.lang.descriptors.ClassDescriptor;
import org.jetbrains.jet.lang.descriptors.PropertyDescriptor; import org.jetbrains.jet.lang.descriptors.PropertyDescriptor;
import org.jetbrains.jet.lang.psi.*; import org.jetbrains.jet.lang.psi.*;
@@ -34,14 +33,14 @@ import java.util.Collections;
import java.util.List; import java.util.List;
import static org.jetbrains.asm4.Opcodes.*; import static org.jetbrains.asm4.Opcodes.*;
import static org.jetbrains.jet.codegen.CodegenUtil.generateMethodThrow; import static org.jetbrains.jet.codegen.AsmUtil.genMethodThrow;
import static org.jetbrains.jet.codegen.CodegenUtil.getVisibilityAccessFlag; import static org.jetbrains.jet.codegen.AsmUtil.getVisibilityAccessFlag;
/** /**
* @author max * @author max
* @author yole * @author yole
*/ */
public abstract class ClassBodyCodegen extends GenerationStateAware { public abstract class ClassBodyCodegen extends MemberCodegen {
protected final JetClassOrObject myClass; protected final JetClassOrObject myClass;
protected final OwnerKind kind; protected final OwnerKind kind;
protected final ClassDescriptor descriptor; protected final ClassDescriptor descriptor;
@@ -89,7 +88,7 @@ public abstract class ClassBodyCodegen extends GenerationStateAware {
protected void generateDeclaration(PropertyCodegen propertyCodegen, JetDeclaration declaration, FunctionCodegen functionCodegen) { protected void generateDeclaration(PropertyCodegen propertyCodegen, JetDeclaration declaration, FunctionCodegen functionCodegen) {
if (declaration instanceof JetProperty || declaration instanceof JetNamedFunction) { if (declaration instanceof JetProperty || declaration instanceof JetNamedFunction) {
state.getMemberCodegen().generateFunctionOrProperty((JetTypeParameterListOwner) declaration, context, v); genFunctionOrProperty(context, (JetTypeParameterListOwner) declaration, v);
} }
} }
@@ -146,7 +145,7 @@ public abstract class ClassBodyCodegen extends GenerationStateAware {
// generates stub 'remove' function for subclasses of Iterator to be compatible with java.util.Iterator // generates stub 'remove' function for subclasses of Iterator to be compatible with java.util.Iterator
if (DescriptorUtils.isIteratorWithoutRemoveImpl(descriptor)) { if (DescriptorUtils.isIteratorWithoutRemoveImpl(descriptor)) {
final MethodVisitor mv = v.getVisitor().visitMethod(ACC_PUBLIC, "remove", "()V", null, null); final MethodVisitor mv = v.getVisitor().visitMethod(ACC_PUBLIC, "remove", "()V", null, null);
generateMethodThrow(mv, "java/lang/UnsupportedOperationException", "Mutating method called on a Kotlin Iterator"); genMethodThrow(mv, "java/lang/UnsupportedOperationException", "Mutating method called on a Kotlin Iterator");
} }
} }
} }
@@ -1,108 +0,0 @@
/*
* 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;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.codegen.context.CodegenContext;
import org.jetbrains.jet.codegen.state.GenerationState;
import org.jetbrains.jet.codegen.state.GenerationStateAware;
import org.jetbrains.jet.lang.descriptors.ClassDescriptor;
import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor;
import org.jetbrains.jet.lang.psi.*;
import org.jetbrains.jet.lang.resolve.BindingContext;
import org.jetbrains.jet.lang.types.ErrorUtils;
import java.util.Map;
import static org.jetbrains.jet.codegen.binding.CodegenBinding.enumEntryNeedSubclass;
/**
* @author max
* @author alex.tkachman
*/
public class ClassCodegen extends GenerationStateAware {
public ClassCodegen(@NotNull GenerationState state) {
super(state);
}
public void generate(CodegenContext context, JetClassOrObject aClass) {
ClassDescriptor descriptor = state.getBindingContext().get(BindingContext.CLASS, aClass);
if (descriptor == null || ErrorUtils.isError(descriptor) || descriptor.getName().equals(JetPsiUtil.NO_NAME_PROVIDED)) {
if (state.getClassBuilderMode() != ClassBuilderMode.SIGNATURES) {
throw new IllegalStateException(
"Generating bad descriptor in ClassBuilderMode = " + state.getClassBuilderMode() + ": " + descriptor);
}
return;
}
ClassBuilder classBuilder = state.getFactory().forClassImplementation(descriptor);
final CodegenContext contextForInners = context.intoClass(descriptor, OwnerKind.IMPLEMENTATION, state);
if (state.getClassBuilderMode() == ClassBuilderMode.SIGNATURES) {
// Outer class implementation must happen prior inner classes so we get proper scoping tree in JetLightClass's delegate
// The same code is present below for the case when we generate real bytecode. This is because the order should be
// different for the case when we compute closures
generateImplementation(context, aClass, OwnerKind.IMPLEMENTATION, contextForInners.getAccessors(), classBuilder);
}
for (JetDeclaration declaration : aClass.getDeclarations()) {
if (declaration instanceof JetClass) {
if (declaration instanceof JetEnumEntry && !enumEntryNeedSubclass(
state.getBindingContext(), (JetEnumEntry) declaration)) {
continue;
}
generate(contextForInners, (JetClass) declaration);
}
else if (declaration instanceof JetClassObject) {
generate(contextForInners, ((JetClassObject) declaration).getObjectDeclaration());
}
else if (declaration instanceof JetObjectDeclaration) {
generate(contextForInners, (JetObjectDeclaration) declaration);
}
}
if (state.getClassBuilderMode() != ClassBuilderMode.SIGNATURES) {
generateImplementation(context, aClass, OwnerKind.IMPLEMENTATION, contextForInners.getAccessors(), classBuilder);
}
classBuilder.done();
}
private void generateImplementation(
CodegenContext context,
JetClassOrObject aClass,
OwnerKind kind,
Map<DeclarationDescriptor, DeclarationDescriptor> accessors,
ClassBuilder classBuilder
) {
ClassDescriptor descriptor = state.getBindingContext().get(BindingContext.CLASS, aClass);
CodegenContext classContext = context.intoClass(descriptor, kind, state);
classContext.copyAccessors(accessors);
new ImplementationBodyCodegen(aClass, classContext, classBuilder, state).generate();
if (aClass instanceof JetClass && ((JetClass) aClass).isTrait()) {
ClassBuilder traitBuilder = state.getFactory().forTraitImplementation(descriptor, state);
new TraitImplBodyCodegen(aClass, context.intoClass(descriptor, OwnerKind.TRAIT_IMPL, state), traitBuilder, state)
.generate();
traitBuilder.done();
}
}
}
@@ -28,6 +28,8 @@ import org.jetbrains.jet.lang.resolve.name.FqName;
import javax.inject.Inject; import javax.inject.Inject;
import java.util.*; import java.util.*;
import static org.jetbrains.jet.codegen.AsmUtil.isPrimitive;
/** /**
* @author max * @author max
* @author alex.tkachman * @author alex.tkachman
@@ -114,7 +116,7 @@ public final class ClassFileFactory extends GenerationStateAware {
public ClassBuilder forClassImplementation(ClassDescriptor aClass) { public ClassBuilder forClassImplementation(ClassDescriptor aClass) {
Type type = state.getTypeMapper().mapType(aClass.getDefaultType(), JetTypeMapperMode.IMPL); Type type = state.getTypeMapper().mapType(aClass.getDefaultType(), JetTypeMapperMode.IMPL);
if (CodegenUtil.isPrimitive(type)) { if (isPrimitive(type)) {
throw new IllegalStateException("Codegen for primitive type is not possible: " + aClass); throw new IllegalStateException("Codegen for primitive type is not possible: " + aClass);
} }
return newVisitor(type.getInternalName() + ".class"); return newVisitor(type.getInternalName() + ".class");
@@ -49,6 +49,7 @@ import java.util.ArrayList;
import java.util.List; import java.util.List;
import static org.jetbrains.asm4.Opcodes.*; import static org.jetbrains.asm4.Opcodes.*;
import static org.jetbrains.jet.codegen.AsmUtil.*;
import static org.jetbrains.jet.codegen.CodegenUtil.*; import static org.jetbrains.jet.codegen.CodegenUtil.*;
import static org.jetbrains.jet.codegen.binding.CodegenBinding.classNameForAnonymousClass; import static org.jetbrains.jet.codegen.binding.CodegenBinding.classNameForAnonymousClass;
import static org.jetbrains.jet.codegen.binding.CodegenBinding.isLocalNamedFun; import static org.jetbrains.jet.codegen.binding.CodegenBinding.isLocalNamedFun;
@@ -108,7 +109,7 @@ public class ClosureCodegen extends GenerationStateAware {
generateConstInstance(fun, cv); generateConstInstance(fun, cv);
} }
generateClosureFields(closure, cv, state.getTypeMapper()); genClosureFields(closure, cv, state.getTypeMapper());
cv.done(); cv.done();
@@ -122,11 +123,11 @@ public class ClosureCodegen extends GenerationStateAware {
cv.newField(fun, ACC_PUBLIC | ACC_STATIC | ACC_FINAL, JvmAbi.INSTANCE_FIELD, name.getDescriptor(), null, null); cv.newField(fun, ACC_PUBLIC | ACC_STATIC | ACC_FINAL, JvmAbi.INSTANCE_FIELD, name.getDescriptor(), null, null);
if (state.getClassBuilderMode() == ClassBuilderMode.STUBS) { if (state.getClassBuilderMode() == ClassBuilderMode.STUBS) {
StubCodegen.generateStubCode(mv); genStubCode(mv);
} }
else if (state.getClassBuilderMode() == ClassBuilderMode.FULL) { else if (state.getClassBuilderMode() == ClassBuilderMode.FULL) {
mv.visitCode(); mv.visitCode();
initSingletonField(fun, name.getAsmType(), cv, iv); genInitSingletonField(name.getAsmType(), iv);
mv.visitInsn(RETURN); mv.visitInsn(RETURN);
FunctionCodegen.endVisit(mv, "<clinit>", fun); FunctionCodegen.endVisit(mv, "<clinit>", fun);
} }
@@ -164,7 +165,7 @@ public class ClosureCodegen extends GenerationStateAware {
cv.newMethod(fun, ACC_PUBLIC | ACC_BRIDGE | ACC_VOLATILE, "invoke", bridge.getAsmMethod().getDescriptor(), null, cv.newMethod(fun, ACC_PUBLIC | ACC_BRIDGE | ACC_VOLATILE, "invoke", bridge.getAsmMethod().getDescriptor(), null,
new String[0]); new String[0]);
if (state.getClassBuilderMode() == ClassBuilderMode.STUBS) { if (state.getClassBuilderMode() == ClassBuilderMode.STUBS) {
StubCodegen.generateStubCode(mv); genStubCode(mv);
} }
if (state.getClassBuilderMode() == ClassBuilderMode.FULL) { if (state.getClassBuilderMode() == ClassBuilderMode.FULL) {
mv.visitCode(); mv.visitCode();
@@ -212,7 +213,7 @@ public class ClosureCodegen extends GenerationStateAware {
final Method constructor = new Method("<init>", Type.VOID_TYPE, argTypes); final Method constructor = new Method("<init>", Type.VOID_TYPE, argTypes);
final MethodVisitor mv = cv.newMethod(fun, ACC_PUBLIC, "<init>", constructor.getDescriptor(), null, new String[0]); final MethodVisitor mv = cv.newMethod(fun, ACC_PUBLIC, "<init>", constructor.getDescriptor(), null, new String[0]);
if (state.getClassBuilderMode() == ClassBuilderMode.STUBS) { if (state.getClassBuilderMode() == ClassBuilderMode.STUBS) {
StubCodegen.generateStubCode(mv); genStubCode(mv);
} }
else if (state.getClassBuilderMode() == ClassBuilderMode.FULL) { else if (state.getClassBuilderMode() == ClassBuilderMode.FULL) {
mv.visitCode(); mv.visitCode();
@@ -16,70 +16,36 @@
package org.jetbrains.jet.codegen; package org.jetbrains.jet.codegen;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Sets;
import com.intellij.openapi.util.Pair;
import com.intellij.psi.PsiElement; import com.intellij.psi.PsiElement;
import com.intellij.util.containers.Stack; import com.intellij.util.containers.Stack;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import org.jetbrains.asm4.MethodVisitor;
import org.jetbrains.asm4.Type;
import org.jetbrains.asm4.commons.InstructionAdapter;
import org.jetbrains.asm4.commons.Method;
import org.jetbrains.jet.codegen.binding.CalculatedClosure; import org.jetbrains.jet.codegen.binding.CalculatedClosure;
import org.jetbrains.jet.codegen.signature.BothSignatureWriter; import org.jetbrains.jet.codegen.signature.BothSignatureWriter;
import org.jetbrains.jet.codegen.signature.JvmMethodParameterKind; import org.jetbrains.jet.codegen.signature.JvmMethodParameterKind;
import org.jetbrains.jet.codegen.signature.JvmMethodSignature; import org.jetbrains.jet.codegen.signature.JvmMethodSignature;
import org.jetbrains.jet.codegen.state.JetTypeMapper;
import org.jetbrains.jet.lang.descriptors.*; import org.jetbrains.jet.lang.descriptors.*;
import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor; import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor;
import org.jetbrains.jet.lang.psi.JetClassObject; import org.jetbrains.jet.lang.psi.JetClassObject;
import org.jetbrains.jet.lang.psi.JetClassOrObject; import org.jetbrains.jet.lang.psi.JetClassOrObject;
import org.jetbrains.jet.lang.psi.JetObjectDeclaration; import org.jetbrains.jet.lang.psi.JetObjectDeclaration;
import org.jetbrains.jet.lang.resolve.DescriptorUtils; import org.jetbrains.jet.lang.resolve.DescriptorUtils;
import org.jetbrains.jet.lang.resolve.java.*; 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.resolve.name.Name; import org.jetbrains.jet.lang.resolve.name.Name;
import org.jetbrains.jet.lang.types.JetType; import org.jetbrains.jet.lang.types.JetType;
import org.jetbrains.jet.lang.types.lang.JetStandardClasses; import org.jetbrains.jet.lang.types.lang.JetStandardClasses;
import org.jetbrains.jet.lang.types.lang.JetStandardLibrary;
import java.util.*; import java.util.*;
import static org.jetbrains.asm4.Opcodes.*; import static org.jetbrains.jet.lang.resolve.java.AsmTypeConstants.OBJECT_TYPE;
import static org.jetbrains.jet.lang.resolve.DescriptorUtils.isClassObject;
import static org.jetbrains.jet.lang.resolve.java.AsmTypeConstants.*;
/** /**
* @author abreslav * @author abreslav
* @author alex.tkachman * @author alex.tkachman
*/ */
public class CodegenUtil { public class CodegenUtil {
public static final String RECEIVER$0 = "receiver$0";
public static final String THIS$0 = "this$0";
private static final int NO_FLAG_LOCAL = 0;
private static final int NO_FLAG_PACKAGE_PRIVATE = 0;
@NotNull
private static final Map<Visibility, Integer> visibilityToAccessFlag = ImmutableMap.<Visibility, Integer>builder()
.put(Visibilities.PRIVATE, ACC_PRIVATE)
.put(Visibilities.PROTECTED, ACC_PROTECTED)
.put(Visibilities.PUBLIC, ACC_PUBLIC)
.put(Visibilities.INTERNAL, ACC_PUBLIC)
.put(Visibilities.LOCAL, NO_FLAG_LOCAL)
.put(JavaDescriptorResolver.PACKAGE_VISIBILITY, NO_FLAG_PACKAGE_PRIVATE)
.build();
private static final Set<ClassDescriptor> PRIMITIVE_NUMBER_CLASSES = Sets.newHashSet(
JetStandardLibrary.getInstance().getByte(),
JetStandardLibrary.getInstance().getShort(),
JetStandardLibrary.getInstance().getInt(),
JetStandardLibrary.getInstance().getLong(),
JetStandardLibrary.getInstance().getFloat(),
JetStandardLibrary.getInstance().getDouble(),
JetStandardLibrary.getInstance().getChar()
);
private CodegenUtil() { private CodegenUtil() {
} }
@@ -124,7 +90,7 @@ public class CodegenUtil {
} }
public static String generateTmpVariableName(Collection<String> existingNames) { public static String createTmpVariableName(Collection<String> existingNames) {
String prefix = "tmp"; String prefix = "tmp";
int i = RANDOM.nextInt(Integer.MAX_VALUE); int i = RANDOM.nextInt(Integer.MAX_VALUE);
String name = prefix + i; String name = prefix + i;
@@ -136,9 +102,8 @@ public class CodegenUtil {
} }
public static
@NotNull @NotNull
BitSet getFlagsForVisibility(@NotNull Visibility visibility) { public static BitSet getFlagsForVisibility(@NotNull Visibility visibility) {
BitSet flags = new BitSet(); BitSet flags = new BitSet();
if (visibility == Visibilities.INTERNAL) { if (visibility == Visibilities.INTERNAL) {
flags.set(JvmStdlibNames.FLAG_INTERNAL_BIT); flags.set(JvmStdlibNames.FLAG_INTERNAL_BIT);
@@ -149,22 +114,6 @@ public class CodegenUtil {
return flags; return flags;
} }
public static void generateThrow(MethodVisitor mv, String exception, String message) {
InstructionAdapter iv = new InstructionAdapter(mv);
iv.anew(Type.getObjectType(exception));
iv.dup();
iv.aconst(message);
iv.invokespecial(exception, "<init>", "(Ljava/lang/String;)V");
iv.athrow();
}
public static void generateMethodThrow(MethodVisitor mv, String exception, String message) {
mv.visitCode();
generateThrow(mv, exception, message);
mv.visitMaxs(-1, -1);
mv.visitEnd();
}
@NotNull @NotNull
public static JvmClassName getInternalClassName(FunctionDescriptor descriptor) { public static JvmClassName getInternalClassName(FunctionDescriptor descriptor) {
final int paramCount = descriptor.getValueParameters().size(); final int paramCount = descriptor.getValueParameters().size();
@@ -210,123 +159,10 @@ public class CodegenUtil {
return closure.getCaptureThis() == null && closure.getCaptureReceiver() == null && closure.getCaptureVariables().isEmpty(); return closure.getCaptureThis() == null && closure.getCaptureReceiver() == null && closure.getCaptureVariables().isEmpty();
} }
public static void generateClosureFields(CalculatedClosure closure, ClassBuilder v, JetTypeMapper typeMapper) {
final ClassifierDescriptor captureThis = closure.getCaptureThis();
final int access = ACC_PUBLIC | ACC_SYNTHETIC | ACC_FINAL;
if (captureThis != null) {
v.newField(null, access, THIS$0, typeMapper.mapType(captureThis).getDescriptor(), null,
null);
}
final ClassifierDescriptor captureReceiver = closure.getCaptureReceiver();
if (captureReceiver != null) {
v.newField(null, access, RECEIVER$0, typeMapper.mapType(captureReceiver).getDescriptor(),
null, null);
}
final List<Pair<String, Type>> fields = closure.getRecordedFields();
for (Pair<String, Type> field : fields) {
v.newField(null, access, field.first, field.second.getDescriptor(), null, null);
}
}
public static <T> T peekFromStack(Stack<T> stack) { public static <T> T peekFromStack(Stack<T> stack) {
return stack.empty() ? null : stack.peek(); return stack.empty() ? null : stack.peek();
} }
//TODO: move mapping logic to front-end java
public static int getVisibilityAccessFlag(@NotNull MemberDescriptor descriptor) {
Integer specialCase = specialCaseVisibility(descriptor);
if (specialCase != null) {
return specialCase;
}
Integer defaultMapping = visibilityToAccessFlag.get(descriptor.getVisibility());
if (defaultMapping == null) {
throw new IllegalStateException(descriptor.getVisibility() + " is not a valid visibility in backend.");
}
return defaultMapping;
}
@Nullable
private static Integer specialCaseVisibility(@NotNull MemberDescriptor memberDescriptor) {
DeclarationDescriptor containingDeclaration = memberDescriptor.getContainingDeclaration();
if (isInterface(containingDeclaration)) {
return ACC_PUBLIC;
}
Visibility memberVisibility = memberDescriptor.getVisibility();
if (memberVisibility != Visibilities.PRIVATE) {
return null;
}
if (isClassObject(containingDeclaration)) {
return NO_FLAG_PACKAGE_PRIVATE;
}
if (memberDescriptor instanceof ConstructorDescriptor) {
ClassKind kind = ((ClassDescriptor) containingDeclaration).getKind();
if (kind == ClassKind.OBJECT) {
//TODO: should be NO_FLAG_PACKAGE_PRIVATE
// see http://youtrack.jetbrains.com/issue/KT-2700
return ACC_PUBLIC;
}
else if (kind == ClassKind.ENUM_ENTRY) {
return NO_FLAG_PACKAGE_PRIVATE;
}
else if (kind == ClassKind.ENUM_CLASS) {
//TODO: should be ACC_PRIVATE
// see http://youtrack.jetbrains.com/issue/KT-2680
return ACC_PROTECTED;
}
}
if (containingDeclaration instanceof NamespaceDescriptor) {
return ACC_PUBLIC;
}
return null;
}
public static Type unboxType(final Type type) {
JvmPrimitiveType jvmPrimitiveType = JvmPrimitiveType.getByWrapperAsmType(type);
if (jvmPrimitiveType != null) {
return jvmPrimitiveType.getAsmType();
}
else {
throw new UnsupportedOperationException("Unboxing: " + type);
}
}
public static Type boxType(Type asmType) {
JvmPrimitiveType jvmPrimitiveType = JvmPrimitiveType.getByAsmType(asmType);
if (jvmPrimitiveType != null) {
return jvmPrimitiveType.getWrapper().getAsmType();
}
else {
return asmType;
}
}
public static boolean isIntPrimitive(Type type) {
return type == Type.INT_TYPE || type == Type.SHORT_TYPE || type == Type.BYTE_TYPE || type == Type.CHAR_TYPE;
}
public static boolean isNumberPrimitive(Type type) {
return isIntPrimitive(type) || type == Type.FLOAT_TYPE || type == Type.DOUBLE_TYPE || type == Type.LONG_TYPE;
}
public static boolean isPrimitive(Type type) {
return type.getSort() != Type.OBJECT && type.getSort() != Type.ARRAY;
}
public static boolean isPrimitiveNumberClassDescriptor(DeclarationDescriptor descriptor) {
if (!(descriptor instanceof ClassDescriptor)) {
return false;
}
return PRIMITIVE_NUMBER_CLASSES.contains(descriptor);
}
public static Type correctElementType(Type type) {
String internalName = type.getInternalName();
assert internalName.charAt(0) == '[';
return Type.getType(internalName.substring(1));
}
@Nullable @Nullable
public static String getLocalNameForObject(JetObjectDeclaration object) { public static String getLocalNameForObject(JetObjectDeclaration object) {
PsiElement parent = object.getParent(); PsiElement parent = object.getParent();
@@ -363,34 +199,4 @@ public class CodegenUtil {
throw new IllegalStateException("code generation for synthesized members should be handled separately"); throw new IllegalStateException("code generation for synthesized members should be handled separately");
} }
} }
public static void initSingletonField(PsiElement element, Type classAsmType, ClassBuilder builder, InstructionAdapter iv) {
iv.anew(classAsmType);
iv.dup();
iv.invokespecial(classAsmType.getInternalName(), "<init>", "()V");
iv.putstatic(classAsmType.getInternalName(), JvmAbi.INSTANCE_FIELD, classAsmType.getDescriptor());
}
public static void generateStringBuilderConstructor(InstructionAdapter v) {
v.visitTypeInsn(NEW, "java/lang/StringBuilder");
v.dup();
v.invokespecial("java/lang/StringBuilder", "<init>", "()V");
}
public static void invokeAppendMethod(InstructionAdapter v, Type exprType) {
Method appendDescriptor = new Method("append", getType(StringBuilder.class),
new Type[] {exprType.getSort() == Type.OBJECT ? (exprType.equals(JAVA_STRING_TYPE) ? JAVA_STRING_TYPE : OBJECT_TYPE) : exprType});
v.invokevirtual("java/lang/StringBuilder", "append", appendDescriptor.getDescriptor());
}
public static StackValue genToString(InstructionAdapter v, StackValue receiver) {
final int sort = receiver.type.getSort();
final Type type = sort == Type.OBJECT || sort == Type.ARRAY
? AsmTypeConstants.OBJECT_TYPE
: sort == Type.BYTE || sort == Type.SHORT ? Type.INT_TYPE : receiver.type;
receiver.put(type, v);
v.invokestatic("java/lang/String", "valueOf", "(" + type.getDescriptor() + ")Ljava/lang/String;");
return StackValue.onStack(JAVA_STRING_TYPE);
}
} }
@@ -30,7 +30,7 @@ import org.jetbrains.jet.lang.diagnostics.DiagnosticUtils;
public class CompilationException extends RuntimeException { public class CompilationException extends RuntimeException {
private final PsiElement element; private final PsiElement element;
CompilationException(@NotNull String message, @Nullable Throwable cause, @NotNull PsiElement element) { public CompilationException(@NotNull String message, @Nullable Throwable cause, @NotNull PsiElement element) {
super(message, cause); super(message, cause);
this.element = element; this.element = element;
} }
@@ -61,6 +61,7 @@ import org.jetbrains.jet.lexer.JetTokens;
import java.util.*; import java.util.*;
import static org.jetbrains.asm4.Opcodes.*; import static org.jetbrains.asm4.Opcodes.*;
import static org.jetbrains.jet.codegen.AsmUtil.*;
import static org.jetbrains.jet.codegen.CodegenUtil.*; import static org.jetbrains.jet.codegen.CodegenUtil.*;
import static org.jetbrains.jet.codegen.binding.CodegenBinding.*; import static org.jetbrains.jet.codegen.binding.CodegenBinding.*;
import static org.jetbrains.jet.lang.resolve.BindingContext.*; import static org.jetbrains.jet.lang.resolve.BindingContext.*;
@@ -116,9 +117,16 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> implem
//noinspection SuspiciousMethodCalls //noinspection SuspiciousMethodCalls
final CalculatedClosure closure = bindingContext.get(CLOSURE, classDescriptor); final CalculatedClosure closure = bindingContext.get(CLOSURE, classDescriptor);
final CodegenContext objectContext = context.intoAnonymousClass(classDescriptor, this); final CodegenContext contextForInners = context.intoClass(classDescriptor, OwnerKind.IMPLEMENTATION, state);
new ImplementationBodyCodegen(objectDeclaration, objectContext, classBuilder, state).generate(); final CodegenContext objectContext = context.intoAnonymousClass(classDescriptor, this);
final ImplementationBodyCodegen implementationBodyCodegen = new ImplementationBodyCodegen(objectDeclaration, objectContext, classBuilder, state);
implementationBodyCodegen.genInners(contextForInners, state, objectDeclaration);
objectContext.copyAccessors(contextForInners.getAccessors());
implementationBodyCodegen.generate();
return closure; return closure;
} }
@@ -991,7 +999,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> implem
return StackValue.constant(constantValue.toString(), type); return StackValue.constant(constantValue.toString(), type);
} }
else { else {
generateStringBuilderConstructor(v); genStringBuilderConstructor(v);
for (JetStringTemplateEntry entry : entries) { for (JetStringTemplateEntry entry : entries) {
if (entry instanceof JetStringTemplateEntryWithExpression) { if (entry instanceof JetStringTemplateEntryWithExpression) {
invokeAppend(entry.getExpression()); invokeAppend(entry.getExpression());
@@ -1001,7 +1009,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> implem
? ((JetEscapeStringTemplateEntry) entry).getUnescapedValue() ? ((JetEscapeStringTemplateEntry) entry).getUnescapedValue()
: entry.getText(); : entry.getText();
v.aconst(text); v.aconst(text);
invokeAppendMethod(v, JAVA_STRING_TYPE); genInvokeAppendMethod(v, JAVA_STRING_TYPE);
} }
} }
v.invokevirtual("java/lang/StringBuilder", "toString", "()Ljava/lang/String;"); v.invokevirtual("java/lang/StringBuilder", "toString", "()Ljava/lang/String;");
@@ -1510,9 +1518,11 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> implem
boolean isStatic = containingDeclaration instanceof NamespaceDescriptor; boolean isStatic = containingDeclaration instanceof NamespaceDescriptor;
boolean overridesTrait = isOverrideForTrait(propertyDescriptor); boolean overridesTrait = isOverrideForTrait(propertyDescriptor);
boolean isFakeOverride = propertyDescriptor.getKind() == CallableMemberDescriptor.Kind.FAKE_OVERRIDE; boolean isFakeOverride = propertyDescriptor.getKind() == CallableMemberDescriptor.Kind.FAKE_OVERRIDE;
boolean isDelegate = propertyDescriptor.getKind() == CallableMemberDescriptor.Kind.DELEGATION;
PropertyDescriptor initialDescriptor = propertyDescriptor; PropertyDescriptor initialDescriptor = propertyDescriptor;
propertyDescriptor = initialDescriptor.getOriginal(); propertyDescriptor = initialDescriptor.getOriginal();
boolean isInsideClass = !isFakeOverride && boolean isInsideClass = !isFakeOverride &&
!isDelegate &&
(((containingDeclaration == null && !context.hasThisDescriptor() || (((containingDeclaration == null && !context.hasThisDescriptor() ||
context.hasThisDescriptor() && containingDeclaration == context.getThisDescriptor()) || context.hasThisDescriptor() && containingDeclaration == context.getThisDescriptor()) ||
(context.getParentContext() instanceof NamespaceContext) && (context.getParentContext() instanceof NamespaceContext) &&
@@ -1660,9 +1670,9 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> implem
PropertySetterDescriptor setter = propertyDescriptor.getSetter(); PropertySetterDescriptor setter = propertyDescriptor.getSetter();
PropertyGetterDescriptor getter = propertyDescriptor.getGetter(); PropertyGetterDescriptor getter = propertyDescriptor.getGetter();
final int flag = CodegenUtil.getVisibilityAccessFlag(propertyDescriptor) | final int flag = getVisibilityAccessFlag(propertyDescriptor) |
(getter == null ? 0 : CodegenUtil.getVisibilityAccessFlag(getter)) | (getter == null ? 0 : getVisibilityAccessFlag(getter)) |
(setter == null ? 0 : CodegenUtil.getVisibilityAccessFlag(setter)); (setter == null ? 0 : getVisibilityAccessFlag(setter));
if ((flag & ACC_PRIVATE) == 0) { if ((flag & ACC_PRIVATE) == 0) {
return propertyDescriptor; return propertyDescriptor;
@@ -1672,7 +1682,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> implem
} }
private FunctionDescriptor accessableFunctionDescriptor(FunctionDescriptor fd) { private FunctionDescriptor accessableFunctionDescriptor(FunctionDescriptor fd) {
final int flag = CodegenUtil.getVisibilityAccessFlag(fd); final int flag = getVisibilityAccessFlag(fd);
if ((flag & ACC_PRIVATE) == 0) { if ((flag & ACC_PRIVATE) == 0) {
return fd; return fd;
} }
@@ -2256,7 +2266,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> implem
else { else {
invokeFunctionByReference(expression.getOperationReference()); invokeFunctionByReference(expression.getOperationReference());
if (inverted) { if (inverted) {
invertBoolean(); genInvertBoolean(v);
} }
} }
return StackValue.onStack(Type.BOOLEAN_TYPE); return StackValue.onStack(Type.BOOLEAN_TYPE);
@@ -2297,7 +2307,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> implem
v.and(Type.INT_TYPE); v.and(Type.INT_TYPE);
if (inverted) { if (inverted) {
invertBoolean(); genInvertBoolean(v);
} }
} }
@@ -2357,10 +2367,11 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> implem
if (isPrimitive(leftType)) // both are primitive if (isPrimitive(leftType)) // both are primitive
{ {
return generateEqualsForExpressionsOnStack(opToken, leftType, rightType, false, false); return genEqualsForExpressionsOnStack(v, opToken, leftType, rightType, false, false);
} }
return generateEqualsForExpressionsOnStack(opToken, leftType, rightType, leftJetType.isNullable(), rightJetType.isNullable()); return
genEqualsForExpressionsOnStack(v, opToken, leftType, rightType, leftJetType.isNullable(), rightJetType.isNullable());
} }
private StackValue genCmpWithNull(JetExpression exp, Type expType, IElementType opToken) { private StackValue genCmpWithNull(JetExpression exp, Type expType, IElementType opToken) {
@@ -2379,81 +2390,6 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> implem
return StackValue.onStack(Type.BOOLEAN_TYPE); return StackValue.onStack(Type.BOOLEAN_TYPE);
} }
public StackValue generateEqualsForExpressionsOnStack(
IElementType opToken,
Type leftType,
Type rightType,
boolean leftNullable,
boolean rightNullable
) {
if ((CodegenUtil.isNumberPrimitive(leftType) || leftType.getSort() == Type.BOOLEAN) && leftType == rightType) {
return compareExpressionsOnStack(opToken, leftType);
}
else {
if (opToken == JetTokens.EQEQEQ || opToken == JetTokens.EXCLEQEQEQ) {
return StackValue.cmp(opToken, leftType);
}
else {
return generateNullSafeEquals(opToken, leftNullable, rightNullable);
}
}
}
private StackValue generateNullSafeEquals(IElementType opToken, boolean leftNullable, boolean rightNullable) {
if (!leftNullable) {
v.invokevirtual("java/lang/Object", "equals", "(Ljava/lang/Object;)Z");
if (opToken == JetTokens.EXCLEQ) {
invertBoolean();
}
}
else {
if (rightNullable) {
v.dup2(); // left right left right
Label rightNull = new Label();
v.ifnull(rightNull);
Label leftNull = new Label();
v.ifnull(leftNull);
v.invokevirtual("java/lang/Object", "equals", "(Ljava/lang/Object;)Z");
if (opToken == JetTokens.EXCLEQ || opToken == JetTokens.EXCLEQEQEQ) {
invertBoolean();
}
Label end = new Label();
v.goTo(end);
v.mark(rightNull);
// left right left
Label bothNull = new Label();
v.ifnull(bothNull);
v.mark(leftNull);
v.pop2();
v.iconst(opToken == JetTokens.EXCLEQ || opToken == JetTokens.EXCLEQEQEQ ? 1 : 0);
v.goTo(end);
v.mark(bothNull);
v.pop2();
v.iconst(opToken == JetTokens.EXCLEQ || opToken == JetTokens.EXCLEQEQEQ ? 0 : 1);
v.mark(end);
}
else {
v.dup2(); // left right left right
v.pop();
Label leftNull = new Label();
v.ifnull(leftNull);
v.invokevirtual("java/lang/Object", "equals", "(Ljava/lang/Object;)Z");
if (opToken == JetTokens.EXCLEQ || opToken == JetTokens.EXCLEQEQEQ) {
invertBoolean();
}
Label end = new Label();
v.goTo(end);
// left right
v.mark(leftNull);
v.pop2();
v.iconst(opToken == JetTokens.EXCLEQ ? 1 : 0);
v.mark(end);
}
}
return StackValue.onStack(Type.BOOLEAN_TYPE);
}
private StackValue generateElvis(JetBinaryExpression expression) { private StackValue generateElvis(JetBinaryExpression expression) {
final Type exprType = expressionType(expression); final Type exprType = expressionType(expression);
JetType type = bindingContext.get(BindingContext.EXPRESSION_TYPE, expression.getLeft()); JetType type = bindingContext.get(BindingContext.EXPRESSION_TYPE, expression.getLeft());
@@ -2490,16 +2426,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> implem
private StackValue generateCompareOp(JetExpression left, JetExpression right, IElementType opToken, Type operandType) { private StackValue generateCompareOp(JetExpression left, JetExpression right, IElementType opToken, Type operandType) {
gen(left, operandType); gen(left, operandType);
gen(right, operandType); gen(right, operandType);
return compareExpressionsOnStack(opToken, operandType); return compareExpressionsOnStack(v, opToken, operandType);
}
private StackValue compareExpressionsOnStack(IElementType opToken, Type operandType) {
if (operandType.getSort() == Type.OBJECT) {
v.invokeinterface("java/lang/Comparable", "compareTo", "(Ljava/lang/Object;)I");
v.iconst(0);
operandType = Type.INT_TYPE;
}
return StackValue.cmp(opToken, operandType);
} }
private StackValue generateAssignmentExpression(JetBinaryExpression expression) { private StackValue generateAssignmentExpression(JetBinaryExpression expression) {
@@ -2593,7 +2520,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> implem
} }
Type exprType = expressionType(expr); Type exprType = expressionType(expr);
gen(expr, exprType); gen(expr, exprType);
invokeAppendMethod(v, exprType.getSort() == Type.ARRAY ? OBJECT_TYPE : exprType); genInvokeAppendMethod(v, exprType.getSort() == Type.ARRAY ? OBJECT_TYPE : exprType);
} }
@Nullable @Nullable
@@ -2767,22 +2694,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> implem
StackValue value = genQualified(receiver, operand); StackValue value = genQualified(receiver, operand);
value.dupReceiver(v); value.dupReceiver(v);
value.put(asmType, v); value.put(asmType, v);
if (asmType == Type.LONG_TYPE) { asmType = genIncrement(asmType, increment, v);
//noinspection UnnecessaryBoxing
v.lconst(increment);
}
else if (asmType == Type.FLOAT_TYPE) {
//noinspection UnnecessaryBoxing
v.fconst(increment);
}
else if (asmType == Type.DOUBLE_TYPE) {
//noinspection UnnecessaryBoxing
v.dconst(increment);
}
else {
v.iconst(increment);
}
v.add(asmType);
value.store(asmType, v); value.store(asmType, v);
} }
@@ -3281,12 +3193,12 @@ The "returned" value of try expression with no finally is either the last expres
boolean patternIsNullable = false; boolean patternIsNullable = false;
JetType condJetType = bindingContext.get(BindingContext.EXPRESSION_TYPE, patternExpression); JetType condJetType = bindingContext.get(BindingContext.EXPRESSION_TYPE, patternExpression);
Type condType; Type condType;
if (CodegenUtil.isNumberPrimitive(subjectType) || subjectType.getSort() == Type.BOOLEAN) { if (isNumberPrimitive(subjectType) || subjectType.getSort() == Type.BOOLEAN) {
assert condJetType != null; assert condJetType != null;
condType = asmType(condJetType); condType = asmType(condJetType);
if (!(CodegenUtil.isNumberPrimitive(condType) || condType.getSort() == Type.BOOLEAN)) { if (!(isNumberPrimitive(condType) || condType.getSort() == Type.BOOLEAN)) {
subjectType = boxType(subjectType); subjectType = boxType(subjectType);
expressionToMatch.coerce(subjectType, v); expressionToMatch.coerceTo(subjectType, v);
} }
} }
else { else {
@@ -3294,8 +3206,8 @@ The "returned" value of try expression with no finally is either the last expres
patternIsNullable = condJetType != null && condJetType.isNullable(); patternIsNullable = condJetType != null && condJetType.isNullable();
} }
gen(patternExpression, condType); gen(patternExpression, condType);
return generateEqualsForExpressionsOnStack(JetTokens.EQEQ, subjectType, condType, expressionToMatchIsNullable, return genEqualsForExpressionsOnStack(v, JetTokens.EQEQ, subjectType, condType, expressionToMatchIsNullable,
patternIsNullable); patternIsNullable);
} }
else { else {
return gen(patternExpression); return gen(patternExpression);
@@ -3420,7 +3332,7 @@ The "returned" value of try expression with no finally is either the last expres
//invokeFunctionNoParams(op, Type.BOOLEAN_TYPE, v); //invokeFunctionNoParams(op, Type.BOOLEAN_TYPE, v);
invokeFunctionByReference(operationReference); invokeFunctionByReference(operationReference);
if (inverted) { if (inverted) {
invertBoolean(); genInvertBoolean(v);
} }
} }
return StackValue.onStack(Type.BOOLEAN_TYPE); return StackValue.onStack(Type.BOOLEAN_TYPE);
@@ -3446,11 +3358,6 @@ The "returned" value of try expression with no finally is either the last expres
invokeFunction(call, StackValue.none(), resolvedCall); invokeFunction(call, StackValue.none(), resolvedCall);
} }
private void invertBoolean() {
v.iconst(1);
v.xor(Type.INT_TYPE);
}
private boolean isIntRangeExpr(JetExpression rangeExpression) { private boolean isIntRangeExpr(JetExpression rangeExpression) {
if (rangeExpression instanceof JetBinaryExpression) { if (rangeExpression instanceof JetBinaryExpression) {
JetBinaryExpression binaryExpression = (JetBinaryExpression) rangeExpression; JetBinaryExpression binaryExpression = (JetBinaryExpression) rangeExpression;
@@ -3464,34 +3371,6 @@ The "returned" value of try expression with no finally is either the last expres
return false; return false;
} }
@Override
public StackValue visitTupleExpression(JetTupleExpression expression, StackValue receiver) {
final List<JetExpression> entries = expression.getEntries();
if (entries.size() > 22) {
throw new UnsupportedOperationException("tuple too large");
}
if (entries.size() == 0) {
v.visitFieldInsn(GETSTATIC, "jet/Tuple0", "INSTANCE", "Ljet/Tuple0;");
return StackValue.onStack(JET_TUPLE0_TYPE);
}
final String className = "jet/Tuple" + entries.size();
Type tupleType = Type.getObjectType(className);
StringBuilder signature = new StringBuilder("(");
for (int i = 0; i != entries.size(); ++i) {
signature.append("Ljava/lang/Object;");
}
signature.append(")V");
v.anew(tupleType);
v.dup();
for (JetExpression entry : entries) {
gen(entry, OBJECT_TYPE);
}
v.invokespecial(className, "<init>", signature.toString());
return StackValue.onStack(tupleType);
}
private void throwNewException(final String className) { private void throwNewException(final String className) {
v.anew(Type.getObjectType(className)); v.anew(Type.getObjectType(className));
v.dup(); v.dup();
@@ -48,6 +48,7 @@ import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor;
import java.util.*; import java.util.*;
import static org.jetbrains.asm4.Opcodes.*; import static org.jetbrains.asm4.Opcodes.*;
import static org.jetbrains.jet.codegen.AsmUtil.*;
import static org.jetbrains.jet.codegen.CodegenUtil.*; import static org.jetbrains.jet.codegen.CodegenUtil.*;
import static org.jetbrains.jet.codegen.binding.CodegenBinding.isLocalFun; import static org.jetbrains.jet.codegen.binding.CodegenBinding.isLocalFun;
import static org.jetbrains.jet.lang.resolve.BindingContextUtils.callableDescriptorToDeclaration; import static org.jetbrains.jet.lang.resolve.BindingContextUtils.callableDescriptorToDeclaration;
@@ -130,7 +131,7 @@ public class FunctionCodegen extends GenerationStateAware {
} }
if (!isAbstract && state.getClassBuilderMode() == ClassBuilderMode.STUBS) { if (!isAbstract && state.getClassBuilderMode() == ClassBuilderMode.STUBS) {
StubCodegen.generateStubCode(mv); genStubCode(mv);
} }
@@ -258,7 +259,7 @@ public class FunctionCodegen extends GenerationStateAware {
Type sharedVarType = state.getTypeMapper().getSharedVarType(parameter); Type sharedVarType = state.getTypeMapper().getSharedVarType(parameter);
mv.visitLocalVariable(parameterName, type.getDescriptor(), null, methodBegin, divideLabel, k); mv.visitLocalVariable(parameterName, type.getDescriptor(), null, methodBegin, divideLabel, k);
String nameForSharedVar = generateTmpVariableName(localVariableNames); String nameForSharedVar = createTmpVariableName(localVariableNames);
localVariableNames.add(nameForSharedVar); localVariableNames.add(nameForSharedVar);
mv.visitLocalVariable(nameForSharedVar, sharedVarType.getDescriptor(), null, divideLabel, methodEnd, k); mv.visitLocalVariable(nameForSharedVar, sharedVarType.getDescriptor(), null, divideLabel, methodEnd, k);
@@ -516,7 +517,7 @@ public class FunctionCodegen extends GenerationStateAware {
descriptor, null, null); descriptor, null, null);
InstructionAdapter iv = new InstructionAdapter(mv); InstructionAdapter iv = new InstructionAdapter(mv);
if (state.getClassBuilderMode() == ClassBuilderMode.STUBS) { if (state.getClassBuilderMode() == ClassBuilderMode.STUBS) {
StubCodegen.generateStubCode(mv); genStubCode(mv);
} }
else if (state.getClassBuilderMode() == ClassBuilderMode.FULL) { else if (state.getClassBuilderMode() == ClassBuilderMode.FULL) {
generateDefaultImpl(owner, state, jvmSignature, functionDescriptor, kind, receiverParameter, hasReceiver, isStatic, generateDefaultImpl(owner, state, jvmSignature, functionDescriptor, kind, receiverParameter, hasReceiver, isStatic,
@@ -684,7 +685,7 @@ public class FunctionCodegen extends GenerationStateAware {
final MethodVisitor mv = v.newMethod(null, flags, jvmSignature.getName(), overridden.getDescriptor(), null, null); final MethodVisitor mv = v.newMethod(null, flags, jvmSignature.getName(), overridden.getDescriptor(), null, null);
if (state.getClassBuilderMode() == ClassBuilderMode.STUBS) { if (state.getClassBuilderMode() == ClassBuilderMode.STUBS) {
StubCodegen.generateStubCode(mv); genStubCode(mv);
} }
else if (state.getClassBuilderMode() == ClassBuilderMode.FULL) { else if (state.getClassBuilderMode() == ClassBuilderMode.FULL) {
mv.visitCode(); mv.visitCode();
@@ -738,7 +739,7 @@ public class FunctionCodegen extends GenerationStateAware {
final MethodVisitor mv = v.newMethod(null, flags, method.getName(), method.getDescriptor(), null, null); final MethodVisitor mv = v.newMethod(null, flags, method.getName(), method.getDescriptor(), null, null);
if (state.getClassBuilderMode() == ClassBuilderMode.STUBS) { if (state.getClassBuilderMode() == ClassBuilderMode.STUBS) {
StubCodegen.generateStubCode(mv); genStubCode(mv);
} }
else if (state.getClassBuilderMode() == ClassBuilderMode.FULL) { else if (state.getClassBuilderMode() == ClassBuilderMode.FULL) {
mv.visitCode(); mv.visitCode();
@@ -22,6 +22,7 @@ import com.intellij.openapi.util.Pair;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import org.jetbrains.asm4.AnnotationVisitor; import org.jetbrains.asm4.AnnotationVisitor;
import org.jetbrains.asm4.Label;
import org.jetbrains.asm4.MethodVisitor; import org.jetbrains.asm4.MethodVisitor;
import org.jetbrains.asm4.Type; import org.jetbrains.asm4.Type;
import org.jetbrains.asm4.commons.InstructionAdapter; import org.jetbrains.asm4.commons.InstructionAdapter;
@@ -40,6 +41,7 @@ import org.jetbrains.jet.codegen.state.JetTypeMapperMode;
import org.jetbrains.jet.lang.descriptors.*; import org.jetbrains.jet.lang.descriptors.*;
import org.jetbrains.jet.lang.psi.*; import org.jetbrains.jet.lang.psi.*;
import org.jetbrains.jet.lang.resolve.BindingContext; import org.jetbrains.jet.lang.resolve.BindingContext;
import org.jetbrains.jet.lang.resolve.DescriptorUtils;
import org.jetbrains.jet.lang.resolve.OverridingUtil; import org.jetbrains.jet.lang.resolve.OverridingUtil;
import org.jetbrains.jet.lang.resolve.calls.ResolvedCall; import org.jetbrains.jet.lang.resolve.calls.ResolvedCall;
import org.jetbrains.jet.lang.resolve.constants.CompileTimeConstant; import org.jetbrains.jet.lang.resolve.constants.CompileTimeConstant;
@@ -56,6 +58,7 @@ import org.jetbrains.jet.utils.BitSetUtils;
import java.util.*; import java.util.*;
import static org.jetbrains.asm4.Opcodes.*; import static org.jetbrains.asm4.Opcodes.*;
import static org.jetbrains.jet.codegen.AsmUtil.*;
import static org.jetbrains.jet.codegen.CodegenUtil.*; import static org.jetbrains.jet.codegen.CodegenUtil.*;
import static org.jetbrains.jet.codegen.binding.CodegenBinding.*; import static org.jetbrains.jet.codegen.binding.CodegenBinding.*;
import static org.jetbrains.jet.lang.resolve.BindingContextUtils.callableDescriptorToDeclaration; import static org.jetbrains.jet.lang.resolve.BindingContextUtils.callableDescriptorToDeclaration;
@@ -164,42 +167,43 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
); );
v.visitSource(myClass.getContainingFile().getName(), null); v.visitSource(myClass.getContainingFile().getName(), null);
writeInnerOuterClasses(); writeOuterClass();
writeInnerClasses();
AnnotationCodegen.forClass(v.getVisitor(), typeMapper).genAnnotations(descriptor); AnnotationCodegen.forClass(v.getVisitor(), typeMapper).genAnnotations(descriptor);
writeClassSignatureIfNeeded(signature); writeClassSignatureIfNeeded(signature);
} }
private void writeInnerOuterClasses() { private void writeOuterClass() {
ClassDescriptor container = getContainingClassDescriptor(descriptor); ClassDescriptor container = getContainingClassDescriptor(descriptor);
if (container != null) { if (container != null) {
v.visitOuterClass(typeMapper.mapType(container.getDefaultType(), JetTypeMapperMode.IMPL).getInternalName(), null, null); v.visitOuterClass(typeMapper.mapType(container.getDefaultType(), JetTypeMapperMode.IMPL).getInternalName(), null, null);
} }
}
for (DeclarationDescriptor declarationDescriptor : descriptor.getUnsubstitutedInnerClassesScope().getAllDescriptors()) { private void writeInnerClasses() {
assert declarationDescriptor instanceof ClassDescriptor; // Inner enums are moved by frontend to a class object of outer class, but we want them to be inner for the outer class itself
ClassDescriptor innerClass = (ClassDescriptor) declarationDescriptor; // (to avoid publicly visible names like A$ClassObject$$B), so they are handled specially in this method
// TODO: proper access
int innerClassAccess = ACC_PUBLIC;
if (innerClass.getModality() == Modality.FINAL) {
innerClassAccess |= ACC_FINAL;
}
else if (innerClass.getModality() == Modality.ABSTRACT) {
innerClassAccess |= ACC_ABSTRACT;
}
if (innerClass.getKind() == ClassKind.TRAIT) { for (ClassDescriptor innerClass : DescriptorUtils.getInnerClasses(descriptor)) {
innerClassAccess |= ACC_INTERFACE; // If it's an inner enum inside a class object, don't write it
// (instead write it to inner classes of this class object's containing class)
if (!isEnumMovedToClassObject(innerClass)) {
writeInnerClass(innerClass, false);
} }
// TODO: cache internal names
String outerClassInernalName = classAsmType.getInternalName();
String innerClassInternalName = typeMapper.mapType(innerClass.getDefaultType(), JetTypeMapperMode.IMPL).getInternalName();
v.visitInnerClass(innerClassInternalName, outerClassInernalName, innerClass.getName().getName(), innerClassAccess);
} }
if (descriptor.getClassObjectDescriptor() != null) { ClassDescriptor classObjectDescriptor = descriptor.getClassObjectDescriptor();
if (classObjectDescriptor != null) {
// Process all enums here which were moved to our class object
for (ClassDescriptor innerClass : DescriptorUtils.getInnerClasses(classObjectDescriptor)) {
if (isEnumMovedToClassObject(innerClass)) {
writeInnerClass(innerClass, true);
}
}
int innerClassAccess = ACC_PUBLIC | ACC_FINAL | ACC_STATIC; int innerClassAccess = ACC_PUBLIC | ACC_FINAL | ACC_STATIC;
v.visitInnerClass(classAsmType.getInternalName() + JvmAbi.CLASS_OBJECT_SUFFIX, classAsmType.getInternalName(), v.visitInnerClass(classAsmType.getInternalName() + JvmAbi.CLASS_OBJECT_SUFFIX, classAsmType.getInternalName(),
JvmAbi.CLASS_OBJECT_CLASS_NAME, JvmAbi.CLASS_OBJECT_CLASS_NAME,
@@ -207,6 +211,39 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
} }
} }
private void writeInnerClass(ClassDescriptor innerClass, boolean isStatic) {
// TODO: proper access
int innerClassAccess = ACC_PUBLIC;
if (innerClass.getModality() == Modality.FINAL) {
innerClassAccess |= ACC_FINAL;
}
else if (innerClass.getModality() == Modality.ABSTRACT) {
innerClassAccess |= ACC_ABSTRACT;
}
if (innerClass.getKind() == ClassKind.TRAIT) {
innerClassAccess |= ACC_INTERFACE;
}
else if (innerClass.getKind() == ClassKind.ENUM_CLASS) {
innerClassAccess |= ACC_ENUM;
}
if (isStatic) {
innerClassAccess |= ACC_STATIC;
}
// TODO: cache internal names
String outerClassInternalName = classAsmType.getInternalName();
String innerClassInternalName = typeMapper.mapType(innerClass.getDefaultType(), JetTypeMapperMode.IMPL).getInternalName();
v.visitInnerClass(innerClassInternalName, outerClassInternalName, innerClass.getName().getName(), innerClassAccess);
}
private boolean isEnumMovedToClassObject(ClassDescriptor innerClass) {
// Checks if this is enum, moved to class object by frontend
return Boolean.TRUE.equals(bindingContext.get(BindingContext.IS_ENUM_MOVED_TO_CLASS_OBJECT, innerClass));
}
private void writeClassSignatureIfNeeded(JvmClassSignature signature) { private void writeClassSignatureIfNeeded(JvmClassSignature signature) {
if (signature.getKotlinGenericSignature() != null || descriptor.getVisibility() != Visibilities.PUBLIC) { if (signature.getKotlinGenericSignature() != null || descriptor.getVisibility() != Visibilities.PUBLIC) {
AnnotationVisitor annotationVisitor = v.newAnnotation(JvmStdlibNames.JET_CLASS.getDescriptor(), true); AnnotationVisitor annotationVisitor = v.newAnnotation(JvmStdlibNames.JET_CLASS.getDescriptor(), true);
@@ -355,7 +392,20 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
generateFunctionsForDataClasses(); generateFunctionsForDataClasses();
generateClosureFields(context.closure, v, state.getTypeMapper()); genClosureFields(context.closure, v, state.getTypeMapper());
}
private List<PropertyDescriptor> getDataProperties() {
ArrayList<PropertyDescriptor> result = Lists.newArrayList();
for (JetParameter parameter : getPrimaryConstructorParameters()) {
if (parameter.getValOrVarNode() == null) continue;
PropertyDescriptor propertyDescriptor = state.getBindingContext().get(BindingContext.PRIMARY_CONSTRUCTOR_PARAMETER, parameter);
assert propertyDescriptor != null;
result.add(propertyDescriptor);
}
return result;
} }
private void generateFunctionsForDataClasses() { private void generateFunctionsForDataClasses() {
@@ -363,67 +413,135 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
generateComponentFunctionsForDataClasses(); generateComponentFunctionsForDataClasses();
generateDataClassToStringMethod(); final List<PropertyDescriptor> properties = getDataProperties();
generateDataClassHashCodeMethod(); if (!properties.isEmpty()) {
generateDataClassEqualsMethod(); generateDataClassToStringMethod(properties);
generateDataClassHashCodeMethod(properties);
generateDataClassEqualsMethod(properties);
}
} }
private void generateDataClassEqualsMethod() { private void generateDataClassEqualsMethod(List<PropertyDescriptor> properties) {
// todo: this is fake implementation
final MethodVisitor mv = v.getVisitor().visitMethod(ACC_PUBLIC, "equals", "(Ljava/lang/Object;)Z", null, null); final MethodVisitor mv = v.getVisitor().visitMethod(ACC_PUBLIC, "equals", "(Ljava/lang/Object;)Z", null, null);
mv.visitVarInsn(ALOAD, 0); final InstructionAdapter iv = new InstructionAdapter(mv);
mv.visitVarInsn(ALOAD, 1);
mv.visitMethodInsn(INVOKESPECIAL, superClassAsmType.getInternalName(), "equals", "(Ljava/lang/Object;)Z"); mv.visitCode();
mv.visitInsn(IRETURN); Label eq = new Label();
mv.visitMaxs(-1,-1); Label ne = new Label();
mv.visitEnd();
iv.load(0, OBJECT_TYPE);
iv.load(1, AsmTypeConstants.OBJECT_TYPE);
iv.ifacmpeq(eq);
iv.load(1, AsmTypeConstants.OBJECT_TYPE);
iv.instanceOf(classAsmType);
iv.ifeq(ne);
iv.load(1, AsmTypeConstants.OBJECT_TYPE);
iv.checkcast(classAsmType);
iv.store(2, AsmTypeConstants.OBJECT_TYPE);
for (PropertyDescriptor propertyDescriptor : properties) {
final JetType type = propertyDescriptor.getType();
final Type asmType = typeMapper.mapType(type);
genPropertyOnStack(iv, propertyDescriptor, 0);
genPropertyOnStack(iv, propertyDescriptor, 2);
if (asmType.getSort() == Type.ARRAY) {
final Type elementType = correctElementType(asmType);
if (elementType.getSort() == Type.OBJECT || elementType.getSort() == Type.ARRAY) {
iv.invokestatic("java/util/Arrays", "equals", "([Ljava/lang/Object;[Ljava/lang/Object;)Z");
}
else {
iv.invokestatic("java/util/Arrays", "equals", "([" + elementType.getDescriptor() + "[" + elementType.getDescriptor() + ")Z");
}
}
else {
final StackValue value =
genEqualsForExpressionsOnStack(iv, JetTokens.EQEQ, asmType, asmType, type.isNullable(), type.isNullable());
value.put(Type.BOOLEAN_TYPE, iv);
}
iv.ifeq(ne);
}
iv.mark(eq);
iv.iconst(1);
iv.areturn(Type.INT_TYPE);
iv.mark(ne);
iv.iconst(0);
iv.areturn(Type.INT_TYPE);
FunctionCodegen.endVisit(mv, "equals", myClass);
} }
private void generateDataClassHashCodeMethod() { private void generateDataClassHashCodeMethod(List<PropertyDescriptor> properties) {
// todo: this is fake implementation
final MethodVisitor mv = v.getVisitor().visitMethod(ACC_PUBLIC, "hashCode", "()I", null, null); final MethodVisitor mv = v.getVisitor().visitMethod(ACC_PUBLIC, "hashCode", "()I", null, null);
mv.visitVarInsn(ALOAD, 0); final InstructionAdapter iv = new InstructionAdapter(mv);
mv.visitMethodInsn(INVOKESPECIAL, superClassAsmType.getInternalName(), "hashCode", "()I");
mv.visitCode();
boolean first = true;
for (PropertyDescriptor propertyDescriptor : properties) {
if (!first) {
iv.iconst(31);
iv.mul(Type.INT_TYPE);
}
genPropertyOnStack(iv, propertyDescriptor, 0);
Label ifNull = null;
if (propertyDescriptor.getType().isNullable()) {
ifNull = new Label();
iv.dup();
iv.ifnull(ifNull);
}
genHashCode(mv, iv, typeMapper.mapType(propertyDescriptor.getType()));
if (ifNull != null) {
Label end = new Label();
iv.goTo(end);
iv.mark(ifNull);
iv.pop();
iv.iconst(0);
iv.mark(end);
}
if (first) {
first = false;
}
else {
iv.add(Type.INT_TYPE);
}
}
mv.visitInsn(IRETURN); mv.visitInsn(IRETURN);
mv.visitMaxs(-1,-1);
mv.visitEnd(); FunctionCodegen.endVisit(mv, "hashCode", myClass);
} }
private void generateDataClassToStringMethod() { private void generateDataClassToStringMethod(List<PropertyDescriptor> properties) {
final MethodVisitor mv = v.getVisitor().visitMethod(ACC_PUBLIC, "toString", "()Ljava/lang/String;", null, null); final MethodVisitor mv = v.getVisitor().visitMethod(ACC_PUBLIC, "toString", "()Ljava/lang/String;", null, null);
final InstructionAdapter iv = new InstructionAdapter(mv); final InstructionAdapter iv = new InstructionAdapter(mv);
mv.visitVarInsn(ALOAD, 0);
generateStringBuilderConstructor(iv); mv.visitCode();
genStringBuilderConstructor(iv);
boolean first = true; boolean first = true;
for (JetParameter parameter : getPrimaryConstructorParameters()) { for (PropertyDescriptor propertyDescriptor : properties) {
if (parameter.getValOrVarNode() == null) continue; if (first) {
iv.aconst(descriptor.getName() + "(" + propertyDescriptor.getName().getName()+"=");
PropertyDescriptor propertyDescriptor = state.getBindingContext().get(BindingContext.PRIMARY_CONSTRUCTOR_PARAMETER, parameter);
assert propertyDescriptor != null;
if(first) {
iv.aconst(descriptor.getName() + "{" + propertyDescriptor.getName().getName()+"=");
first = false; first = false;
} }
else { else {
iv.aconst(", " + propertyDescriptor.getName().getName()+"="); iv.aconst(", " + propertyDescriptor.getName().getName()+"=");
} }
CodegenUtil.invokeAppendMethod(iv, JAVA_STRING_TYPE); genInvokeAppendMethod(iv, JAVA_STRING_TYPE);
iv.load(0, classAsmType); Type type = genPropertyOnStack(iv, propertyDescriptor, 0);
// todo: seems to be more correct - need to be changed in sync with 'componentX' generation and related tests
// final Method
// method = typeMapper.mapGetterSignature(propertyDescriptor, OwnerKind.IMPLEMENTATION).getJvmMethodSignature().getAsmMethod();
//
// iv.invokevirtual(classAsmType.getInternalName(), method.getName(), method.getDescriptor());
// final Type type = method.getReturnType();
Type type = typeMapper.mapType(propertyDescriptor);
iv.getfield(classAsmType.getInternalName(), parameter.getName(), type.getDescriptor());
if (type.getSort() == Type.ARRAY) { if (type.getSort() == Type.ARRAY) {
final Type elementType = correctElementType(type); final Type elementType = correctElementType(type);
@@ -438,11 +556,11 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
} }
} }
} }
CodegenUtil.invokeAppendMethod(iv, type); genInvokeAppendMethod(iv, type);
} }
iv.aconst("}"); iv.aconst(")");
CodegenUtil.invokeAppendMethod(iv, JAVA_STRING_TYPE); genInvokeAppendMethod(iv, JAVA_STRING_TYPE);
iv.invokevirtual("java/lang/StringBuilder", "toString", "()Ljava/lang/String;"); iv.invokevirtual("java/lang/StringBuilder", "toString", "()Ljava/lang/String;");
iv.areturn(JAVA_STRING_TYPE); iv.areturn(JAVA_STRING_TYPE);
@@ -450,6 +568,15 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
FunctionCodegen.endVisit(mv, "toString", myClass); FunctionCodegen.endVisit(mv, "toString", myClass);
} }
private Type genPropertyOnStack(InstructionAdapter iv, PropertyDescriptor propertyDescriptor, int index) {
iv.load(index, classAsmType);
final Method
method = typeMapper.mapGetterSignature(propertyDescriptor, OwnerKind.IMPLEMENTATION).getJvmMethodSignature().getAsmMethod();
iv.invokevirtual(classAsmType.getInternalName(), method.getName(), method.getDescriptor());
return method.getReturnType();
}
private void generateComponentFunctionsForDataClasses() { private void generateComponentFunctionsForDataClasses() {
if (!myClass.hasPrimaryConstructor() || !JetStandardLibrary.isData(descriptor)) return; if (!myClass.hasPrimaryConstructor() || !JetStandardLibrary.isData(descriptor)) return;
@@ -468,10 +595,11 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
assert returnType != null : "Return type of component function should not be null: " + function; assert returnType != null : "Return type of component function should not be null: " + function;
Type componentType = typeMapper.mapReturnType(returnType); Type componentType = typeMapper.mapReturnType(returnType);
final String desc = "()" + componentType.getDescriptor();
MethodVisitor mv = v.newMethod(myClass, MethodVisitor mv = v.newMethod(myClass,
FunctionCodegen.getMethodAsmFlags(function, OwnerKind.IMPLEMENTATION), FunctionCodegen.getMethodAsmFlags(function, OwnerKind.IMPLEMENTATION),
function.getName().getName(), function.getName().getName(),
"()" + componentType.getDescriptor(), desc,
null, null); null, null);
FunctionCodegen.genJetAnnotations(state, function, null, null, mv); FunctionCodegen.genJetAnnotations(state, function, null, null, mv);
@@ -480,7 +608,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
InstructionAdapter iv = new InstructionAdapter(mv); InstructionAdapter iv = new InstructionAdapter(mv);
if (!componentType.equals(Type.VOID_TYPE)) { if (!componentType.equals(Type.VOID_TYPE)) {
iv.load(0, classAsmType); iv.load(0, classAsmType);
iv.getfield(classAsmType.getInternalName(), parameter.getName().getName(), componentType.getDescriptor()); iv.invokevirtual(classAsmType.getInternalName(), PropertyCodegen.getterName(parameter.getName()), desc);
} }
iv.areturn(componentType); iv.areturn(componentType);
@@ -543,7 +671,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
MethodVisitor mv = v.newMethod(null, ACC_BRIDGE | ACC_SYNTHETIC | ACC_STATIC, bridge.getName().getName(), MethodVisitor mv = v.newMethod(null, ACC_BRIDGE | ACC_SYNTHETIC | ACC_STATIC, bridge.getName().getName(),
method.getDescriptor(), null, null); method.getDescriptor(), null, null);
if (state.getClassBuilderMode() == ClassBuilderMode.STUBS) { if (state.getClassBuilderMode() == ClassBuilderMode.STUBS) {
StubCodegen.generateStubCode(mv); genStubCode(mv);
} }
else if (state.getClassBuilderMode() == ClassBuilderMode.FULL) { else if (state.getClassBuilderMode() == ClassBuilderMode.FULL) {
mv.visitCode(); mv.visitCode();
@@ -588,7 +716,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
original, original,
getter.getVisibility()); getter.getVisibility());
if (state.getClassBuilderMode() == ClassBuilderMode.STUBS) { if (state.getClassBuilderMode() == ClassBuilderMode.STUBS) {
StubCodegen.generateStubCode(mv); genStubCode(mv);
} }
else if (state.getClassBuilderMode() == ClassBuilderMode.FULL) { else if (state.getClassBuilderMode() == ClassBuilderMode.FULL) {
mv.visitCode(); mv.visitCode();
@@ -623,7 +751,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
original, original,
setter.getVisibility()); setter.getVisibility());
if (state.getClassBuilderMode() == ClassBuilderMode.STUBS) { if (state.getClassBuilderMode() == ClassBuilderMode.STUBS) {
StubCodegen.generateStubCode(mv); genStubCode(mv);
} }
else if (state.getClassBuilderMode() == ClassBuilderMode.FULL) { else if (state.getClassBuilderMode() == ClassBuilderMode.FULL) {
mv.visitCode(); mv.visitCode();
@@ -665,7 +793,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
staticInitializerChunks.add(new CodeChunk() { staticInitializerChunks.add(new CodeChunk() {
@Override @Override
public void generate(InstructionAdapter iv) { public void generate(InstructionAdapter iv) {
initSingletonField(myClass, classAsmType, v, iv); genInitSingletonField(classAsmType, iv);
} }
}); });
} }
@@ -711,7 +839,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
writeParameterAnnotations(constructorDescriptor, constructorMethod, hasThis0, mv); writeParameterAnnotations(constructorDescriptor, constructorMethod, hasThis0, mv);
if (state.getClassBuilderMode() == ClassBuilderMode.STUBS) { if (state.getClassBuilderMode() == ClassBuilderMode.STUBS) {
StubCodegen.generateStubCode(mv); genStubCode(mv);
return; return;
} }
@@ -1108,7 +1236,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
aw.visitEnd(); aw.visitEnd();
if (state.getClassBuilderMode() == ClassBuilderMode.STUBS) { if (state.getClassBuilderMode() == ClassBuilderMode.STUBS) {
StubCodegen.generateStubCode(mv); genStubCode(mv);
} }
else if (state.getClassBuilderMode() == ClassBuilderMode.FULL) { else if (state.getClassBuilderMode() == ClassBuilderMode.FULL) {
mv.visitCode(); mv.visitCode();
@@ -20,22 +20,28 @@ import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.codegen.context.CodegenContext; import org.jetbrains.jet.codegen.context.CodegenContext;
import org.jetbrains.jet.codegen.state.GenerationState; import org.jetbrains.jet.codegen.state.GenerationState;
import org.jetbrains.jet.codegen.state.GenerationStateAware; import org.jetbrains.jet.codegen.state.GenerationStateAware;
import org.jetbrains.jet.lang.psi.JetNamedFunction; import org.jetbrains.jet.lang.descriptors.ClassDescriptor;
import org.jetbrains.jet.lang.psi.JetProperty; import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor;
import org.jetbrains.jet.lang.psi.JetTypeParameterListOwner; import org.jetbrains.jet.lang.psi.*;
import org.jetbrains.jet.lang.resolve.BindingContext;
import org.jetbrains.jet.lang.types.ErrorUtils;
import java.util.Map;
import static org.jetbrains.jet.codegen.binding.CodegenBinding.enumEntryNeedSubclass;
/** /**
* @author Stepan Koltsov * @author alex.tkachman
*/ */
public class MemberCodegen extends GenerationStateAware { public class MemberCodegen extends GenerationStateAware {
public MemberCodegen(@NotNull GenerationState state) { public MemberCodegen(@NotNull GenerationState state) {
super(state); super(state);
} }
public void generateFunctionOrProperty( public void genFunctionOrProperty(
CodegenContext context,
@NotNull JetTypeParameterListOwner functionOrProperty, @NotNull JetTypeParameterListOwner functionOrProperty,
@NotNull CodegenContext context, @NotNull ClassBuilder classBuilder @NotNull ClassBuilder classBuilder
) { ) {
FunctionCodegen functionCodegen = new FunctionCodegen(context, classBuilder, state); FunctionCodegen functionCodegen = new FunctionCodegen(context, classBuilder, state);
if (functionOrProperty instanceof JetNamedFunction) { if (functionOrProperty instanceof JetNamedFunction) {
@@ -64,4 +70,76 @@ public class MemberCodegen extends GenerationStateAware {
throw new IllegalArgumentException("Unknown parameter: " + functionOrProperty); throw new IllegalArgumentException("Unknown parameter: " + functionOrProperty);
} }
} }
public static void genImplementation(
CodegenContext context,
GenerationState state,
JetClassOrObject aClass,
OwnerKind kind,
Map<DeclarationDescriptor, DeclarationDescriptor> accessors,
ClassBuilder classBuilder
) {
ClassDescriptor descriptor = state.getBindingContext().get(BindingContext.CLASS, aClass);
CodegenContext classContext = context.intoClass(descriptor, kind, state);
classContext.copyAccessors(accessors);
new ImplementationBodyCodegen(aClass, classContext, classBuilder, state).generate();
if (aClass instanceof JetClass && ((JetClass) aClass).isTrait()) {
ClassBuilder traitBuilder = state.getFactory().forTraitImplementation(descriptor, state);
new TraitImplBodyCodegen(aClass, context.intoClass(descriptor, OwnerKind.TRAIT_IMPL, state), traitBuilder, state)
.generate();
traitBuilder.done();
}
}
public void genInners(CodegenContext context, GenerationState state, JetClassOrObject aClass) {
for (JetDeclaration declaration : aClass.getDeclarations()) {
if (declaration instanceof JetClass) {
if (declaration instanceof JetEnumEntry && !enumEntryNeedSubclass(
state.getBindingContext(), (JetEnumEntry) declaration)) {
continue;
}
genClassOrObject(context, (JetClass) declaration);
}
else if (declaration instanceof JetClassObject) {
genClassOrObject(context, ((JetClassObject) declaration).getObjectDeclaration());
}
else if (declaration instanceof JetObjectDeclaration) {
genClassOrObject(context, (JetObjectDeclaration) declaration);
}
}
}
public void genClassOrObject(CodegenContext context, JetClassOrObject aClass) {
ClassDescriptor descriptor = state.getBindingContext().get(BindingContext.CLASS, aClass);
if (descriptor == null || ErrorUtils.isError(descriptor) || descriptor.getName().equals(JetPsiUtil.NO_NAME_PROVIDED)) {
if (state.getClassBuilderMode() != ClassBuilderMode.SIGNATURES) {
throw new IllegalStateException(
"Generating bad descriptor in ClassBuilderMode = " + state.getClassBuilderMode() + ": " + descriptor);
}
return;
}
ClassBuilder classBuilder = state.getFactory().forClassImplementation(descriptor);
final CodegenContext contextForInners = context.intoClass(descriptor, OwnerKind.IMPLEMENTATION, state);
if (state.getClassBuilderMode() == ClassBuilderMode.SIGNATURES) {
// Outer class implementation must happen prior inner classes so we get proper scoping tree in JetLightClass's delegate
// The same code is present below for the case when we genClassOrObject real bytecode. This is because the order should be
// different for the case when we compute closures
genImplementation(context, state, aClass, OwnerKind.IMPLEMENTATION, contextForInners.getAccessors(), classBuilder);
}
genInners(contextForInners, state, aClass);
if (state.getClassBuilderMode() != ClassBuilderMode.SIGNATURES) {
genImplementation(context, state, aClass, OwnerKind.IMPLEMENTATION, contextForInners.getAccessors(), classBuilder);
}
classBuilder.done();
}
} }
@@ -28,7 +28,6 @@ import org.jetbrains.asm4.commons.InstructionAdapter;
import org.jetbrains.jet.codegen.binding.CodegenBinding; import org.jetbrains.jet.codegen.binding.CodegenBinding;
import org.jetbrains.jet.codegen.context.CodegenContext; import org.jetbrains.jet.codegen.context.CodegenContext;
import org.jetbrains.jet.codegen.state.GenerationState; import org.jetbrains.jet.codegen.state.GenerationState;
import org.jetbrains.jet.codegen.state.GenerationStateAware;
import org.jetbrains.jet.lang.descriptors.NamespaceDescriptor; import org.jetbrains.jet.lang.descriptors.NamespaceDescriptor;
import org.jetbrains.jet.lang.descriptors.PropertyDescriptor; import org.jetbrains.jet.lang.descriptors.PropertyDescriptor;
import org.jetbrains.jet.lang.diagnostics.DiagnosticUtils; import org.jetbrains.jet.lang.diagnostics.DiagnosticUtils;
@@ -48,7 +47,7 @@ import static org.jetbrains.asm4.Opcodes.*;
/** /**
* @author max * @author max
*/ */
public class NamespaceCodegen extends GenerationStateAware { public class NamespaceCodegen extends MemberCodegen {
@NotNull @NotNull
private final ClassBuilderOnDemand v; private final ClassBuilderOnDemand v;
@NotNull private final FqName name; @NotNull private final FqName name;
@@ -128,19 +127,17 @@ public class NamespaceCodegen extends GenerationStateAware {
for (JetDeclaration declaration : file.getDeclarations()) { for (JetDeclaration declaration : file.getDeclarations()) {
if (declaration instanceof JetProperty) { if (declaration instanceof JetProperty) {
final CodegenContext context = CodegenContext.STATIC.intoNamespace(descriptor); final CodegenContext context = CodegenContext.STATIC.intoNamespace(descriptor);
state.getMemberCodegen().generateFunctionOrProperty( genFunctionOrProperty(context, (JetTypeParameterListOwner) declaration, v.getClassBuilder());
(JetTypeParameterListOwner) declaration, context, v.getClassBuilder());
} }
else if (declaration instanceof JetNamedFunction) { else if (declaration instanceof JetNamedFunction) {
if (!multiFile) { if (!multiFile) {
final CodegenContext context = CodegenContext.STATIC.intoNamespace(descriptor); final CodegenContext context = CodegenContext.STATIC.intoNamespace(descriptor);
state.getMemberCodegen().generateFunctionOrProperty( genFunctionOrProperty(context, (JetTypeParameterListOwner) declaration, v.getClassBuilder());
(JetTypeParameterListOwner) declaration, context, v.getClassBuilder());
} }
} }
else if (declaration instanceof JetClassOrObject) { else if (declaration instanceof JetClassOrObject) {
final CodegenContext context = CodegenContext.STATIC.intoNamespace(descriptor); final CodegenContext context = CodegenContext.STATIC.intoNamespace(descriptor);
state.getClassCodegen().generate(context, (JetClassOrObject) declaration); genClassOrObject(context, (JetClassOrObject) declaration);
} }
else if (declaration instanceof JetScript) { else if (declaration instanceof JetScript) {
state.getScriptCodegen().generate((JetScript) declaration); state.getScriptCodegen().generate((JetScript) declaration);
@@ -157,7 +154,7 @@ public class NamespaceCodegen extends GenerationStateAware {
if (k > 0) { if (k > 0) {
PsiFile containingFile = file.getContainingFile(); PsiFile containingFile = file.getContainingFile();
String namespaceInternalName = name.child(Name.identifier(JvmAbi.PACKAGE_CLASS)).getFqName().replace('.', '/'); String namespaceInternalName = JvmClassName.byFqNameWithoutInnerClasses(name.child(Name.identifier(JvmAbi.PACKAGE_CLASS))).getInternalName();
String className = getMultiFileNamespaceInternalName(namespaceInternalName, containingFile); String className = getMultiFileNamespaceInternalName(namespaceInternalName, containingFile);
ClassBuilder builder = state.getFactory().forNamespacepart(className); ClassBuilder builder = state.getFactory().forNamespacepart(className);
@@ -176,14 +173,12 @@ public class NamespaceCodegen extends GenerationStateAware {
{ {
final CodegenContext context = final CodegenContext context =
CodegenContext.STATIC.intoNamespace(descriptor); CodegenContext.STATIC.intoNamespace(descriptor);
state.getMemberCodegen() genFunctionOrProperty(context, (JetTypeParameterListOwner) declaration, builder);
.generateFunctionOrProperty((JetTypeParameterListOwner) declaration, context, builder);
} }
{ {
final CodegenContext context = final CodegenContext context =
CodegenContext.STATIC.intoNamespacePart(className, descriptor); CodegenContext.STATIC.intoNamespacePart(className, descriptor);
state.getMemberCodegen() genFunctionOrProperty(context, (JetTypeParameterListOwner) declaration, v.getClassBuilder());
.generateFunctionOrProperty((JetTypeParameterListOwner) declaration, context, v.getClassBuilder());
} }
} }
} }
@@ -287,7 +282,7 @@ public class NamespaceCodegen extends GenerationStateAware {
return JvmClassName.byInternalName(JvmAbi.PACKAGE_CLASS); return JvmClassName.byInternalName(JvmAbi.PACKAGE_CLASS);
} }
return JvmClassName.byInternalName(fqName.getFqName().replace('.', '/') + "/" + JvmAbi.PACKAGE_CLASS); return JvmClassName.byFqNameWithoutInnerClasses(fqName.child(Name.identifier(JvmAbi.PACKAGE_CLASS)));
} }
@NotNull @NotNull
@@ -24,6 +24,7 @@ import org.jetbrains.asm4.MethodVisitor;
import org.jetbrains.asm4.Type; import org.jetbrains.asm4.Type;
import org.jetbrains.asm4.commons.InstructionAdapter; import org.jetbrains.asm4.commons.InstructionAdapter;
import org.jetbrains.jet.codegen.context.CodegenContext; import org.jetbrains.jet.codegen.context.CodegenContext;
import org.jetbrains.jet.codegen.signature.JvmMethodSignature;
import org.jetbrains.jet.codegen.signature.JvmPropertyAccessorSignature; import org.jetbrains.jet.codegen.signature.JvmPropertyAccessorSignature;
import org.jetbrains.jet.codegen.signature.kotlin.JetMethodAnnotationWriter; import org.jetbrains.jet.codegen.signature.kotlin.JetMethodAnnotationWriter;
import org.jetbrains.jet.codegen.state.GenerationStateAware; import org.jetbrains.jet.codegen.state.GenerationStateAware;
@@ -41,6 +42,8 @@ import org.jetbrains.jet.lang.types.lang.JetStandardLibrary;
import java.util.BitSet; import java.util.BitSet;
import static org.jetbrains.asm4.Opcodes.*; import static org.jetbrains.asm4.Opcodes.*;
import static org.jetbrains.jet.codegen.AsmUtil.genStubThrow;
import static org.jetbrains.jet.codegen.AsmUtil.getVisibilityAccessFlag;
import static org.jetbrains.jet.codegen.CodegenUtil.*; import static org.jetbrains.jet.codegen.CodegenUtil.*;
import static org.jetbrains.jet.lang.resolve.BindingContextUtils.descriptorToDeclaration; import static org.jetbrains.jet.lang.resolve.BindingContextUtils.descriptorToDeclaration;
import static org.jetbrains.jet.lang.resolve.java.AsmTypeConstants.OBJECT_TYPE; import static org.jetbrains.jet.lang.resolve.java.AsmTypeConstants.OBJECT_TYPE;
@@ -192,12 +195,13 @@ public class PropertyCodegen extends GenerationStateAware {
} }
JvmPropertyAccessorSignature signature = typeMapper.mapGetterSignature(propertyDescriptor, kind); JvmPropertyAccessorSignature signature = typeMapper.mapGetterSignature(propertyDescriptor, kind);
final String descriptor = signature.getJvmMethodSignature().getAsmMethod().getDescriptor(); final JvmMethodSignature jvmMethodSignature = signature.getJvmMethodSignature();
final String descriptor = jvmMethodSignature.getAsmMethod().getDescriptor();
String getterName = getterName(propertyDescriptor.getName()); String getterName = getterName(propertyDescriptor.getName());
MethodVisitor mv = v.newMethod(origin, flags, getterName, descriptor, null, null); MethodVisitor mv = v.newMethod(origin, flags, getterName, descriptor, jvmMethodSignature.getGenericsSignature(), null);
PropertyGetterDescriptor getter = propertyDescriptor.getGetter(); PropertyGetterDescriptor getter = propertyDescriptor.getGetter();
generateJetPropertyAnnotation(mv, signature.getPropertyTypeKotlinSignature(), generateJetPropertyAnnotation(mv, signature.getPropertyTypeKotlinSignature(),
signature.getJvmMethodSignature().getKotlinTypeParameter(), propertyDescriptor, jvmMethodSignature.getKotlinTypeParameter(), propertyDescriptor,
getter == null getter == null
? propertyDescriptor.getVisibility() ? propertyDescriptor.getVisibility()
: getter.getVisibility()); : getter.getVisibility());
@@ -212,7 +216,7 @@ public class PropertyCodegen extends GenerationStateAware {
if (propertyDescriptor.getModality() != Modality.ABSTRACT) { if (propertyDescriptor.getModality() != Modality.ABSTRACT) {
mv.visitCode(); mv.visitCode();
if (state.getClassBuilderMode() == ClassBuilderMode.STUBS) { if (state.getClassBuilderMode() == ClassBuilderMode.STUBS) {
StubCodegen.generateStubThrow(mv); genStubThrow(mv);
} }
else { else {
InstructionAdapter iv = new InstructionAdapter(mv); InstructionAdapter iv = new InstructionAdapter(mv);
@@ -298,12 +302,13 @@ public class PropertyCodegen extends GenerationStateAware {
JvmPropertyAccessorSignature signature = typeMapper.mapSetterSignature(propertyDescriptor, kind); JvmPropertyAccessorSignature signature = typeMapper.mapSetterSignature(propertyDescriptor, kind);
assert true; assert true;
final String descriptor = signature.getJvmMethodSignature().getAsmMethod().getDescriptor(); final JvmMethodSignature jvmMethodSignature = signature.getJvmMethodSignature();
MethodVisitor mv = v.newMethod(origin, flags, setterName(propertyDescriptor.getName()), descriptor, null, null); final String descriptor = jvmMethodSignature.getAsmMethod().getDescriptor();
MethodVisitor mv = v.newMethod(origin, flags, setterName(propertyDescriptor.getName()), descriptor, jvmMethodSignature.getGenericsSignature(), null);
PropertySetterDescriptor setter = propertyDescriptor.getSetter(); PropertySetterDescriptor setter = propertyDescriptor.getSetter();
assert setter != null; assert setter != null;
generateJetPropertyAnnotation(mv, signature.getPropertyTypeKotlinSignature(), generateJetPropertyAnnotation(mv, signature.getPropertyTypeKotlinSignature(),
signature.getJvmMethodSignature().getKotlinTypeParameter(), propertyDescriptor, jvmMethodSignature.getKotlinTypeParameter(), propertyDescriptor,
setter.getVisibility()); setter.getVisibility());
assert !setter.hasBody(); assert !setter.hasBody();
@@ -313,7 +318,7 @@ public class PropertyCodegen extends GenerationStateAware {
if (propertyDescriptor.getModality() != Modality.ABSTRACT) { if (propertyDescriptor.getModality() != Modality.ABSTRACT) {
mv.visitCode(); mv.visitCode();
if (state.getClassBuilderMode() == ClassBuilderMode.STUBS) { if (state.getClassBuilderMode() == ClassBuilderMode.STUBS) {
StubCodegen.generateStubThrow(mv); genStubThrow(mv);
} }
else { else {
InstructionAdapter iv = new InstructionAdapter(mv); InstructionAdapter iv = new InstructionAdapter(mv);
@@ -27,6 +27,8 @@ import org.jetbrains.jet.lang.types.lang.JetStandardLibrary;
import java.util.List; import java.util.List;
import static org.jetbrains.jet.codegen.AsmUtil.isPrimitiveNumberClassDescriptor;
/** /**
* @author abreslav * @author abreslav
*/ */
@@ -91,7 +93,7 @@ public class RangeCodegenUtil {
public static boolean isOptimizableRangeTo(CallableDescriptor rangeTo) { public static boolean isOptimizableRangeTo(CallableDescriptor rangeTo) {
if ("rangeTo".equals(rangeTo.getName().getName())) { if ("rangeTo".equals(rangeTo.getName().getName())) {
if (CodegenUtil.isPrimitiveNumberClassDescriptor(rangeTo.getContainingDeclaration())) { if (isPrimitiveNumberClassDescriptor(rangeTo.getContainingDeclaration())) {
return true; return true;
} }
} }
@@ -27,7 +27,6 @@ import org.jetbrains.jet.codegen.context.CodegenContext;
import org.jetbrains.jet.codegen.context.ScriptContext; import org.jetbrains.jet.codegen.context.ScriptContext;
import org.jetbrains.jet.codegen.signature.JvmMethodSignature; import org.jetbrains.jet.codegen.signature.JvmMethodSignature;
import org.jetbrains.jet.codegen.state.GenerationState; import org.jetbrains.jet.codegen.state.GenerationState;
import org.jetbrains.jet.codegen.state.GenerationStateAware;
import org.jetbrains.jet.codegen.state.GenerationStrategy; import org.jetbrains.jet.codegen.state.GenerationStrategy;
import org.jetbrains.jet.lang.descriptors.ClassDescriptor; import org.jetbrains.jet.lang.descriptors.ClassDescriptor;
import org.jetbrains.jet.lang.descriptors.ScriptDescriptor; import org.jetbrains.jet.lang.descriptors.ScriptDescriptor;
@@ -42,18 +41,16 @@ import java.util.Collections;
import java.util.List; import java.util.List;
import static org.jetbrains.asm4.Opcodes.*; import static org.jetbrains.asm4.Opcodes.*;
import static org.jetbrains.jet.lang.resolve.java.AsmTypeConstants.OBJECT_TYPE;
import static org.jetbrains.jet.codegen.binding.CodegenBinding.*; import static org.jetbrains.jet.codegen.binding.CodegenBinding.*;
import static org.jetbrains.jet.lang.resolve.java.AsmTypeConstants.OBJECT_TYPE;
/** /**
* @author Stepan Koltsov * @author Stepan Koltsov
*/ */
public class ScriptCodegen extends GenerationStateAware { public class ScriptCodegen extends MemberCodegen {
@NotNull @NotNull
private ClassFileFactory classFileFactory; private ClassFileFactory classFileFactory;
@NotNull
private MemberCodegen memberCodegen;
private List<ScriptDescriptor> earlierScripts; private List<ScriptDescriptor> earlierScripts;
private Method scriptConstructorMethod; private Method scriptConstructorMethod;
@@ -67,11 +64,6 @@ public class ScriptCodegen extends GenerationStateAware {
this.classFileFactory = classFileFactory; this.classFileFactory = classFileFactory;
} }
@Inject
public void setMemberCodegen(@NotNull MemberCodegen memberCodegen) {
this.memberCodegen = memberCodegen;
}
public void generate(JetScript scriptDeclaration) { public void generate(JetScript scriptDeclaration) {
ScriptDescriptor scriptDescriptor = state.getBindingContext().get(BindingContext.SCRIPT, scriptDeclaration); ScriptDescriptor scriptDescriptor = state.getBindingContext().get(BindingContext.SCRIPT, scriptDeclaration);
@@ -209,7 +201,7 @@ public class ScriptCodegen extends GenerationStateAware {
private void genMembers(@NotNull JetScript scriptDeclaration, @NotNull CodegenContext context, @NotNull ClassBuilder classBuilder) { private void genMembers(@NotNull JetScript scriptDeclaration, @NotNull CodegenContext context, @NotNull ClassBuilder classBuilder) {
for (JetDeclaration decl : scriptDeclaration.getDeclarations()) { for (JetDeclaration decl : scriptDeclaration.getDeclarations()) {
memberCodegen.generateFunctionOrProperty((JetTypeParameterListOwner) decl, context, classBuilder); genFunctionOrProperty(context, (JetTypeParameterListOwner) decl, classBuilder);
} }
} }
@@ -39,6 +39,8 @@ import org.jetbrains.jet.lexer.JetTokens;
import java.util.List; import java.util.List;
import static org.jetbrains.asm4.Opcodes.*; import static org.jetbrains.asm4.Opcodes.*;
import static org.jetbrains.jet.codegen.AsmUtil.boxType;
import static org.jetbrains.jet.codegen.AsmUtil.isIntPrimitive;
import static org.jetbrains.jet.lang.resolve.java.AsmTypeConstants.*; import static org.jetbrains.jet.lang.resolve.java.AsmTypeConstants.*;
/** /**
@@ -61,7 +63,7 @@ public abstract class StackValue {
instructionAdapter.aconst(null); instructionAdapter.aconst(null);
} }
else { else {
Type boxed = CodegenUtil.boxType(type); Type boxed = boxType(type);
instructionAdapter.invokestatic(boxed.getInternalName(), "valueOf", "(" + type.getDescriptor() + ")" + boxed.getDescriptor()); instructionAdapter.invokestatic(boxed.getInternalName(), "valueOf", "(" + type.getDescriptor() + ")" + boxed.getDescriptor());
} }
} }
@@ -76,7 +78,7 @@ public abstract class StackValue {
* JVM stack after this value was generated. * JVM stack after this value was generated.
* *
* @param type the type as which the value should be put * @param type the type as which the value should be put
* @param v the visitor used to generate the instructions * @param v the visitor used to genClassOrObject the instructions
* @param depth the number of new values put onto the stack * @param depth the number of new values put onto the stack
*/ */
protected void moveToTopOfStack(Type type, InstructionAdapter v, int depth) { protected void moveToTopOfStack(Type type, InstructionAdapter v, int depth) {
@@ -99,7 +101,7 @@ public abstract class StackValue {
public void condJump(Label label, boolean jumpIfFalse, InstructionAdapter v) { public void condJump(Label label, boolean jumpIfFalse, InstructionAdapter v) {
put(this.type, v); put(this.type, v);
coerce(Type.BOOLEAN_TYPE, v); coerceTo(Type.BOOLEAN_TYPE, v);
if (jumpIfFalse) { if (jumpIfFalse) {
v.ifeq(label); v.ifeq(label);
} }
@@ -171,7 +173,7 @@ public abstract class StackValue {
private static void box(final Type type, final Type toType, InstructionAdapter v) { private static void box(final Type type, final Type toType, InstructionAdapter v) {
// TODO handle toType correctly // TODO handle toType correctly
if (type == Type.INT_TYPE || (CodegenUtil.isIntPrimitive(type) && toType.getInternalName().equals("java/lang/Integer"))) { if (type == Type.INT_TYPE || (isIntPrimitive(type) && toType.getInternalName().equals("java/lang/Integer"))) {
v.invokestatic("java/lang/Integer", "valueOf", "(I)Ljava/lang/Integer;"); v.invokestatic("java/lang/Integer", "valueOf", "(I)Ljava/lang/Integer;");
} }
else if (type == Type.BOOLEAN_TYPE) { else if (type == Type.BOOLEAN_TYPE) {
@@ -231,7 +233,7 @@ public abstract class StackValue {
v.checkcast(type); v.checkcast(type);
} }
else { else {
coerce(type, v); coerceTo(type, v);
} }
} }
@@ -244,11 +246,15 @@ public abstract class StackValue {
} }
} }
protected void coerce(Type toType, InstructionAdapter v) { protected void coerceTo(Type toType, InstructionAdapter v) {
coerce(this.type, toType, v); coerce(this.type, toType, v);
} }
protected static void coerce(Type fromType, Type toType, InstructionAdapter v) { protected void coerceFrom(Type topOfStackType, InstructionAdapter v) {
coerce(topOfStackType, this.type, v);
}
public static void coerce(Type fromType, Type toType, InstructionAdapter v) {
if (toType.equals(fromType)) return; if (toType.equals(fromType)) return;
if (toType.getSort() == Type.VOID && fromType.getSort() != Type.VOID) { if (toType.getSort() == Type.VOID && fromType.getSort() != Type.VOID) {
@@ -306,7 +312,7 @@ public abstract class StackValue {
} }
public static void putTuple0Instance(InstructionAdapter v) { public static void putTuple0Instance(InstructionAdapter v) {
v.visitFieldInsn(GETSTATIC, "jet/Tuple0", "INSTANCE", "Ljet/Tuple0;"); v.visitFieldInsn(GETSTATIC, "jet/Tuple0", "VALUE", "Ljet/Tuple0;");
} }
protected void putAsBoolean(InstructionAdapter v) { protected void putAsBoolean(InstructionAdapter v) {
@@ -382,7 +388,7 @@ public abstract class StackValue {
@Override @Override
public void put(Type type, InstructionAdapter v) { public void put(Type type, InstructionAdapter v) {
coerce(type, v); coerceTo(type, v);
} }
} }
@@ -401,13 +407,13 @@ public abstract class StackValue {
@Override @Override
public void put(Type type, InstructionAdapter v) { public void put(Type type, InstructionAdapter v) {
v.load(index, this.type); v.load(index, this.type);
coerce(type, v); coerceTo(type, v);
// TODO unbox // TODO unbox
} }
@Override @Override
public void store(Type topOfStackType, InstructionAdapter v) { public void store(Type topOfStackType, InstructionAdapter v) {
coerce(topOfStackType, this.type, v); coerceFrom(topOfStackType, v);
v.store(index, this.type); v.store(index, this.type);
} }
} }
@@ -419,7 +425,7 @@ public abstract class StackValue {
@Override @Override
public void put(Type type, InstructionAdapter v) { public void put(Type type, InstructionAdapter v) {
coerce(type, v); coerceTo(type, v);
} }
@Override @Override
@@ -465,7 +471,7 @@ public abstract class StackValue {
else { else {
v.aconst(value); v.aconst(value);
} }
coerce(type, v); coerceTo(type, v);
} }
@Override @Override
@@ -610,18 +616,18 @@ public abstract class StackValue {
public ArrayElement(Type type, boolean unbox) { public ArrayElement(Type type, boolean unbox) {
super(type); super(type);
this.boxed = unbox ? CodegenUtil.boxType(type) : type; this.boxed = unbox ? boxType(type) : type;
} }
@Override @Override
public void put(Type type, InstructionAdapter v) { public void put(Type type, InstructionAdapter v) {
v.aload(boxed); // assumes array and index are on the stack v.aload(boxed); // assumes array and index are on the stack
onStack(boxed).coerce(type, v); coerce(boxed, type, v);
} }
@Override @Override
public void store(Type topOfStackType, InstructionAdapter v) { public void store(Type topOfStackType, InstructionAdapter v) {
onStack(type).coerce(boxed, v); coerce(topOfStackType, boxed, v);
v.astore(boxed); v.astore(boxed);
} }
@@ -677,7 +683,7 @@ public abstract class StackValue {
else { else {
((IntrinsicMethod) getter).generate(codegen, v, type, null, null, null, state); ((IntrinsicMethod) getter).generate(codegen, v, type, null, null, null, state);
} }
coerce(type, v); coerceTo(type, v);
} }
@Override @Override
@@ -901,7 +907,7 @@ public abstract class StackValue {
@Override @Override
public void put(Type type, InstructionAdapter v) { public void put(Type type, InstructionAdapter v) {
v.visitFieldInsn(isStatic ? GETSTATIC : GETFIELD, owner.getInternalName(), name, this.type.getDescriptor()); v.visitFieldInsn(isStatic ? GETSTATIC : GETFIELD, owner.getInternalName(), name, this.type.getDescriptor());
coerce(type, v); coerceTo(type, v);
} }
@Override @Override
@@ -918,7 +924,7 @@ public abstract class StackValue {
@Override @Override
public void store(Type topOfStackType, InstructionAdapter v) { public void store(Type topOfStackType, InstructionAdapter v) {
coerce(topOfStackType, this.type, v); coerceFrom(topOfStackType, v);
v.visitFieldInsn(isStatic ? PUTSTATIC : PUTFIELD, owner.getInternalName(), name, this.type.getDescriptor()); v.visitFieldInsn(isStatic ? PUTSTATIC : PUTFIELD, owner.getInternalName(), name, this.type.getDescriptor());
} }
} }
@@ -976,11 +982,12 @@ public abstract class StackValue {
v.visitMethodInsn(invokeOpcode, methodOwner.getInternalName(), getter.getName(), getter.getDescriptor()); v.visitMethodInsn(invokeOpcode, methodOwner.getInternalName(), getter.getName(), getter.getDescriptor());
} }
} }
coerce(type, v); coerceTo(type, v);
} }
@Override @Override
public void store(Type topOfStackType, InstructionAdapter v) { public void store(Type topOfStackType, InstructionAdapter v) {
coerceFrom(topOfStackType, v);
if (isSuper && isInterface) { if (isSuper && isInterface) {
assert setter != null; assert setter != null;
v.visitMethodInsn(INVOKESTATIC, methodOwner.getInternalName(), setter.getName(), v.visitMethodInsn(INVOKESTATIC, methodOwner.getInternalName(), setter.getName(),
@@ -1047,8 +1054,8 @@ public abstract class StackValue {
Type refType = refType(this.type); Type refType = refType(this.type);
Type sharedType = sharedTypeForType(this.type); Type sharedType = sharedTypeForType(this.type);
v.visitFieldInsn(GETFIELD, sharedType.getInternalName(), "ref", refType.getDescriptor()); v.visitFieldInsn(GETFIELD, sharedType.getInternalName(), "ref", refType.getDescriptor());
coerce(refType, this.type, v); coerceFrom(refType, v);
coerce(this.type, type, v); coerceTo(type, v);
if (isReleaseOnPut) { if (isReleaseOnPut) {
v.aconst(null); v.aconst(null);
v.store(index, OBJECT_TYPE); v.store(index, OBJECT_TYPE);
@@ -1057,6 +1064,7 @@ public abstract class StackValue {
@Override @Override
public void store(Type topOfStackType, InstructionAdapter v) { public void store(Type topOfStackType, InstructionAdapter v) {
coerceFrom(topOfStackType, v);
v.load(index, OBJECT_TYPE); v.load(index, OBJECT_TYPE);
v.swap(); v.swap();
Type refType = refType(this.type); Type refType = refType(this.type);
@@ -1133,13 +1141,13 @@ public abstract class StackValue {
Type sharedType = sharedTypeForType(this.type); Type sharedType = sharedTypeForType(this.type);
Type refType = refType(this.type); Type refType = refType(this.type);
v.visitFieldInsn(GETFIELD, sharedType.getInternalName(), "ref", refType.getDescriptor()); v.visitFieldInsn(GETFIELD, sharedType.getInternalName(), "ref", refType.getDescriptor());
StackValue.onStack(refType).coerce(this.type, v); coerceFrom(refType, v);
StackValue.onStack(this.type).coerce(type, v); coerceTo(type, v);
} }
@Override @Override
public void store(Type topOfStackType, InstructionAdapter v) { public void store(Type topOfStackType, InstructionAdapter v) {
coerce(topOfStackType, v); coerceFrom(topOfStackType, v);
v.visitFieldInsn(PUTFIELD, sharedTypeForType(type).getInternalName(), "ref", refType(type).getDescriptor()); v.visitFieldInsn(PUTFIELD, sharedTypeForType(type).getInternalName(), "ref", refType(type).getDescriptor());
} }
} }
@@ -1200,7 +1208,7 @@ public abstract class StackValue {
public void put(Type type, InstructionAdapter v) { public void put(Type type, InstructionAdapter v) {
if (!type.equals(Type.VOID_TYPE)) { if (!type.equals(Type.VOID_TYPE)) {
v.load(index, Type.INT_TYPE); v.load(index, Type.INT_TYPE);
coerce(type, v); coerceTo(type, v);
} }
v.iinc(index, increment); v.iinc(index, increment);
} }
@@ -1221,7 +1229,7 @@ public abstract class StackValue {
v.iinc(index, increment); v.iinc(index, increment);
if (!type.equals(Type.VOID_TYPE)) { if (!type.equals(Type.VOID_TYPE)) {
v.load(index, Type.INT_TYPE); v.load(index, Type.INT_TYPE);
coerce(type, v); coerceTo(type, v);
} }
} }
} }
@@ -1,41 +0,0 @@
/*
* 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;
import org.jetbrains.asm4.MethodVisitor;
import static org.jetbrains.jet.codegen.CodegenUtil.generateMethodThrow;
import static org.jetbrains.jet.codegen.CodegenUtil.generateThrow;
/**
* @author Stepan Koltsov
*/
public class StubCodegen {
private static final String STUB_EXCEPTION = "java/lang/RuntimeException";
private static final String STUB_EXCEPTION_MESSAGE = "Stubs are for compiler only, do not add them to runtime classpath";
private StubCodegen() {
}
public static void generateStubThrow(MethodVisitor mv) {
generateThrow(mv, STUB_EXCEPTION, STUB_EXCEPTION_MESSAGE);
}
public static void generateStubCode(MethodVisitor mv) {
generateMethodThrow(mv, STUB_EXCEPTION, STUB_EXCEPTION_MESSAGE);
}
}
@@ -115,7 +115,7 @@ class CodegenAnnotatingVisitor extends JetVisitorVoid {
nameStack.push(classNameForScriptPsi(bindingContext, file.getScript()).getInternalName()); nameStack.push(classNameForScriptPsi(bindingContext, file.getScript()).getInternalName());
} }
else { else {
nameStack.push(JetPsiUtil.getFQName(file).getFqName().replace('.', '/')); nameStack.push(JvmClassName.byFqNameWithoutInnerClasses(JetPsiUtil.getFQName(file)).getInternalName());
} }
file.acceptChildren(this); file.acceptChildren(this);
nameStack.pop(); nameStack.pop();
@@ -19,7 +19,6 @@ package org.jetbrains.jet.codegen.binding;
import com.intellij.psi.PsiElement; import com.intellij.psi.PsiElement;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.codegen.CodegenUtil;
import org.jetbrains.jet.lang.descriptors.*; import org.jetbrains.jet.lang.descriptors.*;
import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor; import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor;
import org.jetbrains.jet.lang.psi.*; import org.jetbrains.jet.lang.psi.*;
@@ -39,6 +38,7 @@ import java.util.Collection;
import java.util.Collections; import java.util.Collections;
import java.util.HashSet; import java.util.HashSet;
import static org.jetbrains.jet.codegen.CodegenUtil.isInterface;
import static org.jetbrains.jet.lang.resolve.BindingContext.*; import static org.jetbrains.jet.lang.resolve.BindingContext.*;
import static org.jetbrains.jet.lang.resolve.BindingContextUtils.descriptorToDeclaration; import static org.jetbrains.jet.lang.resolve.BindingContextUtils.descriptorToDeclaration;
@@ -365,7 +365,7 @@ public class CodegenBinding {
assert superType != null; assert superType != null;
ClassDescriptor superClassDescriptor = (ClassDescriptor) superType.getConstructor().getDeclarationDescriptor(); ClassDescriptor superClassDescriptor = (ClassDescriptor) superType.getConstructor().getDeclarationDescriptor();
assert superClassDescriptor != null; assert superClassDescriptor != null;
if (!CodegenUtil.isInterface(superClassDescriptor)) { if (!isInterface(superClassDescriptor)) {
return (JetDelegatorToSuperCall) specifier; return (JetDelegatorToSuperCall) specifier;
} }
} }
@@ -31,6 +31,7 @@ import java.util.Collections;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
import static org.jetbrains.jet.codegen.AsmUtil.THIS$0;
import static org.jetbrains.jet.codegen.binding.CodegenBinding.CLASS_FOR_FUNCTION; import static org.jetbrains.jet.codegen.binding.CodegenBinding.CLASS_FOR_FUNCTION;
import static org.jetbrains.jet.codegen.binding.CodegenBinding.FQN; import static org.jetbrains.jet.codegen.binding.CodegenBinding.FQN;
import static org.jetbrains.jet.lang.resolve.java.AsmTypeConstants.OBJECT_TYPE; import static org.jetbrains.jet.lang.resolve.java.AsmTypeConstants.OBJECT_TYPE;
@@ -261,7 +262,7 @@ public abstract class CodegenContext {
final ClassDescriptor enclosingClass = getEnclosingClass(); final ClassDescriptor enclosingClass = getEnclosingClass();
outerExpression = enclosingClass != null outerExpression = enclosingClass != null
? StackValue ? StackValue
.field(typeMapper.mapType(enclosingClass), CodegenBinding.getJvmInternalName(typeMapper.getBindingTrace(), classDescriptor), CodegenUtil.THIS$0, .field(typeMapper.mapType(enclosingClass), CodegenBinding.getJvmInternalName(typeMapper.getBindingTrace(), classDescriptor), THIS$0,
false) false)
: null; : null;
} }
@@ -17,7 +17,6 @@
package org.jetbrains.jet.codegen.context; package org.jetbrains.jet.codegen.context;
import org.jetbrains.asm4.Type; import org.jetbrains.asm4.Type;
import org.jetbrains.jet.codegen.CodegenUtil;
import org.jetbrains.jet.codegen.ExpressionCodegen; import org.jetbrains.jet.codegen.ExpressionCodegen;
import org.jetbrains.jet.codegen.StackValue; import org.jetbrains.jet.codegen.StackValue;
import org.jetbrains.jet.codegen.binding.MutableClosure; import org.jetbrains.jet.codegen.binding.MutableClosure;
@@ -27,6 +26,7 @@ import org.jetbrains.jet.lang.psi.JetElement;
import org.jetbrains.jet.lang.resolve.java.JvmClassName; import org.jetbrains.jet.lang.resolve.java.JvmClassName;
import org.jetbrains.jet.lang.types.JetType; import org.jetbrains.jet.lang.types.JetType;
import static org.jetbrains.jet.codegen.AsmUtil.RECEIVER$0;
import static org.jetbrains.jet.codegen.binding.CodegenBinding.classNameForAnonymousClass; import static org.jetbrains.jet.codegen.binding.CodegenBinding.classNameForAnonymousClass;
import static org.jetbrains.jet.codegen.binding.CodegenBinding.isLocalNamedFun; import static org.jetbrains.jet.codegen.binding.CodegenBinding.isLocalNamedFun;
import static org.jetbrains.jet.lang.resolve.BindingContextUtils.callableDescriptorToDeclaration; import static org.jetbrains.jet.lang.resolve.BindingContextUtils.callableDescriptorToDeclaration;
@@ -122,7 +122,7 @@ public interface LocalLookup {
final JetType receiverType = ((CallableDescriptor) d).getReceiverParameter().getType(); final JetType receiverType = ((CallableDescriptor) d).getReceiverParameter().getType();
Type type = state.getTypeMapper().mapType(receiverType); Type type = state.getTypeMapper().mapType(receiverType);
StackValue innerValue = StackValue.field(type, className, CodegenUtil.RECEIVER$0, false); StackValue innerValue = StackValue.field(type, className, RECEIVER$0, false);
closure.setCaptureReceiver(); closure.setCaptureReceiver();
return innerValue; return innerValue;
@@ -20,15 +20,16 @@ import com.intellij.psi.PsiElement;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.asm4.Type; import org.jetbrains.asm4.Type;
import org.jetbrains.asm4.commons.InstructionAdapter; import org.jetbrains.asm4.commons.InstructionAdapter;
import org.jetbrains.jet.lang.resolve.java.AsmTypeConstants;
import org.jetbrains.jet.codegen.CodegenUtil;
import org.jetbrains.jet.codegen.ExpressionCodegen; import org.jetbrains.jet.codegen.ExpressionCodegen;
import org.jetbrains.jet.codegen.StackValue; import org.jetbrains.jet.codegen.StackValue;
import org.jetbrains.jet.codegen.state.GenerationState; import org.jetbrains.jet.codegen.state.GenerationState;
import org.jetbrains.jet.lang.psi.JetExpression; import org.jetbrains.jet.lang.psi.JetExpression;
import org.jetbrains.jet.lang.resolve.java.AsmTypeConstants;
import java.util.List; import java.util.List;
import static org.jetbrains.jet.codegen.AsmUtil.correctElementType;
/** /**
* @author alex.tkachman * @author alex.tkachman
*/ */
@@ -44,7 +45,7 @@ public class ArrayGet implements IntrinsicMethod {
@NotNull GenerationState state @NotNull GenerationState state
) { ) {
receiver.put(AsmTypeConstants.OBJECT_TYPE, v); receiver.put(AsmTypeConstants.OBJECT_TYPE, v);
Type type = CodegenUtil.correctElementType(receiver.type); Type type = correctElementType(receiver.type);
codegen.gen(arguments.get(0), Type.INT_TYPE); codegen.gen(arguments.get(0), Type.INT_TYPE);
@@ -20,15 +20,16 @@ import com.intellij.psi.PsiElement;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.asm4.Type; import org.jetbrains.asm4.Type;
import org.jetbrains.asm4.commons.InstructionAdapter; import org.jetbrains.asm4.commons.InstructionAdapter;
import org.jetbrains.jet.lang.resolve.java.AsmTypeConstants;
import org.jetbrains.jet.codegen.CodegenUtil;
import org.jetbrains.jet.codegen.ExpressionCodegen; import org.jetbrains.jet.codegen.ExpressionCodegen;
import org.jetbrains.jet.codegen.StackValue; import org.jetbrains.jet.codegen.StackValue;
import org.jetbrains.jet.codegen.state.GenerationState; import org.jetbrains.jet.codegen.state.GenerationState;
import org.jetbrains.jet.lang.psi.JetExpression; import org.jetbrains.jet.lang.psi.JetExpression;
import org.jetbrains.jet.lang.resolve.java.AsmTypeConstants;
import java.util.List; import java.util.List;
import static org.jetbrains.jet.codegen.AsmUtil.correctElementType;
/** /**
* @author alex.tkachman * @author alex.tkachman
*/ */
@@ -44,7 +45,7 @@ public class ArraySet implements IntrinsicMethod {
@NotNull GenerationState state @NotNull GenerationState state
) { ) {
receiver.put(AsmTypeConstants.OBJECT_TYPE, v); receiver.put(AsmTypeConstants.OBJECT_TYPE, v);
Type type = CodegenUtil.correctElementType(receiver.type); Type type = correctElementType(receiver.type);
codegen.gen(arguments.get(0), Type.INT_TYPE); codegen.gen(arguments.get(0), Type.INT_TYPE);
codegen.gen(arguments.get(1), type); codegen.gen(arguments.get(1), type);
@@ -20,7 +20,6 @@ import com.intellij.psi.PsiElement;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.asm4.Type; import org.jetbrains.asm4.Type;
import org.jetbrains.asm4.commons.InstructionAdapter; import org.jetbrains.asm4.commons.InstructionAdapter;
import org.jetbrains.jet.codegen.CodegenUtil;
import org.jetbrains.jet.codegen.ExpressionCodegen; import org.jetbrains.jet.codegen.ExpressionCodegen;
import org.jetbrains.jet.codegen.StackValue; import org.jetbrains.jet.codegen.StackValue;
import org.jetbrains.jet.codegen.state.GenerationState; import org.jetbrains.jet.codegen.state.GenerationState;
@@ -29,6 +28,8 @@ import org.jetbrains.jet.lang.psi.JetExpression;
import java.util.List; import java.util.List;
import static org.jetbrains.asm4.Opcodes.*; import static org.jetbrains.asm4.Opcodes.*;
import static org.jetbrains.jet.codegen.AsmUtil.boxType;
import static org.jetbrains.jet.codegen.AsmUtil.unboxType;
/** /**
* @author yole * @author yole
@@ -52,7 +53,7 @@ public class BinaryOp implements IntrinsicMethod {
) { ) {
boolean nullable = expectedType.getSort() == Type.OBJECT; boolean nullable = expectedType.getSort() == Type.OBJECT;
if (nullable) { if (nullable) {
expectedType = CodegenUtil.unboxType(expectedType); expectedType = unboxType(expectedType);
} }
if (arguments.size() == 1) { if (arguments.size() == 1) {
// Intrinsic is called as an ordinary function // Intrinsic is called as an ordinary function
@@ -68,7 +69,7 @@ public class BinaryOp implements IntrinsicMethod {
v.visitInsn(expectedType.getOpcode(opcode)); v.visitInsn(expectedType.getOpcode(opcode));
if (nullable) { if (nullable) {
StackValue.onStack(expectedType).put(expectedType = CodegenUtil.boxType(expectedType), v); StackValue.onStack(expectedType).put(expectedType = boxType(expectedType), v);
} }
return StackValue.onStack(expectedType); return StackValue.onStack(expectedType);
} }
@@ -20,7 +20,6 @@ import com.intellij.psi.PsiElement;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.asm4.Type; import org.jetbrains.asm4.Type;
import org.jetbrains.asm4.commons.InstructionAdapter; import org.jetbrains.asm4.commons.InstructionAdapter;
import org.jetbrains.jet.codegen.CodegenUtil;
import org.jetbrains.jet.codegen.ExpressionCodegen; import org.jetbrains.jet.codegen.ExpressionCodegen;
import org.jetbrains.jet.codegen.StackValue; import org.jetbrains.jet.codegen.StackValue;
import org.jetbrains.jet.codegen.state.GenerationState; import org.jetbrains.jet.codegen.state.GenerationState;
@@ -29,6 +28,9 @@ import org.jetbrains.jet.lang.resolve.java.AsmTypeConstants;
import java.util.List; import java.util.List;
import static org.jetbrains.jet.codegen.AsmUtil.genInvokeAppendMethod;
import static org.jetbrains.jet.codegen.AsmUtil.genStringBuilderConstructor;
/** /**
* @author yole * @author yole
*/ */
@@ -44,15 +46,15 @@ public class Concat implements IntrinsicMethod {
@NotNull GenerationState state @NotNull GenerationState state
) { ) {
if (receiver == null || receiver == StackValue.none()) { // LHS + RHS if (receiver == null || receiver == StackValue.none()) { // LHS + RHS
CodegenUtil.generateStringBuilderConstructor(v); genStringBuilderConstructor(v);
codegen.invokeAppend(arguments.get(0)); // StringBuilder(LHS) codegen.invokeAppend(arguments.get(0)); // StringBuilder(LHS)
codegen.invokeAppend(arguments.get(1)); codegen.invokeAppend(arguments.get(1));
} }
else { // LHS.plus(RHS) else { // LHS.plus(RHS)
receiver.put(AsmTypeConstants.OBJECT_TYPE, v); receiver.put(AsmTypeConstants.OBJECT_TYPE, v);
CodegenUtil.generateStringBuilderConstructor(v); genStringBuilderConstructor(v);
v.swap(); // StringBuilder LHS v.swap(); // StringBuilder LHS
CodegenUtil.invokeAppendMethod(v, expectedType); // StringBuilder(LHS) genInvokeAppendMethod(v, expectedType); // StringBuilder(LHS)
codegen.invokeAppend(arguments.get(0)); codegen.invokeAppend(arguments.get(0));
} }
@@ -20,18 +20,20 @@ import com.intellij.psi.PsiElement;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.asm4.Type; import org.jetbrains.asm4.Type;
import org.jetbrains.asm4.commons.InstructionAdapter; import org.jetbrains.asm4.commons.InstructionAdapter;
import org.jetbrains.jet.lang.resolve.java.AsmTypeConstants;
import org.jetbrains.jet.codegen.ExpressionCodegen; import org.jetbrains.jet.codegen.ExpressionCodegen;
import org.jetbrains.jet.codegen.StackValue; import org.jetbrains.jet.codegen.StackValue;
import org.jetbrains.jet.codegen.state.GenerationState; import org.jetbrains.jet.codegen.state.GenerationState;
import org.jetbrains.jet.lang.psi.JetCallExpression; import org.jetbrains.jet.lang.psi.JetCallExpression;
import org.jetbrains.jet.lang.psi.JetExpression; import org.jetbrains.jet.lang.psi.JetExpression;
import org.jetbrains.jet.lang.resolve.BindingContext; import org.jetbrains.jet.lang.resolve.BindingContext;
import org.jetbrains.jet.lang.resolve.java.AsmTypeConstants;
import org.jetbrains.jet.lang.types.JetType; import org.jetbrains.jet.lang.types.JetType;
import org.jetbrains.jet.lexer.JetTokens; import org.jetbrains.jet.lexer.JetTokens;
import java.util.List; import java.util.List;
import static org.jetbrains.jet.codegen.AsmUtil.genEqualsForExpressionsOnStack;
/** /**
* @author alex.tkachman * @author alex.tkachman
*/ */
@@ -74,8 +76,8 @@ public class Equals implements IntrinsicMethod {
codegen.gen(rightExpr).put(AsmTypeConstants.OBJECT_TYPE, v); codegen.gen(rightExpr).put(AsmTypeConstants.OBJECT_TYPE, v);
assert rightType != null; assert rightType != null;
return codegen return genEqualsForExpressionsOnStack(v, JetTokens.EQEQ, AsmTypeConstants.OBJECT_TYPE, AsmTypeConstants.OBJECT_TYPE,
.generateEqualsForExpressionsOnStack(JetTokens.EQEQ, AsmTypeConstants.OBJECT_TYPE, AsmTypeConstants.OBJECT_TYPE, leftNullable, leftNullable,
rightType.isNullable()); rightType.isNullable());
} }
} }
@@ -20,7 +20,6 @@ import com.intellij.psi.PsiElement;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.asm4.Type; import org.jetbrains.asm4.Type;
import org.jetbrains.asm4.commons.InstructionAdapter; import org.jetbrains.asm4.commons.InstructionAdapter;
import org.jetbrains.jet.codegen.CodegenUtil;
import org.jetbrains.jet.codegen.ExpressionCodegen; import org.jetbrains.jet.codegen.ExpressionCodegen;
import org.jetbrains.jet.codegen.StackValue; import org.jetbrains.jet.codegen.StackValue;
import org.jetbrains.jet.codegen.state.GenerationState; import org.jetbrains.jet.codegen.state.GenerationState;
@@ -30,6 +29,8 @@ import org.jetbrains.jet.lang.psi.JetReferenceExpression;
import java.util.List; import java.util.List;
import static org.jetbrains.jet.codegen.AsmUtil.*;
/** /**
* @author yole * @author yole
*/ */
@@ -52,7 +53,7 @@ public class Increment implements IntrinsicMethod {
) { ) {
boolean nullable = expectedType.getSort() == Type.OBJECT; boolean nullable = expectedType.getSort() == Type.OBJECT;
if (nullable) { if (nullable) {
expectedType = CodegenUtil.unboxType(expectedType); expectedType = unboxType(expectedType);
} }
if (arguments.size() > 0) { if (arguments.size() > 0) {
JetExpression operand = arguments.get(0); JetExpression operand = arguments.get(0);
@@ -61,7 +62,7 @@ public class Increment implements IntrinsicMethod {
} }
if (operand instanceof JetReferenceExpression) { if (operand instanceof JetReferenceExpression) {
final int index = codegen.indexOfLocal((JetReferenceExpression) operand); final int index = codegen.indexOfLocal((JetReferenceExpression) operand);
if (index >= 0 && CodegenUtil.isIntPrimitive(expectedType)) { if (index >= 0 && isIntPrimitive(expectedType)) {
return StackValue.preIncrement(index, myDelta); return StackValue.preIncrement(index, myDelta);
} }
} }
@@ -70,30 +71,13 @@ public class Increment implements IntrinsicMethod {
value.dupReceiver(v); value.dupReceiver(v);
value.put(expectedType, v); value.put(expectedType, v);
plusMinus(v, expectedType); value.store(genIncrement(expectedType, myDelta, v), v);
value.store(expectedType, v);
value.put(expectedType, v); value.put(expectedType, v);
} }
else { else {
receiver.put(expectedType, v); receiver.put(expectedType, v);
plusMinus(v, expectedType); StackValue.coerce(genIncrement(expectedType, myDelta, v), expectedType, v);
} }
return StackValue.onStack(expectedType); return StackValue.onStack(expectedType);
} }
private void plusMinus(InstructionAdapter v, Type expectedType) {
if (expectedType == Type.LONG_TYPE) {
v.lconst(myDelta);
}
else if (expectedType == Type.FLOAT_TYPE) {
v.fconst(myDelta);
}
else if (expectedType == Type.DOUBLE_TYPE) {
v.dconst(myDelta);
}
else {
v.iconst(myDelta);
}
v.add(expectedType);
}
} }
@@ -66,7 +66,7 @@ public class IntrinsicMethods {
private static final String KOTLIN_HASH_CODE = "kotlin.hashCode"; private static final String KOTLIN_HASH_CODE = "kotlin.hashCode";
private static final EnumValues ENUM_VALUES = new EnumValues(); private static final EnumValues ENUM_VALUES = new EnumValues();
private static final EnumValueOf ENUM_VALUE_OF = new EnumValueOf(); private static final EnumValueOf ENUM_VALUE_OF = new EnumValueOf();
public static final ToString TO_STRING = new ToString(); private static final ToString TO_STRING = new ToString();
private final Map<String, IntrinsicMethod> namedMethods = new HashMap<String, IntrinsicMethod>(); private final Map<String, IntrinsicMethod> namedMethods = new HashMap<String, IntrinsicMethod>();
private static final IntrinsicMethod ARRAY_ITERATOR = new ArrayIterator(); private static final IntrinsicMethod ARRAY_ITERATOR = new ArrayIterator();
@@ -127,7 +127,6 @@ public class IntrinsicMethods {
intrinsicsMap.registerIntrinsic(JetStandardClasses.STANDARD_CLASSES_FQNAME, Name.identifier("identityEquals"), 1, IDENTITY_EQUALS); intrinsicsMap.registerIntrinsic(JetStandardClasses.STANDARD_CLASSES_FQNAME, Name.identifier("identityEquals"), 1, IDENTITY_EQUALS);
intrinsicsMap.registerIntrinsic(JetStandardClasses.STANDARD_CLASSES_FQNAME, Name.identifier("plus"), 1, STRING_PLUS); intrinsicsMap.registerIntrinsic(JetStandardClasses.STANDARD_CLASSES_FQNAME, Name.identifier("plus"), 1, STRING_PLUS);
intrinsicsMap.registerIntrinsic(JetStandardClasses.STANDARD_CLASSES_FQNAME, Name.identifier("arrayOfNulls"), 1, new NewArray()); intrinsicsMap.registerIntrinsic(JetStandardClasses.STANDARD_CLASSES_FQNAME, Name.identifier("arrayOfNulls"), 1, new NewArray());
intrinsicsMap.registerIntrinsic(JetStandardClasses.STANDARD_CLASSES_FQNAME, Name.identifier("sure"), 0, new Sure());
intrinsicsMap.registerIntrinsic(JetStandardClasses.STANDARD_CLASSES_FQNAME, Name.identifier("synchronized"), 2, new StupidSync()); intrinsicsMap.registerIntrinsic(JetStandardClasses.STANDARD_CLASSES_FQNAME, Name.identifier("synchronized"), 2, new StupidSync());
intrinsicsMap.registerIntrinsic(JetStandardClasses.STANDARD_CLASSES_FQNAME, Name.identifier("iterator"), 0, new IteratorIterator()); intrinsicsMap.registerIntrinsic(JetStandardClasses.STANDARD_CLASSES_FQNAME, Name.identifier("iterator"), 0, new IteratorIterator());
@@ -149,16 +148,25 @@ public class IntrinsicMethods {
declareIntrinsicProperty(Name.identifier("CharSequence"), Name.identifier("length"), new StringLength()); declareIntrinsicProperty(Name.identifier("CharSequence"), Name.identifier("length"), new StringLength());
declareIntrinsicProperty(Name.identifier("String"), Name.identifier("length"), new StringLength()); declareIntrinsicProperty(Name.identifier("String"), Name.identifier("length"), new StringLength());
Name tuple0Name = JetStandardClasses.getTuple(0).getName();
intrinsicsMap.registerIntrinsic(
getClassObjectFqName(tuple0Name),
Name.identifier("VALUE"), -1, new UnitValue());
for (PrimitiveType type : PrimitiveType.NUMBER_TYPES) { for (PrimitiveType type : PrimitiveType.NUMBER_TYPES) {
intrinsicsMap.registerIntrinsic( intrinsicsMap.registerIntrinsic(
JetStandardClasses.STANDARD_CLASSES_FQNAME.child(type.getRangeTypeName()).toUnsafe().child( getClassObjectFqName(type.getRangeTypeName()),
getClassObjectName(type.getRangeTypeName())),
Name.identifier("EMPTY"), -1, new EmptyRange(type)); Name.identifier("EMPTY"), -1, new EmptyRange(type));
} }
declareArrayMethods(); declareArrayMethods();
} }
@NotNull
private static FqNameUnsafe getClassObjectFqName(@NotNull Name builtinClassName) {
return JetStandardClasses.STANDARD_CLASSES_FQNAME.child(builtinClassName).toUnsafe().child(getClassObjectName(builtinClassName));
}
private void declareArrayMethods() { private void declareArrayMethods() {
for (JvmPrimitiveType jvmPrimitiveType : JvmPrimitiveType.values()) { for (JvmPrimitiveType jvmPrimitiveType : JvmPrimitiveType.values()) {
@@ -20,7 +20,6 @@ import com.intellij.psi.PsiElement;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.asm4.Type; import org.jetbrains.asm4.Type;
import org.jetbrains.asm4.commons.InstructionAdapter; import org.jetbrains.asm4.commons.InstructionAdapter;
import org.jetbrains.jet.codegen.CodegenUtil;
import org.jetbrains.jet.codegen.ExpressionCodegen; import org.jetbrains.jet.codegen.ExpressionCodegen;
import org.jetbrains.jet.codegen.StackValue; import org.jetbrains.jet.codegen.StackValue;
import org.jetbrains.jet.codegen.state.GenerationState; import org.jetbrains.jet.codegen.state.GenerationState;
@@ -28,6 +27,8 @@ import org.jetbrains.jet.lang.psi.JetExpression;
import java.util.List; import java.util.List;
import static org.jetbrains.jet.codegen.AsmUtil.unboxType;
/** /**
* @author yole * @author yole
* @author alex.tkachman * @author alex.tkachman
@@ -45,7 +46,7 @@ public class Inv implements IntrinsicMethod {
) { ) {
boolean nullable = expectedType.getSort() == Type.OBJECT; boolean nullable = expectedType.getSort() == Type.OBJECT;
if (nullable) { if (nullable) {
expectedType = CodegenUtil.unboxType(expectedType); expectedType = unboxType(expectedType);
} }
receiver.put(expectedType, v); receiver.put(expectedType, v);
if (expectedType == Type.LONG_TYPE) { if (expectedType == Type.LONG_TYPE) {
@@ -20,7 +20,6 @@ import com.intellij.psi.PsiElement;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.asm4.Type; import org.jetbrains.asm4.Type;
import org.jetbrains.asm4.commons.InstructionAdapter; import org.jetbrains.asm4.commons.InstructionAdapter;
import org.jetbrains.jet.codegen.CodegenUtil;
import org.jetbrains.jet.codegen.ExpressionCodegen; import org.jetbrains.jet.codegen.ExpressionCodegen;
import org.jetbrains.jet.codegen.StackValue; import org.jetbrains.jet.codegen.StackValue;
import org.jetbrains.jet.codegen.state.GenerationState; import org.jetbrains.jet.codegen.state.GenerationState;
@@ -28,6 +27,8 @@ import org.jetbrains.jet.lang.psi.JetExpression;
import java.util.List; import java.util.List;
import static org.jetbrains.jet.codegen.AsmUtil.genToString;
/** /**
* @author alex.tkachman * @author alex.tkachman
*/ */
@@ -42,6 +43,6 @@ public class ToString implements IntrinsicMethod {
StackValue receiver, StackValue receiver,
@NotNull GenerationState state @NotNull GenerationState state
) { ) {
return CodegenUtil.genToString(v, receiver); return genToString(v, receiver);
} }
} }
@@ -20,7 +20,6 @@ import com.intellij.psi.PsiElement;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.asm4.Type; import org.jetbrains.asm4.Type;
import org.jetbrains.asm4.commons.InstructionAdapter; import org.jetbrains.asm4.commons.InstructionAdapter;
import org.jetbrains.jet.codegen.CodegenUtil;
import org.jetbrains.jet.codegen.ExpressionCodegen; import org.jetbrains.jet.codegen.ExpressionCodegen;
import org.jetbrains.jet.codegen.StackValue; import org.jetbrains.jet.codegen.StackValue;
import org.jetbrains.jet.codegen.state.GenerationState; import org.jetbrains.jet.codegen.state.GenerationState;
@@ -28,6 +27,9 @@ import org.jetbrains.jet.lang.psi.JetExpression;
import java.util.List; import java.util.List;
import static org.jetbrains.jet.codegen.AsmUtil.genNegate;
import static org.jetbrains.jet.codegen.AsmUtil.unboxType;
/** /**
* @author yole * @author yole
*/ */
@@ -44,7 +46,7 @@ public class UnaryMinus implements IntrinsicMethod {
) { ) {
boolean nullable = expectedType.getSort() == Type.OBJECT; boolean nullable = expectedType.getSort() == Type.OBJECT;
if (nullable) { if (nullable) {
expectedType = CodegenUtil.unboxType(expectedType); expectedType = unboxType(expectedType);
} }
if (arguments.size() == 1) { if (arguments.size() == 1) {
codegen.gen(arguments.get(0), expectedType); codegen.gen(arguments.get(0), expectedType);
@@ -52,7 +54,7 @@ public class UnaryMinus implements IntrinsicMethod {
else { else {
receiver.put(expectedType, v); receiver.put(expectedType, v);
} }
v.neg(expectedType); StackValue.coerce(genNegate(expectedType, v), expectedType, v);
return StackValue.onStack(expectedType); return StackValue.onStack(expectedType);
} }
} }
@@ -21,7 +21,6 @@ import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import org.jetbrains.asm4.Type; import org.jetbrains.asm4.Type;
import org.jetbrains.asm4.commons.InstructionAdapter; import org.jetbrains.asm4.commons.InstructionAdapter;
import org.jetbrains.jet.codegen.CodegenUtil;
import org.jetbrains.jet.codegen.ExpressionCodegen; import org.jetbrains.jet.codegen.ExpressionCodegen;
import org.jetbrains.jet.codegen.StackValue; import org.jetbrains.jet.codegen.StackValue;
import org.jetbrains.jet.codegen.state.GenerationState; import org.jetbrains.jet.codegen.state.GenerationState;
@@ -29,6 +28,8 @@ import org.jetbrains.jet.lang.psi.JetExpression;
import java.util.List; import java.util.List;
import static org.jetbrains.jet.codegen.AsmUtil.unboxType;
/** /**
* @author alex.tkachman * @author alex.tkachman
*/ */
@@ -45,7 +46,7 @@ public class UnaryPlus implements IntrinsicMethod {
) { ) {
boolean nullable = expectedType.getSort() == Type.OBJECT; boolean nullable = expectedType.getSort() == Type.OBJECT;
if (nullable) { if (nullable) {
expectedType = CodegenUtil.unboxType(expectedType); expectedType = unboxType(expectedType);
} }
if (receiver != null && receiver != StackValue.none()) { if (receiver != null && receiver != StackValue.none()) {
receiver.put(expectedType, v); receiver.put(expectedType, v);
@@ -18,50 +18,34 @@ package org.jetbrains.jet.codegen.intrinsics;
import com.intellij.psi.PsiElement; import com.intellij.psi.PsiElement;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.asm4.Label; import org.jetbrains.annotations.Nullable;
import org.jetbrains.asm4.Type; import org.jetbrains.asm4.Type;
import org.jetbrains.asm4.commons.InstructionAdapter; import org.jetbrains.asm4.commons.InstructionAdapter;
import org.jetbrains.jet.codegen.ExpressionCodegen; import org.jetbrains.jet.codegen.ExpressionCodegen;
import org.jetbrains.jet.codegen.StackValue; import org.jetbrains.jet.codegen.StackValue;
import org.jetbrains.jet.codegen.state.GenerationState; import org.jetbrains.jet.codegen.state.GenerationState;
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.psi.JetExpression;
import org.jetbrains.jet.lang.resolve.BindingContext;
import org.jetbrains.jet.lang.resolve.calls.ResolvedCall;
import java.util.List; import java.util.List;
import static org.jetbrains.jet.lang.resolve.java.AsmTypeConstants.JET_TUPLE0_TYPE;
/** /**
* @author alex.tkachman * @author abreslav
*/ */
public class Sure implements IntrinsicMethod { public class UnitValue implements IntrinsicMethod {
@Override @Override
public StackValue generate( public StackValue generate(
ExpressionCodegen codegen, ExpressionCodegen codegen,
InstructionAdapter v, InstructionAdapter v,
@NotNull Type expectedType, @NotNull Type expectedType,
PsiElement element, @Nullable PsiElement element,
List<JetExpression> arguments, @Nullable List<JetExpression> arguments,
StackValue receiver, StackValue receiver,
@NotNull GenerationState state @NotNull GenerationState state
) { ) {
JetCallExpression call = (JetCallExpression) element; v.getstatic(JET_TUPLE0_TYPE.getInternalName(), "VALUE", JET_TUPLE0_TYPE.getDescriptor());
ResolvedCall<? extends CallableDescriptor> resolvedCall =
codegen.getBindingContext().get(BindingContext.RESOLVED_CALL, call.getCalleeExpression());
assert resolvedCall != null;
if (resolvedCall.getReceiverArgument().getType().isNullable()) {
receiver.put(receiver.type, v);
v.dup();
Label ok = new Label();
v.ifnonnull(ok);
v.invokestatic("jet/runtime/Intrinsics", "throwNpe", "()V");
v.mark(ok);
StackValue.onStack(receiver.type).put(expectedType, v);
}
else {
codegen.generateFromResolvedCall(resolvedCall.getReceiverArgument(), expectedType);
}
return StackValue.onStack(expectedType); return StackValue.onStack(expectedType);
} }
} }
@@ -152,19 +152,22 @@ public class BothSignatureWriter {
state = to; state = to;
} }
public void writeAsmType(Type asmType, boolean nullable) {
writeAsmType(asmType, nullable, null);
}
/** /**
* Shortcut * Shortcut
*/ */
public void writeAsmType(Type asmType, boolean nullable) { public void writeAsmType(Type asmType, boolean nullable, @Nullable String kotlinTypeName) {
switch (asmType.getSort()) { switch (asmType.getSort()) {
case Type.OBJECT: case Type.OBJECT:
writeClassBegin(asmType.getInternalName(), nullable, false); writeClassBegin(asmType.getInternalName(), nullable, false, kotlinTypeName);
writeClassEnd(); writeClassEnd();
return; return;
case Type.ARRAY: case Type.ARRAY:
writeArrayType(nullable); writeArrayType(nullable);
writeAsmType(asmType.getElementType(), false); writeAsmType(asmType.getElementType(), false, kotlinTypeName);
writeArrayEnd(); writeArrayEnd();
return; return;
default: default:
@@ -218,8 +221,12 @@ public class BothSignatureWriter {
} }
public void writeClassBegin(String internalName, boolean nullable, boolean real) { public void writeClassBegin(String internalName, boolean nullable, boolean real) {
writeClassBegin(internalName, nullable, real, null);
}
public void writeClassBegin(String internalName, boolean nullable, boolean real, @Nullable String kotlinTypeName) {
signatureVisitor().visitClassType(internalName); signatureVisitor().visitClassType(internalName);
jetSignatureWriter.visitClassType(internalName, nullable, real); jetSignatureWriter.visitClassType(kotlinTypeName == null ? internalName : kotlinTypeName, nullable, real);
writeAsmType0(Type.getObjectType(internalName)); writeAsmType0(Type.getObjectType(internalName));
} }
@@ -68,12 +68,6 @@ public class GenerationState {
@NotNull @NotNull
private final JetTypeMapper typeMapper; private final JetTypeMapper typeMapper;
@NotNull
private final MemberCodegen memberCodegen;
@NotNull
private final ClassCodegen classCodegen;
public GenerationState(Project project, ClassBuilderFactory builderFactory, AnalyzeExhaust analyzeExhaust, List<JetFile> files) { public GenerationState(Project project, ClassBuilderFactory builderFactory, AnalyzeExhaust analyzeExhaust, List<JetFile> files) {
this(project, builderFactory, Progress.DEAF, analyzeExhaust, files, BuiltinToJavaTypesMapping.ENABLED); this(project, builderFactory, Progress.DEAF, analyzeExhaust, files, BuiltinToJavaTypesMapping.ENABLED);
} }
@@ -98,8 +92,6 @@ public class GenerationState {
builtinToJavaTypesMapping, this, builderFactory, project); builtinToJavaTypesMapping, this, builderFactory, project);
this.scriptCodegen = injector.getScriptCodegen(); this.scriptCodegen = injector.getScriptCodegen();
this.memberCodegen = injector.getMemberCodegen();
this.classCodegen = injector.getClassCodegen();
this.intrinsics = injector.getIntrinsics(); this.intrinsics = injector.getIntrinsics();
this.classFileFactory = injector.getClassFileFactory(); this.classFileFactory = injector.getClassFileFactory();
} }
@@ -154,16 +146,6 @@ public class GenerationState {
return intrinsics; return intrinsics;
} }
@NotNull
public MemberCodegen getMemberCodegen() {
return memberCodegen;
}
@NotNull
public ClassCodegen getClassCodegen() {
return classCodegen;
}
public void beforeCompile() { public void beforeCompile() {
markUsed(); markUsed();
@@ -46,6 +46,7 @@ import java.util.List;
import java.util.Map; import java.util.Map;
import static org.jetbrains.asm4.Opcodes.*; import static org.jetbrains.asm4.Opcodes.*;
import static org.jetbrains.jet.codegen.AsmUtil.boxType;
import static org.jetbrains.jet.codegen.CodegenUtil.*; import static org.jetbrains.jet.codegen.CodegenUtil.*;
import static org.jetbrains.jet.codegen.binding.CodegenBinding.*; import static org.jetbrains.jet.codegen.binding.CodegenBinding.*;
import static org.jetbrains.jet.lang.resolve.BindingContextUtils.descriptorToDeclaration; import static org.jetbrains.jet.lang.resolve.BindingContextUtils.descriptorToDeclaration;
@@ -262,7 +263,7 @@ public class JetTypeMapper extends BindingTraceAware {
} }
Type asmType = Type.getObjectType("error/NonExistentClass"); Type asmType = Type.getObjectType("error/NonExistentClass");
if (signatureVisitor != null) { if (signatureVisitor != null) {
writeSimpleType(signatureVisitor, asmType, true); signatureVisitor.writeAsmType(asmType, true);
} }
checkValidType(asmType); checkValidType(asmType);
return asmType; return asmType;
@@ -302,7 +303,7 @@ public class JetTypeMapper extends BindingTraceAware {
} }
boolean forceReal = KotlinToJavaTypesMap.getInstance().isForceReal(name); boolean forceReal = KotlinToJavaTypesMap.getInstance().isForceReal(name);
writeGenericType(jetType, signatureVisitor, asmType, forceReal); writeGenericType(signatureVisitor, asmType, jetType, forceReal);
checkValidType(asmType); checkValidType(asmType);
return asmType; return asmType;
@@ -339,9 +340,10 @@ public class JetTypeMapper extends BindingTraceAware {
parentDeclarationElement != null ? parentDeclarationElement.getText() : "null"); parentDeclarationElement != null ? parentDeclarationElement.getText() : "null");
} }
private void writeGenericType(JetType jetType, BothSignatureWriter signatureVisitor, Type asmType, boolean forceReal) { private void writeGenericType(BothSignatureWriter signatureVisitor, Type asmType, JetType jetType, boolean forceReal) {
if (signatureVisitor != null) { if (signatureVisitor != null) {
signatureVisitor.writeClassBegin(asmType.getInternalName(), jetType.isNullable(), forceReal); String kotlinTypeName = getKotlinTypeNameForSignature(jetType, asmType);
signatureVisitor.writeClassBegin(asmType.getInternalName(), jetType.isNullable(), forceReal, kotlinTypeName);
for (TypeProjection proj : jetType.getArguments()) { for (TypeProjection proj : jetType.getArguments()) {
// TODO: +- // TODO: +-
signatureVisitor.writeTypeArgument(proj.getProjectionKind()); signatureVisitor.writeTypeArgument(proj.getProjectionKind());
@@ -355,18 +357,28 @@ public class JetTypeMapper extends BindingTraceAware {
private Type mapKnownAsmType(JetType jetType, Type asmType, @Nullable BothSignatureWriter signatureVisitor) { private Type mapKnownAsmType(JetType jetType, Type asmType, @Nullable BothSignatureWriter signatureVisitor) {
if (signatureVisitor != null) { if (signatureVisitor != null) {
if (jetType.getArguments().isEmpty()) { if (jetType.getArguments().isEmpty()) {
writeSimpleType(signatureVisitor, asmType, jetType.isNullable()); String kotlinTypeName = getKotlinTypeNameForSignature(jetType, asmType);
signatureVisitor.writeAsmType(asmType, jetType.isNullable(), kotlinTypeName);
} }
else { else {
writeGenericType(jetType, signatureVisitor, asmType, false); writeGenericType(signatureVisitor, asmType, jetType, false);
} }
} }
checkValidType(asmType); checkValidType(asmType);
return asmType; return asmType;
} }
private static void writeSimpleType(BothSignatureWriter visitor, Type asmType, boolean nullable) { @Nullable
visitor.writeAsmType(asmType, nullable); private static String getKotlinTypeNameForSignature(@NotNull JetType jetType, @NotNull Type asmType) {
ClassifierDescriptor descriptor = jetType.getConstructor().getDeclarationDescriptor();
if (descriptor == null) return null;
if (asmType.getSort() != Type.OBJECT) return null;
JvmClassName jvmClassName = JvmClassName.byType(asmType);
if (JavaToKotlinClassMap.getInstance().mapPlatformClass(jvmClassName.getFqName()).size() > 1) {
return JvmClassName.byClassDescriptor(descriptor).getSignatureName();
}
return null;
} }
private void checkValidType(@NotNull Type type) { private void checkValidType(@NotNull Type type) {
@@ -534,7 +546,7 @@ public class JetTypeMapper extends BindingTraceAware {
else { else {
signatureVisitor.writeReturnType(); signatureVisitor.writeReturnType();
JetType returnType = f.getReturnType(); JetType returnType = f.getReturnType();
assert returnType != null; assert returnType != null : "Function " + f + " has no return type";
mapReturnType(returnType, signatureVisitor); mapReturnType(returnType, signatureVisitor);
signatureVisitor.writeReturnTypeEnd(); signatureVisitor.writeReturnTypeEnd();
} }
@@ -647,7 +659,7 @@ public class JetTypeMapper extends BindingTraceAware {
((ClassDescriptor) parentDescriptor).getKind() == ClassKind.ANNOTATION_CLASS; ((ClassDescriptor) parentDescriptor).getKind() == ClassKind.ANNOTATION_CLASS;
String name = isAnnotation ? descriptor.getName().getName() : PropertyCodegen.getterName(descriptor.getName()); String name = isAnnotation ? descriptor.getName().getName() : PropertyCodegen.getterName(descriptor.getName());
// TODO: do not generate generics if not needed // TODO: do not genClassOrObject generics if not needed
BothSignatureWriter signatureWriter = new BothSignatureWriter(BothSignatureWriter.Mode.METHOD, true); BothSignatureWriter signatureWriter = new BothSignatureWriter(BothSignatureWriter.Mode.METHOD, true);
writeFormalTypeParameters(descriptor.getTypeParameters(), signatureWriter); writeFormalTypeParameters(descriptor.getTypeParameters(), signatureWriter);
@@ -765,10 +777,11 @@ public class JetTypeMapper extends BindingTraceAware {
if (closure != null) { if (closure != null) {
for (Map.Entry<DeclarationDescriptor, EnclosedValueDescriptor> entry : closure.getCaptureVariables().entrySet()) { for (Map.Entry<DeclarationDescriptor, EnclosedValueDescriptor> entry : closure.getCaptureVariables().entrySet()) {
if (entry.getKey() instanceof VariableDescriptor && !(entry.getKey() instanceof PropertyDescriptor)) { DeclarationDescriptor variableDescriptor = entry.getKey();
Type sharedVarType = getSharedVarType(entry.getKey()); if (variableDescriptor instanceof VariableDescriptor && !(variableDescriptor instanceof PropertyDescriptor)) {
Type sharedVarType = getSharedVarType(variableDescriptor);
if (sharedVarType == null) { if (sharedVarType == null) {
sharedVarType = mapType(((VariableDescriptor) entry.getKey()).getType()); sharedVarType = mapType(((VariableDescriptor) variableDescriptor).getType());
} }
signatureWriter.writeParameterType(JvmMethodParameterKind.SHARED_VAR); signatureWriter.writeParameterType(JvmMethodParameterKind.SHARED_VAR);
signatureWriter.writeAsmType(sharedVarType, false); signatureWriter.writeAsmType(sharedVarType, false);
@@ -17,23 +17,18 @@
package org.jetbrains.jet.di; package org.jetbrains.jet.di;
import org.jetbrains.jet.codegen.state.JetTypeMapper;
import java.util.List;
import org.jetbrains.jet.lang.psi.JetFile;
import org.jetbrains.jet.codegen.BuiltinToJavaTypesMapping;
import org.jetbrains.jet.codegen.state.GenerationState;
import org.jetbrains.jet.codegen.ClassBuilderFactory;
import com.intellij.openapi.project.Project; import com.intellij.openapi.project.Project;
import org.jetbrains.jet.lang.resolve.BindingTrace;
import org.jetbrains.jet.lang.resolve.BindingContext;
import org.jetbrains.jet.codegen.ClassBuilderMode;
import org.jetbrains.jet.codegen.ClassCodegen;
import org.jetbrains.jet.codegen.ScriptCodegen;
import org.jetbrains.jet.codegen.intrinsics.IntrinsicMethods;
import org.jetbrains.jet.codegen.ClassFileFactory;
import org.jetbrains.jet.codegen.MemberCodegen;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.codegen.*;
import org.jetbrains.jet.codegen.intrinsics.IntrinsicMethods;
import org.jetbrains.jet.codegen.state.GenerationState;
import org.jetbrains.jet.codegen.state.JetTypeMapper;
import org.jetbrains.jet.lang.psi.JetFile;
import org.jetbrains.jet.lang.resolve.BindingContext;
import org.jetbrains.jet.lang.resolve.BindingTrace;
import javax.annotation.PreDestroy; import javax.annotation.PreDestroy;
import java.util.List;
/* This file is generated by org.jetbrains.jet.di.AllInjectorsGenerator. DO NOT EDIT! */ /* This file is generated by org.jetbrains.jet.di.AllInjectorsGenerator. DO NOT EDIT! */
public class InjectorForJvmCodegen { public class InjectorForJvmCodegen {
@@ -47,11 +42,9 @@ public class InjectorForJvmCodegen {
private BindingTrace bindingTrace; private BindingTrace bindingTrace;
private BindingContext bindingContext; private BindingContext bindingContext;
private ClassBuilderMode classBuilderMode; private ClassBuilderMode classBuilderMode;
private ClassCodegen classCodegen;
private ScriptCodegen scriptCodegen; private ScriptCodegen scriptCodegen;
private IntrinsicMethods intrinsics; private IntrinsicMethods intrinsics;
private ClassFileFactory classFileFactory; private ClassFileFactory classFileFactory;
private MemberCodegen memberCodegen;
public InjectorForJvmCodegen( public InjectorForJvmCodegen(
@NotNull JetTypeMapper jetTypeMapper, @NotNull JetTypeMapper jetTypeMapper,
@@ -70,14 +63,11 @@ public class InjectorForJvmCodegen {
this.bindingTrace = jetTypeMapper.getBindingTrace(); this.bindingTrace = jetTypeMapper.getBindingTrace();
this.bindingContext = bindingTrace.getBindingContext(); this.bindingContext = bindingTrace.getBindingContext();
this.classBuilderMode = classBuilderFactory.getClassBuilderMode(); this.classBuilderMode = classBuilderFactory.getClassBuilderMode();
this.classCodegen = new ClassCodegen(getGenerationState());
this.scriptCodegen = new ScriptCodegen(getGenerationState()); this.scriptCodegen = new ScriptCodegen(getGenerationState());
this.intrinsics = new IntrinsicMethods(); this.intrinsics = new IntrinsicMethods();
this.classFileFactory = new ClassFileFactory(getGenerationState()); this.classFileFactory = new ClassFileFactory(getGenerationState());
this.memberCodegen = new MemberCodegen(getGenerationState());
this.scriptCodegen.setClassFileFactory(classFileFactory); this.scriptCodegen.setClassFileFactory(classFileFactory);
this.scriptCodegen.setMemberCodegen(memberCodegen);
this.classFileFactory.setBuilderFactory(classBuilderFactory); this.classFileFactory.setBuilderFactory(classBuilderFactory);
@@ -105,10 +95,6 @@ public class InjectorForJvmCodegen {
return this.project; return this.project;
} }
public ClassCodegen getClassCodegen() {
return this.classCodegen;
}
public ScriptCodegen getScriptCodegen() { public ScriptCodegen getScriptCodegen() {
return this.scriptCodegen; return this.scriptCodegen;
} }
@@ -121,8 +107,4 @@ public class InjectorForJvmCodegen {
return this.classFileFactory; return this.classFileFactory;
} }
public MemberCodegen getMemberCodegen() {
return this.memberCodegen;
}
} }
@@ -18,20 +18,33 @@ package org.jetbrains.jet.lang.resolve.java;
import com.google.common.base.Predicate; import com.google.common.base.Predicate;
import com.google.common.base.Predicates; import com.google.common.base.Predicates;
import com.google.common.collect.Lists;
import com.intellij.openapi.project.Project; import com.intellij.openapi.project.Project;
import com.intellij.psi.PsiFile; import com.intellij.psi.PsiFile;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.analyzer.AnalyzeExhaust; import org.jetbrains.jet.analyzer.AnalyzeExhaust;
import org.jetbrains.jet.analyzer.AnalyzerFacade; import org.jetbrains.jet.analyzer.AnalyzerFacade;
import org.jetbrains.jet.analyzer.AnalyzerFacadeForEverything; import org.jetbrains.jet.analyzer.AnalyzerFacadeForEverything;
import org.jetbrains.jet.di.InjectorForJavaDescriptorResolver;
import org.jetbrains.jet.di.InjectorForTopDownAnalyzerForJvm; import org.jetbrains.jet.di.InjectorForTopDownAnalyzerForJvm;
import org.jetbrains.jet.lang.BuiltinsScopeExtensionMode; import org.jetbrains.jet.lang.BuiltinsScopeExtensionMode;
import org.jetbrains.jet.lang.DefaultModuleConfiguration;
import org.jetbrains.jet.lang.ModuleConfiguration; import org.jetbrains.jet.lang.ModuleConfiguration;
import org.jetbrains.jet.lang.PlatformToKotlinClassMap;
import org.jetbrains.jet.lang.descriptors.ModuleDescriptor; import org.jetbrains.jet.lang.descriptors.ModuleDescriptor;
import org.jetbrains.jet.lang.descriptors.NamespaceDescriptor;
import org.jetbrains.jet.lang.psi.JetFile; import org.jetbrains.jet.lang.psi.JetFile;
import org.jetbrains.jet.lang.psi.JetImportDirective;
import org.jetbrains.jet.lang.psi.JetPsiFactory;
import org.jetbrains.jet.lang.resolve.*; import org.jetbrains.jet.lang.resolve.*;
import org.jetbrains.jet.lang.resolve.lazy.FileBasedDeclarationProviderFactory;
import org.jetbrains.jet.lang.resolve.lazy.ResolveSession;
import org.jetbrains.jet.lang.resolve.name.FqName;
import org.jetbrains.jet.lang.resolve.name.Name; import org.jetbrains.jet.lang.resolve.name.Name;
import org.jetbrains.jet.lang.resolve.scopes.WritableScope;
import org.jetbrains.jet.lang.types.lang.JetStandardLibrary;
import java.util.Arrays;
import java.util.Collection; import java.util.Collection;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;
@@ -70,6 +83,67 @@ public enum AnalyzerFacadeForJVM implements AnalyzerFacade {
headersTraceContext, bodiesResolveContext, configuration); headersTraceContext, bodiesResolveContext, configuration);
} }
@NotNull
@Override
public ResolveSession getLazyResolveSession(@NotNull final Project fileProject, @NotNull Collection<JetFile> files) {
ModuleDescriptor javaModule = new ModuleDescriptor(Name.special("<java module>"));
BindingTraceContext javaResolverTrace = new BindingTraceContext();
InjectorForJavaDescriptorResolver injector = new InjectorForJavaDescriptorResolver(
fileProject, javaResolverTrace, javaModule, BuiltinsScopeExtensionMode.ALL);
final PsiClassFinder psiClassFinder = injector.getPsiClassFinder();
// TODO: Replace with stub declaration provider
final FileBasedDeclarationProviderFactory declarationProviderFactory = new FileBasedDeclarationProviderFactory(files, new Predicate<FqName>() {
@Override
public boolean apply(FqName fqName) {
return psiClassFinder.findPsiPackage(fqName) != null || new FqName("jet").equals(fqName);
}
});
final JavaDescriptorResolver javaDescriptorResolver = injector.getJavaDescriptorResolver();
ModuleConfiguration moduleConfiguration = new ModuleConfiguration() {
@Override
public void addDefaultImports(@NotNull Collection<JetImportDirective> directives) {
final Collection<ImportPath> defaultImports = Lists.newArrayList(JavaBridgeConfiguration.DEFAULT_JAVA_IMPORTS);
defaultImports.addAll(Arrays.asList(DefaultModuleConfiguration.DEFAULT_JET_IMPORTS));
for (ImportPath defaultJetImport : defaultImports) {
directives.add(JetPsiFactory.createImportDirective(fileProject, defaultJetImport));
}
}
@Override
public void extendNamespaceScope(
@NotNull BindingTrace trace,
@NotNull NamespaceDescriptor namespaceDescriptor,
@NotNull WritableScope namespaceMemberScope
) {
FqName fqName = DescriptorUtils.getFQName(namespaceDescriptor).toSafe();
if (new FqName("jet").equals(fqName)) {
namespaceMemberScope.importScope(JetStandardLibrary.getInstance().getLibraryScope());
}
if (psiClassFinder.findPsiPackage(fqName) != null) {
JavaPackageScope javaPackageScope = javaDescriptorResolver.getJavaPackageScope(fqName, namespaceDescriptor);
assert javaPackageScope != null;
namespaceMemberScope.importScope(javaPackageScope);
}
}
@NotNull
@Override
public PlatformToKotlinClassMap getPlatformToKotlinClassMap() {
return PlatformToKotlinClassMap.EMPTY;
}
};
ModuleDescriptor lazyModule = new ModuleDescriptor(Name.special("<lazy module>"));
return new ResolveSession(fileProject, lazyModule, moduleConfiguration, declarationProviderFactory);
}
public static AnalyzeExhaust analyzeOneFileWithJavaIntegrationAndCheckForErrors( public static AnalyzeExhaust analyzeOneFileWithJavaIntegrationAndCheckForErrors(
JetFile file, List<AnalyzerScriptParameter> scriptParameters, @NotNull BuiltinsScopeExtensionMode builtinsScopeExtensionMode) { JetFile file, List<AnalyzerScriptParameter> scriptParameters, @NotNull BuiltinsScopeExtensionMode builtinsScopeExtensionMode) {
AnalyzingUtils.checkForSyntacticErrors(file); AnalyzingUtils.checkForSyntacticErrors(file);
@@ -114,8 +114,7 @@ public class JavaDescriptorResolver implements DependencyClassByQualifiedNameRes
} }
this.staticMembers = staticMembers; this.staticMembers = staticMembers;
this.kotlin = psiClass != null && this.kotlin = psiClass != null && isKotlinClass(psiClass);
(new PsiClassWrapper(psiClass).getJetClass().isDefined() || psiClass.getName().equals(JvmAbi.PACKAGE_CLASS));
classOrNamespaceDescriptor = descriptor; classOrNamespaceDescriptor = descriptor;
if (fqName != null && fqName.lastSegmentIs(Name.identifier(JvmAbi.PACKAGE_CLASS)) && psiClass != null && kotlin) { if (fqName != null && fqName.lastSegmentIs(Name.identifier(JvmAbi.PACKAGE_CLASS)) && psiClass != null && kotlin) {
@@ -214,9 +213,9 @@ public class JavaDescriptorResolver implements DependencyClassByQualifiedNameRes
} }
static class ResolverEnumClassObjectClassData extends ResolverClassData { static class ResolverSyntheticClassObjectClassData extends ResolverClassData {
protected ResolverEnumClassObjectClassData( protected ResolverSyntheticClassObjectClassData(
@Nullable PsiClass psiClass, @Nullable PsiClass psiClass,
@Nullable FqName fqName, @Nullable FqName fqName,
@NotNull ClassDescriptorFromJvmBytecode descriptor @NotNull ClassDescriptorFromJvmBytecode descriptor
@@ -545,8 +544,9 @@ public class JavaDescriptorResolver implements DependencyClassByQualifiedNameRes
false); false);
String context = "constructor of class " + psiClass.getQualifiedName(); String context = "constructor of class " + psiClass.getQualifiedName();
ValueParameterDescriptors valueParameterDescriptors = resolveParameterDescriptors(constructorDescriptor, ValueParameterDescriptors valueParameterDescriptors = resolveParameterDescriptors(constructorDescriptor,
constructor.getParameters(), constructor.getParameters(),
TypeVariableResolvers.classTypeVariableResolver(classData.classDescriptor, context)); TypeVariableResolvers.classTypeVariableResolver(
classData.classDescriptor, context));
if (valueParameterDescriptors.receiverType != null) { if (valueParameterDescriptors.receiverType != null) {
throw new IllegalStateException(); throw new IllegalStateException();
} }
@@ -585,6 +585,17 @@ public class JavaDescriptorResolver implements DependencyClassByQualifiedNameRes
return createClassObjectDescriptorForEnum(containing, psiClass); return createClassObjectDescriptorForEnum(containing, psiClass);
} }
if (!isKotlinClass(psiClass)) {
return null;
}
// If there's at least one inner enum, we need to create a class object (to put this enum into)
for (PsiClass innerClass : psiClass.getInnerClasses()) {
if (isInnerEnum(innerClass, containing)) {
return createSyntheticClassObject(containing, psiClass);
}
}
PsiClass classObjectPsiClass = getInnerClassClassObject(psiClass); PsiClass classObjectPsiClass = getInnerClassClassObject(psiClass);
if (classObjectPsiClass == null) { if (classObjectPsiClass == null) {
return null; return null;
@@ -602,20 +613,39 @@ public class JavaDescriptorResolver implements DependencyClassByQualifiedNameRes
return classObjectDescriptor; return classObjectDescriptor;
} }
private static boolean isKotlinClass(@NotNull PsiClass psiClass) {
return new PsiClassWrapper(psiClass).getJetClass().isDefined() || psiClass.getName().equals(JvmAbi.PACKAGE_CLASS);
}
private static boolean isInnerEnum(@NotNull PsiClass innerClass, DeclarationDescriptor owner) {
if (!innerClass.isEnum()) return false;
if (!(owner instanceof ClassDescriptor)) return false;
ClassKind kind = ((ClassDescriptor) owner).getKind();
return kind == ClassKind.CLASS || kind == ClassKind.TRAIT || kind == ClassKind.ENUM_CLASS;
}
@NotNull @NotNull
private MutableClassDescriptorLite createClassObjectDescriptorForEnum(@NotNull ClassDescriptor containing, @NotNull PsiClass psiClass) { private MutableClassDescriptorLite createClassObjectDescriptorForEnum(@NotNull ClassDescriptor containing, @NotNull PsiClass psiClass) {
MutableClassDescriptorLite classObjectDescriptor = createSyntheticClassObject(containing, psiClass);
classObjectDescriptor.getBuilder().addFunctionDescriptor(createEnumClassObjectValuesMethod(classObjectDescriptor, trace));
classObjectDescriptor.getBuilder().addFunctionDescriptor(createEnumClassObjectValueOfMethod(classObjectDescriptor, trace));
return classObjectDescriptor;
}
@NotNull
private MutableClassDescriptorLite createSyntheticClassObject(@NotNull ClassDescriptor containing, @NotNull PsiClass psiClass) {
String psiClassQualifiedName = psiClass.getQualifiedName(); String psiClassQualifiedName = psiClass.getQualifiedName();
assert psiClassQualifiedName != null : "Reading java class with no qualified name"; assert psiClassQualifiedName != null : "Reading java class with no qualified name";
FqNameUnsafe fqName = new FqNameUnsafe(psiClassQualifiedName + "." + getClassObjectName(psiClass.getName()).getName()); FqNameUnsafe fqName = new FqNameUnsafe(psiClassQualifiedName + "." + getClassObjectName(psiClass.getName()).getName());
ClassDescriptorFromJvmBytecode classObjectDescriptor = new ClassDescriptorFromJvmBytecode( ClassDescriptorFromJvmBytecode classObjectDescriptor = new ClassDescriptorFromJvmBytecode(
containing, ClassKind.CLASS_OBJECT, psiClass, null, this); containing, ClassKind.CLASS_OBJECT, psiClass, null, this);
ResolverEnumClassObjectClassData data = new ResolverEnumClassObjectClassData(psiClass, null, classObjectDescriptor); ResolverSyntheticClassObjectClassData data = new ResolverSyntheticClassObjectClassData(psiClass, null, classObjectDescriptor);
setUpClassObjectDescriptor(containing, fqName, data, getClassObjectName(containing.getName().getName())); setUpClassObjectDescriptor(containing, fqName, data, getClassObjectName(containing.getName().getName()));
classObjectDescriptor.getBuilder().addFunctionDescriptor(createEnumClassObjectValuesMethod(classObjectDescriptor, trace));
classObjectDescriptor.getBuilder().addFunctionDescriptor(createEnumClassObjectValueOfMethod(classObjectDescriptor, trace));
return classObjectDescriptor; return classObjectDescriptor;
} }
@@ -656,6 +686,13 @@ public class JavaDescriptorResolver implements DependencyClassByQualifiedNameRes
if (clazz == null) { if (clazz == null) {
throw new IllegalStateException("PsiClass not found by name " + containerFqName + ", required to be container declaration of " + fqName); throw new IllegalStateException("PsiClass not found by name " + containerFqName + ", required to be container declaration of " + fqName);
} }
if (isInnerEnum(psiClass, clazz) && isKotlinClass(psiClass)) {
ClassDescriptor classObjectDescriptor = clazz.getClassObjectDescriptor();
if (classObjectDescriptor == null) {
throw new IllegalStateException("Class object for a class with inner enum should've been created earlier: " + clazz);
}
return classObjectDescriptor;
}
return clazz; return clazz;
} }
@@ -1887,7 +1924,7 @@ public class JavaDescriptorResolver implements DependencyClassByQualifiedNameRes
public List<ClassDescriptor> resolveInnerClasses(DeclarationDescriptor owner, PsiClass psiClass, boolean staticMembers) { public List<ClassDescriptor> resolveInnerClasses(DeclarationDescriptor owner, PsiClass psiClass, boolean staticMembers) {
if (staticMembers) { if (staticMembers) {
return new ArrayList<ClassDescriptor>(0); return resolveInnerClassesOfClassObject(owner, psiClass);
} }
PsiClass[] innerPsiClasses = psiClass.getInnerClasses(); PsiClass[] innerPsiClasses = psiClass.getInnerClasses();
@@ -1900,14 +1937,41 @@ public class JavaDescriptorResolver implements DependencyClassByQualifiedNameRes
if (innerPsiClass.getName().equals(JvmAbi.CLASS_OBJECT_CLASS_NAME)) { if (innerPsiClass.getName().equals(JvmAbi.CLASS_OBJECT_CLASS_NAME)) {
continue; continue;
} }
ClassDescriptor classDescriptor = resolveClass(new FqName(innerPsiClass.getQualifiedName()), if (isInnerEnum(innerPsiClass, owner)) {
DescriptorSearchRule.IGNORE_IF_FOUND_IN_KOTLIN); // Inner enums will be put later into our class object
assert classDescriptor != null: "couldn't resolve class " + innerPsiClass.getQualifiedName(); continue;
}
ClassDescriptor classDescriptor = resolveInnerClass(innerPsiClass);
r.add(classDescriptor); r.add(classDescriptor);
} }
return r; return r;
} }
private List<ClassDescriptor> resolveInnerClassesOfClassObject(DeclarationDescriptor owner, PsiClass psiClass) {
if (!DescriptorUtils.isClassObject(owner)) {
return new ArrayList<ClassDescriptor>(0);
}
List<ClassDescriptor> r = new ArrayList<ClassDescriptor>(0);
// If we're a class object, inner enums of our parent need to be put into us
DeclarationDescriptor containingDeclaration = owner.getContainingDeclaration();
for (PsiClass innerPsiClass : psiClass.getInnerClasses()) {
if (isInnerEnum(innerPsiClass, containingDeclaration)) {
ClassDescriptor classDescriptor = resolveInnerClass(innerPsiClass);
r.add(classDescriptor);
}
}
return r;
}
private ClassDescriptor resolveInnerClass(@NotNull PsiClass innerPsiClass) {
String name = innerPsiClass.getQualifiedName();
assert name != null : "Inner class has no qualified name";
ClassDescriptor classDescriptor = resolveClass(new FqName(name), DescriptorSearchRule.IGNORE_IF_FOUND_IN_KOTLIN);
assert classDescriptor != null : "Couldn't resolve class " + name;
return classDescriptor;
}
@NotNull @NotNull
public static PsiAnnotation[] getAllAnnotations(@NotNull PsiModifierListOwner owner) { public static PsiAnnotation[] getAllAnnotations(@NotNull PsiModifierListOwner owner) {
List<PsiAnnotation> result = new ArrayList<PsiAnnotation>(); List<PsiAnnotation> result = new ArrayList<PsiAnnotation>();
@@ -30,13 +30,12 @@ import org.jetbrains.jet.lang.types.lang.JetStandardClasses;
import org.jetbrains.jet.lang.types.lang.JetStandardLibrary; import org.jetbrains.jet.lang.types.lang.JetStandardLibrary;
import org.jetbrains.jet.lang.types.lang.PrimitiveType; import org.jetbrains.jet.lang.types.lang.PrimitiveType;
import java.lang.annotation.Annotation;
import java.util.*; import java.util.*;
/** /**
* @author svtk * @author svtk
*/ */
public class JavaToKotlinClassMap implements PlatformToKotlinClassMap { public class JavaToKotlinClassMap extends JavaToKotlinClassMapBuilder implements PlatformToKotlinClassMap {
private static JavaToKotlinClassMap instance = null; private static JavaToKotlinClassMap instance = null;
@NotNull @NotNull
@@ -57,42 +56,6 @@ public class JavaToKotlinClassMap implements PlatformToKotlinClassMap {
initPrimitives(); initPrimitives();
} }
private void init() {
JetStandardLibrary standardLibrary = JetStandardLibrary.getInstance();
register(Object.class, JetStandardClasses.getAny());
register(String.class, standardLibrary.getString());
register(CharSequence.class, standardLibrary.getCharSequence());
register(Throwable.class, standardLibrary.getThrowable());
register(Number.class, standardLibrary.getNumber());
register(Comparable.class, standardLibrary.getComparable());
register(Enum.class, standardLibrary.getEnum());
register(Annotation.class, standardLibrary.getAnnotation());
register(Iterable.class, standardLibrary.getIterable());
register(Iterator.class, standardLibrary.getIterator());
registerCovariant(Iterable.class, standardLibrary.getMutableIterable());
registerCovariant(Iterator.class, standardLibrary.getMutableIterator());
register(Collection.class, standardLibrary.getCollection());
registerCovariant(Collection.class, standardLibrary.getMutableCollection());
register(List.class, standardLibrary.getList());
registerCovariant(List.class, standardLibrary.getMutableList());
register(Set.class, standardLibrary.getSet());
registerCovariant(Set.class, standardLibrary.getMutableSet());
register(Map.class, standardLibrary.getMap());
registerCovariant(Map.class, standardLibrary.getMutableMap());
register(Map.Entry.class, standardLibrary.getMapEntry());
registerCovariant(Map.Entry.class, standardLibrary.getMutableMapEntry());
register(ListIterator.class, standardLibrary.getListIterator());
registerCovariant(ListIterator.class, standardLibrary.getMutableListIterator());
}
private void initPrimitives() { private void initPrimitives() {
JetStandardLibrary standardLibrary = JetStandardLibrary.getInstance(); JetStandardLibrary standardLibrary = JetStandardLibrary.getInstance();
for (JvmPrimitiveType jvmPrimitiveType : JvmPrimitiveType.values()) { for (JvmPrimitiveType jvmPrimitiveType : JvmPrimitiveType.values()) {
@@ -131,19 +94,30 @@ public class JavaToKotlinClassMap implements PlatformToKotlinClassMap {
return new FqName(javaClass.getName().replace("$", ".")); return new FqName(javaClass.getName().replace("$", "."));
} }
private void register(@NotNull Class<?> javaClass, @NotNull ClassDescriptor kotlinDescriptor) { @Override
/*package*/ void register(
@NotNull Class<?> javaClass,
@NotNull ClassDescriptor kotlinDescriptor
) {
register(getJavaClassFqName(javaClass), kotlinDescriptor); register(getJavaClassFqName(javaClass), kotlinDescriptor);
} }
@Override
/*package*/ void register(
@NotNull Class<?> javaClass,
@NotNull ClassDescriptor kotlinDescriptor,
@NotNull ClassDescriptor kotlinMutableDescriptor
) {
FqName javaClassName = getJavaClassFqName(javaClass);
register(javaClassName, kotlinDescriptor);
registerCovariant(javaClassName, kotlinMutableDescriptor);
}
private void register(@NotNull FqName javaClassName, @NotNull ClassDescriptor kotlinDescriptor) { private void register(@NotNull FqName javaClassName, @NotNull ClassDescriptor kotlinDescriptor) {
classDescriptorMap.put(javaClassName, kotlinDescriptor); classDescriptorMap.put(javaClassName, kotlinDescriptor);
packagesWithMappedClasses.put(javaClassName.parent(), kotlinDescriptor); packagesWithMappedClasses.put(javaClassName.parent(), kotlinDescriptor);
} }
private void registerCovariant(@NotNull Class<?> javaClass, @NotNull ClassDescriptor kotlinDescriptor) {
registerCovariant(getJavaClassFqName(javaClass), kotlinDescriptor);
}
private void registerCovariant(@NotNull FqName javaClassName, @NotNull ClassDescriptor kotlinDescriptor) { private void registerCovariant(@NotNull FqName javaClassName, @NotNull ClassDescriptor kotlinDescriptor) {
classDescriptorMapForCovariantPositions.put(javaClassName, kotlinDescriptor); classDescriptorMapForCovariantPositions.put(javaClassName, kotlinDescriptor);
packagesWithMappedClasses.put(javaClassName.parent(), kotlinDescriptor); packagesWithMappedClasses.put(javaClassName.parent(), kotlinDescriptor);
@@ -0,0 +1,57 @@
/*
* 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.lang.resolve.java;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.descriptors.ClassDescriptor;
import org.jetbrains.jet.lang.types.lang.JetStandardClasses;
import org.jetbrains.jet.lang.types.lang.JetStandardLibrary;
import java.lang.annotation.Annotation;
import java.util.*;
/**
* @author svtk
*/
public abstract class JavaToKotlinClassMapBuilder {
/*package*/ void init() {
JetStandardLibrary standardLibrary = JetStandardLibrary.getInstance();
register(Object.class, JetStandardClasses.getAny());
register(String.class, standardLibrary.getString());
register(CharSequence.class, standardLibrary.getCharSequence());
register(Throwable.class, standardLibrary.getThrowable());
register(Number.class, standardLibrary.getNumber());
register(Comparable.class, standardLibrary.getComparable());
register(Enum.class, standardLibrary.getEnum());
register(Annotation.class, standardLibrary.getAnnotation());
register(Iterable.class, standardLibrary.getIterable(), standardLibrary.getMutableIterable());
register(Iterator.class, standardLibrary.getIterator(), standardLibrary.getMutableIterator());
register(Collection.class, standardLibrary.getCollection(), standardLibrary.getMutableCollection());
register(List.class, standardLibrary.getList(), standardLibrary.getMutableList());
register(Set.class, standardLibrary.getSet(), standardLibrary.getMutableSet());
register(Map.class, standardLibrary.getMap(), standardLibrary.getMutableMap());
register(Map.Entry.class, standardLibrary.getMapEntry(), standardLibrary.getMutableMapEntry());
register(ListIterator.class, standardLibrary.getListIterator(), standardLibrary.getMutableListIterator());
}
/*package*/ abstract void register(@NotNull Class<?> javaClass, @NotNull ClassDescriptor kotlinDescriptor);
/*package*/ abstract void register(@NotNull Class<?> javaClass, @NotNull ClassDescriptor kotlinDescriptor, @NotNull ClassDescriptor kotlinMutableDescriptor);
}
@@ -17,8 +17,10 @@
package org.jetbrains.jet.lang.resolve.java; package org.jetbrains.jet.lang.resolve.java;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.descriptors.ClassDescriptor; import org.jetbrains.jet.lang.descriptors.ClassDescriptor;
import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor; import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor;
import org.jetbrains.jet.lang.resolve.DescriptorUtils;
import org.jetbrains.jet.lang.resolve.name.FqName; import org.jetbrains.jet.lang.resolve.name.FqName;
import org.jetbrains.jet.lang.types.*; import org.jetbrains.jet.lang.types.*;
import org.jetbrains.jet.lang.types.lang.JetStandardClasses; import org.jetbrains.jet.lang.types.lang.JetStandardClasses;
@@ -87,46 +89,58 @@ public abstract class JetTypeJetSignatureReader extends JetSignatureExceptionsAd
private List<TypeProjection> typeArguments; private List<TypeProjection> typeArguments;
@Override @Override
public void visitClassType(String name, boolean nullable, boolean forceReal) { public void visitClassType(String signatureName, boolean nullable, boolean forceReal) {
FqName ourName = new FqName(name FqName fqName = JvmClassName.bySignatureName(signatureName).getFqName();
.replace('/', '.')
.replace('$', '.') // TODO: not sure
);
this.classDescriptor = null;
if (!forceReal) {
classDescriptor = JavaToKotlinClassMap.getInstance().mapKotlinClass(ourName,
JavaTypeTransformer.TypeUsage.MEMBER_SIGNATURE_INVARIANT);
}
if (classDescriptor == null) { enterClass(resolveClassDescriptorByFqName(fqName, forceReal), fqName.getFqName(), nullable);
// TODO: this is the worst code in Kotlin project }
Matcher matcher = Pattern.compile("jet\\.Function(\\d+)").matcher(ourName.getFqName());
if (matcher.matches()) {
classDescriptor = JetStandardClasses.getFunction(Integer.parseInt(matcher.group(1)));
}
}
if (classDescriptor == null) {
Matcher matcher = Pattern.compile("jet\\.Tuple(\\d+)").matcher(ourName.getFqName());
if (matcher.matches()) {
classDescriptor = JetStandardClasses.getTuple(Integer.parseInt(matcher.group(1)));
}
}
private void enterClass(@Nullable ClassDescriptor classDescriptor, @NotNull String className, boolean nullable) {
if (this.classDescriptor == null) { this.classDescriptor = classDescriptor;
this.classDescriptor = javaDescriptorResolver.resolveClass(ourName, DescriptorSearchRule.INCLUDE_KOTLIN);
}
if (this.classDescriptor == null) { if (this.classDescriptor == null) {
// TODO: report in to trace // TODO: report in to trace
this.errorType = ErrorUtils.createErrorType("class not found by name: " + ourName); this.errorType = ErrorUtils.createErrorType("class not found by name: " + className);
} }
this.nullable = nullable; this.nullable = nullable;
this.typeArguments = new ArrayList<TypeProjection>(); this.typeArguments = new ArrayList<TypeProjection>();
} }
@Nullable
private ClassDescriptor resolveClassDescriptorByFqName(FqName ourName, boolean forceReal) {
if (!forceReal) {
ClassDescriptor mappedDescriptor = JavaToKotlinClassMap.getInstance().
mapKotlinClass(ourName, JavaTypeTransformer.TypeUsage.MEMBER_SIGNATURE_INVARIANT);
if (mappedDescriptor != null) {
return mappedDescriptor;
}
}
// TODO: this is the worst code in Kotlin project
Matcher functionMatcher = Pattern.compile("jet\\.Function(\\d+)").matcher(ourName.getFqName());
if (functionMatcher.matches()) {
return JetStandardClasses.getFunction(Integer.parseInt(functionMatcher.group(1)));
}
Matcher patternMatcher = Pattern.compile("jet\\.Tuple(\\d+)").matcher(ourName.getFqName());
if (patternMatcher.matches()) {
return JetStandardClasses.getTuple(Integer.parseInt(patternMatcher.group(1)));
}
return javaDescriptorResolver.resolveClass(ourName, DescriptorSearchRule.INCLUDE_KOTLIN);
}
@Override
public void visitInnerClassType(String signatureName, boolean nullable, boolean forceReal) {
JvmClassName jvmClassName = JvmClassName.bySignatureName(signatureName);
ClassDescriptor descriptor = resolveClassDescriptorByFqName(jvmClassName.getOuterClassFqName(), forceReal);
for (String innerClassName : jvmClassName.getInnerClassNameList()) {
descriptor = descriptor != null ? DescriptorUtils.getInnerClassByName(descriptor, innerClassName) : null;
}
enterClass(descriptor, signatureName, nullable);
}
private static Variance parseVariance(JetSignatureVariance variance) { private static Variance parseVariance(JetSignatureVariance variance) {
switch (variance) { switch (variance) {
case INVARIANT: return Variance.INVARIANT; case INVARIANT: return Variance.INVARIANT;
@@ -16,11 +16,18 @@
package org.jetbrains.jet.lang.resolve.java; package org.jetbrains.jet.lang.resolve.java;
import com.google.common.collect.Lists;
import com.intellij.openapi.util.text.StringUtil; import com.intellij.openapi.util.text.StringUtil;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.asm4.Type; import org.jetbrains.asm4.Type;
import org.jetbrains.jet.lang.descriptors.ClassDescriptor;
import org.jetbrains.jet.lang.descriptors.ClassifierDescriptor;
import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor;
import org.jetbrains.jet.lang.resolve.DescriptorUtils;
import org.jetbrains.jet.lang.resolve.name.FqName; import org.jetbrains.jet.lang.resolve.name.FqName;
import java.util.List;
/** /**
* @author Stepan Koltsov * @author Stepan Koltsov
*/ */
@@ -45,7 +52,7 @@ public class JvmClassName {
*/ */
@NotNull @NotNull
public static JvmClassName byFqNameWithoutInnerClasses(@NotNull FqName fqName) { public static JvmClassName byFqNameWithoutInnerClasses(@NotNull FqName fqName) {
JvmClassName r = new JvmClassName(fqName.getFqName().replace('.', '/')); JvmClassName r = new JvmClassName(fqNameToInternalName(fqName));
r.fqName = fqName; r.fqName = fqName;
return r; return r;
} }
@@ -55,6 +62,13 @@ public class JvmClassName {
return byFqNameWithoutInnerClasses(new FqName(fqName)); return byFqNameWithoutInnerClasses(new FqName(fqName));
} }
@NotNull
public static JvmClassName bySignatureName(@NotNull String signatureName) {
JvmClassName className = new JvmClassName(signatureNameToInternalName(signatureName));
className.signatureName = signatureName;
return className;
}
private static String encodeSpecialNames(String str) { private static String encodeSpecialNames(String str) {
String encodedObjectNames = StringUtil.replace(str, JvmAbi.CLASS_OBJECT_CLASS_NAME, CLASS_OBJECT_REPLACE_GUARD); String encodedObjectNames = StringUtil.replace(str, JvmAbi.CLASS_OBJECT_CLASS_NAME, CLASS_OBJECT_REPLACE_GUARD);
return StringUtil.replace(encodedObjectNames, JvmAbi.TRAIT_IMPL_CLASS_NAME, TRAIT_IMPL_REPLACE_GUARD); return StringUtil.replace(encodedObjectNames, JvmAbi.TRAIT_IMPL_CLASS_NAME, TRAIT_IMPL_REPLACE_GUARD);
@@ -65,13 +79,67 @@ public class JvmClassName {
return StringUtil.replace(decodedObjectNames, TRAIT_IMPL_REPLACE_GUARD, JvmAbi.TRAIT_IMPL_CLASS_NAME); return StringUtil.replace(decodedObjectNames, TRAIT_IMPL_REPLACE_GUARD, JvmAbi.TRAIT_IMPL_CLASS_NAME);
} }
@NotNull
private static JvmClassName byFqNameAndInnerClassList(@NotNull FqName fqName, @NotNull List<String> innerClassList) {
String outerClassName = fqNameToInternalName(fqName);
StringBuilder sb = new StringBuilder(outerClassName);
for (String innerClassName : innerClassList) {
sb.append("$").append(innerClassName);
}
return new JvmClassName(sb.toString());
}
@NotNull
public static JvmClassName byClassDescriptor(@NotNull ClassifierDescriptor classDescriptor) {
DeclarationDescriptor descriptor = classDescriptor;
List<String> innerClassNames = Lists.newArrayList();
while (descriptor.getContainingDeclaration() instanceof ClassDescriptor) {
innerClassNames.add(descriptor.getName().getName());
descriptor = descriptor.getContainingDeclaration();
assert descriptor != null;
}
return byFqNameAndInnerClassList(DescriptorUtils.getFQName(descriptor).toSafe(), innerClassNames);
}
@NotNull
private static String fqNameToInternalName(@NotNull FqName fqName) {
return fqName.getFqName().replace('.', '/');
}
@NotNull
private static String signatureNameToInternalName(@NotNull String signatureName) {
return signatureName.replace('.', '$');
}
@NotNull
private static String internalNameToFqName(@NotNull String name) {
return decodeSpecialNames(encodeSpecialNames(name).replace('$', '.').replace('/', '.'));
}
@NotNull
private static String internalNameToSignatureName(@NotNull String name) {
return decodeSpecialNames(encodeSpecialNames(name).replace('$', '.'));
}
@NotNull
private static String signatureNameToFqName(@NotNull String name) {
return name.replace('/', '.');
}
private final static String CLASS_OBJECT_REPLACE_GUARD = "<class_object>"; private final static String CLASS_OBJECT_REPLACE_GUARD = "<class_object>";
private final static String TRAIT_IMPL_REPLACE_GUARD = "<trait_impl>"; private final static String TRAIT_IMPL_REPLACE_GUARD = "<trait_impl>";
@NotNull // Internal name: jet/Map$Entry
// FqName: jet.Map.Entry
// Signature name: jet/Map.Entry
private final String internalName; private final String internalName;
private FqName fqName; private FqName fqName;
private String descriptor; private String descriptor;
private String signatureName;
private Type asmType; private Type asmType;
@@ -82,7 +150,7 @@ public class JvmClassName {
@NotNull @NotNull
public FqName getFqName() { public FqName getFqName() {
if (fqName == null) { if (fqName == null) {
this.fqName = new FqName(decodeSpecialNames(encodeSpecialNames(internalName).replace('$', '.').replace('/', '.'))); this.fqName = new FqName(internalNameToFqName(internalName));
} }
return fqName; return fqName;
} }
@@ -112,6 +180,36 @@ public class JvmClassName {
return asmType; return asmType;
} }
@NotNull
public String getSignatureName() {
if (signatureName == null) {
signatureName = internalNameToSignatureName(internalName);
}
return signatureName;
}
@NotNull
public FqName getOuterClassFqName() {
String signatureName = getSignatureName();
int index = signatureName.indexOf('.');
String outerClassName = index != -1 ? signatureName.substring(0, index) : signatureName;
return new FqName(signatureNameToFqName(outerClassName));
}
@NotNull
public List<String> getInnerClassNameList() {
List<String> innerClassList = Lists.newArrayList();
String signatureName = getSignatureName();
int index = signatureName.indexOf('.');
while (index != -1) {
int nextIndex = signatureName.indexOf('.', index + 1);
String innerClassName = nextIndex != -1 ? signatureName.substring(index + 1, nextIndex) : signatureName.substring(index + 1);
innerClassList.add(innerClassName);
index = nextIndex;
}
return innerClassList;
}
@Override @Override
public String toString() { public String toString() {
return getInternalName(); return getInternalName();
@@ -27,17 +27,15 @@ import org.jetbrains.jet.lang.resolve.DescriptorUtils;
import org.jetbrains.jet.lang.resolve.name.FqName; import org.jetbrains.jet.lang.resolve.name.FqName;
import org.jetbrains.jet.lang.resolve.name.FqNameUnsafe; import org.jetbrains.jet.lang.resolve.name.FqNameUnsafe;
import org.jetbrains.jet.lang.types.JetType; import org.jetbrains.jet.lang.types.JetType;
import org.jetbrains.jet.lang.types.lang.JetStandardClasses;
import org.jetbrains.jet.lang.types.lang.JetStandardLibrary;
import org.jetbrains.jet.lang.types.lang.PrimitiveType; import org.jetbrains.jet.lang.types.lang.PrimitiveType;
import java.lang.annotation.Annotation; import java.util.Map;
import java.util.*; import java.util.Set;
/** /**
* @author svtk * @author svtk
*/ */
public class KotlinToJavaTypesMap { public class KotlinToJavaTypesMap extends JavaToKotlinClassMapBuilder {
private static KotlinToJavaTypesMap instance = null; private static KotlinToJavaTypesMap instance = null;
@NotNull @NotNull
@@ -57,41 +55,6 @@ public class KotlinToJavaTypesMap {
initPrimitives(); initPrimitives();
} }
private void init() {
JetStandardLibrary standardLibrary = JetStandardLibrary.getInstance();
register(JetStandardClasses.getAny(), Object.class);
register(standardLibrary.getNumber(), Number.class);
register(standardLibrary.getString(), String.class);
register(standardLibrary.getThrowable(), Throwable.class);
register(standardLibrary.getCharSequence(), CharSequence.class);
register(standardLibrary.getComparable(), Comparable.class);
register(standardLibrary.getEnum(), Enum.class);
register(standardLibrary.getAnnotation(), Annotation.class);
register(standardLibrary.getIterable(), Iterable.class);
register(standardLibrary.getIterator(), Iterator.class);
register(standardLibrary.getMutableIterable(), Iterable.class);
register(standardLibrary.getMutableIterator(), Iterator.class);
register(standardLibrary.getCollection(), Collection.class);
register(standardLibrary.getMutableCollection(), Collection.class);
register(standardLibrary.getList(), List.class);
register(standardLibrary.getMutableList(), List.class);
register(standardLibrary.getSet(), Set.class);
register(standardLibrary.getMutableSet(), Set.class);
register(standardLibrary.getMap(), Map.class);
register(standardLibrary.getMutableMap(), Map.class);
register(standardLibrary.getMapEntry(), Map.Entry.class);
register(standardLibrary.getMutableMapEntry(), Map.Entry.class);
register(standardLibrary.getListIterator(), ListIterator.class);
register(standardLibrary.getMutableListIterator(), ListIterator.class);
}
private void initPrimitives() { private void initPrimitives() {
for (JvmPrimitiveType jvmPrimitiveType : JvmPrimitiveType.values()) { for (JvmPrimitiveType jvmPrimitiveType : JvmPrimitiveType.values()) {
FqName className = jvmPrimitiveType.getPrimitiveType().getClassName(); FqName className = jvmPrimitiveType.getPrimitiveType().getClassName();
@@ -121,10 +84,24 @@ public class KotlinToJavaTypesMap {
return asmTypes.get(fqName); return asmTypes.get(fqName);
} }
private void register(@NotNull ClassDescriptor kotlinDescriptor, @NotNull Class<?> javaClass) { @Override
/*package*/ void register(
@NotNull Class<?> javaClass,
@NotNull ClassDescriptor kotlinDescriptor
) {
register(kotlinDescriptor, AsmTypeConstants.getType(javaClass)); register(kotlinDescriptor, AsmTypeConstants.getType(javaClass));
} }
@Override
/*package*/ void register(
@NotNull Class<?> javaClass,
@NotNull ClassDescriptor kotlinDescriptor,
@NotNull ClassDescriptor kotlinMutableDescriptor
) {
register(javaClass, kotlinDescriptor);
register(javaClass, kotlinMutableDescriptor);
}
private void register(@NotNull ClassDescriptor kotlinDescriptor, @NotNull Type javaType) { private void register(@NotNull ClassDescriptor kotlinDescriptor, @NotNull Type javaType) {
FqNameUnsafe fqName = DescriptorUtils.getFQName(kotlinDescriptor); FqNameUnsafe fqName = DescriptorUtils.getFQName(kotlinDescriptor);
assert fqName.isSafe(); assert fqName.isSafe();
@@ -22,11 +22,10 @@ import java.io.PrintStream;
* @author abreslav * @author abreslav
*/ */
public class TuplesAndFunctionsGenerator { public class TuplesAndFunctionsGenerator {
private static int TUPLE_COUNT = 23; private static final int TUPLE_COUNT = 23;
private static void generateTuples(PrintStream out, int count) { private static void generateTuples(PrintStream out, int count) {
generated(out); generated(out);
out.println("public class Tuple0() {}");
for (int i = 1; i < count; i++) { for (int i = 1; i < count; i++) {
out.print("public class Tuple" + i); out.print("public class Tuple" + i);
out.print("<"); out.print("<");
-1
View File
@@ -3,7 +3,6 @@
package jet package jet
public class Tuple0() {}
public class Tuple1<out T1>(public val _1: T1) {} public class Tuple1<out T1>(public val _1: T1) {}
public class Tuple2<out T1, out T2>(public val _1: T1, public val _2: T2) {} public class Tuple2<out T1, out T2>(public val _1: T1, public val _2: T2) {}
public class Tuple3<out T1, out T2, out T3>(public val _1: T1, public val _2: T2, public val _3: T3) {} public class Tuple3<out T1, out T2, out T3>(public val _1: T1, public val _2: T2, public val _3: T3) {}
+7
View File
@@ -0,0 +1,7 @@
package jet
public class Tuple0 private () {
public class object {
public val VALUE: Tuple0
}
}
+1 -1
View File
@@ -108,7 +108,7 @@ public trait MutableSet<E> : Set<E>, MutableCollection<E> {
override fun clear() override fun clear()
} }
public trait Map<K, V> { public trait Map<K, out V> {
// Query Operations // Query Operations
public fun size() : Int public fun size() : Int
public fun isEmpty() : Boolean public fun isEmpty() : Boolean
-2
View File
@@ -16,8 +16,6 @@ public fun Any?.equals(other : Any?) : Boolean// = this === other
// Returns "null" for null // Returns "null" for null
public fun Any?.toString() : String// = this === other public fun Any?.toString() : String// = this === other
public fun <T : Any> T?.sure() : T
public fun String?.plus(other: Any?) : String public fun String?.plus(other: Any?) : String
public trait Comparable<in T> { public trait Comparable<in T> {
@@ -64,10 +64,15 @@ public interface JetNodeTypes {
JetNodeType VALUE_ARGUMENT = new JetNodeType("VALUE_ARGUMENT", JetValueArgument.class); JetNodeType VALUE_ARGUMENT = new JetNodeType("VALUE_ARGUMENT", JetValueArgument.class);
JetNodeType VALUE_ARGUMENT_NAME = new JetNodeType("VALUE_ARGUMENT_NAME", JetValueArgumentName.class); JetNodeType VALUE_ARGUMENT_NAME = new JetNodeType("VALUE_ARGUMENT_NAME", JetValueArgumentName.class);
JetNodeType TYPE_REFERENCE = new JetNodeType("TYPE_REFERENCE", JetTypeReference.class); JetNodeType TYPE_REFERENCE = new JetNodeType("TYPE_REFERENCE", JetTypeReference.class);
@Deprecated // Tuples are to be removed in Kotlin M4
JetNodeType LABELED_TUPLE_ENTRY = new JetNodeType("LABELED_TUPLE_ENTRY"); JetNodeType LABELED_TUPLE_ENTRY = new JetNodeType("LABELED_TUPLE_ENTRY");
@Deprecated // Tuples are to be removed in Kotlin M4
JetNodeType LABELED_TUPLE_TYPE_ENTRY = new JetNodeType("LABELED_TUPLE_TYPE_ENTRY"); JetNodeType LABELED_TUPLE_TYPE_ENTRY = new JetNodeType("LABELED_TUPLE_TYPE_ENTRY");
JetNodeType USER_TYPE = new JetNodeType("USER_TYPE", JetUserType.class); JetNodeType USER_TYPE = new JetNodeType("USER_TYPE", JetUserType.class);
@Deprecated // Tuples are to be removed in Kotlin M4
JetNodeType TUPLE_TYPE = new JetNodeType("TUPLE_TYPE", JetTupleType.class); JetNodeType TUPLE_TYPE = new JetNodeType("TUPLE_TYPE", JetTupleType.class);
JetNodeType FUNCTION_TYPE = new JetNodeType("FUNCTION_TYPE", JetFunctionType.class); JetNodeType FUNCTION_TYPE = new JetNodeType("FUNCTION_TYPE", JetFunctionType.class);
JetNodeType SELF_TYPE = new JetNodeType("SELF_TYPE", JetSelfType.class); JetNodeType SELF_TYPE = new JetNodeType("SELF_TYPE", JetSelfType.class);
@@ -95,6 +100,7 @@ public interface JetNodeTypes {
JetNodeType LITERAL_STRING_TEMPLATE_ENTRY = new JetNodeType("LITERAL_STRING_TEMPLATE_ENTRY", JetLiteralStringTemplateEntry.class); JetNodeType LITERAL_STRING_TEMPLATE_ENTRY = new JetNodeType("LITERAL_STRING_TEMPLATE_ENTRY", JetLiteralStringTemplateEntry.class);
JetNodeType ESCAPE_STRING_TEMPLATE_ENTRY = new JetNodeType("ESCAPE_STRING_TEMPLATE_ENTRY", JetEscapeStringTemplateEntry.class); JetNodeType ESCAPE_STRING_TEMPLATE_ENTRY = new JetNodeType("ESCAPE_STRING_TEMPLATE_ENTRY", JetEscapeStringTemplateEntry.class);
@Deprecated // Tuples are to be removed in Kotlin M4
JetNodeType TUPLE = new JetNodeType("TUPLE", JetTupleExpression.class); JetNodeType TUPLE = new JetNodeType("TUPLE", JetTupleExpression.class);
JetNodeType PARENTHESIZED = new JetNodeType("PARENTHESIZED", JetParenthesizedExpression.class); JetNodeType PARENTHESIZED = new JetNodeType("PARENTHESIZED", JetParenthesizedExpression.class);
JetNodeType RETURN = new JetNodeType("RETURN", JetReturnExpression.class); JetNodeType RETURN = new JetNodeType("RETURN", JetReturnExpression.class);
@@ -136,9 +142,7 @@ public interface JetNodeTypes {
JetNodeType ARRAY_ACCESS_EXPRESSION = new JetNodeType("ARRAY_ACCESS_EXPRESSION", JetArrayAccessExpression.class); JetNodeType ARRAY_ACCESS_EXPRESSION = new JetNodeType("ARRAY_ACCESS_EXPRESSION", JetArrayAccessExpression.class);
JetNodeType INDICES = new JetNodeType("INDICES", JetContainerNode.class); JetNodeType INDICES = new JetNodeType("INDICES", JetContainerNode.class);
JetNodeType DOT_QUALIFIED_EXPRESSION = new JetNodeType("DOT_QUALIFIED_EXPRESSION", JetDotQualifiedExpression.class); JetNodeType DOT_QUALIFIED_EXPRESSION = new JetNodeType("DOT_QUALIFIED_EXPRESSION", JetDotQualifiedExpression.class);
JetNodeType HASH_QUALIFIED_EXPRESSION = new JetNodeType("HASH_QUALIFIED_EXPRESSION", JetHashQualifiedExpression.class);
JetNodeType SAFE_ACCESS_EXPRESSION = new JetNodeType("SAFE_ACCESS_EXPRESSION", JetSafeQualifiedExpression.class); JetNodeType SAFE_ACCESS_EXPRESSION = new JetNodeType("SAFE_ACCESS_EXPRESSION", JetSafeQualifiedExpression.class);
// JetNodeType PREDICATE_EXPRESSION = new JetNodeType("PREDICATE_EXPRESSION", JetPredicateExpression.class);
JetNodeType OBJECT_LITERAL = new JetNodeType("OBJECT_LITERAL", JetObjectLiteralExpression.class); JetNodeType OBJECT_LITERAL = new JetNodeType("OBJECT_LITERAL", JetObjectLiteralExpression.class);
JetNodeType ROOT_NAMESPACE = new JetNodeType("ROOT_NAMESPACE", JetRootNamespaceExpression.class); JetNodeType ROOT_NAMESPACE = new JetNodeType("ROOT_NAMESPACE", JetRootNamespaceExpression.class);
@@ -25,6 +25,7 @@ import org.jetbrains.jet.lang.psi.JetFile;
import org.jetbrains.jet.lang.resolve.AnalyzerScriptParameter; import org.jetbrains.jet.lang.resolve.AnalyzerScriptParameter;
import org.jetbrains.jet.lang.resolve.BindingTrace; import org.jetbrains.jet.lang.resolve.BindingTrace;
import org.jetbrains.jet.lang.resolve.BodiesResolveContext; import org.jetbrains.jet.lang.resolve.BodiesResolveContext;
import org.jetbrains.jet.lang.resolve.lazy.ResolveSession;
import java.util.Collection; import java.util.Collection;
import java.util.List; import java.util.List;
@@ -51,4 +52,10 @@ public interface AnalyzerFacade {
@NotNull BodiesResolveContext bodiesResolveContext, @NotNull BodiesResolveContext bodiesResolveContext,
@NotNull ModuleConfiguration configuration @NotNull ModuleConfiguration configuration
); );
@NotNull
ResolveSession getLazyResolveSession(
@NotNull Project project,
@NotNull Collection<JetFile> files
);
} }
@@ -36,7 +36,9 @@ public abstract class ClassDescriptorBase implements ClassDescriptor {
@NotNull @NotNull
@Override @Override
public JetScope getMemberScope(List<TypeProjection> typeArguments) { public JetScope getMemberScope(List<TypeProjection> typeArguments) {
assert typeArguments.size() == getTypeConstructor().getParameters().size(); assert typeArguments.size() == getTypeConstructor().getParameters().size() : "Illegal number of type arguments: expected "
+ getTypeConstructor().getParameters().size() + " but was " + typeArguments.size()
+ " for " + getTypeConstructor() + " " + getTypeConstructor().getParameters();
if (typeArguments.isEmpty()) return getScopeForMemberLookup(); if (typeArguments.isEmpty()) return getScopeForMemberLookup();
List<TypeParameterDescriptor> typeParameters = getTypeConstructor().getParameters(); List<TypeParameterDescriptor> typeParameters = getTypeConstructor().getParameters();
@@ -25,9 +25,11 @@ import org.jetbrains.jet.lang.resolve.scopes.SubstitutingScope;
import org.jetbrains.jet.lang.resolve.scopes.receivers.ClassReceiver; import org.jetbrains.jet.lang.resolve.scopes.receivers.ClassReceiver;
import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor; import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor;
import org.jetbrains.jet.lang.types.*; import org.jetbrains.jet.lang.types.*;
import org.jetbrains.jet.lang.types.lang.JetStandardClasses;
import java.util.*; import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Set;
/** /**
* @author abreslav * @author abreslav
@@ -40,54 +42,54 @@ public class ClassDescriptorImpl extends DeclarationDescriptorNonRootImpl implem
private ConstructorDescriptor primaryConstructor; private ConstructorDescriptor primaryConstructor;
private ReceiverDescriptor implicitReceiver; private ReceiverDescriptor implicitReceiver;
private final Modality modality; private final Modality modality;
private ClassDescriptor classObjectDescriptor;
private final ClassKind kind;
public ClassDescriptorImpl(
@NotNull DeclarationDescriptor containingDeclaration,
@NotNull List<AnnotationDescriptor> annotations,
@NotNull Modality modality,
@NotNull Name name
) {
this(containingDeclaration, ClassKind.CLASS, annotations, modality, name);
}
public ClassDescriptorImpl( public ClassDescriptorImpl(
@NotNull DeclarationDescriptor containingDeclaration, @NotNull DeclarationDescriptor containingDeclaration,
@NotNull ClassKind kind,
@NotNull List<AnnotationDescriptor> annotations, @NotNull List<AnnotationDescriptor> annotations,
@NotNull Modality modality, @NotNull Modality modality,
@NotNull Name name) { @NotNull Name name) {
super(containingDeclaration, annotations, name); super(containingDeclaration, annotations, name);
this.kind = kind;
this.modality = modality; this.modality = modality;
} }
public final ClassDescriptorImpl initialize(boolean sealed,
@NotNull List<? extends TypeParameterDescriptor> typeParameters,
@NotNull Collection<JetType> supertypes,
@NotNull JetScope memberDeclarations,
@NotNull Set<ConstructorDescriptor> constructors,
@Nullable ConstructorDescriptor primaryConstructor) {
return initialize(sealed, typeParameters, supertypes, memberDeclarations, constructors, primaryConstructor, getClassType(supertypes));
}
public final ClassDescriptorImpl initialize(boolean sealed, public final ClassDescriptorImpl initialize(
@NotNull List<? extends TypeParameterDescriptor> typeParameters, boolean sealed,
@NotNull Collection<JetType> supertypes, @NotNull List<? extends TypeParameterDescriptor> typeParameters,
@NotNull JetScope memberDeclarations, @NotNull Collection<JetType> supertypes,
@NotNull Set<ConstructorDescriptor> constructors, @NotNull JetScope memberDeclarations,
@Nullable ConstructorDescriptor primaryConstructor, @NotNull Set<ConstructorDescriptor> constructors,
@Nullable JetType superclassType) { @Nullable ConstructorDescriptor primaryConstructor
) {
this.typeConstructor = new TypeConstructorImpl(this, getAnnotations(), sealed, getName().getName(), typeParameters, supertypes); this.typeConstructor = new TypeConstructorImpl(this, getAnnotations(), sealed, getName().getName(), typeParameters, supertypes);
this.memberDeclarations = memberDeclarations; this.memberDeclarations = memberDeclarations;
this.constructors = constructors; this.constructors = constructors;
this.primaryConstructor = primaryConstructor; this.primaryConstructor = primaryConstructor;
this.classObjectDescriptor = classObjectDescriptor;
return this; return this;
} }
@NotNull
private JetType getClassType(@NotNull Collection<JetType> types) {
for (JetType type : types) {
ClassDescriptor classDescriptor = TypeUtils.getClassDescriptor(type);
if (classDescriptor != null) {
return type;
}
}
return JetStandardClasses.getAnyType();
}
public void setPrimaryConstructor(@NotNull ConstructorDescriptor primaryConstructor) { public void setPrimaryConstructor(@NotNull ConstructorDescriptor primaryConstructor) {
this.primaryConstructor = primaryConstructor; this.primaryConstructor = primaryConstructor;
} }
public void setClassObjectDescriptor(@NotNull ClassDescriptor classObjectDescriptor) {
this.classObjectDescriptor = classObjectDescriptor;
}
@Override @Override
@NotNull @NotNull
public TypeConstructor getTypeConstructor() { public TypeConstructor getTypeConstructor() {
@@ -126,18 +128,18 @@ public class ClassDescriptorImpl extends DeclarationDescriptorNonRootImpl implem
@Override @Override
public JetType getClassObjectType() { public JetType getClassObjectType() {
return null; return getClassObjectDescriptor().getDefaultType();
} }
@Override @Override
public ClassDescriptor getClassObjectDescriptor() { public ClassDescriptor getClassObjectDescriptor() {
return null; return classObjectDescriptor;
} }
@NotNull @NotNull
@Override @Override
public ClassKind getKind() { public ClassKind getKind() {
return ClassKind.CLASS; return kind;
} }
@Override @Override
@@ -47,6 +47,12 @@ import static org.jetbrains.jet.lang.diagnostics.Severity.WARNING;
*/ */
public interface Errors { public interface Errors {
// TODO: Temporary error message: to deprecate tuples we report this error and provide a quick fix
@Deprecated // Tuples will be dropped in Kotlin M4
SimpleDiagnosticFactory<PsiElement> TUPLES_ARE_NOT_SUPPORTED = SimpleDiagnosticFactory.create(ERROR);
@Deprecated // Tuples will be dropped in Kotlin M4
SimpleDiagnosticFactory<PsiElement> TUPLES_ARE_NOT_SUPPORTED_BIG = SimpleDiagnosticFactory.create(ERROR);
DiagnosticFactory1<JetFile, Throwable> EXCEPTION_WHILE_ANALYZING = DiagnosticFactory1.create(ERROR); DiagnosticFactory1<JetFile, Throwable> EXCEPTION_WHILE_ANALYZING = DiagnosticFactory1.create(ERROR);
UnresolvedReferenceDiagnosticFactory UNRESOLVED_REFERENCE = UnresolvedReferenceDiagnosticFactory.create(); UnresolvedReferenceDiagnosticFactory UNRESOLVED_REFERENCE = UnresolvedReferenceDiagnosticFactory.create();
@@ -70,6 +76,8 @@ public interface Errors {
.create(WARNING, positionModifier(JetTokens.OPEN_KEYWORD)); .create(WARNING, positionModifier(JetTokens.OPEN_KEYWORD));
SimpleDiagnosticFactory<JetModifierListOwner> OPEN_MODIFIER_IN_ENUM = SimpleDiagnosticFactory SimpleDiagnosticFactory<JetModifierListOwner> OPEN_MODIFIER_IN_ENUM = SimpleDiagnosticFactory
.create(ERROR, positionModifier(JetTokens.OPEN_KEYWORD)); .create(ERROR, positionModifier(JetTokens.OPEN_KEYWORD));
SimpleDiagnosticFactory<JetModifierListOwner> ILLEGAL_ENUM_ANNOTATION = SimpleDiagnosticFactory
.create(ERROR, positionModifier(JetTokens.ENUM_KEYWORD));
SimpleDiagnosticFactory<PsiElement> SimpleDiagnosticFactory<PsiElement>
REDUNDANT_MODIFIER_IN_GETTER = SimpleDiagnosticFactory.create(WARNING); REDUNDANT_MODIFIER_IN_GETTER = SimpleDiagnosticFactory.create(WARNING);
SimpleDiagnosticFactory<PsiElement> TRAIT_CAN_NOT_BE_FINAL = SimpleDiagnosticFactory.create(ERROR); SimpleDiagnosticFactory<PsiElement> TRAIT_CAN_NOT_BE_FINAL = SimpleDiagnosticFactory.create(ERROR);
@@ -151,6 +159,7 @@ public interface Errors {
DiagnosticFactory1<JetClass, ClassDescriptor> ENUM_ENTRY_SHOULD_BE_INITIALIZED = DiagnosticFactory1.create(ERROR, NAME_IDENTIFIER); DiagnosticFactory1<JetClass, ClassDescriptor> ENUM_ENTRY_SHOULD_BE_INITIALIZED = DiagnosticFactory1.create(ERROR, NAME_IDENTIFIER);
DiagnosticFactory1<JetTypeReference, ClassDescriptor> ENUM_ENTRY_ILLEGAL_TYPE = DiagnosticFactory1.create(ERROR); DiagnosticFactory1<JetTypeReference, ClassDescriptor> ENUM_ENTRY_ILLEGAL_TYPE = DiagnosticFactory1.create(ERROR);
SimpleDiagnosticFactory<PsiElement> ENUM_NOT_ALLOWED = SimpleDiagnosticFactory.create(ERROR);
DiagnosticFactory1<JetSimpleNameExpression, VariableDescriptor> UNINITIALIZED_VARIABLE = DiagnosticFactory1.create(ERROR); DiagnosticFactory1<JetSimpleNameExpression, VariableDescriptor> UNINITIALIZED_VARIABLE = DiagnosticFactory1.create(ERROR);
DiagnosticFactory1<JetSimpleNameExpression, ValueParameterDescriptor> UNINITIALIZED_PARAMETER = DiagnosticFactory1.create(ERROR); DiagnosticFactory1<JetSimpleNameExpression, ValueParameterDescriptor> UNINITIALIZED_PARAMETER = DiagnosticFactory1.create(ERROR);
@@ -45,6 +45,11 @@ public class DefaultErrorMessages {
public static final DiagnosticRenderer<Diagnostic> RENDERER = new DispatchingDiagnosticRenderer(MAP); public static final DiagnosticRenderer<Diagnostic> RENDERER = new DispatchingDiagnosticRenderer(MAP);
static { static {
// TODO: remove when tuples are completely dropped
MAP.put(TUPLES_ARE_NOT_SUPPORTED, "Tuples are not supported. In the IDE you can use Alt+Enter to replace tuples with library classes");
MAP.put(TUPLES_ARE_NOT_SUPPORTED_BIG, "Tuples are not supported. Use data classes instead");
MAP.put(EXCEPTION_WHILE_ANALYZING, "{0}", new Renderer<Throwable>() { MAP.put(EXCEPTION_WHILE_ANALYZING, "{0}", new Renderer<Throwable>() {
@NotNull @NotNull
@Override @Override
@@ -82,6 +87,7 @@ public class DefaultErrorMessages {
MAP.put(ABSTRACT_MODIFIER_IN_TRAIT, "Modifier ''abstract'' is redundant in trait"); MAP.put(ABSTRACT_MODIFIER_IN_TRAIT, "Modifier ''abstract'' is redundant in trait");
MAP.put(OPEN_MODIFIER_IN_TRAIT, "Modifier ''open'' is redundant in trait"); MAP.put(OPEN_MODIFIER_IN_TRAIT, "Modifier ''open'' is redundant in trait");
MAP.put(OPEN_MODIFIER_IN_ENUM, "Modifier ''open'' is not applicable for enum class"); MAP.put(OPEN_MODIFIER_IN_ENUM, "Modifier ''open'' is not applicable for enum class");
MAP.put(ILLEGAL_ENUM_ANNOTATION, "Annotation ''enum'' is only applicable for class");
MAP.put(REDUNDANT_MODIFIER_IN_GETTER, "Visibility modifiers are redundant in getter"); MAP.put(REDUNDANT_MODIFIER_IN_GETTER, "Visibility modifiers are redundant in getter");
MAP.put(TRAIT_CAN_NOT_BE_FINAL, "Trait cannot be final"); MAP.put(TRAIT_CAN_NOT_BE_FINAL, "Trait cannot be final");
MAP.put(TYPECHECKER_HAS_RUN_INTO_RECURSIVE_PROBLEM, MAP.put(TYPECHECKER_HAS_RUN_INTO_RECURSIVE_PROBLEM,
@@ -95,7 +101,7 @@ public class DefaultErrorMessages {
MAP.put(CANNOT_BE_IMPORTED, "Cannot import ''{0}'', functions and properties can be imported only from packages", NAME); MAP.put(CANNOT_BE_IMPORTED, "Cannot import ''{0}'', functions and properties can be imported only from packages", NAME);
MAP.put(USELESS_HIDDEN_IMPORT, "Useless import, it is hidden further"); MAP.put(USELESS_HIDDEN_IMPORT, "Useless import, it is hidden further");
MAP.put(USELESS_SIMPLE_IMPORT, "Useless import, does nothing"); MAP.put(USELESS_SIMPLE_IMPORT, "Useless import, does nothing");
MAP.put(PLATFORM_CLASS_MAPPED_TO_KOTLIN, "This class shouldn''t be used in Kotlin. Use {0} instead.", CLASS_DESCRIPTOR_LIST); MAP.put(PLATFORM_CLASS_MAPPED_TO_KOTLIN, "This class shouldn''t be used in Kotlin. Use {0} instead.", CLASSES_OR_SEPARATED);
MAP.put(CANNOT_INFER_PARAMETER_TYPE, MAP.put(CANNOT_INFER_PARAMETER_TYPE,
"Cannot infer a type for this parameter. To specify it explicitly use the {(p : Type) => ...} notation"); "Cannot infer a type for this parameter. To specify it explicitly use the {(p : Type) => ...} notation");
@@ -164,6 +170,7 @@ public class DefaultErrorMessages {
MAP.put(ENUM_ENTRY_SHOULD_BE_INITIALIZED, "Missing delegation specifier ''{0}''", NAME); MAP.put(ENUM_ENTRY_SHOULD_BE_INITIALIZED, "Missing delegation specifier ''{0}''", NAME);
MAP.put(ENUM_ENTRY_ILLEGAL_TYPE, "The type constructor of enum entry should be ''{0}''", NAME); MAP.put(ENUM_ENTRY_ILLEGAL_TYPE, "The type constructor of enum entry should be ''{0}''", NAME);
MAP.put(ENUM_NOT_ALLOWED, "Enum class is not allowed here");
MAP.put(UNINITIALIZED_VARIABLE, "Variable ''{0}'' must be initialized", NAME); MAP.put(UNINITIALIZED_VARIABLE, "Variable ''{0}'' must be initialized", NAME);
MAP.put(UNINITIALIZED_PARAMETER, "Parameter ''{0}'' is uninitialized here", NAME); MAP.put(UNINITIALIZED_PARAMETER, "Parameter ''{0}'' is uninitialized here", NAME);
@@ -288,20 +288,22 @@ public class Renderers {
return result; return result;
} }
public static final Renderer<Collection<ClassDescriptor>> CLASS_DESCRIPTOR_LIST = new Renderer<Collection<ClassDescriptor>>() { public static final Renderer<Collection<ClassDescriptor>> CLASSES_OR_SEPARATED = new Renderer<Collection<ClassDescriptor>>() {
@NotNull @NotNull
@Override @Override
public String render(@NotNull Collection<ClassDescriptor> descriptors) { public String render(@NotNull Collection<ClassDescriptor> descriptors) {
StringBuilder sb = new StringBuilder(); StringBuilder sb = new StringBuilder();
sb.append("("); int index = 0;
for (Iterator<ClassDescriptor> iterator = descriptors.iterator(); iterator.hasNext(); ) { for (ClassDescriptor descriptor : descriptors) {
ClassDescriptor descriptor = iterator.next();
sb.append(DescriptorUtils.getFQName(descriptor).getFqName()); sb.append(DescriptorUtils.getFQName(descriptor).getFqName());
if (iterator.hasNext()) { index++;
if (index <= descriptors.size() - 2) {
sb.append(", "); sb.append(", ");
} }
else if (index == descriptors.size() - 1) {
sb.append(" or ");
}
} }
sb.append(")");
return sb.toString(); return sb.toString();
} }
}; };
@@ -1591,6 +1591,7 @@ public class JetExpressionParsing extends AbstractJetParsing {
* : "#" "(" (((SimpleName "=")? expression){","})? ")" * : "#" "(" (((SimpleName "=")? expression){","})? ")"
* ; * ;
*/ */
@Deprecated // Tuples are to be removed in Kotlin M4
private void parseTupleExpression() { private void parseTupleExpression() {
assert _at(HASH); assert _at(HASH);
PsiBuilder.Marker mark = mark(); PsiBuilder.Marker mark = mark();
@@ -980,8 +980,7 @@ public class JetParsing extends AbstractJetParsing {
expect(IDENTIFIER, "Expecting parameter name", TokenSet.create(RPAR, COLON, LBRACE, EQ)); expect(IDENTIFIER, "Expecting parameter name", TokenSet.create(RPAR, COLON, LBRACE, EQ));
if (at(COLON)) { if (at(COLON)) {
advance(); advance(); // COLON
parseTypeRef(); parseTypeRef();
} }
setterParameter.done(VALUE_PARAMETER); setterParameter.done(VALUE_PARAMETER);
@@ -1565,6 +1564,7 @@ public class JetParsing extends AbstractJetParsing {
* : "#" "(" parameter{","} ")" // tuple with named entries, the names do not affect assignment compatibility * : "#" "(" parameter{","} ")" // tuple with named entries, the names do not affect assignment compatibility
* ; * ;
*/ */
@Deprecated // Tuples are to be removed in Kotlin M4
private void parseTupleType() { private void parseTupleType() {
assert _at(HASH); assert _at(HASH);
@@ -1730,20 +1730,23 @@ public class JetParsing extends AbstractJetParsing {
private boolean parseFunctionParameterRest() { private boolean parseFunctionParameterRest() {
expect(IDENTIFIER, "Parameter name expected", PARAMETER_NAME_RECOVERY_SET); expect(IDENTIFIER, "Parameter name expected", PARAMETER_NAME_RECOVERY_SET);
boolean noErrors = true;
if (at(COLON)) { if (at(COLON)) {
advance(); // COLON advance(); // COLON
parseTypeRef(); parseTypeRef();
} }
else { else {
error("Parameters must have type annotation"); errorWithRecovery("Parameters must have type annotation", PARAMETER_NAME_RECOVERY_SET);
return false; noErrors = false;
} }
if (at(EQ)) { if (at(EQ)) {
advance(); // EQ advance(); // EQ
myExpressionParsing.parseExpression(); myExpressionParsing.parseExpression();
} }
return true;
return noErrors;
} }
/* /*
@@ -25,7 +25,10 @@ import java.util.List;
/** /**
* @author max * @author max
*/ */
@Deprecated // Tuples are to be removed in Kotlin M4
public class JetTupleExpression extends JetExpressionImpl { public class JetTupleExpression extends JetExpressionImpl {
@Deprecated // Tuples are to be removed in Kotlin M4
public JetTupleExpression(@NotNull ASTNode node) { public JetTupleExpression(@NotNull ASTNode node) {
super(node); super(node);
} }
@@ -40,6 +43,7 @@ public class JetTupleExpression extends JetExpressionImpl {
return visitor.visitTupleExpression(this, data); return visitor.visitTupleExpression(this, data);
} }
@Deprecated // Tuples are to be removed in Kotlin M4
public List<JetExpression> getEntries() { public List<JetExpression> getEntries() {
return PsiTreeUtil.getChildrenOfTypeAsList(this, JetExpression.class); return PsiTreeUtil.getChildrenOfTypeAsList(this, JetExpression.class);
} }
@@ -25,7 +25,10 @@ import java.util.List;
/** /**
* @author max * @author max
*/ */
@Deprecated // Tuples are to be removed in Kotlin M4
public class JetTupleType extends JetTypeElement { public class JetTupleType extends JetTypeElement {
@Deprecated // Tuples are to be removed in Kotlin M4
public JetTupleType(@NotNull ASTNode node) { public JetTupleType(@NotNull ASTNode node) {
super(node); super(node);
} }
@@ -47,6 +50,7 @@ public class JetTupleType extends JetTypeElement {
} }
@NotNull @NotNull
@Deprecated // Tuples are to be removed in Kotlin M4
public List<JetTypeReference> getComponentTypeRefs() { public List<JetTypeReference> getComponentTypeRefs() {
return findChildrenByType(JetNodeTypes.TYPE_REFERENCE); return findChildrenByType(JetNodeTypes.TYPE_REFERENCE);
} }
@@ -168,6 +168,7 @@ public class JetVisitor<R, D> extends PsiElementVisitor {
return visitExpression(expression, data); return visitExpression(expression, data);
} }
@Deprecated // Tuples are to be removed in Kotlin M4
public R visitTupleExpression(JetTupleExpression expression, D data) { public R visitTupleExpression(JetTupleExpression expression, D data) {
return visitExpression(expression, data); return visitExpression(expression, data);
} }
@@ -336,6 +337,7 @@ public class JetVisitor<R, D> extends PsiElementVisitor {
return visitTypeElement(type, data); return visitTypeElement(type, data);
} }
@Deprecated // Tuples are to be removed in Kotlin M4
public R visitTupleType(JetTupleType type, D data) { public R visitTupleType(JetTupleType type, D data) {
return visitTypeElement(type, data); return visitTypeElement(type, data);
} }
@@ -158,6 +158,7 @@ public class JetVisitorVoid extends PsiElementVisitor {
visitExpression(expression); visitExpression(expression);
} }
@Deprecated // Tuples are to be removed in Kotlin M4
public void visitTupleExpression(JetTupleExpression expression) { public void visitTupleExpression(JetTupleExpression expression) {
visitExpression(expression); visitExpression(expression);
} }
@@ -325,6 +326,7 @@ public class JetVisitorVoid extends PsiElementVisitor {
visitTypeElement(type); visitTypeElement(type);
} }
@Deprecated // Tuples are to be removed in Kotlin M4
public void visitTupleType(JetTupleType type) { public void visitTupleType(JetTupleType type) {
visitTypeElement(type); visitTypeElement(type);
} }
@@ -16,9 +16,11 @@
package org.jetbrains.jet.lang.resolve; package org.jetbrains.jet.lang.resolve;
import com.google.common.collect.ImmutableMap;
import com.intellij.psi.PsiElement; import com.intellij.psi.PsiElement;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import org.jetbrains.annotations.TestOnly;
import org.jetbrains.jet.lang.descriptors.*; import org.jetbrains.jet.lang.descriptors.*;
import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor; import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor;
import org.jetbrains.jet.lang.diagnostics.Diagnostic; import org.jetbrains.jet.lang.diagnostics.Diagnostic;
@@ -59,6 +61,13 @@ public interface BindingContext {
public <K, V> Collection<K> getKeys(WritableSlice<K, V> slice) { public <K, V> Collection<K> getKeys(WritableSlice<K, V> slice) {
return Collections.emptyList(); return Collections.emptyList();
} }
@NotNull
@TestOnly
@Override
public <K, V> ImmutableMap<K, V> getSliceContents(@NotNull ReadOnlySlice<K, V> slice) {
return ImmutableMap.of();
}
}; };
WritableSlice<AnnotationDescriptor, JetAnnotationEntry> ANNOTATION_DESCRIPTOR_TO_PSI_ELEMENT = Slices.createSimpleSlice(); WritableSlice<AnnotationDescriptor, JetAnnotationEntry> ANNOTATION_DESCRIPTOR_TO_PSI_ELEMENT = Slices.createSimpleSlice();
@@ -221,6 +230,8 @@ public interface BindingContext {
ReadOnlySlice<PsiElement, DeclarationDescriptor> DECLARATION_TO_DESCRIPTOR = Slices.<PsiElement, DeclarationDescriptor>sliceBuilder() ReadOnlySlice<PsiElement, DeclarationDescriptor> DECLARATION_TO_DESCRIPTOR = Slices.<PsiElement, DeclarationDescriptor>sliceBuilder()
.setFurtherLookupSlices(DECLARATIONS_TO_DESCRIPTORS).build(); .setFurtherLookupSlices(DECLARATIONS_TO_DESCRIPTORS).build();
WritableSlice<ClassDescriptor, Boolean> IS_ENUM_MOVED_TO_CLASS_OBJECT = Slices.createSimpleSlice();
WritableSlice<JetReferenceExpression, PsiElement> LABEL_TARGET = Slices.<JetReferenceExpression, PsiElement>sliceBuilder().build(); WritableSlice<JetReferenceExpression, PsiElement> LABEL_TARGET = Slices.<JetReferenceExpression, PsiElement>sliceBuilder().build();
WritableSlice<ValueParameterDescriptor, PropertyDescriptor> VALUE_PARAMETER_AS_PROPERTY = WritableSlice<ValueParameterDescriptor, PropertyDescriptor> VALUE_PARAMETER_AS_PROPERTY =
Slices.<ValueParameterDescriptor, PropertyDescriptor>sliceBuilder().build(); Slices.<ValueParameterDescriptor, PropertyDescriptor>sliceBuilder().build();
@@ -253,4 +264,9 @@ public interface BindingContext {
// slice.isCollective() must be true // slice.isCollective() must be true
@NotNull @NotNull
<K, V> Collection<K> getKeys(WritableSlice<K, V> slice); <K, V> Collection<K> getKeys(WritableSlice<K, V> slice);
/** This method should be used only for debug and testing */
@TestOnly
@NotNull
<K, V> ImmutableMap<K, V> getSliceContents(@NotNull ReadOnlySlice<K, V> slice);
} }
@@ -16,8 +16,10 @@
package org.jetbrains.jet.lang.resolve; package org.jetbrains.jet.lang.resolve;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Lists; import com.google.common.collect.Lists;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.TestOnly;
import org.jetbrains.jet.lang.diagnostics.Diagnostic; import org.jetbrains.jet.lang.diagnostics.Diagnostic;
import org.jetbrains.jet.util.slicedmap.MutableSlicedMap; import org.jetbrains.jet.util.slicedmap.MutableSlicedMap;
import org.jetbrains.jet.util.slicedmap.ReadOnlySlice; import org.jetbrains.jet.util.slicedmap.ReadOnlySlice;
@@ -52,6 +54,13 @@ public class BindingTraceContext implements BindingTrace {
public <K, V> Collection<K> getKeys(WritableSlice<K, V> slice) { public <K, V> Collection<K> getKeys(WritableSlice<K, V> slice) {
return BindingTraceContext.this.getKeys(slice); return BindingTraceContext.this.getKeys(slice);
} }
@NotNull
@TestOnly
@Override
public <K, V> ImmutableMap<K, V> getSliceContents(@NotNull ReadOnlySlice<K, V> slice) {
return map.getSliceContents(slice);
}
}; };
@Override @Override
@@ -30,6 +30,7 @@ import org.jetbrains.jet.lang.resolve.scopes.JetScope;
import org.jetbrains.jet.lang.resolve.scopes.WritableScope; import org.jetbrains.jet.lang.resolve.scopes.WritableScope;
import org.jetbrains.jet.lang.types.ErrorUtils; import org.jetbrains.jet.lang.types.ErrorUtils;
import org.jetbrains.jet.lang.types.lang.JetStandardLibrary; import org.jetbrains.jet.lang.types.lang.JetStandardLibrary;
import org.jetbrains.jet.resolve.DescriptorRenderer;
import javax.inject.Inject; import javax.inject.Inject;
import java.util.*; import java.util.*;
@@ -302,7 +303,8 @@ public class DeclarationResolver {
if (descriptors.size() > 1) { if (descriptors.size() > 1) {
for (DeclarationDescriptor declarationDescriptor : descriptors) { for (DeclarationDescriptor declarationDescriptor : descriptors) {
for (PsiElement declaration : getDeclarationsByDescriptor(declarationDescriptor)) { for (PsiElement declaration : getDeclarationsByDescriptor(declarationDescriptor)) {
assert declaration != null; assert declaration != null : "Null declaration for descriptor: " + declarationDescriptor + " " +
(declarationDescriptor != null ? DescriptorRenderer.TEXT.render(declarationDescriptor) : "");
trace.report(REDECLARATION.on(declaration, declarationDescriptor.getName().getName())); trace.report(REDECLARATION.on(declaration, declarationDescriptor.getName().getName()));
} }
} }
@@ -66,6 +66,7 @@ public class DeclarationsChecker {
MutableClassDescriptor objectDescriptor = entry.getValue(); MutableClassDescriptor objectDescriptor = entry.getValue();
if (!bodiesResolveContext.completeAnalysisNeeded(objectDeclaration)) continue; if (!bodiesResolveContext.completeAnalysisNeeded(objectDeclaration)) continue;
checkObject(objectDeclaration);
modifiersChecker.checkIllegalModalityModifiers(objectDeclaration); modifiersChecker.checkIllegalModalityModifiers(objectDeclaration);
} }
@@ -91,12 +92,22 @@ public class DeclarationsChecker {
} }
private void reportErrorIfHasEnumModifier(JetModifierListOwner declaration) {
if (declaration.hasModifier(JetTokens.ENUM_KEYWORD)) {
trace.report(ILLEGAL_ENUM_ANNOTATION.on(declaration));
}
}
private void checkObject(JetObjectDeclaration declaration) {
reportErrorIfHasEnumModifier(declaration);
}
private void checkClass(JetClass aClass, MutableClassDescriptor classDescriptor) { private void checkClass(JetClass aClass, MutableClassDescriptor classDescriptor) {
checkOpenMembers(classDescriptor); checkOpenMembers(classDescriptor);
if (aClass.isTrait()) { if (aClass.isTrait()) {
checkTraitModifiers(aClass); checkTraitModifiers(aClass);
} }
else if (aClass.hasModifier(JetTokens.ENUM_KEYWORD)) { else if (classDescriptor.getKind() == ClassKind.ENUM_CLASS) {
checkEnumModifiers(aClass); checkEnumModifiers(aClass);
} }
else if (classDescriptor.getKind() == ClassKind.ENUM_ENTRY) { else if (classDescriptor.getKind() == ClassKind.ENUM_ENTRY) {
@@ -105,6 +116,7 @@ public class DeclarationsChecker {
} }
private void checkTraitModifiers(JetClass aClass) { private void checkTraitModifiers(JetClass aClass) {
reportErrorIfHasEnumModifier(aClass);
JetModifierList modifierList = aClass.getModifierList(); JetModifierList modifierList = aClass.getModifierList();
if (modifierList == null) return; if (modifierList == null) return;
if (modifierList.hasModifier(JetTokens.FINAL_KEYWORD)) { if (modifierList.hasModifier(JetTokens.FINAL_KEYWORD)) {
@@ -130,6 +142,7 @@ public class DeclarationsChecker {
} }
private void checkProperty(JetProperty property, PropertyDescriptor propertyDescriptor) { private void checkProperty(JetProperty property, PropertyDescriptor propertyDescriptor) {
reportErrorIfHasEnumModifier(property);
DeclarationDescriptor containingDeclaration = propertyDescriptor.getContainingDeclaration(); DeclarationDescriptor containingDeclaration = propertyDescriptor.getContainingDeclaration();
if (containingDeclaration instanceof ClassDescriptor) { if (containingDeclaration instanceof ClassDescriptor) {
checkPropertyAbstractness(property, propertyDescriptor, (ClassDescriptor) containingDeclaration); checkPropertyAbstractness(property, propertyDescriptor, (ClassDescriptor) containingDeclaration);
@@ -247,6 +260,7 @@ public class DeclarationsChecker {
} }
protected void checkFunction(JetNamedFunction function, SimpleFunctionDescriptor functionDescriptor) { protected void checkFunction(JetNamedFunction function, SimpleFunctionDescriptor functionDescriptor) {
reportErrorIfHasEnumModifier(function);
DeclarationDescriptor containingDescriptor = functionDescriptor.getContainingDeclaration(); DeclarationDescriptor containingDescriptor = functionDescriptor.getContainingDeclaration();
boolean hasAbstractModifier = function.hasModifier(JetTokens.ABSTRACT_KEYWORD); boolean hasAbstractModifier = function.hasModifier(JetTokens.ABSTRACT_KEYWORD);
checkDeclaredTypeInPublicMember(function, functionDescriptor); checkDeclaredTypeInPublicMember(function, functionDescriptor);
@@ -16,10 +16,11 @@
package org.jetbrains.jet.lang.resolve; package org.jetbrains.jet.lang.resolve;
import com.google.common.base.Predicate; import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Lists; import com.google.common.collect.Lists;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import org.jetbrains.annotations.TestOnly;
import org.jetbrains.jet.lang.diagnostics.Diagnostic; import org.jetbrains.jet.lang.diagnostics.Diagnostic;
import org.jetbrains.jet.util.slicedmap.*; import org.jetbrains.jet.util.slicedmap.*;
@@ -55,6 +56,15 @@ public class DelegatingBindingTrace implements BindingTrace {
return DelegatingBindingTrace.this.getKeys(slice); return DelegatingBindingTrace.this.getKeys(slice);
} }
@NotNull
@TestOnly
@Override
public <K, V> ImmutableMap<K, V> getSliceContents(@NotNull ReadOnlySlice<K, V> slice) {
ImmutableMap<K, V> parentContents = parentContext.getSliceContents(slice);
ImmutableMap<K, V> currentContents = map.getSliceContents(slice);
return ImmutableMap.<K, V>builder().putAll(parentContents).putAll(currentContents).build();
}
}; };
public DelegatingBindingTrace(BindingContext parentContext) { public DelegatingBindingTrace(BindingContext parentContext) {
@@ -355,4 +355,14 @@ public class DescriptorUtils {
+ (classifier == null ? "null" : classifier.getClass()); + (classifier == null ? "null" : classifier.getClass());
return (ClassDescriptor) classifier; return (ClassDescriptor) classifier;
} }
@SuppressWarnings("unchecked")
public static Collection<ClassDescriptor> getInnerClasses(ClassDescriptor classDescriptor) {
Collection<DeclarationDescriptor> innerClasses = classDescriptor.getUnsubstitutedInnerClassesScope().getAllDescriptors();
for (DeclarationDescriptor inner : innerClasses) {
assert inner instanceof ClassDescriptor
: "Not a class in inner classes scope of " + classDescriptor + ": " + inner;
}
return (Collection) innerClasses;
}
} }
@@ -184,22 +184,25 @@ public class OverrideResolver {
@NotNull ClassDescriptor current, @NotNull ClassDescriptor current,
@NotNull DescriptorSink sink @NotNull DescriptorSink sink
) { ) {
List<CallableMemberDescriptor> notOverridden = Lists.newArrayList(membersFromSupertypes); Collection<CallableMemberDescriptor> notOverridden = Sets.newLinkedHashSet(membersFromSupertypes);
for (CallableMemberDescriptor fromCurrent : membersFromCurrent) { for (CallableMemberDescriptor fromCurrent : membersFromCurrent) {
extractAndBindOverridesForMember(fromCurrent, notOverridden, current, sink); Collection<CallableMemberDescriptor> bound =
extractAndBindOverridesForMember(fromCurrent, membersFromSupertypes, current, sink);
notOverridden.removeAll(bound);
} }
createAndBindFakeOverrides(current, notOverridden, sink); createAndBindFakeOverrides(current, notOverridden, sink);
} }
private static void extractAndBindOverridesForMember( private static Collection<CallableMemberDescriptor> extractAndBindOverridesForMember(
@NotNull CallableMemberDescriptor fromCurrent, @NotNull CallableMemberDescriptor fromCurrent,
@NotNull List<CallableMemberDescriptor> notOverridden, @NotNull ClassDescriptor current, @NotNull Collection<? extends CallableMemberDescriptor> descriptorsFromSuper,
@NotNull ClassDescriptor current,
@NotNull DescriptorSink sink @NotNull DescriptorSink sink
) { ) {
for (Iterator<CallableMemberDescriptor> iterator = notOverridden.iterator(); iterator.hasNext(); ) { Collection<CallableMemberDescriptor> bound = Lists.newArrayList();
CallableMemberDescriptor fromSupertype = iterator.next(); for (CallableMemberDescriptor fromSupertype : descriptorsFromSuper) {
OverridingUtil.OverrideCompatibilityInfo.Result result = OverridingUtil.OverrideCompatibilityInfo.Result result =
OverridingUtil.isOverridableBy(fromSupertype, fromCurrent).getResult(); OverridingUtil.isOverridableBy(fromSupertype, fromCurrent).getResult();
@@ -209,23 +212,24 @@ public class OverrideResolver {
if (isVisible) { if (isVisible) {
OverridingUtil.bindOverride(fromCurrent, fromSupertype); OverridingUtil.bindOverride(fromCurrent, fromSupertype);
} }
iterator.remove(); bound.add(fromSupertype);
break; break;
case CONFLICT: case CONFLICT:
if (isVisible) { if (isVisible) {
sink.conflict(fromSupertype, fromCurrent); sink.conflict(fromSupertype, fromCurrent);
} }
iterator.remove(); bound.add(fromSupertype);
break; break;
case INCOMPATIBLE: case INCOMPATIBLE:
break; break;
} }
} }
return bound;
} }
private static void createAndBindFakeOverrides( private static void createAndBindFakeOverrides(
@NotNull ClassDescriptor current, @NotNull ClassDescriptor current,
@NotNull List<CallableMemberDescriptor> notOverridden, @NotNull Collection<CallableMemberDescriptor> notOverridden,
@NotNull DescriptorSink sink @NotNull DescriptorSink sink
) { ) {
Queue<CallableMemberDescriptor> fromSuperQueue = new LinkedList<CallableMemberDescriptor>(notOverridden); Queue<CallableMemberDescriptor> fromSuperQueue = new LinkedList<CallableMemberDescriptor>(notOverridden);
@@ -735,7 +739,7 @@ public class OverrideResolver {
if (OverridingUtil.isOverridableBy(fromSuper, declared).getResult() == OVERRIDABLE) { if (OverridingUtil.isOverridableBy(fromSuper, declared).getResult() == OVERRIDABLE) {
invisibleOverride = fromSuper; invisibleOverride = fromSuper;
if (Visibilities.isVisible(fromSuper, declared)) { if (Visibilities.isVisible(fromSuper, declared)) {
throw new IllegalStateException("Descriptor " + fromSuper + "is overridable by " + declared + " and visible but does not appear in its getOverriddenDescriptors()"); throw new IllegalStateException("Descriptor " + fromSuper + " is overridable by " + declared + " and visible but does not appear in its getOverriddenDescriptors()");
} }
break outer; break outer;
} }
@@ -19,6 +19,7 @@ package org.jetbrains.jet.lang.resolve;
import com.google.common.collect.Lists; import com.google.common.collect.Lists;
import com.google.common.collect.Multimap; import com.google.common.collect.Multimap;
import com.google.common.collect.Sets; import com.google.common.collect.Sets;
import com.intellij.lang.ASTNode;
import com.intellij.psi.PsiElement; import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiNameIdentifierOwner; import com.intellij.psi.PsiNameIdentifierOwner;
import com.intellij.util.containers.ContainerUtil; import com.intellij.util.containers.ContainerUtil;
@@ -195,164 +196,14 @@ public class TypeHierarchyResolver {
) { ) {
final Collection<JetDeclarationContainer> forDeferredResolve = new ArrayList<JetDeclarationContainer>(); final Collection<JetDeclarationContainer> forDeferredResolve = new ArrayList<JetDeclarationContainer>();
ClassifierCollector collector = new ClassifierCollector(outerScope, owner, forDeferredResolve);
for (PsiElement declaration : declarations) { for (PsiElement declaration : declarations) {
declaration.accept(new JetVisitorVoid() { declaration.accept(collector);
@Override
public void visitJetFile(JetFile file) {
NamespaceDescriptorImpl namespaceDescriptor = namespaceFactory.createNamespaceDescriptorPathIfNeeded(
file, outerScope, RedeclarationHandler.DO_NOTHING);
context.getNamespaceDescriptors().put(file, namespaceDescriptor);
WriteThroughScope namespaceScope = new WriteThroughScope(outerScope, namespaceDescriptor.getMemberScope(),
new TraceBasedRedeclarationHandler(trace), "namespace");
namespaceScope.changeLockLevel(WritableScope.LockLevel.BOTH);
context.getNamespaceScopes().put(file, namespaceScope);
if (file.isScript()) {
scriptHeaderResolver.processScriptHierarchy(file.getScript(), namespaceScope);
}
prepareForDeferredCall(namespaceScope, namespaceDescriptor, file);
}
@Override
public void visitClass(JetClass klass) {
MutableClassDescriptor mutableClassDescriptor = new MutableClassDescriptor(
owner.getOwnerForChildren(), outerScope, getClassKind(klass), JetPsiUtil.safeName(klass.getName()));
context.getClasses().put(klass, mutableClassDescriptor);
trace.record(FQNAME_TO_CLASS_DESCRIPTOR, JetPsiUtil.getFQName(klass), mutableClassDescriptor);
createClassObjectForEnumClass(klass, mutableClassDescriptor);
JetScope classScope = mutableClassDescriptor.getScopeForMemberResolution();
prepareForDeferredCall(classScope, mutableClassDescriptor, klass);
owner.addClassifierDescriptor(mutableClassDescriptor);
}
@Override
public void visitObjectDeclaration(JetObjectDeclaration declaration) {
MutableClassDescriptor objectDescriptor =
createClassDescriptorForObject(declaration, owner, outerScope, JetPsiUtil.safeName(declaration.getName()),
ClassKind.OBJECT);
owner.addObjectDescriptor(objectDescriptor);
trace.record(FQNAME_TO_CLASS_DESCRIPTOR, JetPsiUtil.getFQName(declaration), objectDescriptor);
}
@Override
public void visitEnumEntry(JetEnumEntry enumEntry) {
// TODO: Bad casting
MutableClassDescriptorLite ownerClassDescriptor = (MutableClassDescriptorLite) owner.getOwnerForChildren();
MutableClassDescriptorLite classObjectDescriptor = ownerClassDescriptor.getClassObjectDescriptor();
assert classObjectDescriptor != null : enumEntry.getParent().getText();
createClassDescriptorForEnumEntry(enumEntry, classObjectDescriptor.getBuilder());
}
@Override
public void visitTypedef(JetTypedef typedef) {
trace.report(UNSUPPORTED.on(typedef, "TypeHierarchyResolver"));
}
@Override
public void visitClassObject(JetClassObject classObject) {
JetObjectDeclaration objectDeclaration = classObject.getObjectDeclaration();
if (objectDeclaration != null) {
Name classObjectName = getClassObjectName(owner.getOwnerForChildren().getName());
MutableClassDescriptor classObjectDescriptor =
createClassDescriptorForObject(objectDeclaration, owner, getStaticScope(classObject, owner),
classObjectName, ClassKind.CLASS_OBJECT);
NamespaceLikeBuilder.ClassObjectStatus status = owner.setClassObjectDescriptor(classObjectDescriptor);
switch (status) {
case DUPLICATE:
trace.report(MANY_CLASS_OBJECTS.on(classObject));
break;
case NOT_ALLOWED:
trace.report(CLASS_OBJECT_NOT_ALLOWED.on(classObject));
break;
case OK:
// Everything is OK so no errors to trace.
break;
}
}
}
private void createClassObjectForEnumClass(JetClass klass, MutableClassDescriptor mutableClassDescriptor) {
if (klass.hasModifier(JetTokens.ENUM_KEYWORD)) {
MutableClassDescriptor classObjectDescriptor = new MutableClassDescriptor(
mutableClassDescriptor, outerScope, ClassKind.CLASS_OBJECT,
getClassObjectName(klass.getName()));
mutableClassDescriptor.getBuilder().setClassObjectDescriptor(classObjectDescriptor);
classObjectDescriptor.setModality(Modality.FINAL);
classObjectDescriptor.setVisibility(ModifiersChecker.resolveVisibilityFromModifiers(klass));
classObjectDescriptor.setTypeParameterDescriptors(new ArrayList<TypeParameterDescriptor>(0));
classObjectDescriptor.createTypeConstructor();
ConstructorDescriptorImpl primaryConstructorForObject =
createPrimaryConstructorForObject(null, classObjectDescriptor);
primaryConstructorForObject.setReturnType(classObjectDescriptor.getDefaultType());
classObjectDescriptor.getBuilder().addFunctionDescriptor(DescriptorResolver.createEnumClassObjectValuesMethod(classObjectDescriptor, trace));
classObjectDescriptor.getBuilder().addFunctionDescriptor(DescriptorResolver.createEnumClassObjectValueOfMethod(classObjectDescriptor, trace));
}
}
private MutableClassDescriptor createClassDescriptorForObject(
@NotNull JetObjectDeclaration declaration, @NotNull NamespaceLikeBuilder owner,
@NotNull JetScope scope, @NotNull Name name, @NotNull ClassKind kind
) {
MutableClassDescriptor mutableClassDescriptor = new MutableClassDescriptor(
owner.getOwnerForChildren(), scope, kind, name);
context.getObjects().put(declaration, mutableClassDescriptor);
JetScope classScope = mutableClassDescriptor.getScopeForMemberResolution();
prepareForDeferredCall(classScope, mutableClassDescriptor, declaration);
createPrimaryConstructorForObject(declaration, mutableClassDescriptor);
trace.record(BindingContext.CLASS, declaration, mutableClassDescriptor);
return mutableClassDescriptor;
}
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()));
context.getClasses().put(declaration, mutableClassDescriptor);
prepareForDeferredCall(mutableClassDescriptor.getScopeForMemberResolution(), mutableClassDescriptor, declaration);
// ??? - is enum entry object?
createPrimaryConstructorForObject(declaration, mutableClassDescriptor);
owner.addObjectDescriptor(mutableClassDescriptor);
trace.record(BindingContext.CLASS, declaration, mutableClassDescriptor);
return mutableClassDescriptor;
}
private ConstructorDescriptorImpl createPrimaryConstructorForObject(
@Nullable PsiElement object,
MutableClassDescriptor mutableClassDescriptor
) {
ConstructorDescriptorImpl constructorDescriptor = DescriptorResolver
.createAndRecordPrimaryConstructorForObject(object, mutableClassDescriptor, trace);
mutableClassDescriptor.setPrimaryConstructor(constructorDescriptor, trace);
return constructorDescriptor;
}
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);
}
});
} }
collector.finishProcessing();
return forDeferredResolve; return forDeferredResolve;
} }
@@ -619,4 +470,255 @@ public class TypeHierarchyResolver {
} }
} }
} }
private class ClassifierCollector extends JetVisitorVoid {
private final JetScope outerScope;
private final NamespaceLikeBuilder owner;
private final Collection<JetDeclarationContainer> forDeferredResolve;
private final List<JetClass> enumsToAddLater = new ArrayList<JetClass>(0);
public ClassifierCollector(@NotNull JetScope outerScope,
@NotNull NamespaceLikeBuilder owner,
@NotNull Collection<JetDeclarationContainer> forDeferredResolve
) {
this.outerScope = outerScope;
this.owner = owner;
this.forDeferredResolve = forDeferredResolve;
}
@Override
public void visitJetFile(JetFile file) {
NamespaceDescriptorImpl namespaceDescriptor = namespaceFactory.createNamespaceDescriptorPathIfNeeded(
file, outerScope, RedeclarationHandler.DO_NOTHING);
context.getNamespaceDescriptors().put(file, namespaceDescriptor);
WriteThroughScope namespaceScope = new WriteThroughScope(outerScope, namespaceDescriptor.getMemberScope(),
new TraceBasedRedeclarationHandler(trace), "namespace");
namespaceScope.changeLockLevel(WritableScope.LockLevel.BOTH);
context.getNamespaceScopes().put(file, namespaceScope);
if (file.isScript()) {
scriptHeaderResolver.processScriptHierarchy(file.getScript(), namespaceScope);
}
prepareForDeferredCall(namespaceScope, namespaceDescriptor, file);
}
@Override
public void visitClass(JetClass klass) {
if (getClassKind(klass) == ClassKind.ENUM_CLASS && inClass()) {
// Enums inside non-static context are put not to owner, but rather into its class object.
// This is handled after visiting all declarations in this class, because we may or may not
// encounter class object to put this enum into.
enumsToAddLater.add(klass);
return;
}
MutableClassDescriptor mutableClassDescriptor = createClassDescriptorForClass(klass, owner.getOwnerForChildren());
owner.addClassifierDescriptor(mutableClassDescriptor);
}
private boolean inClass() {
if (!(owner.getOwnerForChildren() instanceof ClassDescriptor)) return false;
ClassKind kind = ((ClassDescriptor) owner.getOwnerForChildren()).getKind();
return kind == ClassKind.CLASS || kind == ClassKind.ENUM_CLASS || kind == ClassKind.TRAIT;
}
@Override
public void visitObjectDeclaration(JetObjectDeclaration declaration) {
MutableClassDescriptor objectDescriptor =
createClassDescriptorForObject(declaration, owner, outerScope, JetPsiUtil.safeName(declaration.getName()),
ClassKind.OBJECT);
owner.addObjectDescriptor(objectDescriptor);
trace.record(FQNAME_TO_CLASS_DESCRIPTOR, JetPsiUtil.getFQName(declaration), objectDescriptor);
}
@Override
public void visitEnumEntry(JetEnumEntry enumEntry) {
// TODO: Bad casting
MutableClassDescriptorLite ownerClassDescriptor = (MutableClassDescriptorLite) owner.getOwnerForChildren();
MutableClassDescriptorLite classObjectDescriptor = ownerClassDescriptor.getClassObjectDescriptor();
assert classObjectDescriptor != null : enumEntry.getParent().getText();
createClassDescriptorForEnumEntry(enumEntry, classObjectDescriptor.getBuilder());
}
@Override
public void visitTypedef(JetTypedef typedef) {
trace.report(UNSUPPORTED.on(typedef, "TypeHierarchyResolver"));
}
@Override
public void visitClassObject(JetClassObject classObject) {
JetObjectDeclaration objectDeclaration = classObject.getObjectDeclaration();
if (objectDeclaration != null) {
Name classObjectName = getClassObjectName(owner.getOwnerForChildren().getName());
MutableClassDescriptor classObjectDescriptor =
createClassDescriptorForObject(objectDeclaration, owner, getStaticScope(classObject, owner),
classObjectName, ClassKind.CLASS_OBJECT);
NamespaceLikeBuilder.ClassObjectStatus status = owner.setClassObjectDescriptor(classObjectDescriptor);
switch (status) {
case DUPLICATE:
trace.report(MANY_CLASS_OBJECTS.on(classObject));
break;
case NOT_ALLOWED:
trace.report(CLASS_OBJECT_NOT_ALLOWED.on(classObject));
break;
case OK:
// Everything is OK so no errors to trace.
break;
}
}
}
private void createClassObjectForEnumClass(JetClass klass, MutableClassDescriptor mutableClassDescriptor) {
if (mutableClassDescriptor.getKind() == ClassKind.ENUM_CLASS) {
MutableClassDescriptor classObjectDescriptor =
createClassObjectDescriptor(mutableClassDescriptor, ModifiersChecker.resolveVisibilityFromModifiers(klass));
mutableClassDescriptor.getBuilder().setClassObjectDescriptor(classObjectDescriptor);
classObjectDescriptor.getBuilder().addFunctionDescriptor(
DescriptorResolver.createEnumClassObjectValuesMethod(classObjectDescriptor, trace));
classObjectDescriptor.getBuilder().addFunctionDescriptor(
DescriptorResolver.createEnumClassObjectValueOfMethod(classObjectDescriptor, trace));
}
}
@NotNull
private MutableClassDescriptor createClassObjectDescriptor(
@NotNull ClassDescriptor classDescriptor,
@NotNull Visibility visibility
) {
MutableClassDescriptor classObjectDescriptor = new MutableClassDescriptor(
classDescriptor, outerScope, ClassKind.CLASS_OBJECT, getClassObjectName(classDescriptor.getName()));
classObjectDescriptor.setModality(Modality.FINAL);
classObjectDescriptor.setVisibility(visibility);
classObjectDescriptor.setTypeParameterDescriptors(new ArrayList<TypeParameterDescriptor>(0));
classObjectDescriptor.createTypeConstructor();
ConstructorDescriptorImpl primaryConstructorForObject = createPrimaryConstructorForObject(null, classObjectDescriptor);
primaryConstructorForObject.setReturnType(classObjectDescriptor.getDefaultType());
return classObjectDescriptor;
}
@NotNull
private MutableClassDescriptor createClassDescriptorForClass(
@NotNull JetClass klass,
@NotNull DeclarationDescriptor containingDeclaration
) {
MutableClassDescriptor mutableClassDescriptor = new MutableClassDescriptor(
containingDeclaration, outerScope, getClassKind(klass), JetPsiUtil.safeName(klass.getName()));
context.getClasses().put(klass, mutableClassDescriptor);
trace.record(FQNAME_TO_CLASS_DESCRIPTOR, JetPsiUtil.getFQName(klass), mutableClassDescriptor);
createClassObjectForEnumClass(klass, mutableClassDescriptor);
JetScope classScope = mutableClassDescriptor.getScopeForMemberResolution();
prepareForDeferredCall(classScope, mutableClassDescriptor, klass);
return mutableClassDescriptor;
}
@NotNull
private MutableClassDescriptor createClassDescriptorForObject(
@NotNull JetObjectDeclaration declaration, @NotNull NamespaceLikeBuilder owner,
@NotNull JetScope scope, @NotNull Name name, @NotNull ClassKind kind
) {
MutableClassDescriptor mutableClassDescriptor = new MutableClassDescriptor(
owner.getOwnerForChildren(), scope, kind, name);
context.getObjects().put(declaration, mutableClassDescriptor);
JetScope classScope = mutableClassDescriptor.getScopeForMemberResolution();
prepareForDeferredCall(classScope, mutableClassDescriptor, declaration);
createPrimaryConstructorForObject(declaration, mutableClassDescriptor);
trace.record(BindingContext.CLASS, declaration, mutableClassDescriptor);
return mutableClassDescriptor;
}
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()));
context.getClasses().put(declaration, mutableClassDescriptor);
prepareForDeferredCall(mutableClassDescriptor.getScopeForMemberResolution(), mutableClassDescriptor, declaration);
// ??? - is enum entry object?
createPrimaryConstructorForObject(declaration, mutableClassDescriptor);
owner.addObjectDescriptor(mutableClassDescriptor);
trace.record(BindingContext.CLASS, declaration, mutableClassDescriptor);
return mutableClassDescriptor;
}
private ConstructorDescriptorImpl createPrimaryConstructorForObject(
@Nullable PsiElement object,
MutableClassDescriptor mutableClassDescriptor
) {
ConstructorDescriptorImpl constructorDescriptor = DescriptorResolver
.createAndRecordPrimaryConstructorForObject(object, mutableClassDescriptor, trace);
mutableClassDescriptor.setPrimaryConstructor(constructorDescriptor, trace);
return constructorDescriptor;
}
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);
}
@Nullable
private MutableClassDescriptor getOrCreateClassObjectDescriptor() {
ClassDescriptor ownerForChildren = (ClassDescriptor) owner.getOwnerForChildren();
MutableClassDescriptor classObjectDescriptor = (MutableClassDescriptor) ownerForChildren.getClassObjectDescriptor();
if (classObjectDescriptor == null) {
classObjectDescriptor = createClassObjectDescriptor(ownerForChildren, Visibilities.PUBLIC);
NamespaceLikeBuilder.ClassObjectStatus status = owner.setClassObjectDescriptor(classObjectDescriptor);
assert status != NamespaceLikeBuilder.ClassObjectStatus.DUPLICATE :
"Attempting to create an artificial class object where the real one exists: " + ownerForChildren;
if (status == NamespaceLikeBuilder.ClassObjectStatus.NOT_ALLOWED) {
return null;
}
}
return classObjectDescriptor;
}
private void putEnumsIntoOuterClassObject() {
if (enumsToAddLater.isEmpty()) return;
MutableClassDescriptor classObjectDescriptor = getOrCreateClassObjectDescriptor();
if (classObjectDescriptor == null) {
// A class object is not allowed in outer class, so report an error on every declared enum
for (JetClass klass : enumsToAddLater) {
JetModifierList modifierList = klass.getModifierList();
assert modifierList != null : "Enum class without modifier list: " + klass.getText();
ASTNode node = modifierList.getModifierNode(JetTokens.ENUM_KEYWORD);
assert node != null : "Enum class without enum modifier: " + klass.getText();
trace.report(ENUM_NOT_ALLOWED.on(node.getPsi()));
}
return;
}
for (JetClass klass : enumsToAddLater) {
MutableClassDescriptor mutableClassDescriptor = createClassDescriptorForClass(klass, classObjectDescriptor);
trace.record(BindingContext.IS_ENUM_MOVED_TO_CLASS_OBJECT, mutableClassDescriptor);
classObjectDescriptor.getBuilder().addClassifierDescriptor(mutableClassDescriptor);
}
}
private void finishProcessing() {
putEnumsIntoOuterClassObject();
}
}
} }
@@ -37,8 +37,7 @@ import java.util.Collection;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;
import static org.jetbrains.jet.lang.diagnostics.Errors.UNSUPPORTED; import static org.jetbrains.jet.lang.diagnostics.Errors.*;
import static org.jetbrains.jet.lang.diagnostics.Errors.WRONG_NUMBER_OF_TYPE_ARGUMENTS;
/** /**
* @author abreslav * @author abreslav
@@ -180,6 +179,14 @@ public class TypeResolver {
@Override @Override
public void visitTupleType(JetTupleType type) { public void visitTupleType(JetTupleType type) {
// TODO: remove this method completely when tuples are droppped
if (type.getComponentTypeRefs().size() <= 3) {
trace.report(TUPLES_ARE_NOT_SUPPORTED.on(type));
}
else {
trace.report(TUPLES_ARE_NOT_SUPPORTED_BIG.on(type));
}
// TODO labels // TODO labels
result[0] = JetStandardClasses.getTupleType(resolveTypes(scope, type.getComponentTypeRefs(), trace, checkBounds)); result[0] = JetStandardClasses.getTupleType(resolveTypes(scope, type.getComponentTypeRefs(), trace, checkBounds));
} }
@@ -20,6 +20,7 @@ import com.google.common.base.Predicate;
import com.google.common.base.Predicates; import com.google.common.base.Predicates;
import com.google.common.collect.Collections2; import com.google.common.collect.Collections2;
import com.google.common.collect.Lists; import com.google.common.collect.Lists;
import com.intellij.psi.PsiElement;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.descriptors.*; import org.jetbrains.jet.lang.descriptors.*;
@@ -139,7 +140,8 @@ public class LazyClassDescriptor extends ClassDescriptorBase implements ClassDes
} }
scope.changeLockLevel(WritableScope.LockLevel.READING); scope.changeLockLevel(WritableScope.LockLevel.READING);
scopeForClassHeaderResolution = new ChainedScope(this, scope, resolveSession.getResolutionScope(declarationProvider.getOwnerInfo().getScopeAnchor())); PsiElement scopeAnchor = declarationProvider.getOwnerInfo().getScopeAnchor();
scopeForClassHeaderResolution = new ChainedScope(this, scope, getScopeProvider().getResolutionScopeForDeclaration(scopeAnchor));
} }
return scopeForClassHeaderResolution; return scopeForClassHeaderResolution;
} }
@@ -285,8 +287,8 @@ public class LazyClassDescriptor extends ClassDescriptorBase implements ClassDes
JetModifierList modifierList = classInfo.getModifierList(); JetModifierList modifierList = classInfo.getModifierList();
if (modifierList != null) { if (modifierList != null) {
AnnotationResolver annotationResolver = resolveSession.getInjector().getAnnotationResolver(); AnnotationResolver annotationResolver = resolveSession.getInjector().getAnnotationResolver();
annotations = annotationResolver JetScope scopeForDeclaration = getScopeProvider().getResolutionScopeForDeclaration(classInfo.getScopeAnchor());
.resolveAnnotations(resolveSession.getResolutionScope(classInfo.getScopeAnchor()), modifierList, resolveSession.getTrace()); annotations = annotationResolver.resolveAnnotations(scopeForDeclaration, modifierList, resolveSession.getTrace());
} }
else { else {
annotations = Collections.emptyList(); annotations = Collections.emptyList();
@@ -426,4 +428,8 @@ public class LazyClassDescriptor extends ClassDescriptorBase implements ClassDes
}; };
} }
private ScopeProvider getScopeProvider() {
return resolveSession.getInjector().getScopeProvider();
}
} }
@@ -34,7 +34,6 @@ import org.jetbrains.jet.lang.resolve.BindingTraceContext;
import org.jetbrains.jet.lang.resolve.name.FqName; import org.jetbrains.jet.lang.resolve.name.FqName;
import org.jetbrains.jet.lang.resolve.name.FqNameUnsafe; import org.jetbrains.jet.lang.resolve.name.FqNameUnsafe;
import org.jetbrains.jet.lang.resolve.name.Name; import org.jetbrains.jet.lang.resolve.name.Name;
import org.jetbrains.jet.lang.resolve.scopes.InnerClassesScopeWrapper;
import org.jetbrains.jet.lang.resolve.scopes.JetScope; import org.jetbrains.jet.lang.resolve.scopes.JetScope;
import java.util.List; import java.util.List;
@@ -135,7 +134,7 @@ public class ResolveSession {
if (classOrObject.getParent() instanceof JetClassObject) { if (classOrObject.getParent() instanceof JetClassObject) {
return getClassObjectDescriptor((JetClassObject) classOrObject.getParent()); return getClassObjectDescriptor((JetClassObject) classOrObject.getParent());
} }
JetScope resolutionScope = getInjector().getScopeProvider().getResolutionScopeForDeclaration((JetDeclaration) classOrObject); JetScope resolutionScope = getInjector().getScopeProvider().getResolutionScopeForDeclaration(classOrObject);
Name name = classOrObject.getNameAsName(); Name name = classOrObject.getNameAsName();
assert name != null : "Name is null for " + classOrObject + " " + classOrObject.getText(); assert name != null : "Name is null for " + classOrObject + " " + classOrObject.getText();
ClassifierDescriptor classifier = resolutionScope.getClassifier(name); ClassifierDescriptor classifier = resolutionScope.getClassifier(name);
@@ -170,33 +169,6 @@ public class ResolveSession {
return declarationProviderFactory; return declarationProviderFactory;
} }
@NotNull
public JetScope getResolutionScope(PsiElement element) {
PsiElement parent = element.getParent();
if (parent instanceof JetFile) {
JetFile file = (JetFile) parent;
return getInjector().getScopeProvider().getFileScopeForDeclarationResolution(file);
}
if (parent instanceof JetClassBody) {
return getEnclosingLazyClass(element).getScopeForMemberDeclarationResolution();
}
if (parent instanceof JetClassObject) {
return new InnerClassesScopeWrapper(getEnclosingLazyClass(element).getScopeForMemberDeclarationResolution());
}
throw new IllegalArgumentException("Unsupported PSI element: " + element);
}
private LazyClassDescriptor getEnclosingLazyClass(PsiElement element) {
JetClassOrObject classOrObject = PsiTreeUtil.getParentOfType(element.getParent(), JetClassOrObject.class);
assert classOrObject != null : "Called for an element that is not a class member: " + element;
ClassDescriptor classDescriptor = getClassDescriptor(classOrObject);
assert classDescriptor instanceof LazyClassDescriptor : "Trying to resolve a member of a non-lazily loaded class: " + element;
return (LazyClassDescriptor) classDescriptor;
}
@NotNull @NotNull
public DeclarationDescriptor resolveToDescriptor(JetDeclaration declaration) { public DeclarationDescriptor resolveToDescriptor(JetDeclaration declaration) {
DeclarationDescriptor result = declaration.accept(new JetVisitor<DeclarationDescriptor, Void>() { DeclarationDescriptor result = declaration.accept(new JetVisitor<DeclarationDescriptor, Void>() {
@@ -183,7 +183,7 @@ public class ResolveSessionUtils {
JetFile file JetFile file
) { ) {
BodyResolver bodyResolver = createBodyResolver(trace, file, resolveSession.getModuleConfiguration()); BodyResolver bodyResolver = createBodyResolver(trace, file, resolveSession.getModuleConfiguration());
JetScope scope = resolveSession.getResolutionScope(namedFunction); JetScope scope = resolveSession.getInjector().getScopeProvider().getResolutionScopeForDeclaration(namedFunction);
FunctionDescriptor functionDescriptor = (FunctionDescriptor) resolveSession.resolveToDescriptor(namedFunction); FunctionDescriptor functionDescriptor = (FunctionDescriptor) resolveSession.resolveToDescriptor(namedFunction);
bodyResolver.resolveFunctionBody(trace, namedFunction, functionDescriptor, scope); bodyResolver.resolveFunctionBody(trace, namedFunction, functionDescriptor, scope);
} }
@@ -216,9 +216,12 @@ public class ResolveSessionUtils {
} }
private static JetScope getExpressionResolutionScope(@NotNull ResolveSession resolveSession, @NotNull JetExpression expression) { private static JetScope getExpressionResolutionScope(@NotNull ResolveSession resolveSession, @NotNull JetExpression expression) {
ScopeProvider provider = resolveSession.getInjector().getScopeProvider();
JetDeclaration parentDeclaration = PsiTreeUtil.getParentOfType(expression, JetDeclaration.class); JetDeclaration parentDeclaration = PsiTreeUtil.getParentOfType(expression, JetDeclaration.class);
// DeclarationDescriptor descriptor = resolveToDescriptor(parentDeclaration); if (parentDeclaration == null) {
return resolveSession.getResolutionScope(parentDeclaration); return provider.getFileScopeForDeclarationResolution((JetFile) expression.getContainingFile());
}
return provider.getResolutionScopeForDeclaration(parentDeclaration);
} }
public static JetScope getExpressionMemberScope(@NotNull ResolveSession resolveSession, @NotNull JetExpression expression) { public static JetScope getExpressionMemberScope(@NotNull ResolveSession resolveSession, @NotNull JetExpression expression) {
@@ -26,6 +26,9 @@ import org.jetbrains.jet.lang.resolve.ImportsResolver;
import org.jetbrains.jet.lang.resolve.name.FqName; import org.jetbrains.jet.lang.resolve.name.FqName;
import org.jetbrains.jet.lang.resolve.scopes.*; import org.jetbrains.jet.lang.resolve.scopes.*;
import java.util.Map;
import java.util.WeakHashMap;
/** /**
* @author abreslav * @author abreslav
*/ */
@@ -37,56 +40,66 @@ public class ScopeProvider {
this.resolveSession = resolveSession; this.resolveSession = resolveSession;
} }
private final Map<JetFile, JetScope> fileScopeCache = new WeakHashMap<JetFile, JetScope>();
// This scope does not contain imported functions // This scope does not contain imported functions
@NotNull @NotNull
public JetScope getFileScopeForDeclarationResolution(JetFile file) { public JetScope getFileScopeForDeclarationResolution(JetFile file) {
// package if (!fileScopeCache.containsKey(file)) {
JetNamespaceHeader header = file.getNamespaceHeader(); // package
if (header == null) { JetNamespaceHeader header = file.getNamespaceHeader();
throw new IllegalArgumentException("Scripts are not supported: " + file.getName()); if (header == null) {
throw new IllegalArgumentException("Scripts are not supported: " + file.getName());
}
FqName fqName = new FqName(header.getQualifiedName());
NamespaceDescriptor packageDescriptor = resolveSession.getPackageDescriptorByFqName(fqName);
if (packageDescriptor == null) {
throw new IllegalStateException("Package not found: " + fqName + " maybe the file is not in scope of this resolve session: " + file.getName());
}
WritableScope fileScope = new WritableScopeImpl(
JetScope.EMPTY, packageDescriptor, RedeclarationHandler.DO_NOTHING, "File scope for declaration resolution");
fileScope.changeLockLevel(WritableScope.LockLevel.BOTH);
NamespaceDescriptor rootPackageDescriptor = resolveSession.getPackageDescriptorByFqName(FqName.ROOT);
if (rootPackageDescriptor == null) {
throw new IllegalStateException("Root package not found");
}
// Don't import twice
if (!packageDescriptor.getQualifiedName().equals(FqName.ROOT)) {
fileScope.importScope(rootPackageDescriptor.getMemberScope());
}
ImportsResolver.processImportsInFile(true, fileScope, Lists.newArrayList(file.getImportDirectives()),
rootPackageDescriptor.getMemberScope(),
resolveSession.getModuleConfiguration(), resolveSession.getTrace(),
resolveSession.getInjector().getQualifiedExpressionResolver());
fileScope.changeLockLevel(WritableScope.LockLevel.READING);
fileScopeCache.put(file, new ChainedScope(packageDescriptor, packageDescriptor.getMemberScope(), fileScope));
} }
FqName fqName = new FqName(header.getQualifiedName()); return fileScopeCache.get(file);
NamespaceDescriptor packageDescriptor = resolveSession.getPackageDescriptorByFqName(fqName);
if (packageDescriptor == null) {
throw new IllegalStateException("Package not found: " + fqName + " maybe the file is not in scope of this resolve session: " + file.getName());
}
WritableScope fileScope = new WritableScopeImpl(
JetScope.EMPTY, packageDescriptor, RedeclarationHandler.DO_NOTHING, "File scope for declaration resolution");
fileScope.changeLockLevel(WritableScope.LockLevel.BOTH);
NamespaceDescriptor rootPackageDescriptor = resolveSession.getPackageDescriptorByFqName(FqName.ROOT);
if (rootPackageDescriptor == null) {
throw new IllegalStateException("Root package not found");
}
// Don't import twice
if (!packageDescriptor.getQualifiedName().equals(FqName.ROOT)) {
fileScope.importScope(rootPackageDescriptor.getMemberScope());
}
ImportsResolver.processImportsInFile(true, fileScope, Lists.newArrayList(file.getImportDirectives()),
rootPackageDescriptor.getMemberScope(),
resolveSession.getModuleConfiguration(), resolveSession.getTrace(),
resolveSession.getInjector().getQualifiedExpressionResolver());
fileScope.changeLockLevel(WritableScope.LockLevel.READING);
// TODO: Cache
return new ChainedScope(packageDescriptor, packageDescriptor.getMemberScope(), fileScope);
} }
@NotNull @NotNull
public JetScope getResolutionScopeForDeclaration(@NotNull JetDeclaration jetDeclaration) { public JetScope getResolutionScopeForDeclaration(@NotNull PsiElement elementOfDeclaration) {
PsiElement immediateParent = jetDeclaration.getParent(); JetDeclaration jetDeclaration = PsiTreeUtil.getParentOfType(elementOfDeclaration, JetDeclaration.class, false);
if (immediateParent instanceof JetFile) {
return getFileScopeForDeclarationResolution((JetFile) immediateParent); assert !(elementOfDeclaration instanceof JetDeclaration) || jetDeclaration == elementOfDeclaration :
} "For JetDeclaration element getParentOfType() should return itself.";
JetDeclaration parentDeclaration = PsiTreeUtil.getParentOfType(jetDeclaration, JetDeclaration.class); JetDeclaration parentDeclaration = PsiTreeUtil.getParentOfType(jetDeclaration, JetDeclaration.class);
if (parentDeclaration == null) {
return getFileScopeForDeclarationResolution((JetFile) elementOfDeclaration.getContainingFile());
}
assert jetDeclaration != null : "Can't happen because of getParentOfType(null, ?) == null";
if (parentDeclaration instanceof JetClassOrObject) { if (parentDeclaration instanceof JetClassOrObject) {
JetClassOrObject classOrObject = (JetClassOrObject) parentDeclaration; JetClassOrObject classOrObject = (JetClassOrObject) parentDeclaration;
LazyClassDescriptor classDescriptor = (LazyClassDescriptor) resolveSession.getClassDescriptor(classOrObject); LazyClassDescriptor classDescriptor = (LazyClassDescriptor) resolveSession.getClassDescriptor(classOrObject);
@@ -98,13 +111,18 @@ public class ScopeProvider {
} }
return classDescriptor.getScopeForMemberDeclarationResolution(); return classDescriptor.getScopeForMemberDeclarationResolution();
} }
else if (parentDeclaration instanceof JetClassObject) {
if (parentDeclaration instanceof JetClassObject) {
assert jetDeclaration instanceof JetObjectDeclaration : "Should be situation for getting scope for object in class [object {...}]";
JetClassObject classObject = (JetClassObject) parentDeclaration; JetClassObject classObject = (JetClassObject) parentDeclaration;
LazyClassDescriptor classObjectDescriptor = resolveSession.getClassObjectDescriptor(classObject); LazyClassDescriptor classObjectDescriptor =
return classObjectDescriptor.getScopeForMemberDeclarationResolution(); (LazyClassDescriptor) resolveSession.getClassObjectDescriptor(classObject).getContainingDeclaration();
}
else { // During class object header resolve there should be no resolution for parent class generic params
throw new IllegalStateException("Don't call this method for local declarations: " + jetDeclaration + " " + jetDeclaration.getText()); return new InnerClassesScopeWrapper(classObjectDescriptor.getScopeForMemberDeclarationResolution());
} }
throw new IllegalStateException("Don't call this method for local declarations: " + jetDeclaration + " " + jetDeclaration.getText());
} }
} }
@@ -356,6 +356,14 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor {
@Override @Override
public JetTypeInfo visitTupleExpression(JetTupleExpression expression, ExpressionTypingContext context) { public JetTypeInfo visitTupleExpression(JetTupleExpression expression, ExpressionTypingContext context) {
// TODO: remove this method completely when tuples are droppped
if (expression.getEntries().size() <= 3) {
context.trace.report(TUPLES_ARE_NOT_SUPPORTED.on(expression));
}
else {
context.trace.report(TUPLES_ARE_NOT_SUPPORTED_BIG.on(expression));
}
List<JetExpression> entries = expression.getEntries(); List<JetExpression> entries = expression.getEntries();
List<JetType> types = new ArrayList<JetType>(); List<JetType> types = new ArrayList<JetType>();
for (JetExpression entry : entries) { for (JetExpression entry : entries) {
@@ -882,7 +890,7 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor {
return typeInfo; return typeInfo;
} }
DataFlowInfo dataFlowInfo = typeInfo.getDataFlowInfo(); DataFlowInfo dataFlowInfo = typeInfo.getDataFlowInfo();
if (isKnownToBeNotNull(baseExpression, context)) { if (isKnownToBeNotNull(baseExpression, context) && !ErrorUtils.isErrorType(type)) {
context.trace.report(UNNECESSARY_NOT_NULL_ASSERTION.on(operationSign, type)); context.trace.report(UNNECESSARY_NOT_NULL_ASSERTION.on(operationSign, type));
} }
else { else {
@@ -966,7 +974,7 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor {
} }
else if (OperatorConventions.COMPARISON_OPERATIONS.contains(operationType)) { else if (OperatorConventions.COMPARISON_OPERATIONS.contains(operationType)) {
JetType compareToReturnType = getTypeForBinaryCall(context.scope, Name.identifier("compareTo"), context, expression); JetType compareToReturnType = getTypeForBinaryCall(context.scope, Name.identifier("compareTo"), context, expression);
if (compareToReturnType != null) { if (compareToReturnType != null && !ErrorUtils.isErrorType(compareToReturnType)) {
TypeConstructor constructor = compareToReturnType.getConstructor(); TypeConstructor constructor = compareToReturnType.getConstructor();
JetStandardLibrary standardLibrary = JetStandardLibrary.getInstance(); JetStandardLibrary standardLibrary = JetStandardLibrary.getInstance();
TypeConstructor intTypeConstructor = standardLibrary.getInt().getTypeConstructor(); TypeConstructor intTypeConstructor = standardLibrary.getInt().getTypeConstructor();
@@ -22,6 +22,7 @@ import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.descriptors.*; import org.jetbrains.jet.lang.descriptors.*;
import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor; import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor;
import org.jetbrains.jet.lang.resolve.DescriptorResolver;
import org.jetbrains.jet.lang.resolve.DescriptorUtils; import org.jetbrains.jet.lang.resolve.DescriptorUtils;
import org.jetbrains.jet.lang.resolve.name.FqName; import org.jetbrains.jet.lang.resolve.name.FqName;
import org.jetbrains.jet.lang.resolve.name.FqNameUnsafe; import org.jetbrains.jet.lang.resolve.name.FqNameUnsafe;
@@ -91,7 +92,6 @@ public class JetStandardClasses {
}, },
JetScope.EMPTY, JetScope.EMPTY,
Collections.<ConstructorDescriptor>singleton(constructorDescriptor), Collections.<ConstructorDescriptor>singleton(constructorDescriptor),
null,
null null
); );
NOTHING_TYPE = new JetTypeImpl(getNothing()); NOTHING_TYPE = new JetTypeImpl(getNothing());
@@ -125,7 +125,6 @@ public class JetStandardClasses {
Collections.<JetType>emptySet(), Collections.<JetType>emptySet(),
JetScope.EMPTY, JetScope.EMPTY,
Collections.<ConstructorDescriptor>singleton(constructorDescriptor), Collections.<ConstructorDescriptor>singleton(constructorDescriptor),
null,
null null
); );
ANY_TYPE = new JetTypeImpl(ANY.getTypeConstructor(), new JetScopeImpl() { ANY_TYPE = new JetTypeImpl(ANY.getTypeConstructor(), new JetScopeImpl() {
@@ -201,14 +200,84 @@ public class JetStandardClasses {
writableScope, writableScope,
Collections.<ConstructorDescriptor>singleton(constructorDescriptor), Collections.<ConstructorDescriptor>singleton(constructorDescriptor),
null); null);
if (i == 0) {
// Unit.VALUE
classDescriptor.setClassObjectDescriptor(createClassObjectForUnit(classDescriptor));
}
TUPLE_CONSTRUCTORS.add(TUPLE[i].getTypeConstructor()); TUPLE_CONSTRUCTORS.add(TUPLE[i].getTypeConstructor());
constructorDescriptor.initialize(classDescriptor.getTypeConstructor().getParameters(), constructorValueParameters, Visibilities.PUBLIC); constructorDescriptor.initialize(classDescriptor.getTypeConstructor().getParameters(), constructorValueParameters, i == 0 ? Visibilities.PRIVATE : Visibilities.PUBLIC);
constructorDescriptor.setReturnType(classDescriptor.getDefaultType()); constructorDescriptor.setReturnType(classDescriptor.getDefaultType());
} }
} }
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// @NotNull
private static ClassDescriptor createClassObjectForUnit(@NotNull ClassDescriptorImpl unitClass) {
ClassDescriptorImpl classObjectDescriptor = new ClassDescriptorImpl(
unitClass,
ClassKind.CLASS_OBJECT,
Collections.<AnnotationDescriptor>emptyList(),
Modality.FINAL,
DescriptorUtils.getClassObjectName(unitClass.getName())
);
WritableScopeImpl classObjectMemberScope = new WritableScopeImpl(
JetScope.EMPTY,
classObjectDescriptor,
RedeclarationHandler.DO_NOTHING,
"Unit class object members"
);
PropertyDescriptor valueProperty = createUnitValueProperty(unitClass, classObjectDescriptor);
classObjectMemberScope.addPropertyDescriptor(valueProperty);
classObjectMemberScope.changeLockLevel(WritableScope.LockLevel.READING);
ConstructorDescriptorImpl classObjectConstructorDescriptor = new ConstructorDescriptorImpl(classObjectDescriptor, Collections.<AnnotationDescriptor>emptyList(), true);
classObjectConstructorDescriptor.initialize(
Collections.<TypeParameterDescriptor>emptyList(),
Collections.<ValueParameterDescriptor>emptyList(),
Visibilities.PRIVATE
);
classObjectDescriptor.initialize(
/*sealed = */ true,
Collections.<TypeParameterDescriptor>emptyList(),
Collections.singleton(getAnyType()),
classObjectMemberScope,
Collections.<ConstructorDescriptor>singleton(classObjectConstructorDescriptor),
classObjectConstructorDescriptor
);
classObjectConstructorDescriptor.setReturnType(classObjectDescriptor.getDefaultType());
return classObjectDescriptor;
}
@NotNull
private static PropertyDescriptor createUnitValueProperty(
@NotNull ClassDescriptorImpl unitClass,
@NotNull ClassDescriptorImpl unitClassObject
) {
PropertyDescriptor valueProperty = new PropertyDescriptor(
unitClassObject,
Collections.<AnnotationDescriptor>emptyList(),
Modality.FINAL,
Visibilities.PUBLIC,
/*isVar = */ false,
Name.identifier("VALUE"),
CallableMemberDescriptor.Kind.DECLARATION);
valueProperty.setType(
unitClass.getDefaultType(),
Collections.<TypeParameterDescriptor>emptyList(),
unitClassObject.getImplicitReceiver(),
ReceiverDescriptor.NO_RECEIVER);
PropertyGetterDescriptor getter = DescriptorResolver.createDefaultGetter(valueProperty);
getter.initialize(unitClass.getDefaultType());
valueProperty.initialize(getter, null);
return valueProperty;
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
public static final int MAX_FUNCTION_ORDER = 22; public static final int MAX_FUNCTION_ORDER = 22;
@@ -16,6 +16,10 @@
package org.jetbrains.jet.util.slicedmap; package org.jetbrains.jet.util.slicedmap;
import com.google.common.collect.ImmutableMap;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.TestOnly;
/** /**
* @author abreslav * @author abreslav
*/ */
@@ -26,4 +30,8 @@ public interface MutableSlicedMap extends SlicedMap {
<K, V> V remove(RemovableSlice<K, V> slice, K key); <K, V> V remove(RemovableSlice<K, V> slice, K key);
void clear(); void clear();
@NotNull
@TestOnly
<K, V> ImmutableMap<K, V> getSliceContents(@NotNull ReadOnlySlice<K, V> slice);
} }
@@ -16,9 +16,11 @@
package org.jetbrains.jet.util.slicedmap; package org.jetbrains.jet.util.slicedmap;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Maps; import com.google.common.collect.Maps;
import com.google.common.collect.Multimap; import com.google.common.collect.Multimap;
import com.google.common.collect.Multimaps; import com.google.common.collect.Multimaps;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.util.CommonSuppliers; import org.jetbrains.jet.util.CommonSuppliers;
import java.util.Collection; import java.util.Collection;
@@ -106,4 +108,16 @@ public class SlicedMapImpl implements MutableSlicedMap {
//noinspection unchecked //noinspection unchecked
return (Iterator) map.entrySet().iterator(); return (Iterator) map.entrySet().iterator();
} }
@NotNull
@Override
public <K, V> ImmutableMap<K, V> getSliceContents(@NotNull ReadOnlySlice<K, V> slice) {
ImmutableMap.Builder<K, V> builder = ImmutableMap.builder();
for (Map.Entry<SlicedMapKey<?, ?>, ?> entry : map.entrySet()) {
if (entry.getKey().getSlice() == slice) {
builder.put((K) entry.getKey().getKey(), (V) entry.getValue());
}
}
return builder.build();
}
} }
@@ -29,7 +29,6 @@ import com.intellij.psi.search.GlobalSearchScope;
import com.intellij.util.SmartList; import com.intellij.util.SmartList;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.codegen.CodegenUtil;
import org.jetbrains.jet.codegen.NamespaceCodegen; import org.jetbrains.jet.codegen.NamespaceCodegen;
import org.jetbrains.jet.lang.psi.*; import org.jetbrains.jet.lang.psi.*;
import org.jetbrains.jet.lang.resolve.java.JavaPsiFacadeKotlinHacks; import org.jetbrains.jet.lang.resolve.java.JavaPsiFacadeKotlinHacks;
@@ -41,6 +40,8 @@ import org.jetbrains.jet.util.QualifiedNamesUtil;
import java.util.*; import java.util.*;
import static org.jetbrains.jet.codegen.CodegenUtil.getLocalNameForObject;
public class JavaElementFinder extends PsiElementFinder implements JavaPsiFacadeKotlinHacks.KotlinFinderMarker { public class JavaElementFinder extends PsiElementFinder implements JavaPsiFacadeKotlinHacks.KotlinFinderMarker {
private final Project project; private final Project project;
private final PsiManager psiManager; private final PsiManager psiManager;
@@ -166,7 +167,7 @@ public class JavaElementFinder extends PsiElementFinder implements JavaPsiFacade
if (given != null) return given; if (given != null) return given;
if (declaration instanceof JetObjectDeclaration) { if (declaration instanceof JetObjectDeclaration) {
return CodegenUtil.getLocalNameForObject((JetObjectDeclaration) declaration); return getLocalNameForObject((JetObjectDeclaration) declaration);
} }
return null; return null;
@@ -266,7 +266,7 @@ public class JetLightClass extends AbstractLightClass implements JetJavaMirrorMa
public static PsiMethod wrapMethod(@NotNull JetNamedFunction function) { public static PsiMethod wrapMethod(@NotNull JetNamedFunction function) {
//noinspection unchecked //noinspection unchecked
if (PsiTreeUtil.getParentOfType(function, JetFunction.class, JetProperty.class) != null) { if (PsiTreeUtil.getParentOfType(function, JetFunction.class, JetProperty.class) != null) {
// Don't generate method wrappers for internal declarations. Their classes are not generated during calcStub // Don't genClassOrObject method wrappers for internal declarations. Their classes are not generated during calcStub
// with ClassBuilderMode.SIGNATURES mode, and this produces "Class not found exception" in getDelegate() // with ClassBuilderMode.SIGNATURES mode, and this produces "Class not found exception" in getDelegate()
return null; return null;
} }
+6 -3
View File
@@ -864,7 +864,7 @@ public final class jet.LongRange : jet.Range<jet.Long>, jet.LongIterable {
public final val EMPTY: jet.LongRange public final val EMPTY: jet.LongRange
} }
} }
public abstract trait jet.Map</*0*/ K : jet.Any?, /*1*/ V : jet.Any?> : jet.Any { public abstract trait jet.Map</*0*/ K : jet.Any?, /*1*/ out V : jet.Any?> : jet.Any {
public abstract fun containsKey(/*0*/ key: jet.Any?): jet.Boolean public abstract fun containsKey(/*0*/ key: jet.Any?): jet.Boolean
public abstract fun containsValue(/*0*/ value: jet.Any?): jet.Boolean public abstract fun containsValue(/*0*/ value: jet.Any?): jet.Boolean
public abstract fun entrySet(): jet.Set<jet.Map.Entry<K, V>> public abstract fun entrySet(): jet.Set<jet.Map.Entry<K, V>>
@@ -1123,7 +1123,11 @@ public open class jet.Throwable : jet.Any {
public final fun printStackTrace(): jet.Tuple0 public final fun printStackTrace(): jet.Tuple0
} }
public final class jet.Tuple0 : jet.Any { public final class jet.Tuple0 : jet.Any {
public final /*constructor*/ fun <init>(): jet.Tuple0 private final /*constructor*/ fun <init>(): jet.Tuple0
public final class object jet.Tuple0.<class-object-for-Tuple0> : jet.Any {
private final /*constructor*/ fun <init>(): jet.Tuple0.<class-object-for-Tuple0>
public final val VALUE: jet.Tuple0
}
} }
public final class jet.Tuple1</*0*/ out T1 : jet.Any?> : jet.Any { public final class jet.Tuple1</*0*/ out T1 : jet.Any?> : jet.Any {
public final /*constructor*/ fun </*0*/ out T1 : jet.Any?><init>(/*0*/ _1: T1): jet.Tuple1<T1> public final /*constructor*/ fun </*0*/ out T1 : jet.Any?><init>(/*0*/ _1: T1): jet.Tuple1<T1>
@@ -1466,6 +1470,5 @@ public final fun </*0*/ T : jet.Any?>jet.Iterator<T>.iterator(): jet.Iterator<T>
public final fun jet.LongIterator.iterator(): jet.LongIterator public final fun jet.LongIterator.iterator(): jet.LongIterator
public final fun jet.ShortIterator.iterator(): jet.ShortIterator public final fun jet.ShortIterator.iterator(): jet.ShortIterator
public final fun jet.String?.plus(/*0*/ other: jet.Any?): jet.String public final fun jet.String?.plus(/*0*/ other: jet.Any?): jet.String
public final fun </*0*/ T : jet.Any>T?.sure(): T
public final fun </*0*/ R : jet.Any?>synchronized(/*0*/ lock: jet.Any, /*1*/ block: jet.Function0<R>): R public final fun </*0*/ R : jet.Any?>synchronized(/*0*/ lock: jet.Any, /*1*/ block: jet.Function0<R>): R
public final fun jet.Any?.toString(): jet.String public final fun jet.Any?.toString(): jet.String
@@ -1,7 +1,7 @@
import java.lang.Runtime import java.lang.Runtime
fun box() : String { fun box() : String {
val processors = Runtime.getRuntime().sure().availableProcessors() val processors = Runtime.getRuntime()!!.availableProcessors()
var threadNum = 1 var threadNum = 1
while(threadNum <= 1024) { while(threadNum <= 1024) {
System.out?.println(threadNum) System.out?.println(threadNum)
@@ -0,0 +1,6 @@
data class A(val v: Array<Int>)
fun box() : String {
if(A(array(0,1,2)) != A(array(0,1,2))) return "fail"
return "OK"
}
@@ -0,0 +1,13 @@
class Dummy {
fun equals(other: Any?) = true
}
open data class A(val v: Any)
class B(v: Any) : A(v)
fun box() : String {
val a = A(Dummy())
val b = B(Dummy())
return if(b == a) "OK" else "fail"
}
@@ -0,0 +1,6 @@
data class A(val v: IntArray)
fun box() : String {
if(A(intArray(0,1,2)) != A(intArray(0,1,2))) return "fail"
return "OK"
}
@@ -0,0 +1,11 @@
class Dummy {
fun equals(other: Any?) = true
}
data class A(val v: Any?)
fun box() : String {
val a = A(Dummy())
val b: A? = null
return if(a != b && b != a) "OK" else "fail"
}
@@ -0,0 +1,7 @@
data class A()
fun box() : String {
val a = A()
val b = a
return if(b == a) "OK" else "fail"
}
@@ -0,0 +1,6 @@
data class A(val a: IntArray, var b: Array<String>)
fun box() : String {
if( A(intArray(1,2,3),array("239")).hashCode() != 31*java.util.Arrays.hashCode(intArray(0,1,2)) + "239".hashCode()) "fail"
return "OK"
}
@@ -0,0 +1,5 @@
data class A(val a: Boolean)
fun box() : String {
return if( A(true).hashCode()==1 && A(false).hashCode()==0 ) "OK" else "fail"
}
@@ -0,0 +1,7 @@
data class A(val a: Byte)
fun box() : String {
val v1 = A(-10.toByte()).hashCode()
val v2 = (-10.toByte() as Byte?)!!.hashCode()
return if( v1 == v2 ) "OK" else "$v1 $v2"
}
@@ -0,0 +1,7 @@
data class A(val a: Char)
fun box() : String {
val v1 = A('a').hashCode()
val v2 = ('a' as Char?)!!.hashCode()
return if( v1 == v2 ) "OK" else "$v1 $v2"
}
@@ -0,0 +1,7 @@
data class A(val a: Double)
fun box() : String {
val v1 = A(-10.toDouble()).hashCode()
val v2 = (-10.toDouble() as Double?)!!.hashCode()
return if( v1 == v2 ) "OK" else "$v1 $v2"
}
@@ -0,0 +1,7 @@
data class A(val a: Float)
fun box() : String {
val v1 = A(-10.toFloat()).hashCode()
val v2 = (-10.toFloat() as Float?)!!.hashCode()
return if( v1 == v2 ) "OK" else "$v1 $v2"
}
@@ -0,0 +1,7 @@
data class A(val a: Int)
fun box() : String {
val v1 = A(-10.toInt()).hashCode()
val v2 = (-10.toInt() as Int?)!!.hashCode()
return if( v1 == v2 ) "OK" else "$v1 $v2"
}
@@ -0,0 +1,7 @@
data class A(val a: Long)
fun box() : String {
val v1 = A(-10.toLong()).hashCode()
val v2 = (-10.toLong() as Long?)!!.hashCode()
return if( v1 == v2 ) "OK" else "$v1 $v2"
}
@@ -0,0 +1,16 @@
data class A(val a: Any?, var x: Int)
data class B(val a: Any?, x: Int)
data class C(val a: Int, var x: Int?)
data class D(val a: Int?)
fun box() : String {
if( A(null,19).hashCode() != 19) "fail"
if( A(239,19).hashCode() != (239*31+19)) "fail"
if( B(null,19).hashCode() != 0) "fail"
if( B(239,19).hashCode() != 239) "fail"
if( C(239,19).hashCode() != (239*31+19)) "fail"
if( C(239,null).hashCode() != 239*31) "fail"
if( D(239).hashCode() != (239)) "fail"
if( D(null).hashCode() != 0) "fail"
return "OK"
}
@@ -0,0 +1,7 @@
data class A(val a: Short)
fun box() : String {
val v1 = A(-10.toShort()).hashCode()
val v2 = (-10.toShort() as Short?)!!.hashCode()
return if( v1 == v2 ) "OK" else "$v1 $v2"
}

Some files were not shown because too many files have changed in this diff Show More