Added dianostic error for non-local return on disabled inlines,

Render bytecode diagnostics in BytecodeToolWindow

  #KT-5584 Fixed
This commit is contained in:
Michael Bogdanov
2015-05-20 15:04:59 +03:00
parent ef4981b0ef
commit 5bca1d3c8f
8 changed files with 71 additions and 2 deletions
@@ -46,6 +46,7 @@ import org.jetbrains.kotlin.codegen.when.SwitchCodegen;
import org.jetbrains.kotlin.codegen.when.SwitchCodegenUtil;
import org.jetbrains.kotlin.descriptors.*;
import org.jetbrains.kotlin.diagnostics.DiagnosticUtils;
import org.jetbrains.kotlin.diagnostics.Errors;
import org.jetbrains.kotlin.lexer.JetTokens;
import org.jetbrains.kotlin.load.java.JvmAbi;
import org.jetbrains.kotlin.load.java.descriptors.JavaClassDescriptor;
@@ -1828,7 +1829,10 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> implem
NonLocalReturnInfo nonLocalReturn = getNonLocalReturnInfo(descriptor, expression);
boolean isNonLocalReturn = nonLocalReturn != null;
if (isNonLocalReturn && !state.isInlineEnabled()) {
throw new CompilationException("Non local returns requires enabled inlining", null, expression);
state.getDiagnostics().report(Errors.NON_LOCAL_RETURN_IN_DISABLED_INLINE.on(expression));
genThrow(v, "java/lang/UnsupportedOperationException",
"Non-local returns are not allowed with inlining disabled");
return StackValue.none();
}
Type returnType = isNonLocalReturn ? nonLocalReturn.returnType : this.returnType;
@@ -21,6 +21,8 @@ import com.intellij.psi.PsiFile;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.kotlin.diagnostics.rendering.DefaultErrorMessages;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public interface DiagnosticSink {
@@ -29,6 +31,22 @@ public interface DiagnosticSink {
public void report(@NotNull Diagnostic diagnostic) {
}
};
class CollectAll implements DiagnosticSink {
List<Diagnostic> diagnostics = new ArrayList<Diagnostic>();
@Override
public void report(@NotNull Diagnostic diagnostic) {
diagnostics.add(diagnostic);
}
@NotNull
public List<Diagnostic> getDiagnostics() {
return Collections.unmodifiableList(diagnostics);
}
};
DiagnosticSink THROW_EXCEPTION = new DiagnosticSink() {
@Override
public void report(@NotNull Diagnostic diagnostic) {
@@ -613,6 +613,7 @@ public class DefaultErrorMessages {
//Inline non Locals
MAP.put(NON_LOCAL_RETURN_NOT_ALLOWED, "Can''t inline ''{0}'' here: it may contain non-local returns. Annotate parameter declaration ''{0}'' with ''inlineOptions(ONLY_LOCAL_RETURN)''", ELEMENT_TEXT, SHORT_NAMES_IN_TYPES, SHORT_NAMES_IN_TYPES);
MAP.put(INLINE_CALL_CYCLE, "The ''{0}'' invocation is a part of inline cycle", NAME);
MAP.put(NON_LOCAL_RETURN_IN_DISABLED_INLINE, "Non-local returns are not allowed with inlining disabled");
MAP.setImmutable();
@@ -0,0 +1,4 @@
$TESTDATA_DIR$/nonLocalDisabled.kt
-Xno-inline
-d
$TEMP_DIR$
@@ -0,0 +1,13 @@
fun a() {
c {
return
}
c {
return@a
}
}
inline fun c(p: () -> Unit) {
p()
}
@@ -0,0 +1,3 @@
ERROR: compiler/testData/cli/jvm/nonLocalDisabled.kt: (3, 9) Non-local returns are not allowed with inlining disabled
ERROR: compiler/testData/cli/jvm/nonLocalDisabled.kt: (7, 9) Non-local returns are not allowed with inlining disabled
COMPILATION_ERROR
@@ -109,6 +109,12 @@ public class KotlincExecutableTestGenerated extends AbstractKotlincExecutableTes
doJvmTest(fileName);
}
@TestMetadata("nonLocalDisabled.args")
public void testNonLocalDisabled() throws Exception {
String fileName = JetTestUtils.navigationMetadata("compiler/testData/cli/jvm/nonLocalDisabled.args");
doJvmTest(fileName);
}
@TestMetadata("pluginSimple.args")
public void testPluginSimple() throws Exception {
String fileName = JetTestUtils.navigationMetadata("compiler/testData/cli/jvm/pluginSimple.args");
@@ -43,7 +43,9 @@ import org.jetbrains.kotlin.codegen.KotlinCodegenFacade;
import org.jetbrains.kotlin.codegen.state.GenerationState;
import org.jetbrains.kotlin.codegen.state.Progress;
import org.jetbrains.kotlin.descriptors.ModuleDescriptor;
import org.jetbrains.kotlin.diagnostics.Diagnostic;
import org.jetbrains.kotlin.diagnostics.DiagnosticSink;
import org.jetbrains.kotlin.diagnostics.rendering.DefaultErrorMessages;
import org.jetbrains.kotlin.idea.caches.resolve.ResolutionFacade;
import org.jetbrains.kotlin.idea.caches.resolve.ResolvePackage;
import org.jetbrains.kotlin.idea.util.DebuggerUtils;
@@ -54,6 +56,7 @@ import org.jetbrains.kotlin.psi.JetClassOrObject;
import org.jetbrains.kotlin.psi.JetFile;
import org.jetbrains.kotlin.psi.JetScript;
import org.jetbrains.kotlin.resolve.BindingContext;
import org.jetbrains.kotlin.utils.UtilsPackage;
import javax.swing.*;
import java.awt.*;
@@ -197,6 +200,7 @@ public class KotlinBytecodeToolWindow extends JPanel implements Disposable {
boolean enableOptimization
) {
GenerationState state;
DiagnosticSink.CollectAll sink = new DiagnosticSink.CollectAll();
try {
ResolutionFacade resolutionFacade = ResolvePackage.getResolutionFacade(jetFile);
@@ -233,12 +237,13 @@ public class KotlinBytecodeToolWindow extends JPanel implements Disposable {
};
ModuleDescriptor moduleDescriptor = resolutionFacade.findModuleDescriptor(jetFile);
state = new GenerationState(jetFile.getProject(), ClassBuilderFactories.TEST, Progress.DEAF,
moduleDescriptor, bindingContext,
toProcess, !enableAssertions, !enableAssertions,
generateClassFilter,
!enableInline, !enableOptimization, null, null,
DiagnosticSink.DO_NOTHING, null);
sink, null);
KotlinCodegenFacade.compileCorrectFiles(state, CompilationErrorHandler.THROW_EXCEPTION);
}
catch (ProcessCanceledException e) {
@@ -250,6 +255,21 @@ public class KotlinBytecodeToolWindow extends JPanel implements Disposable {
StringBuilder answer = new StringBuilder();
List<Diagnostic> diagnostics = sink.getDiagnostics();
if (!diagnostics.isEmpty()) {
answer.append("// Backend Errors: \n");
answer.append("// ================\n");
for (Diagnostic diagnostic : diagnostics) {
answer.append("// Error at ")
.append(diagnostic.getPsiFile().getName())
.append(UtilsPackage.join(diagnostic.getTextRanges(), ","))
.append(": ")
.append(DefaultErrorMessages.render(diagnostic))
.append("\n");
}
answer.append("// ================\n\n");
}
OutputFileCollection outputFiles = state.getFactory();
for (OutputFile outputFile : outputFiles.asList()) {
answer.append("// ================");