fix(syntax): allow block comments between members
`skipTrivia` skipped `// line comments` but not `/* block comments */`, so one
written between two page or component members failed with a bare "Unexpected
character '/'". Block comments inside a braced body already worked, which made
the failure look arbitrary: the same comment parsed or did not depending on
whether it happened to sit inside a block.
`startsWithBlockComment` now skips only whitespace and line comments, so
`props {}` keeps refusing block comments with its own explained error rather
than silently swallowing one and dropping the declaration after it.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -163,8 +163,13 @@ export class Lexer {
|
||||
pos = 0;
|
||||
constructor(public readonly src: string) {}
|
||||
|
||||
/** Skip whitespace and `// line comments`. */
|
||||
private skipTrivia(): void {
|
||||
/**
|
||||
* Skip whitespace and `// line comments`, but NOT block comments.
|
||||
*
|
||||
* Kept separate from `skipTrivia` so `startsWithBlockComment` can still see a
|
||||
* block comment that `skipTrivia` would otherwise consume.
|
||||
*/
|
||||
private skipWhitespaceAndLineComments(): void {
|
||||
const { src } = this;
|
||||
while (this.pos < src.length) {
|
||||
const c = src[this.pos]!;
|
||||
@@ -180,9 +185,35 @@ export class Lexer {
|
||||
}
|
||||
}
|
||||
|
||||
/** True when the next non-trivia characters open a block comment. */
|
||||
/**
|
||||
* Skip whitespace, line comments and block comments.
|
||||
*
|
||||
* Block comments used to be skipped only inside a braced body, so one written
|
||||
* between two members failed with a bare "Unexpected character '/'" -- the
|
||||
* same comment parsed or did not depending on where it sat.
|
||||
*/
|
||||
private skipTrivia(): void {
|
||||
const { src } = this;
|
||||
while (this.pos < src.length) {
|
||||
this.skipWhitespaceAndLineComments();
|
||||
if (src[this.pos] === "/" && src[this.pos + 1] === "*") {
|
||||
const close = src.indexOf("*/", this.pos + 2);
|
||||
this.pos = close === -1 ? src.length : close + 2;
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* True when the next non-trivia characters open a block comment.
|
||||
*
|
||||
* Deliberately skips only whitespace and line comments: `props {}` refuses
|
||||
* block comments with an explained error, and that check must run before
|
||||
* `skipTrivia` would swallow the comment and drop a declaration silently.
|
||||
*/
|
||||
startsWithBlockComment(): boolean {
|
||||
this.skipTrivia();
|
||||
this.skipWhitespaceAndLineComments();
|
||||
return this.src[this.pos] === "/" && this.src[this.pos + 1] === "*";
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user