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/ExpressionCodegen.java b/compiler/backend/src/org/jetbrains/jet/codegen/ExpressionCodegen.java index a5ef0c787f7..e77bf07342d 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/ExpressionCodegen.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/ExpressionCodegen.java @@ -1196,7 +1196,7 @@ public class ExpressionCodegen extends JetVisitor { receiver.put(receiver.type, v); } - protected void generateFromResolvedCall(ReceiverDescriptor descriptor, Type type) { + public void generateFromResolvedCall(ReceiverDescriptor descriptor, Type type) { if(descriptor instanceof ClassReceiver) { Type exprType = asmType(descriptor.getType()); ClassReceiver classReceiver = (ClassReceiver) descriptor; @@ -1377,7 +1377,8 @@ public class ExpressionCodegen extends JetVisitor { JetType receiverJetType = bindingContext.get(BindingContext.EXPRESSION_TYPE, expression.getReceiverExpression()); Type receiverType = asmType(receiverJetType); gen(expr, receiverType); - if(receiverType.getSort() != Type.OBJECT && receiverType.getSort() != Type.ARRAY) { + assert receiverJetType != null; + if(!receiverJetType.isNullable()) { StackValue propValue = genQualified(StackValue.onStack(receiverType), expression.getSelectorExpression()); Type type = propValue.type; propValue.put(type, v); @@ -1691,18 +1692,26 @@ public class ExpressionCodegen extends JetVisitor { private StackValue generateElvis(JetBinaryExpression expression) { final Type exprType = expressionType(expression); - final Type leftType = expressionType(expression.getLeft()); - gen(expression.getLeft(), leftType); - v.dup(); - Label end = new Label(); - Label ifNull = new Label(); - v.ifnull(ifNull); - StackValue.onStack(leftType).put(exprType, v); - v.goTo(end); - v.mark(ifNull); - v.pop(); - gen(expression.getRight(), exprType); - v.mark(end); + JetType type = bindingContext.get(BindingContext.EXPRESSION_TYPE, expression.getLeft()); + assert type != null; + final Type leftType = asmType(type); + if(type.isNullable()) { + gen(expression.getLeft(), leftType); + v.dup(); + Label end = new Label(); + Label ifNull = new Label(); + v.ifnull(ifNull); + StackValue.onStack(leftType).put(exprType, v); + v.goTo(end); + v.mark(ifNull); + v.pop(); + gen(expression.getRight(), exprType); + v.mark(end); + } + else { + gen(expression.getLeft(), leftType); + StackValue.onStack(leftType).put(exprType, v); + } return StackValue.onStack(exprType); } @@ -1830,7 +1839,7 @@ public class ExpressionCodegen extends JetVisitor { @Override public StackValue visitPrefixExpression(JetPrefixExpression expression, StackValue receiver) { - DeclarationDescriptor op = bindingContext.get(BindingContext.REFERENCE_TARGET, expression.getOperationSign()); + DeclarationDescriptor op = bindingContext.get(BindingContext.REFERENCE_TARGET, expression.getOperationReference()); final Callable callable = resolveToCallable(op, false); if (callable instanceof IntrinsicMethod) { IntrinsicMethod intrinsic = (IntrinsicMethod) callable; @@ -1847,7 +1856,7 @@ public class ExpressionCodegen extends JetVisitor { @Override public StackValue visitPostfixExpression(JetPostfixExpression expression, StackValue receiver) { - DeclarationDescriptor op = bindingContext.get(BindingContext.REFERENCE_TARGET, expression.getOperationSign()); + DeclarationDescriptor op = bindingContext.get(BindingContext.REFERENCE_TARGET, expression.getOperationReference()); if (op instanceof FunctionDescriptor) { final Type asmType = expressionType(expression); DeclarationDescriptor cls = op.getContainingDeclaration(); diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/FunctionCodegen.java b/compiler/backend/src/org/jetbrains/jet/codegen/FunctionCodegen.java index 35999f2461b..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,31 +63,77 @@ 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()) { mv.visitCode(); - FrameMap frameMap = context.prepareFrame(); + + Label methodBegin = new Label(); + mv.visitLabel(methodBegin); + + 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(); @@ -110,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); @@ -126,6 +176,35 @@ public class FunctionCodegen { codegen.returnExpression(bodyExpressions); } + + Label methodEnd = new Label(); + mv.visitLabel(methodEnd); + + int k = 0; + + if(expectedThisObject.exists()) { + Type type = typeMapper.mapType(expectedThisObject.getType()); + // TODO: specify signature + 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); mv.visitEnd(); @@ -148,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) { @@ -164,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) { @@ -183,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; @@ -235,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..e83fd50e11e 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; @@ -82,11 +82,12 @@ public class GenerationState { return factory.forNamespace(namespace); } - public void compile(JetFile psiFile) { + public BindingContext 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)); + return bindingContext; // NamespaceCodegen codegen = forNamespace(namespace); // bindingContexts.push(bindingContext); // typeMapper = new JetTypeMapper(standardLibrary, bindingContext); 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 16a49a0d746..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; @@ -95,16 +95,7 @@ public class JetTypeMapper { } public static boolean isPrimitive(Type type) { - return type == Type.INT_TYPE - || type == Type.SHORT_TYPE - || type == Type.BYTE_TYPE - || type == Type.CHAR_TYPE - || type == Type.SHORT_TYPE - || type == Type.FLOAT_TYPE - || type == Type.DOUBLE_TYPE - || type == Type.LONG_TYPE - || type == Type.BOOLEAN_TYPE - || type == Type.VOID_TYPE; + return type.getSort() != Type.OBJECT && type.getSort() != Type.ARRAY; } public static Type getBoxedType(final Type type) { @@ -139,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; @@ -314,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; } @@ -329,7 +320,8 @@ public class JetTypeMapper { ClassDescriptor containingClass = (ClassDescriptor) functionParent; boolean isInterface = CodegenUtil.isInterface(containingClass); OwnerKind kind1 = isInterface && superCall ? OwnerKind.TRAIT_IMPL : OwnerKind.IMPLEMENTATION; - owner = mapType(containingClass.getDefaultType(), kind1).getInternalName(); + Type type = mapType(containingClass.getDefaultType(), kind1); + owner = type.getInternalName(); invokeOpcode = isInterface ? (superCall ? Opcodes.INVOKESTATIC : Opcodes.INVOKEINTERFACE) : (superCall ? Opcodes.INVOKESPECIAL : Opcodes.INVOKEVIRTUAL); @@ -356,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); @@ -370,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/CompareTo.java b/compiler/backend/src/org/jetbrains/jet/codegen/intrinsics/CompareTo.java new file mode 100644 index 00000000000..991d84c1231 --- /dev/null +++ b/compiler/backend/src/org/jetbrains/jet/codegen/intrinsics/CompareTo.java @@ -0,0 +1,45 @@ +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 CompareTo implements IntrinsicMethod { + @Override + public StackValue generate(ExpressionCodegen codegen, InstructionAdapter v, Type expectedType, @Nullable PsiElement element, @Nullable List arguments, StackValue receiver) { + assert arguments != null; + receiver.put(receiver.type, v); + codegen.gen(arguments.get(0), receiver.type); + if(receiver.type == Type.BYTE_TYPE || receiver.type == Type.SHORT_TYPE || receiver.type == Type.CHAR_TYPE) + v.sub(Type.INT_TYPE); + else if(receiver.type == Type.INT_TYPE) { + v.invokestatic("jet/runtime/Intrinsics", "compare", "(II)I"); + } + else if(receiver.type == Type.BOOLEAN_TYPE) { + v.invokestatic("jet/runtime/Intrinsics", "compare", "(ZZ)I"); + } + else if(receiver.type == Type.LONG_TYPE) { + v.invokestatic("jet/runtime/Intrinsics", "compare", "(JJ)I"); + } + else if(receiver.type == Type.FLOAT_TYPE) { + v.invokestatic("java/lang/Float", "compare", "(FF)I"); + } + else if(receiver.type == Type.DOUBLE_TYPE) { + v.invokestatic("java/lang/Double", "compare", "(DD)I"); + } + else { + throw new UnsupportedOperationException(); + } + return StackValue.onStack(Type.INT_TYPE); + } +} 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 33e107c2143..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); @@ -97,6 +99,9 @@ public class IntrinsicMethods { declareIntrinsicFunction("FloatIterator", "next", 0, ITERATOR_NEXT); declareIntrinsicFunction("DoubleIterator", "next", 0, ITERATOR_NEXT); + for (String type : PRIMITIVE_NUMBER_TYPES) { + declareIntrinsicFunction(type, "compareTo", 1, new CompareTo()); + } // declareIntrinsicFunction("Any", "equals", 1, new Equals()); // declareIntrinsicStringMethods(); 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/Sure.java b/compiler/backend/src/org/jetbrains/jet/codegen/intrinsics/Sure.java index 0019fed155f..c31e2983c25 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/intrinsics/Sure.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/intrinsics/Sure.java @@ -4,7 +4,12 @@ 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.descriptors.CallableDescriptor; +import org.jetbrains.jet.lang.psi.JetCallExpression; import org.jetbrains.jet.lang.psi.JetExpression; +import org.jetbrains.jet.lang.resolve.BindingContext; +import org.jetbrains.jet.lang.resolve.calls.ResolvedCall; +import org.objectweb.asm.Label; import org.objectweb.asm.Type; import org.objectweb.asm.commons.InstructionAdapter; @@ -16,9 +21,21 @@ import java.util.List; public class Sure implements IntrinsicMethod { @Override public StackValue generate(ExpressionCodegen codegen, InstructionAdapter v, Type expectedType, PsiElement element, List arguments, StackValue receiver) { - receiver.put(JetTypeMapper.TYPE_OBJECT, v); - v.invokestatic("jet/runtime/Intrinsics", "sure", "(Ljava/lang/Object;)Ljava/lang/Object;"); - StackValue.onStack(JetTypeMapper.TYPE_OBJECT).put(expectedType, v); + JetCallExpression call = (JetCallExpression) element; + ResolvedCall resolvedCall = codegen.getBindingContext().get(BindingContext.RESOLVED_CALL, call.getCalleeExpression()); + assert resolvedCall != null; + if(resolvedCall.getReceiverArgument().getType().isNullable()) { + receiver.put(receiver.type, v); + v.dup(); + Label ok = new Label(); + v.ifnonnull(ok); + v.invokestatic("jet/runtime/Intrinsics", "throwNpe", "()V"); + v.mark(ok); + StackValue.onStack(receiver.type).put(expectedType, v); + } + else { + codegen.generateFromResolvedCall(resolvedCall.getReceiverArgument(), expectedType); + } return StackValue.onStack(expectedType); } } 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/CompileEnvironment.java b/compiler/backend/src/org/jetbrains/jet/compiler/CompileEnvironment.java index cf23d5c948b..ba0f2765822 100644 --- a/compiler/backend/src/org/jetbrains/jet/compiler/CompileEnvironment.java +++ b/compiler/backend/src/org/jetbrains/jet/compiler/CompileEnvironment.java @@ -356,7 +356,7 @@ public class CompileEnvironment { } } - private static void writeToOutputDirectory(ClassFileFactory factory, final String outputDir) { + public static void writeToOutputDirectory(ClassFileFactory factory, final String outputDir) { List files = factory.files(); for (String file : files) { if(!skipFile(file)) { 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 6e1178a050d..7b581578eb0 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); @@ -326,32 +325,65 @@ public class JavaDescriptorResolver { List result = new ArrayList(); for (int i = 0, parametersLength = parameters.length; i < parametersLength; i++) { PsiParameter parameter = parameters[i]; - String name = parameter.getName(); - PsiType psiType = parameter.getType(); - - JetType varargElementType; - if (psiType instanceof PsiEllipsisType) { - PsiEllipsisType psiEllipsisType = (PsiEllipsisType) psiType; - varargElementType = semanticServices.getTypeTransformer().transformToType(psiEllipsisType.getComponentType()); - } - else { - varargElementType = null; - } - JetType outType = semanticServices.getTypeTransformer().transformToType(psiType); - result.add(new ValueParameterDescriptorImpl( - containingDeclaration, - i, - Collections.emptyList(), // TODO - name == null ? "p" + i : name, - null, // TODO : review - outType, - false, - varargElementType - )); + ValueParameterDescriptor valueParameterDescriptor = resolveParameterDescriptor(containingDeclaration, i, parameter); + result.add(valueParameterDescriptor); } return result; } + private ValueParameterDescriptor resolveParameterDescriptor(DeclarationDescriptor containingDeclaration, int i, PsiParameter parameter) { + PsiType psiType = parameter.getType(); + + JetType varargElementType; + if (psiType instanceof PsiEllipsisType) { + PsiEllipsisType psiEllipsisType = (PsiEllipsisType) psiType; + varargElementType = semanticServices.getTypeTransformer().transformToType(psiEllipsisType.getComponentType()); + } + else { + varargElementType = null; + } + + boolean changeNullable = false; + boolean nullable = true; + + // TODO: must be very slow, make it lazy? + String name = parameter.getName() != null ? parameter.getName() : "p" + i; + for (PsiAnnotation annotation : parameter.getModifierList().getAnnotations()) { + // TODO: softcode annotation name + + PsiNameValuePair[] attributes = annotation.getParameterList().getAttributes(); + attributes.toString(); + + if (annotation.getQualifiedName().equals("jet.typeinfo.JetParameter")) { + PsiLiteralExpression nameExpression = (PsiLiteralExpression) annotation.findAttributeValue("name"); + if (nameExpression != null) { + name = (String) nameExpression.getValue(); + } + + PsiLiteralExpression nullableExpression = (PsiLiteralExpression) annotation.findAttributeValue("nullable"); + if (nullableExpression != null) { + nullable = (Boolean) nullableExpression.getValue(); + } else { + // default value of parameter + nullable = false; + changeNullable = true; + } + } + } + + JetType outType = semanticServices.getTypeTransformer().transformToType(psiType); + return new ValueParameterDescriptorImpl( + containingDeclaration, + i, + Collections.emptyList(), // TODO + name, + null, // TODO : review + changeNullable ? TypeUtils.makeNullableAsSpecified(outType, nullable) : outType, + false, + varargElementType + ); + } + public VariableDescriptor resolveFieldToVariableDescriptor(DeclarationDescriptor containingDeclaration, PsiField field) { VariableDescriptor variableDescriptor = fieldDescriptorCache.get(field); if (variableDescriptor != null) { @@ -363,7 +395,7 @@ public class JavaDescriptorResolver { containingDeclaration, Collections.emptyList(), Modality.FINAL, - resolveVisibilityFromPsiModifiers(semanticServices.getTrace(), field), + resolveVisibilityFromPsiModifiers(field), !isFinal, null, DescriptorUtils.getExpectedThisObjectIfNeeded(containingDeclaration), @@ -449,7 +481,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; @@ -459,7 +491,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.java/src/org/jetbrains/jet/lang/resolve/java/JavaPackageScope.java b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/JavaPackageScope.java index 11b92aee25a..776e5219dfc 100644 --- a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/JavaPackageScope.java +++ b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/JavaPackageScope.java @@ -1,5 +1,6 @@ package org.jetbrains.jet.lang.resolve.java; +import com.intellij.psi.PsiClass; import org.jetbrains.annotations.NotNull; import org.jetbrains.jet.lang.descriptors.*; import org.jetbrains.jet.lang.resolve.scopes.JetScopeImpl; @@ -34,7 +35,17 @@ public class JavaPackageScope extends JetScopeImpl { @NotNull @Override public Set getFunctions(@NotNull String name) { - return Collections.emptySet(); + // TODO: what is GlobalSearchScope + PsiClass psiClass = semanticServices.getDescriptorResolver().javaFacade.findClass(packagePrefix + "namespace"); + if (psiClass == null) { + return Collections.emptySet(); + } + + if (containingDescriptor == null) { + return Collections.emptySet(); + } + + return semanticServices.getDescriptorResolver().resolveFunctionGroup(containingDescriptor, psiClass, null, name, true); } @NotNull diff --git a/compiler/frontend/src/org/jetbrains/jet/JetCoreEnvironment.java b/compiler/frontend/src/org/jetbrains/jet/JetCoreEnvironment.java index eac28f341d6..65218c54fcf 100644 --- a/compiler/frontend/src/org/jetbrains/jet/JetCoreEnvironment.java +++ b/compiler/frontend/src/org/jetbrains/jet/JetCoreEnvironment.java @@ -1,6 +1,7 @@ package org.jetbrains.jet; import com.intellij.core.JavaCoreEnvironment; +import com.intellij.lang.java.JavaParserDefinition; import com.intellij.openapi.Disposable; import org.jetbrains.jet.lang.parsing.JetParserDefinition; import org.jetbrains.jet.plugin.JetFileType; @@ -15,6 +16,7 @@ public class JetCoreEnvironment extends JavaCoreEnvironment { registerFileType(JetFileType.INSTANCE, "kts"); registerFileType(JetFileType.INSTANCE, "ktm"); registerFileType(JetFileType.INSTANCE, "jet"); + registerParserDefinition(new JavaParserDefinition()); registerParserDefinition(new JetParserDefinition()); } } 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/cfg/JetControlFlowProcessor.java b/compiler/frontend/src/org/jetbrains/jet/lang/cfg/JetControlFlowProcessor.java index e0a035d9b0b..44df643b150 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/cfg/JetControlFlowProcessor.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/cfg/JetControlFlowProcessor.java @@ -14,7 +14,6 @@ import org.jetbrains.jet.lang.types.JetType; import org.jetbrains.jet.lang.types.expressions.OperatorConventions; import org.jetbrains.jet.lexer.JetTokens; -import java.util.Collections; import java.util.Iterator; import java.util.LinkedList; import java.util.List; @@ -284,7 +283,7 @@ public class JetControlFlowProcessor { @Override public void visitUnaryExpression(JetUnaryExpression expression) { - JetSimpleNameExpression operationSign = expression.getOperationSign(); + JetSimpleNameExpression operationSign = expression.getOperationReference(); IElementType operationType = operationSign.getReferencedNameElementType(); JetExpression baseExpression = expression.getBaseExpression(); if (baseExpression == null) return; diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/cfg/JetFlowInformationProvider.java b/compiler/frontend/src/org/jetbrains/jet/lang/cfg/JetFlowInformationProvider.java index 4f7166c0425..8050efe8be6 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/cfg/JetFlowInformationProvider.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/cfg/JetFlowInformationProvider.java @@ -288,7 +288,7 @@ public class JetFlowInformationProvider { operationReference = ((JetBinaryExpression) parent).getOperationReference(); } else if (parent instanceof JetUnaryExpression) { - operationReference = ((JetUnaryExpression) parent).getOperationSign(); + operationReference = ((JetUnaryExpression) parent).getOperationReference(); } if (operationReference != null) { DeclarationDescriptor descriptor = trace.get(BindingContext.REFERENCE_TARGET, operationReference); diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/MutableClassDescriptor.java b/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/MutableClassDescriptor.java index 3d80086d425..b8096c3dfdc 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/MutableClassDescriptor.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/MutableClassDescriptor.java @@ -48,6 +48,16 @@ public class MutableClassDescriptor extends MutableDeclarationDescriptor impleme public MutableClassDescriptor(@NotNull BindingTrace trace, @NotNull DeclarationDescriptor containingDeclaration, @NotNull JetScope outerScope, ClassKind kind) { super(containingDeclaration); + + if (containingDeclaration instanceof ClassDescriptor + || containingDeclaration instanceof NamespaceLike + || containingDeclaration instanceof ModuleDescriptor + || containingDeclaration instanceof FunctionDescriptor) + { + } else { + throw new IllegalStateException(); + } + TraceBasedRedeclarationHandler redeclarationHandler = new TraceBasedRedeclarationHandler(trace); this.scopeForMemberLookup = new WritableScopeImpl(JetScope.EMPTY, this, redeclarationHandler).setDebugName("MemberLookup").changeLockLevel(WritableScope.LockLevel.BOTH); this.scopeForSupertypeResolution = new WritableScopeImpl(outerScope, this, redeclarationHandler).setDebugName("SupertypeResolution").changeLockLevel(WritableScope.LockLevel.BOTH); diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/Errors.java b/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/Errors.java index 1a91ce479d5..0cf5938185d 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/Errors.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/Errors.java @@ -8,7 +8,7 @@ import org.jetbrains.annotations.Nullable; import org.jetbrains.jet.lang.descriptors.*; import org.jetbrains.jet.lang.psi.*; import org.jetbrains.jet.lang.types.JetType; -import org.jetbrains.jet.lang.types.inference.SolutionStatus; +import org.jetbrains.jet.lang.resolve.calls.inference.SolutionStatus; import org.jetbrains.jet.lexer.JetKeywordToken; import org.jetbrains.jet.resolve.DescriptorRenderer; diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/psi/JetBinaryExpression.java b/compiler/frontend/src/org/jetbrains/jet/lang/psi/JetBinaryExpression.java index 5d60411e203..01fdbc57ce2 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/psi/JetBinaryExpression.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/psi/JetBinaryExpression.java @@ -10,7 +10,7 @@ import org.jetbrains.jet.JetNodeTypes; /** * @author max */ -public class JetBinaryExpression extends JetExpression { +public class JetBinaryExpression extends JetExpression implements JetOperationExpression { public JetBinaryExpression(@NotNull ASTNode node) { super(node); } @@ -46,6 +46,7 @@ public class JetBinaryExpression extends JetExpression { return null; } + @Override @NotNull public JetSimpleNameExpression getOperationReference() { return (JetSimpleNameExpression) findChildByType(JetNodeTypes.OPERATION_REFERENCE); diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/psi/JetCallExpression.java b/compiler/frontend/src/org/jetbrains/jet/lang/psi/JetCallExpression.java index 987a7481529..7525985bf77 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/psi/JetCallExpression.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/psi/JetCallExpression.java @@ -65,7 +65,7 @@ public class JetCallExpression extends JetExpression implements JetCallElement { } else if (psi instanceof JetPrefixExpression) { JetPrefixExpression prefixExpression = (JetPrefixExpression) psi; - if (JetTokens.LABELS.contains(prefixExpression.getOperationSign().getReferencedNameElementType())) { + if (JetTokens.LABELS.contains(prefixExpression.getOperationReference().getReferencedNameElementType())) { JetExpression labeledExpression = prefixExpression.getBaseExpression(); if (labeledExpression instanceof JetFunctionLiteralExpression) { result.add(labeledExpression); diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/psi/JetOperationExpression.java b/compiler/frontend/src/org/jetbrains/jet/lang/psi/JetOperationExpression.java new file mode 100644 index 00000000000..9c658e8df21 --- /dev/null +++ b/compiler/frontend/src/org/jetbrains/jet/lang/psi/JetOperationExpression.java @@ -0,0 +1,11 @@ +package org.jetbrains.jet.lang.psi; + +import org.jetbrains.annotations.NotNull; + +/** + * @author abreslav + */ +public interface JetOperationExpression { + @NotNull + JetSimpleNameExpression getOperationReference(); +} diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/psi/JetPrefixExpression.java b/compiler/frontend/src/org/jetbrains/jet/lang/psi/JetPrefixExpression.java index 451c00663b4..0c8d1aa2355 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/psi/JetPrefixExpression.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/psi/JetPrefixExpression.java @@ -25,7 +25,7 @@ public class JetPrefixExpression extends JetUnaryExpression { @Nullable @IfNotParsed public JetExpression getBaseExpression() { - PsiElement expression = getOperationSign().getNextSibling(); + PsiElement expression = getOperationReference().getNextSibling(); while (expression != null && !(expression instanceof JetExpression)) { expression = expression.getNextSibling(); } diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/psi/JetPsiUtil.java b/compiler/frontend/src/org/jetbrains/jet/lang/psi/JetPsiUtil.java index 8afc13f7b0f..73433fb6cc9 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/psi/JetPsiUtil.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/psi/JetPsiUtil.java @@ -26,7 +26,7 @@ public class JetPsiUtil { } } else if (expression instanceof JetPrefixExpression) { - if (JetTokens.LABELS.contains(((JetPrefixExpression) expression).getOperationSign().getReferencedNameElementType())) { + if (JetTokens.LABELS.contains(((JetPrefixExpression) expression).getOperationReference().getReferencedNameElementType())) { JetExpression baseExpression = ((JetPrefixExpression) expression).getBaseExpression(); if (baseExpression != null) { expression = baseExpression; diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/psi/JetTypeReference.java b/compiler/frontend/src/org/jetbrains/jet/lang/psi/JetTypeReference.java index faf32b925fd..8dc33d8aa50 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/psi/JetTypeReference.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/psi/JetTypeReference.java @@ -10,6 +10,9 @@ import java.util.Collections; import java.util.List; /** + * Type reference element. + * Underlying token is {@link org.jetbrains.jet.JetNodeTypes#TYPE_REFERENCE} + * * @author max */ public class JetTypeReference extends JetElement { diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/psi/JetUnaryExpression.java b/compiler/frontend/src/org/jetbrains/jet/lang/psi/JetUnaryExpression.java index ca81e0d0735..87d9a2f6758 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/psi/JetUnaryExpression.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/psi/JetUnaryExpression.java @@ -8,7 +8,7 @@ import org.jetbrains.jet.JetNodeTypes; /** * @author abreslav */ -public abstract class JetUnaryExpression extends JetExpression { +public abstract class JetUnaryExpression extends JetExpression implements JetOperationExpression { public JetUnaryExpression(ASTNode node) { super(node); } @@ -16,8 +16,9 @@ public abstract class JetUnaryExpression extends JetExpression { @Nullable @IfNotParsed public abstract JetExpression getBaseExpression(); + @Override @NotNull - public JetSimpleNameExpression getOperationSign() { + public JetSimpleNameExpression getOperationReference() { return (JetSimpleNameExpression) findChildByType(JetNodeTypes.OPERATION_REFERENCE); } } 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/BindingContext.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/BindingContext.java index 5a14b835dad..5e8557fd62a 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/BindingContext.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/BindingContext.java @@ -41,11 +41,15 @@ public interface BindingContext { WritableSlice> INDEXED_LVALUE_SET = Slices.createSimpleSlice(); WritableSlice AUTOCAST = Slices.createSimpleSlice(); + + /** A scope where type of expression has been resolved */ WritableSlice RESOLUTION_SCOPE = Slices.createSimpleSlice(); WritableSlice VARIABLE_REASSIGNMENT = Slices.createSimpleSetSlice(); WritableSlice AUTO_CREATED_IT = Slices.createSimpleSetSlice(); WritableSlice VARIABLE_ASSIGNMENT = Slices.createSimpleSlice(); + + /** Has type of current expression has been already resolved */ WritableSlice PROCESSED = Slices.createSimpleSetSlice(); WritableSlice STATEMENT = Slices.createRemovableSetSlice(); WritableSlice DELEGATED = Slices.createRemovableSetSlice(); 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/TypeResolver.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/TypeResolver.java index 654135be994..8896830d305 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/TypeResolver.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/TypeResolver.java @@ -49,11 +49,14 @@ public class TypeResolver { JetTypeElement typeElement = typeReference.getTypeElement(); JetType type = resolveTypeElement(scope, annotations, typeElement, false); trace.record(BindingContext.TYPE, typeReference, type); + return type; } @NotNull - private JetType resolveTypeElement(final JetScope scope, final List annotations, JetTypeElement typeElement, final boolean nullable) { + private JetType resolveTypeElement(final JetScope scope, final List annotations, + JetTypeElement typeElement, final boolean nullable) { + final JetType[] result = new JetType[1]; if (typeElement != null) { typeElement.accept(new JetVisitorVoid() { @@ -70,6 +73,7 @@ public class TypeResolver { resolveTypeProjections(scope, ErrorUtils.createErrorType("No type").getConstructor(), type.getTypeArguments()); return; } + if (classifierDescriptor instanceof TypeParameterDescriptor) { TypeParameterDescriptor typeParameterDescriptor = (TypeParameterDescriptor) classifierDescriptor; @@ -268,6 +272,8 @@ public class TypeResolver { ClassifierDescriptor classifierDescriptor; if (userType.isAbsoluteInRootNamespace()) { classifierDescriptor = JetModuleUtil.getRootNamespaceType(userType).getMemberScope().getClassifier(referencedName); + trace.record(BindingContext.RESOLUTION_SCOPE, userType.getReferenceExpression(), + JetModuleUtil.getRootNamespaceType(userType).getMemberScope()); } else { JetUserType qualifier = userType.getQualifier(); @@ -278,7 +284,9 @@ public class TypeResolver { return ErrorUtils.getErrorClass(); } classifierDescriptor = scope.getClassifier(referencedName); + trace.record(BindingContext.RESOLUTION_SCOPE, userType.getReferenceExpression(), scope); } + return classifierDescriptor; } diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/CallMaker.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/CallMaker.java index 1dc4a2e08c0..62f6a07f69b 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/CallMaker.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/CallMaker.java @@ -162,7 +162,7 @@ public class CallMaker { } public static Call makeCall(@NotNull ReceiverDescriptor baseAsReceiver, JetUnaryExpression expression) { - return makeCall(expression, baseAsReceiver, null, expression.getOperationSign(), Collections.emptyList()); + return makeCall(expression, baseAsReceiver, null, expression.getOperationReference(), Collections.emptyList()); } public static Call makeArraySetCall(@NotNull ReceiverDescriptor arrayAsReceiver, JetArrayAccessExpression arrayAccessExpression, JetExpression rightHandSide) { diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/CallResolver.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/CallResolver.java index 09fef717803..f73557fcdd4 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/CallResolver.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/CallResolver.java @@ -19,10 +19,10 @@ import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor; import org.jetbrains.jet.lang.types.*; import org.jetbrains.jet.lang.types.expressions.ExpressionTypingServices; import org.jetbrains.jet.lang.types.expressions.OperatorConventions; -import org.jetbrains.jet.lang.types.inference.ConstraintSystem; -import org.jetbrains.jet.lang.types.inference.ConstraintSystemSolution; -import org.jetbrains.jet.lang.types.inference.ConstraintSystemImpl; -import org.jetbrains.jet.lang.types.inference.SolutionStatus; +import org.jetbrains.jet.lang.resolve.calls.inference.ConstraintSystem; +import org.jetbrains.jet.lang.resolve.calls.inference.ConstraintSystemSolution; +import org.jetbrains.jet.lang.resolve.calls.inference.ConstraintSystemImpl; +import org.jetbrains.jet.lang.resolve.calls.inference.SolutionStatus; import org.jetbrains.jet.lexer.JetTokens; import java.util.*; diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/TracingStrategy.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/TracingStrategy.java index 40d06bf6999..5e07ebb9e76 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/TracingStrategy.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/TracingStrategy.java @@ -6,7 +6,7 @@ import org.jetbrains.jet.lang.descriptors.ValueParameterDescriptor; import org.jetbrains.jet.lang.resolve.BindingTrace; import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor; import org.jetbrains.jet.lang.types.JetType; -import org.jetbrains.jet.lang.types.inference.SolutionStatus; +import org.jetbrains.jet.lang.resolve.calls.inference.SolutionStatus; import java.util.Collection; diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/types/inference/ConstraintSystem.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/inference/ConstraintSystem.java similarity index 90% rename from compiler/frontend/src/org/jetbrains/jet/lang/types/inference/ConstraintSystem.java rename to compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/inference/ConstraintSystem.java index 20b47986c0b..8511fb78b37 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/types/inference/ConstraintSystem.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/inference/ConstraintSystem.java @@ -1,4 +1,4 @@ -package org.jetbrains.jet.lang.types.inference; +package org.jetbrains.jet.lang.resolve.calls.inference; import org.jetbrains.annotations.NotNull; import org.jetbrains.jet.lang.descriptors.TypeParameterDescriptor; diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/types/inference/ConstraintSystemImpl.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/inference/ConstraintSystemImpl.java similarity index 99% rename from compiler/frontend/src/org/jetbrains/jet/lang/types/inference/ConstraintSystemImpl.java rename to compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/inference/ConstraintSystemImpl.java index f5baf6d6e77..fd274762a09 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/types/inference/ConstraintSystemImpl.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/inference/ConstraintSystemImpl.java @@ -1,4 +1,4 @@ -package org.jetbrains.jet.lang.types.inference; +package org.jetbrains.jet.lang.resolve.calls.inference; import com.google.common.collect.Maps; import com.google.common.collect.Sets; diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/types/inference/ConstraintSystemSolution.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/inference/ConstraintSystemSolution.java similarity index 90% rename from compiler/frontend/src/org/jetbrains/jet/lang/types/inference/ConstraintSystemSolution.java rename to compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/inference/ConstraintSystemSolution.java index 40a2cbbb90e..cffdca00922 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/types/inference/ConstraintSystemSolution.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/inference/ConstraintSystemSolution.java @@ -1,4 +1,4 @@ -package org.jetbrains.jet.lang.types.inference; +package org.jetbrains.jet.lang.resolve.calls.inference; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/types/inference/SolutionStatus.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/inference/SolutionStatus.java similarity index 81% rename from compiler/frontend/src/org/jetbrains/jet/lang/types/inference/SolutionStatus.java rename to compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/inference/SolutionStatus.java index 0fd5cd02517..eae73924099 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/types/inference/SolutionStatus.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/inference/SolutionStatus.java @@ -1,4 +1,4 @@ -package org.jetbrains.jet.lang.types.inference; +package org.jetbrains.jet.lang.resolve.calls.inference; /** * @author abreslav 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/lang/types/expressions/BasicExpressionTypingVisitor.java b/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/BasicExpressionTypingVisitor.java index c59643b06d6..a2898afa2dd 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/BasicExpressionTypingVisitor.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/BasicExpressionTypingVisitor.java @@ -613,7 +613,7 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor { public JetType visitUnaryExpression(JetUnaryExpression expression, ExpressionTypingContext context) { JetExpression baseExpression = expression.getBaseExpression(); if (baseExpression == null) return null; - JetSimpleNameExpression operationSign = expression.getOperationSign(); + JetSimpleNameExpression operationSign = expression.getOperationReference(); if (JetTokens.LABELS.contains(operationSign.getReferencedNameElementType())) { String referencedName = operationSign.getReferencedName(); referencedName = referencedName == null ? " " : referencedName; @@ -634,7 +634,7 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor { FunctionDescriptor functionDescriptor = context.resolveCallWithGivenNameToDescriptor( CallMaker.makeCall(receiver, expression), - expression.getOperationSign(), + expression.getOperationReference(), name); if (functionDescriptor == null) return null; diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/DataFlowUtils.java b/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/DataFlowUtils.java index 9d1fcc2974e..e8e4e992221 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/DataFlowUtils.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/DataFlowUtils.java @@ -109,7 +109,7 @@ public class DataFlowUtils { @Override public void visitUnaryExpression(JetUnaryExpression expression) { - IElementType operationTokenType = expression.getOperationSign().getReferencedNameElementType(); + IElementType operationTokenType = expression.getOperationReference().getReferencedNameElementType(); if (operationTokenType == JetTokens.EXCL) { JetExpression baseExpression = expression.getBaseExpression(); if (baseExpression != null) { 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/testData/diagnostics/tests/regressions/kt716.jet b/compiler/testData/diagnostics/tests/regressions/kt716.jet new file mode 100644 index 00000000000..5e06695ad54 --- /dev/null +++ b/compiler/testData/diagnostics/tests/regressions/kt716.jet @@ -0,0 +1,13 @@ +// KT-716 Type inference failed +// +JDK + +fun typeinfo.TypeInfo.getJavaClass() : java.lang.Class { + val t : java.lang.Object = this as java.lang.Object + return t.getClass() as java.lang.Class // inferred type is Object but Serializable was expected +} + +fun getJavaClass() = typeinfo.typeinfo.getJavaClass() + +fun main(args : Array) { + System.out?.println(getJavaClass) +} \ No newline at end of file diff --git a/compiler/testData/readClass/Class.kt b/compiler/testData/readClass/Class.kt new file mode 100644 index 00000000000..957e3e9c54d --- /dev/null +++ b/compiler/testData/readClass/Class.kt @@ -0,0 +1,3 @@ +namespace test + +class Ramification diff --git a/compiler/testData/readClass/ClassFun.kt b/compiler/testData/readClass/ClassFun.kt new file mode 100644 index 00000000000..27eb0bc5e37 --- /dev/null +++ b/compiler/testData/readClass/ClassFun.kt @@ -0,0 +1,5 @@ +namespace test + +class River { + fun song() = 1 +} diff --git a/compiler/testData/readClass/FunParamNotNull.kt b/compiler/testData/readClass/FunParamNotNull.kt new file mode 100644 index 00000000000..72d84f88278 --- /dev/null +++ b/compiler/testData/readClass/FunParamNotNull.kt @@ -0,0 +1,3 @@ +namespace test + +fun fff(a: String) = 1 diff --git a/compiler/testData/readClass/FunParamNullable.kt b/compiler/testData/readClass/FunParamNullable.kt new file mode 100644 index 00000000000..288582a2f08 --- /dev/null +++ b/compiler/testData/readClass/FunParamNullable.kt @@ -0,0 +1,3 @@ +namespace test + +fun fff(a: String?) = 1 diff --git a/compiler/testData/readClass/NsFun.kt b/compiler/testData/readClass/NsFun.kt new file mode 100644 index 00000000000..6fc14ecc6df --- /dev/null +++ b/compiler/testData/readClass/NsFun.kt @@ -0,0 +1,3 @@ +namespace test + +fun f() = 1 diff --git a/compiler/tests/org/jetbrains/jet/JetTestCaseBuilder.java b/compiler/tests/org/jetbrains/jet/JetTestCaseBuilder.java index e182951833a..ca7256763fb 100644 --- a/compiler/tests/org/jetbrains/jet/JetTestCaseBuilder.java +++ b/compiler/tests/org/jetbrains/jet/JetTestCaseBuilder.java @@ -32,7 +32,7 @@ public abstract class JetTestCaseBuilder { } public interface NamedTestFactory { - @NotNull Test createTest(@NotNull String dataPath, @NotNull String name); + @NotNull Test createTest(@NotNull String dataPath, @NotNull String name, @NotNull File file); } @NotNull @@ -90,7 +90,7 @@ public abstract class JetTestCaseBuilder { String fileName = file.getName(); assert fileName != null; String extension = fileName.endsWith(extensionJet) ? extensionJet : extensionKt; - suite.addTest(factory.createTest(dataPath, fileName.substring(0, fileName.length() - extension.length()))); + suite.addTest(factory.createTest(dataPath, fileName.substring(0, fileName.length() - extension.length()), file)); } } } 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/ReadClassDataTest.java b/compiler/tests/org/jetbrains/jet/ReadClassDataTest.java new file mode 100644 index 00000000000..b476555280e --- /dev/null +++ b/compiler/tests/org/jetbrains/jet/ReadClassDataTest.java @@ -0,0 +1,247 @@ +package org.jetbrains.jet; + +import com.intellij.lang.ASTFactory; +import com.intellij.lang.LanguageASTFactory; +import com.intellij.lang.java.JavaLanguage; +import com.intellij.openapi.Disposable; +import com.intellij.openapi.util.Disposer; +import com.intellij.openapi.util.io.FileUtil; +import com.intellij.openapi.vfs.CharsetToolkit; +import com.intellij.psi.PsiFileFactory; +import com.intellij.psi.impl.PsiFileFactoryImpl; +import com.intellij.psi.impl.source.tree.JavaASTFactory; +import com.intellij.testFramework.LightVirtualFile; +import com.intellij.testFramework.UsefulTestCase; +import junit.framework.Test; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.jet.codegen.ClassBuilderFactory; +import org.jetbrains.jet.codegen.ClassFileFactory; +import org.jetbrains.jet.codegen.GenerationState; +import org.jetbrains.jet.compiler.CompileEnvironment; +import org.jetbrains.jet.lang.JetSemanticServices; +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.descriptors.FunctionDescriptor; +import org.jetbrains.jet.lang.descriptors.NamespaceDescriptor; +import org.jetbrains.jet.lang.descriptors.ValueParameterDescriptor; +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.BindingTraceContext; +import org.jetbrains.jet.lang.resolve.java.JavaDescriptorResolver; +import org.jetbrains.jet.lang.resolve.java.JavaSemanticServices; +import org.jetbrains.jet.plugin.JetLanguage; +import org.junit.Assert; + +import java.io.File; +import java.io.IOException; +import java.lang.reflect.Method; +import java.util.Arrays; +import java.util.Set; + +/** + * @author Stepan Koltsov + */ +public class ReadClassDataTest extends UsefulTestCase { + + protected final Disposable myTestRootDisposable = new Disposable() { + @Override + public void dispose() { + } + }; + + private JetCoreEnvironment jetCoreEnvironment; + private File tmpdir; + + private final File testFile; + + public ReadClassDataTest(@NotNull File testFile) { + this.testFile = testFile; + setName(testFile.getName()); + } + + @Override + protected void setUp() throws Exception { + super.setUp(); + tmpdir = new File("tmp/" + this.getClass().getSimpleName() + "." + this.getName()); + rmrf(tmpdir); + mkdirs(tmpdir); + } + + @Override + public void tearDown() throws Exception { + Disposer.dispose(myTestRootDisposable); + } + + private void mkdirs(File file) throws IOException { + if (file.isDirectory()) { + return; + } + if (!file.mkdirs()) { + throw new IOException(); + } + } + + private void rmrf(File file) { + if (file != null) { + File[] children = file.listFiles(); + if (children != null) { + for (File child : children) { + rmrf(child); + } + } + file.delete(); + } + } + + private void createMockCoreEnvironment() { + jetCoreEnvironment = new JetCoreEnvironment(myTestRootDisposable); + + final File rtJar = new File(JetTestCaseBuilder.getHomeDirectory(), "compiler/testData/mockJDK-1.7/jre/lib/rt.jar"); + jetCoreEnvironment.addToClasspath(rtJar); + jetCoreEnvironment.addToClasspath(new File(JetTestCaseBuilder.getHomeDirectory(), "compiler/testData/mockJDK-1.7/jre/lib/annotations.jar")); + } + + @Override + public void runTest() throws Exception { + if (true) return; + + createMockCoreEnvironment(); + + LanguageASTFactory.INSTANCE.addExplicitExtension(JavaLanguage.INSTANCE, new JavaASTFactory()); + + + String text = FileUtil.loadFile(testFile); + + LightVirtualFile virtualFile = new LightVirtualFile("Hello.kt", JetLanguage.INSTANCE, text); + virtualFile.setCharset(CharsetToolkit.UTF8_CHARSET); + JetFile psiFile = (JetFile) ((PsiFileFactoryImpl) PsiFileFactory.getInstance(jetCoreEnvironment.getProject())).trySetupPsiForFile(virtualFile, JetLanguage.INSTANCE, true, false); + + GenerationState state = new GenerationState(jetCoreEnvironment.getProject(), ClassBuilderFactory.BINARIES); + AnalyzingUtils.checkForSyntacticErrors(psiFile); + BindingContext bindingContext = state.compile(psiFile); + + ClassFileFactory classFileFactory = state.getFactory(); + + CompileEnvironment.writeToOutputDirectory(classFileFactory, tmpdir.getPath()); + + NamespaceDescriptor namespaceFromSource = (NamespaceDescriptor) bindingContext.get(BindingContext.DECLARATION_TO_DESCRIPTOR, psiFile.getRootNamespace()); + + Assert.assertEquals("test", namespaceFromSource.getName()); + + Disposer.dispose(myTestRootDisposable); + + + + createMockCoreEnvironment(); + + jetCoreEnvironment.addToClasspath(tmpdir); + + JetSemanticServices jetSemanticServices = JetSemanticServices.createSemanticServices(jetCoreEnvironment.getProject()); + JavaSemanticServices semanticServices = new JavaSemanticServices(jetCoreEnvironment.getProject(), jetSemanticServices, new BindingTraceContext()); + + JavaDescriptorResolver javaDescriptorResolver = semanticServices.getDescriptorResolver(); + NamespaceDescriptor namespaceFromClass = javaDescriptorResolver.resolveNamespace("test"); + + compareNamespaces(namespaceFromSource, namespaceFromClass); + } + + private void compareNamespaces(@NotNull NamespaceDescriptor nsa, @NotNull NamespaceDescriptor nsb) { + Assert.assertEquals(nsa.getName(), nsb.getName()); + System.out.println("namespace " + nsa.getName()); + for (DeclarationDescriptor ad : nsa.getMemberScope().getAllDescriptors()) { + if (ad instanceof ClassifierDescriptor) { + ClassifierDescriptor bd = nsb.getMemberScope().getClassifier(ad.getName()); + compareClassifiers((ClassifierDescriptor) ad, bd); + } else if (ad instanceof FunctionDescriptor) { + Set functions = nsb.getMemberScope().getFunctions(ad.getName()); + Assert.assertTrue(functions.size() >= 1); + Assert.assertTrue("not implemented", functions.size() == 1); + FunctionDescriptor bd = functions.iterator().next(); + compareFunctions((FunctionDescriptor) ad, bd); + } else { + throw new AssertionError("Unknown member: " + ad); + } + } + } + + private void compareClassifiers(@NotNull ClassifierDescriptor a, @NotNull ClassifierDescriptor b) { + Assert.assertEquals(a.getName(), b.getName()); + System.out.println("classifier " + a.getName()); + if (a instanceof ClassDescriptor || b instanceof ClassDescriptor) { + compareClasses((ClassDescriptor) a, (ClassDescriptor) b); + } + } + + private void compareClasses(@NotNull ClassDescriptor a, @NotNull ClassDescriptor b) { + System.out.println("... is class"); + } + + private void compareFunctions(@NotNull FunctionDescriptor a, @NotNull FunctionDescriptor b) { + Assert.assertEquals(a.getName(), b.getName()); + Assert.assertEquals(a.getValueParameters().size(), b.getValueParameters().size()); + for (int i = 0; i < a.getValueParameters().size(); ++i) { + compareAnything(ValueParameterDescriptor.class, a.getValueParameters().get(i), b.getValueParameters().get(i)); + } + System.out.println("function " + a.getName()); + } + + private void compareAnything(Class clazz, T a, T b) { + System.out.println("Comparing " + clazz); + Assert.assertNotNull(a); + Assert.assertNotNull(b); + + for (Method method : clazz.getMethods()) { + if (!isGetter(method)) { + continue; + } + if (method.getName().equals("getContainingDeclaration")) { + continue; + } + + if (clazz.equals(ValueParameterDescriptor.class)) { + if (method.getName().equals("isRef") || method.getName().equals("getOriginal")) { + continue; + } + } + + System.out.println(method.getName()); + Object ap = invoke(method, a); + Object bp = invoke(method, b); + Assert.assertEquals(ap, bp); + } + } + + private static boolean isGetter(Method method) { + if (method.getParameterTypes().length > 0) { + return false; + } + if (method.getName().matches("is.+")) { + return method.getReturnType().equals(boolean.class); + } else if (method.getName().matches("get.+")) { + return true; + } else { + return false; + } + } + + private static Object invoke(Method method, Object thiz, Object... args) { + try { + return method.invoke(thiz, args); + } catch (Exception e) { + throw new RuntimeException("failed to invoke " + method + ": " + e); + } + } + + public static Test suite() { + return JetTestCaseBuilder.suiteForDirectory(JetTestCaseBuilder.getTestDataPathBase(), "/readClass", true, new JetTestCaseBuilder.NamedTestFactory() { + @NotNull + @Override + public Test createTest(@NotNull String dataPath, @NotNull String name, @NotNull File file) { + return new ReadClassDataTest(file); + } + }); + } + +} diff --git a/compiler/tests/org/jetbrains/jet/cfg/JetControlFlowTest.java b/compiler/tests/org/jetbrains/jet/cfg/JetControlFlowTest.java index 820bc7a431d..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) { @@ -420,7 +420,7 @@ public class JetControlFlowTest extends JetLiteFixture { suite.addTest(JetTestCaseBuilder.suiteForDirectory(JetTestCaseBuilder.getTestDataPathBase(), "/cfg/", true, new JetTestCaseBuilder.NamedTestFactory() { @NotNull @Override - public Test createTest(@NotNull String dataPath, @NotNull String name) { + public Test createTest(@NotNull String dataPath, @NotNull String name, @NotNull File file) { return new JetControlFlowTest(dataPath, name); } })); 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 942ab311916..e661113e310 100644 --- a/compiler/tests/org/jetbrains/jet/checkers/JetDiagnosticsTest.java +++ b/compiler/tests/org/jetbrains/jet/checkers/JetDiagnosticsTest.java @@ -9,15 +9,16 @@ 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; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -81,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) { @@ -167,7 +174,7 @@ public class JetDiagnosticsTest extends JetLiteFixture { return JetTestCaseBuilder.suiteForDirectory(JetTestCaseBuilder.getTestDataPathBase(), "/diagnostics/tests", true, new JetTestCaseBuilder.NamedTestFactory() { @NotNull @Override - public Test createTest(@NotNull String dataPath, @NotNull String name) { + public Test createTest(@NotNull String dataPath, @NotNull String name, @NotNull File file) { return new JetDiagnosticsTest(dataPath, name); } }); diff --git a/compiler/tests/org/jetbrains/jet/codegen/FunctionGenTest.java b/compiler/tests/org/jetbrains/jet/codegen/FunctionGenTest.java index 8ab99d48757..7b5a7a33e7a 100644 --- a/compiler/tests/org/jetbrains/jet/codegen/FunctionGenTest.java +++ b/compiler/tests/org/jetbrains/jet/codegen/FunctionGenTest.java @@ -39,7 +39,7 @@ public class FunctionGenTest extends CodegenTestCase { loadText("fun foo(x: String?, y: Any?) = x + y"); String text = generateToText(); assertTrue(text.contains(".stringPlus")); - System.out.println(text); +// System.out.println(text); Method foo = generateFunction(); assertEquals("something239", foo.invoke(null, "something", 239)); assertEquals("null239", foo.invoke(null, null, 239)); @@ -52,7 +52,7 @@ public class FunctionGenTest extends CodegenTestCase { loadText("fun foo(x: String, y: Any?) = x + y + 120"); String text = generateToText(); assertFalse(text.contains(".stringPlus")); - System.out.println(text); +// System.out.println(text); Method foo = generateFunction(); assertEquals("something239120", foo.invoke(null, "something", 239)); assertEquals("null239120", foo.invoke(null, null, 239)); diff --git a/compiler/tests/org/jetbrains/jet/codegen/PrimitiveTypesTest.java b/compiler/tests/org/jetbrains/jet/codegen/PrimitiveTypesTest.java index 033f9c56b68..0c7ad33b70b 100644 --- a/compiler/tests/org/jetbrains/jet/codegen/PrimitiveTypesTest.java +++ b/compiler/tests/org/jetbrains/jet/codegen/PrimitiveTypesTest.java @@ -285,6 +285,36 @@ public class PrimitiveTypesTest extends CodegenTestCase { blackBoxFile("regressions/kt518.jet"); } + public void testKt711 () throws Exception { + loadText("fun box() = if ((1 ?: 0) == 1) \"OK\" else \"fail\""); + blackBox(); + } + + public void testSureNonnull () throws Exception { + loadText("fun box() = 10.sure().toString()"); + assertFalse(generateToText().contains("IFNONNULL")); + } + + public void testSureNullable () throws Exception { + loadText("val a : Int? = 10; fun box() = a.sure().toString()"); + assertTrue(generateToText().contains("IFNONNULL")); + } + + public void testSafeNonnull () throws Exception { + loadText("fun box() = 10?.toString()"); + assertFalse(generateToText().contains("IFNULL")); + } + + public void testSafeNullable () throws Exception { + loadText("val a : Int? = 10; fun box() = a?.toString()"); + 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\""); + assertEquals("OK", blackBox()); + } + public void testKt665() throws Exception { loadText("fun f(x: Long, zzz: Long = 1): Long\n" + "{\n" + @@ -298,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/parsing/JetParsingTest.java b/compiler/tests/org/jetbrains/jet/parsing/JetParsingTest.java index 1a2dadff195..0191484e111 100644 --- a/compiler/tests/org/jetbrains/jet/parsing/JetParsingTest.java +++ b/compiler/tests/org/jetbrains/jet/parsing/JetParsingTest.java @@ -104,7 +104,7 @@ public class JetParsingTest extends ParsingTestCase { JetTestCaseBuilder.NamedTestFactory factory = new JetTestCaseBuilder.NamedTestFactory() { @NotNull @Override - public Test createTest(@NotNull String dataPath, @NotNull String name) { + public Test createTest(@NotNull String dataPath, @NotNull String name, @NotNull File file) { return new JetParsingTest(dataPath, name); } }; 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/compiler/tests/org/jetbrains/jet/resolve/JetResolveTest.java b/compiler/tests/org/jetbrains/jet/resolve/JetResolveTest.java index ca206ae88c0..0e772f2acd4 100644 --- a/compiler/tests/org/jetbrains/jet/resolve/JetResolveTest.java +++ b/compiler/tests/org/jetbrains/jet/resolve/JetResolveTest.java @@ -157,7 +157,7 @@ public class JetResolveTest extends ExtensibleResolveTestCase { return JetTestCaseBuilder.suiteForDirectory(getHomeDirectory() + "/compiler/testData/", "/resolve/", true, new JetTestCaseBuilder.NamedTestFactory() { @NotNull @Override - public Test createTest(@NotNull String dataPath, @NotNull String name) { + public Test createTest(@NotNull String dataPath, @NotNull String name, @NotNull File file) { return new JetResolveTest(dataPath + "/" + name + ".jet", name); } }); diff --git a/compiler/tests/org/jetbrains/jet/runtime/JetNpeTest.java b/compiler/tests/org/jetbrains/jet/runtime/JetNpeTest.java index 51dd11b201b..a4ad31bfa9b 100644 --- a/compiler/tests/org/jetbrains/jet/runtime/JetNpeTest.java +++ b/compiler/tests/org/jetbrains/jet/runtime/JetNpeTest.java @@ -8,7 +8,7 @@ import java.lang.reflect.Method; public class JetNpeTest extends CodegenTestCase { public void testStackTrace () { try { - Intrinsics.sure(null); + Intrinsics.throwNpe(); fail("No Sure thrown"); } catch (NullPointerException e) { @@ -25,7 +25,7 @@ public class JetNpeTest extends CodegenTestCase { public void testNull () throws Exception { loadText("fun box() = if(null.sure() == 10) \"OK\" else \"fail\""); - System.out.println(generateToText()); +// System.out.println(generateToText()); Method box = generateFunction("box"); assertThrows(box, NullPointerException.class, null); } diff --git a/idea/src/META-INF/plugin.xml b/idea/src/META-INF/plugin.xml index 472e7e9f54e..a42a55fc25b 100644 --- a/idea/src/META-INF/plugin.xml +++ b/idea/src/META-INF/plugin.xml @@ -59,7 +59,9 @@ + diff --git a/idea/src/org/jetbrains/jet/plugin/JetQuickDocumentationProvider.java b/idea/src/org/jetbrains/jet/plugin/JetQuickDocumentationProvider.java index fc2dfbece84..5ab5eec567b 100644 --- a/idea/src/org/jetbrains/jet/plugin/JetQuickDocumentationProvider.java +++ b/idea/src/org/jetbrains/jet/plugin/JetQuickDocumentationProvider.java @@ -52,6 +52,11 @@ public class JetQuickDocumentationProvider extends AbstractDocumentationProvider return "Not a reference"; } + @Override + public String generateDoc(PsiElement element, PsiElement originalElement) { + return getQuickNavigateInfo(element, originalElement); + } + private String render(DeclarationDescriptor declarationDescriptor) { return DescriptorRenderer.HTML.render(declarationDescriptor); } diff --git a/idea/src/org/jetbrains/jet/plugin/annotations/LabelsAnnotator.java b/idea/src/org/jetbrains/jet/plugin/annotations/LabelsAnnotator.java index f29c07db362..f7d227f4984 100644 --- a/idea/src/org/jetbrains/jet/plugin/annotations/LabelsAnnotator.java +++ b/idea/src/org/jetbrains/jet/plugin/annotations/LabelsAnnotator.java @@ -20,7 +20,7 @@ public class LabelsAnnotator implements Annotator { element.accept(new JetVisitorVoid() { @Override public void visitPrefixExpression(JetPrefixExpression expression) { - JetSimpleNameExpression operationSign = expression.getOperationSign(); + JetSimpleNameExpression operationSign = expression.getOperationReference(); if (JetTokens.LABELS.contains(operationSign.getReferencedNameElementType())) { holder.createInfoAnnotation(operationSign, null).setTextAttributes(JetHighlighter.JET_LABEL_IDENTIFIER); } 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 49cead70134..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; @@ -78,7 +79,6 @@ class JetSimpleNameReference extends JetPsiReference { private Object[] collectLookupElements(BindingContext bindingContext, JetScope scope) { List result = Lists.newArrayList(); for (final DeclarationDescriptor descriptor : scope.getAllDescriptors()) { - PsiElement declaration = bindingContext.get(BindingContext.DESCRIPTOR_TO_DECLARATION, descriptor.getOriginal()); LookupElementBuilder element = LookupElementBuilder.create(descriptor.getName()); String typeText = ""; String tailText = ""; @@ -100,16 +100,19 @@ 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 { typeText = DescriptorRenderer.TEXT.render(descriptor); } element = element.setTailText(tailText, tailTextGrayed).setTypeText(typeText); + + PsiElement declaration = bindingContext.get(BindingContext.DESCRIPTOR_TO_DECLARATION, descriptor.getOriginal()); if (declaration != null) { element = element.setIcon(declaration.getIcon(Iconable.ICON_FLAG_OPEN | Iconable.ICON_FLAG_VISIBILITY)); } + result.add(element); } return result.toArray(); diff --git a/idea/testData/checker/Bounds.jet b/idea/testData/checker/Bounds.jet index 87d5cfa1579..8434607edf8 100644 --- a/idea/testData/checker/Bounds.jet +++ b/idea/testData/checker/Bounds.jet @@ -24,17 +24,3 @@ namespace boundsWithSubstitutors { abstract val x : fun (B<Char>) : B<Any> } - -fun test() { - foo<Int?>() - foo() - bar() - bar() - bar<Double?>() - bar<Double>() - 1.buzz<Double>() -} - -fun foo() {} -fun bar() {} -fun Int> Int.buzz() : Unit {} diff --git a/idea/testData/checker/Bounds2.jet b/idea/testData/checker/Bounds2.jet new file mode 100644 index 00000000000..c53d78acb4b --- /dev/null +++ b/idea/testData/checker/Bounds2.jet @@ -0,0 +1,13 @@ +fun test() { + foo<Int?>() + foo() + bar() + bar() + bar<Double?>() + bar<Double>() + 1.buzz<Double>() +} + +fun foo() {} +fun bar() {} +fun Int> Int.buzz() : Unit {} diff --git a/idea/testData/completion/basic/ExtendClassName.kt b/idea/testData/completion/basic/ExtendClassName.kt new file mode 100644 index 00000000000..47daf28eff9 --- /dev/null +++ b/idea/testData/completion/basic/ExtendClassName.kt @@ -0,0 +1,13 @@ +open class MySecondClass() { +} + +open class MyFirstClass { + +} + +class A() : My { + public fun test() { + } +} + +// EXIST: MySecondClass, MyFirstClass \ No newline at end of file diff --git a/idea/testData/completion/basic/ExtendQualifiedClassName.kt b/idea/testData/completion/basic/ExtendQualifiedClassName.kt new file mode 100644 index 00000000000..da13ff4b8c0 --- /dev/null +++ b/idea/testData/completion/basic/ExtendQualifiedClassName.kt @@ -0,0 +1,11 @@ +namespace Test.SubTest.AnotherTest + +open class TestClass { +} + +class A() : Test.SubTest.AnotherTest.Te { + public fun test() { + } +} + +// EXIST: TestClass diff --git a/idea/testData/completion/basic/VariableClassName.kt b/idea/testData/completion/basic/VariableClassName.kt new file mode 100644 index 00000000000..0296a23af4c --- /dev/null +++ b/idea/testData/completion/basic/VariableClassName.kt @@ -0,0 +1,10 @@ +open class MyClass() { +} + +class A() : My { + public fun test() { + val a : MyC + } +} + +// EXIST: MyClass \ No newline at end of file diff --git a/idea/tests/org/jetbrains/jet/checkers/JetPsiCheckerTest.java b/idea/tests/org/jetbrains/jet/checkers/JetPsiCheckerTest.java index fefb1af6a4d..a768935461e 100644 --- a/idea/tests/org/jetbrains/jet/checkers/JetPsiCheckerTest.java +++ b/idea/tests/org/jetbrains/jet/checkers/JetPsiCheckerTest.java @@ -58,21 +58,21 @@ public class JetPsiCheckerTest extends LightDaemonAnalyzerTestCase { JetTestCaseBuilder.appendTestsInDirectory(PluginTestCaseBase.getTestDataPathBase(), "/checker/", false, JetTestCaseBuilder.emptyFilter, new JetTestCaseBuilder.NamedTestFactory() { @NotNull @Override - public Test createTest(@NotNull String dataPath, @NotNull String name) { + public Test createTest(@NotNull String dataPath, @NotNull String name, @NotNull File file) { return new JetPsiCheckerTest(dataPath, name); } }, suite); JetTestCaseBuilder.appendTestsInDirectory(PluginTestCaseBase.getTestDataPathBase(), "/checker/regression/", false, JetTestCaseBuilder.emptyFilter, new JetTestCaseBuilder.NamedTestFactory() { @NotNull @Override - public Test createTest(@NotNull String dataPath, @NotNull String name) { + public Test createTest(@NotNull String dataPath, @NotNull String name, @NotNull File file) { return new JetPsiCheckerTest(dataPath, name); } }, suite); JetTestCaseBuilder.appendTestsInDirectory(PluginTestCaseBase.getTestDataPathBase(), "/checker/infos/", false, JetTestCaseBuilder.emptyFilter, new JetTestCaseBuilder.NamedTestFactory() { @NotNull @Override - public Test createTest(@NotNull String dataPath, @NotNull String name) { + public Test createTest(@NotNull String dataPath, @NotNull String name, @NotNull File file) { return new JetPsiCheckerTest(dataPath, name).setCheckInfos(true); } }, suite); diff --git a/idea/tests/org/jetbrains/jet/completion/JetBasicCompletionTest.java b/idea/tests/org/jetbrains/jet/completion/JetBasicCompletionTest.java new file mode 100644 index 00000000000..14bc6d16912 --- /dev/null +++ b/idea/tests/org/jetbrains/jet/completion/JetBasicCompletionTest.java @@ -0,0 +1,59 @@ +package org.jetbrains.jet.completion; + +import junit.framework.Test; +import junit.framework.TestSuite; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.jet.JetTestCaseBuilder; +import org.jetbrains.jet.plugin.PluginTestCaseBase; + +import java.io.File; + +/** + * @author Nikolay.Krasko + */ +public class JetBasicCompletionTest extends JetCompletionTestBase { + private final String myPath; + private final String myName; + + public JetBasicCompletionTest(@NotNull String path, @NotNull String name) { + myPath = path; + myName = name; + + // Set name explicitly because otherwise there will be "TestCase.fName cannot be null" + setName("testCompletionExecute"); + } + + public void testCompletionExecute() { + doTest(); + } + + @Override + protected String getTestDataPath() { + return new File(PluginTestCaseBase.getTestDataPathBase(), myPath).getPath() + + File.separator; + } + + @NotNull + @Override + public String getName() { + return "test" + myName; + } + + @NotNull + public static TestSuite suite() { + TestSuite suite = new TestSuite(); + + JetTestCaseBuilder.appendTestsInDirectory( + PluginTestCaseBase.getTestDataPathBase(), "/completion/basic/", false, + JetTestCaseBuilder.emptyFilter, new JetTestCaseBuilder.NamedTestFactory() { + + @NotNull + @Override + public Test createTest(@NotNull String dataPath, @NotNull String name, @NotNull File file) { + return new JetBasicCompletionTest(dataPath, name); + } + }, suite); + + return suite; + } +} diff --git a/idea/tests/org/jetbrains/jet/completion/KeywordsCompletionTest.java b/idea/tests/org/jetbrains/jet/completion/KeywordsCompletionTest.java index 7cb30ecfe96..1df0d5ef2cf 100644 --- a/idea/tests/org/jetbrains/jet/completion/KeywordsCompletionTest.java +++ b/idea/tests/org/jetbrains/jet/completion/KeywordsCompletionTest.java @@ -22,10 +22,10 @@ public class KeywordsCompletionTest extends JetCompletionTestBase { myName = name; // Set name explicitly because otherwise there will be "TestCase.fName cannot be null" - setName("testComletionExecute"); + setName("testCompletionExecute"); } - public void testComletionExecute() { + public void testCompletionExecute() { doTest(); } @@ -51,7 +51,7 @@ public class KeywordsCompletionTest extends JetCompletionTestBase { @NotNull @Override - public junit.framework.Test createTest(@NotNull String dataPath, @NotNull String name) { + public junit.framework.Test createTest(@NotNull String dataPath, @NotNull String name, @NotNull File file) { return new KeywordsCompletionTest(dataPath, name); } }, suite); diff --git a/idea/tests/org/jetbrains/jet/plugin/quickfix/JetQuickFixTest.java b/idea/tests/org/jetbrains/jet/plugin/quickfix/JetQuickFixTest.java index 7b8521fb419..3bfb5ac99d0 100644 --- a/idea/tests/org/jetbrains/jet/plugin/quickfix/JetQuickFixTest.java +++ b/idea/tests/org/jetbrains/jet/plugin/quickfix/JetQuickFixTest.java @@ -53,7 +53,7 @@ public class JetQuickFixTest extends LightQuickFixTestCase { JetTestCaseBuilder.NamedTestFactory namedTestFactory = new JetTestCaseBuilder.NamedTestFactory() { @NotNull @Override - public Test createTest(@NotNull String dataPath, @NotNull String name) { + public Test createTest(@NotNull String dataPath, @NotNull String name, @NotNull File file) { return new JetQuickFixTest(dataPath, name); } }; diff --git a/stdlib/src/jet/runtime/Intrinsics.java b/stdlib/src/jet/runtime/Intrinsics.java index 1011e0ea2a7..19488b98ba2 100644 --- a/stdlib/src/jet/runtime/Intrinsics.java +++ b/stdlib/src/jet/runtime/Intrinsics.java @@ -13,14 +13,20 @@ public class Intrinsics { return ((self == null) ? "null" : self) + ((other == null) ? "null" : other.toString()); } - public static Object sure(Object self) { - if(self == null) - return throwNpe(); - return self; + public static void throwNpe() { + throw new JetNullPointerException(); } - private static Object throwNpe() { - throw new JetNullPointerException(); + public static int compare(long thisVal, long anotherVal) { + return (thisVal 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;