Skip to content

Commit

Permalink
fix(language-service): Autocomplete block keywords in more cases (#52198
Browse files Browse the repository at this point in the history
)

Previously, autocompletions were not available in two main cases. We correct them.

1. Autocompletions immediately after `@` were usually not working, for example `foo @|`. We fix this by causing the lexer to not consider the `@` part of the text node.
2. Autocompletions such as `@\nfoo`, where a newline follows a bare `@`, were not working because the language service visitor considered us inside the subsequent text node. We fix this by adding a block name span for the block keyword, and special-case whether we are completing inside the name span. If we are, we don't continue to the following text node.

PR Close #52198
  • Loading branch information
dylhunn committed Oct 23, 2023
1 parent 182d574 commit 9d565cd
Show file tree
Hide file tree
Showing 11 changed files with 1,323 additions and 29 deletions.
4 changes: 2 additions & 2 deletions packages/compiler/src/ml_parser/ast.ts
Original file line number Diff line number Diff line change
Expand Up @@ -89,8 +89,8 @@ export class Comment implements BaseNode {
export class Block implements BaseNode {
constructor(
public name: string, public parameters: BlockParameter[], public children: Node[],
public sourceSpan: ParseSourceSpan, public startSourceSpan: ParseSourceSpan,
public endSourceSpan: ParseSourceSpan|null = null) {}
public sourceSpan: ParseSourceSpan, public nameSpan: ParseSourceSpan,
public startSourceSpan: ParseSourceSpan, public endSourceSpan: ParseSourceSpan|null = null) {}

visit(visitor: Visitor, context: any) {
return visitor.visitBlock(this, context);
Expand Down
2 changes: 1 addition & 1 deletion packages/compiler/src/ml_parser/html_whitespaces.ts
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ export class WhitespaceVisitor implements html.Visitor {
visitBlock(block: html.Block, context: any): any {
return new html.Block(
block.name, block.parameters, visitAllWithSiblings(this, block.children), block.sourceSpan,
block.startSourceSpan, block.endSourceSpan);
block.nameSpan, block.startSourceSpan, block.endSourceSpan);
}

visitBlockParameter(parameter: html.BlockParameter, context: any) {
Expand Down
2 changes: 1 addition & 1 deletion packages/compiler/src/ml_parser/icu_ast_expander.ts
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ class _Expander implements html.Visitor {
visitBlock(block: html.Block, context: any) {
return new html.Block(
block.name, block.parameters, html.visitAll(this, block.children), block.sourceSpan,
block.startSourceSpan, block.endSourceSpan);
block.nameSpan, block.startSourceSpan, block.endSourceSpan);
}

visitBlockParameter(parameter: html.BlockParameter, context: any) {
Expand Down
15 changes: 1 addition & 14 deletions packages/compiler/src/ml_parser/lexer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -918,7 +918,7 @@ class _Tokenizer {
}

if (this._tokenizeBlocks && !this._inInterpolation && !this._isInExpansion() &&
(this._isBlockStart() || this._cursor.peek() === chars.$RBRACE)) {
(this._cursor.peek() === chars.$AT || this._cursor.peek() === chars.$RBRACE)) {
return true;
}

Expand All @@ -944,19 +944,6 @@ class _Tokenizer {
return false;
}

private _isBlockStart(): boolean {
if (this._tokenizeBlocks && this._cursor.peek() === chars.$AT) {
const tmp = this._cursor.clone();

// If it is, also verify that the next character is a valid block identifier.
tmp.advance();
if (isBlockNameChar(tmp.peek())) {
return true;
}
}
return false;
}

private _readUntil(char: number): string {
const start = this._cursor.clone();
this._attemptUntilChar(char);
Expand Down
4 changes: 2 additions & 2 deletions packages/compiler/src/ml_parser/parser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -474,7 +474,7 @@ class _TreeBuilder {
const span = new ParseSourceSpan(token.sourceSpan.start, end, token.sourceSpan.fullStart);
// Create a separate `startSpan` because `span` will be modified when there is an `end` span.
const startSpan = new ParseSourceSpan(token.sourceSpan.start, end, token.sourceSpan.fullStart);
const block = new html.Block(token.parts[0], parameters, [], span, startSpan);
const block = new html.Block(token.parts[0], parameters, [], span, token.sourceSpan, startSpan);
this._pushContainer(block, false);
}

Expand All @@ -500,7 +500,7 @@ class _TreeBuilder {
const span = new ParseSourceSpan(token.sourceSpan.start, end, token.sourceSpan.fullStart);
// Create a separate `startSpan` because `span` will be modified when there is an `end` span.
const startSpan = new ParseSourceSpan(token.sourceSpan.start, end, token.sourceSpan.fullStart);
const block = new html.Block(token.parts[0], parameters, [], span, startSpan);
const block = new html.Block(token.parts[0], parameters, [], span, token.sourceSpan, startSpan);
this._pushContainer(block, false);

// Incomplete blocks don't have children so we close them immediately and report an error.
Expand Down
3 changes: 2 additions & 1 deletion packages/compiler/src/render3/r3_ast.ts
Original file line number Diff line number Diff line change
Expand Up @@ -315,7 +315,8 @@ export class IfBlockBranch implements Node {
}

export class UnknownBlock implements Node {
constructor(public name: string, public sourceSpan: ParseSourceSpan) {}
constructor(
public name: string, public sourceSpan: ParseSourceSpan, public nameSpan: ParseSourceSpan) {}

visit<Result>(visitor: Visitor<Result>): Result {
return visitor.visitUnknownBlock(this);
Expand Down
2 changes: 1 addition & 1 deletion packages/compiler/src/render3/r3_control_flow.ts
Original file line number Diff line number Diff line change
Expand Up @@ -163,7 +163,7 @@ export function createSwitchBlock(
}

if ((node.name !== 'case' || node.parameters.length === 0) && node.name !== 'default') {
unknownBlocks.push(new t.UnknownBlock(node.name, node.sourceSpan));
unknownBlocks.push(new t.UnknownBlock(node.name, node.sourceSpan, node.nameSpan));
continue;
}

Expand Down
2 changes: 1 addition & 1 deletion packages/compiler/src/render3/r3_template_transform.ts
Original file line number Diff line number Diff line change
Expand Up @@ -383,7 +383,7 @@ class HtmlAstToIvyAst implements html.Visitor {
}

result = {
node: new t.UnknownBlock(block.name, block.sourceSpan),
node: new t.UnknownBlock(block.name, block.sourceSpan, block.nameSpan),
errors: [new ParseError(block.sourceSpan, errorMessage)],
};
break;
Expand Down
Loading

0 comments on commit 9d565cd

Please sign in to comment.