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.codegen.when.SwitchCodegenUtil;
|
||||||
import org.jetbrains.kotlin.descriptors.*;
|
import org.jetbrains.kotlin.descriptors.*;
|
||||||
import org.jetbrains.kotlin.diagnostics.DiagnosticUtils;
|
import org.jetbrains.kotlin.diagnostics.DiagnosticUtils;
|
||||||
|
import org.jetbrains.kotlin.diagnostics.Errors;
|
||||||
import org.jetbrains.kotlin.lexer.JetTokens;
|
import org.jetbrains.kotlin.lexer.JetTokens;
|
||||||
import org.jetbrains.kotlin.load.java.JvmAbi;
|
import org.jetbrains.kotlin.load.java.JvmAbi;
|
||||||
import org.jetbrains.kotlin.load.java.descriptors.JavaClassDescriptor;
|
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);
|
NonLocalReturnInfo nonLocalReturn = getNonLocalReturnInfo(descriptor, expression);
|
||||||
boolean isNonLocalReturn = nonLocalReturn != null;
|
boolean isNonLocalReturn = nonLocalReturn != null;
|
||||||
if (isNonLocalReturn && !state.isInlineEnabled()) {
|
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;
|
Type returnType = isNonLocalReturn ? nonLocalReturn.returnType : this.returnType;
|
||||||
|
|||||||
@@ -21,6 +21,8 @@ import com.intellij.psi.PsiFile;
|
|||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.kotlin.diagnostics.rendering.DefaultErrorMessages;
|
import org.jetbrains.kotlin.diagnostics.rendering.DefaultErrorMessages;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
public interface DiagnosticSink {
|
public interface DiagnosticSink {
|
||||||
@@ -29,6 +31,22 @@ public interface DiagnosticSink {
|
|||||||
public void report(@NotNull Diagnostic diagnostic) {
|
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() {
|
DiagnosticSink THROW_EXCEPTION = new DiagnosticSink() {
|
||||||
@Override
|
@Override
|
||||||
public void report(@NotNull Diagnostic diagnostic) {
|
public void report(@NotNull Diagnostic diagnostic) {
|
||||||
|
|||||||
+1
@@ -613,6 +613,7 @@ public class DefaultErrorMessages {
|
|||||||
//Inline non Locals
|
//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(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(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();
|
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);
|
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")
|
@TestMetadata("pluginSimple.args")
|
||||||
public void testPluginSimple() throws Exception {
|
public void testPluginSimple() throws Exception {
|
||||||
String fileName = JetTestUtils.navigationMetadata("compiler/testData/cli/jvm/pluginSimple.args");
|
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.GenerationState;
|
||||||
import org.jetbrains.kotlin.codegen.state.Progress;
|
import org.jetbrains.kotlin.codegen.state.Progress;
|
||||||
import org.jetbrains.kotlin.descriptors.ModuleDescriptor;
|
import org.jetbrains.kotlin.descriptors.ModuleDescriptor;
|
||||||
|
import org.jetbrains.kotlin.diagnostics.Diagnostic;
|
||||||
import org.jetbrains.kotlin.diagnostics.DiagnosticSink;
|
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.ResolutionFacade;
|
||||||
import org.jetbrains.kotlin.idea.caches.resolve.ResolvePackage;
|
import org.jetbrains.kotlin.idea.caches.resolve.ResolvePackage;
|
||||||
import org.jetbrains.kotlin.idea.util.DebuggerUtils;
|
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.JetFile;
|
||||||
import org.jetbrains.kotlin.psi.JetScript;
|
import org.jetbrains.kotlin.psi.JetScript;
|
||||||
import org.jetbrains.kotlin.resolve.BindingContext;
|
import org.jetbrains.kotlin.resolve.BindingContext;
|
||||||
|
import org.jetbrains.kotlin.utils.UtilsPackage;
|
||||||
|
|
||||||
import javax.swing.*;
|
import javax.swing.*;
|
||||||
import java.awt.*;
|
import java.awt.*;
|
||||||
@@ -197,6 +200,7 @@ public class KotlinBytecodeToolWindow extends JPanel implements Disposable {
|
|||||||
boolean enableOptimization
|
boolean enableOptimization
|
||||||
) {
|
) {
|
||||||
GenerationState state;
|
GenerationState state;
|
||||||
|
DiagnosticSink.CollectAll sink = new DiagnosticSink.CollectAll();
|
||||||
try {
|
try {
|
||||||
ResolutionFacade resolutionFacade = ResolvePackage.getResolutionFacade(jetFile);
|
ResolutionFacade resolutionFacade = ResolvePackage.getResolutionFacade(jetFile);
|
||||||
|
|
||||||
@@ -233,12 +237,13 @@ public class KotlinBytecodeToolWindow extends JPanel implements Disposable {
|
|||||||
};
|
};
|
||||||
|
|
||||||
ModuleDescriptor moduleDescriptor = resolutionFacade.findModuleDescriptor(jetFile);
|
ModuleDescriptor moduleDescriptor = resolutionFacade.findModuleDescriptor(jetFile);
|
||||||
|
|
||||||
state = new GenerationState(jetFile.getProject(), ClassBuilderFactories.TEST, Progress.DEAF,
|
state = new GenerationState(jetFile.getProject(), ClassBuilderFactories.TEST, Progress.DEAF,
|
||||||
moduleDescriptor, bindingContext,
|
moduleDescriptor, bindingContext,
|
||||||
toProcess, !enableAssertions, !enableAssertions,
|
toProcess, !enableAssertions, !enableAssertions,
|
||||||
generateClassFilter,
|
generateClassFilter,
|
||||||
!enableInline, !enableOptimization, null, null,
|
!enableInline, !enableOptimization, null, null,
|
||||||
DiagnosticSink.DO_NOTHING, null);
|
sink, null);
|
||||||
KotlinCodegenFacade.compileCorrectFiles(state, CompilationErrorHandler.THROW_EXCEPTION);
|
KotlinCodegenFacade.compileCorrectFiles(state, CompilationErrorHandler.THROW_EXCEPTION);
|
||||||
}
|
}
|
||||||
catch (ProcessCanceledException e) {
|
catch (ProcessCanceledException e) {
|
||||||
@@ -250,6 +255,21 @@ public class KotlinBytecodeToolWindow extends JPanel implements Disposable {
|
|||||||
|
|
||||||
StringBuilder answer = new StringBuilder();
|
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();
|
OutputFileCollection outputFiles = state.getFactory();
|
||||||
for (OutputFile outputFile : outputFiles.asList()) {
|
for (OutputFile outputFile : outputFiles.asList()) {
|
||||||
answer.append("// ================");
|
answer.append("// ================");
|
||||||
|
|||||||
Reference in New Issue
Block a user