Added dianostic error for non-local return on disabled inlines,
Render bytecode diagnostics in BytecodeToolWindow #KT-5584 Fixed
This commit is contained in:
@@ -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) {
|
||||
|
||||
+1
@@ -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("// ================");
|
||||
|
||||
Reference in New Issue
Block a user