diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/CallableMethod.java b/compiler/backend/src/org/jetbrains/jet/codegen/CallableMethod.java index 74a523bbe39..8f284c416fc 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/CallableMethod.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/CallableMethod.java @@ -81,9 +81,14 @@ public class CallableMethod implements Callable { public void invokeWithDefault(InstructionAdapter v, int mask) { v.iconst(mask); String desc = getSignature().getDescriptor().replace(")", "I)"); - if(getInvokeOpcode() != Opcodes.INVOKESTATIC) - desc = desc.replace("(", "(L" + getOwner() + ";"); - v.visitMethodInsn(Opcodes.INVOKESTATIC, getInvokeOpcode() == Opcodes.INVOKEINTERFACE ? getOwner() + "$$TImpl" : getOwner(), getSignature().getName() + "$default", desc); + if("".equals(getSignature().getName())) { + v.visitMethodInsn(Opcodes.INVOKESPECIAL, getOwner(), "", desc); + } + else { + if(getInvokeOpcode() != Opcodes.INVOKESTATIC) + desc = desc.replace("(", "(L" + getOwner() + ";"); + v.visitMethodInsn(Opcodes.INVOKESTATIC, getInvokeOpcode() == Opcodes.INVOKEINTERFACE ? getOwner() + "$$TImpl" : getOwner(), getSignature().getName() + "$default", desc); + } } public boolean isNeedsThis() { diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/CodegenContext.java b/compiler/backend/src/org/jetbrains/jet/codegen/CodegenContext.java index 11c1bf1c810..a5d3447e98c 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/CodegenContext.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/CodegenContext.java @@ -124,15 +124,17 @@ public abstract class CodegenContext { return new ClosureContext(funDescriptor, classDescriptor, this, closureCodegen, internalClassName); } - public FrameMap prepareFrame() { + public FrameMap prepareFrame(JetTypeMapper mapper) { FrameMap frameMap = new FrameMap(); if (getContextKind() != OwnerKind.NAMESPACE) { frameMap.enterTemp(); // 0 slot for this } - if (getReceiverDescriptor() != null) { - frameMap.enterTemp(); // Next slot for fake this + CallableDescriptor receiverDescriptor = getReceiverDescriptor(); + if (receiverDescriptor != null) { + Type type = mapper.mapType(receiverDescriptor.getReceiverParameter().getType()); + frameMap.enterTemp(type.getSize()); // Next slot for fake this } return frameMap; diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/FunctionCodegen.java b/compiler/backend/src/org/jetbrains/jet/codegen/FunctionCodegen.java index 27d971944dd..e730798fbee 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/FunctionCodegen.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/FunctionCodegen.java @@ -1,10 +1,12 @@ package org.jetbrains.jet.codegen; import com.intellij.psi.PsiElement; +import org.jetbrains.annotations.Nullable; import org.jetbrains.jet.lang.descriptors.*; import org.jetbrains.jet.lang.psi.*; import org.jetbrains.jet.lang.resolve.BindingContext; -import org.jetbrains.jet.resolve.DescriptorRenderer; +import org.jetbrains.jet.lang.resolve.DescriptorUtils; +import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor; import org.objectweb.asm.AnnotationVisitor; import org.objectweb.asm.Label; import org.objectweb.asm.MethodVisitor; @@ -26,17 +28,19 @@ public class FunctionCodegen { private final CodegenContext owner; private final ClassBuilder v; private final GenerationState state; + private final JetTypeMapper typeMapper; public FunctionCodegen(CodegenContext owner, ClassBuilder v, GenerationState state) { this.owner = owner; this.v = v; this.state = state; + typeMapper = state.getTypeMapper(); } public void gen(JetNamedFunction f) { final FunctionDescriptor functionDescriptor = state.getBindingContext().get(BindingContext.FUNCTION, f); assert functionDescriptor != null; - Method method = state.getTypeMapper().mapToCallableMethod(functionDescriptor, false, owner.getContextKind()).getSignature(); + Method method = typeMapper.mapToCallableMethod(functionDescriptor, false, owner.getContextKind()).getSignature(); generateMethod(f, method, functionDescriptor); } @@ -59,21 +63,57 @@ public class FunctionCodegen { OwnerKind kind = context.getContextKind(); + ReceiverDescriptor expectedThisObject = functionDescriptor.getExpectedThisObject(); + ReceiverDescriptor receiverParameter = functionDescriptor.getReceiverParameter(); + if (kind != OwnerKind.TRAIT_IMPL || bodyExpressions != null) { + boolean isStatic = kind == OwnerKind.NAMESPACE; + if (isStatic || kind == OwnerKind.TRAIT_IMPL) + flags |= ACC_STATIC; - boolean isStatic = kind == OwnerKind.NAMESPACE || kind == OwnerKind.TRAIT_IMPL; - if (isStatic) flags |= ACC_STATIC; - - boolean isAbstract = !isStatic && (bodyExpressions == null || CodegenUtil.isInterface(functionDescriptor.getContainingDeclaration())); + boolean isAbstract = !isStatic && !(kind == OwnerKind.TRAIT_IMPL) && (bodyExpressions == null || CodegenUtil.isInterface(functionDescriptor.getContainingDeclaration())); if (isAbstract) flags |= ACC_ABSTRACT; final MethodVisitor mv = v.newMethod(fun, flags, jvmSignature.getName(), jvmSignature.getDescriptor(), null, null); - if(kind != OwnerKind.TRAIT_IMPL && v.generateCode()) { - int start = functionDescriptor.getReceiverParameter().exists() ? 1 : 0; + if(v.generateCode()) { + int start = 0; + if(kind != OwnerKind.TRAIT_IMPL) { + AnnotationVisitor av = mv.visitAnnotation("Ljet/typeinfo/JetMethod;", true); + if(functionDescriptor.getReturnType().isNullable()) { + av.visit("nullableReturnType", true); + } + av.visitEnd(); + } + + if(kind == OwnerKind.TRAIT_IMPL) { + AnnotationVisitor av = mv.visitParameterAnnotation(start++, "Ljet/typeinfo/JetParameter;", true); + av.visit("value", "this$self"); + av.visitEnd(); + } + if(receiverParameter.exists()) { + AnnotationVisitor av = mv.visitParameterAnnotation(start++, "Ljet/typeinfo/JetParameter;", true); + av.visit("value", "this$receiver"); + if(receiverParameter.getType().isNullable()) { + av.visit("nullable", true); + } + av.visitEnd(); + } + for (final TypeParameterDescriptor typeParameterDescriptor : typeParameters) { + AnnotationVisitor av = mv.visitParameterAnnotation(start++, "Ljet/typeinfo/JetTypeParameter;", true); + av.visit("value", typeParameterDescriptor.getName()); + av.visitEnd(); + } for(int i = 0; i != paramDescrs.size(); ++i) { - AnnotationVisitor annotationVisitor = mv.visitParameterAnnotation(i + start, "Ljet/typeinfo/JetParameterName;", true); - annotationVisitor.visit("value", paramDescrs.get(i).getName()); - annotationVisitor.visitEnd(); + AnnotationVisitor av = mv.visitParameterAnnotation(i + start, "Ljet/typeinfo/JetParameter;", true); + ValueParameterDescriptor parameterDescriptor = paramDescrs.get(i); + av.visit("name", parameterDescriptor.getName()); + if(parameterDescriptor.hasDefaultValue()) { + av.visit("hasDefaultValue", true); + } + if(parameterDescriptor.getOutType().isNullable()) { + av.visit("nullable", true); + } + av.visitEnd(); } } if (!isAbstract && v.generateCode()) { @@ -82,12 +122,18 @@ public class FunctionCodegen { Label methodBegin = new Label(); mv.visitLabel(methodBegin); - FrameMap frameMap = context.prepareFrame(); + FrameMap frameMap = context.prepareFrame(typeMapper); ExpressionCodegen codegen = new ExpressionCodegen(mv, frameMap, jvmSignature.getReturnType(), context, state); Type[] argTypes = jvmSignature.getArgumentTypes(); - int add = functionDescriptor.getReceiverParameter().exists() ? state.getTypeMapper().mapType(functionDescriptor.getReceiverParameter().getType()).getSize() : 0; + int add = 0; + + if(kind == OwnerKind.TRAIT_IMPL) + add++; + + if(receiverParameter.exists()) + add++; for (final TypeParameterDescriptor typeParameterDescriptor : typeParameters) { int slot = frameMap.enterTemp(); @@ -114,9 +160,9 @@ public class FunctionCodegen { } else { for (ValueParameterDescriptor parameter : paramDescrs) { - Type sharedVarType = state.getTypeMapper().getSharedVarType(parameter); - Type localVarType = state.getTypeMapper().mapType(parameter.getOutType()); + Type sharedVarType = typeMapper.getSharedVarType(parameter); if (sharedVarType != null) { + Type localVarType = typeMapper.mapType(parameter.getOutType()); int index = frameMap.getIndex(parameter); mv.visitTypeInsn(NEW, sharedVarType.getInternalName()); mv.visitInsn(DUP); @@ -134,13 +180,30 @@ public class FunctionCodegen { Label methodEnd = new Label(); mv.visitLabel(methodEnd); - // http://youtrack.jetbrains.net/issue/KT-746 - // Fill LocalVariableTable with method parameter names - for (int i = 0; i < paramDescrs.size(); i++) { - ValueParameterDescriptor parameter = paramDescrs.get(i); - Type type = state.getTypeMapper().mapType(parameter.getOutType()); + int k = 0; + + if(expectedThisObject.exists()) { + Type type = typeMapper.mapType(expectedThisObject.getType()); // TODO: specify signature - mv.visitLocalVariable(parameter.getName(), type.getDescriptor(), null, methodBegin, methodEnd, i + add); + mv.visitLocalVariable("this", type.getDescriptor(), null, methodBegin, methodEnd, k++); + } + + if(receiverParameter.exists()) { + Type type = typeMapper.mapType(receiverParameter.getType()); + // TODO: specify signature + mv.visitLocalVariable("this$receiver", type.getDescriptor(), null, methodBegin, methodEnd, k); + k += type.getSize(); + } + + for (final TypeParameterDescriptor typeParameterDescriptor : typeParameters) { + mv.visitLocalVariable(typeParameterDescriptor.getName(), JetTypeMapper.TYPE_TYPEINFO.getDescriptor(), null, methodBegin, methodEnd, k++); + } + + for (ValueParameterDescriptor parameter : paramDescrs) { + Type type = typeMapper.mapType(parameter.getOutType()); + // TODO: specify signature + mv.visitLocalVariable(parameter.getName(), type.getDescriptor(), null, methodBegin, methodEnd, k); + k += type.getSize(); } mv.visitMaxs(0, 0); @@ -164,7 +227,7 @@ public class FunctionCodegen { } } - static void generateDefaultIfNeeded(CodegenContext.MethodContext owner, GenerationState state, ClassBuilder v, Method jvmSignature, FunctionDescriptor functionDescriptor, OwnerKind kind) { + static void generateDefaultIfNeeded(CodegenContext.MethodContext owner, GenerationState state, ClassBuilder v, Method jvmSignature, @Nullable FunctionDescriptor functionDescriptor, OwnerKind kind) { DeclarationDescriptor contextClass = owner.getContextDescriptor().getContainingDeclaration(); if(kind != OwnerKind.TRAIT_IMPL) { @@ -180,15 +243,18 @@ public class FunctionCodegen { } boolean needed = false; - for (ValueParameterDescriptor parameterDescriptor : functionDescriptor.getValueParameters()) { - if(parameterDescriptor.hasDefaultValue()) { - needed = true; - break; + if(functionDescriptor != null) { + for (ValueParameterDescriptor parameterDescriptor : functionDescriptor.getValueParameters()) { + if(parameterDescriptor.hasDefaultValue()) { + needed = true; + break; + } } } if(needed) { - boolean hasReceiver = functionDescriptor.getReceiverParameter().exists(); + ReceiverDescriptor receiverParameter = functionDescriptor.getReceiverParameter(); + boolean hasReceiver = receiverParameter.exists(); boolean isStatic = kind == OwnerKind.NAMESPACE; if(kind == OwnerKind.TRAIT_IMPL) { @@ -199,50 +265,46 @@ public class FunctionCodegen { int flags = ACC_PUBLIC; // TODO. String ownerInternalName = contextClass instanceof NamespaceDescriptor ? - NamespaceCodegen.getJVMClassName(DescriptorRenderer.getFQName(contextClass)) : + NamespaceCodegen.getJVMClassName(DescriptorUtils.getFQName(contextClass)) : state.getTypeMapper().mapType(((ClassDescriptor) contextClass).getDefaultType(), OwnerKind.IMPLEMENTATION).getInternalName(); String descriptor = jvmSignature.getDescriptor().replace(")","I)"); - if(!isStatic) + boolean isConstructor = "".equals(jvmSignature.getName()); + if(!isStatic && !isConstructor) descriptor = descriptor.replace("(","(L" + ownerInternalName + ";"); - final MethodVisitor mv = v.newMethod(null, flags | ACC_STATIC, jvmSignature.getName() + "$default", descriptor, null, null); + final MethodVisitor mv = v.newMethod(null, flags | (isConstructor ? 0 : ACC_STATIC), isConstructor ? "" : jvmSignature.getName() + "$default", descriptor, null, null); InstructionAdapter iv = new InstructionAdapter(mv); if (v.generateCode()) { mv.visitCode(); - FrameMap frameMap = owner.prepareFrame(); + FrameMap frameMap = owner.prepareFrame(state.getTypeMapper()); ExpressionCodegen codegen = new ExpressionCodegen(mv, frameMap, jvmSignature.getReturnType(), owner, state); int var = 0; if(!isStatic) { - frameMap.enterTemp(); var++; } + Type receiverType = receiverParameter.exists() ? state.getTypeMapper().mapType(receiverParameter.getType()) : Type.DOUBLE_TYPE; if(hasReceiver) { - frameMap.enterTemp(); - var++; + var += receiverType.getSize(); } List typeParameters = functionDescriptor.getTypeParameters(); for (final TypeParameterDescriptor typeParameterDescriptor : typeParameters) { - int slot = frameMap.enterTemp(); - codegen.addTypeParameter(typeParameterDescriptor, StackValue.local(slot, JetTypeMapper.TYPE_TYPEINFO)); - var++; + if(typeParameterDescriptor.isReified()) { + codegen.addTypeParameter(typeParameterDescriptor, StackValue.local(var++, JetTypeMapper.TYPE_TYPEINFO)); + } } Type[] argTypes = jvmSignature.getArgumentTypes(); List paramDescrs = functionDescriptor.getValueParameters(); for (int i = 0; i < paramDescrs.size(); i++) { - ValueParameterDescriptor parameter = paramDescrs.get(i); int size = argTypes[i + (hasReceiver ? 1 : 0)].getSize(); var += size; - frameMap.enter(parameter, size); } - frameMap.enterTemp(); - int maskIndex = var; var = 0; @@ -251,7 +313,8 @@ public class FunctionCodegen { } if(hasReceiver) { - mv.visitVarInsn(ALOAD, var++); // todo - Long etc. + iv.load(var, receiverType); + var += receiverType.getSize(); } int extra = hasReceiver ? 1 : 0; diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/GenerationState.java b/compiler/backend/src/org/jetbrains/jet/codegen/GenerationState.java index e1a163ccd5d..2a3c0d45b67 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/GenerationState.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/GenerationState.java @@ -15,7 +15,7 @@ import org.jetbrains.jet.lang.diagnostics.DiagnosticUtils; import org.jetbrains.jet.lang.psi.*; import org.jetbrains.jet.lang.resolve.AnalyzingUtils; import org.jetbrains.jet.lang.resolve.BindingContext; -import org.jetbrains.jet.lang.resolve.java.JavaDefaultImports; +import org.jetbrains.jet.lang.resolve.java.AnalyzerFacade; import org.jetbrains.jet.lang.types.JetStandardLibrary; import java.util.Collections; @@ -84,7 +84,7 @@ public class GenerationState { public void compile(JetFile psiFile) { final JetNamespace namespace = psiFile.getRootNamespace(); - final BindingContext bindingContext = AnalyzingUtils.getInstance(JavaDefaultImports.JAVA_DEFAULT_IMPORTS).analyzeNamespace(namespace, JetControlFlowDataTraceFactory.EMPTY); + final BindingContext bindingContext = AnalyzerFacade.analyzeOneNamespaceWithJavaIntegration(namespace, JetControlFlowDataTraceFactory.EMPTY); AnalyzingUtils.throwExceptionOnErrors(bindingContext); compileCorrectNamespaces(bindingContext, Collections.singletonList(namespace)); // NamespaceCodegen codegen = forNamespace(namespace); diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/ImplementationBodyCodegen.java b/compiler/backend/src/org/jetbrains/jet/codegen/ImplementationBodyCodegen.java index c3fe305c016..d9a6678e5f2 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/ImplementationBodyCodegen.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/ImplementationBodyCodegen.java @@ -269,7 +269,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen { CodegenContext.ConstructorContext constructorContext = context.intoConstructor(constructorDescriptor); - Method method; + Method constructorMethod; CallableMethod callableMethod; if (constructorDescriptor == null) { List parameterTypes = new ArrayList(); @@ -282,17 +282,17 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen { parameterTypes.add(JetTypeMapper.TYPE_TYPEINFO); } - method = new Method("", Type.VOID_TYPE, parameterTypes.toArray(new Type[parameterTypes.size()])); - callableMethod = new CallableMethod("", method, Opcodes.INVOKESPECIAL, Collections.emptyList()); + constructorMethod = new Method("", Type.VOID_TYPE, parameterTypes.toArray(new Type[parameterTypes.size()])); + callableMethod = new CallableMethod("", constructorMethod, Opcodes.INVOKESPECIAL, Collections.emptyList()); } else { callableMethod = typeMapper.mapToCallableMethod(constructorDescriptor, kind); - method = callableMethod.getSignature(); + constructorMethod = callableMethod.getSignature(); } ObjectOrClosureCodegen closure = context.closure; if(closure != null) { - final List consArgTypes = new LinkedList(Arrays.asList(method.getArgumentTypes())); + final List consArgTypes = new LinkedList(Arrays.asList(constructorMethod.getArgumentTypes())); int insert = 0; if(closure.captureThis) { @@ -319,11 +319,11 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen { } } - method = new Method("", Type.VOID_TYPE, consArgTypes.toArray(new Type[consArgTypes.size()])); + constructorMethod = new Method("", Type.VOID_TYPE, consArgTypes.toArray(new Type[consArgTypes.size()])); } int flags = Opcodes.ACC_PUBLIC; // TODO - final MethodVisitor mv = v.newMethod(myClass, flags, "", method.getDescriptor(), null, null); + final MethodVisitor mv = v.newMethod(myClass, flags, "", constructorMethod.getDescriptor(), null, null); if (!v.generateCode()) return; mv.visitCode(); @@ -470,6 +470,8 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen { mv.visitInsn(Opcodes.RETURN); mv.visitMaxs(0, 0); mv.visitEnd(); + + FunctionCodegen.generateDefaultIfNeeded(constructorContext, state, v, constructorMethod, constructorDescriptor, OwnerKind.IMPLEMENTATION ); } private void generateTraitMethods(ExpressionCodegen codegen) { diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/JetTypeMapper.java b/compiler/backend/src/org/jetbrains/jet/codegen/JetTypeMapper.java index 5649fe11f01..da8f91a181f 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/JetTypeMapper.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/JetTypeMapper.java @@ -8,12 +8,12 @@ import org.jetbrains.annotations.NotNull; 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.java.JavaDescriptorResolver; import org.jetbrains.jet.lang.resolve.java.JavaNamespaceDescriptor; import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor; import org.jetbrains.jet.lang.types.*; import org.jetbrains.jet.lexer.JetTokens; -import org.jetbrains.jet.resolve.DescriptorRenderer; import org.objectweb.asm.Opcodes; import org.objectweb.asm.Type; import org.objectweb.asm.commons.Method; @@ -130,7 +130,7 @@ public class JetTypeMapper { String owner; DeclarationDescriptor containingDeclaration = descriptor.getContainingDeclaration(); if (containingDeclaration instanceof NamespaceDescriptor) { - owner = NamespaceCodegen.getJVMClassName(DescriptorRenderer.getFQName((NamespaceDescriptor) containingDeclaration)); + owner = NamespaceCodegen.getJVMClassName(DescriptorUtils.getFQName((NamespaceDescriptor) containingDeclaration)); } else if (containingDeclaration instanceof ClassDescriptor) { ClassDescriptor classDescriptor = (ClassDescriptor) containingDeclaration; @@ -305,7 +305,7 @@ public class JetTypeMapper { ClassDescriptor thisClass; if (functionParent instanceof NamespaceDescriptor) { assert !superCall; - owner = NamespaceCodegen.getJVMClassName(DescriptorRenderer.getFQName(functionParent)); + owner = NamespaceCodegen.getJVMClassName(DescriptorUtils.getFQName(functionParent)); invokeOpcode = INVOKESTATIC; thisClass = null; } @@ -348,9 +348,6 @@ public class JetTypeMapper { final JetType receiverType = !receiverTypeRef.exists() ? null : receiverTypeRef.getType(); final List parameters = f.getValueParameters(); List parameterTypes = new ArrayList(); - if (receiverType != null) { - parameterTypes.add(mapType(receiverType)); - } if(kind == OwnerKind.TRAIT_IMPL) { ClassDescriptor containingDeclaration = (ClassDescriptor) f.getContainingDeclaration(); JetType jetType = TraitImplBodyCodegen.getSuperClass(containingDeclaration, bindingContext); @@ -362,6 +359,9 @@ public class JetTypeMapper { valueParameterTypes.add(type); parameterTypes.add(type); } + if (receiverType != null) { + parameterTypes.add(mapType(receiverType)); + } for (TypeParameterDescriptor parameterDescriptor : f.getTypeParameters()) { if(parameterDescriptor.isReified()) { parameterTypes.add(TYPE_TYPEINFO); diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/SignatureUtil.java b/compiler/backend/src/org/jetbrains/jet/codegen/SignatureUtil.java index 2bcfbc5804d..72d2ae08868 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/SignatureUtil.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/SignatureUtil.java @@ -10,6 +10,7 @@ import org.jetbrains.jet.lang.resolve.BindingContext; import org.jetbrains.jet.lang.types.JetType; import org.jetbrains.jet.lang.types.TypeProjection; import org.jetbrains.jet.lang.types.Variance; +import org.objectweb.asm.Type; import java.util.List; @@ -17,6 +18,9 @@ import java.util.List; * @author alex.tkachman */ public class SignatureUtil { + private SignatureUtil() { + } + public static String classToSignature(JetClass type, BindingContext bindingContext, JetTypeMapper typeMapper) { StringBuilder sb = new StringBuilder(); genTypeParams(type, sb); @@ -33,7 +37,7 @@ public class SignatureUtil { DeclarationDescriptor descriptor = jetType.getConstructor().getDeclarationDescriptor(); if(descriptor instanceof ClassDescriptor) { JetType defaultType = ((ClassDescriptor) descriptor).getDefaultType(); - org.objectweb.asm.Type type = typeMapper.mapType(defaultType, OwnerKind.IMPLEMENTATION); + Type type = typeMapper.mapType(defaultType, OwnerKind.IMPLEMENTATION); if(JetTypeMapper.isPrimitive(type)) { type = JetTypeMapper.boxType(type); } diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/intrinsics/BinaryOp.java b/compiler/backend/src/org/jetbrains/jet/codegen/intrinsics/BinaryOp.java index e813857f0de..1255b108ef2 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/intrinsics/BinaryOp.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/intrinsics/BinaryOp.java @@ -5,6 +5,7 @@ import org.jetbrains.jet.codegen.ExpressionCodegen; import org.jetbrains.jet.codegen.JetTypeMapper; import org.jetbrains.jet.codegen.StackValue; import org.jetbrains.jet.lang.psi.JetExpression; +import org.objectweb.asm.Opcodes; import org.objectweb.asm.Type; import org.objectweb.asm.commons.InstructionAdapter; @@ -31,11 +32,11 @@ public class BinaryOp implements IntrinsicMethod { if (receiver != null) { receiver.put(expectedType, v); } - codegen.gen(arguments.get(0), expectedType); + codegen.gen(arguments.get(0), shift() ? Type.INT_TYPE : expectedType); } else { codegen.gen(arguments.get(0), expectedType); - codegen.gen(arguments.get(1), expectedType); + codegen.gen(arguments.get(1), shift() ? Type.INT_TYPE : expectedType); } v.visitInsn(expectedType.getOpcode(opcode)); @@ -44,4 +45,8 @@ public class BinaryOp implements IntrinsicMethod { } return StackValue.onStack(expectedType); } + + private boolean shift() { + return opcode == Opcodes.ISHL || opcode == Opcodes.ISHR || opcode == Opcodes.IUSHR; + } } diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/intrinsics/Increment.java b/compiler/backend/src/org/jetbrains/jet/codegen/intrinsics/Increment.java index a53c8791f80..d140d937507 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/intrinsics/Increment.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/intrinsics/Increment.java @@ -24,20 +24,38 @@ public class Increment implements IntrinsicMethod { @Override public StackValue generate(ExpressionCodegen codegen, InstructionAdapter v, Type expectedType, PsiElement element, List arguments, StackValue receiver) { - JetExpression operand = arguments.get(0); - while(operand instanceof JetParenthesizedExpression) { - operand = ((JetParenthesizedExpression)operand).getExpression(); + boolean nullable = expectedType.getSort() == Type.OBJECT; + if(nullable) { + expectedType = JetTypeMapper.unboxType(expectedType); } - if (operand instanceof JetReferenceExpression) { - final int index = codegen.indexOfLocal((JetReferenceExpression) operand); - if (index >= 0 && JetTypeMapper.isIntPrimitive(expectedType)) { - return StackValue.preIncrement(index, myDelta); + if(arguments.size() > 0) { + JetExpression operand = arguments.get(0); + while(operand instanceof JetParenthesizedExpression) { + operand = ((JetParenthesizedExpression)operand).getExpression(); } + if (operand instanceof JetReferenceExpression) { + final int index = codegen.indexOfLocal((JetReferenceExpression) operand); + if (index >= 0 && JetTypeMapper.isIntPrimitive(expectedType)) { + return StackValue.preIncrement(index, myDelta); + } + } + StackValue value = codegen.genQualified(receiver, operand); + value. dupReceiver(v); + value. dupReceiver(v); + + value.put(expectedType, v); + plusMinus(v, expectedType); + value.store(v); + value.put(expectedType, v); } - StackValue value = codegen.genQualified(receiver, operand); - value. dupReceiver(v); - value. dupReceiver(v); - value.put(expectedType, v); + else { + receiver.put(expectedType, v); + plusMinus(v, expectedType); + } + return StackValue.onStack(expectedType); + } + + private void plusMinus(InstructionAdapter v, Type expectedType) { if (expectedType == Type.LONG_TYPE) { v.lconst(myDelta); } @@ -51,8 +69,5 @@ public class Increment implements IntrinsicMethod { v.iconst(myDelta); } v.add(expectedType); - value.store(v); - value.put(expectedType, v); - return StackValue.onStack(expectedType); } } diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/intrinsics/IntrinsicMethods.java b/compiler/backend/src/org/jetbrains/jet/codegen/intrinsics/IntrinsicMethods.java index 6ccff8d02b3..79374780086 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/intrinsics/IntrinsicMethods.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/intrinsics/IntrinsicMethods.java @@ -23,6 +23,7 @@ import java.util.*; */ public class IntrinsicMethods { private static final IntrinsicMethod UNARY_MINUS = new UnaryMinus(); + private static final IntrinsicMethod UNARY_PLUS = new UnaryPlus(); private static final IntrinsicMethod NUMBER_CAST = new NumberCast(); private static final IntrinsicMethod INV = new Inv(); private static final IntrinsicMethod TYPEINFO = new TypeInfo(); @@ -53,6 +54,7 @@ public class IntrinsicMethods { } for (String type : PRIMITIVE_NUMBER_TYPES) { + declareIntrinsicFunction(type, "plus", 0, UNARY_PLUS); declareIntrinsicFunction(type, "minus", 0, UNARY_MINUS); declareIntrinsicFunction(type, "inv", 0, INV); declareIntrinsicFunction(type, "rangeTo", 1, RANGE_TO); diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/intrinsics/Inv.java b/compiler/backend/src/org/jetbrains/jet/codegen/intrinsics/Inv.java index fd6a663f964..b4b1e287310 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/intrinsics/Inv.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/intrinsics/Inv.java @@ -2,6 +2,7 @@ package org.jetbrains.jet.codegen.intrinsics; import com.intellij.psi.PsiElement; import org.jetbrains.jet.codegen.ExpressionCodegen; +import org.jetbrains.jet.codegen.JetTypeMapper; import org.jetbrains.jet.codegen.StackValue; import org.jetbrains.jet.lang.psi.JetExpression; import org.objectweb.asm.Type; @@ -11,12 +12,22 @@ import java.util.List; /** * @author yole + * @author alex.tkachman */ public class Inv implements IntrinsicMethod { @Override public StackValue generate(ExpressionCodegen codegen, InstructionAdapter v, Type expectedType, PsiElement element, List arguments, StackValue receiver) { + boolean nullable = expectedType.getSort() == Type.OBJECT; + if(nullable) { + expectedType = JetTypeMapper.unboxType(expectedType); + } receiver.put(expectedType, v); - v.iconst(-1); + if(expectedType == Type.LONG_TYPE) { + v.lconst(-1L); + } + else { + v.iconst(-1); + } v.xor(expectedType); return StackValue.onStack(expectedType); } diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/intrinsics/RangeTo.java b/compiler/backend/src/org/jetbrains/jet/codegen/intrinsics/RangeTo.java index 86850d21051..ac46bd31b60 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/intrinsics/RangeTo.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/intrinsics/RangeTo.java @@ -18,16 +18,24 @@ import java.util.List; public class RangeTo implements IntrinsicMethod { @Override public StackValue generate(ExpressionCodegen codegen, InstructionAdapter v, Type expectedType, PsiElement element, List arguments, StackValue receiver) { - JetBinaryExpression expression = (JetBinaryExpression) element; - final Type leftType = codegen.expressionType(expression.getLeft()); - if (JetTypeMapper.isIntPrimitive(leftType)) { - codegen.gen(expression.getLeft(), Type.INT_TYPE); - codegen.gen(expression.getRight(), Type.INT_TYPE); + if(arguments.size()==1) { + receiver.put(Type.INT_TYPE, v); + codegen.gen(arguments.get(0), Type.INT_TYPE); v.invokestatic("jet/IntRange", "rangeTo", "(II)Ljet/IntRange;"); return StackValue.onStack(JetTypeMapper.TYPE_INT_RANGE); } else { - throw new UnsupportedOperationException("ranges are only supported for int objects"); + JetBinaryExpression expression = (JetBinaryExpression) element; + final Type leftType = codegen.expressionType(expression.getLeft()); + if (JetTypeMapper.isIntPrimitive(leftType)) { + codegen.gen(expression.getLeft(), Type.INT_TYPE); + codegen.gen(expression.getRight(), Type.INT_TYPE); + v.invokestatic("jet/IntRange", "rangeTo", "(II)Ljet/IntRange;"); + return StackValue.onStack(JetTypeMapper.TYPE_INT_RANGE); + } + else { + throw new UnsupportedOperationException("ranges are only supported for int objects"); + } } } } diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/intrinsics/UnaryMinus.java b/compiler/backend/src/org/jetbrains/jet/codegen/intrinsics/UnaryMinus.java index b84d3f79fdf..4eb8ecb4d20 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/intrinsics/UnaryMinus.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/intrinsics/UnaryMinus.java @@ -2,6 +2,7 @@ package org.jetbrains.jet.codegen.intrinsics; import com.intellij.psi.PsiElement; import org.jetbrains.jet.codegen.ExpressionCodegen; +import org.jetbrains.jet.codegen.JetTypeMapper; import org.jetbrains.jet.codegen.StackValue; import org.jetbrains.jet.lang.psi.JetExpression; import org.objectweb.asm.Type; @@ -15,6 +16,10 @@ import java.util.List; public class UnaryMinus implements IntrinsicMethod { @Override public StackValue generate(ExpressionCodegen codegen, InstructionAdapter v, Type expectedType, PsiElement element, List arguments, StackValue receiver) { + boolean nullable = expectedType.getSort() == Type.OBJECT; + if(nullable) { + expectedType = JetTypeMapper.unboxType(expectedType); + } if (arguments.size() == 1) { codegen.gen(arguments.get(0), expectedType); } diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/intrinsics/UnaryPlus.java b/compiler/backend/src/org/jetbrains/jet/codegen/intrinsics/UnaryPlus.java new file mode 100644 index 00000000000..2405ef3d8aa --- /dev/null +++ b/compiler/backend/src/org/jetbrains/jet/codegen/intrinsics/UnaryPlus.java @@ -0,0 +1,27 @@ +package org.jetbrains.jet.codegen.intrinsics; + +import com.intellij.psi.PsiElement; +import org.jetbrains.annotations.Nullable; +import org.jetbrains.jet.codegen.ExpressionCodegen; +import org.jetbrains.jet.codegen.JetTypeMapper; +import org.jetbrains.jet.codegen.StackValue; +import org.jetbrains.jet.lang.psi.JetExpression; +import org.objectweb.asm.Type; +import org.objectweb.asm.commons.InstructionAdapter; + +import java.util.List; + +/** + * @author alex.tkachman + */ +public class UnaryPlus implements IntrinsicMethod { + @Override + public StackValue generate(ExpressionCodegen codegen, InstructionAdapter v, Type expectedType, @Nullable PsiElement element, @Nullable List arguments, StackValue receiver) { + boolean nullable = expectedType.getSort() == Type.OBJECT; + if(nullable) { + expectedType = JetTypeMapper.unboxType(expectedType); + } + receiver.put(expectedType, v); + return StackValue.onStack(expectedType); + } +} diff --git a/compiler/backend/src/org/jetbrains/jet/compiler/CompileSession.java b/compiler/backend/src/org/jetbrains/jet/compiler/CompileSession.java index 91a0dccaf9e..f35ee3b07fe 100644 --- a/compiler/backend/src/org/jetbrains/jet/compiler/CompileSession.java +++ b/compiler/backend/src/org/jetbrains/jet/compiler/CompileSession.java @@ -11,9 +11,8 @@ import org.jetbrains.jet.codegen.GenerationState; import org.jetbrains.jet.lang.cfg.pseudocode.JetControlFlowDataTraceFactory; import org.jetbrains.jet.lang.psi.JetFile; import org.jetbrains.jet.lang.psi.JetNamespace; -import org.jetbrains.jet.lang.resolve.AnalyzingUtils; import org.jetbrains.jet.lang.resolve.BindingContext; -import org.jetbrains.jet.lang.resolve.java.JavaDefaultImports; +import org.jetbrains.jet.lang.resolve.java.AnalyzerFacade; import org.jetbrains.jet.plugin.JetFileType; import java.io.File; @@ -93,10 +92,10 @@ public class CompileSession { } return false; } - final AnalyzingUtils instance = AnalyzingUtils.getInstance(JavaDefaultImports.JAVA_DEFAULT_IMPORTS); List allNamespaces = new ArrayList(mySourceFileNamespaces); allNamespaces.addAll(myLibrarySourceFileNamespaces); - myBindingContext = instance.analyzeNamespaces(myEnvironment.getProject(), allNamespaces, Predicates.alwaysTrue(), JetControlFlowDataTraceFactory.EMPTY); + myBindingContext = AnalyzerFacade.analyzeNamespacesWithJavaIntegration( + myEnvironment.getProject(), allNamespaces, Predicates.alwaysTrue(), JetControlFlowDataTraceFactory.EMPTY); ErrorCollector errorCollector = new ErrorCollector(myBindingContext); errorCollector.report(out); return !errorCollector.hasErrors; diff --git a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/AnalyzerFacade.java b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/AnalyzerFacade.java index ad4e1f20d74..e21ac04214f 100644 --- a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/AnalyzerFacade.java +++ b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/AnalyzerFacade.java @@ -1,7 +1,9 @@ package org.jetbrains.jet.lang.resolve.java; +import com.google.common.base.Predicate; import com.google.common.base.Predicates; import com.intellij.openapi.progress.ProcessCanceledException; +import com.intellij.openapi.project.Project; import com.intellij.openapi.util.Key; import com.intellij.psi.PsiFile; import com.intellij.psi.util.CachedValue; @@ -20,8 +22,10 @@ import org.jetbrains.jet.lang.resolve.AnalyzingUtils; import org.jetbrains.jet.lang.resolve.BindingContext; import org.jetbrains.jet.lang.resolve.BindingTraceContext; +import java.util.ArrayList; import java.util.Collection; import java.util.Collections; +import java.util.List; /** * @author abreslav @@ -34,22 +38,11 @@ public class AnalyzerFacade { return Collections.singleton(file.getRootNamespace()); } }; - - private static final AnalyzingUtils ANALYZING_UTILS = AnalyzingUtils.getInstance(JavaDefaultImports.JAVA_DEFAULT_IMPORTS); + private final static Key> BINDING_CONTEXT = Key.create("BINDING_CONTEXT"); private static final Object lock = new Object(); - public static BindingContext analyzeNamespace(@NotNull JetNamespace namespace, @NotNull JetControlFlowDataTraceFactory flowDataTraceFactory) { - return ANALYZING_UTILS.analyzeNamespace(namespace, flowDataTraceFactory); - } - public static BindingContext analyzeFileWithCache(@NotNull final JetFile file, @NotNull final Function> declarationProvider) { - return analyzeFileWithCache(ANALYZING_UTILS, file, declarationProvider); - } - - public static BindingContext analyzeFileWithCache(@NotNull final AnalyzingUtils analyzingUtils, - @NotNull final JetFile file, - @NotNull final Function> declarationProvider) { // TODO : Synchronization? CachedValue bindingContextCachedValue = file.getUserData(BINDING_CONTEXT); if (bindingContextCachedValue == null) { @@ -58,11 +51,7 @@ public class AnalyzerFacade { public Result compute() { synchronized (lock) { try { - BindingContext bindingContext = analyzingUtils.analyzeNamespaces( - file.getProject(), - declarationProvider.fun(file), - Predicates.equalTo(file), - JetControlFlowDataTraceFactory.EMPTY); + BindingContext bindingContext = analyzeNamespacesWithJavaIntegration(file.getProject(), declarationProvider.fun(file), Predicates.equalTo(file), JetControlFlowDataTraceFactory.EMPTY); return new Result(bindingContext, PsiModificationTracker.MODIFICATION_COUNT); } catch (ProcessCanceledException e) { @@ -84,4 +73,39 @@ public class AnalyzerFacade { } return bindingContextCachedValue.getValue(); } + + public static BindingContext analyzeOneNamespaceWithJavaIntegration(JetNamespace namespace, JetControlFlowDataTraceFactory flowDataTraceFactory) { + return analyzeNamespacesWithJavaIntegration(namespace.getProject(), Collections.singleton(namespace), Predicates.alwaysTrue(), flowDataTraceFactory); + } + + public static BindingContext analyzeNamespacesWithJavaIntegration(Project project, Collection declarations, Predicate filesToAnalyzeCompletely, JetControlFlowDataTraceFactory flowDataTraceFactory) { + BindingTraceContext bindingTraceContext = new BindingTraceContext(); + return AnalyzingUtils.getInstance().analyzeNamespacesWithGivenTrace( + project, + JavaBridgeConfiguration.createJavaBridgeConfiguration(project, bindingTraceContext), + declarations, + filesToAnalyzeCompletely, + flowDataTraceFactory, bindingTraceContext); + } + + public static BindingContext shallowAnalyzeFiles(Collection files) { + assert files.size() > 0; + + Project project = files.iterator().next().getProject(); + + Collection namespaces = collectRootNamespaces(files); + + return analyzeNamespacesWithJavaIntegration(project, namespaces, Predicates.alwaysFalse(), JetControlFlowDataTraceFactory.EMPTY); + } + + public static List collectRootNamespaces(Collection files) { + List namespaces = new ArrayList(); + + for (PsiFile file : files) { + if (file instanceof JetFile) { + namespaces.add(((JetFile) file).getRootNamespace()); + } + } + return namespaces; + } } diff --git a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/JavaBridgeConfiguration.java b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/JavaBridgeConfiguration.java new file mode 100644 index 00000000000..a160b707229 --- /dev/null +++ b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/JavaBridgeConfiguration.java @@ -0,0 +1,37 @@ +package org.jetbrains.jet.lang.resolve.java; + +import com.intellij.openapi.project.Project; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.jet.lang.Configuration; +import org.jetbrains.jet.lang.JetSemanticServices; +import org.jetbrains.jet.lang.descriptors.NamespaceDescriptor; +import org.jetbrains.jet.lang.resolve.BindingTrace; +import org.jetbrains.jet.lang.resolve.DescriptorUtils; +import org.jetbrains.jet.lang.resolve.scopes.WritableScope; + +/** + * @author abreslav + */ +public class JavaBridgeConfiguration implements Configuration { + + public static Configuration createJavaBridgeConfiguration(@NotNull Project project, @NotNull BindingTrace trace) { + return new JavaBridgeConfiguration(project, trace); + } + + private final JavaSemanticServices javaSemanticServices; + + private JavaBridgeConfiguration(Project project, BindingTrace trace) { + this.javaSemanticServices = new JavaSemanticServices(project, JetSemanticServices.createSemanticServices(project), trace); + } + + @Override + public void addDefaultImports(BindingTrace trace, WritableScope rootScope) { + rootScope.importScope(new JavaPackageScope("", null, javaSemanticServices)); + rootScope.importScope(new JavaPackageScope("java.lang", null, javaSemanticServices)); + } + + @Override + public void extendNamespaceScope(BindingTrace trace, @NotNull NamespaceDescriptor namespaceDescriptor, @NotNull WritableScope namespaceMemberScope) { + namespaceMemberScope.importScope(new JavaPackageScope(DescriptorUtils.getFQName(namespaceDescriptor), namespaceDescriptor, javaSemanticServices)); + } +} diff --git a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/JavaDefaultImports.java b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/JavaDefaultImports.java deleted file mode 100644 index 24d820330e6..00000000000 --- a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/JavaDefaultImports.java +++ /dev/null @@ -1,24 +0,0 @@ -package org.jetbrains.jet.lang.resolve.java; - -import com.intellij.openapi.project.Project; -import org.jetbrains.jet.lang.JetSemanticServices; -import org.jetbrains.jet.lang.resolve.BindingTrace; -import org.jetbrains.jet.lang.resolve.ImportingStrategy; -import org.jetbrains.jet.lang.resolve.scopes.WritableScope; - -/** - * @author abreslav - */ -public class JavaDefaultImports { - public static final ImportingStrategy JAVA_DEFAULT_IMPORTS = new ImportingStrategy() { - @Override - public void addImports(Project project, JetSemanticServices semanticServices, BindingTrace trace, WritableScope rootScope) { - JavaSemanticServices javaSemanticServices = new JavaSemanticServices(project, semanticServices, trace); - rootScope.importScope(new JavaPackageScope("", null, javaSemanticServices)); - rootScope.importScope(new JavaPackageScope("java.lang", null, javaSemanticServices)); - } - }; - - private JavaDefaultImports() { - } -} diff --git a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/JavaDescriptorResolver.java b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/JavaDescriptorResolver.java index 0aca34c7176..f37b2993d9a 100644 --- a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/JavaDescriptorResolver.java +++ b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/JavaDescriptorResolver.java @@ -13,7 +13,6 @@ 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.BindingContext; -import org.jetbrains.jet.lang.resolve.BindingTrace; import org.jetbrains.jet.lang.resolve.DescriptorUtils; import org.jetbrains.jet.lang.types.*; import org.jetbrains.jet.plugin.JetFileType; @@ -53,7 +52,7 @@ public class JavaDescriptorResolver { } }; - protected final Map classDescriptorCache = new HashMap(); + protected final Map classDescriptorCache = Maps.newHashMap(); protected final Map typeParameterDescriptorCache = Maps.newHashMap(); protected final Map methodDescriptorCache = Maps.newHashMap(); protected final Map fieldDescriptorCache = Maps.newHashMap(); @@ -122,7 +121,7 @@ public class JavaDescriptorResolver { psiClass.hasModifierProperty(PsiModifier.ABSTRACT) || psiClass.isInterface(), !psiClass.hasModifierProperty(PsiModifier.FINAL)) ); - classDescriptor.setVisibility(resolveVisibilityFromPsiModifiers(semanticServices.getTrace(), psiClass)); + classDescriptor.setVisibility(resolveVisibilityFromPsiModifiers(psiClass)); classDescriptorCache.put(psiClass.getQualifiedName(), classDescriptor); classDescriptor.setUnsubstitutedMemberScope(new JavaClassMembersScope(classDescriptor, psiClass, semanticServices, false)); @@ -163,7 +162,7 @@ public class JavaDescriptorResolver { Collections.emptyList(), // TODO false); constructorDescriptor.initialize(typeParameters, resolveParameterDescriptors(constructorDescriptor, constructor.getParameterList().getParameters()), Modality.FINAL, - resolveVisibilityFromPsiModifiers(semanticServices.getTrace(), constructor)); + resolveVisibilityFromPsiModifiers(constructor)); constructorDescriptor.setReturnType(classDescriptor.getDefaultType()); classDescriptor.addConstructor(constructorDescriptor); semanticServices.getTrace().record(BindingContext.CONSTRUCTOR, constructor, constructorDescriptor); @@ -368,7 +367,7 @@ public class JavaDescriptorResolver { containingDeclaration, Collections.emptyList(), Modality.FINAL, - resolveVisibilityFromPsiModifiers(semanticServices.getTrace(), field), + resolveVisibilityFromPsiModifiers(field), !isFinal, null, DescriptorUtils.getExpectedThisObjectIfNeeded(containingDeclaration), @@ -454,7 +453,7 @@ public class JavaDescriptorResolver { semanticServices.getDescriptorResolver().resolveParameterDescriptors(functionDescriptorImpl, parameters), semanticServices.getTypeTransformer().transformToType(returnType), Modality.convertFromFlags(method.hasModifierProperty(PsiModifier.ABSTRACT), !method.hasModifierProperty(PsiModifier.FINAL)), - resolveVisibilityFromPsiModifiers(semanticServices.getTrace(), method) + resolveVisibilityFromPsiModifiers(method) ); semanticServices.getTrace().record(BindingContext.FUNCTION, method, functionDescriptorImpl); FunctionDescriptor substitutedFunctionDescriptor = functionDescriptorImpl; @@ -464,7 +463,7 @@ public class JavaDescriptorResolver { return substitutedFunctionDescriptor; } - private static Visibility resolveVisibilityFromPsiModifiers(BindingTrace trace, PsiModifierListOwner modifierListOwner) { + private static Visibility resolveVisibilityFromPsiModifiers(PsiModifierListOwner modifierListOwner) { //TODO report error return modifierListOwner.hasModifierProperty(PsiModifier.PUBLIC) ? Visibility.PUBLIC : (modifierListOwner.hasModifierProperty(PsiModifier.PRIVATE) ? Visibility.PRIVATE : diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/Configuration.java b/compiler/frontend/src/org/jetbrains/jet/lang/Configuration.java new file mode 100644 index 00000000000..e376a6ebaf6 --- /dev/null +++ b/compiler/frontend/src/org/jetbrains/jet/lang/Configuration.java @@ -0,0 +1,29 @@ +package org.jetbrains.jet.lang; + +import org.jetbrains.annotations.NotNull; +import org.jetbrains.jet.lang.descriptors.NamespaceDescriptor; +import org.jetbrains.jet.lang.resolve.BindingTrace; +import org.jetbrains.jet.lang.resolve.scopes.WritableScope; + +/** + * @author abreslav + */ +public interface Configuration { + Configuration EMPTY = new Configuration() { + @Override + public void addDefaultImports(BindingTrace trace, WritableScope rootScope) { + } + + @Override + public void extendNamespaceScope(BindingTrace trace, @NotNull NamespaceDescriptor namespaceDescriptor, @NotNull WritableScope namespaceMemberScope) { + } + }; + + void addDefaultImports(BindingTrace trace, WritableScope rootScope); + + /** + * + * This method is called every time a namespace descriptor is created. Use it to add extra descriptors to the namespace, e.g. merge a Java package with a Kotlin one + */ + void extendNamespaceScope(BindingTrace trace, @NotNull NamespaceDescriptor namespaceDescriptor, @NotNull WritableScope namespaceMemberScope); +} diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/AnalyzingUtils.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/AnalyzingUtils.java index 13cb17841bc..7e5d791edd3 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/AnalyzingUtils.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/AnalyzingUtils.java @@ -1,7 +1,6 @@ package org.jetbrains.jet.lang.resolve; import com.google.common.base.Predicate; -import com.google.common.base.Predicates; import com.google.common.collect.Maps; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.TextRange; @@ -10,6 +9,7 @@ import com.intellij.psi.PsiElementVisitor; import com.intellij.psi.PsiErrorElement; import com.intellij.psi.PsiFile; import org.jetbrains.annotations.NotNull; +import org.jetbrains.jet.lang.Configuration; import org.jetbrains.jet.lang.JetSemanticServices; import org.jetbrains.jet.lang.cfg.pseudocode.JetControlFlowDataTraceFactory; import org.jetbrains.jet.lang.descriptors.*; @@ -17,20 +17,24 @@ import org.jetbrains.jet.lang.diagnostics.Diagnostic; import org.jetbrains.jet.lang.diagnostics.DiagnosticHolder; import org.jetbrains.jet.lang.diagnostics.DiagnosticUtils; import org.jetbrains.jet.lang.psi.JetDeclaration; -import org.jetbrains.jet.lang.psi.JetFile; -import org.jetbrains.jet.lang.psi.JetNamespace; import org.jetbrains.jet.lang.resolve.scopes.JetScope; import org.jetbrains.jet.lang.resolve.scopes.WritableScope; import org.jetbrains.jet.lang.resolve.scopes.WritableScopeImpl; -import java.util.*; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import java.util.Map; /** * @author abreslav */ public class AnalyzingUtils { - public static AnalyzingUtils getInstance(@NotNull ImportingStrategy importingStrategy) { - return new AnalyzingUtils(importingStrategy); + + private static final AnalyzingUtils INSTANCE = new AnalyzingUtils(); + + public static AnalyzingUtils getInstance() { + return INSTANCE; } public static void checkForSyntacticErrors(@NotNull PsiElement root) { @@ -69,32 +73,26 @@ public class AnalyzingUtils { } } - private final ImportingStrategy importingStrategy; - - private AnalyzingUtils(ImportingStrategy importingStrategy) { - this.importingStrategy = importingStrategy; - } - - public BindingContext analyzeNamespace(@NotNull JetNamespace namespace, @NotNull JetControlFlowDataTraceFactory flowDataTraceFactory) { - Project project = namespace.getProject(); - List declarations = Collections.singletonList(namespace); - - return analyzeNamespaces(project, declarations, Predicates.equalTo(namespace.getContainingFile()), flowDataTraceFactory); - } + // -------------------------------------------------------------------------------------------------------------------------- public BindingContext analyzeNamespaces( @NotNull Project project, + @NotNull Configuration configuration, @NotNull Collection declarations, @NotNull Predicate filesToAnalyzeCompletely, @NotNull JetControlFlowDataTraceFactory flowDataTraceFactory) { BindingTraceContext bindingTraceContext = new BindingTraceContext(); + return analyzeNamespacesWithGivenTrace(project, configuration, declarations, filesToAnalyzeCompletely, flowDataTraceFactory, bindingTraceContext); + } + + public BindingContext analyzeNamespacesWithGivenTrace(Project project, Configuration configuration, Collection declarations, Predicate filesToAnalyzeCompletely, JetControlFlowDataTraceFactory flowDataTraceFactory, BindingTraceContext bindingTraceContext) { JetSemanticServices semanticServices = JetSemanticServices.createSemanticServices(project); JetScope libraryScope = semanticServices.getStandardLibrary().getLibraryScope(); ModuleDescriptor owner = new ModuleDescriptor(""); final WritableScope scope = new WritableScopeImpl(JetScope.EMPTY, owner, new TraceBasedRedeclarationHandler(bindingTraceContext)).setDebugName("Root scope in analyzeNamespace"); - importingStrategy.addImports(project, semanticServices, bindingTraceContext, scope); +// configuration.addImports(project, semanticServices, bindingTraceContext, scope); scope.importScope(libraryScope); scope.changeLockLevel(WritableScope.LockLevel.BOTH); @@ -132,29 +130,8 @@ public class AnalyzingUtils { public ClassObjectStatus setClassObjectDescriptor(@NotNull MutableClassDescriptor classObjectDescriptor) { throw new IllegalStateException("Must be guaranteed not to happen by the parser"); } - }, declarations, filesToAnalyzeCompletely, flowDataTraceFactory); + }, declarations, filesToAnalyzeCompletely, flowDataTraceFactory, configuration); return bindingTraceContext.getBindingContext(); } - public BindingContext shallowAnalyzeFiles(Collection files) { - assert files.size() > 0; - - Project project = files.iterator().next().getProject(); - - Collection namespaces = collectRootNamespaces(files); - - return analyzeNamespaces(project, namespaces, Predicates.alwaysFalse(), JetControlFlowDataTraceFactory.EMPTY); - } - - public static List collectRootNamespaces(Collection files) { - List namespaces = new ArrayList(); - - for (PsiFile file : files) { - if (file instanceof JetFile) { - namespaces.add(((JetFile) file).getRootNamespace()); - } - } - return namespaces; - } - } diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/DescriptorUtils.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/DescriptorUtils.java index c66af6e8f03..b76f5efa4b6 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/DescriptorUtils.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/DescriptorUtils.java @@ -154,4 +154,14 @@ public class DescriptorUtils { } return false; } + + public static String getFQName(DeclarationDescriptor descriptor) { + DeclarationDescriptor container = descriptor.getContainingDeclaration(); + if (container != null && !(container instanceof ModuleDescriptor)) { + String baseName = getFQName(container); + if (!baseName.isEmpty()) return baseName + "." + descriptor.getName(); + } + + return descriptor.getName(); + } } diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/ImportingStrategy.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/ImportingStrategy.java deleted file mode 100644 index 1671b51fa74..00000000000 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/ImportingStrategy.java +++ /dev/null @@ -1,19 +0,0 @@ -package org.jetbrains.jet.lang.resolve; - -import com.intellij.openapi.project.Project; -import org.jetbrains.jet.lang.JetSemanticServices; -import org.jetbrains.jet.lang.resolve.scopes.WritableScope; - -/** -* @author abreslav -*/ -public interface ImportingStrategy { - ImportingStrategy NONE = new ImportingStrategy() { - @Override - public void addImports(Project project, JetSemanticServices semanticServices, BindingTrace trace, WritableScope rootScope) { - - } - }; - - void addImports(Project project, JetSemanticServices semanticServices, BindingTrace trace, WritableScope rootScope); -} diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/OverloadResolver.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/OverloadResolver.java index c4575ed71cc..3fd237d3cac 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/OverloadResolver.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/OverloadResolver.java @@ -1,18 +1,13 @@ package org.jetbrains.jet.lang.resolve; import com.intellij.openapi.util.Pair; -import com.intellij.psi.PsiElement; import com.intellij.util.containers.MultiMap; import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; import org.jetbrains.jet.lang.descriptors.*; import org.jetbrains.jet.lang.diagnostics.Errors; import org.jetbrains.jet.lang.psi.*; -import org.jetbrains.jet.resolve.DescriptorRenderer; import java.util.Collection; -import java.util.Collections; -import java.util.List; import java.util.Map; import static org.jetbrains.jet.lang.resolve.BindingContext.DELEGATED; @@ -51,7 +46,7 @@ public class OverloadResolver { } Key(NamespaceDescriptor namespaceDescriptor, String name) { - this(DescriptorRenderer.getFQName(namespaceDescriptor), name); + this(DescriptorUtils.getFQName(namespaceDescriptor), name); } public String getNamespace() { diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/TopDownAnalysisContext.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/TopDownAnalysisContext.java index 96483be60c3..6ca87908251 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/TopDownAnalysisContext.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/TopDownAnalysisContext.java @@ -6,6 +6,7 @@ import com.google.common.collect.Sets; import com.intellij.psi.PsiElement; import com.intellij.psi.PsiFile; import org.jetbrains.annotations.NotNull; +import org.jetbrains.jet.lang.Configuration; import org.jetbrains.jet.lang.JetSemanticServices; import org.jetbrains.jet.lang.descriptors.*; import org.jetbrains.jet.lang.psi.*; @@ -23,31 +24,31 @@ import java.util.Set; private final ObservableBindingTrace trace; private final JetSemanticServices semanticServices; - private final DescriptorResolver descriptorResolver; + private final Configuration configuration; + private final DescriptorResolver descriptorResolver; private final Map classes = Maps.newLinkedHashMap(); private final Map objects = Maps.newLinkedHashMap(); protected final Map namespaceScopes = Maps.newHashMap(); protected final Map namespaceDescriptors = Maps.newHashMap(); private final Map declaringScopes = Maps.newHashMap(); - private final Map functions = Maps.newLinkedHashMap(); private final Map constructors = Maps.newLinkedHashMap(); private final Map properties = Maps.newLinkedHashMap(); private final Set primaryConstructorParameterProperties = Sets.newHashSet(); private final Predicate analyzeCompletely; - - private StringBuilder debugOutput; + private StringBuilder debugOutput; private boolean analyzingBootstrapLibrary = false; - public TopDownAnalysisContext(JetSemanticServices semanticServices, BindingTrace trace, Predicate analyzeCompletely) { + public TopDownAnalysisContext(JetSemanticServices semanticServices, BindingTrace trace, Predicate analyzeCompletely, @NotNull Configuration configuration) { this.trace = new ObservableBindingTrace(trace); this.semanticServices = semanticServices; this.descriptorResolver = semanticServices.getClassDescriptorResolver(trace); this.analyzeCompletely = analyzeCompletely; + this.configuration = configuration; } public void debug(Object message) { @@ -133,4 +134,8 @@ import java.util.Set; return functions; } + @NotNull + public Configuration getConfiguration() { + return configuration; + } } diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/TopDownAnalyzer.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/TopDownAnalyzer.java index 5e311a37bd8..d9a8fe008fa 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/TopDownAnalyzer.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/TopDownAnalyzer.java @@ -4,6 +4,7 @@ import com.google.common.base.Predicate; import com.google.common.base.Predicates; import com.intellij.psi.PsiFile; import org.jetbrains.annotations.NotNull; +import org.jetbrains.jet.lang.Configuration; import org.jetbrains.jet.lang.JetSemanticServices; import org.jetbrains.jet.lang.cfg.pseudocode.JetControlFlowDataTraceFactory; import org.jetbrains.jet.lang.descriptors.*; @@ -30,8 +31,10 @@ public class TopDownAnalyzer { @NotNull NamespaceLike owner, @NotNull Collection declarations, @NotNull Predicate analyzeCompletely, - @NotNull JetControlFlowDataTraceFactory flowDataTraceFactory) { - process(semanticServices, trace, outerScope, owner, declarations, analyzeCompletely, flowDataTraceFactory, false); + @NotNull JetControlFlowDataTraceFactory flowDataTraceFactory, + @NotNull Configuration configuration + ) { + process(semanticServices, trace, outerScope, owner, declarations, analyzeCompletely, flowDataTraceFactory, configuration, false); } private static void process( @@ -42,8 +45,9 @@ public class TopDownAnalyzer { @NotNull Collection declarations, @NotNull Predicate analyzeCompletely, @NotNull JetControlFlowDataTraceFactory flowDataTraceFactory, + @NotNull Configuration configuration, boolean declaredLocally) { - TopDownAnalysisContext context = new TopDownAnalysisContext(semanticServices, trace, analyzeCompletely); + TopDownAnalysisContext context = new TopDownAnalysisContext(semanticServices, trace, analyzeCompletely, configuration); doProcess(context, outerScope, owner, declarations, flowDataTraceFactory, declaredLocally); } @@ -89,7 +93,7 @@ public class TopDownAnalyzer { @NotNull JetSemanticServices semanticServices, @NotNull BindingTrace trace, @NotNull WritableScope outerScope, @NotNull NamespaceDescriptorImpl standardLibraryNamespace, @NotNull JetNamespace namespace) { - TopDownAnalysisContext context = new TopDownAnalysisContext(semanticServices, trace, Predicates.alwaysTrue()); + TopDownAnalysisContext context = new TopDownAnalysisContext(semanticServices, trace, Predicates.alwaysTrue(), Configuration.EMPTY); context.getNamespaceScopes().put(namespace, standardLibraryNamespace.getMemberScope()); context.getNamespaceDescriptors().put(namespace, standardLibraryNamespace); context.getDeclaringScopes().put(namespace, outerScope); @@ -135,7 +139,7 @@ public class TopDownAnalyzer { public ClassObjectStatus setClassObjectDescriptor(@NotNull MutableClassDescriptor classObjectDescriptor) { return ClassObjectStatus.NOT_ALLOWED; } - }, Collections.singletonList(object), Predicates.equalTo(object.getContainingFile()), JetControlFlowDataTraceFactory.EMPTY, true); + }, Collections.singletonList(object), Predicates.equalTo(object.getContainingFile()), JetControlFlowDataTraceFactory.EMPTY, Configuration.EMPTY, true); } } diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/TypeHierarchyResolver.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/TypeHierarchyResolver.java index 7ea0b24800c..6a694ed7d99 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/TypeHierarchyResolver.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/TypeHierarchyResolver.java @@ -75,6 +75,7 @@ public class TypeHierarchyResolver { WriteThroughScope namespaceScope = new WriteThroughScope(outerScope, namespaceDescriptor.getMemberScope(), new TraceBasedRedeclarationHandler(context.getTrace())); namespaceScope.changeLockLevel(WritableScope.LockLevel.BOTH); + context.getConfiguration().addDefaultImports(context.getTrace(), namespaceScope); context.getNamespaceScopes().put(namespace, namespaceScope); context.getDeclaringScopes().put(namespace, outerScope); @@ -215,6 +216,7 @@ public class TypeHierarchyResolver { WritableScopeImpl scope = new WritableScopeImpl(JetScope.EMPTY, namespaceDescriptor, new TraceBasedRedeclarationHandler(context.getTrace())).setDebugName("Namespace member scope"); scope.changeLockLevel(WritableScope.LockLevel.BOTH); namespaceDescriptor.initialize(scope); + context.getConfiguration().extendNamespaceScope(context.getTrace(), namespaceDescriptor, scope); owner.addNamespace(namespaceDescriptor); if (namespace != null) { context.getTrace().record(BindingContext.NAMESPACE, namespace, namespaceDescriptor); diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/scopes/WritableScopeWithImports.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/scopes/WritableScopeWithImports.java index 540d5a456de..eb848429135 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/scopes/WritableScopeWithImports.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/scopes/WritableScopeWithImports.java @@ -38,7 +38,7 @@ public abstract class WritableScopeWithImports extends JetScopeAdapter implement @Override public WritableScope changeLockLevel(LockLevel lockLevel) { if (lockLevel.ordinal() < this.lockLevel.ordinal()) { - throw new IllegalStateException("cannot lower lock level from " + this.lockLevel + " to " + lockLevel); + throw new IllegalStateException("cannot lower lock level from " + this.lockLevel + " to " + lockLevel + " at " + debugName); } this.lockLevel = lockLevel; return this; @@ -46,13 +46,13 @@ public abstract class WritableScopeWithImports extends JetScopeAdapter implement protected void checkMayRead() { if (lockLevel != LockLevel.READING && lockLevel != LockLevel.BOTH) { - throw new IllegalStateException("cannot read with lock level " + lockLevel); + throw new IllegalStateException("cannot read with lock level " + lockLevel + " at " + debugName); } } protected void checkMayWrite() { if (lockLevel != LockLevel.WRITING && lockLevel != LockLevel.BOTH) { - throw new IllegalStateException("cannot write with lock level " + lockLevel); + throw new IllegalStateException("cannot write with lock level " + lockLevel + " at " + debugName); } } diff --git a/compiler/frontend/src/org/jetbrains/jet/resolve/DescriptorRenderer.java b/compiler/frontend/src/org/jetbrains/jet/resolve/DescriptorRenderer.java index 991c3ced6a9..43a466e428b 100644 --- a/compiler/frontend/src/org/jetbrains/jet/resolve/DescriptorRenderer.java +++ b/compiler/frontend/src/org/jetbrains/jet/resolve/DescriptorRenderer.java @@ -18,16 +18,6 @@ import java.util.List; */ public class DescriptorRenderer implements Renderer { - public static String getFQName(DeclarationDescriptor descriptor) { - DeclarationDescriptor container = descriptor.getContainingDeclaration(); - if (container != null && !(container instanceof ModuleDescriptor)) { - String baseName = getFQName(container); - if (!baseName.isEmpty()) return baseName + "." + descriptor.getName(); - } - - return descriptor.getName(); - } - public static final DescriptorRenderer TEXT = new DescriptorRenderer(); public static final DescriptorRenderer HTML = new DescriptorRenderer() { diff --git a/compiler/testData/codegen/regressions/kt684.jet b/compiler/testData/codegen/regressions/kt684.jet new file mode 100644 index 00000000000..41048cec7c5 --- /dev/null +++ b/compiler/testData/codegen/regressions/kt684.jet @@ -0,0 +1,29 @@ +fun escapeChar(c : Char) : String? = when (c) { + '\\' => "\\\\" + '\n' => "\\n" + '"' => "\\\"" + else => String.valueOf(c) +} + +fun String.escape(i : Int = 0, result : String = "") : String = + if (i == length) result + else escape(i + 1, result + escapeChar(get(i))) + +fun box() : String { + val s = " System.out?.println(\"fun escapeChar(c : Char) : String? = when (c) {\");\n System.out?.println(\" '\\\\\\\\' => \\\"\\\\\\\\\\\\\\\\\\\"\");\n System.out?.println(\" '\\\\n' => \\\"\\\\\\\\n\\\"\");\n System.out?.println(\" '\\\"' => \\\"\\\\\\\\\\\\\\\"\\\"\");\n System.out?.println(\" else => String.valueOf(c)\");\n System.out?.println(\"}\");\n System.out?.println();\n System.out?.println(\"fun String.escape(i : Int = 0, result : String = \\\"\\\") : String =\");\n System.out?.println(\" if (i == length) result\");\n System.out?.println(\" else escape(i + 1, result + escapeChar(this.get(i)))\");\n System.out?.println();\n System.out?.println(\"fun main(args : Array) {\");\n System.out?.println(\" val s = \\\"\" + s.escape() + \"\\\";\");\n System.out?.println(s);\n}\n"; + System.out?.println("fun escapeChar(c : Char) : String? = when (c) {"); + System.out?.println(" '\\\\' => \"\\\\\\\\\""); + System.out?.println(" '\\n' => \"\\\\n\""); + System.out?.println(" '\"' => \"\\\\\\\"\""); + System.out?.println(" else => String.valueOf(c)"); + System.out?.println("}"); + System.out?.println(); + System.out?.println("fun String.escape(i : Int = 0, result : String = \"\") : String ="); + System.out?.println(" if (i == length) result"); + System.out?.println(" else escape(i + 1, result + escapeChar(this.get(i)))"); + System.out?.println(); + System.out?.println("fun main(args : Array) {"); + System.out?.println(" val s = \"" + s.escape() + "\";"); + System.out?.println(s); + return "OK" +} \ No newline at end of file diff --git a/compiler/testData/codegen/regressions/kt752.jet b/compiler/testData/codegen/regressions/kt752.jet new file mode 100644 index 00000000000..20132c9f6a8 --- /dev/null +++ b/compiler/testData/codegen/regressions/kt752.jet @@ -0,0 +1,12 @@ +namespace demo_range + +fun Int?.rangeTo(other : Int?) : IntRange = this.sure().rangeTo(other.sure()) + +fun box() : String { + val x : Int? = 10 + val y : Int? = 12 + + for (i in x..y) + System.out?.println(i.inv()) + return "OK" +} \ No newline at end of file diff --git a/compiler/testData/codegen/regressions/kt753.jet b/compiler/testData/codegen/regressions/kt753.jet new file mode 100644 index 00000000000..a1b81de8138 --- /dev/null +++ b/compiler/testData/codegen/regressions/kt753.jet @@ -0,0 +1,11 @@ +namespace bitwise_demo + +fun Long?.shl(bits : Int?) : Long = this.sure().shl(bits.sure()) + +fun box() : String { + val x : Long? = 10 + val y : Int? = 12 + + System.out?.println(x.shl(y)) + return "OK" +} \ No newline at end of file diff --git a/compiler/testData/codegen/regressions/kt756.jet b/compiler/testData/codegen/regressions/kt756.jet new file mode 100644 index 00000000000..4cff1aecd11 --- /dev/null +++ b/compiler/testData/codegen/regressions/kt756.jet @@ -0,0 +1,12 @@ +namespace demo_range + +fun Int?.plus() : Int = this.sure().plus() +fun Int?.dec() : Int = this.sure().dec() +fun Int?.inc() : Int = this.sure().inc() +fun Int?.minus() : Int = this.sure().minus() + +fun box() : String { + val x : Int? = 10 + System.out?.println(x?.inv())// * x?.plus() * x?.dec() * x?.minus() as Number) + return "OK" +} \ No newline at end of file diff --git a/compiler/testData/codegen/regressions/kt757.jet b/compiler/testData/codegen/regressions/kt757.jet new file mode 100644 index 00000000000..8ddfb3d879a --- /dev/null +++ b/compiler/testData/codegen/regressions/kt757.jet @@ -0,0 +1,9 @@ +namespace demo_long + +fun Long?.inv() : Long = this.sure().inv() + +fun box() : String { + val x : Long? = 10 + System.out?.println(x.inv()) + return if(x.inv() == -11.lng) "OK" else "fail" +} \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/MergePackagesWithJava.jet b/compiler/testData/diagnostics/tests/MergePackagesWithJava.jet new file mode 100644 index 00000000000..9da16a7c82d --- /dev/null +++ b/compiler/testData/diagnostics/tests/MergePackagesWithJava.jet @@ -0,0 +1,9 @@ +// +JDK +// KT-689 Allow to put Java and Kotlin files in the same packages + +// This is a stub test. One should not extend Java packages that come from libraries. +namespace java + +val c : lang.Class<*>? = null + +val Array?.length : Int get() = if (this != null) this.size else throw NullPointerException() diff --git a/compiler/tests/org/jetbrains/jet/JetTestUtils.java b/compiler/tests/org/jetbrains/jet/JetTestUtils.java index 26e29d8b777..3187caacb4e 100644 --- a/compiler/tests/org/jetbrains/jet/JetTestUtils.java +++ b/compiler/tests/org/jetbrains/jet/JetTestUtils.java @@ -1,11 +1,14 @@ package org.jetbrains.jet; import org.jetbrains.annotations.NotNull; +import org.jetbrains.jet.lang.cfg.pseudocode.JetControlFlowDataTraceFactory; import org.jetbrains.jet.lang.diagnostics.Diagnostic; import org.jetbrains.jet.lang.diagnostics.Severity; import org.jetbrains.jet.lang.diagnostics.UnresolvedReferenceDiagnostic; +import org.jetbrains.jet.lang.psi.JetNamespace; import org.jetbrains.jet.lang.resolve.BindingContext; import org.jetbrains.jet.lang.resolve.BindingTrace; +import org.jetbrains.jet.lang.resolve.java.AnalyzerFacade; import org.jetbrains.jet.util.slicedmap.ReadOnlySlice; import org.jetbrains.jet.util.slicedmap.WritableSlice; @@ -120,4 +123,8 @@ public class JetTestUtils { } } }; + + public static BindingContext analyzeNamespace(@NotNull JetNamespace namespace, @NotNull JetControlFlowDataTraceFactory flowDataTraceFactory) { + return AnalyzerFacade.analyzeOneNamespaceWithJavaIntegration(namespace, flowDataTraceFactory); + } } diff --git a/compiler/tests/org/jetbrains/jet/cfg/JetControlFlowTest.java b/compiler/tests/org/jetbrains/jet/cfg/JetControlFlowTest.java index 54119d272dd..637b953aa4b 100644 --- a/compiler/tests/org/jetbrains/jet/cfg/JetControlFlowTest.java +++ b/compiler/tests/org/jetbrains/jet/cfg/JetControlFlowTest.java @@ -11,10 +11,10 @@ import junit.framework.TestSuite; import org.jetbrains.annotations.NotNull; import org.jetbrains.jet.JetLiteFixture; import org.jetbrains.jet.JetTestCaseBuilder; +import org.jetbrains.jet.JetTestUtils; import org.jetbrains.jet.lang.cfg.LoopInfo; import org.jetbrains.jet.lang.cfg.pseudocode.*; import org.jetbrains.jet.lang.psi.*; -import org.jetbrains.jet.lang.resolve.java.AnalyzerFacade; import java.io.File; import java.io.FileNotFoundException; @@ -72,7 +72,7 @@ public class JetControlFlowTest extends JetLiteFixture { }; - AnalyzerFacade.analyzeNamespace(file.getRootNamespace(), new JetControlFlowDataTraceFactory() { + JetTestUtils.analyzeNamespace(file.getRootNamespace(), new JetControlFlowDataTraceFactory() { @NotNull @Override public JetPseudocodeTrace createTrace(JetElement element) { diff --git a/compiler/tests/org/jetbrains/jet/checkers/CheckerTestUtilTest.java b/compiler/tests/org/jetbrains/jet/checkers/CheckerTestUtilTest.java index 9befab190ad..eb1e3267d9f 100644 --- a/compiler/tests/org/jetbrains/jet/checkers/CheckerTestUtilTest.java +++ b/compiler/tests/org/jetbrains/jet/checkers/CheckerTestUtilTest.java @@ -3,11 +3,10 @@ package org.jetbrains.jet.checkers; import com.google.common.collect.Lists; import com.intellij.psi.PsiFile; import org.jetbrains.jet.JetLiteFixture; +import org.jetbrains.jet.lang.cfg.pseudocode.JetControlFlowDataTraceFactory; import org.jetbrains.jet.lang.diagnostics.Diagnostic; import org.jetbrains.jet.lang.psi.JetFile; -import org.jetbrains.jet.lang.resolve.AnalyzingUtils; import org.jetbrains.jet.lang.resolve.BindingContext; -import org.jetbrains.jet.lang.resolve.ImportingStrategy; import org.jetbrains.jet.lang.resolve.java.AnalyzerFacade; import java.util.Collections; @@ -81,7 +80,10 @@ public class CheckerTestUtilTest extends JetLiteFixture { } public void test(PsiFile psiFile) { - BindingContext bindingContext = AnalyzerFacade.analyzeFileWithCache(AnalyzingUtils.getInstance(ImportingStrategy.NONE), (JetFile) psiFile, AnalyzerFacade.SINGLE_DECLARATION_PROVIDER); + BindingContext bindingContext = AnalyzerFacade.analyzeOneNamespaceWithJavaIntegration( + ((JetFile) psiFile).getRootNamespace(), + JetControlFlowDataTraceFactory.EMPTY); + String expectedText = CheckerTestUtil.addDiagnosticMarkersToText(psiFile, CheckerTestUtil.getDiagnosticsIncludingSyntaxErrors(bindingContext, psiFile)).toString(); List diagnosedRanges = Lists.newArrayList(); diff --git a/compiler/tests/org/jetbrains/jet/checkers/JetDiagnosticsTest.java b/compiler/tests/org/jetbrains/jet/checkers/JetDiagnosticsTest.java index c574462ece3..e661113e310 100644 --- a/compiler/tests/org/jetbrains/jet/checkers/JetDiagnosticsTest.java +++ b/compiler/tests/org/jetbrains/jet/checkers/JetDiagnosticsTest.java @@ -9,14 +9,14 @@ import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; import org.jetbrains.jet.JetLiteFixture; import org.jetbrains.jet.JetTestCaseBuilder; +import org.jetbrains.jet.lang.Configuration; import org.jetbrains.jet.lang.cfg.pseudocode.JetControlFlowDataTraceFactory; import org.jetbrains.jet.lang.diagnostics.DiagnosticUtils; import org.jetbrains.jet.lang.psi.JetDeclaration; import org.jetbrains.jet.lang.psi.JetFile; import org.jetbrains.jet.lang.resolve.AnalyzingUtils; import org.jetbrains.jet.lang.resolve.BindingContext; -import org.jetbrains.jet.lang.resolve.ImportingStrategy; -import org.jetbrains.jet.lang.resolve.java.JavaDefaultImports; +import org.jetbrains.jet.lang.resolve.java.AnalyzerFacade; import java.io.File; import java.util.List; @@ -82,14 +82,20 @@ public class JetDiagnosticsTest extends JetLiteFixture { List testFileFiles = createTestFiles(testFileName, expectedText); boolean importJdk = expectedText.contains("+JDK"); - ImportingStrategy importingStrategy = importJdk ? JavaDefaultImports.JAVA_DEFAULT_IMPORTS : ImportingStrategy.NONE; +// Configuration configuration = importJdk ? JavaBridgeConfiguration.createJavaBridgeConfiguration(getProject()) : Configuration.EMPTY; List namespaces = Lists.newArrayList(); for (TestFile testFileFile : testFileFiles) { namespaces.add(testFileFile.jetFile.getRootNamespace()); } - BindingContext bindingContext = AnalyzingUtils.getInstance(importingStrategy).analyzeNamespaces(getProject(), namespaces, Predicates.alwaysTrue(), JetControlFlowDataTraceFactory.EMPTY); + BindingContext bindingContext; + if (importJdk) { + bindingContext = AnalyzerFacade.analyzeNamespacesWithJavaIntegration(getProject(), namespaces, Predicates.alwaysTrue(), JetControlFlowDataTraceFactory.EMPTY); + } + else { + bindingContext = AnalyzingUtils.getInstance().analyzeNamespaces(getProject(), Configuration.EMPTY, namespaces, Predicates.alwaysTrue(), JetControlFlowDataTraceFactory.EMPTY); + } StringBuilder actualText = new StringBuilder(); for (TestFile testFileFile : testFileFiles) { diff --git a/compiler/tests/org/jetbrains/jet/codegen/PrimitiveTypesTest.java b/compiler/tests/org/jetbrains/jet/codegen/PrimitiveTypesTest.java index 9fda35ee5ad..0c7ad33b70b 100644 --- a/compiler/tests/org/jetbrains/jet/codegen/PrimitiveTypesTest.java +++ b/compiler/tests/org/jetbrains/jet/codegen/PrimitiveTypesTest.java @@ -287,37 +287,31 @@ public class PrimitiveTypesTest extends CodegenTestCase { public void testKt711 () throws Exception { loadText("fun box() = if ((1 ?: 0) == 1) \"OK\" else \"fail\""); -// System.out.println(generateToText()); blackBox(); } public void testSureNonnull () throws Exception { loadText("fun box() = 10.sure().toString()"); -// System.out.println(generateToText()); assertFalse(generateToText().contains("IFNONNULL")); } public void testSureNullable () throws Exception { loadText("val a : Int? = 10; fun box() = a.sure().toString()"); -// System.out.println(generateToText()); assertTrue(generateToText().contains("IFNONNULL")); } public void testSafeNonnull () throws Exception { loadText("fun box() = 10?.toString()"); -// System.out.println(generateToText()); assertFalse(generateToText().contains("IFNULL")); } public void testSafeNullable () throws Exception { loadText("val a : Int? = 10; fun box() = a?.toString()"); -// System.out.println(generateToText()); assertTrue(generateToText().contains("IFNULL")); } public void testKt737() throws Exception { loadText("fun box() = if(3.compareTo(2) != 1) \"fail\" else if(5.byt.compareTo(10.lng) >= 0) \"fail\" else \"OK\""); - System.out.println(generateToText()); assertEquals("OK", blackBox()); } @@ -334,7 +328,27 @@ public class PrimitiveTypesTest extends CodegenTestCase { " System.out?.println(f(six))\n" + " return \"OK\"" + "}"); -// System.out.println(generateToText()); blackBox(); } + + public void testKt752 () { + blackBoxFile("regressions/kt752.jet"); + } + + public void testKt753 () { + blackBoxFile("regressions/kt753.jet"); + } + + public void testKt684 () { + blackBoxFile("regressions/kt684.jet"); + } + + public void testKt756 () { + blackBoxFile("regressions/kt756.jet"); + System.out.println(generateToText()); + } + + public void testKt757 () { + blackBoxFile("regressions/kt757.jet"); + } } diff --git a/compiler/tests/org/jetbrains/jet/resolve/ExpectedResolveData.java b/compiler/tests/org/jetbrains/jet/resolve/ExpectedResolveData.java index d71fe52d5fa..7224b087dc3 100644 --- a/compiler/tests/org/jetbrains/jet/resolve/ExpectedResolveData.java +++ b/compiler/tests/org/jetbrains/jet/resolve/ExpectedResolveData.java @@ -2,6 +2,7 @@ package org.jetbrains.jet.resolve; import com.intellij.psi.PsiElement; import com.intellij.psi.util.PsiTreeUtil; +import org.jetbrains.jet.JetTestUtils; import org.jetbrains.jet.lang.JetSemanticServices; import org.jetbrains.jet.lang.cfg.pseudocode.JetControlFlowDataTraceFactory; import org.jetbrains.jet.lang.descriptors.*; @@ -11,7 +12,6 @@ import org.jetbrains.jet.lang.diagnostics.UnresolvedReferenceDiagnostic; import org.jetbrains.jet.lang.psi.*; import org.jetbrains.jet.lang.resolve.BindingContext; import org.jetbrains.jet.lang.resolve.BindingContextUtils; -import org.jetbrains.jet.lang.resolve.java.AnalyzerFacade; import org.jetbrains.jet.lang.types.ErrorUtils; import org.jetbrains.jet.lang.types.JetStandardLibrary; import org.jetbrains.jet.lang.types.JetType; @@ -84,7 +84,7 @@ public class ExpectedResolveData { JetSemanticServices semanticServices = JetSemanticServices.createSemanticServices(file.getProject()); JetStandardLibrary lib = semanticServices.getStandardLibrary(); - BindingContext bindingContext = AnalyzerFacade.analyzeNamespace(file.getRootNamespace(), JetControlFlowDataTraceFactory.EMPTY); + BindingContext bindingContext = JetTestUtils.analyzeNamespace(file.getRootNamespace(), JetControlFlowDataTraceFactory.EMPTY); for (Diagnostic diagnostic : bindingContext.getDiagnostics()) { if (diagnostic instanceof UnresolvedReferenceDiagnostic) { UnresolvedReferenceDiagnostic unresolvedReferenceDiagnostic = (UnresolvedReferenceDiagnostic) diagnostic; diff --git a/idea/src/org/jetbrains/jet/plugin/compiler/JetCompiler.java b/idea/src/org/jetbrains/jet/plugin/compiler/JetCompiler.java index 0a16cb56f58..21dea6ed517 100644 --- a/idea/src/org/jetbrains/jet/plugin/compiler/JetCompiler.java +++ b/idea/src/org/jetbrains/jet/plugin/compiler/JetCompiler.java @@ -24,9 +24,8 @@ import org.jetbrains.jet.lang.cfg.pseudocode.JetControlFlowDataTraceFactory; import org.jetbrains.jet.lang.diagnostics.Diagnostic; import org.jetbrains.jet.lang.psi.JetFile; import org.jetbrains.jet.lang.psi.JetNamespace; -import org.jetbrains.jet.lang.resolve.AnalyzingUtils; import org.jetbrains.jet.lang.resolve.BindingContext; -import org.jetbrains.jet.lang.resolve.java.JavaDefaultImports; +import org.jetbrains.jet.lang.resolve.java.AnalyzerFacade; import org.jetbrains.jet.plugin.JetFileType; import java.io.File; @@ -59,7 +58,7 @@ public class JetCompiler implements TranslatingCompiler { public void compile(final CompileContext compileContext, Chunk moduleChunk, final VirtualFile[] virtualFiles, OutputSink outputSink) { if (virtualFiles.length == 0) return; - Module module = compileContext.getModuleByFile(virtualFiles[0]); + final Module module = compileContext.getModuleByFile(virtualFiles[0]); final VirtualFile outputDir = compileContext.getModuleOutputDirectory(module); if (outputDir == null) { compileContext.addMessage(ERROR, "[Internal Error] No output directory", "", -1, -1); @@ -80,10 +79,8 @@ public class JetCompiler implements TranslatingCompiler { } } - BindingContext bindingContext = AnalyzingUtils.getInstance(JavaDefaultImports.JAVA_DEFAULT_IMPORTS).analyzeNamespaces( - compileContext.getProject(), namespaces, - Predicates.alwaysTrue(), - JetControlFlowDataTraceFactory.EMPTY); + BindingContext bindingContext = + AnalyzerFacade.analyzeNamespacesWithJavaIntegration(compileContext.getProject(), namespaces, Predicates.alwaysTrue(), JetControlFlowDataTraceFactory.EMPTY); boolean errors = false; for (Diagnostic diagnostic : bindingContext.getDiagnostics()) { diff --git a/idea/src/org/jetbrains/jet/plugin/java/JavaElementFinder.java b/idea/src/org/jetbrains/jet/plugin/java/JavaElementFinder.java index 7cfa0fe1b86..78b31e8fad6 100644 --- a/idea/src/org/jetbrains/jet/plugin/java/JavaElementFinder.java +++ b/idea/src/org/jetbrains/jet/plugin/java/JavaElementFinder.java @@ -35,9 +35,8 @@ import org.jetbrains.jet.lang.psi.JetClassOrObject; import org.jetbrains.jet.lang.psi.JetDeclaration; import org.jetbrains.jet.lang.psi.JetFile; import org.jetbrains.jet.lang.psi.JetNamespace; -import org.jetbrains.jet.lang.resolve.AnalyzingUtils; import org.jetbrains.jet.lang.resolve.BindingContext; -import org.jetbrains.jet.lang.resolve.java.JavaDefaultImports; +import org.jetbrains.jet.lang.resolve.java.AnalyzerFacade; import org.jetbrains.jet.plugin.JetFileType; import java.util.*; @@ -211,8 +210,8 @@ public class JavaElementFinder extends PsiElementFinder { if (dirty.size() > 0) { - final BindingContext context = AnalyzingUtils.getInstance(JavaDefaultImports.JAVA_DEFAULT_IMPORTS).shallowAnalyzeFiles(dirty); - state.compileCorrectNamespaces(context, AnalyzingUtils.collectRootNamespaces(dirty)); + final BindingContext context = AnalyzerFacade.shallowAnalyzeFiles(dirty); + state.compileCorrectNamespaces(context, AnalyzerFacade.collectRootNamespaces(dirty)); state.getFactory().files(); } diff --git a/idea/src/org/jetbrains/jet/plugin/references/JetSimpleNameReference.java b/idea/src/org/jetbrains/jet/plugin/references/JetSimpleNameReference.java index a4ccddf8fa0..9fb52fa377c 100644 --- a/idea/src/org/jetbrains/jet/plugin/references/JetSimpleNameReference.java +++ b/idea/src/org/jetbrains/jet/plugin/references/JetSimpleNameReference.java @@ -13,6 +13,7 @@ import org.jetbrains.annotations.NotNull; 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.scopes.JetScope; import org.jetbrains.jet.lang.types.JetType; import org.jetbrains.jet.plugin.compiler.WholeProjectAnalyzerFacade; @@ -99,7 +100,7 @@ class JetSimpleNameReference extends JetPsiReference { typeText = DescriptorRenderer.TEXT.renderType(outType); } else if (descriptor instanceof ClassDescriptor) { - tailText = " (" + DescriptorRenderer.getFQName(descriptor.getContainingDeclaration()) + ")"; + tailText = " (" + DescriptorUtils.getFQName(descriptor.getContainingDeclaration()) + ")"; tailTextGrayed = true; } else { diff --git a/idea/tests/org/jetbrains/jet/completion/JetBasicCompletion.java b/idea/tests/org/jetbrains/jet/completion/JetBasicCompletionTest.java similarity index 86% rename from idea/tests/org/jetbrains/jet/completion/JetBasicCompletion.java rename to idea/tests/org/jetbrains/jet/completion/JetBasicCompletionTest.java index 4de7bb1d400..14bc6d16912 100644 --- a/idea/tests/org/jetbrains/jet/completion/JetBasicCompletion.java +++ b/idea/tests/org/jetbrains/jet/completion/JetBasicCompletionTest.java @@ -11,11 +11,11 @@ import java.io.File; /** * @author Nikolay.Krasko */ -public class JetBasicCompletion extends JetCompletionTestBase { +public class JetBasicCompletionTest extends JetCompletionTestBase { private final String myPath; private final String myName; - public JetBasicCompletion(@NotNull String path, @NotNull String name) { + public JetBasicCompletionTest(@NotNull String path, @NotNull String name) { myPath = path; myName = name; @@ -50,7 +50,7 @@ public class JetBasicCompletion extends JetCompletionTestBase { @NotNull @Override public Test createTest(@NotNull String dataPath, @NotNull String name, @NotNull File file) { - return new JetBasicCompletion(dataPath, name); + return new JetBasicCompletionTest(dataPath, name); } }, suite); diff --git a/stdlib/src/jet/typeinfo/JetMethod.java b/stdlib/src/jet/typeinfo/JetMethod.java new file mode 100644 index 00000000000..a999ce2f298 --- /dev/null +++ b/stdlib/src/jet/typeinfo/JetMethod.java @@ -0,0 +1,27 @@ +package jet.typeinfo; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * Annotation for method + * + * The fact of receiver presence must be deducted from presence of 'this$receiver' parameter + * + * @author alex.tkachman + */ +@Target({ElementType.METHOD}) +@Retention(RetentionPolicy.RUNTIME) +public @interface JetMethod { + /** + * @return type projections or empty + */ + JetTypeProjection[] returnTypeProjections() default {}; + + /** + * @return is this type returnTypeNullable + */ + boolean nullableReturnType() default false; +} diff --git a/stdlib/src/jet/typeinfo/JetParameter.java b/stdlib/src/jet/typeinfo/JetParameter.java new file mode 100644 index 00000000000..bae06e264b1 --- /dev/null +++ b/stdlib/src/jet/typeinfo/JetParameter.java @@ -0,0 +1,35 @@ +package jet.typeinfo; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * Annotation for parameters + * + * @author alex.tkachman + */ +@Target({ElementType.PARAMETER}) +@Retention(RetentionPolicy.RUNTIME) +public @interface JetParameter { + /** + * @return name of parameter + */ + String name (); + + /** + * @return type projections or empty + */ + JetTypeProjection[] typeProjections() default {}; + + /** + * @return is this type nullable + */ + boolean nullable () default false; + + /** + * @return if this parameter has default value + */ + boolean hasDefaultValue () default false; +} diff --git a/stdlib/src/jet/typeinfo/JetTypeDescriptor.java b/stdlib/src/jet/typeinfo/JetTypeDescriptor.java new file mode 100644 index 00000000000..9d289c97b41 --- /dev/null +++ b/stdlib/src/jet/typeinfo/JetTypeDescriptor.java @@ -0,0 +1,20 @@ +package jet.typeinfo; + +/** + * @author alex.tkachman + */ +public @interface JetTypeDescriptor{ + // + // case of type parameter + // + String varName() default ""; + boolean reified () default true; + TypeInfoVariance variance() default TypeInfoVariance.INVARIANT; + int [] upperBounds() default {}; + + // + // case of real type + // + Class javaClass() default Object.class; + JetTypeProjection [] projections() default {}; +} diff --git a/stdlib/src/jet/typeinfo/JetParameterName.java b/stdlib/src/jet/typeinfo/JetTypeParameter.java similarity index 67% rename from stdlib/src/jet/typeinfo/JetParameterName.java rename to stdlib/src/jet/typeinfo/JetTypeParameter.java index 904da5dc449..b57809b98e5 100644 --- a/stdlib/src/jet/typeinfo/JetParameterName.java +++ b/stdlib/src/jet/typeinfo/JetTypeParameter.java @@ -6,10 +6,15 @@ import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; /** + * Annotation for parameters + * * @author alex.tkachman */ @Target({ElementType.PARAMETER}) @Retention(RetentionPolicy.RUNTIME) -public @interface JetParameterName { - String value (); +public @interface JetTypeParameter { + /** + * @return name of parameter + */ + String name(); } diff --git a/stdlib/src/jet/typeinfo/JetTypeProjection.java b/stdlib/src/jet/typeinfo/JetTypeProjection.java new file mode 100644 index 00000000000..3605c0640e6 --- /dev/null +++ b/stdlib/src/jet/typeinfo/JetTypeProjection.java @@ -0,0 +1,20 @@ +package jet.typeinfo; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; + +/** + * @author alex.tkachman + */ +@Retention(RetentionPolicy.RUNTIME) +public @interface JetTypeProjection { + /** + * @return variance of the type + */ + TypeInfoVariance variance(); + + /** + * @return index of the class in the per class table of JetTypeDescriptor + */ + int typeDescriptorIndex(); +} diff --git a/stdlib/src/jet/typeinfo/TypeInfo.java b/stdlib/src/jet/typeinfo/TypeInfo.java index 75f84bb22f2..fa7abb6afa1 100644 --- a/stdlib/src/jet/typeinfo/TypeInfo.java +++ b/stdlib/src/jet/typeinfo/TypeInfo.java @@ -60,7 +60,7 @@ public abstract class TypeInfo implements JetObject { // @NotNull @Override public TypeInfoVariance getVariance() { - return TypeInfoVariance.IN_VARIANCE; + return TypeInfoVariance.IN; } }; } @@ -70,7 +70,7 @@ public abstract class TypeInfo implements JetObject { // @NotNull @Override public TypeInfoVariance getVariance() { - return TypeInfoVariance.OUT_VARIANCE; + return TypeInfoVariance.OUT; } }; } @@ -606,11 +606,11 @@ public abstract class TypeInfo implements JetObject { private TypeInfoVariance parseVariance() { if(string[cur] == 'i' && string[cur+1] == 'n' && string[cur+2] == ' ' ) { cur += 3; - return TypeInfoVariance.IN_VARIANCE; + return TypeInfoVariance.IN; } else if (string[cur] == 'o' && string[cur+1] == 'u' && string[cur+2] == 't' && string[cur+3] == ' ') { cur += 4; - return TypeInfoVariance.OUT_VARIANCE; + return TypeInfoVariance.OUT; } else { return TypeInfoVariance.INVARIANT; diff --git a/stdlib/src/jet/typeinfo/TypeInfoVariance.java b/stdlib/src/jet/typeinfo/TypeInfoVariance.java index 410d45e3c49..647bb6693a9 100644 --- a/stdlib/src/jet/typeinfo/TypeInfoVariance.java +++ b/stdlib/src/jet/typeinfo/TypeInfoVariance.java @@ -5,8 +5,8 @@ package jet.typeinfo; */ public enum TypeInfoVariance { INVARIANT("") , - IN_VARIANCE("in"), - OUT_VARIANCE("out"); + IN("in"), + OUT("out"); private final String label;