refactor(compiler-cli): move the expression expression type checker (#16562)
The expression type checker moved from the language service to the compiler-cli in preparation to using it to check template expressions.
This commit is contained in:

committed by
Jason Aden

parent
9e661e58d1
commit
bb0902c592
@ -6,6 +6,7 @@
|
||||
* found in the LICENSE file at https://angular.io/license
|
||||
*/
|
||||
|
||||
import {AstPath} from '../ast_path';
|
||||
import {ParseSourceSpan} from '../parse_util';
|
||||
|
||||
export interface Node {
|
||||
@ -80,3 +81,70 @@ export function visitAll(visitor: Visitor, nodes: Node[], context: any = null):
|
||||
});
|
||||
return result;
|
||||
}
|
||||
|
||||
export class RecursiveVisitor implements Visitor {
|
||||
constructor() {}
|
||||
|
||||
visitElement(ast: Element, context: any): any {
|
||||
this.visitChildren(context, visit => {
|
||||
visit(ast.attrs);
|
||||
visit(ast.children);
|
||||
});
|
||||
}
|
||||
|
||||
visitAttribute(ast: Attribute, context: any): any {}
|
||||
visitText(ast: Text, context: any): any {}
|
||||
visitComment(ast: Comment, context: any): any {}
|
||||
|
||||
visitExpansion(ast: Expansion, context: any): any {
|
||||
return this.visitChildren(context, visit => { visit(ast.cases); });
|
||||
}
|
||||
|
||||
visitExpansionCase(ast: ExpansionCase, context: any): any {}
|
||||
|
||||
private visitChildren<T extends Node>(
|
||||
context: any, cb: (visit: (<V extends Node>(children: V[]|undefined) => void)) => void) {
|
||||
let results: any[][] = [];
|
||||
let t = this;
|
||||
function visit<T extends Node>(children: T[] | undefined) {
|
||||
if (children) results.push(visitAll(t, children, context));
|
||||
}
|
||||
cb(visit);
|
||||
return [].concat.apply([], results);
|
||||
}
|
||||
}
|
||||
|
||||
export type HtmlAstPath = AstPath<Node>;
|
||||
|
||||
function spanOf(ast: Node) {
|
||||
const start = ast.sourceSpan.start.offset;
|
||||
let end = ast.sourceSpan.end.offset;
|
||||
if (ast instanceof Element) {
|
||||
if (ast.endSourceSpan) {
|
||||
end = ast.endSourceSpan.end.offset;
|
||||
} else if (ast.children && ast.children.length) {
|
||||
end = spanOf(ast.children[ast.children.length - 1]).end;
|
||||
}
|
||||
}
|
||||
return {start, end};
|
||||
}
|
||||
|
||||
export function findNode(nodes: Node[], position: number): HtmlAstPath {
|
||||
const path: Node[] = [];
|
||||
|
||||
const visitor = new class extends RecursiveVisitor {
|
||||
visit(ast: Node, context: any): any {
|
||||
const span = spanOf(ast);
|
||||
if (span.start <= position && position < span.end) {
|
||||
path.push(ast);
|
||||
} else {
|
||||
// Returning a value here will result in the children being skipped.
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
visitAll(visitor, nodes);
|
||||
|
||||
return new AstPath<Node>(path, position);
|
||||
}
|
Reference in New Issue
Block a user