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 extends CallableDescriptor> 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 extends CallableDescriptor> 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 extends FunctionDescriptor> 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 @@
+