add jump to def and type on hover for top level

This commit is contained in:
2024-12-07 12:23:47 -08:00
parent 45390066ae
commit 421f5ea208
14 changed files with 378 additions and 174 deletions

View File

@@ -5,20 +5,78 @@ import { useEffect, useRef, useState } from "preact/hooks";
import { h, render, VNode } from "preact";
import { ChangeEvent } from "preact/compat";
interface FC {
file: string;
line: number;
col: number;
}
interface TopEntry {
fc: FC;
name: String;
type: String;
}
interface TopData {
context: TopEntry[];
}
let topData: undefined | TopData;
// we need to fix the definition of word
monaco.languages.register({ id: "newt" });
monaco.languages.setMonarchTokensProvider("newt", newtTokens);
monaco.languages.setLanguageConfiguration("newt", newtConfig);
monaco.languages.registerDefinitionProvider("newt", {
provideDefinition(model, position, token) {
if (!topData) return;
// HACK - we don't know our filename which was generated from `module` decl, so
// assume the last context entry is in our file.
let last = topData.context[topData.context.length-1]
let file = last.fc.file
const info = model.getWordAtPosition(position);
if (!info) return;
let entry = topData.context.find((entry) => entry.name === info.word);
// we can't switch files at the moment
if (!entry || entry.fc.file !== file) return
let lineNumber = entry.fc.line + 1
let column = entry.fc.col + 1
let word = model.getWordAtPosition({lineNumber, column})
let range = new monaco.Range(lineNumber, column, lineNumber, column)
if (word) {
range = new monaco.Range(lineNumber, word.startColumn, lineNumber, word.endColumn)
}
return { uri: model.uri,range}
},
});
monaco.languages.registerHoverProvider("newt", {
provideHover(model, position, token, context) {
if (!topData) return;
const info = model.getWordAtPosition(position);
if (!info) return;
let entry = topData.context.find((entry) => entry.name === info.word);
if (!entry) return;
return {
range: new monaco.Range(
position.lineNumber,
info.startColumn,
position.lineNumber,
info.endColumn
),
contents: [{ value: `${entry.name} : ${entry.type}` }],
};
},
});
const newtWorker = new Worker("worker.js");
let postMessage = (msg: any) => newtWorker.postMessage(msg)
let postMessage = (msg: any) => newtWorker.postMessage(msg);
// Safari/MobileSafari have small stacks in webworkers.
if (navigator.vendor.includes('Apple')) {
if (navigator.vendor.includes("Apple")) {
const workerFrame = document.createElement("iframe");
workerFrame.src = "worker.html"
workerFrame.style.display = "none"
document.body.appendChild(workerFrame)
postMessage = (msg: any) => workerFrame.contentWindow?.postMessage(msg, '*')
workerFrame.src = "worker.html";
workerFrame.style.display = "none";
document.body.appendChild(workerFrame);
postMessage = (msg: any) => workerFrame.contentWindow?.postMessage(msg, "*");
}
// iframe for running newt output
@@ -28,8 +86,8 @@ iframe.style.display = "none";
document.body.appendChild(iframe);
function run(src: string) {
console.log('SEND TO', iframe.contentWindow)
postMessage({src})
console.log("SEND TO", iframe.contentWindow);
postMessage({ src });
}
function runOutput() {
@@ -42,21 +100,38 @@ function runOutput() {
}
}
function setOutput(output: string) {
let lines = output.split("\n");
output = lines.filter((l) => !l.startsWith("TOP:")).join("\n");
let data = lines.find((l) => l.startsWith("TOP:"));
if (data) {
try {
topData = JSON.parse(data.slice(4));
console.log({ topData });
} catch (e) {
console.error(e);
}
} else {
topData = undefined;
}
state.output.value = output;
}
window.onmessage = (ev) => {
console.log("window got", ev.data);
if (ev.data.messages) state.messages.value = ev.data.messages;
if (ev.data.message) {
state.messages.value = [...state.messages.value, ev.data.message]
state.messages.value = [...state.messages.value, ev.data.message];
}
// safari callback
if (ev.data.output !== undefined) {
state.output.value = ev.data.output;
setOutput(ev.data.output);
state.javascript.value = ev.data.javascript;
}
};
newtWorker.onmessage = (ev) => {
state.output.value = ev.data.output;
setOutput(ev.data.output);
state.javascript.value = ev.data.javascript;
};
@@ -310,9 +385,9 @@ const processOutput = (
let model = editor.getModel()!;
let markers: monaco.editor.IMarkerData[] = [];
let lines = output.split("\n");
let m = lines[0].match(/.*Process (.*)/)
let fn = ''
if (m) fn = m[1]
let m = lines[0].match(/.*Process (.*)/);
let fn = "";
if (m) fn = m[1];
for (let i = 0; i < lines.length; i++) {
const line = lines[i];
const match = line.match(/(INFO|ERROR) at (.*):\((\d+), (\d+)\):\s*(.*)/);
@@ -321,7 +396,7 @@ const processOutput = (
let lineNumber = +line + 1;
let column = +col + 1;
if (fn && file !== fn) {
lineNumber = column = 0
lineNumber = column = 0;
}
let start = { column, lineNumber };
// we don't have the full range, so grab the surrounding word
@@ -340,15 +415,15 @@ const processOutput = (
kind === "ERROR"
? monaco.MarkerSeverity.Error
: monaco.MarkerSeverity.Info;
if (kind === 'ERROR' || lineNumber)
markers.push({
severity,
message,
startLineNumber: lineNumber,
endLineNumber: lineNumber,
startColumn: column,
endColumn,
});
if (kind === "ERROR" || lineNumber)
markers.push({
severity,
message,
startLineNumber: lineNumber,
endLineNumber: lineNumber,
startColumn: column,
endColumn,
});
}
}
monaco.editor.setModelMarkers(model, "newt", markers);

View File

@@ -139,7 +139,7 @@ const handleMessage = async function (e) {
let m = src.match(/module (\w+)/)
if (m) module = m[1]
let fn = `${module}.newt`
process.argv = ["", "", fn, "-o", "out.js"];
process.argv = ["", "", fn, "-o", "out.js", "--top"];
console.log("args", process.argv);
files[fn] = src;
files['out.js'] = 'No JS output';