Skip to content

Commit 9d565cd

Browse files
committed
fix(language-service): Autocomplete block keywords in more cases (#52198)
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
1 parent 182d574 commit 9d565cd

File tree

11 files changed

+1323
-29
lines changed

11 files changed

+1323
-29
lines changed

packages/compiler/src/ml_parser/ast.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -89,8 +89,8 @@ export class Comment implements BaseNode {
8989
export class Block implements BaseNode {
9090
constructor(
9191
public name: string, public parameters: BlockParameter[], public children: Node[],
92-
public sourceSpan: ParseSourceSpan, public startSourceSpan: ParseSourceSpan,
93-
public endSourceSpan: ParseSourceSpan|null = null) {}
92+
public sourceSpan: ParseSourceSpan, public nameSpan: ParseSourceSpan,
93+
public startSourceSpan: ParseSourceSpan, public endSourceSpan: ParseSourceSpan|null = null) {}
9494

9595
visit(visitor: Visitor, context: any) {
9696
return visitor.visitBlock(this, context);

packages/compiler/src/ml_parser/html_whitespaces.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,7 @@ export class WhitespaceVisitor implements html.Visitor {
101101
visitBlock(block: html.Block, context: any): any {
102102
return new html.Block(
103103
block.name, block.parameters, visitAllWithSiblings(this, block.children), block.sourceSpan,
104-
block.startSourceSpan, block.endSourceSpan);
104+
block.nameSpan, block.startSourceSpan, block.endSourceSpan);
105105
}
106106

107107
visitBlockParameter(parameter: html.BlockParameter, context: any) {

packages/compiler/src/ml_parser/icu_ast_expander.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,7 @@ class _Expander implements html.Visitor {
9191
visitBlock(block: html.Block, context: any) {
9292
return new html.Block(
9393
block.name, block.parameters, html.visitAll(this, block.children), block.sourceSpan,
94-
block.startSourceSpan, block.endSourceSpan);
94+
block.nameSpan, block.startSourceSpan, block.endSourceSpan);
9595
}
9696

9797
visitBlockParameter(parameter: html.BlockParameter, context: any) {

packages/compiler/src/ml_parser/lexer.ts

Lines changed: 1 addition & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -918,7 +918,7 @@ class _Tokenizer {
918918
}
919919

920920
if (this._tokenizeBlocks && !this._inInterpolation && !this._isInExpansion() &&
921-
(this._isBlockStart() || this._cursor.peek() === chars.$RBRACE)) {
921+
(this._cursor.peek() === chars.$AT || this._cursor.peek() === chars.$RBRACE)) {
922922
return true;
923923
}
924924

@@ -944,19 +944,6 @@ class _Tokenizer {
944944
return false;
945945
}
946946

947-
private _isBlockStart(): boolean {
948-
if (this._tokenizeBlocks && this._cursor.peek() === chars.$AT) {
949-
const tmp = this._cursor.clone();
950-
951-
// If it is, also verify that the next character is a valid block identifier.
952-
tmp.advance();
953-
if (isBlockNameChar(tmp.peek())) {
954-
return true;
955-
}
956-
}
957-
return false;
958-
}
959-
960947
private _readUntil(char: number): string {
961948
const start = this._cursor.clone();
962949
this._attemptUntilChar(char);

packages/compiler/src/ml_parser/parser.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -474,7 +474,7 @@ class _TreeBuilder {
474474
const span = new ParseSourceSpan(token.sourceSpan.start, end, token.sourceSpan.fullStart);
475475
// Create a separate `startSpan` because `span` will be modified when there is an `end` span.
476476
const startSpan = new ParseSourceSpan(token.sourceSpan.start, end, token.sourceSpan.fullStart);
477-
const block = new html.Block(token.parts[0], parameters, [], span, startSpan);
477+
const block = new html.Block(token.parts[0], parameters, [], span, token.sourceSpan, startSpan);
478478
this._pushContainer(block, false);
479479
}
480480

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

506506
// Incomplete blocks don't have children so we close them immediately and report an error.

packages/compiler/src/render3/r3_ast.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -315,7 +315,8 @@ export class IfBlockBranch implements Node {
315315
}
316316

317317
export class UnknownBlock implements Node {
318-
constructor(public name: string, public sourceSpan: ParseSourceSpan) {}
318+
constructor(
319+
public name: string, public sourceSpan: ParseSourceSpan, public nameSpan: ParseSourceSpan) {}
319320

320321
visit<Result>(visitor: Visitor<Result>): Result {
321322
return visitor.visitUnknownBlock(this);

packages/compiler/src/render3/r3_control_flow.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -163,7 +163,7 @@ export function createSwitchBlock(
163163
}
164164

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

packages/compiler/src/render3/r3_template_transform.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -383,7 +383,7 @@ class HtmlAstToIvyAst implements html.Visitor {
383383
}
384384

385385
result = {
386-
node: new t.UnknownBlock(block.name, block.sourceSpan),
386+
node: new t.UnknownBlock(block.name, block.sourceSpan, block.nameSpan),
387387
errors: [new ParseError(block.sourceSpan, errorMessage)],
388388
};
389389
break;

0 commit comments

Comments
 (0)