From 627a1dbf6f1034497bab84bb030a18a2f95c6889 Mon Sep 17 00:00:00 2001 From: Maxim Shafirov Date: Fri, 11 Nov 2011 19:57:40 +0400 Subject: [PATCH] Resolve Kotlin from Java, first drop. --- .../jet/codegen/ClassBodyCodegen.java | 20 +- .../jetbrains/jet/codegen/ClassBuilder.java | 42 ++-- .../jet/codegen/ClassBuilderFactory.java | 4 +- .../jetbrains/jet/codegen/ClosureCodegen.java | 108 ++++---- .../jet/codegen/FunctionCodegen.java | 214 ++++++++-------- .../jet/codegen/GenerationState.java | 8 +- .../codegen/ImplementationBodyCodegen.java | 232 ++++++++++-------- .../jet/codegen/NamespaceCodegen.java | 32 +-- .../jet/codegen/PropertyCodegen.java | 4 +- .../jet/codegen/TraitImplBodyCodegen.java | 2 +- .../resolve/java/JavaDescriptorResolver.java | 24 +- .../jet/lang/resolve/AnalyzingUtils.java | 27 +- idea/src/META-INF/plugin.xml | 2 + .../plugin/java/ClsWrapperStubPsiFactory.java | 122 +++++++++ .../jet/plugin/java/JavaElementFinder.java | 220 +++++++++++++++++ .../jet/plugin/java/StubClassBuilder.java | 98 ++++++++ 16 files changed, 842 insertions(+), 317 deletions(-) create mode 100644 idea/src/org/jetbrains/jet/plugin/java/ClsWrapperStubPsiFactory.java create mode 100644 idea/src/org/jetbrains/jet/plugin/java/JavaElementFinder.java create mode 100644 idea/src/org/jetbrains/jet/plugin/java/StubClassBuilder.java diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/ClassBodyCodegen.java b/compiler/backend/src/org/jetbrains/jet/codegen/ClassBodyCodegen.java index 36eed72bf4a..59d472f16d7 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/ClassBodyCodegen.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/ClassBodyCodegen.java @@ -116,18 +116,20 @@ public abstract class ClassBodyCodegen { if (staticInitializerChunks.size() > 0) { final MethodVisitor mv = v.newMethod(null, Opcodes.ACC_PUBLIC | Opcodes.ACC_STATIC, "", "()V", null, null); - mv.visitCode(); + if (v.generateCode()) { + mv.visitCode(); - InstructionAdapter v = new InstructionAdapter(mv); + InstructionAdapter v = new InstructionAdapter(mv); - for (CodeChunk chunk : staticInitializerChunks) { - chunk.generate(v); + for (CodeChunk chunk : staticInitializerChunks) { + chunk.generate(v); + } + + mv.visitInsn(Opcodes.RETURN); + mv.visitMaxs(0, 0); + + mv.visitEnd(); } - - mv.visitInsn(Opcodes.RETURN); - mv.visitMaxs(0, 0); - - mv.visitEnd(); } } } diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/ClassBuilder.java b/compiler/backend/src/org/jetbrains/jet/codegen/ClassBuilder.java index b55adbc5dad..2665770d752 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/ClassBuilder.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/ClassBuilder.java @@ -10,20 +10,26 @@ import org.objectweb.asm.ClassVisitor; import org.objectweb.asm.FieldVisitor; import org.objectweb.asm.MethodVisitor; -public class ClassBuilder { - private final ClassVisitor v; +public abstract class ClassBuilder { + public static class Concrete extends ClassBuilder { + private final ClassVisitor v; - public ClassBuilder(ClassVisitor v) { - this.v = v; + public Concrete(ClassVisitor v) { + this.v = v; + } + + @Override + public ClassVisitor getVisitor() { + return v; + } } - public FieldVisitor newField(@Nullable PsiElement origin, int access, String name, String desc, @Nullable String signature, @Nullable Object value) { - return v.visitField(access, name, desc, signature, value); + return getVisitor().visitField(access, name, desc, signature, value); } public MethodVisitor newMethod(@Nullable PsiElement origin, @@ -32,28 +38,34 @@ public class ClassBuilder { String desc, @Nullable String signature, @Nullable String[] exceptions) { - return v.visitMethod(access, name, desc, signature, exceptions); + return getVisitor().visitMethod(access, name, desc, signature, exceptions); } public AnnotationVisitor newAnnotation(PsiElement origin, String desc, boolean visible) { - return v.visitAnnotation(desc, visible); + return getVisitor().visitAnnotation(desc, visible); } public void done() { - v.visitEnd(); + getVisitor().visitEnd(); } - public ClassVisitor getVisitor() { - return v; - } + public abstract ClassVisitor getVisitor(); - public void defineClass(int version, int access, String name, @Nullable String signature, String superName, String[] interfaces) { - v.visit(version, access, name, signature, superName, interfaces); + public void defineClass(PsiElement origin, int version, int access, String name, @Nullable String signature, String superName, String[] interfaces) { + getVisitor().visit(version, access, name, signature, superName, interfaces); } public void visitSource(String name, @Nullable String debug) { - v.visitSource(name, debug); + getVisitor().visitSource(name, debug); + } + + public void visitOuterClass(String owner, String name, String desc) { + getVisitor().visitOuterClass(owner, name, desc); + } + + public boolean generateCode() { + return true; } } diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/ClassBuilderFactory.java b/compiler/backend/src/org/jetbrains/jet/codegen/ClassBuilderFactory.java index dc4075d0cf4..f5bf4be4dec 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/ClassBuilderFactory.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/ClassBuilderFactory.java @@ -17,7 +17,7 @@ public interface ClassBuilderFactory { ClassBuilderFactory TEXT = new ClassBuilderFactory() { @Override public ClassBuilder newClassBuilder() { - return new ClassBuilder(new TraceClassVisitor(new PrintWriter(new StringWriter()))); + return new ClassBuilder.Concrete(new TraceClassVisitor(new PrintWriter(new StringWriter()))); } @Override @@ -39,7 +39,7 @@ public interface ClassBuilderFactory { ClassBuilderFactory BINARIES = new ClassBuilderFactory() { @Override public ClassBuilder newClassBuilder() { - return new ClassBuilder(new ClassWriter(ClassWriter.COMPUTE_FRAMES | ClassWriter.COMPUTE_MAXS)); + return new ClassBuilder.Concrete(new ClassWriter(ClassWriter.COMPUTE_FRAMES | ClassWriter.COMPUTE_MAXS)); } @Override diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/ClosureCodegen.java b/compiler/backend/src/org/jetbrains/jet/codegen/ClosureCodegen.java index 10e9857f40d..e0cc263d9fa 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/ClosureCodegen.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/ClosureCodegen.java @@ -69,7 +69,8 @@ public class ClosureCodegen extends ObjectOrClosureCodegen { appendType(signatureWriter, funDescriptor.getReturnType(), '='); signatureWriter.visitEnd(); - cv.defineClass(V1_6, + cv.defineClass(fun, + V1_6, ACC_PUBLIC/*|ACC_SUPER*/, name, null, @@ -112,23 +113,25 @@ public class ClosureCodegen extends ObjectOrClosureCodegen { cv.newField(fun, ACC_PRIVATE | ACC_STATIC, "$instance", classDescr, null, null); MethodVisitor mv = cv.newMethod(fun, ACC_PUBLIC | ACC_STATIC, "$getInstance", "()" + classDescr, null, new String[0]); - mv.visitCode(); - mv.visitFieldInsn(GETSTATIC, name, "$instance", classDescr); - mv.visitInsn(DUP); - Label ret = new Label(); - mv.visitJumpInsn(IFNONNULL, ret); + if (cv.generateCode()) { + mv.visitCode(); + mv.visitFieldInsn(GETSTATIC, name, "$instance", classDescr); + mv.visitInsn(DUP); + Label ret = new Label(); + mv.visitJumpInsn(IFNONNULL, ret); - mv.visitInsn(POP); - mv.visitTypeInsn(NEW, name); - mv.visitInsn(DUP); - mv.visitMethodInsn(INVOKESPECIAL, name, "", "()V"); - mv.visitInsn(DUP); - mv.visitFieldInsn(PUTSTATIC, name, "$instance", classDescr); + mv.visitInsn(POP); + mv.visitTypeInsn(NEW, name); + mv.visitInsn(DUP); + mv.visitMethodInsn(INVOKESPECIAL, name, "", "()V"); + mv.visitInsn(DUP); + mv.visitFieldInsn(PUTSTATIC, name, "$instance", classDescr); - mv.visitLabel(ret); - mv.visitInsn(ARETURN); - mv.visitMaxs(0,0); - mv.visitEnd(); + mv.visitLabel(ret); + mv.visitInsn(ARETURN); + mv.visitMaxs(0,0); + mv.visitEnd(); + } } private boolean generateBody(FunctionDescriptor funDescriptor, ClassBuilder cv, JetFunctionLiteral body) { @@ -157,34 +160,36 @@ public class ClosureCodegen extends ObjectOrClosureCodegen { return; final MethodVisitor mv = cv.newMethod(fun, ACC_PUBLIC, "invoke", bridge.getDescriptor(), state.getTypeMapper().genericSignature(funDescriptor), new String[0]); - mv.visitCode(); + if (cv.generateCode()) { + mv.visitCode(); - InstructionAdapter iv = new InstructionAdapter(mv); + InstructionAdapter iv = new InstructionAdapter(mv); - iv.load(0, Type.getObjectType(className)); + iv.load(0, Type.getObjectType(className)); - final ReceiverDescriptor receiver = funDescriptor.getReceiverParameter(); - int count = 1; - if (receiver.exists()) { - StackValue.local(count, JetTypeMapper.TYPE_OBJECT).put(JetTypeMapper.TYPE_OBJECT, iv); - StackValue.onStack(JetTypeMapper.TYPE_OBJECT).upcast(state.getTypeMapper().mapType(receiver.getType()), iv); - count++; + final ReceiverDescriptor receiver = funDescriptor.getReceiverParameter(); + int count = 1; + if (receiver.exists()) { + StackValue.local(count, JetTypeMapper.TYPE_OBJECT).put(JetTypeMapper.TYPE_OBJECT, iv); + StackValue.onStack(JetTypeMapper.TYPE_OBJECT).upcast(state.getTypeMapper().mapType(receiver.getType()), iv); + count++; + } + + final List params = funDescriptor.getValueParameters(); + for (ValueParameterDescriptor param : params) { + StackValue.local(count, JetTypeMapper.TYPE_OBJECT).put(JetTypeMapper.TYPE_OBJECT, iv); + StackValue.onStack(JetTypeMapper.TYPE_OBJECT).upcast(state.getTypeMapper().mapType(param.getOutType()), iv); + count++; + } + + iv.invokespecial(className, "invoke", delegate.getDescriptor()); + StackValue.onStack(delegate.getReturnType()).put(JetTypeMapper.TYPE_OBJECT, iv); + + iv.areturn(JetTypeMapper.TYPE_OBJECT); + + mv.visitMaxs(0, 0); + mv.visitEnd(); } - - final List params = funDescriptor.getValueParameters(); - for (ValueParameterDescriptor param : params) { - StackValue.local(count, JetTypeMapper.TYPE_OBJECT).put(JetTypeMapper.TYPE_OBJECT, iv); - StackValue.onStack(JetTypeMapper.TYPE_OBJECT).upcast(state.getTypeMapper().mapType(param.getOutType()), iv); - count++; - } - - iv.invokespecial(className, "invoke", delegate.getDescriptor()); - StackValue.onStack(delegate.getReturnType()).put(JetTypeMapper.TYPE_OBJECT, iv); - - iv.areturn(JetTypeMapper.TYPE_OBJECT); - - mv.visitMaxs(0, 0); - mv.visitEnd(); } private Method generateConstructor(String funClass, JetFunctionLiteralExpression fun) { @@ -221,14 +226,15 @@ public class ClosureCodegen extends ObjectOrClosureCodegen { final Method constructor = new Method("", Type.VOID_TYPE, argTypes); final MethodVisitor mv = cv.newMethod(fun, ACC_PUBLIC, "", constructor.getDescriptor(), null, new String[0]); - mv.visitCode(); - InstructionAdapter iv = new InstructionAdapter(mv); - ExpressionCodegen expressionCodegen = new ExpressionCodegen(mv, null, Type.VOID_TYPE, context, state); + if (cv.generateCode()) { + mv.visitCode(); + InstructionAdapter iv = new InstructionAdapter(mv); + ExpressionCodegen expressionCodegen = new ExpressionCodegen(mv, null, Type.VOID_TYPE, context, state); - iv.load(0, Type.getObjectType(funClass)); + iv.load(0, Type.getObjectType(funClass)); // expressionCodegen.generateTypeInfo(new ProjectionErasingJetType(returnType)); - iv.aconst(null); // @todo - iv.invokespecial(funClass, "", "(Ljet/typeinfo/TypeInfo;)V"); + iv.aconst(null); // @todo + iv.invokespecial(funClass, "", "(Ljet/typeinfo/TypeInfo;)V"); i = 1; for (Type type : argTypes) { @@ -248,13 +254,11 @@ public class ClosureCodegen extends ObjectOrClosureCodegen { } } - StackValue.field(type, name, fieldName, false).store(iv); + iv.visitInsn(RETURN); + + mv.visitMaxs(0, 0); + mv.visitEnd(); } - - iv.visitInsn(RETURN); - - mv.visitMaxs(0, 0); - mv.visitEnd(); return constructor; } diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/FunctionCodegen.java b/compiler/backend/src/org/jetbrains/jet/codegen/FunctionCodegen.java index b2fae930c34..909c4953c88 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/FunctionCodegen.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/FunctionCodegen.java @@ -70,12 +70,12 @@ public class FunctionCodegen { if(kind != OwnerKind.TRAIT_IMPL) { int start = functionDescriptor.getReceiverParameter().exists() ? 1 : 0; for(int i = 0; i != paramDescrs.size(); ++i) { - AnnotationVisitor annotationVisitor = mv.visitParameterAnnotation(i + start, "jet/typeinfo/JetParameterName", true); + AnnotationVisitor annotationVisitor = mv.visitParameterAnnotation(i + start, "Ljet/typeinfo/JetParameterName;", true); annotationVisitor.visit("value", paramDescrs.get(i).getName()); annotationVisitor.visitEnd(); } } - if (!isAbstract) { + if (!isAbstract && v.generateCode()) { mv.visitCode(); FrameMap frameMap = context.prepareFrame(); @@ -192,103 +192,105 @@ public class FunctionCodegen { descriptor = descriptor.replace("(","(L" + ownerInternalName + ";"); final MethodVisitor mv = v.newMethod(null, flags | ACC_STATIC, jvmSignature.getName() + "$default", descriptor, null, null); InstructionAdapter iv = new InstructionAdapter(mv); - mv.visitCode(); + if (v.generateCode()) { + mv.visitCode(); - FrameMap frameMap = owner.prepareFrame(); + FrameMap frameMap = owner.prepareFrame(); - ExpressionCodegen codegen = new ExpressionCodegen(mv, frameMap, jvmSignature.getReturnType(), owner, state); + ExpressionCodegen codegen = new ExpressionCodegen(mv, frameMap, jvmSignature.getReturnType(), owner, state); + + int var = 0; + if(!isStatic) { + frameMap.enterTemp(); + var++; + } + + if(hasReceiver) { + frameMap.enterTemp(); + var++; + } + + 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); + } + + List typeParameters = functionDescriptor.getTypeParameters(); + for (final TypeParameterDescriptor typeParameterDescriptor : typeParameters) { + int slot = frameMap.enterTemp(); + codegen.addTypeParameter(typeParameterDescriptor, StackValue.local(slot, JetTypeMapper.TYPE_TYPEINFO)); + var++; + } - int var = 0; - if(!isStatic) { frameMap.enterTemp(); - var++; - } - if(hasReceiver) { - frameMap.enterTemp(); - var++; - } + int maskIndex = var; - 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); - } - - List typeParameters = functionDescriptor.getTypeParameters(); - for (final TypeParameterDescriptor typeParameterDescriptor : typeParameters) { - int slot = frameMap.enterTemp(); - codegen.addTypeParameter(typeParameterDescriptor, StackValue.local(slot, JetTypeMapper.TYPE_TYPEINFO)); - var++; - } - - frameMap.enterTemp(); - - int maskIndex = var; - - var = 0; - if(!isStatic) { - mv.visitVarInsn(ALOAD, var++); - } - - if(hasReceiver) { - mv.visitVarInsn(ALOAD, var++); - } - - Type[] argumentTypes = jvmSignature.getArgumentTypes(); - for (int index = 0; index < paramDescrs.size(); index++) { - ValueParameterDescriptor parameterDescriptor = paramDescrs.get(index); - - Type t = argumentTypes[(hasReceiver ? 1 : 0) + index]; - Label endArg = null; - if (parameterDescriptor.hasDefaultValue()) { - iv.load(maskIndex, Type.INT_TYPE); - iv.iconst(1 << index); - iv.and(Type.INT_TYPE); - Label loadArg = new Label(); - iv.ifeq(loadArg); - - JetParameter jetParameter = (JetParameter) state.getBindingContext().get(BindingContext.DESCRIPTOR_TO_DECLARATION, parameterDescriptor); - assert jetParameter != null; - codegen.gen(jetParameter.getDefaultValue(), t); - - endArg = new Label(); - iv.goTo(endArg); - - iv.mark(loadArg); + var = 0; + if(!isStatic) { + mv.visitVarInsn(ALOAD, var++); } - iv.load(var, t); - var += t.getSize(); - - if (parameterDescriptor.hasDefaultValue()) { - iv.mark(endArg); + if(hasReceiver) { + mv.visitVarInsn(ALOAD, var++); } - } - for (final TypeParameterDescriptor typeParameterDescriptor : typeParameters) { - if(typeParameterDescriptor.isReified()) - iv.load(var++, JetTypeMapper.TYPE_OBJECT); - } + Type[] argumentTypes = jvmSignature.getArgumentTypes(); + for (int index = 0; index < paramDescrs.size(); index++) { + ValueParameterDescriptor parameterDescriptor = paramDescrs.get(index); - if(!isStatic) { - if(kind == OwnerKind.TRAIT_IMPL) { - iv.invokeinterface(ownerInternalName, jvmSignature.getName(), jvmSignature.getDescriptor()); + Type t = argumentTypes[(hasReceiver ? 1 : 0) + index]; + Label endArg = null; + if (parameterDescriptor.hasDefaultValue()) { + iv.load(maskIndex, Type.INT_TYPE); + iv.iconst(1 << index); + iv.and(Type.INT_TYPE); + Label loadArg = new Label(); + iv.ifeq(loadArg); + + JetParameter jetParameter = (JetParameter) state.getBindingContext().get(BindingContext.DESCRIPTOR_TO_DECLARATION, parameterDescriptor); + assert jetParameter != null; + codegen.gen(jetParameter.getDefaultValue(), t); + + endArg = new Label(); + iv.goTo(endArg); + + iv.mark(loadArg); + } + + iv.load(var, t); + var += t.getSize(); + + if (parameterDescriptor.hasDefaultValue()) { + iv.mark(endArg); + } } - else - iv.invokevirtual(ownerInternalName, jvmSignature.getName(), jvmSignature.getDescriptor()); - } - else { - iv.invokestatic(ownerInternalName, jvmSignature.getName(), jvmSignature.getDescriptor()); - } - iv.areturn(jvmSignature.getReturnType()); + for (final TypeParameterDescriptor typeParameterDescriptor : typeParameters) { + if(typeParameterDescriptor.isReified()) + iv.load(var++, JetTypeMapper.TYPE_OBJECT); + } - mv.visitMaxs(0, 0); - mv.visitEnd(); + if(!isStatic) { + if(kind == OwnerKind.TRAIT_IMPL) { + iv.invokeinterface(ownerInternalName, jvmSignature.getName(), jvmSignature.getDescriptor()); + } + else + iv.invokevirtual(ownerInternalName, jvmSignature.getName(), jvmSignature.getDescriptor()); + } + else { + iv.invokestatic(ownerInternalName, jvmSignature.getName(), jvmSignature.getDescriptor()); + } + + iv.areturn(jvmSignature.getReturnType()); + + mv.visitMaxs(0, 0); + mv.visitEnd(); + } } } @@ -300,29 +302,31 @@ public class FunctionCodegen { int flags = ACC_PUBLIC; // TODO. final MethodVisitor mv = v.newMethod(null, flags, jvmSignature.getName(), overriden.getDescriptor(), null, null); - mv.visitCode(); + if (v.generateCode()) { + mv.visitCode(); - Type[] argTypes = jvmSignature.getArgumentTypes(); - InstructionAdapter iv = new InstructionAdapter(mv); - iv.load(0, JetTypeMapper.TYPE_OBJECT); - for (int i = 0, reg = 1; i < argTypes.length; i++) { - Type argType = argTypes[i]; - iv.load(reg, argType); - if(argType.getSort() == Type.OBJECT) { - iv.checkcast(argType); + Type[] argTypes = jvmSignature.getArgumentTypes(); + InstructionAdapter iv = new InstructionAdapter(mv); + iv.load(0, JetTypeMapper.TYPE_OBJECT); + for (int i = 0, reg = 1; i < argTypes.length; i++) { + Type argType = argTypes[i]; + iv.load(reg, argType); + if(argType.getSort() == Type.OBJECT) { + iv.checkcast(argType); + } + //noinspection AssignmentToForLoopParameter + reg += argType.getSize(); } - //noinspection AssignmentToForLoopParameter - reg += argType.getSize(); - } - iv.invokevirtual(state.getTypeMapper().jvmName((ClassDescriptor) owner.getContextDescriptor(), OwnerKind.IMPLEMENTATION), jvmSignature.getName(), jvmSignature.getDescriptor()); - if(JetTypeMapper.isPrimitive(jvmSignature.getReturnType()) && !JetTypeMapper.isPrimitive(overriden.getReturnType())) - StackValue.valueOf(iv, jvmSignature.getReturnType()); - if(jvmSignature.getReturnType() == Type.VOID_TYPE) - iv.aconst(null); - iv.areturn(overriden.getReturnType()); - mv.visitMaxs(0, 0); - mv.visitEnd(); + iv.invokevirtual(state.getTypeMapper().jvmName((ClassDescriptor) owner.getContextDescriptor(), OwnerKind.IMPLEMENTATION), jvmSignature.getName(), jvmSignature.getDescriptor()); + if(JetTypeMapper.isPrimitive(jvmSignature.getReturnType()) && !JetTypeMapper.isPrimitive(overriden.getReturnType())) + StackValue.valueOf(iv, jvmSignature.getReturnType()); + if(jvmSignature.getReturnType() == Type.VOID_TYPE) + iv.aconst(null); + iv.areturn(overriden.getReturnType()); + mv.visitMaxs(0, 0); + mv.visitEnd(); + } } } diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/GenerationState.java b/compiler/backend/src/org/jetbrains/jet/codegen/GenerationState.java index 8025a67b5ce..84e40db7f9e 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/GenerationState.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/GenerationState.java @@ -104,8 +104,7 @@ public class GenerationState { bindingContexts.push(bindingContext); try { for (JetNamespace namespace : namespaces) { - NamespaceCodegen codegen = forNamespace(namespace); - codegen.generate(namespace); + generateNamespace(namespace); } } finally { @@ -114,6 +113,11 @@ public class GenerationState { } } + protected void generateNamespace(JetNamespace namespace) { + NamespaceCodegen codegen = forNamespace(namespace); + codegen.generate(namespace); + } + public GeneratedAnonymousClassDescriptor generateObjectLiteral(JetObjectLiteralExpression literal, ObjectOrClosureCodegen closure) { JetObjectDeclaration objectDeclaration = literal.getObjectDeclaration(); Pair nameAndVisitor = forAnonymousSubclass(objectDeclaration); diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/ImplementationBodyCodegen.java b/compiler/backend/src/org/jetbrains/jet/codegen/ImplementationBodyCodegen.java index 660aaa8206b..b73a2b56279 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/ImplementationBodyCodegen.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/ImplementationBodyCodegen.java @@ -96,7 +96,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen { } } - v.defineClass(Opcodes.V1_6, + v.defineClass(myClass, Opcodes.V1_6, Opcodes.ACC_PUBLIC | (isAbstract ? Opcodes.ACC_ABSTRACT : 0) | (isInterface ? Opcodes.ACC_INTERFACE : 0/*Opcodes.ACC_SUPER*/), @@ -108,7 +108,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen { v.visitSource(myClass.getContainingFile().getName(), null); if(descriptor.getContainingDeclaration() instanceof ClassDescriptor) { - v.getVisitor().visitOuterClass(state.getTypeMapper().jvmType((ClassDescriptor) descriptor.getContainingDeclaration(), OwnerKind.IMPLEMENTATION).getInternalName(), null, null); + v.visitOuterClass(state.getTypeMapper().jvmType((ClassDescriptor) descriptor.getContainingDeclaration(), OwnerKind.IMPLEMENTATION).getInternalName(), null, null); } if(myClass instanceof JetClass) { @@ -181,22 +181,24 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen { Type[] argTypes = method.getArgumentTypes(); MethodVisitor mv = v.newMethod(null, Opcodes.ACC_PUBLIC|Opcodes.ACC_BRIDGE|Opcodes.ACC_FINAL, bridge.getName(), method.getDescriptor(), null, null); - mv.visitCode(); + if (v.generateCode()) { + mv.visitCode(); - InstructionAdapter iv = new InstructionAdapter(mv); + InstructionAdapter iv = new InstructionAdapter(mv); - iv.load(0, JetTypeMapper.TYPE_OBJECT); - for (int i = 0, reg = 1; i < argTypes.length; i++) { - Type argType = argTypes[i]; - iv.load(reg, argType); - //noinspection AssignmentToForLoopParameter - reg += argType.getSize(); + iv.load(0, JetTypeMapper.TYPE_OBJECT); + for (int i = 0, reg = 1; i < argTypes.length; i++) { + Type argType = argTypes[i]; + iv.load(reg, argType); + //noinspection AssignmentToForLoopParameter + reg += argType.getSize(); + } + iv.invokespecial(state.getTypeMapper().getOwner(original, OwnerKind.IMPLEMENTATION), originalMethod.getName(), originalMethod.getDescriptor()); + + iv.areturn(method.getReturnType()); + mv.visitMaxs(0,0); + mv.visitEnd(); } - iv.invokespecial(state.getTypeMapper().getOwner(original, OwnerKind.IMPLEMENTATION), originalMethod.getName(), originalMethod.getDescriptor()); - - iv.areturn(method.getReturnType()); - mv.visitMaxs(0,0); - mv.visitEnd(); } else if(entry.getValue() instanceof PropertyDescriptor) { PropertyDescriptor bridge = (PropertyDescriptor) entry.getValue(); @@ -205,37 +207,42 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen { Method method = state.getTypeMapper().mapGetterSignature(bridge, OwnerKind.IMPLEMENTATION); Method originalMethod = state.getTypeMapper().mapGetterSignature(original, OwnerKind.IMPLEMENTATION); MethodVisitor mv = v.newMethod(null, Opcodes.ACC_PUBLIC|Opcodes.ACC_BRIDGE|Opcodes.ACC_FINAL, method.getName(), method.getDescriptor(), null, null); - mv.visitCode(); + InstructionAdapter iv = null; + if (v.generateCode()) { + mv.visitCode(); - InstructionAdapter iv = new InstructionAdapter(mv); + iv = new InstructionAdapter(mv); - iv.load(0, JetTypeMapper.TYPE_OBJECT); - iv.invokespecial(state.getTypeMapper().getOwner(original, OwnerKind.IMPLEMENTATION), originalMethod.getName(), originalMethod.getDescriptor()); + iv.load(0, JetTypeMapper.TYPE_OBJECT); + iv.invokespecial(state.getTypeMapper().getOwner(original, OwnerKind.IMPLEMENTATION), originalMethod.getName(), originalMethod.getDescriptor()); - iv.areturn(method.getReturnType()); - mv.visitMaxs(0,0); - mv.visitEnd(); + iv.areturn(method.getReturnType()); + mv.visitMaxs(0,0); + mv.visitEnd(); + } method = state.getTypeMapper().mapSetterSignature(bridge, OwnerKind.IMPLEMENTATION); originalMethod = state.getTypeMapper().mapSetterSignature(original, OwnerKind.IMPLEMENTATION); mv = v.newMethod(null, Opcodes.ACC_PUBLIC|Opcodes.ACC_BRIDGE|Opcodes.ACC_FINAL, method.getName(), method.getDescriptor(), null, null); - mv.visitCode(); + if (v.generateCode()) { + mv.visitCode(); - iv = new InstructionAdapter(mv); + iv = new InstructionAdapter(mv); - iv.load(0, JetTypeMapper.TYPE_OBJECT); - Type[] argTypes = method.getArgumentTypes(); - for (int i = 0, reg = 1; i < argTypes.length; i++) { - Type argType = argTypes[i]; - iv.load(reg, argType); - //noinspection AssignmentToForLoopParameter - reg += argType.getSize(); + iv.load(0, JetTypeMapper.TYPE_OBJECT); + Type[] argTypes = method.getArgumentTypes(); + for (int i = 0, reg = 1; i < argTypes.length; i++) { + Type argType = argTypes[i]; + iv.load(reg, argType); + //noinspection AssignmentToForLoopParameter + reg += argType.getSize(); + } + iv.invokespecial(state.getTypeMapper().getOwner(original, OwnerKind.IMPLEMENTATION), originalMethod.getName(), originalMethod.getDescriptor()); + + iv.areturn(method.getReturnType()); + mv.visitMaxs(0,0); + mv.visitEnd(); } - iv.invokespecial(state.getTypeMapper().getOwner(original, OwnerKind.IMPLEMENTATION), originalMethod.getName(), originalMethod.getDescriptor()); - - iv.areturn(method.getReturnType()); - mv.visitMaxs(0,0); - mv.visitEnd(); } else { throw new UnsupportedOperationException(); @@ -330,6 +337,8 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen { int flags = Opcodes.ACC_PUBLIC; // TODO final MethodVisitor mv = v.newMethod(myClass, flags, "", method.getDescriptor(), null, null); + if (!v.generateCode()) return; + mv.visitCode(); List paramDescrs = constructorDescriptor != null @@ -485,36 +494,38 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen { Method functionOriginal = state.getTypeMapper().mapSignature(fun.getName(), fun.getOriginal()); final MethodVisitor mv = v.newMethod(myClass, flags, function.getName(), function.getDescriptor(), null, null); - mv.visitCode(); + if (v.generateCode()) { + mv.visitCode(); - codegen.generateThisOrOuter(descriptor); + codegen.generateThisOrOuter(descriptor); - Type[] argTypes = function.getArgumentTypes(); - InstructionAdapter iv = new InstructionAdapter(mv); - iv.load(0, JetTypeMapper.TYPE_OBJECT); - for (int i = 0, reg = 1; i < argTypes.length; i++) { - Type argType = argTypes[i]; - iv.load(reg, argType); - //noinspection AssignmentToForLoopParameter - reg += argType.getSize(); + Type[] argTypes = function.getArgumentTypes(); + InstructionAdapter iv = new InstructionAdapter(mv); + iv.load(0, JetTypeMapper.TYPE_OBJECT); + for (int i = 0, reg = 1; i < argTypes.length; i++) { + Type argType = argTypes[i]; + iv.load(reg, argType); + //noinspection AssignmentToForLoopParameter + reg += argType.getSize(); + } + + JetType jetType = TraitImplBodyCodegen.getSuperClass(declaration, state.getBindingContext()); + Type type = state.getTypeMapper().mapType(jetType); + if(type.getInternalName().equals("java/lang/Object")) { + jetType = declaration.getDefaultType(); + type = state.getTypeMapper().mapType(jetType); + } + + String fdescriptor = functionOriginal.getDescriptor().replace("(","(" + type.getDescriptor()); + iv.invokestatic(state.getTypeMapper().jvmName((ClassDescriptor) fun.getContainingDeclaration(), OwnerKind.TRAIT_IMPL), function.getName(), fdescriptor); + if(function.getReturnType().getSort() == Type.OBJECT) { + iv.checkcast(function.getReturnType()); + } + iv.areturn(function.getReturnType()); + mv.visitMaxs(0, 0); + mv.visitEnd(); } - JetType jetType = TraitImplBodyCodegen.getSuperClass(declaration, state.getBindingContext()); - Type type = state.getTypeMapper().mapType(jetType); - if(type.getInternalName().equals("java/lang/Object")) { - jetType = declaration.getDefaultType(); - type = state.getTypeMapper().mapType(jetType); - } - - String fdescriptor = functionOriginal.getDescriptor().replace("(","(" + type.getDescriptor()); - iv.invokestatic(state.getTypeMapper().jvmName((ClassDescriptor) fun.getContainingDeclaration(), OwnerKind.TRAIT_IMPL), function.getName(), fdescriptor); - if(function.getReturnType().getSort() == Type.OBJECT) { - iv.checkcast(function.getReturnType()); - } - iv.areturn(function.getReturnType()); - mv.visitMaxs(0, 0); - mv.visitEnd(); - FunctionCodegen.generateBridgeIfNeeded(context, state, v, function, fun, kind); } } @@ -619,35 +630,37 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen { CallableMethod method = state.getTypeMapper().mapToCallableMethod(constructorDescriptor, kind); int flags = Opcodes.ACC_PUBLIC; // TODO final MethodVisitor mv = v.newMethod(constructor, flags, "", method.getSignature().getDescriptor(), null, null); - mv.visitCode(); + if (v.generateCode()) { + mv.visitCode(); - ConstructorFrameMap frameMap = new ConstructorFrameMap(method, constructorDescriptor, descriptor, kind); + ConstructorFrameMap frameMap = new ConstructorFrameMap(method, constructorDescriptor, descriptor, kind); - final InstructionAdapter iv = new InstructionAdapter(mv); - ExpressionCodegen codegen = new ExpressionCodegen(mv, frameMap, Type.VOID_TYPE, context, state); + final InstructionAdapter iv = new InstructionAdapter(mv); + ExpressionCodegen codegen = new ExpressionCodegen(mv, frameMap, Type.VOID_TYPE, context, state); - for (JetDelegationSpecifier initializer : constructor.getInitializers()) { - if (initializer instanceof JetDelegatorToThisCall) { - JetDelegatorToThisCall thisCall = (JetDelegatorToThisCall) initializer; - DeclarationDescriptor thisDescriptor = state.getBindingContext().get(BindingContext.REFERENCE_TARGET, thisCall.getThisReference()); - if (!(thisDescriptor instanceof ConstructorDescriptor)) { - throw new UnsupportedOperationException("expected 'this' delegator to resolve to constructor"); + for (JetDelegationSpecifier initializer : constructor.getInitializers()) { + if (initializer instanceof JetDelegatorToThisCall) { + JetDelegatorToThisCall thisCall = (JetDelegatorToThisCall) initializer; + DeclarationDescriptor thisDescriptor = state.getBindingContext().get(BindingContext.REFERENCE_TARGET, thisCall.getThisReference()); + if (!(thisDescriptor instanceof ConstructorDescriptor)) { + throw new UnsupportedOperationException("expected 'this' delegator to resolve to constructor"); + } + generateDelegatorToConstructorCall(iv, codegen, thisCall, (ConstructorDescriptor) thisDescriptor, frameMap); + } + else { + throw new UnsupportedOperationException("unknown initializer type"); } - generateDelegatorToConstructorCall(iv, codegen, thisCall, (ConstructorDescriptor) thisDescriptor, frameMap); } - else { - throw new UnsupportedOperationException("unknown initializer type"); + + JetExpression bodyExpression = constructor.getBodyExpression(); + if (bodyExpression != null) { + codegen.gen(bodyExpression, Type.VOID_TYPE); } - } - JetExpression bodyExpression = constructor.getBodyExpression(); - if (bodyExpression != null) { - codegen.gen(bodyExpression, Type.VOID_TYPE); + mv.visitInsn(Opcodes.RETURN); + mv.visitMaxs(0, 0); + mv.visitEnd(); } - - mv.visitInsn(Opcodes.RETURN); - mv.visitMaxs(0, 0); - mv.visitEnd(); } protected void generateTypeInfoInitializer(int firstTypeParameter, int typeParamCount, InstructionAdapter iv) { @@ -792,24 +805,29 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen { MethodVisitor mv = v.newMethod(myClass, Opcodes.ACC_PUBLIC, "getTypeInfo", "()Ljet/typeinfo/TypeInfo;", null, null); mv.visitCode(); - InstructionAdapter iv = new InstructionAdapter(mv); - String owner = state.getTypeMapper().jvmName(descriptor, OwnerKind.IMPLEMENTATION); - iv.load(0, JetTypeMapper.TYPE_OBJECT); - iv.getfield(owner, "$typeInfo", "Ljet/typeinfo/TypeInfo;"); - iv.areturn(JetTypeMapper.TYPE_TYPEINFO); - mv.visitMaxs(0, 0); - mv.visitEnd(); + InstructionAdapter iv = null; + if (v.generateCode()) { + iv = new InstructionAdapter(mv); + String owner = state.getTypeMapper().jvmName(descriptor, OwnerKind.IMPLEMENTATION); + iv.load(0, JetTypeMapper.TYPE_OBJECT); + iv.getfield(owner, "$typeInfo", "Ljet/typeinfo/TypeInfo;"); + iv.areturn(JetTypeMapper.TYPE_TYPEINFO); + mv.visitMaxs(0, 0); + mv.visitEnd(); + } mv = v.newMethod(myClass, Opcodes.ACC_PROTECTED | Opcodes.ACC_FINAL, "$setTypeInfo", "(Ljet/typeinfo/TypeInfo;)V", null, null); - mv.visitCode(); - iv = new InstructionAdapter(mv); - owner = state.getTypeMapper().jvmName(descriptor, OwnerKind.IMPLEMENTATION); - iv.load(0, JetTypeMapper.TYPE_OBJECT); - iv.load(1, JetTypeMapper.TYPE_OBJECT); - iv.putfield(owner, "$typeInfo", "Ljet/typeinfo/TypeInfo;"); - mv.visitInsn(Opcodes.RETURN); - mv.visitMaxs(0, 0); - mv.visitEnd(); + if (v.generateCode()) { + mv.visitCode(); + iv = new InstructionAdapter(mv); + String owner = state.getTypeMapper().jvmName(descriptor, OwnerKind.IMPLEMENTATION); + iv.load(0, JetTypeMapper.TYPE_OBJECT); + iv.load(1, JetTypeMapper.TYPE_OBJECT); + iv.putfield(owner, "$typeInfo", "Ljet/typeinfo/TypeInfo;"); + mv.visitInsn(Opcodes.RETURN); + mv.visitMaxs(0, 0); + mv.visitEnd(); + } } } else { @@ -820,13 +838,15 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen { private void genGetStaticGetTypeInfoMethod() { final MethodVisitor mv = v.newMethod(myClass, Opcodes.ACC_PUBLIC, "getTypeInfo", "()Ljet/typeinfo/TypeInfo;", null, null); - mv.visitCode(); - InstructionAdapter v = new InstructionAdapter(mv); - String owner = state.getTypeMapper().jvmName(descriptor, OwnerKind.IMPLEMENTATION); - v.getstatic(owner, "$staticTypeInfo", "Ljet/typeinfo/TypeInfo;"); - v.areturn(JetTypeMapper.TYPE_TYPEINFO); - mv.visitMaxs(0, 0); - mv.visitEnd(); + if (v.generateCode()) { + mv.visitCode(); + InstructionAdapter v = new InstructionAdapter(mv); + String owner = state.getTypeMapper().jvmName(descriptor, OwnerKind.IMPLEMENTATION); + v.getstatic(owner, "$staticTypeInfo", "Ljet/typeinfo/TypeInfo;"); + v.areturn(JetTypeMapper.TYPE_TYPEINFO); + mv.visitMaxs(0, 0); + mv.visitEnd(); + } } private void staticTypeInfoField() { diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/NamespaceCodegen.java b/compiler/backend/src/org/jetbrains/jet/codegen/NamespaceCodegen.java index 06fcb015ad1..2c2840afefc 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/NamespaceCodegen.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/NamespaceCodegen.java @@ -31,7 +31,7 @@ public class NamespaceCodegen { this.v = v; this.state = state; - v.defineClass(V1_6, + v.defineClass(sourceFile, V1_6, ACC_PUBLIC/*|ACC_SUPER*/, getJVMClassName(fqName), null, @@ -82,25 +82,27 @@ public class NamespaceCodegen { private void generateStaticInitializers(JetNamespace namespace) { MethodVisitor mv = v.newMethod(namespace, ACC_PUBLIC | ACC_STATIC, "", "()V", null, null); - mv.visitCode(); + if (v.generateCode()) { + mv.visitCode(); - FrameMap frameMap = new FrameMap(); - ExpressionCodegen codegen = new ExpressionCodegen(mv, frameMap, Type.VOID_TYPE, CodegenContext.STATIC, state); + FrameMap frameMap = new FrameMap(); + ExpressionCodegen codegen = new ExpressionCodegen(mv, frameMap, Type.VOID_TYPE, CodegenContext.STATIC, state); - for (JetDeclaration declaration : namespace.getDeclarations()) { - if (declaration instanceof JetProperty) { - final JetExpression initializer = ((JetProperty) declaration).getInitializer(); - if (initializer != null && !(initializer instanceof JetConstantExpression)) { - final PropertyDescriptor descriptor = (PropertyDescriptor) state.getBindingContext().get(BindingContext.VARIABLE, declaration); - codegen.genToJVMStack(initializer); - codegen.intermediateValueForProperty(descriptor, true, null).store(new InstructionAdapter(mv)); + for (JetDeclaration declaration : namespace.getDeclarations()) { + if (declaration instanceof JetProperty) { + final JetExpression initializer = ((JetProperty) declaration).getInitializer(); + if (initializer != null && !(initializer instanceof JetConstantExpression)) { + final PropertyDescriptor descriptor = (PropertyDescriptor) state.getBindingContext().get(BindingContext.VARIABLE, declaration); + codegen.genToJVMStack(initializer); + codegen.intermediateValueForProperty(descriptor, true, null).store(new InstructionAdapter(mv)); + } } } - } - mv.visitInsn(RETURN); - mv.visitMaxs(0, 0); - mv.visitEnd(); + mv.visitInsn(RETURN); + mv.visitMaxs(0, 0); + mv.visitEnd(); + } } private void generateTypeInfoFields(JetNamespace namespace, CodegenContext context) { diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/PropertyCodegen.java b/compiler/backend/src/org/jetbrains/jet/codegen/PropertyCodegen.java index 278edf168be..9ce660adcbe 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/PropertyCodegen.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/PropertyCodegen.java @@ -137,7 +137,7 @@ public class PropertyCodegen { final String signature = state.getTypeMapper().mapGetterSignature(propertyDescriptor, kind).getDescriptor(); String getterName = getterName(propertyDescriptor.getName()); MethodVisitor mv = v.newMethod(origin, flags, getterName, signature, null, null); - if (!isTrait || kind instanceof OwnerKind.DelegateKind) { + if (v.generateCode() && (!isTrait || kind instanceof OwnerKind.DelegateKind)) { mv.visitCode(); InstructionAdapter iv = new InstructionAdapter(mv); if (kind != OwnerKind.NAMESPACE) { @@ -182,7 +182,7 @@ public class PropertyCodegen { final String signature = state.getTypeMapper().mapSetterSignature(propertyDescriptor, kind).getDescriptor(); MethodVisitor mv = v.newMethod(origin, flags, setterName(propertyDescriptor.getName()), signature, null, null); - if (!isTrait || kind instanceof OwnerKind.DelegateKind) { + if (v.generateCode() && (!isTrait || kind instanceof OwnerKind.DelegateKind)) { mv.visitCode(); InstructionAdapter iv = new InstructionAdapter(mv); final Type type = state.getTypeMapper().mapType(propertyDescriptor.getOutType()); diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/TraitImplBodyCodegen.java b/compiler/backend/src/org/jetbrains/jet/codegen/TraitImplBodyCodegen.java index cdd5f7e3a48..ac374b72c5d 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/TraitImplBodyCodegen.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/TraitImplBodyCodegen.java @@ -45,7 +45,7 @@ public class TraitImplBodyCodegen extends ClassBodyCodegen { @Override protected void generateDeclaration() { - v.defineClass(Opcodes.V1_6, + v.defineClass(myClass, Opcodes.V1_6, Opcodes.ACC_PUBLIC | Opcodes.ACC_FINAL/*| Opcodes.ACC_SUPER*/, jvmName(), null, 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 61c59a5a058..f960da815bb 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 @@ -4,7 +4,9 @@ import com.google.common.collect.Lists; import com.google.common.collect.Maps; import com.google.common.collect.Sets; import com.intellij.openapi.project.Project; +import com.intellij.openapi.vfs.VirtualFile; import com.intellij.psi.*; +import com.intellij.psi.search.DelegatingGlobalSearchScope; import com.intellij.psi.search.GlobalSearchScope; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -14,6 +16,7 @@ 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; import java.util.*; @@ -61,7 +64,12 @@ public class JavaDescriptorResolver { public JavaDescriptorResolver(Project project, JavaSemanticServices semanticServices) { this.javaFacade = JavaPsiFacade.getInstance(project); - this.javaSearchScope = GlobalSearchScope.allScope(project); + this.javaSearchScope = new DelegatingGlobalSearchScope(GlobalSearchScope.allScope(project)) { + @Override + public boolean contains(VirtualFile file) { + return myBaseScope.contains(file) && file.getFileType() != JetFileType.INSTANCE; + } + }; this.semanticServices = semanticServices; } @@ -80,7 +88,7 @@ public class JavaDescriptorResolver { public ClassDescriptor resolveClass(@NotNull String qualifiedName) { ClassDescriptor classDescriptor = classDescriptorCache.get(qualifiedName); if (classDescriptor == null) { - PsiClass psiClass = javaFacade.findClass(qualifiedName, javaSearchScope); + PsiClass psiClass = findClass(qualifiedName); if (psiClass == null) { return null; } @@ -247,15 +255,23 @@ public class JavaDescriptorResolver { } public NamespaceDescriptor resolveNamespace(String qualifiedName) { - PsiPackage psiPackage = javaFacade.findPackage(qualifiedName); + PsiPackage psiPackage = findPackage(qualifiedName); if (psiPackage == null) { - PsiClass psiClass = javaFacade.findClass(qualifiedName, javaSearchScope); + PsiClass psiClass = findClass(qualifiedName); if (psiClass == null) return null; return resolveNamespace(psiClass); } return resolveNamespace(psiPackage); } + private PsiClass findClass(String qualifiedName) { + return javaFacade.findClass(qualifiedName, javaSearchScope); + } + + private PsiPackage findPackage(String qualifiedName) { + return javaFacade.findPackage(qualifiedName); + } + private NamespaceDescriptor resolveNamespace(@NotNull PsiPackage psiPackage) { NamespaceDescriptor namespaceDescriptor = namespaceDescriptorCache.get(psiPackage); if (namespaceDescriptor == null) { 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 5834dd945b7..483a5673739 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/AnalyzingUtils.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/AnalyzingUtils.java @@ -16,15 +16,13 @@ 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.Collection; -import java.util.Collections; -import java.util.List; -import java.util.Map; +import java.util.*; /** * @author abreslav @@ -120,4 +118,25 @@ public class AnalyzingUtils { 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/idea/src/META-INF/plugin.xml b/idea/src/META-INF/plugin.xml index a14c23ddbed..e767fd35eb3 100644 --- a/idea/src/META-INF/plugin.xml +++ b/idea/src/META-INF/plugin.xml @@ -56,5 +56,7 @@ + + diff --git a/idea/src/org/jetbrains/jet/plugin/java/ClsWrapperStubPsiFactory.java b/idea/src/org/jetbrains/jet/plugin/java/ClsWrapperStubPsiFactory.java new file mode 100644 index 00000000000..9da8650a56e --- /dev/null +++ b/idea/src/org/jetbrains/jet/plugin/java/ClsWrapperStubPsiFactory.java @@ -0,0 +1,122 @@ +/* + * @author max + */ +package org.jetbrains.jet.plugin.java; + +import com.intellij.openapi.util.Key; +import com.intellij.psi.*; +import com.intellij.psi.impl.compiled.ClsClassImpl; +import com.intellij.psi.impl.compiled.ClsEnumConstantImpl; +import com.intellij.psi.impl.compiled.ClsFieldImpl; +import com.intellij.psi.impl.compiled.ClsMethodImpl; +import com.intellij.psi.impl.java.stubs.*; +import com.intellij.psi.stubs.StubBase; +import org.jetbrains.annotations.NotNull; + +class ClsWrapperStubPsiFactory extends StubPsiFactory { + public static final Key ORIGIN_ELEMENT = Key.create("ORIGIN_ELEMENT"); + private final StubPsiFactory delegate = new ClsStubPsiFactory(); + + @Override + public PsiClass createClass(PsiClassStub stub) { + final PsiElement origin = ((StubBase) stub).getUserData(ORIGIN_ELEMENT); + if (origin == null) return delegate.createClass(stub); + + return new ClsClassImpl(stub) { + @NotNull + @Override + public PsiElement getNavigationElement() { + return origin; + } + }; + } + + @Override + public PsiAnnotation createAnnotation(PsiAnnotationStub stub) { + return delegate.createAnnotation(stub); + } + + @Override + public PsiClassInitializer createClassInitializer(PsiClassInitializerStub stub) { + return delegate.createClassInitializer(stub); + } + + @Override + public PsiReferenceList createClassReferenceList(PsiClassReferenceListStub stub) { + return delegate.createClassReferenceList(stub); + } + + @Override + public PsiField createField(PsiFieldStub stub) { + final PsiElement origin = ((StubBase) stub).getUserData(ORIGIN_ELEMENT); + if (origin == null) return delegate.createField(stub); + if (stub.isEnumConstant()) { + return new ClsEnumConstantImpl(stub) { + @NotNull + @Override + public PsiElement getNavigationElement() { + return origin; + } + }; + } + else { + return new ClsFieldImpl(stub) { + @NotNull + @Override + public PsiElement getNavigationElement() { + return origin; + } + }; + } + } + + @Override + public PsiImportList createImportList(PsiImportListStub stub) { + return delegate.createImportList(stub); + } + + @Override + public PsiImportStatementBase createImportStatement(PsiImportStatementStub stub) { + return delegate.createImportStatement(stub); + } + + @Override + public PsiMethod createMethod(PsiMethodStub stub) { + final PsiElement origin = ((StubBase) stub).getUserData(ORIGIN_ELEMENT); + if (origin == null) return delegate.createMethod(stub); + + return new ClsMethodImpl(stub) { + @NotNull + @Override + public PsiElement getNavigationElement() { + return origin; + } + }; + } + + @Override + public PsiModifierList createModifierList(PsiModifierListStub stub) { + return delegate.createModifierList(stub); + } + + @Override + public PsiParameter createParameter(PsiParameterStub stub) { + return delegate.createParameter(stub); + } + + @Override + public PsiParameterList createParameterList(PsiParameterListStub stub) { + return delegate.createParameterList(stub); + } + + @Override + public PsiTypeParameter createTypeParameter(PsiTypeParameterStub stub) { + return delegate.createTypeParameter(stub); + } + + @Override + public PsiTypeParameterList createTypeParameterList(PsiTypeParameterListStub stub) { + return delegate.createTypeParameterList(stub); + } + +} diff --git a/idea/src/org/jetbrains/jet/plugin/java/JavaElementFinder.java b/idea/src/org/jetbrains/jet/plugin/java/JavaElementFinder.java new file mode 100644 index 00000000000..5dcc079631f --- /dev/null +++ b/idea/src/org/jetbrains/jet/plugin/java/JavaElementFinder.java @@ -0,0 +1,220 @@ +/* + * @author max + */ +package org.jetbrains.jet.plugin.java; + +import com.google.common.base.Predicate; +import com.google.common.collect.Collections2; +import com.intellij.openapi.compiler.ex.CompilerPathsEx; +import com.intellij.openapi.fileTypes.FileType; +import com.intellij.openapi.fileTypes.FileTypeManager; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.roots.ProjectRootManager; +import com.intellij.openapi.util.Comparing; +import com.intellij.openapi.util.Key; +import com.intellij.openapi.vfs.VirtualFile; +import com.intellij.psi.*; +import com.intellij.psi.impl.PsiManagerImpl; +import com.intellij.psi.impl.compiled.ClsFileImpl; +import com.intellij.psi.impl.file.PsiPackageImpl; +import com.intellij.psi.impl.java.stubs.PsiClassStub; +import com.intellij.psi.impl.java.stubs.PsiJavaFileStub; +import com.intellij.psi.impl.java.stubs.impl.PsiJavaFileStubImpl; +import com.intellij.psi.search.GlobalSearchScope; +import com.intellij.psi.stubs.PsiClassHolderFileStub; +import com.intellij.psi.stubs.StubElement; +import com.intellij.util.SmartList; +import com.intellij.util.containers.Stack; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.jet.codegen.ClassBuilder; +import org.jetbrains.jet.codegen.ClassBuilderFactory; +import org.jetbrains.jet.codegen.GenerationState; +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.plugin.JetFileType; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; + +public class JavaElementFinder extends PsiElementFinder { + private final Project project; + + public JavaElementFinder(Project project) { + this.project = project; + } + + private final static Key JAVA_API_STUB = Key.create("JAVA_API_STUB"); + + @Override + public PsiClass findClass(@NotNull String qualifiedName, @NotNull GlobalSearchScope scope) { + final PsiClass[] allClasses = findClasses(qualifiedName, scope); + return allClasses.length > 0 ? allClasses[0] : null; + } + + @NotNull + @Override + public PsiClass[] findClasses(@NotNull String qualifiedName, @NotNull GlobalSearchScope scope) { + // Backend searches for java.lang.String. Will fail with SOE if continue + if (qualifiedName.startsWith("java.")) return PsiClass.EMPTY_ARRAY; + + List answer = new SmartList(); + final List filesInScope = ensureUpToDate(scope); + for (PsiFile file : filesInScope) { + final PsiJavaFileStub stub = file.getUserData(JAVA_API_STUB); + if (stub == null) continue; + + final String packageName = stub.getPackageName(); + if (packageName != null && qualifiedName.startsWith(packageName)) { + collectClasses(answer, qualifiedName, stub); + } + } + return answer.toArray(new PsiClass[answer.size()]); + } + + @Override + public PsiPackage findPackage(@NotNull String qualifiedName) { + final List psiFiles = collectProjectFiles(project, GlobalSearchScope.allScope(project)); + + for (PsiFile psiFile : psiFiles) { + if (psiFile instanceof JetFile) { + if (qualifiedName.equals(((JetFile) psiFile).getRootNamespace().getFQName())) { + return new PsiPackageImpl(psiFile.getManager(), qualifiedName); + } + } + } + + return null; + } + + @NotNull + @Override + public PsiClass[] getClasses(@NotNull PsiPackage psiPackage, @NotNull GlobalSearchScope scope) { + List answer = new SmartList(); + final List filesInScope = ensureUpToDate(scope); + final String qualifiedName = psiPackage.getQualifiedName(); + for (PsiFile file : filesInScope) { + final PsiJavaFileStub stub = file.getUserData(JAVA_API_STUB); + if (stub == null) continue; + + if (Comparing.equal(qualifiedName, stub.getPackageName())) { + for (StubElement child : stub.getChildrenStubs()) { + if (child instanceof PsiClassStub) { + answer.add((PsiClass) child.getPsi()); + } + } + } + } + return answer.toArray(new PsiClass[answer.size()]); + } + + private static void collectClasses(List answer, String qualifiedName, StubElement stub) { + if (stub instanceof PsiClassStub && qualifiedName.equals(((PsiClassStub) stub).getQualifiedName())) { + answer.add((PsiClass) stub.getPsi()); + } + + for (StubElement child : stub.getChildrenStubs()) { + collectClasses(answer, qualifiedName, child); + } + } + + private List ensureUpToDate(GlobalSearchScope scope) { + final Stack stubStack = new Stack(); + + final ClassBuilderFactory builderFactory = new ClassBuilderFactory() { + @Override + public ClassBuilder newClassBuilder() { + return new StubClassBuilder(stubStack); + } + + @Override + public String asText(ClassBuilder builder) { + throw new UnsupportedOperationException("asText is not implemented"); // TODO + } + + @Override + public byte[] asBytes(ClassBuilder builder) { + throw new UnsupportedOperationException("asBytes is not implemented"); // TODO + } + }; + + final GenerationState state = new GenerationState(project, builderFactory) { + @Override + protected void generateNamespace(JetNamespace namespace) { + final PsiJavaFileStubImpl fileStub = new PsiJavaFileStubImpl(namespace.getFQName(), true); + PsiManager manager = PsiManager.getInstance(project); + stubStack.push(fileStub); + + final PsiFile file = namespace.getContainingFile(); + file.putUserData(JAVA_API_STUB, fileStub); + fileStub.setPsiFactory(new ClsWrapperStubPsiFactory()); + final ClsFileImpl fakeFile = new ClsFileImpl((PsiManagerImpl) manager, new ClassFileViewProvider(manager, file.getVirtualFile())) { + @NotNull + @Override + public PsiClassHolderFileStub getStub() { + return fileStub; + } + }; + + fakeFile.setPhysical(false); + fileStub.setPsi(fakeFile); + + try { + super.generateNamespace(namespace); + } + finally { + final StubElement pop = stubStack.pop(); + assert pop == fileStub : "Unbalanced stack operations"; + } + } + }; + + final List psiFiles = collectProjectFiles(project, scope); + + Collection dirty = Collections2.filter(psiFiles, new Predicate() { + @Override + public boolean apply(PsiFile psiFile) { + return psiFile.getUserData(JAVA_API_STUB) == null; + } + }); + + + if (dirty.size() > 0) { + final BindingContext context = AnalyzingUtils.getInstance(JavaDefaultImports.JAVA_DEFAULT_IMPORTS).shallowAnalyzeFiles(dirty); + state.compileCorrectNamespaces(context, AnalyzingUtils.collectRootNamespaces(dirty)); + state.getFactory().files(); + } + + return psiFiles; + } + + private static List collectProjectFiles(final Project project, @NotNull final GlobalSearchScope scope) { + final List answer = new ArrayList(); + + + final FileTypeManager fileTypeManager = FileTypeManager.getInstance(); + final PsiManager psiManager = PsiManager.getInstance(project); + + VirtualFile[] contentRoots = ProjectRootManager.getInstance(project).getContentRoots(); + CompilerPathsEx.visitFiles(contentRoots, new CompilerPathsEx.FileVisitor() { + @Override + protected void acceptFile(VirtualFile file, String fileRoot, String filePath) { + final FileType fileType = fileTypeManager.getFileTypeByFile(file); + if (fileType != JetFileType.INSTANCE) return; + + if (scope.accept(file)) { + final PsiFile psiFile = psiManager.findFile(file); + if (psiFile instanceof JetFile) { + answer.add(psiFile); + } + } + } + }); + + return answer; + } +} + diff --git a/idea/src/org/jetbrains/jet/plugin/java/StubClassBuilder.java b/idea/src/org/jetbrains/jet/plugin/java/StubClassBuilder.java new file mode 100644 index 00000000000..99112749893 --- /dev/null +++ b/idea/src/org/jetbrains/jet/plugin/java/StubClassBuilder.java @@ -0,0 +1,98 @@ +/* + * @author max + */ +package org.jetbrains.jet.plugin.java; + +import com.intellij.psi.PsiElement; +import com.intellij.psi.impl.compiled.InnerClassSourceStrategy; +import com.intellij.psi.impl.compiled.StubBuildingVisitor; +import com.intellij.psi.stubs.StubBase; +import com.intellij.psi.stubs.StubElement; +import com.intellij.util.containers.Stack; +import org.jetbrains.annotations.Nullable; +import org.jetbrains.jet.codegen.ClassBuilder; +import org.objectweb.asm.ClassReader; +import org.objectweb.asm.ClassVisitor; +import org.objectweb.asm.FieldVisitor; +import org.objectweb.asm.MethodVisitor; + +import java.util.List; + +public class StubClassBuilder extends ClassBuilder { + private static final InnerClassSourceStrategy EMPTY_STRATEGY = new InnerClassSourceStrategy() { + @Override + public Object findInnerClass(String s, Object o) { + return null; + } + + @Override + public ClassReader readerForInnerClass(Object o) { + throw new UnsupportedOperationException("Shall not be called!"); + } + }; + private final StubElement parent; + private StubBuildingVisitor v; + private final Stack parentStack; + private boolean isNamespace = false; + + public StubClassBuilder(Stack parentStack) { + this.parentStack = parentStack; + this.parent = parentStack.peek(); + } + + @Override + public ClassVisitor getVisitor() { + assert v != null : "Called before class is defined"; + return v; + } + + @Override + public void defineClass(PsiElement origin, int version, int access, String name, @Nullable String signature, String superName, String[] interfaces) { + assert v == null : "defineClass() called twice?"; + v = new StubBuildingVisitor(null, EMPTY_STRATEGY, parent, access); + + super.defineClass(origin, version, access, name, signature, superName, interfaces); + if (name.equals("namespace") || name.endsWith("/namespace")) { + isNamespace = true; + } + else { + parentStack.push(v.getResult()); + } + + ((StubBase) v.getResult()).putUserData(ClsWrapperStubPsiFactory.ORIGIN_ELEMENT, origin); + } + + @Override + public MethodVisitor newMethod(@Nullable PsiElement origin, int access, String name, String desc, @Nullable String signature, @Nullable String[] exceptions) { + final MethodVisitor answer = super.newMethod(origin, access, name, desc, signature, exceptions); + markLastChild(origin); + return answer; + } + + @Override + public FieldVisitor newField(@Nullable PsiElement origin, int access, String name, String desc, @Nullable String signature, @Nullable Object value) { + final FieldVisitor answer = super.newField(origin, access, name, desc, signature, value); + markLastChild(origin); + return answer; + } + + private void markLastChild(PsiElement origin) { + final List children = v.getResult().getChildrenStubs(); + StubBase last = (StubBase) children.get(children.size() - 1); + last.putUserData(ClsWrapperStubPsiFactory.ORIGIN_ELEMENT, origin); + } + + @Override + public void done() { + if (!isNamespace) { + final StubElement pop = parentStack.pop(); + assert pop == v.getResult(); + } + super.done(); + } + + @Override + public boolean generateCode() { + return false; + } +}