diff --git a/build.xml b/build.xml index 68287f6f74f..83eaecaba8b 100644 --- a/build.xml +++ b/build.xml @@ -167,7 +167,7 @@ - + diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/ClassBodyCodegen.java b/compiler/backend/src/org/jetbrains/jet/codegen/ClassBodyCodegen.java index c6275166cea..a06a150cb3a 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/ClassBodyCodegen.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/ClassBodyCodegen.java @@ -136,7 +136,7 @@ public abstract class ClassBodyCodegen { private void generateStaticInitializer() { if (staticInitializerChunks.size() > 0) { final MethodVisitor mv = v.newMethod(null, Opcodes.ACC_PUBLIC | Opcodes.ACC_STATIC,"", "()V", null, null); - if (v.generateCode()) { + if (v.generateCode() == ClassBuilder.Mode.FULL) { mv.visitCode(); InstructionAdapter v = new InstructionAdapter(mv); diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/ClassBuilder.java b/compiler/backend/src/org/jetbrains/jet/codegen/ClassBuilder.java index dba4333f031..1847c77f6d2 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/ClassBuilder.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/ClassBuilder.java @@ -29,15 +29,22 @@ import org.objectweb.asm.MethodVisitor; public abstract class ClassBuilder { public static class Concrete extends ClassBuilder { private final ClassVisitor v; + private final boolean stubs; - public Concrete(ClassVisitor v) { + public Concrete(ClassVisitor v, boolean stubs) { this.v = v; + this.stubs = stubs; } @Override public ClassVisitor getVisitor() { return v; } + + @Override + public Mode generateCode() { + return stubs ? Mode.STUBS : Mode.FULL; + } } public FieldVisitor newField(@Nullable PsiElement origin, int access, @@ -85,7 +92,14 @@ public abstract class ClassBuilder { getVisitor().visitInnerClass(name, outerName, innerName, access); } - public boolean generateCode() { - return true; + public enum Mode { + /** Full function bodies */ + FULL, + /** Only function signatures */ + SIGNATURES, + /** Function with stub bodies: just throw exception */ + STUBS, } + + public abstract Mode generateCode(); } diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/ClassBuilderFactories.java b/compiler/backend/src/org/jetbrains/jet/codegen/ClassBuilderFactories.java new file mode 100644 index 00000000000..ff2e616aa82 --- /dev/null +++ b/compiler/backend/src/org/jetbrains/jet/codegen/ClassBuilderFactories.java @@ -0,0 +1,82 @@ +/* + * Copyright 2000-2012 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jetbrains.jet.codegen; + +import org.objectweb.asm.ClassWriter; +import org.objectweb.asm.util.TraceClassVisitor; + +import java.io.PrintWriter; +import java.io.StringWriter; + +/** + * @author Stepan Koltsov + */ +public class ClassBuilderFactories { + + public static ClassBuilderFactory TEXT = new ClassBuilderFactory() { + @Override + public ClassBuilder newClassBuilder() { + return new ClassBuilder.Concrete(new TraceClassVisitor(new PrintWriter(new StringWriter())), false); + } + + @Override + public String asText(ClassBuilder builder) { + TraceClassVisitor visitor = (TraceClassVisitor) builder.getVisitor(); + + StringWriter writer = new StringWriter(); + visitor.print(new PrintWriter(writer)); + + return writer.toString(); + } + + @Override + public byte[] asBytes(ClassBuilder builder) { + throw new UnsupportedOperationException("TEXT generator asked for bytes"); + } + }; + + public static ClassBuilderFactory binaries(final boolean stubs) { + return new ClassBuilderFactory() { + @Override + public ClassBuilder newClassBuilder() { + return new ClassBuilder.Concrete(new ClassWriter(ClassWriter.COMPUTE_FRAMES | ClassWriter.COMPUTE_MAXS){ + @Override + protected String getCommonSuperClass(String type1, String type2) { + try { + return super.getCommonSuperClass(type1, type2); + } + catch (Throwable t) { + // @todo we might need at some point do more sofisticated handling + return "java/lang/Object"; + } + } + }, stubs); + } + + @Override + public String asText(ClassBuilder builder) { + throw new UnsupportedOperationException("BINARIES generator asked for text"); + } + + @Override + public byte[] asBytes(ClassBuilder builder) { + ClassWriter visitor = (ClassWriter) builder.getVisitor(); + return visitor.toByteArray(); + } + }; + } +} diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/ClassBuilderFactory.java b/compiler/backend/src/org/jetbrains/jet/codegen/ClassBuilderFactory.java index d4dc9949467..e46d50c4fe2 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/ClassBuilderFactory.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/ClassBuilderFactory.java @@ -29,56 +29,4 @@ public interface ClassBuilderFactory { ClassBuilder newClassBuilder(); String asText(ClassBuilder builder); byte[] asBytes(ClassBuilder builder); - - ClassBuilderFactory TEXT = new ClassBuilderFactory() { - @Override - public ClassBuilder newClassBuilder() { - return new ClassBuilder.Concrete(new TraceClassVisitor(new PrintWriter(new StringWriter()))); - } - - @Override - public String asText(ClassBuilder builder) { - TraceClassVisitor visitor = (TraceClassVisitor) builder.getVisitor(); - - StringWriter writer = new StringWriter(); - visitor.print(new PrintWriter(writer)); - - return writer.toString(); - } - - @Override - public byte[] asBytes(ClassBuilder builder) { - throw new UnsupportedOperationException("TEXT generator asked for bytes"); - } - }; - - ClassBuilderFactory BINARIES = new ClassBuilderFactory() { - @Override - public ClassBuilder newClassBuilder() { - return new ClassBuilder.Concrete(new ClassWriter(ClassWriter.COMPUTE_FRAMES | ClassWriter.COMPUTE_MAXS){ - @Override - protected String getCommonSuperClass(String type1, String type2) { - try { - return super.getCommonSuperClass(type1, type2); - } - catch (Throwable t) { - // @todo we might need at some point do more sofisticated handling - return "java/lang/Object"; - } - } - }); - } - - @Override - public String asText(ClassBuilder builder) { - throw new UnsupportedOperationException("BINARIES generator asked for text"); - } - - @Override - public byte[] asBytes(ClassBuilder builder) { - ClassWriter visitor = (ClassWriter) builder.getVisitor(); - return visitor.toByteArray(); - } - }; - } diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/ClassCodegen.java b/compiler/backend/src/org/jetbrains/jet/codegen/ClassCodegen.java index aa8753a8d8d..ea884fd62d0 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/ClassCodegen.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/ClassCodegen.java @@ -40,7 +40,7 @@ public class ClassCodegen { final CodegenContext contextForInners = context.intoClass(descriptor, OwnerKind.IMPLEMENTATION, state.getTypeMapper()); - if (!classBuilder.generateCode()) { + if (classBuilder.generateCode() == ClassBuilder.Mode.SIGNATURES) { // Outer class implementation must happen prior inner classes so we get proper scoping tree in JetLightClass's delegate generateImplementation(context, aClass, OwnerKind.IMPLEMENTATION, contextForInners.accessors, classBuilder); } @@ -54,7 +54,7 @@ public class ClassCodegen { } } - if (classBuilder.generateCode()) { + if (classBuilder.generateCode() != ClassBuilder.Mode.SIGNATURES) { generateImplementation(context, aClass, OwnerKind.IMPLEMENTATION, contextForInners.accessors, classBuilder); } diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/ClosureCodegen.java b/compiler/backend/src/org/jetbrains/jet/codegen/ClosureCodegen.java index 310039906e3..c77fc814625 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/ClosureCodegen.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/ClosureCodegen.java @@ -166,7 +166,10 @@ public class ClosureCodegen extends ObjectOrClosureCodegen { cv.newField(fun, ACC_PRIVATE | ACC_STATIC | ACC_FINAL, "$instance", classDescr, null, null); MethodVisitor mv = cv.newMethod(fun, ACC_PUBLIC | ACC_STATIC, "$getInstance", "()" + classDescr, null, new String[0]); - if (cv.generateCode()) { + if (cv.generateCode() == ClassBuilder.Mode.STUBS) { + StubCodegen.generateStubCode(mv); + } + else if (cv.generateCode() == ClassBuilder.Mode.FULL) { mv.visitCode(); mv.visitFieldInsn(GETSTATIC, name, "$instance", classDescr); mv.visitInsn(DUP); @@ -204,7 +207,10 @@ public class ClosureCodegen extends ObjectOrClosureCodegen { return; final MethodVisitor mv = cv.newMethod(fun, ACC_PUBLIC, "invoke", bridge.getAsmMethod().getDescriptor(), null, new String[0]); - if (cv.generateCode()) { + if (cv.generateCode() == ClassBuilder.Mode.STUBS) { + StubCodegen.generateStubCode(mv); + } + if (cv.generateCode() == ClassBuilder.Mode.FULL) { mv.visitCode(); InstructionAdapter iv = new InstructionAdapter(mv); @@ -280,7 +286,10 @@ 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]); - if (cv.generateCode()) { + if (cv.generateCode() == ClassBuilder.Mode.STUBS) { + StubCodegen.generateStubCode(mv); + } + else if (cv.generateCode() == ClassBuilder.Mode.FULL) { mv.visitCode(); InstructionAdapter iv = new InstructionAdapter(mv); diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/FunctionCodegen.java b/compiler/backend/src/org/jetbrains/jet/codegen/FunctionCodegen.java index 678bceaa671..636e96e9cc0 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/FunctionCodegen.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/FunctionCodegen.java @@ -115,7 +115,7 @@ public class FunctionCodegen { final MethodVisitor mv = v.newMethod(fun, flags, jvmSignature.getAsmMethod().getName(), jvmSignature.getAsmMethod().getDescriptor(), jvmSignature.getGenericsSignature(), null); AnnotationCodegen.forMethod(mv).genAnnotations(functionDescriptor, state.getTypeMapper()); - if(v.generateCode()) { + if(v.generateCode() != ClassBuilder.Mode.SIGNATURES) { int start = 0; if (needJetAnnotations) { if (functionDescriptor instanceof PropertyAccessorDescriptor) { @@ -164,8 +164,12 @@ public class FunctionCodegen { } } + if (!isAbstract && v.generateCode() == ClassBuilder.Mode.STUBS) { + StubCodegen.generateStubCode(mv); + } - if (!isAbstract && v.generateCode()) { + + if (!isAbstract && v.generateCode() == ClassBuilder.Mode.FULL) { mv.visitCode(); Label methodBegin = new Label(); @@ -323,7 +327,10 @@ public class FunctionCodegen { descriptor = descriptor.replace("(","(L" + ownerInternalName + ";"); final MethodVisitor mv = v.newMethod(null, flags | (isConstructor ? 0 : ACC_STATIC), isConstructor ? "" : jvmSignature.getName() + JvmAbi.DEFAULT_PARAMS_IMPL_SUFFIX, descriptor, null, null); InstructionAdapter iv = new InstructionAdapter(mv); - if (v.generateCode()) { + if (v.generateCode() == ClassBuilder.Mode.STUBS) { + StubCodegen.generateStubCode(mv); + } + else if (v.generateCode() == ClassBuilder.Mode.FULL) { mv.visitCode(); FrameMap frameMap = owner.prepareFrame(state.getTypeMapper()); @@ -443,7 +450,10 @@ public class FunctionCodegen { int flags = ACC_PUBLIC | ACC_BRIDGE; // TODO. final MethodVisitor mv = v.newMethod(null, flags, jvmSignature.getName(), overriden.getDescriptor(), null, null); - if (v.generateCode()) { + if (v.generateCode() == ClassBuilder.Mode.STUBS) { + StubCodegen.generateStubCode(mv); + } + else if (v.generateCode() == ClassBuilder.Mode.FULL) { mv.visitCode(); Type[] argTypes = overriden.getArgumentTypes(); @@ -481,7 +491,10 @@ public class FunctionCodegen { int flags = ACC_PUBLIC | ACC_SYNTHETIC; // TODO. final MethodVisitor mv = v.newMethod(null, flags, method.getName(), method.getDescriptor(), null, null); - if (v.generateCode()) { + if (v.generateCode() == ClassBuilder.Mode.STUBS) { + StubCodegen.generateStubCode(mv); + } + else if (v.generateCode() == ClassBuilder.Mode.FULL) { mv.visitCode(); Type[] argTypes = method.getArgumentTypes(); diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/ImplementationBodyCodegen.java b/compiler/backend/src/org/jetbrains/jet/codegen/ImplementationBodyCodegen.java index e377090ba2c..0ff3405763f 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/ImplementationBodyCodegen.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/ImplementationBodyCodegen.java @@ -272,7 +272,10 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen { Type[] argTypes = method.getArgumentTypes(); MethodVisitor mv = v.newMethod(null, ACC_PUBLIC| ACC_BRIDGE| ACC_FINAL, bridge.getName(), method.getDescriptor(), null, null); - if (v.generateCode()) { + if (v.generateCode() == ClassBuilder.Mode.STUBS) { + StubCodegen.generateStubCode(mv); + } + else if (v.generateCode() == ClassBuilder.Mode.FULL) { mv.visitCode(); InstructionAdapter iv = new InstructionAdapter(mv); @@ -300,7 +303,10 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen { Method originalMethod = originalSignature.getJvmMethodSignature().getAsmMethod(); MethodVisitor mv = v.newMethod(null, ACC_PUBLIC | ACC_BRIDGE | ACC_FINAL, method.getName(), method.getDescriptor(), null, null); PropertyCodegen.generateJetPropertyAnnotation(mv, originalSignature.getPropertyTypeKotlinSignature(), originalSignature.getJvmMethodSignature().getKotlinTypeParameter()); - if (v.generateCode()) { + if (v.generateCode() == ClassBuilder.Mode.STUBS) { + StubCodegen.generateStubCode(mv); + } + else if (v.generateCode() == ClassBuilder.Mode.FULL) { mv.visitCode(); InstructionAdapter iv = new InstructionAdapter(mv); @@ -323,7 +329,10 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen { Method originalMethod = originalSignature2.getJvmMethodSignature().getAsmMethod(); MethodVisitor mv = v.newMethod(null, ACC_PUBLIC | ACC_BRIDGE | ACC_FINAL, method.getName(), method.getDescriptor(), null, null); PropertyCodegen.generateJetPropertyAnnotation(mv, originalSignature2.getPropertyTypeKotlinSignature(), originalSignature2.getJvmMethodSignature().getKotlinTypeParameter()); - if (v.generateCode()) { + if (v.generateCode() == ClassBuilder.Mode.STUBS) { + StubCodegen.generateStubCode(mv); + } + else if (v.generateCode() == ClassBuilder.Mode.FULL) { mv.visitCode(); InstructionAdapter iv = new InstructionAdapter(mv); @@ -482,8 +491,8 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen { int flags = ACC_PUBLIC; // TODO final MethodVisitor mv = v.newMethod(myClass, flags, constructorMethod.getName(), constructorMethod.getAsmMethod().getDescriptor(), constructorMethod.getGenericsSignature(), null); - if (!v.generateCode()) return; - + if (v.generateCode() == ClassBuilder.Mode.SIGNATURES) return; + AnnotationVisitor jetConstructorVisitor = mv.visitAnnotation(JvmStdlibNames.JET_CONSTRUCTOR.getDescriptor(), true); if (constructorDescriptor == null) { jetConstructorVisitor.visit(JvmStdlibNames.JET_CONSTRUCTOR_HIDDEN_FIELD, true); @@ -509,6 +518,11 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen { } } + if (v.generateCode() == ClassBuilder.Mode.STUBS) { + StubCodegen.generateStubCode(mv); + return; + } + mv.visitCode(); List paramDescrs = constructorDescriptor != null @@ -678,7 +692,10 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen { Method functionOriginal = typeMapper.mapSignature(fun.getName(), fun.getOriginal()).getAsmMethod(); final MethodVisitor mv = v.newMethod(myClass, flags, function.getName(), function.getDescriptor(), null, null); - if (v.generateCode()) { + if (v.generateCode() == ClassBuilder.Mode.STUBS) { + StubCodegen.generateStubCode(mv); + } + else if (v.generateCode() == ClassBuilder.Mode.FULL) { mv.visitCode(); codegen.generateThisOrOuter(descriptor); @@ -813,7 +830,10 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen { CallableMethod method = typeMapper.mapToCallableMethod(constructorDescriptor, kind, typeMapper.hasThis0(constructorDescriptor.getContainingDeclaration())); int flags = ACC_PUBLIC; // TODO final MethodVisitor mv = v.newMethod(constructor, flags, "", method.getSignature().getAsmMethod().getDescriptor(), null, null); - if (v.generateCode()) { + if (v.generateCode() == ClassBuilder.Mode.STUBS) { + StubCodegen.generateStubCode(mv); + } + else if (v.generateCode() == ClassBuilder.Mode.FULL) { mv.visitCode(); ConstructorFrameMap frameMap = new ConstructorFrameMap(method, constructorDescriptor, typeMapper.hasThis0(constructorDescriptor.getContainingDeclaration())); diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/NamespaceCodegen.java b/compiler/backend/src/org/jetbrains/jet/codegen/NamespaceCodegen.java index d417ad19eb5..6f1c1c255c1 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/NamespaceCodegen.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/NamespaceCodegen.java @@ -89,7 +89,7 @@ public class NamespaceCodegen { private void generateStaticInitializers(JetFile namespace) { MethodVisitor mv = v.newMethod(namespace, ACC_PUBLIC | ACC_STATIC, "", "()V", null, null); - if (v.generateCode()) { + if (v.generateCode() == ClassBuilder.Mode.FULL) { mv.visitCode(); FrameMap frameMap = new FrameMap(); diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/PropertyCodegen.java b/compiler/backend/src/org/jetbrains/jet/codegen/PropertyCodegen.java index 5710b95ee5e..375fbca4fd3 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/PropertyCodegen.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/PropertyCodegen.java @@ -169,24 +169,28 @@ public class PropertyCodegen { AnnotationCodegen.forMethod(mv).genAnnotations(propertyDescriptor.getGetter(), state.getTypeMapper()); } - if (v.generateCode() && (!isTrait || kind instanceof OwnerKind.DelegateKind)) { + if (v.generateCode() != ClassBuilder.Mode.SIGNATURES && (!isTrait || kind instanceof OwnerKind.DelegateKind)) { mv.visitCode(); - InstructionAdapter iv = new InstructionAdapter(mv); - if (kind != OwnerKind.NAMESPACE) { - iv.load(0, JetTypeMapper.TYPE_OBJECT); + if (v.generateCode() == ClassBuilder.Mode.STUBS) { + StubCodegen.generateStubThrow(mv); + } else { + InstructionAdapter iv = new InstructionAdapter(mv); + if (kind != OwnerKind.NAMESPACE) { + iv.load(0, JetTypeMapper.TYPE_OBJECT); + } + final Type type = state.getTypeMapper().mapType(propertyDescriptor.getType()); + if (kind instanceof OwnerKind.DelegateKind) { + OwnerKind.DelegateKind dk = (OwnerKind.DelegateKind) kind; + dk.getDelegate().put(JetTypeMapper.TYPE_OBJECT, iv); + iv.invokeinterface(dk.getOwnerClass(), getterName, descriptor); + } + else { + iv.visitFieldInsn(kind == OwnerKind.NAMESPACE ? Opcodes.GETSTATIC : Opcodes.GETFIELD, + state.getTypeMapper().getOwner(propertyDescriptor, kind), propertyDescriptor.getName(), + type.getDescriptor()); + } + iv.areturn(type); } - final Type type = state.getTypeMapper().mapType(propertyDescriptor.getType()); - if (kind instanceof OwnerKind.DelegateKind) { - OwnerKind.DelegateKind dk = (OwnerKind.DelegateKind) kind; - dk.getDelegate().put(JetTypeMapper.TYPE_OBJECT, iv); - iv.invokeinterface(dk.getOwnerClass(), getterName, descriptor); - } - else { - iv.visitFieldInsn(kind == OwnerKind.NAMESPACE ? Opcodes.GETSTATIC : Opcodes.GETFIELD, - state.getTypeMapper().getOwner(propertyDescriptor, kind), propertyDescriptor.getName(), - type.getDescriptor()); - } - iv.areturn(type); FunctionCodegen.endVisit(mv, "getter", origin); } } @@ -233,32 +237,36 @@ public class PropertyCodegen { AnnotationCodegen.forMethod(mv).genAnnotations(propertyDescriptor.getSetter(), state.getTypeMapper()); } - if (v.generateCode() && (!isTrait || kind instanceof OwnerKind.DelegateKind)) { + if (v.generateCode() != ClassBuilder.Mode.SIGNATURES && (!isTrait || kind instanceof OwnerKind.DelegateKind)) { mv.visitCode(); - InstructionAdapter iv = new InstructionAdapter(mv); - final Type type = state.getTypeMapper().mapType(propertyDescriptor.getType()); - int paramCode = 0; - if (kind != OwnerKind.NAMESPACE) { - iv.load(0, JetTypeMapper.TYPE_OBJECT); - paramCode = 1; - } + if (v.generateCode() == ClassBuilder.Mode.STUBS) { + StubCodegen.generateStubThrow(mv); + } else { + InstructionAdapter iv = new InstructionAdapter(mv); + final Type type = state.getTypeMapper().mapType(propertyDescriptor.getType()); + int paramCode = 0; + if (kind != OwnerKind.NAMESPACE) { + iv.load(0, JetTypeMapper.TYPE_OBJECT); + paramCode = 1; + } - if (kind instanceof OwnerKind.DelegateKind) { - OwnerKind.DelegateKind dk = (OwnerKind.DelegateKind) kind; - iv.load(0, JetTypeMapper.TYPE_OBJECT); - dk.getDelegate().put(JetTypeMapper.TYPE_OBJECT, iv); + if (kind instanceof OwnerKind.DelegateKind) { + OwnerKind.DelegateKind dk = (OwnerKind.DelegateKind) kind; + iv.load(0, JetTypeMapper.TYPE_OBJECT); + dk.getDelegate().put(JetTypeMapper.TYPE_OBJECT, iv); - iv.load(paramCode, type); - iv.invokeinterface(dk.getOwnerClass(), setterName(propertyDescriptor.getName()), descriptor); - } - else { - iv.load(paramCode, type); - iv.visitFieldInsn(kind == OwnerKind.NAMESPACE ? Opcodes.PUTSTATIC : Opcodes.PUTFIELD, - state.getTypeMapper().getOwner(propertyDescriptor, kind), propertyDescriptor.getName(), - type.getDescriptor()); - } + iv.load(paramCode, type); + iv.invokeinterface(dk.getOwnerClass(), setterName(propertyDescriptor.getName()), descriptor); + } + else { + iv.load(paramCode, type); + iv.visitFieldInsn(kind == OwnerKind.NAMESPACE ? Opcodes.PUTSTATIC : Opcodes.PUTFIELD, + state.getTypeMapper().getOwner(propertyDescriptor, kind), propertyDescriptor.getName(), + type.getDescriptor()); + } - iv.visitInsn(Opcodes.RETURN); + iv.visitInsn(Opcodes.RETURN); + } FunctionCodegen.endVisit(mv, "setter", origin); mv.visitEnd(); } diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/StubCodegen.java b/compiler/backend/src/org/jetbrains/jet/codegen/StubCodegen.java new file mode 100644 index 00000000000..d6a1ac94f95 --- /dev/null +++ b/compiler/backend/src/org/jetbrains/jet/codegen/StubCodegen.java @@ -0,0 +1,41 @@ +/* + * Copyright 2000-2012 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jetbrains.jet.codegen; + +import org.objectweb.asm.MethodVisitor; +import org.objectweb.asm.Type; +import org.objectweb.asm.commons.InstructionAdapter; + +/** + * @author Stepan Koltsov + */ +public class StubCodegen { + public static void generateStubThrow(MethodVisitor mv) { + new InstructionAdapter(mv).anew(Type.getObjectType("java/lang/RuntimeException")); + new InstructionAdapter(mv).dup(); + new InstructionAdapter(mv).aconst("Stubs are for compiler only, do not add them to runtime classpath"); + new InstructionAdapter(mv).invokespecial("java/lang/RuntimeException", "", "(Ljava/lang/String;)V"); + new InstructionAdapter(mv).athrow(); + } + + public static void generateStubCode(MethodVisitor mv) { + mv.visitCode(); + generateStubThrow(mv); + mv.visitMaxs(-1, -1); + mv.visitEnd(); + } +} diff --git a/compiler/cli/src/org/jetbrains/jet/cli/KotlinCompiler.java b/compiler/cli/src/org/jetbrains/jet/cli/KotlinCompiler.java index 7c550694bb6..62d0e459c6b 100644 --- a/compiler/cli/src/org/jetbrains/jet/cli/KotlinCompiler.java +++ b/compiler/cli/src/org/jetbrains/jet/cli/KotlinCompiler.java @@ -69,8 +69,8 @@ public class KotlinCompiler { @Argument(value = "help", alias = "h", description = "show help") public boolean help; - @Argument(value = "ignoreErrors", description = "Emit byte code even if there are compilation errors (not recommended)") - public boolean ignoreErrors; + @Argument(value = "stubs", description = "Compile stubs: ignore function bodies") + public boolean stubs; @Argument(value = "transformNamesToJava", description = "Transform Kotlin file names to *.java. This option is needed for compiling kotlinized Java library headers") public boolean transformNamesToJava; @@ -119,14 +119,10 @@ public class KotlinCompiler { CompileEnvironment environment = new CompileEnvironment(arguments.transformNamesToJava ? ANY_EXTENSION_TO_JAVA : FileNameTransformer.IDENTITY); try { - environment.setIgnoreErrors(arguments.ignoreErrors); - if (arguments.ignoreErrors) { - // To avoid outputting error messages - environment.setErrorStream(new PrintStream(new ByteArrayOutputStream())); - } - else { - environment.setErrorStream(errStream); - } + environment.setIgnoreErrors(false); + environment.setErrorStream(errStream); + + environment.setStubs(arguments.stubs); if (arguments.docOutputDir != null) { KDocLoader factory = new KDocLoader(arguments.docOutputDir); diff --git a/compiler/cli/src/org/jetbrains/jet/compiler/CompileEnvironment.java b/compiler/cli/src/org/jetbrains/jet/compiler/CompileEnvironment.java index 95ba252fc8d..a1dd8251b17 100644 --- a/compiler/cli/src/org/jetbrains/jet/compiler/CompileEnvironment.java +++ b/compiler/cli/src/org/jetbrains/jet/compiler/CompileEnvironment.java @@ -60,6 +60,7 @@ public class CompileEnvironment { private URL myStdlib; private boolean ignoreErrors = false; + private boolean stubs = false; public CompileEnvironment() { this(FileNameTransformer.IDENTITY); @@ -83,6 +84,10 @@ public class CompileEnvironment { this.ignoreErrors = ignoreErrors; } + public void setStubs(boolean stubs) { + this.stubs = stubs; + } + public void dispose() { Disposer.dispose(myRootDisposable); } @@ -229,6 +234,7 @@ public class CompileEnvironment { public ClassFileFactory compileModule(Module moduleBuilder, String directory) { CompileSession moduleCompileSession = new CompileSession(myEnvironment); + moduleCompileSession.setStubs(stubs); if (moduleBuilder.getSourceFiles().isEmpty()) { throw new CompileEnvironmentException("No source files where defined"); @@ -349,6 +355,8 @@ public class CompileEnvironment { public boolean compileBunchOfSources(String sourceFileOrDir, String jar, String outputDir, boolean includeRuntime) { CompileSession session = new CompileSession(myEnvironment, myFileNameTransformer); + session.setStubs(stubs); + session.addSources(sourceFileOrDir); String mainClass = null; diff --git a/compiler/cli/src/org/jetbrains/jet/compiler/CompileSession.java b/compiler/cli/src/org/jetbrains/jet/compiler/CompileSession.java index 804730b40f6..641376b40b4 100644 --- a/compiler/cli/src/org/jetbrains/jet/compiler/CompileSession.java +++ b/compiler/cli/src/org/jetbrains/jet/compiler/CompileSession.java @@ -16,6 +16,7 @@ package org.jetbrains.jet.compiler; +import com.google.common.base.Predicate; import com.google.common.base.Predicates; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.text.StringUtil; @@ -56,6 +57,7 @@ public class CompileSession { private final List mySourceFiles = new ArrayList(); private final FileNameTransformer myFileNameTransformer; private List myErrors = new ArrayList(); + private boolean stubs = false; public BindingContext getMyBindingContext() { return myBindingContext; @@ -71,7 +73,11 @@ public class CompileSession { myEnvironment = environment; myFileNameTransformer = fileNameTransformer; } - + + public void setStubs(boolean stubs) { + this.stubs = stubs; + } + public void addSources(String path) { if(path == null) return; @@ -172,8 +178,10 @@ public class CompileSession { } private void analyzeAndReportSemanticErrors(ErrorCollector errorCollector) { + Predicate filesToAnalyzeCompletely = + stubs ? Predicates.alwaysFalse() : Predicates.alwaysTrue(); myBindingContext = AnalyzerFacade.analyzeFilesWithJavaIntegration( - myEnvironment.getProject(), mySourceFiles, Predicates.alwaysTrue(), JetControlFlowDataTraceFactory.EMPTY); + myEnvironment.getProject(), mySourceFiles, filesToAnalyzeCompletely, JetControlFlowDataTraceFactory.EMPTY); for (Diagnostic diagnostic : myBindingContext.getDiagnostics()) { errorCollector.report(diagnostic); @@ -197,7 +205,7 @@ public class CompileSession { @NotNull public ClassFileFactory generate() { Project project = myEnvironment.getProject(); - GenerationState generationState = new GenerationState(project, ClassBuilderFactory.BINARIES, myFileNameTransformer); + GenerationState generationState = new GenerationState(project, ClassBuilderFactories.binaries(stubs), myFileNameTransformer); generationState.compileCorrectFiles(myBindingContext, mySourceFiles, CompilationErrorHandler.THROW_EXCEPTION, true); ClassFileFactory answer = generationState.getFactory(); diff --git a/compiler/jet.as.java.psi/src/org/jetbrains/jet/asJava/StubClassBuilder.java b/compiler/jet.as.java.psi/src/org/jetbrains/jet/asJava/StubClassBuilder.java index 7360c136ffa..3939934acdd 100644 --- a/compiler/jet.as.java.psi/src/org/jetbrains/jet/asJava/StubClassBuilder.java +++ b/compiler/jet.as.java.psi/src/org/jetbrains/jet/asJava/StubClassBuilder.java @@ -109,7 +109,7 @@ public class StubClassBuilder extends ClassBuilder { } @Override - public boolean generateCode() { - return false; + public Mode generateCode() { + return Mode.SIGNATURES; } } diff --git a/compiler/tests/org/jetbrains/jet/codegen/CodegenTestCase.java b/compiler/tests/org/jetbrains/jet/codegen/CodegenTestCase.java index 73b78acc40c..9fefc9e5cc5 100644 --- a/compiler/tests/org/jetbrains/jet/codegen/CodegenTestCase.java +++ b/compiler/tests/org/jetbrains/jet/codegen/CodegenTestCase.java @@ -116,7 +116,7 @@ public abstract class CodegenTestCase extends JetLiteFixture { } protected String generateToText() { - GenerationState state = new GenerationState(getProject(), ClassBuilderFactory.TEXT); + GenerationState state = new GenerationState(getProject(), ClassBuilderFactories.TEXT); AnalyzingUtils.checkForSyntacticErrors(myFile); state.compile(myFile); @@ -159,7 +159,7 @@ public abstract class CodegenTestCase extends JetLiteFixture { @NotNull protected ClassFileFactory generateClassesInFile() { try { - GenerationState state = new GenerationState(getProject(), ClassBuilderFactory.BINARIES); + GenerationState state = new GenerationState(getProject(), ClassBuilderFactories.binaries(false)); AnalyzingUtils.checkForSyntacticErrors(myFile); state.compile(myFile); diff --git a/compiler/tests/org/jetbrains/jet/compiler/CompileJavaAgainstKotlinTest.java b/compiler/tests/org/jetbrains/jet/compiler/CompileJavaAgainstKotlinTest.java index 64d036a7693..1f911cd1e9d 100644 --- a/compiler/tests/org/jetbrains/jet/compiler/CompileJavaAgainstKotlinTest.java +++ b/compiler/tests/org/jetbrains/jet/compiler/CompileJavaAgainstKotlinTest.java @@ -26,7 +26,7 @@ import junit.framework.Test; import org.jetbrains.annotations.NotNull; import org.jetbrains.jet.JetTestCaseBuilder; import org.jetbrains.jet.JetTestUtils; -import org.jetbrains.jet.codegen.ClassBuilderFactory; +import org.jetbrains.jet.codegen.ClassBuilderFactories; import org.jetbrains.jet.codegen.ClassFileFactory; import org.jetbrains.jet.codegen.GenerationState; import org.jetbrains.jet.lang.psi.JetFile; @@ -78,7 +78,7 @@ public class CompileJavaAgainstKotlinTest extends TestCaseWithTmpdir { 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); + GenerationState state = new GenerationState(jetCoreEnvironment.getProject(), ClassBuilderFactories.binaries(false)); AnalyzingUtils.checkForSyntacticErrors(psiFile); state.compile(psiFile); diff --git a/compiler/tests/org/jetbrains/jet/compiler/CompileKotlinAgainstKotlinTest.java b/compiler/tests/org/jetbrains/jet/compiler/CompileKotlinAgainstKotlinTest.java index d2d955d41e1..0b3e3ef1af6 100644 --- a/compiler/tests/org/jetbrains/jet/compiler/CompileKotlinAgainstKotlinTest.java +++ b/compiler/tests/org/jetbrains/jet/compiler/CompileKotlinAgainstKotlinTest.java @@ -27,6 +27,7 @@ import junit.framework.Test; import org.jetbrains.annotations.NotNull; import org.jetbrains.jet.JetTestCaseBuilder; import org.jetbrains.jet.JetTestUtils; +import org.jetbrains.jet.codegen.ClassBuilderFactories; import org.jetbrains.jet.codegen.ClassBuilderFactory; import org.jetbrains.jet.codegen.ClassFileFactory; import org.jetbrains.jet.codegen.GenerationState; @@ -92,7 +93,7 @@ public class CompileKotlinAgainstKotlinTest extends TestCaseWithTmpdir { 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); + GenerationState state = new GenerationState(jetCoreEnvironment.getProject(), ClassBuilderFactories.binaries(false)); AnalyzingUtils.checkForSyntacticErrors(psiFile); state.compile(psiFile); @@ -115,7 +116,7 @@ public class CompileKotlinAgainstKotlinTest extends TestCaseWithTmpdir { 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); + GenerationState state = new GenerationState(jetCoreEnvironment.getProject(), ClassBuilderFactories.binaries(false)); AnalyzingUtils.checkForSyntacticErrors(psiFile); state.compile(psiFile); diff --git a/compiler/tests/org/jetbrains/jet/compiler/ReadKotlinBinaryClassTest.java b/compiler/tests/org/jetbrains/jet/compiler/ReadKotlinBinaryClassTest.java index 9f6180041bd..39b3fc5668a 100644 --- a/compiler/tests/org/jetbrains/jet/compiler/ReadKotlinBinaryClassTest.java +++ b/compiler/tests/org/jetbrains/jet/compiler/ReadKotlinBinaryClassTest.java @@ -26,7 +26,7 @@ import junit.framework.Test; import org.jetbrains.annotations.NotNull; import org.jetbrains.jet.JetTestCaseBuilder; import org.jetbrains.jet.JetTestUtils; -import org.jetbrains.jet.codegen.ClassBuilderFactory; +import org.jetbrains.jet.codegen.ClassBuilderFactories; import org.jetbrains.jet.codegen.ClassFileFactory; import org.jetbrains.jet.codegen.GenerationState; import org.jetbrains.jet.lang.JetSemanticServices; @@ -70,7 +70,7 @@ public class ReadKotlinBinaryClassTest extends TestCaseWithTmpdir { 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); + GenerationState state = new GenerationState(jetCoreEnvironment.getProject(), ClassBuilderFactories.binaries(false)); AnalyzingUtils.checkForSyntacticErrors(psiFile); BindingContext bindingContext = state.compile(psiFile); diff --git a/compiler/tests/org/jetbrains/jet/compiler/WriteSignatureTest.java b/compiler/tests/org/jetbrains/jet/compiler/WriteSignatureTest.java index 26ca9910cf6..d943b1a9eec 100644 --- a/compiler/tests/org/jetbrains/jet/compiler/WriteSignatureTest.java +++ b/compiler/tests/org/jetbrains/jet/compiler/WriteSignatureTest.java @@ -29,6 +29,7 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.jet.JetTestCaseBuilder; import org.jetbrains.jet.JetTestUtils; +import org.jetbrains.jet.codegen.ClassBuilderFactories; import org.jetbrains.jet.codegen.ClassBuilderFactory; import org.jetbrains.jet.codegen.ClassFileFactory; import org.jetbrains.jet.codegen.GenerationState; @@ -83,7 +84,7 @@ public class WriteSignatureTest extends TestCaseWithTmpdir { 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); + GenerationState state = new GenerationState(jetCoreEnvironment.getProject(), ClassBuilderFactories.binaries(false)); AnalyzingUtils.checkForSyntacticErrors(psiFile); state.compile(psiFile); diff --git a/idea/src/org/jetbrains/jet/plugin/internal/codewindow/BytecodeToolwindow.java b/idea/src/org/jetbrains/jet/plugin/internal/codewindow/BytecodeToolwindow.java index 2c5fdaf5244..7995caf3c78 100644 --- a/idea/src/org/jetbrains/jet/plugin/internal/codewindow/BytecodeToolwindow.java +++ b/idea/src/org/jetbrains/jet/plugin/internal/codewindow/BytecodeToolwindow.java @@ -36,6 +36,7 @@ import com.intellij.openapi.vfs.VirtualFile; import com.intellij.psi.PsiFile; import com.intellij.psi.PsiManager; import com.intellij.util.Alarm; +import org.jetbrains.jet.codegen.ClassBuilderFactories; import org.jetbrains.jet.codegen.ClassBuilderFactory; import org.jetbrains.jet.codegen.ClassFileFactory; import org.jetbrains.jet.codegen.CompilationErrorHandler; @@ -200,7 +201,7 @@ public class BytecodeToolwindow extends JPanel implements Disposable { } protected String generateToText(JetFile file) { - GenerationState state = new GenerationState(myProject, ClassBuilderFactory.TEXT); + GenerationState state = new GenerationState(myProject, ClassBuilderFactories.TEXT); try { BindingContext binding = WholeProjectAnalyzerFacade.analyzeProjectWithCacheOnAFile(file); AnalyzingUtils.throwExceptionOnErrors(binding); diff --git a/jdk-headers/src/java/util/AbstractCollection.kt b/jdk-headers/src/java/util/AbstractCollection.kt index 8c84b380549..6b9b8100d3c 100644 --- a/jdk-headers/src/java/util/AbstractCollection.kt +++ b/jdk-headers/src/java/util/AbstractCollection.kt @@ -1,5 +1,5 @@ package java.util -abstract public open class AbstractCollection protected () : java.util.Collection { +abstract public open class AbstractCollection protected () : java.lang.Object(), java.util.Collection { abstract override public fun iterator() : java.util.Iterator abstract override public fun size() : Int override public fun isEmpty() : Boolean {} @@ -14,4 +14,4 @@ abstract public open class AbstractCollection protected () : java.util override public fun retainAll(c : java.util.Collection<*>) : Boolean {} override public fun clear() : Unit {} //override public fun toString() : java.lang.String {} -} \ No newline at end of file +} diff --git a/jdk-headers/src/java/util/AbstractMap.kt b/jdk-headers/src/java/util/AbstractMap.kt index 5ff3e33ce63..4bc7a494184 100644 --- a/jdk-headers/src/java/util/AbstractMap.kt +++ b/jdk-headers/src/java/util/AbstractMap.kt @@ -1,6 +1,6 @@ package java.util -abstract public open class AbstractMap protected () : java.util.Map { +abstract public open class AbstractMap protected () : java.lang.Object(), java.util.Map { override public fun size() : Int {} override public fun isEmpty() : Boolean {} override public fun containsValue(value : Any?) : Boolean {} @@ -16,4 +16,4 @@ abstract public open class AbstractMap protected () : java.u //override public fun equals(o : Any?) : Boolean //override public fun hashCode() : Int //override public fun toString() : java.lang.String? -} \ No newline at end of file +} diff --git a/jdk-headers/src/java/util/ArrayList.kt b/jdk-headers/src/java/util/ArrayList.kt index 5c4c1e8ddb4..288168f5142 100644 --- a/jdk-headers/src/java/util/ArrayList.kt +++ b/jdk-headers/src/java/util/ArrayList.kt @@ -34,4 +34,4 @@ public open class ArrayList(c : java.util.Collection) : java.ut // return __ // } // } -} \ No newline at end of file +}