153 lines
4.3 KiB
JavaScript
153 lines
4.3 KiB
JavaScript
"use strict";
|
|
|
|
const assert = require("node:assert");
|
|
const { test } = require("node:test");
|
|
const Module = require("node:module");
|
|
|
|
const originalLoad = Module._load;
|
|
Module._load = function load(request, parent, isMain) {
|
|
if (request === "vscode") {
|
|
return {
|
|
Diagnostic: class Diagnostic {
|
|
constructor(range, message, severity) {
|
|
this.range = range;
|
|
this.message = message;
|
|
this.severity = severity;
|
|
}
|
|
},
|
|
DiagnosticSeverity: { Error: 0, Warning: 1 },
|
|
Range: class Range {
|
|
constructor(start, end) {
|
|
this.start = start;
|
|
this.end = end;
|
|
}
|
|
},
|
|
};
|
|
}
|
|
return originalLoad.call(this, request, parent, isMain);
|
|
};
|
|
const {
|
|
findTopLevelDeclaration,
|
|
maskLeadingTrivia,
|
|
validateBalancedCharacters,
|
|
validateHtmlTags,
|
|
validateRootMembers,
|
|
} = require("../src/diagnostics");
|
|
Module._load = originalLoad;
|
|
|
|
function mockDocument() {
|
|
return {
|
|
positionAt(offset) {
|
|
return offset;
|
|
},
|
|
};
|
|
}
|
|
|
|
test("recognizes a WRN declaration after leading line comments", () => {
|
|
const source = `// Component summary
|
|
// More details
|
|
|
|
component ThemeToggle {
|
|
view { <button>Toggle</button> }
|
|
}`;
|
|
|
|
const declaration = findTopLevelDeclaration({}, source);
|
|
|
|
assert.equal(declaration.kind, "component");
|
|
assert.equal(declaration.name, "ThemeToggle");
|
|
assert.equal(declaration.diagnostic, undefined);
|
|
});
|
|
|
|
test("recognizes a WRN declaration after top-level imports", () => {
|
|
const source = `import { appUrl } from "@wrnexus/helpers";
|
|
import type { Context } from "@wrnexus/core";
|
|
|
|
page Home {
|
|
view { <PublicHeader signInHref="{appUrl('sso', '/sign-in')}" /> }
|
|
}`;
|
|
const declaration = findTopLevelDeclaration({}, source);
|
|
assert.equal(declaration.kind, "page");
|
|
assert.equal(declaration.name, "Home");
|
|
assert.equal(declaration.diagnostic, undefined);
|
|
});
|
|
|
|
test("masks only leading trivia and preserves source offsets", () => {
|
|
const source = "\uFEFF// Summary\r\npage Home {\n // member comment\n}";
|
|
const masked = maskLeadingTrivia(source);
|
|
|
|
assert.equal(masked.length, source.length);
|
|
assert.equal(masked.indexOf("page Home"), source.indexOf("page Home"));
|
|
assert.match(masked, /\/\/ member comment/);
|
|
});
|
|
|
|
test("ignores apostrophes and brackets in line comments when checking balance", () => {
|
|
const source = `// The framework's theme runtime binds the click }
|
|
component ThemeToggle {
|
|
props {
|
|
label = "Toggle theme"
|
|
class = ""
|
|
}
|
|
view { <button class="{class}" data-wire-theme-toggle><slot>{label}</slot></button> }
|
|
}`;
|
|
|
|
const diagnostics = validateBalancedCharacters(mockDocument(source), source);
|
|
|
|
assert.deepEqual(diagnostics, []);
|
|
});
|
|
|
|
test("accepts all WRN 0.3 root members without false unknown-member errors", () => {
|
|
const source = `page Dashboard {
|
|
runtime = "universal"
|
|
hydrate = "visible"
|
|
computed { doubled = count * 2 }
|
|
effect { console.log(doubled) }
|
|
security { auth = "required" }
|
|
load server { return {} }
|
|
action save(input) { return input }
|
|
client { functions { function ready() {} } }
|
|
view { <main>{doubled}</main> }
|
|
}`;
|
|
const declaration = findTopLevelDeclaration({}, source);
|
|
const document = {
|
|
positionAt(offset) {
|
|
return offset;
|
|
},
|
|
};
|
|
|
|
assert.deepEqual(validateRootMembers(document, source, declaration.kind, declaration.match), []);
|
|
});
|
|
|
|
test("ignores member-like words inside component line and block comments", () => {
|
|
const source = `component Counter {
|
|
// Props are passed as attributes on the mount element.
|
|
/* State and View are explained here, not declared here. */
|
|
props {
|
|
start = 0
|
|
label = "Count"
|
|
}
|
|
state count = start
|
|
view { <button>{label}: {count}</button> }
|
|
}`;
|
|
const declaration = findTopLevelDeclaration({}, source);
|
|
|
|
assert.deepEqual(
|
|
validateRootMembers(mockDocument(source), source, declaration.kind, declaration.match),
|
|
[],
|
|
);
|
|
});
|
|
|
|
test("ignores HTML-like tags inside WRN comments", () => {
|
|
const source = `// The <section> below listens for child events.
|
|
// <ComboBox> is only documentation in this comment.
|
|
page Test {
|
|
/*
|
|
Example markup: <article><strong>Preview</strong></article>
|
|
*/
|
|
view {
|
|
<main><section>Real content</section></main>
|
|
}
|
|
}`;
|
|
|
|
assert.deepEqual(validateHtmlTags(mockDocument(source), source), []);
|
|
});
|