mirror of
https://github.com/sehugg/8bitworkshop.git
synced 2026-10-24 08:02:27 +00:00
ui: yellow for warnings
This commit is contained in:
1 parent
09d99f2c30
commit
3ac80cfe99
5 files changed
+35
-14
No files matched your search
+1
-1
@@ -14,7 +14,7 @@ See [extension/CHANGELOG.md](extension/CHANGELOG.md).
|
||||
- Reset clears the call graph; breakpoints are re-armed after a build.
|
||||
- Click the hex offset in the gutter to run to that line.
|
||||
- Probe Log no longer shows a blank line for every clock tick with no event; only recorded events get a line, so instructions and their bus accesses stay together.
|
||||
- Compiler warnings no longer fail a build or get lost. cc65/ca65/ld65 and SDCC warnings show as gutter markers in the IDE (not in the error dialog), as warnings in the VS Code Problems panel, and on stderr from `8bws` (`--no-warnings` hides them).
|
||||
- Compiler warnings no longer fail a build or get lost. cc65/ca65/ld65 and SDCC warnings show as yellow gutter markers and yellow squiggles on the source line in the IDE (not in the error dialog), as warnings in the VS Code Problems panel, and on stderr from `8bws` (`--no-warnings` hides them).
|
||||
- Emulators now run on a timeline (CLI and extension only for now): step back, seek, reverse run, `rbreak`, and deterministic replay with a replay-verification test that found determinism bugs in several platforms.
|
||||
|
||||
### `8bws` CLI
|
||||
|
||||
@@ -524,7 +524,7 @@ export class SourceEditor implements ProjectView {
|
||||
this.clearErrors();
|
||||
errors = errors.slice(0, MAX_ERRORS);
|
||||
const newErrors = new Map<number, ErrorInfo>();
|
||||
const spans: { line: number, start: number, end: number }[] = [];
|
||||
const spans: { line: number, start: number, end: number, warning?: boolean }[] = [];
|
||||
for (var info of errors) {
|
||||
// only mark errors with this filename, or without any filename
|
||||
if (!info.path || this.path.endsWith(info.path)) {
|
||||
@@ -537,7 +537,7 @@ export class SourceEditor implements ProjectView {
|
||||
}
|
||||
// collect column-level spans
|
||||
if (info.start != null && info.end != null && info.end > info.start) {
|
||||
spans.push({ line, start: info.start, end: info.end });
|
||||
spans.push({ line, start: info.start, end: info.end, warning: info.severity === 'warning' });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,7 +17,7 @@ const setErrors = StateEffect.define<Map<number, ErrorInfo>>();
|
||||
const setCurrentPc = StateEffect.define<number | null>();
|
||||
const runToLineEffect = StateEffect.define<number>();
|
||||
|
||||
const showErrorMessage = StateEffect.define<{ line: number, msg: string, toggle?: boolean } | null>();
|
||||
const showErrorMessage = StateEffect.define<{ line: number, msg: string, warning?: boolean, toggle?: boolean } | null>();
|
||||
|
||||
const offsetField = StateField.define<RangeSet<GutterMarker>>({
|
||||
create() { return RangeSet.empty; },
|
||||
@@ -273,13 +273,15 @@ const statusGutter = gutter({
|
||||
if (errorMarkers.size > 0) {
|
||||
const pos = line.from;
|
||||
let msg = "";
|
||||
let warning = false;
|
||||
errorMarkers.between(pos, pos, (from, to, marker: ErrorMarker) => {
|
||||
msg = marker.msg;
|
||||
warning = marker.warning === true;
|
||||
});
|
||||
if (msg) {
|
||||
const lineNum = view.state.doc.lineAt(line.from).number;
|
||||
view.dispatch({
|
||||
effects: showErrorMessage.of({ line: lineNum, msg, toggle: true })
|
||||
effects: showErrorMessage.of({ line: lineNum, msg, warning, toggle: true })
|
||||
});
|
||||
}
|
||||
} else if (canUseBreakpoints()) {
|
||||
|
||||
@@ -33,12 +33,19 @@ const currentPcLineField = StateField.define({
|
||||
|
||||
// Error message widget to show below error lines
|
||||
class ErrorMessageWidget extends WidgetType {
|
||||
constructor(readonly message: string) { super() }
|
||||
constructor(readonly message: string, readonly warning?: boolean) { super() }
|
||||
|
||||
toDOM() {
|
||||
let div = document.createElement("div");
|
||||
div.textContent = this.message;
|
||||
div.style.cssText = `
|
||||
div.style.cssText = this.warning ? `
|
||||
color: #ffcc44;
|
||||
background-color: #332900;
|
||||
padding: 4px 8px;
|
||||
margin: 2px 0;
|
||||
border-left: 3px solid #ffcc44;
|
||||
font-family: monospace;
|
||||
` : `
|
||||
color: #ff6666;
|
||||
background-color: #330000;
|
||||
padding: 4px 8px;
|
||||
@@ -50,6 +57,8 @@ class ErrorMessageWidget extends WidgetType {
|
||||
}
|
||||
}
|
||||
|
||||
interface ErrorMessageInfo { msg: string, warning?: boolean }
|
||||
|
||||
// State field to manage error message decorations (supports multiple messages)
|
||||
const errorMessageField = StateField.define<DecorationSet>({
|
||||
create() { return Decoration.none; },
|
||||
@@ -67,12 +76,13 @@ const errorMessageField = StateField.define<DecorationSet>({
|
||||
const widgets: any[] = [];
|
||||
|
||||
// Collect existing decorations
|
||||
const existingMessages = new Map<number, string>();
|
||||
const existingMessages = new Map<number, ErrorMessageInfo>();
|
||||
decorations.between(0, tr.state.doc.length, (from, to, value) => {
|
||||
try {
|
||||
const lineNum = tr.state.doc.lineAt(to).number;
|
||||
if (value.spec.widget instanceof ErrorMessageWidget) {
|
||||
existingMessages.set(lineNum, (value.spec.widget as ErrorMessageWidget).message);
|
||||
const widget = value.spec.widget as ErrorMessageWidget;
|
||||
existingMessages.set(lineNum, { msg: widget.message, warning: widget.warning });
|
||||
}
|
||||
} catch { }
|
||||
});
|
||||
@@ -85,7 +95,7 @@ const errorMessageField = StateField.define<DecorationSet>({
|
||||
existingMessages.delete(e.value.line);
|
||||
} else {
|
||||
// Add the new message
|
||||
existingMessages.set(e.value.line, e.value.msg);
|
||||
existingMessages.set(e.value.line, { msg: e.value.msg, warning: e.value.warning });
|
||||
}
|
||||
|
||||
// Build sorted decorations
|
||||
@@ -93,9 +103,10 @@ const errorMessageField = StateField.define<DecorationSet>({
|
||||
sortedLines.forEach(lineNum => {
|
||||
try {
|
||||
const line = tr.state.doc.line(lineNum);
|
||||
const info = existingMessages.get(lineNum)!;
|
||||
widgets.push(
|
||||
Decoration.widget({
|
||||
widget: new ErrorMessageWidget(existingMessages.get(lineNum)!),
|
||||
widget: new ErrorMessageWidget(info.msg, info.warning),
|
||||
block: true,
|
||||
side: 1
|
||||
}).range(line.to)
|
||||
@@ -159,13 +170,17 @@ const showValueDecorationField = StateField.define({
|
||||
provide: f => EditorView.decorations.from(f),
|
||||
});
|
||||
|
||||
// Error span decorations for inline column-range highlighting
|
||||
const errorSpansEffect = StateEffect.define<{ line: number, start: number, end: number }[] | null>();
|
||||
// Error/warning span decorations for inline column-range highlighting
|
||||
const errorSpansEffect = StateEffect.define<{ line: number, start: number, end: number, warning?: boolean }[] | null>();
|
||||
|
||||
const errorSpanDecoration = Decoration.mark({
|
||||
attributes: { class: "cm-error-span" }
|
||||
});
|
||||
|
||||
const warningSpanDecoration = Decoration.mark({
|
||||
attributes: { class: "cm-warning-span" }
|
||||
});
|
||||
|
||||
const errorSpansField = StateField.define({
|
||||
create() { return Decoration.none },
|
||||
update(decorations, tr) {
|
||||
@@ -183,7 +198,7 @@ const errorSpansField = StateField.define({
|
||||
const to = line.from + span.end;
|
||||
// Clamp to line boundaries
|
||||
if (from >= line.from && to <= line.to && from < to) {
|
||||
ranges.push(errorSpanDecoration.range(from, to));
|
||||
ranges.push((span.warning ? warningSpanDecoration : errorSpanDecoration).range(from, to));
|
||||
}
|
||||
} catch {
|
||||
// Line doesn't exist, skip
|
||||
|
||||
@@ -35,6 +35,10 @@ export const editorTheme = EditorView.theme({
|
||||
textDecoration: "underline wavy red",
|
||||
backgroundColor: "rgba(255, 0, 0, 0.15)",
|
||||
},
|
||||
".cm-warning-span": {
|
||||
textDecoration: "underline wavy #ffcc44",
|
||||
backgroundColor: "rgba(255, 204, 68, 0.15)",
|
||||
},
|
||||
".gutter-offset .cm-gutterElement": {
|
||||
paddingRight: "0.25em",
|
||||
},
|
||||
|
||||
Reference in new issue
Block a user