diff --git a/.idea/modules.xml b/.idea/modules.xml index 463eb8bb67fdeeb016398a9e075d2ef17f365995..9c559c5bba15a9ca94bcf14e9845978aa2cd5382 100644 --- a/.idea/modules.xml +++ b/.idea/modules.xml @@ -12,6 +12,7 @@ + diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/ClassBodyCodegen.java b/compiler/backend/src/org/jetbrains/jet/codegen/ClassBodyCodegen.java index 59d472f16d7688ed8fb18f42fc46851ac7e8e1a4..83d535a52a15ea0f30df769278f8ea8222a5b338 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/ClassBodyCodegen.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/ClassBodyCodegen.java @@ -126,9 +126,7 @@ public abstract class ClassBodyCodegen { } mv.visitInsn(Opcodes.RETURN); - mv.visitMaxs(0, 0); - - mv.visitEnd(); + FunctionCodegen.endVisit(v, "static initializer", myClass); } } } diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/ClosureCodegen.java b/compiler/backend/src/org/jetbrains/jet/codegen/ClosureCodegen.java index feced45f382c7924602a99c8f85d2807c238590b..38e58aa2846f7a36c0877dcb855aaa453012dd80 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/ClosureCodegen.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/ClosureCodegen.java @@ -147,8 +147,7 @@ public class ClosureCodegen extends ObjectOrClosureCodegen { mv.visitLabel(ret); mv.visitInsn(ARETURN); - mv.visitMaxs(0,0); - mv.visitEnd(); + FunctionCodegen.endVisit(mv, "$getInstance", fun); } } @@ -205,8 +204,7 @@ public class ClosureCodegen extends ObjectOrClosureCodegen { iv.areturn(JetTypeMapper.TYPE_OBJECT); - mv.visitMaxs(0, 0); - mv.visitEnd(); + FunctionCodegen.endVisit(mv, "bridge", fun); } } @@ -286,8 +284,7 @@ public class ClosureCodegen extends ObjectOrClosureCodegen { iv.visitInsn(RETURN); - mv.visitMaxs(0, 0); - mv.visitEnd(); + FunctionCodegen.endVisit(iv, "constructor", fun); } return constructor; } diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/CompilationException.java b/compiler/backend/src/org/jetbrains/jet/codegen/CompilationException.java new file mode 100644 index 0000000000000000000000000000000000000000..84f336f74a59b401e548a8d3b86b47106baa6b35 --- /dev/null +++ b/compiler/backend/src/org/jetbrains/jet/codegen/CompilationException.java @@ -0,0 +1,20 @@ +package org.jetbrains.jet.codegen; + +import com.intellij.psi.PsiElement; +import org.jetbrains.jet.lang.psi.JetElement; + +/** +* @author alex.tkachman +*/ +public class CompilationException extends RuntimeException { + private PsiElement element; + + CompilationException(String message, Throwable cause, PsiElement element) { + super(message, cause); + this.element = element; + } + + public PsiElement getElement() { + return element; + } +} diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/ExpressionCodegen.java b/compiler/backend/src/org/jetbrains/jet/codegen/ExpressionCodegen.java index da8894292f2b2be0065ace3adfe2de689edc3e91..4885242db447932b94e34bbe9d926ddf8cbb698c 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/ExpressionCodegen.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/ExpressionCodegen.java @@ -130,7 +130,15 @@ public class ExpressionCodegen extends JetVisitor { public StackValue genQualified(StackValue receiver, JetElement selector) { markLineNumber(selector); - return selector.accept(this, receiver); + try { + return selector.accept(this, receiver); + } + catch(CompilationException e) { + throw e; + } + catch (Throwable error) { + throw new CompilationException(error.getMessage(), error, selector); + } } public StackValue gen(JetElement expr) { @@ -204,7 +212,7 @@ public class ExpressionCodegen extends JetVisitor { JetExpression elseExpression = expression.getElse(); if (thenExpression == null && elseExpression == null) { - throw new CompilationException(); + throw new CompilationException("Both brunches of if/else are null", null, expression); } if (isEmptyExpression(thenExpression)) { @@ -1126,7 +1134,7 @@ public class ExpressionCodegen extends JetVisitor { ResolvedCall resolvedCall = bindingContext.get(BindingContext.RESOLVED_CALL, callee); if(resolvedCall == null) { - throw new CompilationException("Cannot resolve: " + callee.getText()); + throw new CompilationException("Cannot resolve: " + callee.getText(), null, expression); } receiver = StackValue.receiver(resolvedCall, receiver, this, null); @@ -2074,7 +2082,7 @@ public class ExpressionCodegen extends JetVisitor { ResolvedCall resolvedCall = bindingContext.get(BindingContext.RESOLVED_CALL, callee); if(resolvedCall == null) { assert callee != null; - throw new CompilationException("Cannot resolve: " + callee.getText()); + throw new CompilationException("Cannot resolve: " + callee.getText(), null, expression); } FunctionDescriptor descriptor = (FunctionDescriptor) resolvedCall.getResultingDescriptor(); @@ -2098,7 +2106,7 @@ public class ExpressionCodegen extends JetVisitor { } else { if (args.size() != 1) { - throw new CompilationException("primitive array constructor requires one argument"); + throw new CompilationException("primitive array constructor requires one argument", null, expression); } } @@ -2784,15 +2792,6 @@ If finally block is present, its last expression is the value of try expression. v.athrow(); } - private static class CompilationException extends RuntimeException { - private CompilationException() { - } - - private CompilationException(String message) { - super(message); - } - } - @Override public String toString() { return context.getContextDescriptor().toString(); diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/FunctionCodegen.java b/compiler/backend/src/org/jetbrains/jet/codegen/FunctionCodegen.java index befdaf21a7e30471899c9a59daaa4ad5f2dd4611..85eab7d6335a8f2d92b02ae298571d3c34f3ccf3 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/FunctionCodegen.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/FunctionCodegen.java @@ -223,7 +223,7 @@ public class FunctionCodegen { k += type.getSize(); } - mv.visitMaxs(0, 0); + endVisit(mv, null, fun); mv.visitEnd(); generateBridgeIfNeeded(owner, state, v, jvmSignature.getAsmMethod(), functionDescriptor, kind); @@ -233,6 +233,16 @@ public class FunctionCodegen { generateDefaultIfNeeded(context, state, v, jvmSignature.getAsmMethod(), functionDescriptor, kind); } + public static void endVisit(MethodVisitor mv, String description, PsiElement method) { + try { + mv.visitMaxs(0, 0); + } + catch (Throwable t) { + throw new CompilationException("wrong code generated" + (description != null ? " for " + description : "") + t.getClass().getName() + " " + t.getMessage(), t, method); + } + mv.visitEnd(); + } + static void generateBridgeIfNeeded(CodegenContext owner, GenerationState state, ClassBuilder v, Method jvmSignature, FunctionDescriptor functionDescriptor, OwnerKind kind) { Set overriddenFunctions = functionDescriptor.getOverriddenDescriptors(); if(kind != OwnerKind.TRAIT_IMPL) { @@ -390,7 +400,7 @@ public class FunctionCodegen { iv.areturn(jvmSignature.getReturnType()); - mv.visitMaxs(0, 0); + endVisit(mv, "default method", state.getBindingContext().get(BindingContext.DESCRIPTOR_TO_DECLARATION, functionDescriptor)); mv.visitEnd(); } } @@ -426,7 +436,7 @@ public class FunctionCodegen { if(jvmSignature.getReturnType() == Type.VOID_TYPE) iv.aconst(null); iv.areturn(overriden.getReturnType()); - mv.visitMaxs(0, 0); + endVisit(mv, "bridge method", state.getBindingContext().get(BindingContext.DESCRIPTOR_TO_DECLARATION, functionDescriptor)); mv.visitEnd(); } } diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/ImplementationBodyCodegen.java b/compiler/backend/src/org/jetbrains/jet/codegen/ImplementationBodyCodegen.java index 77c65e1c4d4bd46bdf99681f3df8b84987c75529..852b12ac22ed8211545d106010aed1252c1b53bc 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/ImplementationBodyCodegen.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/ImplementationBodyCodegen.java @@ -198,8 +198,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen { iv.invokespecial(typeMapper.getOwner(original, OwnerKind.IMPLEMENTATION), originalMethod.getName(), originalMethod.getDescriptor()); iv.areturn(method.getReturnType()); - mv.visitMaxs(0,0); - mv.visitEnd(); + FunctionCodegen.endVisit(iv, "accessor", null); } } else if(entry.getValue() instanceof PropertyDescriptor) { @@ -222,8 +221,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen { iv.invokespecial(typeMapper.getOwner(original, OwnerKind.IMPLEMENTATION), originalMethod.getName(), originalMethod.getDescriptor()); iv.areturn(method.getReturnType()); - mv.visitMaxs(0,0); - mv.visitEnd(); + FunctionCodegen.endVisit(iv, "accessor", null); } method = typeMapper.mapSetterSignature(bridge, OwnerKind.IMPLEMENTATION).getAsmMethod(); @@ -248,8 +246,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen { iv.invokespecial(typeMapper.getOwner(original, OwnerKind.IMPLEMENTATION), originalMethod.getName(), originalMethod.getDescriptor()); iv.areturn(method.getReturnType()); - mv.visitMaxs(0,0); - mv.visitEnd(); + FunctionCodegen.endVisit(iv, "accessor", null); } } else { @@ -465,8 +462,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen { outer.visitVarInsn(Opcodes.ALOAD, 0); outer.visitFieldInsn(Opcodes.GETFIELD, classname, "this$0", outerType.getDescriptor()); outer.visitInsn(Opcodes.ARETURN); - outer.visitMaxs(0, 0); - outer.visitEnd(); + FunctionCodegen.endVisit(outer, "getOuterObject", myClass); } if (CodegenUtil.requireTypeInfoConstructorArg(descriptor.getDefaultType()) && kind == OwnerKind.IMPLEMENTATION) { @@ -518,8 +514,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen { generateTraitMethods(codegen); mv.visitInsn(Opcodes.RETURN); - mv.visitMaxs(0, 0); - mv.visitEnd(); + FunctionCodegen.endVisit(mv, "constructor", myClass); FunctionCodegen.generateDefaultIfNeeded(constructorContext, state, v, constructorMethod, constructorDescriptor, OwnerKind.IMPLEMENTATION); } @@ -572,8 +567,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen { iv.checkcast(function.getReturnType()); } iv.areturn(function.getReturnType()); - mv.visitMaxs(0, 0); - mv.visitEnd(); + FunctionCodegen.endVisit(iv, "trait method", bindingContext.get(BindingContext.DESCRIPTOR_TO_DECLARATION, fun)); } FunctionCodegen.generateBridgeIfNeeded(context, state, v, function, fun, kind); @@ -708,8 +702,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen { } mv.visitInsn(Opcodes.RETURN); - mv.visitMaxs(0, 0); - mv.visitEnd(); + FunctionCodegen.endVisit(mv, "constructor", null); } } @@ -821,8 +814,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen { iv.load(0, JetTypeMapper.TYPE_OBJECT); iv.getfield(owner, "$typeInfo", "Ljet/typeinfo/TypeInfo;"); iv.areturn(JetTypeMapper.TYPE_TYPEINFO); - mv.visitMaxs(0, 0); - mv.visitEnd(); + FunctionCodegen.endVisit(iv, "getTypeInfo", myClass); } mv = v.newMethod(myClass, Opcodes.ACC_PROTECTED | Opcodes.ACC_FINAL, "$setTypeInfo", "(Ljet/typeinfo/TypeInfo;)V", null, null); @@ -834,8 +826,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen { iv.load(1, JetTypeMapper.TYPE_OBJECT); iv.putfield(owner, "$typeInfo", "Ljet/typeinfo/TypeInfo;"); mv.visitInsn(Opcodes.RETURN); - mv.visitMaxs(0, 0); - mv.visitEnd(); + FunctionCodegen.endVisit(iv, "$setTypeInfo", myClass); } } } @@ -853,8 +844,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen { String owner = typeMapper.mapType(descriptor.getDefaultType(), OwnerKind.IMPLEMENTATION).getInternalName(); v.getstatic(owner, "$staticTypeInfo", "Ljet/typeinfo/TypeInfo;"); v.areturn(JetTypeMapper.TYPE_TYPEINFO); - mv.visitMaxs(0, 0); - mv.visitEnd(); + FunctionCodegen.endVisit(v, "getTypeInfo", myClass); } } diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/NamespaceCodegen.java b/compiler/backend/src/org/jetbrains/jet/codegen/NamespaceCodegen.java index 5e8b92a7849ea514d326f75663042f7faa51cc55..78a768791e18ac53ca80bcd2acfff8afde595d35 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/NamespaceCodegen.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/NamespaceCodegen.java @@ -62,8 +62,11 @@ public class NamespaceCodegen { else if (declaration instanceof JetNamedFunction) { try { functionCodegen.gen((JetNamedFunction) declaration); - } catch (Exception e) { - throw new RuntimeException("Failed to generate function " + declaration.getName(), e); + } catch (CompilationException e) { + throw e; + } + catch (Exception e) { + throw new CompilationException("Failed to generate function " + declaration.getName(), e, declaration); } } else if (declaration instanceof JetClassOrObject) { @@ -107,7 +110,7 @@ public class NamespaceCodegen { } mv.visitInsn(RETURN); - mv.visitMaxs(0, 0); + FunctionCodegen.endVisit(mv, "static initializer for namespace", namespace); mv.visitEnd(); } } @@ -134,8 +137,7 @@ public class NamespaceCodegen { v.visitFieldInsn(PUTSTATIC, jvmClassName, fieldName, "Ljet/typeinfo/TypeInfo;"); v.visitLabel(end); v.visitInsn(ARETURN); - v.visitMaxs(0, 0); - v.visitEnd(); + FunctionCodegen.endVisit(v, "type info method", namespace); } } } diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/PropertyCodegen.java b/compiler/backend/src/org/jetbrains/jet/codegen/PropertyCodegen.java index dc05e02b32d22432de42ab067c2f6560982b45f8..2267922aeb70c6be454acaf2e35b3fd26d72e393 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/PropertyCodegen.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/PropertyCodegen.java @@ -154,8 +154,7 @@ public class PropertyCodegen { type.getDescriptor()); } iv.areturn(type); - mv.visitMaxs(0, 0); - mv.visitEnd(); + FunctionCodegen.endVisit(mv, "getter", origin); } } @@ -207,7 +206,7 @@ public class PropertyCodegen { } iv.visitInsn(Opcodes.RETURN); - mv.visitMaxs(0, 0); + FunctionCodegen.endVisit(mv, "setter", origin); mv.visitEnd(); } } diff --git a/idea/src/org/jetbrains/jet/plugin/compiler/JetCompiler.java b/idea/src/org/jetbrains/jet/plugin/compiler/JetCompiler.java index 21dea6ed51707cf9b883584ded2c862b84fa22f7..766868d3fc831afd2ced686c11e95f4346b6cb91 100644 --- a/idea/src/org/jetbrains/jet/plugin/compiler/JetCompiler.java +++ b/idea/src/org/jetbrains/jet/plugin/compiler/JetCompiler.java @@ -16,10 +16,7 @@ import com.intellij.psi.PsiFile; import com.intellij.psi.PsiManager; import com.intellij.util.Chunk; import org.jetbrains.annotations.NotNull; -import org.jetbrains.jet.codegen.ClassBuilderFactory; -import org.jetbrains.jet.codegen.ClassFileFactory; -import org.jetbrains.jet.codegen.CompilationErrorHandler; -import org.jetbrains.jet.codegen.GenerationState; +import org.jetbrains.jet.codegen.*; import org.jetbrains.jet.lang.cfg.pseudocode.JetControlFlowDataTraceFactory; import org.jetbrains.jet.lang.diagnostics.Diagnostic; import org.jetbrains.jet.lang.psi.JetFile; @@ -102,7 +99,12 @@ public class JetCompiler implements TranslatingCompiler { generationState.compileCorrectNamespaces(bindingContext, namespaces, new CompilationErrorHandler() { @Override public void reportException(Throwable exception, String fileUrl) { - compileContext.addMessage(CompilerMessageCategory.WARNING, exception.getClass().getCanonicalName() + ": " + exception.getMessage(), fileUrl, 0, 0); + if(exception instanceof CompilationException) { + report((CompilationException) exception, compileContext); + } + else { + compileContext.addMessage(CompilerMessageCategory.ERROR, exception.getClass().getCanonicalName() + ": " + exception.getMessage(), fileUrl, 0, 0); + } } }); /////////// @@ -175,6 +177,29 @@ public class JetCompiler implements TranslatingCompiler { } } + private void report(CompilationException diagnostic, CompileContext compileContext) { + PsiFile psiFile = diagnostic.getElement().getContainingFile(); + TextRange textRange = diagnostic.getElement().getTextRange(); + Document document = psiFile.getViewProvider().getDocument(); + int line; + int col; + if (document != null) { + line = document.getLineNumber(textRange.getStartOffset()); + col = textRange.getStartOffset() - document.getLineStartOffset(line) + 1; + } + else { + line = -1; + col = -1; + } + VirtualFile virtualFile = psiFile.getVirtualFile(); + if (virtualFile == null) { + compileContext.addMessage(ERROR, "[Internal Error] No virtual file for PsiFile. Diagnostic: " + diagnostic.getMessage(), "", -1, -1); + } + else { + compileContext.addMessage(ERROR, diagnostic.getMessage(), virtualFile.getUrl(), line + 1, col); + } + } + // private static class ModuleCompileState { // private final GenerationState state; // private final CompileContext compileContext; diff --git a/testlib/testlib.iml b/testlib/testlib.iml index 408dd5e34f82bb9ae40a2963ff3a8454383b526f..d1780f417e7fc7b842fc54cb35a2fbfce5a24299 100644 --- a/testlib/testlib.iml +++ b/testlib/testlib.iml @@ -8,7 +8,6 @@ - @@ -18,6 +17,7 @@ +