Merge branch 'master' of github.com:JetBrains/kotlin
This commit is contained in:
@@ -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);
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -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);
|
||||
|
||||
+9
-25
@@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+74
@@ -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);
|
||||
|
||||
+78
-14
@@ -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>();
|
||||
|
||||
+17
-43
@@ -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);
|
||||
|
||||
+57
@@ -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);
|
||||
}
|
||||
+44
-30
@@ -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();
|
||||
|
||||
+18
-41
@@ -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("<");
|
||||
|
||||
@@ -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) {}
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
package jet
|
||||
|
||||
public class Tuple0 private () {
|
||||
public class object {
|
||||
public val VALUE: Tuple0
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
|
||||
+8
-1
@@ -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());
|
||||
}
|
||||
}
|
||||
+10
-2
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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
Reference in New Issue
Block a user