From 6518ff88b248246b8a62bfd1b5e11fbb108a30bc Mon Sep 17 00:00:00 2001 From: Chuck Jazdzewski Date: Wed, 13 Jul 2016 11:15:23 -0700 Subject: [PATCH] fix(compiler): No longer writes 0 length files outside of genDir (#10023) Fixes: #9984 --- .../compiler-cli/src/reflector_host.ts | 36 ++++++++++++------- modules/@angular/compiler-cli/test/mocks.ts | 22 +++++++----- 2 files changed, 38 insertions(+), 20 deletions(-) diff --git a/modules/@angular/compiler-cli/src/reflector_host.ts b/modules/@angular/compiler-cli/src/reflector_host.ts index 90d47c4cf9..5ce03e5ef1 100644 --- a/modules/@angular/compiler-cli/src/reflector_host.ts +++ b/modules/@angular/compiler-cli/src/reflector_host.ts @@ -18,9 +18,10 @@ const EXT = /(\.ts|\.d\.ts|\.js|\.jsx|\.tsx)$/; const DTS = /\.d\.ts$/; export interface ReflectorHostContext { - exists(fileName: string): boolean; - read(fileName: string): string; - write(fileName: string, data: string): void; + fileExists(fileName: string): boolean; + directoryExists(directoryName: string): boolean; + readFile(fileName: string): string; + assumeFileExists(fileName: string): void; } export class ReflectorHost implements StaticReflectorHost, ImportGenerator { @@ -44,7 +45,7 @@ export class ReflectorHost implements StaticReflectorHost, ImportGenerator { } private resolve(m: string, containingFile: string) { const resolved = - ts.resolveModuleName(m, containingFile, this.options, this.compilerHost).resolvedModule; + ts.resolveModuleName(m, containingFile, this.options, this.context).resolvedModule; return resolved ? resolved.resolvedFileName : null; }; @@ -77,8 +78,7 @@ export class ReflectorHost implements StaticReflectorHost, ImportGenerator { if (this.options.trace) { console.log(`Generating empty file ${importedFile} to allow resolution of import`); } - this.compilerHost.writeFile(importedFile, '', false); - this.context.write(importedFile, ''); + this.context.assumeFileExists(importedFile); } const importModuleName = importedFile.replace(EXT, ''); @@ -178,7 +178,7 @@ export class ReflectorHost implements StaticReflectorHost, ImportGenerator { } getMetadataFor(filePath: string): ModuleMetadata { - if (!this.context.exists(filePath)) { + if (!this.context.fileExists(filePath)) { // If the file doesn't exists then we cannot return metadata for the file. // This will occur if the user refernced a declared module for which no file // exists for the module (i.e. jQuery or angularjs). @@ -186,7 +186,7 @@ export class ReflectorHost implements StaticReflectorHost, ImportGenerator { } if (DTS.test(filePath)) { const metadataPath = filePath.replace(DTS, '.metadata.json'); - if (this.context.exists(metadataPath)) { + if (this.context.fileExists(metadataPath)) { return this.readMetadata(metadataPath); } } else { @@ -200,7 +200,7 @@ export class ReflectorHost implements StaticReflectorHost, ImportGenerator { readMetadata(filePath: string) { try { - const result = JSON.parse(this.context.read(filePath)); + const result = JSON.parse(this.context.readFile(filePath)); return result; } catch (e) { console.error(`Failed to read JSON file ${filePath}`); @@ -210,9 +210,21 @@ export class ReflectorHost implements StaticReflectorHost, ImportGenerator { } export class NodeReflectorHostContext implements ReflectorHostContext { - exists(fileName: string): boolean { return fs.existsSync(fileName); } + private assumedExists: {[fileName: string]: boolean} = {}; - read(fileName: string): string { return fs.readFileSync(fileName, 'utf8'); } + fileExists(fileName: string): boolean { + return this.assumedExists[fileName] || fs.existsSync(fileName); + } - write(fileName: string, data: string): void { fs.writeFileSync(fileName, data, 'utf8'); } + directoryExists(directoryName: string): boolean { + try { + return fs.statSync(directoryName).isDirectory(); + } catch (e) { + return false; + } + } + + readFile(fileName: string): string { return fs.readFileSync(fileName, 'utf8'); } + + assumeFileExists(fileName: string): void { this.assumedExists[fileName] = true; } } diff --git a/modules/@angular/compiler-cli/test/mocks.ts b/modules/@angular/compiler-cli/test/mocks.ts index 1233a95161..4c2e42861c 100644 --- a/modules/@angular/compiler-cli/test/mocks.ts +++ b/modules/@angular/compiler-cli/test/mocks.ts @@ -17,9 +17,11 @@ export interface Directory { [name: string]: Entry; } export class MockContext implements ReflectorHostContext { constructor(public currentDirectory: string, private files: Entry) {} - exists(fileName: string): boolean { return this.getEntry(fileName) !== undefined; } + fileExists(fileName: string): boolean { return typeof this.getEntry(fileName) === 'string'; } - read(fileName: string): string|undefined { + directoryExists(path: string): boolean { return typeof this.getEntry(path) === 'object' } + + readFile(fileName: string): string|undefined { let data = this.getEntry(fileName); if (typeof data === 'string') { return data; @@ -27,7 +29,7 @@ export class MockContext implements ReflectorHostContext { return undefined; } - write(fileName: string, data: string): void { + writeFile(fileName: string, data: string): void { let parts = fileName.split('/'); let name = parts.pop(); let entry = this.getEntry(parts); @@ -36,6 +38,8 @@ export class MockContext implements ReflectorHostContext { } } + assumeFileExists(fileName: string): void { this.writeFile(fileName, ''); } + getEntry(fileName: string|string[]): Entry|undefined { let parts = typeof fileName === 'string' ? fileName.split('/') : fileName; if (parts[0]) { @@ -79,16 +83,18 @@ function normalize(parts: string[]): string[] { export class MockCompilerHost implements ts.CompilerHost { constructor(private context: MockContext) {} - fileExists(fileName: string): boolean { return this.context.exists(fileName); } + fileExists(fileName: string): boolean { return this.context.fileExists(fileName); } - readFile(fileName: string): string { return this.context.read(fileName); } + readFile(fileName: string): string { return this.context.readFile(fileName); } - directoryExists(directoryName: string): boolean { return this.context.exists(directoryName); } + directoryExists(directoryName: string): boolean { + return this.context.directoryExists(directoryName); + } getSourceFile( fileName: string, languageVersion: ts.ScriptTarget, onError?: (message: string) => void): ts.SourceFile { - let sourceText = this.context.read(fileName); + let sourceText = this.context.readFile(fileName); if (sourceText) { return ts.createSourceFile(fileName, sourceText, languageVersion); } else { @@ -100,7 +106,7 @@ export class MockCompilerHost implements ts.CompilerHost { return ts.getDefaultLibFileName(options); } - writeFile: ts.WriteFileCallback = (fileName, text) => { this.context.write(fileName, text); } + writeFile: ts.WriteFileCallback = (fileName, text) => { this.context.writeFile(fileName, text); } getCurrentDirectory(): string { return this.context.currentDirectory;