The "enableIvy" compiler option is the initial implementation of the Render3 (or Ivy) code generation. This commit enables generation generating "Hello, World" (example in the test) but not much else. It is currenly only useful for internal Ivy testing as Ivy is in development. PR Close #21427
151 lines
4.1 KiB
TypeScript
151 lines
4.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 * 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 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); }
|
|
}
|