From ebe438d8dee65930d3c9bc70f1865e1766a41704 Mon Sep 17 00:00:00 2001 From: chrisramsey Date: Tue, 29 Mar 2016 15:03:36 -0500 Subject: [PATCH 1/3] feature: adds public folder --- .../blueprints/ng2/files/public/.gitignore | 0 .../blueprints/ng2/files/public/.placeholder | 0 addon/ng2/commands/version.ts | 16 +- lib/broccoli/angular2-app.js | 13 +- lib/broccoli/broccoli-typescript.js | 364 ++++++++---------- lib/cli/index.js | 7 +- tests/e2e/e2e_workflow.spec.js | 17 + 7 files changed, 206 insertions(+), 211 deletions(-) create mode 100644 addon/ng2/blueprints/ng2/files/public/.gitignore create mode 100644 addon/ng2/blueprints/ng2/files/public/.placeholder diff --git a/addon/ng2/blueprints/ng2/files/public/.gitignore b/addon/ng2/blueprints/ng2/files/public/.gitignore new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/addon/ng2/blueprints/ng2/files/public/.placeholder b/addon/ng2/blueprints/ng2/files/public/.placeholder new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/addon/ng2/commands/version.ts b/addon/ng2/commands/version.ts index 20989468b6b3..5c34b91af81c 100644 --- a/addon/ng2/commands/version.ts +++ b/addon/ng2/commands/version.ts @@ -1,6 +1,6 @@ import * as Command from 'ember-cli/lib/models/command'; import * as path from 'path'; - +import * as child_process from 'child_process'; const VersionCommand = Command.extend({ name: 'version', @@ -21,7 +21,19 @@ const VersionCommand = Command.extend({ var alwaysPrint = ['node', 'os']; - this.printVersion('angular-cli', pkg.version); + var ngCliVersion = pkg.version; + if (!__dirname.match(/node_modules/)) { + var gitBranch = '??'; + try { + var gitRefName = '' + child_process.execSync('git symbolic-ref HEAD', {cwd: __dirname}); + gitBranch = path.basename(gitRefName.replace('\n', '')); + } catch (e) { + } + + ngCliVersion = `local (v${pkg.version}, branch: ${gitBranch})`; + } + + this.printVersion('angular-cli', ngCliVersion); for (var module in versions) { if (options.verbose || alwaysPrint.indexOf(module) > -1) { diff --git a/lib/broccoli/angular2-app.js b/lib/broccoli/angular2-app.js index 6b02cd3a468c..725b62d6b167 100644 --- a/lib/broccoli/angular2-app.js +++ b/lib/broccoli/angular2-app.js @@ -1,6 +1,6 @@ var path = require('path'); var configReplace = require('./broccoli-config-replace'); -var compileWithTypescript = require('./broccoli-typescript').default; +var compileWithTypescript = require('./broccoli-typescript'); var SwManifest = require('./service-worker-manifest').default; var fs = require('fs'); var Funnel = require('broccoli-funnel'); @@ -71,11 +71,6 @@ Angular2App.prototype.toTree = function () { exclude: ['*.d.ts', 'tsconfig.json'] }); - var tsSrcTree = new Funnel(sourceDir, { - include: ['**/*.ts'], - allowEmpty: true - }); - var jsTree = new Funnel(sourceDir, { include: ['**/*.js'], allowEmpty: true @@ -92,11 +87,15 @@ Angular2App.prototype.toTree = function () { destDir: 'vendor' }); + var publicDirTree = new Funnel('public', { + allowEmpty: true + }); + var merged = mergeTrees([ assetTree, - tsSrcTree, tsTree, jsTree, + publicDirTree, this.index(), vendorNpmTree ], { overwrite: true }); diff --git a/lib/broccoli/broccoli-typescript.js b/lib/broccoli/broccoli-typescript.js index 003fd2dcfc0d..163a8e362fd4 100644 --- a/lib/broccoli/broccoli-typescript.js +++ b/lib/broccoli/broccoli-typescript.js @@ -1,32 +1,16 @@ -/*eslint-disable no-console */ - -/// 'use strict'; + const Plugin = require('broccoli-caching-writer'); -var fs = require('fs'); -var fse = require('fs-extra'); -var path = require('path'); -var ts = require('typescript'); -var FS_OPTS = { +const fs = require('fs'); +const fse = require('fs-extra'); +const path = require('path'); +const ts = require('typescript'); + +const FS_OPTS = { encoding: 'utf-8' }; -// Sub-directory where the @internal typing files (.d.ts) are stored -exports.INTERNAL_TYPINGS_PATH = 'internal_typings'; -// Monkey patch the TS compiler to be able to re-emit files with @internal symbols -var tsEmitInternal = false; -var originalEmitFiles = ts.emitFiles; -ts.emitFiles = function (resolver, host, targetSourceFile) { - if (tsEmitInternal) { - var orignalgetCompilerOptions_1 = host.getCompilerOptions; - host.getCompilerOptions = function () { - var options = clone(orignalgetCompilerOptions_1.call(host)); - options.stripInternal = false; - options.outDir = options.outDir + '/' + exports.INTERNAL_TYPINGS_PATH; - return options; - }; - } - return originalEmitFiles(resolver, host, targetSourceFile); -}; + + /** * Broccoli plugin that implements incremental Typescript compiler. * @@ -37,90 +21,80 @@ ts.emitFiles = function (resolver, host, targetSourceFile) { * re-emitted. This primarily affects code that uses `const enum`s, because changing the enum value * requires global emit, which can affect many files. */ -class DiffingTSCompiler extends Plugin { +class BroccoliTypeScriptCompiler extends Plugin { constructor(inputPath, options) { super([inputPath], {}); - this.options = options; - this.fileRegistry = Object.create(null); - this.firstRun = true; - this.previousRunFailed = false; - // Whether to generate the @internal typing files (they are only generated when `stripInternal` is - // true) - this.genInternalTypings = false; - if (options.files) { - this.rootFilePaths = options.files.splice(0); - } else { - this.rootFilePaths = []; - } - if (options.internalTypings) { - this.genInternalTypings = true; - delete options.internalTypings; - } - } + this._fileRegistry = Object.create(null); + this._rootfilePaths = []; + this._tsOpts = null; + this._tsServiceHost = null; + this._tsService = null; - createServiceHost() { - // the conversion is a bit awkward, see https://github.com/Microsoft/TypeScript/issues/5276 - // in 1.8 use convertCompilerOptionsFromJson - this.tsOpts = ts.parseJsonConfigFileContent(this.options, null, null).options; - if (this.tsOpts.stripInternal === false) { - // @internal are included in the generated .d.ts, do not generate them separately - this.genInternalTypings = false; + this._options = options; + if (options.files) { + this._rootFilePaths = options.files.splice(0); } - this.tsOpts.rootDir = ''; - this.tsOpts.outDir = ''; - - this.tsServiceHost = new CustomLanguageServiceHost( - this.tsOpts, this.rootFilePaths, this.fileRegistry, this.inputPaths[0]); - this.tsService = ts.createLanguageService(this.tsServiceHost, ts.createDocumentRegistry()); } build() { - if (!this.tsServiceHost) { - this.createServiceHost(); - this.doFullBuild(); - return; + if (!this._tsServiceHost) { + this._createServiceHost(); + this._doFullBuild(); + } else { + this._doIncrementalBuild(); } + } - var _this = this; + _doIncrementalBuild() { var pathsWithErrors = []; var errorMessages = []; - var pathsEmitted = []; var entries = this.listEntries(); + const inputPath = this.inputPaths[0]; - entries.forEach(function (entry) { - const tsFilePath = path.join(_this.inputPaths[0], entry.relativePath); - // const entry = entries.filter(e => e.relativePath == tsFilePath)[0]; - if (!tsFilePath.match(/\.ts$/)) { + entries.forEach(entry => { + const tsFilePath = path.join(inputPath, entry.relativePath); + if (!tsFilePath.match(/\.ts$/) || !fs.existsSync(tsFilePath)) { return; } - if (!_this.fileRegistry[tsFilePath]) { - _this.fileRegistry[tsFilePath] = { version: entry.mtime }; - } else if (_this.fileRegistry[tsFilePath].version >= entry.mtime) { - // Nothing to do for this file. Just reoutput. + + if (!this._fileRegistry[tsFilePath]) { + // Not in the registry? Add it. + this._addNewFileEntry(entry); + + // We need to add the file to the rootFiles as well, as otherwise it _might_ + // not get compiled. It needs to be referenced at some point, and unless we + // add the spec files first (which we don't know the order), it won't. + // So make every new files an entry point instead. + // TODO(hansl): We should rather build a list and recreate the program only once. + // We need to investigate if we should emit files that are not + // referenced. This doesn't take that into account. + this._tsServiceHost.fileNames.push(tsFilePath); + + // Force the TS Service to recreate the program (ie. call synchronizeHostData). + this._tsServiceHost.projectVersion++; + } else if (this._fileRegistry[tsFilePath].version >= entry.mtime) { + // Nothing to do for this file. Just link the cached outputs. + this._fileRegistry[tsFilePath].outputs.forEach(absoluteFilePath => { + const outputFilePath = absoluteFilePath.replace(this.cachePath, this.outputPath); + fse.mkdirsSync(path.dirname(outputFilePath)); + fs.linkSync(absoluteFilePath, outputFilePath); + }); + return; } else { - _this.fileRegistry[tsFilePath].version = entry.mtime; + this._fileRegistry[tsFilePath].version = entry.mtime; } - pathsEmitted.push(tsFilePath); - var output = _this.tsService.getEmitOutput(tsFilePath); + var output = this._tsService.getEmitOutput(tsFilePath); if (output.emitSkipped) { - var errorFound = _this.collectErrors(tsFilePath); + var errorFound = this.collectErrors(tsFilePath); if (errorFound) { pathsWithErrors.push(tsFilePath); errorMessages.push(errorFound); } } else { - output.outputFiles.forEach(function (o) { - var filePath = o.name; - if (path.isAbsolute(filePath)) { - filePath = filePath.replace(_this.inputPaths[0], _this.outputPath); - } else { - filePath = path.join(_this.outputPath, filePath); - } - var destDirPath = path.dirname(filePath); - fse.mkdirsSync(destDirPath); - fs.writeFileSync(filePath, _this.fixSourceMapSources(o.text), FS_OPTS); + output.outputFiles.forEach(o => { + this._outputFile(o.name, o.text, this._fileRegistry[tsFilePath]); }); } }); @@ -131,39 +105,28 @@ class DiffingTSCompiler extends Plugin { error['showStack'] = false; throw error; } else if (this.previousRunFailed) { - this.doFullBuild(); - } else if (this.genInternalTypings) { - // serialize the .d.ts files containing @internal symbols - tsEmitInternal = true; - pathsEmitted.forEach(function (tsFilePath) { - var output = _this.tsService.getEmitOutput(tsFilePath); - if (!output.emitSkipped) { - output.outputFiles.forEach(function (o) { - var filePath = o.name; - if (path.isAbsolute(filePath)) { - filePath = filePath.replace(_this.inputPaths[0], _this.outputPath); - } else { - filePath = path.join(_this.outputPath, filePath); - } - console.log(4, filePath); - if (endsWith(filePath, '.d.ts')) { - var destDirPath = path.dirname(filePath); - fse.mkdirsSync(destDirPath); - fs.writeFileSync(filePath, _this.fixSourceMapSources(o.text), FS_OPTS); - } - }); - } - }); - tsEmitInternal = false; + this._doFullBuild(); } } + _createServiceHost() { + // the conversion is a bit awkward, see https://github.com/Microsoft/TypeScript/issues/5276 + // in 1.8 use convertCompilerOptionsFromJson + this._tsOpts = ts.parseJsonConfigFileContent(this._options, null, null).options; + this._tsOpts.rootDir = ''; + this._tsOpts.outDir = ''; + + this._tsServiceHost = new CustomLanguageServiceHost( + this._tsOpts, this._rootFilePaths, this._fileRegistry, this.inputPaths[0]); + this._tsService = ts.createLanguageService(this._tsServiceHost, ts.createDocumentRegistry()); + } + collectErrors(tsFilePath) { - var allDiagnostics = this.tsService.getCompilerOptionsDiagnostics() - .concat(this.tsService.getSyntacticDiagnostics(tsFilePath)) - .concat(this.tsService.getSemanticDiagnostics(tsFilePath)); + var allDiagnostics = this._tsService.getCompilerOptionsDiagnostics() + .concat(this._tsService.getSyntacticDiagnostics(tsFilePath)) + .concat(this._tsService.getSemanticDiagnostics(tsFilePath)); var errors = []; - allDiagnostics.forEach(function (diagnostic) { + allDiagnostics.forEach(diagnostic => { var message = ts.flattenDiagnosticMessageText(diagnostic.messageText, '\n'); if (diagnostic.file) { var _a = diagnostic.file.getLineAndCharacterOfPosition(diagnostic.start), line = _a.line, character = _a.character; @@ -177,52 +140,74 @@ class DiffingTSCompiler extends Plugin { } } - doFullBuild() { - var _this = this; - var program = this.tsService.getProgram(); - tsEmitInternal = false; - var emitResult = program.emit(undefined, (absoluteFilePath, fileContent) => { - absoluteFilePath = path.resolve(this.outputPath, absoluteFilePath); - // Replace the input path by the output. - absoluteFilePath = absoluteFilePath.replace(this.inputPaths[0], this.outputPath); - fse.mkdirsSync(path.dirname(absoluteFilePath)); - fs.writeFileSync(absoluteFilePath, _this.fixSourceMapSources(fileContent), FS_OPTS); - }); - if (this.genInternalTypings) { - // serialize the .d.ts files containing @internal symbols - tsEmitInternal = true; - program.emit(undefined, function (absoluteFilePath, fileContent) { - absoluteFilePath = path.resolve(this.outputPath, absoluteFilePath); - // Replace the input path by the output. - absoluteFilePath = absoluteFilePath.replace(this.inputPaths[0], this.outputPath); - if (endsWith(absoluteFilePath, '.d.ts')) { - fse.mkdirsSync(path.dirname(absoluteFilePath)); - fs.writeFileSync(absoluteFilePath, fileContent, FS_OPTS); - } + _doFullBuild() { + var program = this._tsService.getProgram(); + + // Add file registry. + var allFiles = program.getSourceFiles(); + + // Find the entry, update the registry. + let allEntries = this.listEntries(); + allEntries.forEach(entry => this._addNewFileEntry(entry)); + + allFiles.forEach(sourceFile => { + const registry = this._fileRegistry[path.resolve(this.inputPaths[0], sourceFile.fileName)]; + const emitResult = program.emit(sourceFile, (absoluteFilePath, fileContent) => { + this._outputFile(absoluteFilePath, fileContent, registry); }); - tsEmitInternal = false; - } - if (emitResult.emitSkipped) { - var allDiagnostics = ts.getPreEmitDiagnostics(program).concat(emitResult.diagnostics); - var errorMessages_1 = []; - allDiagnostics.forEach(function (diagnostic) { - var pos = ''; - if (diagnostic.file) { - var _a = diagnostic.file.getLineAndCharacterOfPosition(diagnostic.start), line = _a.line, character = _a.character; - pos = diagnostic.file.fileName + ' (' + (line + 1) + ', ' + (character + 1) + '): '; + + if (emitResult.emitSkipped) { + var allDiagnostics = ts.getPreEmitDiagnostics(program).concat(emitResult.diagnostics); + var errorMessages_1 = []; + allDiagnostics.forEach(function (diagnostic) { + var pos = ''; + if (diagnostic.file) { + var _a = diagnostic.file.getLineAndCharacterOfPosition(diagnostic.start), line = _a.line, character = _a.character; + pos = diagnostic.file.fileName + ' (' + (line + 1) + ', ' + (character + 1) + '): '; + } + var message = ts.flattenDiagnosticMessageText(diagnostic.messageText, '\n'); + errorMessages_1.push(' ' + pos + message); + }); + if (errorMessages_1.length) { + this.previousRunFailed = true; + var error = new Error('Typescript found the following errors:\n' + errorMessages_1.join('\n')); + error['showStack'] = false; + throw error; + } else { + this.previousRunFailed = false; } - var message = ts.flattenDiagnosticMessageText(diagnostic.messageText, '\n'); - errorMessages_1.push(' ' + pos + message); - }); - if (errorMessages_1.length) { - this.previousRunFailed = true; - var error = new Error('Typescript found the following errors:\n' + errorMessages_1.join('\n')); - error['showStack'] = false; - throw error; - } else { - this.previousRunFailed = false; } + }); + } + + _outputFile(absoluteFilePath, fileContent, registry) { + absoluteFilePath = path.resolve(this.cachePath, absoluteFilePath); + // Replace the input path by the output. + absoluteFilePath = absoluteFilePath.replace(this.inputPaths[0], this.cachePath); + const outputFilePath = absoluteFilePath.replace(this.cachePath, this.outputPath); + + if (registry) { + registry.outputs.add(absoluteFilePath); } + + fse.mkdirsSync(path.dirname(absoluteFilePath)); + const content = this.fixSourceMapSources(fileContent); + fs.writeFileSync(absoluteFilePath, content, FS_OPTS); + + fse.mkdirsSync(path.dirname(outputFilePath)); + fs.linkSync(absoluteFilePath, outputFilePath); + } + + _addNewFileEntry(entry) { + const p = path.join(this.inputPaths[0], entry.relativePath); + if (this._fileRegistry[p]) { + throw new Error('Trying to add a new entry to an already existing one: ' + p); + } + + this._fileRegistry[p] = { + version: entry.mtime, + outputs: new Set() + }; } /** @@ -251,38 +236,31 @@ class DiffingTSCompiler extends Plugin { return content; } } - - removeOutputFor(tsFilePath) { - var absoluteJsFilePath = path.join(this.outputPath, tsFilePath.replace(/\.ts$/, '.js')); - var absoluteMapFilePath = path.join(this.outputPath, tsFilePath.replace(/.ts$/, '.js.map')); - var absoluteDtsFilePath = path.join(this.outputPath, tsFilePath.replace(/\.ts$/, '.d.ts')); - if (fs.existsSync(absoluteJsFilePath)) { - fs.unlinkSync(absoluteJsFilePath); - if (fs.existsSync(absoluteMapFilePath)) { - // source map could be inline or not generated - fs.unlinkSync(absoluteMapFilePath); - } - fs.unlinkSync(absoluteDtsFilePath); - } - } } -var CustomLanguageServiceHost = (function () { - function CustomLanguageServiceHost(compilerOptions, fileNames, fileRegistry, treeInputPath) { +class CustomLanguageServiceHost { + constructor(compilerOptions, fileNames, fileRegistry, treeInputPath) { this.compilerOptions = compilerOptions; this.fileNames = fileNames; this.fileRegistry = fileRegistry; this.treeInputPath = treeInputPath; this.currentDirectory = treeInputPath; this.defaultLibFilePath = ts.getDefaultLibFilePath(compilerOptions).replace(/\\/g, '/'); + this.projectVersion = 0; } - CustomLanguageServiceHost.prototype.getScriptFileNames = function () { + getScriptFileNames() { return this.fileNames; - }; - CustomLanguageServiceHost.prototype.getScriptVersion = function (fileName) { + } + + getScriptVersion(fileName) { return this.fileRegistry[fileName] && this.fileRegistry[fileName].version.toString(); - }; + } + + getProjectVersion() { + return this.projectVersion.toString(); + } + /** * This method is called quite a bit to lookup 3 kinds of paths: * 1/ files in the fileRegistry @@ -300,7 +278,7 @@ var CustomLanguageServiceHost = (function () { * In the initial experiments the impact of this caching was insignificant (single digit %) and * not worth the potential issues with stale cache records. */ - CustomLanguageServiceHost.prototype.getScriptSnapshot = function (tsFilePath) { + getScriptSnapshot(tsFilePath) { var absoluteTsFilePath; if (tsFilePath == this.defaultLibFilePath || path.isAbsolute(tsFilePath)) { absoluteTsFilePath = tsFilePath; @@ -317,33 +295,23 @@ var CustomLanguageServiceHost = (function () { // so we we just return undefined when the path is not correct. return undefined; } + return ts.ScriptSnapshot.fromString(fs.readFileSync(absoluteTsFilePath, FS_OPTS)); - }; - CustomLanguageServiceHost.prototype.getCurrentDirectory = function () { + } + + getCurrentDirectory() { return this.currentDirectory; - }; - CustomLanguageServiceHost.prototype.getCompilationSettings = function () { + } + + getCompilationSettings() { return this.compilerOptions; - }; - CustomLanguageServiceHost.prototype.getDefaultLibFileName = function () { + } + + getDefaultLibFileName(/* options */) { // ignore options argument, options should not change during the lifetime of the plugin return this.defaultLibFilePath; - }; - return CustomLanguageServiceHost; -}()); - - -exports.__esModule = true; -exports['default'] = DiffingTSCompiler; - -function clone(object) { - var result = {}; - for (var id in object) { - result[id] = object[id]; } - return result; -} -function endsWith(str, substring) { - return str.indexOf(substring, str.length - substring.length) !== -1; } -//# sourceMappingURL=broccoli-typescript.js.map + + +module.exports = BroccoliTypeScriptCompiler; diff --git a/lib/cli/index.js b/lib/cli/index.js index 3dbe261cb92b..98ad728fd8ea 100644 --- a/lib/cli/index.js +++ b/lib/cli/index.js @@ -1,17 +1,16 @@ /*eslint-disable no-console */ - const cli = require('ember-cli/lib/cli'); const path = require('path'); - // This file hooks up on require calls to transpile TypeScript. const fs = require('fs'); const ts = require('typescript'); const old = require.extensions['.ts']; -require.extensions['.ts'] = function (m, filename) { +require.extensions['.ts'] = function(m, filename) { // If we're in node module, either call the old hook or simply compile the // file without transpilation. We do not touch node_modules/**. + // We do touch `angular-cli` files anywhere though. if (!filename.match(/angular-cli/) && filename.match(/node_modules/)) { if (old) { return old(m, filename); @@ -38,7 +37,7 @@ require.extensions['.ts'] = function (m, filename) { }; -module.exports = function (options) { +module.exports = function(options) { const oldStdoutWrite = process.stdout.write; process.stdout.write = function (line) { line = line.toString(); diff --git a/tests/e2e/e2e_workflow.spec.js b/tests/e2e/e2e_workflow.spec.js index 21d7c36d5c8c..4768afadd545 100644 --- a/tests/e2e/e2e_workflow.spec.js +++ b/tests/e2e/e2e_workflow.spec.js @@ -176,6 +176,23 @@ describe('Basic end-to-end Workflow', function () { }); }); + + it('moves all files that live inside `public` into `dist`', function () { + this.timeout(420000); + + const tmpFile = path.join(process.cwd(), 'public', 'test.abc'); + const tmpFileLocation = path.join(process.cwd(), 'dist', 'test.abc'); + fs.writeFileSync(tmpFile, 'hello world'); + + return ng(['build', '--silent']) + .then(function () { + expect(existsSync(tmpFileLocation)); + }) + .catch(err => { + throw new Error(err) + }); + }); + it('Turn on `noImplicitAny` in tsconfig.json and rebuild', function (done) { this.timeout(420000); From 0714c41475d951ce658c5c6d9f4a80c48d739085 Mon Sep 17 00:00:00 2001 From: Hans Larsen Date: Tue, 29 Mar 2016 17:11:20 -0700 Subject: [PATCH 2/3] fix: regenerate the program on file change, and only once per rerun --- lib/broccoli/broccoli-typescript.js | 41 ++++++++++++++++++----------- 1 file changed, 25 insertions(+), 16 deletions(-) diff --git a/lib/broccoli/broccoli-typescript.js b/lib/broccoli/broccoli-typescript.js index 163a8e362fd4..e0a5bcda13ff 100644 --- a/lib/broccoli/broccoli-typescript.js +++ b/lib/broccoli/broccoli-typescript.js @@ -52,6 +52,8 @@ class BroccoliTypeScriptCompiler extends Plugin { var entries = this.listEntries(); const inputPath = this.inputPaths[0]; + const pathsToEmit = []; + entries.forEach(entry => { const tsFilePath = path.join(inputPath, entry.relativePath); if (!tsFilePath.match(/\.ts$/) || !fs.existsSync(tsFilePath)) { @@ -66,13 +68,11 @@ class BroccoliTypeScriptCompiler extends Plugin { // not get compiled. It needs to be referenced at some point, and unless we // add the spec files first (which we don't know the order), it won't. // So make every new files an entry point instead. - // TODO(hansl): We should rather build a list and recreate the program only once. - // We need to investigate if we should emit files that are not + // TODO(hansl): We need to investigate if we should emit files that are not // referenced. This doesn't take that into account. this._tsServiceHost.fileNames.push(tsFilePath); - // Force the TS Service to recreate the program (ie. call synchronizeHostData). - this._tsServiceHost.projectVersion++; + pathsToEmit.push(tsFilePath); } else if (this._fileRegistry[tsFilePath].version >= entry.mtime) { // Nothing to do for this file. Just link the cached outputs. this._fileRegistry[tsFilePath].outputs.forEach(absoluteFilePath => { @@ -83,21 +83,29 @@ class BroccoliTypeScriptCompiler extends Plugin { return; } else { this._fileRegistry[tsFilePath].version = entry.mtime; + pathsToEmit.push(tsFilePath); } + }); - var output = this._tsService.getEmitOutput(tsFilePath); - if (output.emitSkipped) { - var errorFound = this.collectErrors(tsFilePath); - if (errorFound) { - pathsWithErrors.push(tsFilePath); - errorMessages.push(errorFound); + if (pathsToEmit.length > 0) { + // Force the TS Service to recreate the program (ie. call synchronizeHostData). + this._tsServiceHost.projectVersion++; + + pathsToEmit.forEach(tsFilePath => { + var output = this._tsService.getEmitOutput(tsFilePath); + if (output.emitSkipped) { + var errorFound = this.collectErrors(tsFilePath); + if (errorFound) { + pathsWithErrors.push(tsFilePath); + errorMessages.push(errorFound); + } + } else { + output.outputFiles.forEach(o => { + this._outputFile(o.name, o.text, this._fileRegistry[tsFilePath]); + }); } - } else { - output.outputFiles.forEach(o => { - this._outputFile(o.name, o.text, this._fileRegistry[tsFilePath]); - }); - } - }); + }); + } if (pathsWithErrors.length) { this.previousRunFailed = true; @@ -254,6 +262,7 @@ class CustomLanguageServiceHost { } getScriptVersion(fileName) { + fileName = path.resolve(this.treeInputPath, fileName); return this.fileRegistry[fileName] && this.fileRegistry[fileName].version.toString(); } From d09eba5ba48bcc459fe155ebaa2fa8ae333058da Mon Sep 17 00:00:00 2001 From: chrisramsey Date: Tue, 29 Mar 2016 20:44:35 -0500 Subject: [PATCH 3/3] Removing placeholder file --- addon/ng2/blueprints/ng2/files/public/.placeholder | 0 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 addon/ng2/blueprints/ng2/files/public/.placeholder diff --git a/addon/ng2/blueprints/ng2/files/public/.placeholder b/addon/ng2/blueprints/ng2/files/public/.placeholder deleted file mode 100644 index e69de29bb2d1..000000000000