angular-cn/packages/compiler-cli/test/mocks.ts

153 lines
4.2 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 * as ts from 'typescript';
export type Entry = string | Directory;
export interface Directory { [name: string]: Entry; }
export class MockAotContext {
private files: Entry[];
constructor(public currentDirectory: string, ...files: Entry[]) { this.files = files; }
fileExists(fileName: string): boolean { return typeof this.getEntry(fileName) === 'string'; }
directoryExists(path: string): boolean {
return path === this.currentDirectory || typeof this.getEntry(path) === 'object';
}
readFile(fileName: string): string {
const data = this.getEntry(fileName);
if (typeof data === 'string') {
return data;
}
return undefined !;
}
readResource(fileName: string): Promise<string> {
const result = this.readFile(fileName);
if (result == null) {
return Promise.reject(new Error(`Resource not found: ${fileName}`));
}
return Promise.resolve(result);
}
writeFile(fileName: string, data: string): void {
const parts = fileName.split('/');
const name = parts.pop() !;
const entry = this.getEntry(parts);
if (entry && typeof entry !== 'string') {
entry[name] = data;
}
}
assumeFileExists(fileName: string): void { this.writeFile(fileName, ''); }
getEntry(fileName: string|string[]): Entry|undefined {
let parts = typeof fileName === 'string' ? fileName.split('/') : fileName;
if (parts[0]) {
parts = this.currentDirectory.split('/').concat(parts);
}
parts.shift();
parts = normalize(parts);
return first(this.files, files => getEntryFromFiles(parts, files));
}
getDirectories(path: string): string[] {
const dir = this.getEntry(path);
if (typeof dir !== 'object') {
return [];
} else {
return Object.keys(dir).filter(key => typeof dir[key] === 'object');
}
}
override(files: Entry) { return new MockAotContext(this.currentDirectory, files, ...this.files); }
}
function first<T>(a: T[], cb: (value: T) => T | undefined): T|undefined {
for (const value of a) {
const result = cb(value);
if (result != null) return result;
}
}
function getEntryFromFiles(parts: string[], files: Entry) {
let current = files;
while (parts.length) {
const part = parts.shift() !;
if (typeof current === 'string') {
return undefined;
}
const next = (<Directory>current)[part];
if (next === undefined) {
return undefined;
}
current = next;
}
return current;
}
function normalize(parts: string[]): string[] {
const result: string[] = [];
while (parts.length) {
const part = parts.shift() !;
switch (part) {
case '.':
break;
case '..':
result.pop();
break;
default:
result.push(part);
}
}
return result;
}
export class MockCompilerHost implements ts.CompilerHost {
constructor(private context: MockAotContext) {}
fileExists(fileName: string): boolean { return this.context.fileExists(fileName); }
readFile(fileName: string): string { return this.context.readFile(fileName); }
directoryExists(directoryName: string): boolean {
return this.context.directoryExists(directoryName);
}
getSourceFile(
fileName: string, languageVersion: ts.ScriptTarget,
onError?: (message: string) => void): ts.SourceFile {
const sourceText = this.context.readFile(fileName);
if (sourceText != null) {
return ts.createSourceFile(fileName, sourceText, languageVersion);
} else {
return undefined !;
}
}
getDefaultLibFileName(options: ts.CompilerOptions): string {
return ts.getDefaultLibFileName(options);
}
writeFile: ts.WriteFileCallback = (fileName, text) => { this.context.writeFile(fileName, text); };
getCurrentDirectory(): string { return this.context.currentDirectory; }
getCanonicalFileName(fileName: string): string { return fileName; }
useCaseSensitiveFileNames(): boolean { return false; }
getNewLine(): string { return '\n'; }
getDirectories(path: string): string[] { return this.context.getDirectories(path); }
}