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("kt344.jet"); // Bug KT-2251
excludedFiles.add("kt529.kt"); // Bug
excludedFiles.add("noClassObjectForJavaClass.kt");
}
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.receivers.ExpressionReceiver;
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.NamespaceType;
import org.jetbrains.jet.lang.types.expressions.ExpressionTypingUtils;
@@ -61,7 +62,7 @@ public final class TipsManager {
JetScope resolutionScope = context.get(BindingContext.RESOLUTION_SCOPE, expression);
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)) {
ExpressionReceiver receiverDescriptor = new ExpressionReceiver(receiverExpression, expressionType);
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.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.PropertyDescriptor;
import org.jetbrains.jet.lang.psi.*;
@@ -34,14 +33,14 @@ import java.util.Collections;
import java.util.List;
import static org.jetbrains.asm4.Opcodes.*;
import static org.jetbrains.jet.codegen.CodegenUtil.generateMethodThrow;
import static org.jetbrains.jet.codegen.CodegenUtil.getVisibilityAccessFlag;
import static org.jetbrains.jet.codegen.AsmUtil.genMethodThrow;
import static org.jetbrains.jet.codegen.AsmUtil.getVisibilityAccessFlag;
/**
* @author max
* @author yole
*/
public abstract class ClassBodyCodegen extends GenerationStateAware {
public abstract class ClassBodyCodegen extends MemberCodegen {
protected final JetClassOrObject myClass;
protected final OwnerKind kind;
protected final ClassDescriptor descriptor;
@@ -89,7 +88,7 @@ public abstract class ClassBodyCodegen extends GenerationStateAware {
protected void generateDeclaration(PropertyCodegen propertyCodegen, JetDeclaration declaration, FunctionCodegen functionCodegen) {
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
if (DescriptorUtils.isIteratorWithoutRemoveImpl(descriptor)) {
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 java.util.*;
import static org.jetbrains.jet.codegen.AsmUtil.isPrimitive;
/**
* @author max
* @author alex.tkachman
@@ -114,7 +116,7 @@ public final class ClassFileFactory extends GenerationStateAware {
public ClassBuilder forClassImplementation(ClassDescriptor aClass) {
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);
}
return newVisitor(type.getInternalName() + ".class");
@@ -49,6 +49,7 @@ import java.util.ArrayList;
import java.util.List;
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.binding.CodegenBinding.classNameForAnonymousClass;
import static org.jetbrains.jet.codegen.binding.CodegenBinding.isLocalNamedFun;
@@ -108,7 +109,7 @@ public class ClosureCodegen extends GenerationStateAware {
generateConstInstance(fun, cv);
}
generateClosureFields(closure, cv, state.getTypeMapper());
genClosureFields(closure, cv, state.getTypeMapper());
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);
if (state.getClassBuilderMode() == ClassBuilderMode.STUBS) {
StubCodegen.generateStubCode(mv);
genStubCode(mv);
}
else if (state.getClassBuilderMode() == ClassBuilderMode.FULL) {
mv.visitCode();
initSingletonField(fun, name.getAsmType(), cv, iv);
genInitSingletonField(name.getAsmType(), iv);
mv.visitInsn(RETURN);
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,
new String[0]);
if (state.getClassBuilderMode() == ClassBuilderMode.STUBS) {
StubCodegen.generateStubCode(mv);
genStubCode(mv);
}
if (state.getClassBuilderMode() == ClassBuilderMode.FULL) {
mv.visitCode();
@@ -212,7 +213,7 @@ public class ClosureCodegen extends GenerationStateAware {
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]);
if (state.getClassBuilderMode() == ClassBuilderMode.STUBS) {
StubCodegen.generateStubCode(mv);
genStubCode(mv);
}
else if (state.getClassBuilderMode() == ClassBuilderMode.FULL) {
mv.visitCode();
@@ -16,70 +16,36 @@
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.util.containers.Stack;
import org.jetbrains.annotations.NotNull;
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.signature.BothSignatureWriter;
import org.jetbrains.jet.codegen.signature.JvmMethodParameterKind;
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.annotations.AnnotationDescriptor;
import org.jetbrains.jet.lang.psi.JetClassObject;
import org.jetbrains.jet.lang.psi.JetClassOrObject;
import org.jetbrains.jet.lang.psi.JetObjectDeclaration;
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.types.JetType;
import org.jetbrains.jet.lang.types.lang.JetStandardClasses;
import org.jetbrains.jet.lang.types.lang.JetStandardLibrary;
import java.util.*;
import static org.jetbrains.asm4.Opcodes.*;
import static org.jetbrains.jet.lang.resolve.DescriptorUtils.isClassObject;
import static org.jetbrains.jet.lang.resolve.java.AsmTypeConstants.*;
import static org.jetbrains.jet.lang.resolve.java.AsmTypeConstants.OBJECT_TYPE;
/**
* @author abreslav
* @author alex.tkachman
*/
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() {
}
@@ -124,7 +90,7 @@ public class CodegenUtil {
}
public static String generateTmpVariableName(Collection<String> existingNames) {
public static String createTmpVariableName(Collection<String> existingNames) {
String prefix = "tmp";
int i = RANDOM.nextInt(Integer.MAX_VALUE);
String name = prefix + i;
@@ -136,9 +102,8 @@ public class CodegenUtil {
}
public static
@NotNull
BitSet getFlagsForVisibility(@NotNull Visibility visibility) {
public static BitSet getFlagsForVisibility(@NotNull Visibility visibility) {
BitSet flags = new BitSet();
if (visibility == Visibilities.INTERNAL) {
flags.set(JvmStdlibNames.FLAG_INTERNAL_BIT);
@@ -149,22 +114,6 @@ public class CodegenUtil {
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
public static JvmClassName getInternalClassName(FunctionDescriptor descriptor) {
final int paramCount = descriptor.getValueParameters().size();
@@ -210,123 +159,10 @@ public class CodegenUtil {
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) {
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
public static String getLocalNameForObject(JetObjectDeclaration object) {
PsiElement parent = object.getParent();
@@ -363,34 +199,4 @@ public class CodegenUtil {
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 {
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);
this.element = element;
}
@@ -61,6 +61,7 @@ import org.jetbrains.jet.lexer.JetTokens;
import java.util.*;
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.binding.CodegenBinding.*;
import static org.jetbrains.jet.lang.resolve.BindingContext.*;
@@ -116,9 +117,16 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> implem
//noinspection SuspiciousMethodCalls
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;
}
@@ -991,7 +999,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> implem
return StackValue.constant(constantValue.toString(), type);
}
else {
generateStringBuilderConstructor(v);
genStringBuilderConstructor(v);
for (JetStringTemplateEntry entry : entries) {
if (entry instanceof JetStringTemplateEntryWithExpression) {
invokeAppend(entry.getExpression());
@@ -1001,7 +1009,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> implem
? ((JetEscapeStringTemplateEntry) entry).getUnescapedValue()
: entry.getText();
v.aconst(text);
invokeAppendMethod(v, JAVA_STRING_TYPE);
genInvokeAppendMethod(v, JAVA_STRING_TYPE);
}
}
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 overridesTrait = isOverrideForTrait(propertyDescriptor);
boolean isFakeOverride = propertyDescriptor.getKind() == CallableMemberDescriptor.Kind.FAKE_OVERRIDE;
boolean isDelegate = propertyDescriptor.getKind() == CallableMemberDescriptor.Kind.DELEGATION;
PropertyDescriptor initialDescriptor = propertyDescriptor;
propertyDescriptor = initialDescriptor.getOriginal();
boolean isInsideClass = !isFakeOverride &&
!isDelegate &&
(((containingDeclaration == null && !context.hasThisDescriptor() ||
context.hasThisDescriptor() && containingDeclaration == context.getThisDescriptor()) ||
(context.getParentContext() instanceof NamespaceContext) &&
@@ -1660,9 +1670,9 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> implem
PropertySetterDescriptor setter = propertyDescriptor.getSetter();
PropertyGetterDescriptor getter = propertyDescriptor.getGetter();
final int flag = CodegenUtil.getVisibilityAccessFlag(propertyDescriptor) |
(getter == null ? 0 : CodegenUtil.getVisibilityAccessFlag(getter)) |
(setter == null ? 0 : CodegenUtil.getVisibilityAccessFlag(setter));
final int flag = getVisibilityAccessFlag(propertyDescriptor) |
(getter == null ? 0 : getVisibilityAccessFlag(getter)) |
(setter == null ? 0 : getVisibilityAccessFlag(setter));
if ((flag & ACC_PRIVATE) == 0) {
return propertyDescriptor;
@@ -1672,7 +1682,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> implem
}
private FunctionDescriptor accessableFunctionDescriptor(FunctionDescriptor fd) {
final int flag = CodegenUtil.getVisibilityAccessFlag(fd);
final int flag = getVisibilityAccessFlag(fd);
if ((flag & ACC_PRIVATE) == 0) {
return fd;
}
@@ -2256,7 +2266,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> implem
else {
invokeFunctionByReference(expression.getOperationReference());
if (inverted) {
invertBoolean();
genInvertBoolean(v);
}
}
return StackValue.onStack(Type.BOOLEAN_TYPE);
@@ -2297,7 +2307,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> implem
v.and(Type.INT_TYPE);
if (inverted) {
invertBoolean();
genInvertBoolean(v);
}
}
@@ -2357,10 +2367,11 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> implem
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) {
@@ -2379,81 +2390,6 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> implem
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) {
final Type exprType = expressionType(expression);
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) {
gen(left, operandType);
gen(right, operandType);
return compareExpressionsOnStack(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);
return compareExpressionsOnStack(v, opToken, operandType);
}
private StackValue generateAssignmentExpression(JetBinaryExpression expression) {
@@ -2593,7 +2520,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> implem
}
Type exprType = expressionType(expr);
gen(expr, exprType);
invokeAppendMethod(v, exprType.getSort() == Type.ARRAY ? OBJECT_TYPE : exprType);
genInvokeAppendMethod(v, exprType.getSort() == Type.ARRAY ? OBJECT_TYPE : exprType);
}
@Nullable
@@ -2767,22 +2694,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> implem
StackValue value = genQualified(receiver, operand);
value.dupReceiver(v);
value.put(asmType, v);
if (asmType == Type.LONG_TYPE) {
//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);
asmType = genIncrement(asmType, increment, 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;
JetType condJetType = bindingContext.get(BindingContext.EXPRESSION_TYPE, patternExpression);
Type condType;
if (CodegenUtil.isNumberPrimitive(subjectType) || subjectType.getSort() == Type.BOOLEAN) {
if (isNumberPrimitive(subjectType) || subjectType.getSort() == Type.BOOLEAN) {
assert condJetType != null;
condType = asmType(condJetType);
if (!(CodegenUtil.isNumberPrimitive(condType) || condType.getSort() == Type.BOOLEAN)) {
if (!(isNumberPrimitive(condType) || condType.getSort() == Type.BOOLEAN)) {
subjectType = boxType(subjectType);
expressionToMatch.coerce(subjectType, v);
expressionToMatch.coerceTo(subjectType, v);
}
}
else {
@@ -3294,8 +3206,8 @@ The "returned" value of try expression with no finally is either the last expres
patternIsNullable = condJetType != null && condJetType.isNullable();
}
gen(patternExpression, condType);
return generateEqualsForExpressionsOnStack(JetTokens.EQEQ, subjectType, condType, expressionToMatchIsNullable,
patternIsNullable);
return genEqualsForExpressionsOnStack(v, JetTokens.EQEQ, subjectType, condType, expressionToMatchIsNullable,
patternIsNullable);
}
else {
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);
invokeFunctionByReference(operationReference);
if (inverted) {
invertBoolean();
genInvertBoolean(v);
}
}
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);
}
private void invertBoolean() {
v.iconst(1);
v.xor(Type.INT_TYPE);
}
private boolean isIntRangeExpr(JetExpression rangeExpression) {
if (rangeExpression instanceof JetBinaryExpression) {
JetBinaryExpression binaryExpression = (JetBinaryExpression) rangeExpression;
@@ -3464,34 +3371,6 @@ The "returned" value of try expression with no finally is either the last expres
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) {
v.anew(Type.getObjectType(className));
v.dup();
@@ -48,6 +48,7 @@ import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor;
import java.util.*;
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.binding.CodegenBinding.isLocalFun;
import static org.jetbrains.jet.lang.resolve.BindingContextUtils.callableDescriptorToDeclaration;
@@ -130,7 +131,7 @@ public class FunctionCodegen extends GenerationStateAware {
}
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);
mv.visitLocalVariable(parameterName, type.getDescriptor(), null, methodBegin, divideLabel, k);
String nameForSharedVar = generateTmpVariableName(localVariableNames);
String nameForSharedVar = createTmpVariableName(localVariableNames);
localVariableNames.add(nameForSharedVar);
mv.visitLocalVariable(nameForSharedVar, sharedVarType.getDescriptor(), null, divideLabel, methodEnd, k);
@@ -516,7 +517,7 @@ public class FunctionCodegen extends GenerationStateAware {
descriptor, null, null);
InstructionAdapter iv = new InstructionAdapter(mv);
if (state.getClassBuilderMode() == ClassBuilderMode.STUBS) {
StubCodegen.generateStubCode(mv);
genStubCode(mv);
}
else if (state.getClassBuilderMode() == ClassBuilderMode.FULL) {
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);
if (state.getClassBuilderMode() == ClassBuilderMode.STUBS) {
StubCodegen.generateStubCode(mv);
genStubCode(mv);
}
else if (state.getClassBuilderMode() == ClassBuilderMode.FULL) {
mv.visitCode();
@@ -738,7 +739,7 @@ public class FunctionCodegen extends GenerationStateAware {
final MethodVisitor mv = v.newMethod(null, flags, method.getName(), method.getDescriptor(), null, null);
if (state.getClassBuilderMode() == ClassBuilderMode.STUBS) {
StubCodegen.generateStubCode(mv);
genStubCode(mv);
}
else if (state.getClassBuilderMode() == ClassBuilderMode.FULL) {
mv.visitCode();
@@ -22,6 +22,7 @@ import com.intellij.openapi.util.Pair;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.asm4.AnnotationVisitor;
import org.jetbrains.asm4.Label;
import org.jetbrains.asm4.MethodVisitor;
import org.jetbrains.asm4.Type;
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.psi.*;
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.calls.ResolvedCall;
import org.jetbrains.jet.lang.resolve.constants.CompileTimeConstant;
@@ -56,6 +58,7 @@ import org.jetbrains.jet.utils.BitSetUtils;
import java.util.*;
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.binding.CodegenBinding.*;
import static org.jetbrains.jet.lang.resolve.BindingContextUtils.callableDescriptorToDeclaration;
@@ -164,42 +167,43 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
);
v.visitSource(myClass.getContainingFile().getName(), null);
writeInnerOuterClasses();
writeOuterClass();
writeInnerClasses();
AnnotationCodegen.forClass(v.getVisitor(), typeMapper).genAnnotations(descriptor);
writeClassSignatureIfNeeded(signature);
}
private void writeInnerOuterClasses() {
private void writeOuterClass() {
ClassDescriptor container = getContainingClassDescriptor(descriptor);
if (container != null) {
v.visitOuterClass(typeMapper.mapType(container.getDefaultType(), JetTypeMapperMode.IMPL).getInternalName(), null, null);
}
}
for (DeclarationDescriptor declarationDescriptor : descriptor.getUnsubstitutedInnerClassesScope().getAllDescriptors()) {
assert declarationDescriptor instanceof ClassDescriptor;
ClassDescriptor innerClass = (ClassDescriptor) declarationDescriptor;
// TODO: proper access
int innerClassAccess = ACC_PUBLIC;
if (innerClass.getModality() == Modality.FINAL) {
innerClassAccess |= ACC_FINAL;
}
else if (innerClass.getModality() == Modality.ABSTRACT) {
innerClassAccess |= ACC_ABSTRACT;
}
private void writeInnerClasses() {
// 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
// (to avoid publicly visible names like A$ClassObject$$B), so they are handled specially in this method
if (innerClass.getKind() == ClassKind.TRAIT) {
innerClassAccess |= ACC_INTERFACE;
for (ClassDescriptor innerClass : DescriptorUtils.getInnerClasses(descriptor)) {
// 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;
v.visitInnerClass(classAsmType.getInternalName() + JvmAbi.CLASS_OBJECT_SUFFIX, classAsmType.getInternalName(),
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) {
if (signature.getKotlinGenericSignature() != null || descriptor.getVisibility() != Visibilities.PUBLIC) {
AnnotationVisitor annotationVisitor = v.newAnnotation(JvmStdlibNames.JET_CLASS.getDescriptor(), true);
@@ -355,7 +392,20 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
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() {
@@ -363,67 +413,135 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
generateComponentFunctionsForDataClasses();
generateDataClassToStringMethod();
generateDataClassHashCodeMethod();
generateDataClassEqualsMethod();
final List<PropertyDescriptor> properties = getDataProperties();
if (!properties.isEmpty()) {
generateDataClassToStringMethod(properties);
generateDataClassHashCodeMethod(properties);
generateDataClassEqualsMethod(properties);
}
}
private void generateDataClassEqualsMethod() {
// todo: this is fake implementation
private void generateDataClassEqualsMethod(List<PropertyDescriptor> properties) {
final MethodVisitor mv = v.getVisitor().visitMethod(ACC_PUBLIC, "equals", "(Ljava/lang/Object;)Z", null, null);
mv.visitVarInsn(ALOAD, 0);
mv.visitVarInsn(ALOAD, 1);
mv.visitMethodInsn(INVOKESPECIAL, superClassAsmType.getInternalName(), "equals", "(Ljava/lang/Object;)Z");
mv.visitInsn(IRETURN);
mv.visitMaxs(-1,-1);
mv.visitEnd();
final InstructionAdapter iv = new InstructionAdapter(mv);
mv.visitCode();
Label eq = new Label();
Label ne = new Label();
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() {
// todo: this is fake implementation
private void generateDataClassHashCodeMethod(List<PropertyDescriptor> properties) {
final MethodVisitor mv = v.getVisitor().visitMethod(ACC_PUBLIC, "hashCode", "()I", null, null);
mv.visitVarInsn(ALOAD, 0);
mv.visitMethodInsn(INVOKESPECIAL, superClassAsmType.getInternalName(), "hashCode", "()I");
final InstructionAdapter iv = new InstructionAdapter(mv);
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.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 InstructionAdapter iv = new InstructionAdapter(mv);
mv.visitVarInsn(ALOAD, 0);
generateStringBuilderConstructor(iv);
mv.visitCode();
genStringBuilderConstructor(iv);
boolean first = true;
for (JetParameter parameter : getPrimaryConstructorParameters()) {
if (parameter.getValOrVarNode() == null) continue;
PropertyDescriptor propertyDescriptor = state.getBindingContext().get(BindingContext.PRIMARY_CONSTRUCTOR_PARAMETER, parameter);
assert propertyDescriptor != null;
if(first) {
iv.aconst(descriptor.getName() + "{" + propertyDescriptor.getName().getName()+"=");
for (PropertyDescriptor propertyDescriptor : properties) {
if (first) {
iv.aconst(descriptor.getName() + "(" + propertyDescriptor.getName().getName()+"=");
first = false;
}
else {
iv.aconst(", " + propertyDescriptor.getName().getName()+"=");
}
CodegenUtil.invokeAppendMethod(iv, JAVA_STRING_TYPE);
genInvokeAppendMethod(iv, JAVA_STRING_TYPE);
iv.load(0, classAsmType);
// 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());
Type type = genPropertyOnStack(iv, propertyDescriptor, 0);
if (type.getSort() == Type.ARRAY) {
final Type elementType = correctElementType(type);
@@ -438,11 +556,11 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
}
}
}
CodegenUtil.invokeAppendMethod(iv, type);
genInvokeAppendMethod(iv, type);
}
iv.aconst("}");
CodegenUtil.invokeAppendMethod(iv, JAVA_STRING_TYPE);
iv.aconst(")");
genInvokeAppendMethod(iv, JAVA_STRING_TYPE);
iv.invokevirtual("java/lang/StringBuilder", "toString", "()Ljava/lang/String;");
iv.areturn(JAVA_STRING_TYPE);
@@ -450,6 +568,15 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
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() {
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;
Type componentType = typeMapper.mapReturnType(returnType);
final String desc = "()" + componentType.getDescriptor();
MethodVisitor mv = v.newMethod(myClass,
FunctionCodegen.getMethodAsmFlags(function, OwnerKind.IMPLEMENTATION),
function.getName().getName(),
"()" + componentType.getDescriptor(),
desc,
null, null);
FunctionCodegen.genJetAnnotations(state, function, null, null, mv);
@@ -480,7 +608,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
InstructionAdapter iv = new InstructionAdapter(mv);
if (!componentType.equals(Type.VOID_TYPE)) {
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);
@@ -543,7 +671,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
MethodVisitor mv = v.newMethod(null, ACC_BRIDGE | ACC_SYNTHETIC | ACC_STATIC, bridge.getName().getName(),
method.getDescriptor(), null, null);
if (state.getClassBuilderMode() == ClassBuilderMode.STUBS) {
StubCodegen.generateStubCode(mv);
genStubCode(mv);
}
else if (state.getClassBuilderMode() == ClassBuilderMode.FULL) {
mv.visitCode();
@@ -588,7 +716,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
original,
getter.getVisibility());
if (state.getClassBuilderMode() == ClassBuilderMode.STUBS) {
StubCodegen.generateStubCode(mv);
genStubCode(mv);
}
else if (state.getClassBuilderMode() == ClassBuilderMode.FULL) {
mv.visitCode();
@@ -623,7 +751,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
original,
setter.getVisibility());
if (state.getClassBuilderMode() == ClassBuilderMode.STUBS) {
StubCodegen.generateStubCode(mv);
genStubCode(mv);
}
else if (state.getClassBuilderMode() == ClassBuilderMode.FULL) {
mv.visitCode();
@@ -665,7 +793,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
staticInitializerChunks.add(new CodeChunk() {
@Override
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);
if (state.getClassBuilderMode() == ClassBuilderMode.STUBS) {
StubCodegen.generateStubCode(mv);
genStubCode(mv);
return;
}
@@ -1108,7 +1236,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
aw.visitEnd();
if (state.getClassBuilderMode() == ClassBuilderMode.STUBS) {
StubCodegen.generateStubCode(mv);
genStubCode(mv);
}
else if (state.getClassBuilderMode() == ClassBuilderMode.FULL) {
mv.visitCode();
@@ -20,22 +20,28 @@ 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.psi.JetNamedFunction;
import org.jetbrains.jet.lang.psi.JetProperty;
import org.jetbrains.jet.lang.psi.JetTypeParameterListOwner;
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 Stepan Koltsov
* @author alex.tkachman
*/
public class MemberCodegen extends GenerationStateAware {
public MemberCodegen(@NotNull GenerationState state) {
super(state);
}
public void generateFunctionOrProperty(
public void genFunctionOrProperty(
CodegenContext context,
@NotNull JetTypeParameterListOwner functionOrProperty,
@NotNull CodegenContext context, @NotNull ClassBuilder classBuilder
@NotNull ClassBuilder classBuilder
) {
FunctionCodegen functionCodegen = new FunctionCodegen(context, classBuilder, state);
if (functionOrProperty instanceof JetNamedFunction) {
@@ -64,4 +70,76 @@ public class MemberCodegen extends GenerationStateAware {
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.context.CodegenContext;
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.PropertyDescriptor;
import org.jetbrains.jet.lang.diagnostics.DiagnosticUtils;
@@ -48,7 +47,7 @@ import static org.jetbrains.asm4.Opcodes.*;
/**
* @author max
*/
public class NamespaceCodegen extends GenerationStateAware {
public class NamespaceCodegen extends MemberCodegen {
@NotNull
private final ClassBuilderOnDemand v;
@NotNull private final FqName name;
@@ -128,19 +127,17 @@ public class NamespaceCodegen extends GenerationStateAware {
for (JetDeclaration declaration : file.getDeclarations()) {
if (declaration instanceof JetProperty) {
final CodegenContext context = CodegenContext.STATIC.intoNamespace(descriptor);
state.getMemberCodegen().generateFunctionOrProperty(
(JetTypeParameterListOwner) declaration, context, v.getClassBuilder());
genFunctionOrProperty(context, (JetTypeParameterListOwner) declaration, v.getClassBuilder());
}
else if (declaration instanceof JetNamedFunction) {
if (!multiFile) {
final CodegenContext context = CodegenContext.STATIC.intoNamespace(descriptor);
state.getMemberCodegen().generateFunctionOrProperty(
(JetTypeParameterListOwner) declaration, context, v.getClassBuilder());
genFunctionOrProperty(context, (JetTypeParameterListOwner) declaration, v.getClassBuilder());
}
}
else if (declaration instanceof JetClassOrObject) {
final CodegenContext context = CodegenContext.STATIC.intoNamespace(descriptor);
state.getClassCodegen().generate(context, (JetClassOrObject) declaration);
genClassOrObject(context, (JetClassOrObject) declaration);
}
else if (declaration instanceof JetScript) {
state.getScriptCodegen().generate((JetScript) declaration);
@@ -157,7 +154,7 @@ public class NamespaceCodegen extends GenerationStateAware {
if (k > 0) {
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);
ClassBuilder builder = state.getFactory().forNamespacepart(className);
@@ -176,14 +173,12 @@ public class NamespaceCodegen extends GenerationStateAware {
{
final CodegenContext context =
CodegenContext.STATIC.intoNamespace(descriptor);
state.getMemberCodegen()
.generateFunctionOrProperty((JetTypeParameterListOwner) declaration, context, builder);
genFunctionOrProperty(context, (JetTypeParameterListOwner) declaration, builder);
}
{
final CodegenContext context =
CodegenContext.STATIC.intoNamespacePart(className, descriptor);
state.getMemberCodegen()
.generateFunctionOrProperty((JetTypeParameterListOwner) declaration, context, v.getClassBuilder());
genFunctionOrProperty(context, (JetTypeParameterListOwner) declaration, v.getClassBuilder());
}
}
}
@@ -287,7 +282,7 @@ public class NamespaceCodegen extends GenerationStateAware {
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
@@ -24,6 +24,7 @@ import org.jetbrains.asm4.MethodVisitor;
import org.jetbrains.asm4.Type;
import org.jetbrains.asm4.commons.InstructionAdapter;
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.kotlin.JetMethodAnnotationWriter;
import org.jetbrains.jet.codegen.state.GenerationStateAware;
@@ -41,6 +42,8 @@ import org.jetbrains.jet.lang.types.lang.JetStandardLibrary;
import java.util.BitSet;
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.lang.resolve.BindingContextUtils.descriptorToDeclaration;
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);
final String descriptor = signature.getJvmMethodSignature().getAsmMethod().getDescriptor();
final JvmMethodSignature jvmMethodSignature = signature.getJvmMethodSignature();
final String descriptor = jvmMethodSignature.getAsmMethod().getDescriptor();
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();
generateJetPropertyAnnotation(mv, signature.getPropertyTypeKotlinSignature(),
signature.getJvmMethodSignature().getKotlinTypeParameter(), propertyDescriptor,
jvmMethodSignature.getKotlinTypeParameter(), propertyDescriptor,
getter == null
? propertyDescriptor.getVisibility()
: getter.getVisibility());
@@ -212,7 +216,7 @@ public class PropertyCodegen extends GenerationStateAware {
if (propertyDescriptor.getModality() != Modality.ABSTRACT) {
mv.visitCode();
if (state.getClassBuilderMode() == ClassBuilderMode.STUBS) {
StubCodegen.generateStubThrow(mv);
genStubThrow(mv);
}
else {
InstructionAdapter iv = new InstructionAdapter(mv);
@@ -298,12 +302,13 @@ public class PropertyCodegen extends GenerationStateAware {
JvmPropertyAccessorSignature signature = typeMapper.mapSetterSignature(propertyDescriptor, kind);
assert true;
final String descriptor = signature.getJvmMethodSignature().getAsmMethod().getDescriptor();
MethodVisitor mv = v.newMethod(origin, flags, setterName(propertyDescriptor.getName()), descriptor, null, null);
final JvmMethodSignature jvmMethodSignature = signature.getJvmMethodSignature();
final String descriptor = jvmMethodSignature.getAsmMethod().getDescriptor();
MethodVisitor mv = v.newMethod(origin, flags, setterName(propertyDescriptor.getName()), descriptor, jvmMethodSignature.getGenericsSignature(), null);
PropertySetterDescriptor setter = propertyDescriptor.getSetter();
assert setter != null;
generateJetPropertyAnnotation(mv, signature.getPropertyTypeKotlinSignature(),
signature.getJvmMethodSignature().getKotlinTypeParameter(), propertyDescriptor,
jvmMethodSignature.getKotlinTypeParameter(), propertyDescriptor,
setter.getVisibility());
assert !setter.hasBody();
@@ -313,7 +318,7 @@ public class PropertyCodegen extends GenerationStateAware {
if (propertyDescriptor.getModality() != Modality.ABSTRACT) {
mv.visitCode();
if (state.getClassBuilderMode() == ClassBuilderMode.STUBS) {
StubCodegen.generateStubThrow(mv);
genStubThrow(mv);
}
else {
InstructionAdapter iv = new InstructionAdapter(mv);
@@ -27,6 +27,8 @@ import org.jetbrains.jet.lang.types.lang.JetStandardLibrary;
import java.util.List;
import static org.jetbrains.jet.codegen.AsmUtil.isPrimitiveNumberClassDescriptor;
/**
* @author abreslav
*/
@@ -91,7 +93,7 @@ public class RangeCodegenUtil {
public static boolean isOptimizableRangeTo(CallableDescriptor rangeTo) {
if ("rangeTo".equals(rangeTo.getName().getName())) {
if (CodegenUtil.isPrimitiveNumberClassDescriptor(rangeTo.getContainingDeclaration())) {
if (isPrimitiveNumberClassDescriptor(rangeTo.getContainingDeclaration())) {
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.signature.JvmMethodSignature;
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.lang.descriptors.ClassDescriptor;
import org.jetbrains.jet.lang.descriptors.ScriptDescriptor;
@@ -42,18 +41,16 @@ import java.util.Collections;
import java.util.List;
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.lang.resolve.java.AsmTypeConstants.OBJECT_TYPE;
/**
* @author Stepan Koltsov
*/
public class ScriptCodegen extends GenerationStateAware {
public class ScriptCodegen extends MemberCodegen {
@NotNull
private ClassFileFactory classFileFactory;
@NotNull
private MemberCodegen memberCodegen;
private List<ScriptDescriptor> earlierScripts;
private Method scriptConstructorMethod;
@@ -67,11 +64,6 @@ public class ScriptCodegen extends GenerationStateAware {
this.classFileFactory = classFileFactory;
}
@Inject
public void setMemberCodegen(@NotNull MemberCodegen memberCodegen) {
this.memberCodegen = memberCodegen;
}
public void generate(JetScript 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) {
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 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.*;
/**
@@ -61,7 +63,7 @@ public abstract class StackValue {
instructionAdapter.aconst(null);
}
else {
Type boxed = CodegenUtil.boxType(type);
Type boxed = boxType(type);
instructionAdapter.invokestatic(boxed.getInternalName(), "valueOf", "(" + type.getDescriptor() + ")" + boxed.getDescriptor());
}
}
@@ -76,7 +78,7 @@ public abstract class StackValue {
* JVM stack after this value was generated.
*
* @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
*/
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) {
put(this.type, v);
coerce(Type.BOOLEAN_TYPE, v);
coerceTo(Type.BOOLEAN_TYPE, v);
if (jumpIfFalse) {
v.ifeq(label);
}
@@ -171,7 +173,7 @@ public abstract class StackValue {
private static void box(final Type type, final Type toType, InstructionAdapter v) {
// 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;");
}
else if (type == Type.BOOLEAN_TYPE) {
@@ -231,7 +233,7 @@ public abstract class StackValue {
v.checkcast(type);
}
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);
}
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.getSort() == Type.VOID && fromType.getSort() != Type.VOID) {
@@ -306,7 +312,7 @@ public abstract class StackValue {
}
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) {
@@ -382,7 +388,7 @@ public abstract class StackValue {
@Override
public void put(Type type, InstructionAdapter v) {
coerce(type, v);
coerceTo(type, v);
}
}
@@ -401,13 +407,13 @@ public abstract class StackValue {
@Override
public void put(Type type, InstructionAdapter v) {
v.load(index, this.type);
coerce(type, v);
coerceTo(type, v);
// TODO unbox
}
@Override
public void store(Type topOfStackType, InstructionAdapter v) {
coerce(topOfStackType, this.type, v);
coerceFrom(topOfStackType, v);
v.store(index, this.type);
}
}
@@ -419,7 +425,7 @@ public abstract class StackValue {
@Override
public void put(Type type, InstructionAdapter v) {
coerce(type, v);
coerceTo(type, v);
}
@Override
@@ -465,7 +471,7 @@ public abstract class StackValue {
else {
v.aconst(value);
}
coerce(type, v);
coerceTo(type, v);
}
@Override
@@ -610,18 +616,18 @@ public abstract class StackValue {
public ArrayElement(Type type, boolean unbox) {
super(type);
this.boxed = unbox ? CodegenUtil.boxType(type) : type;
this.boxed = unbox ? boxType(type) : type;
}
@Override
public void put(Type type, InstructionAdapter v) {
v.aload(boxed); // assumes array and index are on the stack
onStack(boxed).coerce(type, v);
coerce(boxed, type, v);
}
@Override
public void store(Type topOfStackType, InstructionAdapter v) {
onStack(type).coerce(boxed, v);
coerce(topOfStackType, boxed, v);
v.astore(boxed);
}
@@ -677,7 +683,7 @@ public abstract class StackValue {
else {
((IntrinsicMethod) getter).generate(codegen, v, type, null, null, null, state);
}
coerce(type, v);
coerceTo(type, v);
}
@Override
@@ -901,7 +907,7 @@ public abstract class StackValue {
@Override
public void put(Type type, InstructionAdapter v) {
v.visitFieldInsn(isStatic ? GETSTATIC : GETFIELD, owner.getInternalName(), name, this.type.getDescriptor());
coerce(type, v);
coerceTo(type, v);
}
@Override
@@ -918,7 +924,7 @@ public abstract class StackValue {
@Override
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());
}
}
@@ -976,11 +982,12 @@ public abstract class StackValue {
v.visitMethodInsn(invokeOpcode, methodOwner.getInternalName(), getter.getName(), getter.getDescriptor());
}
}
coerce(type, v);
coerceTo(type, v);
}
@Override
public void store(Type topOfStackType, InstructionAdapter v) {
coerceFrom(topOfStackType, v);
if (isSuper && isInterface) {
assert setter != null;
v.visitMethodInsn(INVOKESTATIC, methodOwner.getInternalName(), setter.getName(),
@@ -1047,8 +1054,8 @@ public abstract class StackValue {
Type refType = refType(this.type);
Type sharedType = sharedTypeForType(this.type);
v.visitFieldInsn(GETFIELD, sharedType.getInternalName(), "ref", refType.getDescriptor());
coerce(refType, this.type, v);
coerce(this.type, type, v);
coerceFrom(refType, v);
coerceTo(type, v);
if (isReleaseOnPut) {
v.aconst(null);
v.store(index, OBJECT_TYPE);
@@ -1057,6 +1064,7 @@ public abstract class StackValue {
@Override
public void store(Type topOfStackType, InstructionAdapter v) {
coerceFrom(topOfStackType, v);
v.load(index, OBJECT_TYPE);
v.swap();
Type refType = refType(this.type);
@@ -1133,13 +1141,13 @@ public abstract class StackValue {
Type sharedType = sharedTypeForType(this.type);
Type refType = refType(this.type);
v.visitFieldInsn(GETFIELD, sharedType.getInternalName(), "ref", refType.getDescriptor());
StackValue.onStack(refType).coerce(this.type, v);
StackValue.onStack(this.type).coerce(type, v);
coerceFrom(refType, v);
coerceTo(type, v);
}
@Override
public void store(Type topOfStackType, InstructionAdapter v) {
coerce(topOfStackType, v);
coerceFrom(topOfStackType, v);
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) {
if (!type.equals(Type.VOID_TYPE)) {
v.load(index, Type.INT_TYPE);
coerce(type, v);
coerceTo(type, v);
}
v.iinc(index, increment);
}
@@ -1221,7 +1229,7 @@ public abstract class StackValue {
v.iinc(index, increment);
if (!type.equals(Type.VOID_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());
}
else {
nameStack.push(JetPsiUtil.getFQName(file).getFqName().replace('.', '/'));
nameStack.push(JvmClassName.byFqNameWithoutInnerClasses(JetPsiUtil.getFQName(file)).getInternalName());
}
file.acceptChildren(this);
nameStack.pop();
@@ -19,7 +19,6 @@ package org.jetbrains.jet.codegen.binding;
import com.intellij.psi.PsiElement;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.codegen.CodegenUtil;
import org.jetbrains.jet.lang.descriptors.*;
import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor;
import org.jetbrains.jet.lang.psi.*;
@@ -39,6 +38,7 @@ import java.util.Collection;
import java.util.Collections;
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.BindingContextUtils.descriptorToDeclaration;
@@ -365,7 +365,7 @@ public class CodegenBinding {
assert superType != null;
ClassDescriptor superClassDescriptor = (ClassDescriptor) superType.getConstructor().getDeclarationDescriptor();
assert superClassDescriptor != null;
if (!CodegenUtil.isInterface(superClassDescriptor)) {
if (!isInterface(superClassDescriptor)) {
return (JetDelegatorToSuperCall) specifier;
}
}
@@ -31,6 +31,7 @@ import java.util.Collections;
import java.util.HashMap;
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.FQN;
import static org.jetbrains.jet.lang.resolve.java.AsmTypeConstants.OBJECT_TYPE;
@@ -261,7 +262,7 @@ public abstract class CodegenContext {
final ClassDescriptor enclosingClass = getEnclosingClass();
outerExpression = enclosingClass != null
? 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)
: null;
}
@@ -17,7 +17,6 @@
package org.jetbrains.jet.codegen.context;
import org.jetbrains.asm4.Type;
import org.jetbrains.jet.codegen.CodegenUtil;
import org.jetbrains.jet.codegen.ExpressionCodegen;
import org.jetbrains.jet.codegen.StackValue;
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.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.isLocalNamedFun;
import static org.jetbrains.jet.lang.resolve.BindingContextUtils.callableDescriptorToDeclaration;
@@ -122,7 +122,7 @@ public interface LocalLookup {
final JetType receiverType = ((CallableDescriptor) d).getReceiverParameter().getType();
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();
return innerValue;
@@ -20,15 +20,16 @@ import com.intellij.psi.PsiElement;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.asm4.Type;
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.StackValue;
import org.jetbrains.jet.codegen.state.GenerationState;
import org.jetbrains.jet.lang.psi.JetExpression;
import org.jetbrains.jet.lang.resolve.java.AsmTypeConstants;
import java.util.List;
import static org.jetbrains.jet.codegen.AsmUtil.correctElementType;
/**
* @author alex.tkachman
*/
@@ -44,7 +45,7 @@ public class ArrayGet implements IntrinsicMethod {
@NotNull GenerationState state
) {
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);
@@ -20,15 +20,16 @@ import com.intellij.psi.PsiElement;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.asm4.Type;
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.StackValue;
import org.jetbrains.jet.codegen.state.GenerationState;
import org.jetbrains.jet.lang.psi.JetExpression;
import org.jetbrains.jet.lang.resolve.java.AsmTypeConstants;
import java.util.List;
import static org.jetbrains.jet.codegen.AsmUtil.correctElementType;
/**
* @author alex.tkachman
*/
@@ -44,7 +45,7 @@ public class ArraySet implements IntrinsicMethod {
@NotNull GenerationState state
) {
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(1), type);
@@ -20,7 +20,6 @@ import com.intellij.psi.PsiElement;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.asm4.Type;
import org.jetbrains.asm4.commons.InstructionAdapter;
import org.jetbrains.jet.codegen.CodegenUtil;
import org.jetbrains.jet.codegen.ExpressionCodegen;
import org.jetbrains.jet.codegen.StackValue;
import org.jetbrains.jet.codegen.state.GenerationState;
@@ -29,6 +28,8 @@ import org.jetbrains.jet.lang.psi.JetExpression;
import java.util.List;
import static org.jetbrains.asm4.Opcodes.*;
import static org.jetbrains.jet.codegen.AsmUtil.boxType;
import static org.jetbrains.jet.codegen.AsmUtil.unboxType;
/**
* @author yole
@@ -52,7 +53,7 @@ public class BinaryOp implements IntrinsicMethod {
) {
boolean nullable = expectedType.getSort() == Type.OBJECT;
if (nullable) {
expectedType = CodegenUtil.unboxType(expectedType);
expectedType = unboxType(expectedType);
}
if (arguments.size() == 1) {
// Intrinsic is called as an ordinary function
@@ -68,7 +69,7 @@ public class BinaryOp implements IntrinsicMethod {
v.visitInsn(expectedType.getOpcode(opcode));
if (nullable) {
StackValue.onStack(expectedType).put(expectedType = CodegenUtil.boxType(expectedType), v);
StackValue.onStack(expectedType).put(expectedType = boxType(expectedType), v);
}
return StackValue.onStack(expectedType);
}
@@ -20,7 +20,6 @@ import com.intellij.psi.PsiElement;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.asm4.Type;
import org.jetbrains.asm4.commons.InstructionAdapter;
import org.jetbrains.jet.codegen.CodegenUtil;
import org.jetbrains.jet.codegen.ExpressionCodegen;
import org.jetbrains.jet.codegen.StackValue;
import org.jetbrains.jet.codegen.state.GenerationState;
@@ -29,6 +28,9 @@ import org.jetbrains.jet.lang.resolve.java.AsmTypeConstants;
import java.util.List;
import static org.jetbrains.jet.codegen.AsmUtil.genInvokeAppendMethod;
import static org.jetbrains.jet.codegen.AsmUtil.genStringBuilderConstructor;
/**
* @author yole
*/
@@ -44,15 +46,15 @@ public class Concat implements IntrinsicMethod {
@NotNull GenerationState state
) {
if (receiver == null || receiver == StackValue.none()) { // LHS + RHS
CodegenUtil.generateStringBuilderConstructor(v);
genStringBuilderConstructor(v);
codegen.invokeAppend(arguments.get(0)); // StringBuilder(LHS)
codegen.invokeAppend(arguments.get(1));
}
else { // LHS.plus(RHS)
receiver.put(AsmTypeConstants.OBJECT_TYPE, v);
CodegenUtil.generateStringBuilderConstructor(v);
genStringBuilderConstructor(v);
v.swap(); // StringBuilder LHS
CodegenUtil.invokeAppendMethod(v, expectedType); // StringBuilder(LHS)
genInvokeAppendMethod(v, expectedType); // StringBuilder(LHS)
codegen.invokeAppend(arguments.get(0));
}
@@ -20,18 +20,20 @@ import com.intellij.psi.PsiElement;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.asm4.Type;
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.StackValue;
import org.jetbrains.jet.codegen.state.GenerationState;
import org.jetbrains.jet.lang.psi.JetCallExpression;
import org.jetbrains.jet.lang.psi.JetExpression;
import org.jetbrains.jet.lang.resolve.BindingContext;
import org.jetbrains.jet.lang.resolve.java.AsmTypeConstants;
import org.jetbrains.jet.lang.types.JetType;
import org.jetbrains.jet.lexer.JetTokens;
import java.util.List;
import static org.jetbrains.jet.codegen.AsmUtil.genEqualsForExpressionsOnStack;
/**
* @author alex.tkachman
*/
@@ -74,8 +76,8 @@ public class Equals implements IntrinsicMethod {
codegen.gen(rightExpr).put(AsmTypeConstants.OBJECT_TYPE, v);
assert rightType != null;
return codegen
.generateEqualsForExpressionsOnStack(JetTokens.EQEQ, AsmTypeConstants.OBJECT_TYPE, AsmTypeConstants.OBJECT_TYPE, leftNullable,
rightType.isNullable());
return genEqualsForExpressionsOnStack(v, JetTokens.EQEQ, AsmTypeConstants.OBJECT_TYPE, AsmTypeConstants.OBJECT_TYPE,
leftNullable,
rightType.isNullable());
}
}
@@ -20,7 +20,6 @@ import com.intellij.psi.PsiElement;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.asm4.Type;
import org.jetbrains.asm4.commons.InstructionAdapter;
import org.jetbrains.jet.codegen.CodegenUtil;
import org.jetbrains.jet.codegen.ExpressionCodegen;
import org.jetbrains.jet.codegen.StackValue;
import org.jetbrains.jet.codegen.state.GenerationState;
@@ -30,6 +29,8 @@ import org.jetbrains.jet.lang.psi.JetReferenceExpression;
import java.util.List;
import static org.jetbrains.jet.codegen.AsmUtil.*;
/**
* @author yole
*/
@@ -52,7 +53,7 @@ public class Increment implements IntrinsicMethod {
) {
boolean nullable = expectedType.getSort() == Type.OBJECT;
if (nullable) {
expectedType = CodegenUtil.unboxType(expectedType);
expectedType = unboxType(expectedType);
}
if (arguments.size() > 0) {
JetExpression operand = arguments.get(0);
@@ -61,7 +62,7 @@ public class Increment implements IntrinsicMethod {
}
if (operand instanceof JetReferenceExpression) {
final int index = codegen.indexOfLocal((JetReferenceExpression) operand);
if (index >= 0 && CodegenUtil.isIntPrimitive(expectedType)) {
if (index >= 0 && isIntPrimitive(expectedType)) {
return StackValue.preIncrement(index, myDelta);
}
}
@@ -70,30 +71,13 @@ public class Increment implements IntrinsicMethod {
value.dupReceiver(v);
value.put(expectedType, v);
plusMinus(v, expectedType);
value.store(expectedType, v);
value.store(genIncrement(expectedType, myDelta, v), v);
value.put(expectedType, v);
}
else {
receiver.put(expectedType, v);
plusMinus(v, expectedType);
StackValue.coerce(genIncrement(expectedType, myDelta, v), expectedType, v);
}
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 EnumValues ENUM_VALUES = new EnumValues();
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 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("plus"), 1, STRING_PLUS);
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("iterator"), 0, new IteratorIterator());
@@ -149,16 +148,25 @@ public class IntrinsicMethods {
declareIntrinsicProperty(Name.identifier("CharSequence"), 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) {
intrinsicsMap.registerIntrinsic(
JetStandardClasses.STANDARD_CLASSES_FQNAME.child(type.getRangeTypeName()).toUnsafe().child(
getClassObjectName(type.getRangeTypeName())),
getClassObjectFqName(type.getRangeTypeName()),
Name.identifier("EMPTY"), -1, new EmptyRange(type));
}
declareArrayMethods();
}
@NotNull
private static FqNameUnsafe getClassObjectFqName(@NotNull Name builtinClassName) {
return JetStandardClasses.STANDARD_CLASSES_FQNAME.child(builtinClassName).toUnsafe().child(getClassObjectName(builtinClassName));
}
private void declareArrayMethods() {
for (JvmPrimitiveType jvmPrimitiveType : JvmPrimitiveType.values()) {
@@ -20,7 +20,6 @@ import com.intellij.psi.PsiElement;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.asm4.Type;
import org.jetbrains.asm4.commons.InstructionAdapter;
import org.jetbrains.jet.codegen.CodegenUtil;
import org.jetbrains.jet.codegen.ExpressionCodegen;
import org.jetbrains.jet.codegen.StackValue;
import org.jetbrains.jet.codegen.state.GenerationState;
@@ -28,6 +27,8 @@ import org.jetbrains.jet.lang.psi.JetExpression;
import java.util.List;
import static org.jetbrains.jet.codegen.AsmUtil.unboxType;
/**
* @author yole
* @author alex.tkachman
@@ -45,7 +46,7 @@ public class Inv implements IntrinsicMethod {
) {
boolean nullable = expectedType.getSort() == Type.OBJECT;
if (nullable) {
expectedType = CodegenUtil.unboxType(expectedType);
expectedType = unboxType(expectedType);
}
receiver.put(expectedType, v);
if (expectedType == Type.LONG_TYPE) {
@@ -20,7 +20,6 @@ import com.intellij.psi.PsiElement;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.asm4.Type;
import org.jetbrains.asm4.commons.InstructionAdapter;
import org.jetbrains.jet.codegen.CodegenUtil;
import org.jetbrains.jet.codegen.ExpressionCodegen;
import org.jetbrains.jet.codegen.StackValue;
import org.jetbrains.jet.codegen.state.GenerationState;
@@ -28,6 +27,8 @@ import org.jetbrains.jet.lang.psi.JetExpression;
import java.util.List;
import static org.jetbrains.jet.codegen.AsmUtil.genToString;
/**
* @author alex.tkachman
*/
@@ -42,6 +43,6 @@ public class ToString implements IntrinsicMethod {
StackValue receiver,
@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.asm4.Type;
import org.jetbrains.asm4.commons.InstructionAdapter;
import org.jetbrains.jet.codegen.CodegenUtil;
import org.jetbrains.jet.codegen.ExpressionCodegen;
import org.jetbrains.jet.codegen.StackValue;
import org.jetbrains.jet.codegen.state.GenerationState;
@@ -28,6 +27,9 @@ import org.jetbrains.jet.lang.psi.JetExpression;
import java.util.List;
import static org.jetbrains.jet.codegen.AsmUtil.genNegate;
import static org.jetbrains.jet.codegen.AsmUtil.unboxType;
/**
* @author yole
*/
@@ -44,7 +46,7 @@ public class UnaryMinus implements IntrinsicMethod {
) {
boolean nullable = expectedType.getSort() == Type.OBJECT;
if (nullable) {
expectedType = CodegenUtil.unboxType(expectedType);
expectedType = unboxType(expectedType);
}
if (arguments.size() == 1) {
codegen.gen(arguments.get(0), expectedType);
@@ -52,7 +54,7 @@ public class UnaryMinus implements IntrinsicMethod {
else {
receiver.put(expectedType, v);
}
v.neg(expectedType);
StackValue.coerce(genNegate(expectedType, v), expectedType, v);
return StackValue.onStack(expectedType);
}
}
@@ -21,7 +21,6 @@ import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.asm4.Type;
import org.jetbrains.asm4.commons.InstructionAdapter;
import org.jetbrains.jet.codegen.CodegenUtil;
import org.jetbrains.jet.codegen.ExpressionCodegen;
import org.jetbrains.jet.codegen.StackValue;
import org.jetbrains.jet.codegen.state.GenerationState;
@@ -29,6 +28,8 @@ import org.jetbrains.jet.lang.psi.JetExpression;
import java.util.List;
import static org.jetbrains.jet.codegen.AsmUtil.unboxType;
/**
* @author alex.tkachman
*/
@@ -45,7 +46,7 @@ public class UnaryPlus implements IntrinsicMethod {
) {
boolean nullable = expectedType.getSort() == Type.OBJECT;
if (nullable) {
expectedType = CodegenUtil.unboxType(expectedType);
expectedType = unboxType(expectedType);
}
if (receiver != null && receiver != StackValue.none()) {
receiver.put(expectedType, v);
@@ -18,50 +18,34 @@ package org.jetbrains.jet.codegen.intrinsics;
import com.intellij.psi.PsiElement;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.asm4.Label;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.asm4.Type;
import org.jetbrains.asm4.commons.InstructionAdapter;
import org.jetbrains.jet.codegen.ExpressionCodegen;
import org.jetbrains.jet.codegen.StackValue;
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.resolve.BindingContext;
import org.jetbrains.jet.lang.resolve.calls.ResolvedCall;
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
public StackValue generate(
ExpressionCodegen codegen,
InstructionAdapter v,
@NotNull Type expectedType,
PsiElement element,
List<JetExpression> arguments,
@Nullable PsiElement element,
@Nullable List<JetExpression> arguments,
StackValue receiver,
@NotNull GenerationState state
) {
JetCallExpression call = (JetCallExpression) element;
ResolvedCall<? extends CallableDescriptor> resolvedCall =
codegen.getBindingContext().get(BindingContext.RESOLVED_CALL, call.getCalleeExpression());
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);
}
v.getstatic(JET_TUPLE0_TYPE.getInternalName(), "VALUE", JET_TUPLE0_TYPE.getDescriptor());
return StackValue.onStack(expectedType);
}
}
@@ -152,19 +152,22 @@ public class BothSignatureWriter {
state = to;
}
public void writeAsmType(Type asmType, boolean nullable) {
writeAsmType(asmType, nullable, null);
}
/**
* Shortcut
*/
public void writeAsmType(Type asmType, boolean nullable) {
public void writeAsmType(Type asmType, boolean nullable, @Nullable String kotlinTypeName) {
switch (asmType.getSort()) {
case Type.OBJECT:
writeClassBegin(asmType.getInternalName(), nullable, false);
writeClassBegin(asmType.getInternalName(), nullable, false, kotlinTypeName);
writeClassEnd();
return;
case Type.ARRAY:
writeArrayType(nullable);
writeAsmType(asmType.getElementType(), false);
writeAsmType(asmType.getElementType(), false, kotlinTypeName);
writeArrayEnd();
return;
default:
@@ -218,8 +221,12 @@ public class BothSignatureWriter {
}
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);
jetSignatureWriter.visitClassType(internalName, nullable, real);
jetSignatureWriter.visitClassType(kotlinTypeName == null ? internalName : kotlinTypeName, nullable, real);
writeAsmType0(Type.getObjectType(internalName));
}
@@ -68,12 +68,6 @@ public class GenerationState {
@NotNull
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) {
this(project, builderFactory, Progress.DEAF, analyzeExhaust, files, BuiltinToJavaTypesMapping.ENABLED);
}
@@ -98,8 +92,6 @@ public class GenerationState {
builtinToJavaTypesMapping, this, builderFactory, project);
this.scriptCodegen = injector.getScriptCodegen();
this.memberCodegen = injector.getMemberCodegen();
this.classCodegen = injector.getClassCodegen();
this.intrinsics = injector.getIntrinsics();
this.classFileFactory = injector.getClassFileFactory();
}
@@ -154,16 +146,6 @@ public class GenerationState {
return intrinsics;
}
@NotNull
public MemberCodegen getMemberCodegen() {
return memberCodegen;
}
@NotNull
public ClassCodegen getClassCodegen() {
return classCodegen;
}
public void beforeCompile() {
markUsed();
@@ -46,6 +46,7 @@ import java.util.List;
import java.util.Map;
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.binding.CodegenBinding.*;
import static org.jetbrains.jet.lang.resolve.BindingContextUtils.descriptorToDeclaration;
@@ -262,7 +263,7 @@ public class JetTypeMapper extends BindingTraceAware {
}
Type asmType = Type.getObjectType("error/NonExistentClass");
if (signatureVisitor != null) {
writeSimpleType(signatureVisitor, asmType, true);
signatureVisitor.writeAsmType(asmType, true);
}
checkValidType(asmType);
return asmType;
@@ -302,7 +303,7 @@ public class JetTypeMapper extends BindingTraceAware {
}
boolean forceReal = KotlinToJavaTypesMap.getInstance().isForceReal(name);
writeGenericType(jetType, signatureVisitor, asmType, forceReal);
writeGenericType(signatureVisitor, asmType, jetType, forceReal);
checkValidType(asmType);
return asmType;
@@ -339,9 +340,10 @@ public class JetTypeMapper extends BindingTraceAware {
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) {
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()) {
// TODO: +-
signatureVisitor.writeTypeArgument(proj.getProjectionKind());
@@ -355,18 +357,28 @@ public class JetTypeMapper extends BindingTraceAware {
private Type mapKnownAsmType(JetType jetType, Type asmType, @Nullable BothSignatureWriter signatureVisitor) {
if (signatureVisitor != null) {
if (jetType.getArguments().isEmpty()) {
writeSimpleType(signatureVisitor, asmType, jetType.isNullable());
String kotlinTypeName = getKotlinTypeNameForSignature(jetType, asmType);
signatureVisitor.writeAsmType(asmType, jetType.isNullable(), kotlinTypeName);
}
else {
writeGenericType(jetType, signatureVisitor, asmType, false);
writeGenericType(signatureVisitor, asmType, jetType, false);
}
}
checkValidType(asmType);
return asmType;
}
private static void writeSimpleType(BothSignatureWriter visitor, Type asmType, boolean nullable) {
visitor.writeAsmType(asmType, nullable);
@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) {
@@ -534,7 +546,7 @@ public class JetTypeMapper extends BindingTraceAware {
else {
signatureVisitor.writeReturnType();
JetType returnType = f.getReturnType();
assert returnType != null;
assert returnType != null : "Function " + f + " has no return type";
mapReturnType(returnType, signatureVisitor);
signatureVisitor.writeReturnTypeEnd();
}
@@ -647,7 +659,7 @@ public class JetTypeMapper extends BindingTraceAware {
((ClassDescriptor) parentDescriptor).getKind() == ClassKind.ANNOTATION_CLASS;
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);
writeFormalTypeParameters(descriptor.getTypeParameters(), signatureWriter);
@@ -765,10 +777,11 @@ public class JetTypeMapper extends BindingTraceAware {
if (closure != null) {
for (Map.Entry<DeclarationDescriptor, EnclosedValueDescriptor> entry : closure.getCaptureVariables().entrySet()) {
if (entry.getKey() instanceof VariableDescriptor && !(entry.getKey() instanceof PropertyDescriptor)) {
Type sharedVarType = getSharedVarType(entry.getKey());
DeclarationDescriptor variableDescriptor = entry.getKey();
if (variableDescriptor instanceof VariableDescriptor && !(variableDescriptor instanceof PropertyDescriptor)) {
Type sharedVarType = getSharedVarType(variableDescriptor);
if (sharedVarType == null) {
sharedVarType = mapType(((VariableDescriptor) entry.getKey()).getType());
sharedVarType = mapType(((VariableDescriptor) variableDescriptor).getType());
}
signatureWriter.writeParameterType(JvmMethodParameterKind.SHARED_VAR);
signatureWriter.writeAsmType(sharedVarType, false);
@@ -17,23 +17,18 @@
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 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.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 java.util.List;
/* This file is generated by org.jetbrains.jet.di.AllInjectorsGenerator. DO NOT EDIT! */
public class InjectorForJvmCodegen {
@@ -47,11 +42,9 @@ public class InjectorForJvmCodegen {
private BindingTrace bindingTrace;
private BindingContext bindingContext;
private ClassBuilderMode classBuilderMode;
private ClassCodegen classCodegen;
private ScriptCodegen scriptCodegen;
private IntrinsicMethods intrinsics;
private ClassFileFactory classFileFactory;
private MemberCodegen memberCodegen;
public InjectorForJvmCodegen(
@NotNull JetTypeMapper jetTypeMapper,
@@ -70,14 +63,11 @@ public class InjectorForJvmCodegen {
this.bindingTrace = jetTypeMapper.getBindingTrace();
this.bindingContext = bindingTrace.getBindingContext();
this.classBuilderMode = classBuilderFactory.getClassBuilderMode();
this.classCodegen = new ClassCodegen(getGenerationState());
this.scriptCodegen = new ScriptCodegen(getGenerationState());
this.intrinsics = new IntrinsicMethods();
this.classFileFactory = new ClassFileFactory(getGenerationState());
this.memberCodegen = new MemberCodegen(getGenerationState());
this.scriptCodegen.setClassFileFactory(classFileFactory);
this.scriptCodegen.setMemberCodegen(memberCodegen);
this.classFileFactory.setBuilderFactory(classBuilderFactory);
@@ -105,10 +95,6 @@ public class InjectorForJvmCodegen {
return this.project;
}
public ClassCodegen getClassCodegen() {
return this.classCodegen;
}
public ScriptCodegen getScriptCodegen() {
return this.scriptCodegen;
}
@@ -121,8 +107,4 @@ public class InjectorForJvmCodegen {
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.Predicates;
import com.google.common.collect.Lists;
import com.intellij.openapi.project.Project;
import com.intellij.psi.PsiFile;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.analyzer.AnalyzeExhaust;
import org.jetbrains.jet.analyzer.AnalyzerFacade;
import org.jetbrains.jet.analyzer.AnalyzerFacadeForEverything;
import org.jetbrains.jet.di.InjectorForJavaDescriptorResolver;
import org.jetbrains.jet.di.InjectorForTopDownAnalyzerForJvm;
import org.jetbrains.jet.lang.BuiltinsScopeExtensionMode;
import org.jetbrains.jet.lang.DefaultModuleConfiguration;
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.NamespaceDescriptor;
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.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.scopes.WritableScope;
import org.jetbrains.jet.lang.types.lang.JetStandardLibrary;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
@@ -70,6 +83,67 @@ public enum AnalyzerFacadeForJVM implements AnalyzerFacade {
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(
JetFile file, List<AnalyzerScriptParameter> scriptParameters, @NotNull BuiltinsScopeExtensionMode builtinsScopeExtensionMode) {
AnalyzingUtils.checkForSyntacticErrors(file);
@@ -114,8 +114,7 @@ public class JavaDescriptorResolver implements DependencyClassByQualifiedNameRes
}
this.staticMembers = staticMembers;
this.kotlin = psiClass != null &&
(new PsiClassWrapper(psiClass).getJetClass().isDefined() || psiClass.getName().equals(JvmAbi.PACKAGE_CLASS));
this.kotlin = psiClass != null && isKotlinClass(psiClass);
classOrNamespaceDescriptor = descriptor;
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 FqName fqName,
@NotNull ClassDescriptorFromJvmBytecode descriptor
@@ -545,8 +544,9 @@ public class JavaDescriptorResolver implements DependencyClassByQualifiedNameRes
false);
String context = "constructor of class " + psiClass.getQualifiedName();
ValueParameterDescriptors valueParameterDescriptors = resolveParameterDescriptors(constructorDescriptor,
constructor.getParameters(),
TypeVariableResolvers.classTypeVariableResolver(classData.classDescriptor, context));
constructor.getParameters(),
TypeVariableResolvers.classTypeVariableResolver(
classData.classDescriptor, context));
if (valueParameterDescriptors.receiverType != null) {
throw new IllegalStateException();
}
@@ -585,6 +585,17 @@ public class JavaDescriptorResolver implements DependencyClassByQualifiedNameRes
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);
if (classObjectPsiClass == null) {
return null;
@@ -602,20 +613,39 @@ public class JavaDescriptorResolver implements DependencyClassByQualifiedNameRes
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
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();
assert psiClassQualifiedName != null : "Reading java class with no qualified name";
FqNameUnsafe fqName = new FqNameUnsafe(psiClassQualifiedName + "." + getClassObjectName(psiClass.getName()).getName());
ClassDescriptorFromJvmBytecode classObjectDescriptor = new ClassDescriptorFromJvmBytecode(
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()));
classObjectDescriptor.getBuilder().addFunctionDescriptor(createEnumClassObjectValuesMethod(classObjectDescriptor, trace));
classObjectDescriptor.getBuilder().addFunctionDescriptor(createEnumClassObjectValueOfMethod(classObjectDescriptor, trace));
return classObjectDescriptor;
}
@@ -656,6 +686,13 @@ public class JavaDescriptorResolver implements DependencyClassByQualifiedNameRes
if (clazz == null) {
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;
}
@@ -1887,7 +1924,7 @@ public class JavaDescriptorResolver implements DependencyClassByQualifiedNameRes
public List<ClassDescriptor> resolveInnerClasses(DeclarationDescriptor owner, PsiClass psiClass, boolean staticMembers) {
if (staticMembers) {
return new ArrayList<ClassDescriptor>(0);
return resolveInnerClassesOfClassObject(owner, psiClass);
}
PsiClass[] innerPsiClasses = psiClass.getInnerClasses();
@@ -1900,14 +1937,41 @@ public class JavaDescriptorResolver implements DependencyClassByQualifiedNameRes
if (innerPsiClass.getName().equals(JvmAbi.CLASS_OBJECT_CLASS_NAME)) {
continue;
}
ClassDescriptor classDescriptor = resolveClass(new FqName(innerPsiClass.getQualifiedName()),
DescriptorSearchRule.IGNORE_IF_FOUND_IN_KOTLIN);
assert classDescriptor != null: "couldn't resolve class " + innerPsiClass.getQualifiedName();
if (isInnerEnum(innerPsiClass, owner)) {
// Inner enums will be put later into our class object
continue;
}
ClassDescriptor classDescriptor = resolveInnerClass(innerPsiClass);
r.add(classDescriptor);
}
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
public static PsiAnnotation[] getAllAnnotations(@NotNull PsiModifierListOwner owner) {
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.PrimitiveType;
import java.lang.annotation.Annotation;
import java.util.*;
/**
* @author svtk
*/
public class JavaToKotlinClassMap implements PlatformToKotlinClassMap {
public class JavaToKotlinClassMap extends JavaToKotlinClassMapBuilder implements PlatformToKotlinClassMap {
private static JavaToKotlinClassMap instance = null;
@NotNull
@@ -57,42 +56,6 @@ public class JavaToKotlinClassMap implements PlatformToKotlinClassMap {
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() {
JetStandardLibrary standardLibrary = JetStandardLibrary.getInstance();
for (JvmPrimitiveType jvmPrimitiveType : JvmPrimitiveType.values()) {
@@ -131,19 +94,30 @@ public class JavaToKotlinClassMap implements PlatformToKotlinClassMap {
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);
}
@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) {
classDescriptorMap.put(javaClassName, 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) {
classDescriptorMapForCovariantPositions.put(javaClassName, 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;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.descriptors.ClassDescriptor;
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.types.*;
import org.jetbrains.jet.lang.types.lang.JetStandardClasses;
@@ -87,46 +89,58 @@ public abstract class JetTypeJetSignatureReader extends JetSignatureExceptionsAd
private List<TypeProjection> typeArguments;
@Override
public void visitClassType(String name, boolean nullable, boolean forceReal) {
FqName ourName = new FqName(name
.replace('/', '.')
.replace('$', '.') // TODO: not sure
);
this.classDescriptor = null;
if (!forceReal) {
classDescriptor = JavaToKotlinClassMap.getInstance().mapKotlinClass(ourName,
JavaTypeTransformer.TypeUsage.MEMBER_SIGNATURE_INVARIANT);
}
public void visitClassType(String signatureName, boolean nullable, boolean forceReal) {
FqName fqName = JvmClassName.bySignatureName(signatureName).getFqName();
if (classDescriptor == null) {
// 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)));
}
}
enterClass(resolveClassDescriptorByFqName(fqName, forceReal), fqName.getFqName(), nullable);
}
if (this.classDescriptor == null) {
this.classDescriptor = javaDescriptorResolver.resolveClass(ourName, DescriptorSearchRule.INCLUDE_KOTLIN);
}
private void enterClass(@Nullable ClassDescriptor classDescriptor, @NotNull String className, boolean nullable) {
this.classDescriptor = classDescriptor;
if (this.classDescriptor == null) {
// 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.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) {
switch (variance) {
case INVARIANT: return Variance.INVARIANT;
@@ -16,11 +16,18 @@
package org.jetbrains.jet.lang.resolve.java;
import com.google.common.collect.Lists;
import com.intellij.openapi.util.text.StringUtil;
import org.jetbrains.annotations.NotNull;
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 java.util.List;
/**
* @author Stepan Koltsov
*/
@@ -45,7 +52,7 @@ public class JvmClassName {
*/
@NotNull
public static JvmClassName byFqNameWithoutInnerClasses(@NotNull FqName fqName) {
JvmClassName r = new JvmClassName(fqName.getFqName().replace('.', '/'));
JvmClassName r = new JvmClassName(fqNameToInternalName(fqName));
r.fqName = fqName;
return r;
}
@@ -55,6 +62,13 @@ public class JvmClassName {
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) {
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);
@@ -65,13 +79,67 @@ public class JvmClassName {
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 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 FqName fqName;
private String descriptor;
private String signatureName;
private Type asmType;
@@ -82,7 +150,7 @@ public class JvmClassName {
@NotNull
public FqName getFqName() {
if (fqName == null) {
this.fqName = new FqName(decodeSpecialNames(encodeSpecialNames(internalName).replace('$', '.').replace('/', '.')));
this.fqName = new FqName(internalNameToFqName(internalName));
}
return fqName;
}
@@ -112,6 +180,36 @@ public class JvmClassName {
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
public String toString() {
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.FqNameUnsafe;
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 java.lang.annotation.Annotation;
import java.util.*;
import java.util.Map;
import java.util.Set;
/**
* @author svtk
*/
public class KotlinToJavaTypesMap {
public class KotlinToJavaTypesMap extends JavaToKotlinClassMapBuilder {
private static KotlinToJavaTypesMap instance = null;
@NotNull
@@ -57,41 +55,6 @@ public class KotlinToJavaTypesMap {
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() {
for (JvmPrimitiveType jvmPrimitiveType : JvmPrimitiveType.values()) {
FqName className = jvmPrimitiveType.getPrimitiveType().getClassName();
@@ -121,10 +84,24 @@ public class KotlinToJavaTypesMap {
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));
}
@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) {
FqNameUnsafe fqName = DescriptorUtils.getFQName(kotlinDescriptor);
assert fqName.isSafe();
@@ -22,11 +22,10 @@ import java.io.PrintStream;
* @author abreslav
*/
public class TuplesAndFunctionsGenerator {
private static int TUPLE_COUNT = 23;
private static final int TUPLE_COUNT = 23;
private static void generateTuples(PrintStream out, int count) {
generated(out);
out.println("public class Tuple0() {}");
for (int i = 1; i < count; i++) {
out.print("public class Tuple" + i);
out.print("<");
-1
View File
@@ -3,7 +3,6 @@
package jet
public class Tuple0() {}
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 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()
}
public trait Map<K, V> {
public trait Map<K, out V> {
// Query Operations
public fun size() : Int
public fun isEmpty() : Boolean
-2
View File
@@ -16,8 +16,6 @@ public fun Any?.equals(other : Any?) : Boolean// = this === other
// Returns "null" for null
public fun Any?.toString() : String// = this === other
public fun <T : Any> T?.sure() : T
public fun String?.plus(other: Any?) : String
public trait Comparable<in T> {
@@ -64,10 +64,15 @@ public interface JetNodeTypes {
JetNodeType VALUE_ARGUMENT = new JetNodeType("VALUE_ARGUMENT", JetValueArgument.class);
JetNodeType VALUE_ARGUMENT_NAME = new JetNodeType("VALUE_ARGUMENT_NAME", JetValueArgumentName.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");
@Deprecated // Tuples are to be removed in Kotlin M4
JetNodeType LABELED_TUPLE_TYPE_ENTRY = new JetNodeType("LABELED_TUPLE_TYPE_ENTRY");
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 FUNCTION_TYPE = new JetNodeType("FUNCTION_TYPE", JetFunctionType.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 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 PARENTHESIZED = new JetNodeType("PARENTHESIZED", JetParenthesizedExpression.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 INDICES = new JetNodeType("INDICES", JetContainerNode.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 PREDICATE_EXPRESSION = new JetNodeType("PREDICATE_EXPRESSION", JetPredicateExpression.class);
JetNodeType OBJECT_LITERAL = new JetNodeType("OBJECT_LITERAL", JetObjectLiteralExpression.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.BindingTrace;
import org.jetbrains.jet.lang.resolve.BodiesResolveContext;
import org.jetbrains.jet.lang.resolve.lazy.ResolveSession;
import java.util.Collection;
import java.util.List;
@@ -51,4 +52,10 @@ public interface AnalyzerFacade {
@NotNull BodiesResolveContext bodiesResolveContext,
@NotNull ModuleConfiguration configuration
);
@NotNull
ResolveSession getLazyResolveSession(
@NotNull Project project,
@NotNull Collection<JetFile> files
);
}
@@ -36,7 +36,9 @@ public abstract class ClassDescriptorBase implements ClassDescriptor {
@NotNull
@Override
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();
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.ReceiverDescriptor;
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
@@ -40,54 +42,54 @@ public class ClassDescriptorImpl extends DeclarationDescriptorNonRootImpl implem
private ConstructorDescriptor primaryConstructor;
private ReceiverDescriptor implicitReceiver;
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(
@NotNull DeclarationDescriptor containingDeclaration,
@NotNull ClassKind kind,
@NotNull List<AnnotationDescriptor> annotations,
@NotNull Modality modality,
@NotNull Name name) {
super(containingDeclaration, annotations, name);
this.kind = kind;
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,
@NotNull List<? extends TypeParameterDescriptor> typeParameters,
@NotNull Collection<JetType> supertypes,
@NotNull JetScope memberDeclarations,
@NotNull Set<ConstructorDescriptor> constructors,
@Nullable ConstructorDescriptor primaryConstructor,
@Nullable JetType superclassType) {
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
) {
this.typeConstructor = new TypeConstructorImpl(this, getAnnotations(), sealed, getName().getName(), typeParameters, supertypes);
this.memberDeclarations = memberDeclarations;
this.constructors = constructors;
this.primaryConstructor = primaryConstructor;
this.classObjectDescriptor = classObjectDescriptor;
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) {
this.primaryConstructor = primaryConstructor;
}
public void setClassObjectDescriptor(@NotNull ClassDescriptor classObjectDescriptor) {
this.classObjectDescriptor = classObjectDescriptor;
}
@Override
@NotNull
public TypeConstructor getTypeConstructor() {
@@ -126,18 +128,18 @@ public class ClassDescriptorImpl extends DeclarationDescriptorNonRootImpl implem
@Override
public JetType getClassObjectType() {
return null;
return getClassObjectDescriptor().getDefaultType();
}
@Override
public ClassDescriptor getClassObjectDescriptor() {
return null;
return classObjectDescriptor;
}
@NotNull
@Override
public ClassKind getKind() {
return ClassKind.CLASS;
return kind;
}
@Override
@@ -47,6 +47,12 @@ import static org.jetbrains.jet.lang.diagnostics.Severity.WARNING;
*/
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);
UnresolvedReferenceDiagnosticFactory UNRESOLVED_REFERENCE = UnresolvedReferenceDiagnosticFactory.create();
@@ -70,6 +76,8 @@ public interface Errors {
.create(WARNING, positionModifier(JetTokens.OPEN_KEYWORD));
SimpleDiagnosticFactory<JetModifierListOwner> OPEN_MODIFIER_IN_ENUM = SimpleDiagnosticFactory
.create(ERROR, positionModifier(JetTokens.OPEN_KEYWORD));
SimpleDiagnosticFactory<JetModifierListOwner> ILLEGAL_ENUM_ANNOTATION = SimpleDiagnosticFactory
.create(ERROR, positionModifier(JetTokens.ENUM_KEYWORD));
SimpleDiagnosticFactory<PsiElement>
REDUNDANT_MODIFIER_IN_GETTER = SimpleDiagnosticFactory.create(WARNING);
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<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, ValueParameterDescriptor> UNINITIALIZED_PARAMETER = DiagnosticFactory1.create(ERROR);
@@ -45,6 +45,11 @@ public class DefaultErrorMessages {
public static final DiagnosticRenderer<Diagnostic> RENDERER = new DispatchingDiagnosticRenderer(MAP);
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>() {
@NotNull
@Override
@@ -82,6 +87,7 @@ public class DefaultErrorMessages {
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_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(TRAIT_CAN_NOT_BE_FINAL, "Trait cannot be final");
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(USELESS_HIDDEN_IMPORT, "Useless import, it is hidden further");
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,
"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_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_PARAMETER, "Parameter ''{0}'' is uninitialized here", NAME);
@@ -288,20 +288,22 @@ public class Renderers {
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
@Override
public String render(@NotNull Collection<ClassDescriptor> descriptors) {
StringBuilder sb = new StringBuilder();
sb.append("(");
for (Iterator<ClassDescriptor> iterator = descriptors.iterator(); iterator.hasNext(); ) {
ClassDescriptor descriptor = iterator.next();
int index = 0;
for (ClassDescriptor descriptor : descriptors) {
sb.append(DescriptorUtils.getFQName(descriptor).getFqName());
if (iterator.hasNext()) {
index++;
if (index <= descriptors.size() - 2) {
sb.append(", ");
}
else if (index == descriptors.size() - 1) {
sb.append(" or ");
}
}
sb.append(")");
return sb.toString();
}
};
@@ -1591,6 +1591,7 @@ public class JetExpressionParsing extends AbstractJetParsing {
* : "#" "(" (((SimpleName "=")? expression){","})? ")"
* ;
*/
@Deprecated // Tuples are to be removed in Kotlin M4
private void parseTupleExpression() {
assert _at(HASH);
PsiBuilder.Marker mark = mark();
@@ -980,8 +980,7 @@ public class JetParsing extends AbstractJetParsing {
expect(IDENTIFIER, "Expecting parameter name", TokenSet.create(RPAR, COLON, LBRACE, EQ));
if (at(COLON)) {
advance();
advance(); // COLON
parseTypeRef();
}
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
* ;
*/
@Deprecated // Tuples are to be removed in Kotlin M4
private void parseTupleType() {
assert _at(HASH);
@@ -1730,20 +1730,23 @@ public class JetParsing extends AbstractJetParsing {
private boolean parseFunctionParameterRest() {
expect(IDENTIFIER, "Parameter name expected", PARAMETER_NAME_RECOVERY_SET);
boolean noErrors = true;
if (at(COLON)) {
advance(); // COLON
parseTypeRef();
}
else {
error("Parameters must have type annotation");
return false;
errorWithRecovery("Parameters must have type annotation", PARAMETER_NAME_RECOVERY_SET);
noErrors = false;
}
if (at(EQ)) {
advance(); // EQ
myExpressionParsing.parseExpression();
}
return true;
return noErrors;
}
/*
@@ -25,7 +25,10 @@ import java.util.List;
/**
* @author max
*/
@Deprecated // Tuples are to be removed in Kotlin M4
public class JetTupleExpression extends JetExpressionImpl {
@Deprecated // Tuples are to be removed in Kotlin M4
public JetTupleExpression(@NotNull ASTNode node) {
super(node);
}
@@ -40,6 +43,7 @@ public class JetTupleExpression extends JetExpressionImpl {
return visitor.visitTupleExpression(this, data);
}
@Deprecated // Tuples are to be removed in Kotlin M4
public List<JetExpression> getEntries() {
return PsiTreeUtil.getChildrenOfTypeAsList(this, JetExpression.class);
}
@@ -25,7 +25,10 @@ import java.util.List;
/**
* @author max
*/
@Deprecated // Tuples are to be removed in Kotlin M4
public class JetTupleType extends JetTypeElement {
@Deprecated // Tuples are to be removed in Kotlin M4
public JetTupleType(@NotNull ASTNode node) {
super(node);
}
@@ -47,6 +50,7 @@ public class JetTupleType extends JetTypeElement {
}
@NotNull
@Deprecated // Tuples are to be removed in Kotlin M4
public List<JetTypeReference> getComponentTypeRefs() {
return findChildrenByType(JetNodeTypes.TYPE_REFERENCE);
}
@@ -168,6 +168,7 @@ public class JetVisitor<R, D> extends PsiElementVisitor {
return visitExpression(expression, data);
}
@Deprecated // Tuples are to be removed in Kotlin M4
public R visitTupleExpression(JetTupleExpression expression, D data) {
return visitExpression(expression, data);
}
@@ -336,6 +337,7 @@ public class JetVisitor<R, D> extends PsiElementVisitor {
return visitTypeElement(type, data);
}
@Deprecated // Tuples are to be removed in Kotlin M4
public R visitTupleType(JetTupleType type, D data) {
return visitTypeElement(type, data);
}
@@ -158,6 +158,7 @@ public class JetVisitorVoid extends PsiElementVisitor {
visitExpression(expression);
}
@Deprecated // Tuples are to be removed in Kotlin M4
public void visitTupleExpression(JetTupleExpression expression) {
visitExpression(expression);
}
@@ -325,6 +326,7 @@ public class JetVisitorVoid extends PsiElementVisitor {
visitTypeElement(type);
}
@Deprecated // Tuples are to be removed in Kotlin M4
public void visitTupleType(JetTupleType type) {
visitTypeElement(type);
}
@@ -16,9 +16,11 @@
package org.jetbrains.jet.lang.resolve;
import com.google.common.collect.ImmutableMap;
import com.intellij.psi.PsiElement;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.annotations.TestOnly;
import org.jetbrains.jet.lang.descriptors.*;
import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor;
import org.jetbrains.jet.lang.diagnostics.Diagnostic;
@@ -59,6 +61,13 @@ public interface BindingContext {
public <K, V> Collection<K> getKeys(WritableSlice<K, V> slice) {
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();
@@ -221,6 +230,8 @@ public interface BindingContext {
ReadOnlySlice<PsiElement, DeclarationDescriptor> DECLARATION_TO_DESCRIPTOR = Slices.<PsiElement, DeclarationDescriptor>sliceBuilder()
.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<ValueParameterDescriptor, PropertyDescriptor> VALUE_PARAMETER_AS_PROPERTY =
Slices.<ValueParameterDescriptor, PropertyDescriptor>sliceBuilder().build();
@@ -253,4 +264,9 @@ public interface BindingContext {
// slice.isCollective() must be true
@NotNull
<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;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Lists;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.TestOnly;
import org.jetbrains.jet.lang.diagnostics.Diagnostic;
import org.jetbrains.jet.util.slicedmap.MutableSlicedMap;
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) {
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
@@ -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.types.ErrorUtils;
import org.jetbrains.jet.lang.types.lang.JetStandardLibrary;
import org.jetbrains.jet.resolve.DescriptorRenderer;
import javax.inject.Inject;
import java.util.*;
@@ -302,7 +303,8 @@ public class DeclarationResolver {
if (descriptors.size() > 1) {
for (DeclarationDescriptor declarationDescriptor : descriptors) {
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()));
}
}
@@ -66,6 +66,7 @@ public class DeclarationsChecker {
MutableClassDescriptor objectDescriptor = entry.getValue();
if (!bodiesResolveContext.completeAnalysisNeeded(objectDeclaration)) continue;
checkObject(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) {
checkOpenMembers(classDescriptor);
if (aClass.isTrait()) {
checkTraitModifiers(aClass);
}
else if (aClass.hasModifier(JetTokens.ENUM_KEYWORD)) {
else if (classDescriptor.getKind() == ClassKind.ENUM_CLASS) {
checkEnumModifiers(aClass);
}
else if (classDescriptor.getKind() == ClassKind.ENUM_ENTRY) {
@@ -105,6 +116,7 @@ public class DeclarationsChecker {
}
private void checkTraitModifiers(JetClass aClass) {
reportErrorIfHasEnumModifier(aClass);
JetModifierList modifierList = aClass.getModifierList();
if (modifierList == null) return;
if (modifierList.hasModifier(JetTokens.FINAL_KEYWORD)) {
@@ -130,6 +142,7 @@ public class DeclarationsChecker {
}
private void checkProperty(JetProperty property, PropertyDescriptor propertyDescriptor) {
reportErrorIfHasEnumModifier(property);
DeclarationDescriptor containingDeclaration = propertyDescriptor.getContainingDeclaration();
if (containingDeclaration instanceof ClassDescriptor) {
checkPropertyAbstractness(property, propertyDescriptor, (ClassDescriptor) containingDeclaration);
@@ -247,6 +260,7 @@ public class DeclarationsChecker {
}
protected void checkFunction(JetNamedFunction function, SimpleFunctionDescriptor functionDescriptor) {
reportErrorIfHasEnumModifier(function);
DeclarationDescriptor containingDescriptor = functionDescriptor.getContainingDeclaration();
boolean hasAbstractModifier = function.hasModifier(JetTokens.ABSTRACT_KEYWORD);
checkDeclaredTypeInPublicMember(function, functionDescriptor);
@@ -16,10 +16,11 @@
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 org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.annotations.TestOnly;
import org.jetbrains.jet.lang.diagnostics.Diagnostic;
import org.jetbrains.jet.util.slicedmap.*;
@@ -55,6 +56,15 @@ public class DelegatingBindingTrace implements BindingTrace {
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) {
@@ -355,4 +355,14 @@ public class DescriptorUtils {
+ (classifier == null ? "null" : classifier.getClass());
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 DescriptorSink sink
) {
List<CallableMemberDescriptor> notOverridden = Lists.newArrayList(membersFromSupertypes);
Collection<CallableMemberDescriptor> notOverridden = Sets.newLinkedHashSet(membersFromSupertypes);
for (CallableMemberDescriptor fromCurrent : membersFromCurrent) {
extractAndBindOverridesForMember(fromCurrent, notOverridden, current, sink);
Collection<CallableMemberDescriptor> bound =
extractAndBindOverridesForMember(fromCurrent, membersFromSupertypes, current, sink);
notOverridden.removeAll(bound);
}
createAndBindFakeOverrides(current, notOverridden, sink);
}
private static void extractAndBindOverridesForMember(
private static Collection<CallableMemberDescriptor> extractAndBindOverridesForMember(
@NotNull CallableMemberDescriptor fromCurrent,
@NotNull List<CallableMemberDescriptor> notOverridden, @NotNull ClassDescriptor current,
@NotNull Collection<? extends CallableMemberDescriptor> descriptorsFromSuper,
@NotNull ClassDescriptor current,
@NotNull DescriptorSink sink
) {
for (Iterator<CallableMemberDescriptor> iterator = notOverridden.iterator(); iterator.hasNext(); ) {
CallableMemberDescriptor fromSupertype = iterator.next();
Collection<CallableMemberDescriptor> bound = Lists.newArrayList();
for (CallableMemberDescriptor fromSupertype : descriptorsFromSuper) {
OverridingUtil.OverrideCompatibilityInfo.Result result =
OverridingUtil.isOverridableBy(fromSupertype, fromCurrent).getResult();
@@ -209,23 +212,24 @@ public class OverrideResolver {
if (isVisible) {
OverridingUtil.bindOverride(fromCurrent, fromSupertype);
}
iterator.remove();
bound.add(fromSupertype);
break;
case CONFLICT:
if (isVisible) {
sink.conflict(fromSupertype, fromCurrent);
}
iterator.remove();
bound.add(fromSupertype);
break;
case INCOMPATIBLE:
break;
}
}
return bound;
}
private static void createAndBindFakeOverrides(
@NotNull ClassDescriptor current,
@NotNull List<CallableMemberDescriptor> notOverridden,
@NotNull Collection<CallableMemberDescriptor> notOverridden,
@NotNull DescriptorSink sink
) {
Queue<CallableMemberDescriptor> fromSuperQueue = new LinkedList<CallableMemberDescriptor>(notOverridden);
@@ -735,7 +739,7 @@ public class OverrideResolver {
if (OverridingUtil.isOverridableBy(fromSuper, declared).getResult() == OVERRIDABLE) {
invisibleOverride = fromSuper;
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;
}
@@ -19,6 +19,7 @@ package org.jetbrains.jet.lang.resolve;
import com.google.common.collect.Lists;
import com.google.common.collect.Multimap;
import com.google.common.collect.Sets;
import com.intellij.lang.ASTNode;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiNameIdentifierOwner;
import com.intellij.util.containers.ContainerUtil;
@@ -195,164 +196,14 @@ public class TypeHierarchyResolver {
) {
final Collection<JetDeclarationContainer> forDeferredResolve = new ArrayList<JetDeclarationContainer>();
ClassifierCollector collector = new ClassifierCollector(outerScope, owner, forDeferredResolve);
for (PsiElement declaration : declarations) {
declaration.accept(new JetVisitorVoid() {
@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);
}
});
declaration.accept(collector);
}
collector.finishProcessing();
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.List;
import static org.jetbrains.jet.lang.diagnostics.Errors.UNSUPPORTED;
import static org.jetbrains.jet.lang.diagnostics.Errors.WRONG_NUMBER_OF_TYPE_ARGUMENTS;
import static org.jetbrains.jet.lang.diagnostics.Errors.*;
/**
* @author abreslav
@@ -180,6 +179,14 @@ public class TypeResolver {
@Override
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
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.collect.Collections2;
import com.google.common.collect.Lists;
import com.intellij.psi.PsiElement;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.descriptors.*;
@@ -139,7 +140,8 @@ public class LazyClassDescriptor extends ClassDescriptorBase implements ClassDes
}
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;
}
@@ -285,8 +287,8 @@ public class LazyClassDescriptor extends ClassDescriptorBase implements ClassDes
JetModifierList modifierList = classInfo.getModifierList();
if (modifierList != null) {
AnnotationResolver annotationResolver = resolveSession.getInjector().getAnnotationResolver();
annotations = annotationResolver
.resolveAnnotations(resolveSession.getResolutionScope(classInfo.getScopeAnchor()), modifierList, resolveSession.getTrace());
JetScope scopeForDeclaration = getScopeProvider().getResolutionScopeForDeclaration(classInfo.getScopeAnchor());
annotations = annotationResolver.resolveAnnotations(scopeForDeclaration, modifierList, resolveSession.getTrace());
}
else {
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.FqNameUnsafe;
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 java.util.List;
@@ -135,7 +134,7 @@ public class ResolveSession {
if (classOrObject.getParent() instanceof JetClassObject) {
return getClassObjectDescriptor((JetClassObject) classOrObject.getParent());
}
JetScope resolutionScope = getInjector().getScopeProvider().getResolutionScopeForDeclaration((JetDeclaration) classOrObject);
JetScope resolutionScope = getInjector().getScopeProvider().getResolutionScopeForDeclaration(classOrObject);
Name name = classOrObject.getNameAsName();
assert name != null : "Name is null for " + classOrObject + " " + classOrObject.getText();
ClassifierDescriptor classifier = resolutionScope.getClassifier(name);
@@ -170,33 +169,6 @@ public class ResolveSession {
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
public DeclarationDescriptor resolveToDescriptor(JetDeclaration declaration) {
DeclarationDescriptor result = declaration.accept(new JetVisitor<DeclarationDescriptor, Void>() {
@@ -183,7 +183,7 @@ public class ResolveSessionUtils {
JetFile file
) {
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);
bodyResolver.resolveFunctionBody(trace, namedFunction, functionDescriptor, scope);
}
@@ -216,9 +216,12 @@ public class ResolveSessionUtils {
}
private static JetScope getExpressionResolutionScope(@NotNull ResolveSession resolveSession, @NotNull JetExpression expression) {
ScopeProvider provider = resolveSession.getInjector().getScopeProvider();
JetDeclaration parentDeclaration = PsiTreeUtil.getParentOfType(expression, JetDeclaration.class);
// DeclarationDescriptor descriptor = resolveToDescriptor(parentDeclaration);
return resolveSession.getResolutionScope(parentDeclaration);
if (parentDeclaration == null) {
return provider.getFileScopeForDeclarationResolution((JetFile) expression.getContainingFile());
}
return provider.getResolutionScopeForDeclaration(parentDeclaration);
}
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.scopes.*;
import java.util.Map;
import java.util.WeakHashMap;
/**
* @author abreslav
*/
@@ -37,56 +40,66 @@ public class ScopeProvider {
this.resolveSession = resolveSession;
}
private final Map<JetFile, JetScope> fileScopeCache = new WeakHashMap<JetFile, JetScope>();
// This scope does not contain imported functions
@NotNull
public JetScope getFileScopeForDeclarationResolution(JetFile file) {
// package
JetNamespaceHeader header = file.getNamespaceHeader();
if (header == null) {
throw new IllegalArgumentException("Scripts are not supported: " + file.getName());
if (!fileScopeCache.containsKey(file)) {
// package
JetNamespaceHeader header = file.getNamespaceHeader();
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());
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);
return fileScopeCache.get(file);
}
@NotNull
public JetScope getResolutionScopeForDeclaration(@NotNull JetDeclaration jetDeclaration) {
PsiElement immediateParent = jetDeclaration.getParent();
if (immediateParent instanceof JetFile) {
return getFileScopeForDeclarationResolution((JetFile) immediateParent);
}
public JetScope getResolutionScopeForDeclaration(@NotNull PsiElement elementOfDeclaration) {
JetDeclaration jetDeclaration = PsiTreeUtil.getParentOfType(elementOfDeclaration, JetDeclaration.class, false);
assert !(elementOfDeclaration instanceof JetDeclaration) || jetDeclaration == elementOfDeclaration :
"For JetDeclaration element getParentOfType() should return itself.";
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) {
JetClassOrObject classOrObject = (JetClassOrObject) parentDeclaration;
LazyClassDescriptor classDescriptor = (LazyClassDescriptor) resolveSession.getClassDescriptor(classOrObject);
@@ -98,13 +111,18 @@ public class ScopeProvider {
}
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;
LazyClassDescriptor classObjectDescriptor = resolveSession.getClassObjectDescriptor(classObject);
return classObjectDescriptor.getScopeForMemberDeclarationResolution();
}
else {
throw new IllegalStateException("Don't call this method for local declarations: " + jetDeclaration + " " + jetDeclaration.getText());
LazyClassDescriptor classObjectDescriptor =
(LazyClassDescriptor) resolveSession.getClassObjectDescriptor(classObject).getContainingDeclaration();
// During class object header resolve there should be no resolution for parent class generic params
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
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<JetType> types = new ArrayList<JetType>();
for (JetExpression entry : entries) {
@@ -882,7 +890,7 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor {
return typeInfo;
}
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));
}
else {
@@ -966,7 +974,7 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor {
}
else if (OperatorConventions.COMPARISON_OPERATIONS.contains(operationType)) {
JetType compareToReturnType = getTypeForBinaryCall(context.scope, Name.identifier("compareTo"), context, expression);
if (compareToReturnType != null) {
if (compareToReturnType != null && !ErrorUtils.isErrorType(compareToReturnType)) {
TypeConstructor constructor = compareToReturnType.getConstructor();
JetStandardLibrary standardLibrary = JetStandardLibrary.getInstance();
TypeConstructor intTypeConstructor = standardLibrary.getInt().getTypeConstructor();
@@ -22,6 +22,7 @@ import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.descriptors.*;
import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor;
import org.jetbrains.jet.lang.resolve.DescriptorResolver;
import org.jetbrains.jet.lang.resolve.DescriptorUtils;
import org.jetbrains.jet.lang.resolve.name.FqName;
import org.jetbrains.jet.lang.resolve.name.FqNameUnsafe;
@@ -91,7 +92,6 @@ public class JetStandardClasses {
},
JetScope.EMPTY,
Collections.<ConstructorDescriptor>singleton(constructorDescriptor),
null,
null
);
NOTHING_TYPE = new JetTypeImpl(getNothing());
@@ -125,7 +125,6 @@ public class JetStandardClasses {
Collections.<JetType>emptySet(),
JetScope.EMPTY,
Collections.<ConstructorDescriptor>singleton(constructorDescriptor),
null,
null
);
ANY_TYPE = new JetTypeImpl(ANY.getTypeConstructor(), new JetScopeImpl() {
@@ -201,14 +200,84 @@ public class JetStandardClasses {
writableScope,
Collections.<ConstructorDescriptor>singleton(constructorDescriptor),
null);
if (i == 0) {
// Unit.VALUE
classDescriptor.setClassObjectDescriptor(createClassObjectForUnit(classDescriptor));
}
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());
}
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
@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;
@@ -16,6 +16,10 @@
package org.jetbrains.jet.util.slicedmap;
import com.google.common.collect.ImmutableMap;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.TestOnly;
/**
* @author abreslav
*/
@@ -26,4 +30,8 @@ public interface MutableSlicedMap extends SlicedMap {
<K, V> V remove(RemovableSlice<K, V> slice, K key);
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;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Maps;
import com.google.common.collect.Multimap;
import com.google.common.collect.Multimaps;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.util.CommonSuppliers;
import java.util.Collection;
@@ -106,4 +108,16 @@ public class SlicedMapImpl implements MutableSlicedMap {
//noinspection unchecked
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 org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.codegen.CodegenUtil;
import org.jetbrains.jet.codegen.NamespaceCodegen;
import org.jetbrains.jet.lang.psi.*;
import org.jetbrains.jet.lang.resolve.java.JavaPsiFacadeKotlinHacks;
@@ -41,6 +40,8 @@ import org.jetbrains.jet.util.QualifiedNamesUtil;
import java.util.*;
import static org.jetbrains.jet.codegen.CodegenUtil.getLocalNameForObject;
public class JavaElementFinder extends PsiElementFinder implements JavaPsiFacadeKotlinHacks.KotlinFinderMarker {
private final Project project;
private final PsiManager psiManager;
@@ -166,7 +167,7 @@ public class JavaElementFinder extends PsiElementFinder implements JavaPsiFacade
if (given != null) return given;
if (declaration instanceof JetObjectDeclaration) {
return CodegenUtil.getLocalNameForObject((JetObjectDeclaration) declaration);
return getLocalNameForObject((JetObjectDeclaration) declaration);
}
return null;
@@ -266,7 +266,7 @@ public class JetLightClass extends AbstractLightClass implements JetJavaMirrorMa
public static PsiMethod wrapMethod(@NotNull JetNamedFunction function) {
//noinspection unchecked
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()
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 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 containsValue(/*0*/ value: jet.Any?): jet.Boolean
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 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 /*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.ShortIterator.iterator(): jet.ShortIterator
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 jet.Any?.toString(): jet.String
@@ -1,7 +1,7 @@
import java.lang.Runtime
fun box() : String {
val processors = Runtime.getRuntime().sure().availableProcessors()
val processors = Runtime.getRuntime()!!.availableProcessors()
var threadNum = 1
while(threadNum <= 1024) {
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