Skip to content

Commit

Permalink
Fix incremental parser diagnostics failures
Browse files Browse the repository at this point in the history
  • Loading branch information
TheUnlocked committed Mar 29, 2024
1 parent 5a586c4 commit 733b9cc
Show file tree
Hide file tree
Showing 8 changed files with 241 additions and 1,457 deletions.
1,421 changes: 78 additions & 1,343 deletions package-lock.json

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,6 @@
"omit-deep-lodash": "^1.1.7",
"rimraf": "^3.0.2",
"ts-node": "^10.8.0",
"typescript": "^4.9.4"
"typescript": "^5.4.3"
}
}
11 changes: 3 additions & 8 deletions src/diagnostics/Diagnostics.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ export class Diagnostic {

export interface DiagnosticsReporter {
report(id: number, ...args: string[]): void;
focus(node: AnyNode | Range): void;
focus(getRange: () => Range): void;
// clear(range?: Range): void;
}

Expand All @@ -60,13 +60,8 @@ export class BasicDiagnosticsReporter implements DiagnosticsReporter {

}

focus(nodeOrRange: Range | AnyNode): void {
if (nodeOrRange && 'kind' in nodeOrRange) {
this.currentRange = getNodeSourceRange(nodeOrRange);
}
else {
this.currentRange = nodeOrRange;
}
focus(getRange: () => Range): void {
this.currentRange = getRange();
}

report(id: number, ...args: string[]): Range {
Expand Down
13 changes: 8 additions & 5 deletions src/diagnostics/DiagnosticsMixin.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Range } from '../ast';
import { Range, getNodeSourceRange } from '../ast';
import { AnyNode } from '../ast/Ast';
import { Token } from '../parser/lexer';
import { AnyType, stringifyType } from '../types/KnownType';
Expand All @@ -20,12 +20,15 @@ export class DiagnosticsMixin {
this.diagnostics = diagnostics;
}

protected focus(node: AnyNode | Range | { range: Range }) {
if (node && 'range' in node) {
this.diagnostics.focus(node.range);
protected focus(target: (() => Range) | { range: Range } | AnyNode) {
if (target instanceof Function) {
this.diagnostics.focus(() => target());
}
else if ('range' in target) {
this.diagnostics.focus(() => target.range);
}
else {
this.diagnostics.focus(node);
this.diagnostics.focus(() => getNodeSourceRange(target));
}
}

Expand Down
42 changes: 19 additions & 23 deletions src/parser/TrackingReporter.ts
Original file line number Diff line number Diff line change
@@ -1,26 +1,20 @@
import { AnyNode, Range, getNodeSourceRange } from "../ast";
import { BasicDiagnosticsReporter, DiagnosticsMixin, DiagnosticsReporter } from "../diagnostics";
import { DiagnosticsMixin, DiagnosticsReporter } from "../diagnostics";

export class TrackingReportInfo {
constructor(public reportArgs: [number, ...string[]], private target: AnyNode | Range | { range: Range }) {
constructor(public reportArgs: [number, ...string[]], private getRange: () => Range) {

}

get range() {
if ('kind' in this.target) {
return getNodeSourceRange(this.target);
}
else if ('range' in this.target) {
return this.target.range;
}
return this.target;
return this.getRange();
}
}

class TrackingReporter implements DiagnosticsReporter {
export class TrackingReporter implements DiagnosticsReporter {

private _reports = [] as TrackingReportInfo[];
private target!: AnyNode | Range | { range: Range };
private currentRangeGetter!: () => Range;

constructor(private _baseReporter: DiagnosticsReporter) {

Expand All @@ -44,40 +38,42 @@ class TrackingReporter implements DiagnosticsReporter {

report(id: number, ...args: string[]) {
const range = this._baseReporter.report(id, ...args);
this._reports.push(new TrackingReportInfo([id, ...args], this.target));
this._reports.push(new TrackingReportInfo([id, ...args], this.currentRangeGetter));
return range;
}

focus(node: AnyNode | Range | { range: Range }) {
this.baseReporter.focus('range' in node ? node.range : node);
this.target = node;
focus(getRange: () => Range) {
this.baseReporter.focus(getRange);
this.currentRangeGetter = getRange;
}

}

export abstract class TrackedDiagnosticsMixin extends DiagnosticsMixin {

private _diagnostics = new TrackingReporter(this.diagnostics);
constructor() {
super();
this.diagnostics = new TrackingReporter(this.diagnostics);
}

override setDiagnostics(diagnostics: DiagnosticsReporter): void {
this._diagnostics.setBaseReporter(diagnostics);
this.diagnostics = this._diagnostics;
(this.diagnostics as TrackingReporter).setBaseReporter(diagnostics);
}

protected override focus(node: Range | AnyNode | { range: Range }): void {
this._diagnostics.focus(node);
protected override focus(node: (() => Range) | { range: Range } | AnyNode): void {
super.focus(node);
}

protected get internalDiagnosticsReporter() {
return this._diagnostics.baseReporter;
return (this.diagnostics as TrackingReporter).baseReporter;
}

protected get diagnosticsReports() {
return this._diagnostics.reports;
return (this.diagnostics as TrackingReporter).reports;
}

protected clearDiagnosticsReports() {
this._diagnostics.clearReports();
(this.diagnostics as TrackingReporter).clearReports();
}

}
4 changes: 2 additions & 2 deletions src/parser/lexer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -615,7 +615,7 @@ export class StringLexer extends TrackedDiagnosticsMixin implements ILexer {
if (isAfter(report.range.end, this.tokens[firstTokenIndex].range.start)) {
break;
}
this.diagnostics.focus(report.range);
this.focus(report);
this.diagnostics.report(...report.reportArgs);
}

Expand Down Expand Up @@ -724,7 +724,7 @@ export class StringLexer extends TrackedDiagnosticsMixin implements ILexer {
// Add any diagnostics from the existing tokens
for (const report of oldReports) {
if (isAfterOrEquals(report.range.start, token.range.start)) {
this.diagnostics.focus(report.range);
this.focus(report);
this.diagnostics.report(...report.reportArgs);
}
}
Expand Down
Loading

0 comments on commit 733b9cc

Please sign in to comment.