2016-11-22 12:10:23 -05:00
|
|
|
/**
|
|
|
|
* @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
|
|
|
|
*/
|
|
|
|
|
2017-01-27 20:39:48 -05:00
|
|
|
import {CompileDirectiveSummary, CompileTypeMetadata, CssSelector, ParseSourceSpan, SelectorMatcher, identifierName} from '@angular/compiler';
|
2016-11-22 12:10:23 -05:00
|
|
|
|
|
|
|
import {SelectorInfo, TemplateInfo} from './common';
|
|
|
|
import {Span} from './types';
|
|
|
|
|
|
|
|
export interface SpanHolder {
|
|
|
|
sourceSpan: ParseSourceSpan;
|
2017-03-24 12:57:32 -04:00
|
|
|
endSourceSpan?: ParseSourceSpan|null;
|
2016-11-22 12:10:23 -05:00
|
|
|
children?: SpanHolder[];
|
|
|
|
}
|
|
|
|
|
|
|
|
export function isParseSourceSpan(value: any): value is ParseSourceSpan {
|
|
|
|
return value && !!value.start;
|
|
|
|
}
|
|
|
|
|
2017-03-24 12:57:32 -04:00
|
|
|
export function spanOf(span?: SpanHolder | ParseSourceSpan): Span|undefined {
|
2016-11-22 12:10:23 -05:00
|
|
|
if (!span) return undefined;
|
|
|
|
if (isParseSourceSpan(span)) {
|
|
|
|
return {start: span.start.offset, end: span.end.offset};
|
|
|
|
} else {
|
|
|
|
if (span.endSourceSpan) {
|
|
|
|
return {start: span.sourceSpan.start.offset, end: span.endSourceSpan.end.offset};
|
|
|
|
} else if (span.children && span.children.length) {
|
|
|
|
return {
|
|
|
|
start: span.sourceSpan.start.offset,
|
2017-03-24 12:57:32 -04:00
|
|
|
end: spanOf(span.children[span.children.length - 1]) !.end
|
2016-11-22 12:10:23 -05:00
|
|
|
};
|
|
|
|
}
|
|
|
|
return {start: span.sourceSpan.start.offset, end: span.sourceSpan.end.offset};
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
export function inSpan(position: number, span?: Span, exclusive?: boolean): boolean {
|
|
|
|
return span && exclusive ? position >= span.start && position < span.end :
|
2017-03-24 12:57:32 -04:00
|
|
|
position >= span !.start && position <= span !.end;
|
2016-11-22 12:10:23 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
export function offsetSpan(span: Span, amount: number): Span {
|
|
|
|
return {start: span.start + amount, end: span.end + amount};
|
|
|
|
}
|
|
|
|
|
|
|
|
export function isNarrower(spanA: Span, spanB: Span): boolean {
|
|
|
|
return spanA.start >= spanB.start && spanA.end <= spanB.end;
|
|
|
|
}
|
|
|
|
|
|
|
|
export function hasTemplateReference(type: CompileTypeMetadata): boolean {
|
|
|
|
if (type.diDeps) {
|
|
|
|
for (let diDep of type.diDeps) {
|
2017-03-24 12:57:32 -04:00
|
|
|
if (diDep.token !.identifier && identifierName(diDep.token !.identifier !) == 'TemplateRef')
|
2016-11-23 12:42:19 -05:00
|
|
|
return true;
|
2016-11-22 12:10:23 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
export function getSelectors(info: TemplateInfo): SelectorInfo {
|
|
|
|
const map = new Map<CssSelector, CompileDirectiveSummary>();
|
2017-03-24 12:57:32 -04:00
|
|
|
const selectors: CssSelector[] = flatten(info.directives.map(directive => {
|
|
|
|
const selectors: CssSelector[] = CssSelector.parse(directive.selector !);
|
2016-11-22 12:10:23 -05:00
|
|
|
selectors.forEach(selector => map.set(selector, directive));
|
|
|
|
return selectors;
|
|
|
|
}));
|
|
|
|
return {selectors, map};
|
|
|
|
}
|
|
|
|
|
|
|
|
export function flatten<T>(a: T[][]) {
|
|
|
|
return (<T[]>[]).concat(...a);
|
|
|
|
}
|
|
|
|
|
|
|
|
export function removeSuffix(value: string, suffix: string) {
|
|
|
|
if (value.endsWith(suffix)) return value.substring(0, value.length - suffix.length);
|
|
|
|
return value;
|
|
|
|
}
|
|
|
|
|
|
|
|
export function uniqueByName < T extends {
|
|
|
|
name: string;
|
|
|
|
}
|
|
|
|
> (elements: T[] | undefined): T[]|undefined {
|
|
|
|
if (elements) {
|
|
|
|
const result: T[] = [];
|
|
|
|
const set = new Set<string>();
|
|
|
|
for (const element of elements) {
|
|
|
|
if (!set.has(element.name)) {
|
|
|
|
set.add(element.name);
|
|
|
|
result.push(element);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
}
|