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:
Chuck Jazdzewski
2017-05-09 16:16:50 -07:00
committed by Jason Aden
parent 9e661e58d1
commit bb0902c592
23 changed files with 2891 additions and 2270 deletions

View File

@ -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);
}