mirror of
https://github.com/enso-org/enso.git
synced 2024-12-23 07:51:56 +03:00
Reverse order of stack frames and test the result (#9954)
Fixes #9934 by reversing the order of `dropInitJava` frames.
This commit is contained in:
parent
c437721ba5
commit
a53b2f0b18
@ -3,8 +3,6 @@ import * as fs from 'node:fs/promises'
|
||||
import * as path from 'node:path'
|
||||
import * as url from 'node:url'
|
||||
|
||||
import BUILD_INFO from '../../../../../build.json' assert { type: 'json' }
|
||||
|
||||
// ===============================
|
||||
// === readEnvironmentFromFile ===
|
||||
// ===============================
|
||||
@ -50,10 +48,17 @@ export async function readEnvironmentFromFile() {
|
||||
if (!isProduction || entries.length > 0) {
|
||||
Object.assign(process.env, variables)
|
||||
}
|
||||
const buildInfo = await (async () => {
|
||||
try {
|
||||
return await import('../../../../../build.json', { type: 'json' })
|
||||
} catch {
|
||||
return { commit: '', version: '', engineVersion: '', name: '' }
|
||||
}
|
||||
})()
|
||||
// @ts-expect-error This is the only file where `process.env` should be written to.
|
||||
process.env.ENSO_CLOUD_DASHBOARD_VERSION ??= BUILD_INFO.version
|
||||
process.env.ENSO_CLOUD_DASHBOARD_VERSION ??= buildInfo.version
|
||||
// @ts-expect-error This is the only file where `process.env` should be written to.
|
||||
process.env.ENSO_CLOUD_DASHBOARD_COMMIT_HASH ??= BUILD_INFO.commit
|
||||
process.env.ENSO_CLOUD_DASHBOARD_COMMIT_HASH ??= buildInfo.commit
|
||||
} catch (error) {
|
||||
if (missingKeys.length !== 0) {
|
||||
console.warn('Could not load `.env` file; disabling cloud backend.')
|
||||
|
@ -11,9 +11,9 @@ import java.nio.file.Paths;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedList;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
import org.apache.commons.cli.CommandLine;
|
||||
@ -43,6 +43,7 @@ import org.enso.profiling.sampler.OutputStreamSampler;
|
||||
import org.enso.version.VersionDescription;
|
||||
import org.graalvm.polyglot.PolyglotException;
|
||||
import org.graalvm.polyglot.PolyglotException.StackFrame;
|
||||
import org.graalvm.polyglot.SourceSection;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.slf4j.event.Level;
|
||||
import scala.concurrent.ExecutionContext;
|
||||
@ -1231,69 +1232,22 @@ public final class Main {
|
||||
scala.Option.apply(profilingPath), scala.Option.apply(profilingTime));
|
||||
}
|
||||
|
||||
private void printFrame(StackFrame frame, File relativeTo) {
|
||||
var langId = frame.isHostFrame() ? "java" : frame.getLanguage().getId();
|
||||
|
||||
String fmtFrame;
|
||||
if (LanguageInfo.ID.equals(langId)) {
|
||||
var fName = frame.getRootName();
|
||||
|
||||
var src = "Internal";
|
||||
var sourceLoc = frame.getSourceLocation();
|
||||
if (sourceLoc != null) {
|
||||
var path = sourceLoc.getSource().getPath();
|
||||
var ident = sourceLoc.getSource().getName();
|
||||
if (path != null) {
|
||||
if (relativeTo != null) {
|
||||
var absRoot = relativeTo.getAbsoluteFile();
|
||||
if (path.startsWith(absRoot.getAbsolutePath())) {
|
||||
var rootDir = absRoot.isDirectory() ? absRoot : absRoot.getParentFile();
|
||||
ident = rootDir.toPath().relativize(new File(path).toPath()).toString();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var loc = sourceLoc.getStartLine() + "-" + sourceLoc.getEndLine();
|
||||
var line = sourceLoc.getStartLine();
|
||||
if (line == sourceLoc.getEndLine()) {
|
||||
var start = sourceLoc.getStartColumn();
|
||||
var end = sourceLoc.getEndColumn();
|
||||
loc = line + ":" + start + "-" + end;
|
||||
}
|
||||
src = ident + ":" + loc;
|
||||
}
|
||||
fmtFrame = fName + "(" + src + ")";
|
||||
} else {
|
||||
fmtFrame = frame.toString();
|
||||
}
|
||||
println(" at <" + langId + "> " + fmtFrame);
|
||||
}
|
||||
|
||||
private void printPolyglotException(PolyglotException exception, File relativeTo) {
|
||||
var fullStackReversed = new LinkedList<StackFrame>();
|
||||
for (var e : exception.getPolyglotStackTrace()) {
|
||||
fullStackReversed.addFirst(e);
|
||||
}
|
||||
|
||||
var dropInitJava =
|
||||
fullStackReversed.stream()
|
||||
.dropWhile(f -> !LanguageInfo.ID.equals(f.getLanguage().getId()))
|
||||
.toList();
|
||||
Collections.reverse(fullStackReversed);
|
||||
var msg = HostEnsoUtils.findExceptionMessage(exception);
|
||||
println("Execution finished with an error: " + msg);
|
||||
Function<StackFrame, String> fnLangId =
|
||||
(frame) -> frame.isHostFrame() ? "java" : frame.getLanguage().getId();
|
||||
Function<StackFrame, String> fnRootName = StackFrame::getRootName;
|
||||
Function<StackFrame, SourceSection> fnSourceSection = StackFrame::getSourceLocation;
|
||||
|
||||
if (exception.isSyntaxError()) {
|
||||
// no stack
|
||||
} else if (dropInitJava.isEmpty()) {
|
||||
for (var f : exception.getPolyglotStackTrace()) {
|
||||
printFrame(f, relativeTo);
|
||||
}
|
||||
} else {
|
||||
for (var f : dropInitJava) {
|
||||
printFrame(f, relativeTo);
|
||||
}
|
||||
}
|
||||
Utils.printStackTrace(
|
||||
exception.getPolyglotStackTrace(),
|
||||
exception.isSyntaxError(),
|
||||
msg,
|
||||
relativeTo,
|
||||
this::println,
|
||||
fnLangId,
|
||||
fnRootName,
|
||||
fnSourceSection);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
|
@ -2,6 +2,13 @@ package org.enso.runner;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.LinkedList;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Function;
|
||||
import org.enso.common.LanguageInfo;
|
||||
import org.graalvm.polyglot.SourceSection;
|
||||
import scala.Tuple3;
|
||||
|
||||
final class Utils {
|
||||
@ -66,4 +73,86 @@ final class Utils {
|
||||
}
|
||||
return Tuple3.apply(projectMode, canonicalFile, projectRoot);
|
||||
}
|
||||
|
||||
static <S> void printStackTrace(
|
||||
Iterable<S> stack,
|
||||
boolean syntaxError,
|
||||
String msg,
|
||||
File relativeTo,
|
||||
Consumer<String> print,
|
||||
Function<S, String> fnLangId,
|
||||
Function<S, String> fnRootName,
|
||||
Function<S, SourceSection> fnSourceSection) {
|
||||
|
||||
var fullStackReversed = new LinkedList<S>();
|
||||
for (var e : stack) {
|
||||
fullStackReversed.addFirst(e);
|
||||
}
|
||||
|
||||
var dropInitJava =
|
||||
new ArrayList<S>(
|
||||
fullStackReversed.stream()
|
||||
.dropWhile(f -> !LanguageInfo.ID.equals(fnLangId.apply(f)))
|
||||
.toList());
|
||||
Collections.reverse(dropInitJava);
|
||||
print.accept("Execution finished with an error: " + msg);
|
||||
|
||||
Iterable<S> toPrint;
|
||||
if (syntaxError) {
|
||||
toPrint = null;
|
||||
} else if (dropInitJava.isEmpty()) {
|
||||
toPrint = stack;
|
||||
} else {
|
||||
toPrint = dropInitJava;
|
||||
}
|
||||
if (toPrint != null) {
|
||||
for (var f : toPrint) {
|
||||
printFrame(f, relativeTo, print, fnLangId, fnRootName, fnSourceSection);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static <S> void printFrame(
|
||||
S frame,
|
||||
File relativeTo,
|
||||
Consumer<String> print,
|
||||
Function<S, String> fnLangId,
|
||||
Function<S, String> fnRootName,
|
||||
Function<S, SourceSection> fnSourceSection) {
|
||||
var langId = fnLangId.apply(frame);
|
||||
|
||||
String fmtFrame;
|
||||
if (LanguageInfo.ID.equals(langId)) {
|
||||
var fName = fnRootName.apply(frame);
|
||||
|
||||
var src = "Internal";
|
||||
var sourceLoc = fnSourceSection.apply(frame);
|
||||
if (sourceLoc != null) {
|
||||
var path = sourceLoc.getSource().getPath();
|
||||
var ident = sourceLoc.getSource().getName();
|
||||
if (path != null) {
|
||||
if (relativeTo != null) {
|
||||
var absRoot = relativeTo.getAbsoluteFile();
|
||||
if (path.startsWith(absRoot.getAbsolutePath())) {
|
||||
var rootDir = absRoot.isDirectory() ? absRoot : absRoot.getParentFile();
|
||||
ident = rootDir.toPath().relativize(new File(path).toPath()).toString();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var loc = sourceLoc.getStartLine() + "-" + sourceLoc.getEndLine();
|
||||
var line = sourceLoc.getStartLine();
|
||||
if (line == sourceLoc.getEndLine()) {
|
||||
var start = sourceLoc.getStartColumn();
|
||||
var end = sourceLoc.getEndColumn();
|
||||
loc = line + ":" + start + "-" + end;
|
||||
}
|
||||
src = ident + ":" + loc;
|
||||
}
|
||||
fmtFrame = fName + "(" + src + ")";
|
||||
} else {
|
||||
fmtFrame = frame.toString();
|
||||
}
|
||||
print.accept(" at <" + langId + "> " + fmtFrame);
|
||||
}
|
||||
}
|
||||
|
@ -7,6 +7,10 @@ import static org.junit.Assert.assertTrue;
|
||||
|
||||
import java.io.File;
|
||||
import java.nio.file.Files;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
import org.graalvm.polyglot.SourceSection;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.rules.TemporaryFolder;
|
||||
@ -16,6 +20,48 @@ public class UtilsTest {
|
||||
|
||||
public UtilsTest() {}
|
||||
|
||||
@Test
|
||||
public void printStackTrace1() throws Exception {
|
||||
var f = folder.newFile("p.enso");
|
||||
var code =
|
||||
"""
|
||||
from Standard.Base import all
|
||||
|
||||
a = b
|
||||
b = c
|
||||
c = Panic.throw "foo"
|
||||
|
||||
main = a
|
||||
""";
|
||||
Files.writeString(f.toPath(), code);
|
||||
|
||||
var lines = new ArrayList<String>();
|
||||
|
||||
var stack =
|
||||
List.of(
|
||||
new MockFrame("enso", "Panic", "throw", "Internal", -1, -1, -1),
|
||||
new MockFrame("enso", "p", "c", "p.enso", 5, 5, 21),
|
||||
new MockFrame("enso", "m", "main", "p.enso", 20, 4, 8));
|
||||
|
||||
Utils.printStackTrace(
|
||||
stack,
|
||||
false,
|
||||
"foo",
|
||||
new File("/"),
|
||||
lines::add,
|
||||
MockFrame::lang,
|
||||
MockFrame::method,
|
||||
MockFrame::section);
|
||||
|
||||
assertEquals(
|
||||
"""
|
||||
Execution finished with an error: foo
|
||||
at <enso> throw(Internal)
|
||||
at <enso> c(Internal)
|
||||
at <enso> main(Internal)""",
|
||||
lines.stream().collect(Collectors.joining("\n")));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void detectParentProject() throws Exception {
|
||||
var dir = folder.newFolder("dir", "prj", "src", "some", "file").getCanonicalFile();
|
||||
@ -100,4 +146,17 @@ public class UtilsTest {
|
||||
assertEquals("Source detected", src, found._2());
|
||||
assertEquals("No project folder detected without src dir", "", found._3());
|
||||
}
|
||||
|
||||
private static record MockFrame(
|
||||
String lang,
|
||||
String type,
|
||||
String method,
|
||||
String src,
|
||||
int line,
|
||||
int startColumn,
|
||||
int endColumn) {
|
||||
SourceSection section() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user