angular-cn/modules/@angular/language-service/src/html_path.ts

73 lines
2.1 KiB
TypeScript

/**
* @license
* Copyright Google Inc. All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
import {Attribute, Comment, Element, Expansion, ExpansionCase, Node, Text, Visitor, visitAll} from '@angular/compiler/src/ml_parser/ast';
import {AstPath} from './ast_path';
import {inSpan, spanOf} from './utils';
export class HtmlAstPath extends AstPath<Node> {
constructor(ast: Node[], public position: number) { super(buildPath(ast, position)); }
}
function buildPath(ast: Node[], position: number): Node[] {
let visitor = new HtmlAstPathBuilder(position);
visitAll(visitor, ast);
return visitor.getPath();
}
export class ChildVisitor implements Visitor {
constructor(private visitor?: Visitor) {}
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) {
const visitor = this.visitor || this;
let results: any[][] = [];
function visit<T extends Node>(children: T[] | undefined) {
if (children) results.push(visitAll(visitor, children, context));
}
cb(visit);
return [].concat.apply([], results);
}
}
class HtmlAstPathBuilder extends ChildVisitor {
private path: Node[] = [];
constructor(private position: number) { super(); }
visit(ast: Node, context: any): any {
let span = spanOf(ast);
if (inSpan(this.position, span)) {
this.path.push(ast);
} else {
// Returning a value here will result in the children being skipped.
return true;
}
}
getPath(): Node[] { return this.path; }
}