From c97acf84df746fc03f71964cd4ecbb9597f9771e Mon Sep 17 00:00:00 2001 From: ezolenko Date: Sat, 4 Mar 2017 16:43:04 -0700 Subject: [PATCH 1/3] - update dependencies --- package.json | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/package.json b/package.json index adefa98..b5a3bb4 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "rollup-plugin-typescript2", - "version": "0.1.2", + "version": "0.1.3", "description": "Seamless integration between Rollup and TypeScript. Now with errors.", "main": "dist/rollup-plugin-typescript2.cjs.js", "module": "dist/rollup-plugin-typescript2.es.js", @@ -29,14 +29,14 @@ "lodash": "^4.17.4", "object-hash": "^1.1.5", "rollup-pluginutils": "^2.0.1", - "tslib": "^1.5.0" + "tslib": "^1.6.0" }, "peerDependencies": { "typescript": "^2.0", "tslib": "^1.5.0" }, "devDependencies": { - "rollup-plugin-typescript2": "^0.1.0", + "rollup-plugin-typescript2": "^0.1.2", "@types/colors": "^1.1.1", "@types/fs-extra": "0.0.37", "@types/graphlib": "^2.1.3", @@ -45,8 +45,8 @@ "@types/object-hash": "^0.5.28", "rimraf": "^2.5.4", "rollup": "^0.41.4", - "tslint": "^4.4.2", - "typescript": "^2.1.5" + "tslint": "^4.5.1", + "typescript": "^2.2.1" }, "repository": { "type": "git", From 903bd3fbf92cfa4386057ab404503c6cb56e84c7 Mon Sep 17 00:00:00 2001 From: ezolenko Date: Sat, 4 Mar 2017 16:59:55 -0700 Subject: [PATCH 2/3] - vscode settings --- .vscode/settings.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.vscode/settings.json b/.vscode/settings.json index 90e1422..a7201b0 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,4 +1,5 @@ { "editor.tabSize": 4, - "editor.useTabStops": true + "editor.useTabStops": true, + "editor.dragAndDrop": true } \ No newline at end of file From 883cee62bb98b30e265c400979d7ba5d87ef248a Mon Sep 17 00:00:00 2001 From: ezolenko Date: Sat, 4 Mar 2017 18:50:39 -0700 Subject: [PATCH 3/3] - better diagnostics treatment --- README.md | 29 ++++- dist/rollup-plugin-typescript2.cjs.js | 154 +++++++++++++++++++------ dist/rollup-plugin-typescript2.es.js | 158 +++++++++++++++++++------- package.json | 2 +- src/cache.ts | 80 ++++++++----- src/index.ts | 90 +++++++++++---- src/rollupcontext.ts | 40 +++++++ 7 files changed, 422 insertions(+), 131 deletions(-) create mode 100644 src/rollupcontext.ts diff --git a/README.md b/README.md index 6f475ee..4daffe1 100644 --- a/README.md +++ b/README.md @@ -33,18 +33,35 @@ Following compiler options are forced though: * `noResolve`: false Plugin takes following options: + * `check`: true - - set to false to avoid doing any diagnostic checks on the code + + Set to false to avoid doing any diagnostic checks on the code. + * `verbosity`: 2 - - goes up to 3 + + Goes up to 3. + * `clean`: false - - set to true for clean build (wipes out cache) + + Set to true for clean build (wipes out cache on every build). + * `cacheRoot`: ".rts2_cache" - - path to cache + + Path to cache. + * `include`: `[ "*.ts+(|x)", "**/*.ts+(|x)" ]` - - passes all .ts files through typescript compiler. + + Passes all .ts files through typescript compiler. + * `exclude`: `[ "*.d.ts", "**/*.d.ts" ]` - - but not types + + But excludes types. + +* `abortOnError`: true + + Bail out on first syntactic error. Im most cases setting this to false will result in exception in rollup itself. + ### TypeScript version This plugin currently requires TypeScript 2.0+. diff --git a/dist/rollup-plugin-typescript2.cjs.js b/dist/rollup-plugin-typescript2.cjs.js index b9f42b7..83efcb6 100644 --- a/dist/rollup-plugin-typescript2.cjs.js +++ b/dist/rollup-plugin-typescript2.cjs.js @@ -71,6 +71,40 @@ var ConsoleContext = (function () { return ConsoleContext; }()); +var RollupContext = (function () { + function RollupContext(verbosity, bail, context, prefix) { + if (prefix === void 0) { prefix = ""; } + this.verbosity = verbosity; + this.bail = bail; + this.context = context; + this.prefix = prefix; + } + RollupContext.prototype.warn = function (message) { + if (this.verbosity < VerbosityLevel.Warning) + return; + this.context.warn("" + this.prefix + message); + }; + RollupContext.prototype.error = function (message) { + if (this.verbosity < VerbosityLevel.Error) + return; + if (this.bail) + this.context.error("" + this.prefix + message); + else + this.context.warn("" + this.prefix + message); + }; + RollupContext.prototype.info = function (message) { + if (this.verbosity < VerbosityLevel.Info) + return; + this.context.warn("" + this.prefix + message); + }; + RollupContext.prototype.debug = function (message) { + if (this.verbosity < VerbosityLevel.Debug) + return; + this.context.warn("" + this.prefix + message); + }; + return RollupContext; +}()); + var LanguageServiceHost = (function () { function LanguageServiceHost(parsedConfig) { this.parsedConfig = parsedConfig; @@ -175,15 +209,33 @@ var RollingCache = (function () { return RollingCache; }()); +function convertDiagnostic(data) { + return _.map(data, function (diagnostic) { + var entry = { + flatMessage: ts.flattenDiagnosticMessageText(diagnostic.messageText, "\n"), + category: diagnostic.category, + }; + if (diagnostic.file) { + var _a = diagnostic.file.getLineAndCharacterOfPosition(diagnostic.start), line = _a.line, character = _a.character; + entry.fileLine = diagnostic.file.fileName + " (" + (line + 1) + "," + (character + 1) + ")"; + } + return entry; + }); +} var Cache = (function () { function Cache(host, cache, options, rootFilenames, context) { var _this = this; this.host = host; this.options = options; this.context = context; - this.cacheVersion = "1"; + this.cacheVersion = "2"; this.ambientTypesDirty = false; - this.cacheDir = cache + "/" + hash.sha1({ version: this.cacheVersion, rootFilenames: rootFilenames, options: this.options }); + this.cacheDir = cache + "/" + hash.sha1({ + version: this.cacheVersion, + rootFilenames: rootFilenames, + options: this.options, + tsVersion: ts.version, + }); this.dependencyTree = new graph.Graph({ directed: true }); this.dependencyTree.setDefaultNodeLabel(function (_node) { return { dirty: false }; }); this.ambientTypes = _.filter(rootFilenames, function (file) { return _.endsWith(file, ".d.ts"); }) @@ -221,7 +273,8 @@ var Cache = (function () { }; Cache.prototype.diagnosticsDone = function () { this.codeCache.roll(); - this.diagnosticsCache.roll(); + this.semanticDiagnosticsCache.roll(); + this.syntacticDiagnosticsCache.roll(); this.typesCache.roll(); }; Cache.prototype.getCompiled = function (id, snapshot, transform) { @@ -238,24 +291,31 @@ var Cache = (function () { this.codeCache.write(name, data); return data; }; - Cache.prototype.getDiagnostics = function (id, snapshot, check) { + Cache.prototype.getSyntacticDiagnostics = function (id, snapshot, check) { + return this.getDiagnostics(this.syntacticDiagnosticsCache, id, snapshot, check); + }; + Cache.prototype.getSemanticDiagnostics = function (id, snapshot, check) { + return this.getDiagnostics(this.semanticDiagnosticsCache, id, snapshot, check); + }; + Cache.prototype.getDiagnostics = function (cache, id, snapshot, check) { var name = this.makeName(id, snapshot); - if (!this.diagnosticsCache.exists(name) || this.isDirty(id, snapshot, true)) { + if (!cache.exists(name) || this.isDirty(id, snapshot, true)) { this.context.debug("fresh diagnostics for: " + id); - var data_2 = this.convert(check()); - this.diagnosticsCache.write(name, data_2); + var data_2 = convertDiagnostic(check()); + cache.write(name, data_2); this.markAsDirty(id, snapshot); return data_2; } this.context.debug("old diagnostics for: " + id); - var data = this.diagnosticsCache.read(name); - this.diagnosticsCache.write(name, data); + var data = cache.read(name); + cache.write(name, data); return data; }; Cache.prototype.init = function () { this.codeCache = new RollingCache(this.cacheDir + "/code", true); this.typesCache = new RollingCache(this.cacheDir + "/types", false); - this.diagnosticsCache = new RollingCache(this.cacheDir + "/diagnostics", false); + this.syntacticDiagnosticsCache = new RollingCache(this.cacheDir + "/syntacticDiagnostics", false); + this.semanticDiagnosticsCache = new RollingCache(this.cacheDir + "/semanticDiagnostics", false); }; Cache.prototype.markAsDirty = function (id, _snapshot) { this.context.debug("changed: " + id); @@ -286,18 +346,6 @@ var Cache = (function () { var data = snapshot.getText(0, snapshot.getLength()); return hash.sha1({ data: data, id: id }); }; - Cache.prototype.convert = function (data) { - return _.map(data, function (diagnostic) { - var entry = { - flatMessage: ts.flattenDiagnosticMessageText(diagnostic.messageText, "\n"), - }; - if (diagnostic.file) { - var _a = diagnostic.file.getLineAndCharacterOfPosition(diagnostic.start), line = _a.line, character = _a.character; - entry.fileLine = diagnostic.file.fileName + " (" + (line + 1) + "," + (character + 1) + ")"; - } - return entry; - }); - }; return Cache; }()); @@ -352,10 +400,27 @@ function parseTsConfig() { } function printDiagnostics(context, diagnostics) { _.each(diagnostics, function (diagnostic) { + var print; + var color; + switch (diagnostic.category) { + case ts.DiagnosticCategory.Message: + print = context.info; + color = colors.white; + break; + case ts.DiagnosticCategory.Error: + print = context.error; + color = colors.red; + break; + case ts.DiagnosticCategory.Warning: + default: + print = context.warn; + color = colors.yellow; + break; + } if (diagnostic.fileLine) - context.warn(diagnostic.fileLine + ": " + colors.yellow(diagnostic.flatMessage)); + print.call(context, [diagnostic.fileLine + ": " + color(diagnostic.flatMessage)]); else - context.warn(colors.yellow(diagnostic.flatMessage)); + print.call(context, [color(diagnostic.flatMessage)]); }); } @@ -368,6 +433,7 @@ function typescript(options) { cacheRoot: process.cwd() + "/.rts2_cache", include: ["*.ts+(|x)", "**/*.ts+(|x)"], exclude: ["*.d.ts", "**/*.d.ts"], + abortOnError: true, }); var filter$$1 = createFilter(options.include, options.exclude); var parsedConfig = parseTsConfig(); @@ -403,17 +469,21 @@ function typescript(options) { var _this = this; if (!filter$$1(id)) return undefined; + var contextWrapper = new RollupContext(options.verbosity, options.abortOnError, this, "rollup-plugin-typescript2: "); + contextWrapper.debug(id); var snapshot = servicesHost.setSnapshot(id, code); + // getting compiled file from cache of from ts var result = cache.getCompiled(id, snapshot, function () { var output = services.getEmitOutput(id); if (output.emitSkipped) { - var diagnostics = cache.getDiagnostics(id, snapshot, function () { - return services - .getCompilerOptionsDiagnostics() - .concat(services.getSyntacticDiagnostics(id)) - .concat(services.getSemanticDiagnostics(id)); - }); - printDiagnostics(_this, diagnostics); + if (options.check) { + var diagnostics = cache.getSyntacticDiagnostics(id, snapshot, function () { + return services.getSyntacticDiagnostics(id); + }); + contextWrapper.debug("printDiagnostics"); + printDiagnostics(contextWrapper, diagnostics); + } + // if no output was generated, aborting compilation _this.error(colors.red("failed to transpile " + id)); } var transpiled = _.find(output.outputFiles, function (entry) { return _.endsWith(entry.name, ".js"); }); @@ -423,11 +493,26 @@ function typescript(options) { map: map$$1 ? JSON.parse(map$$1.text) : { mappings: "" }, }; }); + // printing syntactic errors + if (options.check) { + var diagnostics = cache.getSyntacticDiagnostics(id, snapshot, function () { + return services.getSyntacticDiagnostics(id); + }); + contextWrapper.debug("printDiagnostics"); + printDiagnostics(contextWrapper, diagnostics); + } return result; }, + intro: function () { + context.debug("intro"); + // printing compiler option errors + if (options.check) + printDiagnostics(context, convertDiagnostic(services.getCompilerOptionsDiagnostics())); + }, outro: function () { context.debug("outro"); cache.compileDone(); + // printing semantic errors if (options.check) { cache.walkTree(function (id) { var snapshot = servicesHost.getScriptSnapshot(id); @@ -435,11 +520,8 @@ function typescript(options) { context.error(colors.red("failed lo load snapshot for " + id)); return; } - var diagnostics = cache.getDiagnostics(id, snapshot, function () { - return services - .getCompilerOptionsDiagnostics() - .concat(services.getSyntacticDiagnostics(id)) - .concat(services.getSemanticDiagnostics(id)); + var diagnostics = cache.getSemanticDiagnostics(id, snapshot, function () { + return services.getSemanticDiagnostics(id); }); printDiagnostics(context, diagnostics); }); diff --git a/dist/rollup-plugin-typescript2.es.js b/dist/rollup-plugin-typescript2.es.js index 0dc977c..175f9dc 100644 --- a/dist/rollup-plugin-typescript2.es.js +++ b/dist/rollup-plugin-typescript2.es.js @@ -1,7 +1,7 @@ /* eslint-disable */ import { emptyDirSync, ensureFile, ensureFileSync, existsSync, move, readFileSync, readJsonSync, readdirSync, remove, writeJson, writeJsonSync } from 'fs-extra'; import * as fs from 'fs-extra'; -import { ModuleKind, ScriptSnapshot, createDocumentRegistry, createLanguageService, flattenDiagnosticMessageText, getDefaultLibFilePath, nodeModuleNameResolver, parseConfigFileTextToJson, parseJsonConfigFileContent, sys } from 'typescript'; +import { DiagnosticCategory, ModuleKind, ScriptSnapshot, createDocumentRegistry, createLanguageService, flattenDiagnosticMessageText, getDefaultLibFilePath, nodeModuleNameResolver, parseConfigFileTextToJson, parseJsonConfigFileContent, sys, version } from 'typescript'; import * as ts from 'typescript'; import { defaults, each, endsWith, filter, find, has, isEqual, map, some } from 'lodash'; import * as _ from 'lodash'; @@ -11,7 +11,7 @@ import { sha1 } from 'object-hash'; import * as hash from 'object-hash'; import { dirname, sep } from 'path'; import * as path from 'path'; -import { red, yellow } from 'colors/safe'; +import { red, white, yellow } from 'colors/safe'; import * as colors from 'colors/safe'; /*! ***************************************************************************** @@ -76,6 +76,40 @@ var ConsoleContext = (function () { return ConsoleContext; }()); +var RollupContext = (function () { + function RollupContext(verbosity, bail, context, prefix) { + if (prefix === void 0) { prefix = ""; } + this.verbosity = verbosity; + this.bail = bail; + this.context = context; + this.prefix = prefix; + } + RollupContext.prototype.warn = function (message) { + if (this.verbosity < VerbosityLevel.Warning) + return; + this.context.warn("" + this.prefix + message); + }; + RollupContext.prototype.error = function (message) { + if (this.verbosity < VerbosityLevel.Error) + return; + if (this.bail) + this.context.error("" + this.prefix + message); + else + this.context.warn("" + this.prefix + message); + }; + RollupContext.prototype.info = function (message) { + if (this.verbosity < VerbosityLevel.Info) + return; + this.context.warn("" + this.prefix + message); + }; + RollupContext.prototype.debug = function (message) { + if (this.verbosity < VerbosityLevel.Debug) + return; + this.context.warn("" + this.prefix + message); + }; + return RollupContext; +}()); + var LanguageServiceHost = (function () { function LanguageServiceHost(parsedConfig) { this.parsedConfig = parsedConfig; @@ -180,15 +214,33 @@ var RollingCache = (function () { return RollingCache; }()); +function convertDiagnostic(data) { + return map(data, function (diagnostic) { + var entry = { + flatMessage: flattenDiagnosticMessageText(diagnostic.messageText, "\n"), + category: diagnostic.category, + }; + if (diagnostic.file) { + var _a = diagnostic.file.getLineAndCharacterOfPosition(diagnostic.start), line = _a.line, character = _a.character; + entry.fileLine = diagnostic.file.fileName + " (" + (line + 1) + "," + (character + 1) + ")"; + } + return entry; + }); +} var Cache = (function () { function Cache(host, cache, options, rootFilenames, context) { var _this = this; this.host = host; this.options = options; this.context = context; - this.cacheVersion = "1"; + this.cacheVersion = "2"; this.ambientTypesDirty = false; - this.cacheDir = cache + "/" + sha1({ version: this.cacheVersion, rootFilenames: rootFilenames, options: this.options }); + this.cacheDir = cache + "/" + sha1({ + version: this.cacheVersion, + rootFilenames: rootFilenames, + options: this.options, + tsVersion: version, + }); this.dependencyTree = new Graph({ directed: true }); this.dependencyTree.setDefaultNodeLabel(function (_node) { return { dirty: false }; }); this.ambientTypes = filter(rootFilenames, function (file) { return endsWith(file, ".d.ts"); }) @@ -226,7 +278,8 @@ var Cache = (function () { }; Cache.prototype.diagnosticsDone = function () { this.codeCache.roll(); - this.diagnosticsCache.roll(); + this.semanticDiagnosticsCache.roll(); + this.syntacticDiagnosticsCache.roll(); this.typesCache.roll(); }; Cache.prototype.getCompiled = function (id, snapshot, transform) { @@ -243,24 +296,31 @@ var Cache = (function () { this.codeCache.write(name, data); return data; }; - Cache.prototype.getDiagnostics = function (id, snapshot, check) { + Cache.prototype.getSyntacticDiagnostics = function (id, snapshot, check) { + return this.getDiagnostics(this.syntacticDiagnosticsCache, id, snapshot, check); + }; + Cache.prototype.getSemanticDiagnostics = function (id, snapshot, check) { + return this.getDiagnostics(this.semanticDiagnosticsCache, id, snapshot, check); + }; + Cache.prototype.getDiagnostics = function (cache, id, snapshot, check) { var name = this.makeName(id, snapshot); - if (!this.diagnosticsCache.exists(name) || this.isDirty(id, snapshot, true)) { + if (!cache.exists(name) || this.isDirty(id, snapshot, true)) { this.context.debug("fresh diagnostics for: " + id); - var data_2 = this.convert(check()); - this.diagnosticsCache.write(name, data_2); + var data_2 = convertDiagnostic(check()); + cache.write(name, data_2); this.markAsDirty(id, snapshot); return data_2; } this.context.debug("old diagnostics for: " + id); - var data = this.diagnosticsCache.read(name); - this.diagnosticsCache.write(name, data); + var data = cache.read(name); + cache.write(name, data); return data; }; Cache.prototype.init = function () { this.codeCache = new RollingCache(this.cacheDir + "/code", true); this.typesCache = new RollingCache(this.cacheDir + "/types", false); - this.diagnosticsCache = new RollingCache(this.cacheDir + "/diagnostics", false); + this.syntacticDiagnosticsCache = new RollingCache(this.cacheDir + "/syntacticDiagnostics", false); + this.semanticDiagnosticsCache = new RollingCache(this.cacheDir + "/semanticDiagnostics", false); }; Cache.prototype.markAsDirty = function (id, _snapshot) { this.context.debug("changed: " + id); @@ -291,18 +351,6 @@ var Cache = (function () { var data = snapshot.getText(0, snapshot.getLength()); return sha1({ data: data, id: id }); }; - Cache.prototype.convert = function (data) { - return map(data, function (diagnostic) { - var entry = { - flatMessage: flattenDiagnosticMessageText(diagnostic.messageText, "\n"), - }; - if (diagnostic.file) { - var _a = diagnostic.file.getLineAndCharacterOfPosition(diagnostic.start), line = _a.line, character = _a.character; - entry.fileLine = diagnostic.file.fileName + " (" + (line + 1) + "," + (character + 1) + ")"; - } - return entry; - }); - }; return Cache; }()); @@ -357,10 +405,27 @@ function parseTsConfig() { } function printDiagnostics(context, diagnostics) { each(diagnostics, function (diagnostic) { + var print; + var color; + switch (diagnostic.category) { + case DiagnosticCategory.Message: + print = context.info; + color = white; + break; + case DiagnosticCategory.Error: + print = context.error; + color = red; + break; + case DiagnosticCategory.Warning: + default: + print = context.warn; + color = yellow; + break; + } if (diagnostic.fileLine) - context.warn(diagnostic.fileLine + ": " + yellow(diagnostic.flatMessage)); + print.call(context, [diagnostic.fileLine + ": " + color(diagnostic.flatMessage)]); else - context.warn(yellow(diagnostic.flatMessage)); + print.call(context, [color(diagnostic.flatMessage)]); }); } @@ -373,6 +438,7 @@ function typescript(options) { cacheRoot: process.cwd() + "/.rts2_cache", include: ["*.ts+(|x)", "**/*.ts+(|x)"], exclude: ["*.d.ts", "**/*.d.ts"], + abortOnError: true, }); var filter$$1 = createFilter(options.include, options.exclude); var parsedConfig = parseTsConfig(); @@ -408,17 +474,21 @@ function typescript(options) { var _this = this; if (!filter$$1(id)) return undefined; + var contextWrapper = new RollupContext(options.verbosity, options.abortOnError, this, "rollup-plugin-typescript2: "); + contextWrapper.debug(id); var snapshot = servicesHost.setSnapshot(id, code); + // getting compiled file from cache of from ts var result = cache.getCompiled(id, snapshot, function () { var output = services.getEmitOutput(id); if (output.emitSkipped) { - var diagnostics = cache.getDiagnostics(id, snapshot, function () { - return services - .getCompilerOptionsDiagnostics() - .concat(services.getSyntacticDiagnostics(id)) - .concat(services.getSemanticDiagnostics(id)); - }); - printDiagnostics(_this, diagnostics); + if (options.check) { + var diagnostics = cache.getSyntacticDiagnostics(id, snapshot, function () { + return services.getSyntacticDiagnostics(id); + }); + contextWrapper.debug("printDiagnostics"); + printDiagnostics(contextWrapper, diagnostics); + } + // if no output was generated, aborting compilation _this.error(red("failed to transpile " + id)); } var transpiled = find(output.outputFiles, function (entry) { return endsWith(entry.name, ".js"); }); @@ -428,11 +498,26 @@ function typescript(options) { map: map$$1 ? JSON.parse(map$$1.text) : { mappings: "" }, }; }); + // printing syntactic errors + if (options.check) { + var diagnostics = cache.getSyntacticDiagnostics(id, snapshot, function () { + return services.getSyntacticDiagnostics(id); + }); + contextWrapper.debug("printDiagnostics"); + printDiagnostics(contextWrapper, diagnostics); + } return result; }, + intro: function () { + context.debug("intro"); + // printing compiler option errors + if (options.check) + printDiagnostics(context, convertDiagnostic(services.getCompilerOptionsDiagnostics())); + }, outro: function () { context.debug("outro"); cache.compileDone(); + // printing semantic errors if (options.check) { cache.walkTree(function (id) { var snapshot = servicesHost.getScriptSnapshot(id); @@ -440,11 +525,8 @@ function typescript(options) { context.error(red("failed lo load snapshot for " + id)); return; } - var diagnostics = cache.getDiagnostics(id, snapshot, function () { - return services - .getCompilerOptionsDiagnostics() - .concat(services.getSyntacticDiagnostics(id)) - .concat(services.getSemanticDiagnostics(id)); + var diagnostics = cache.getSemanticDiagnostics(id, snapshot, function () { + return services.getSemanticDiagnostics(id); }); printDiagnostics(context, diagnostics); }); diff --git a/package.json b/package.json index b5a3bb4..39408a9 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "rollup-plugin-typescript2", - "version": "0.1.3", + "version": "0.2.0", "description": "Seamless integration between Rollup and TypeScript. Now with errors.", "main": "dist/rollup-plugin-typescript2.cjs.js", "module": "dist/rollup-plugin-typescript2.es.js", diff --git a/src/cache.ts b/src/cache.ts index 5e00ba2..d852969 100644 --- a/src/cache.ts +++ b/src/cache.ts @@ -21,6 +21,7 @@ export interface IDiagnostics { flatMessage: string; fileLine?: string; + category: ts.DiagnosticCategory; } interface ITypeSnapshot @@ -29,20 +30,46 @@ interface ITypeSnapshot snapshot: ts.IScriptSnapshot | undefined; } +export function convertDiagnostic(data: ts.Diagnostic[]): IDiagnostics[] +{ + return _.map(data, (diagnostic) => + { + let entry: IDiagnostics = + { + flatMessage: ts.flattenDiagnosticMessageText(diagnostic.messageText, "\n"), + category: diagnostic.category, + }; + + if (diagnostic.file) + { + let { line, character } = diagnostic.file.getLineAndCharacterOfPosition(diagnostic.start); + entry.fileLine = `${diagnostic.file.fileName} (${line + 1},${character + 1})`; + } + + return entry; + }); +} + export class Cache { - private cacheVersion = "1"; + private cacheVersion = "2"; private dependencyTree: graph.Graph; private ambientTypes: ITypeSnapshot[]; private ambientTypesDirty = false; private cacheDir: string; private codeCache: RollingCache; private typesCache: RollingCache; - private diagnosticsCache: RollingCache; + private semanticDiagnosticsCache: RollingCache; + private syntacticDiagnosticsCache: RollingCache; constructor(private host: ts.LanguageServiceHost, cache: string, private options: ts.CompilerOptions, rootFilenames: string[], private context: IContext) { - this.cacheDir = `${cache}/${hash.sha1({ version: this.cacheVersion, rootFilenames, options: this.options })}`; + this.cacheDir = `${cache}/${hash.sha1({ + version: this.cacheVersion, + rootFilenames, + options: this.options, + tsVersion : ts.version, + })}`; this.dependencyTree = new graph.Graph({ directed: true }); this.dependencyTree.setDefaultNodeLabel((_node: string) => { return { dirty: false }; }); @@ -102,7 +129,8 @@ export class Cache public diagnosticsDone() { this.codeCache.roll(); - this.diagnosticsCache.roll(); + this.semanticDiagnosticsCache.roll(); + this.syntacticDiagnosticsCache.roll(); this.typesCache.roll(); } @@ -127,24 +155,34 @@ export class Cache return data; } - public getDiagnostics(id: string, snapshot: ts.IScriptSnapshot, check: () => ts.Diagnostic[]): IDiagnostics[] + public getSyntacticDiagnostics(id: string, snapshot: ts.IScriptSnapshot, check: () => ts.Diagnostic[]): IDiagnostics[] + { + return this.getDiagnostics(this.syntacticDiagnosticsCache, id, snapshot, check); + } + + public getSemanticDiagnostics(id: string, snapshot: ts.IScriptSnapshot, check: () => ts.Diagnostic[]): IDiagnostics[] + { + return this.getDiagnostics(this.semanticDiagnosticsCache, id, snapshot, check); + } + + private getDiagnostics(cache: RollingCache, id: string, snapshot: ts.IScriptSnapshot, check: () => ts.Diagnostic[]): IDiagnostics[] { let name = this.makeName(id, snapshot); - if (!this.diagnosticsCache.exists(name) || this.isDirty(id, snapshot, true)) + if (!cache.exists(name) || this.isDirty(id, snapshot, true)) { this.context.debug(`fresh diagnostics for: ${id}`); - let data = this.convert(check()); - this.diagnosticsCache.write(name, data); + let data = convertDiagnostic(check()); + cache.write(name, data); this.markAsDirty(id, snapshot); return data; } this.context.debug(`old diagnostics for: ${id}`); - let data = this.diagnosticsCache.read(name); - this.diagnosticsCache.write(name, data); + let data = cache.read(name); + cache.write(name, data); return data; } @@ -152,7 +190,8 @@ export class Cache { this.codeCache = new RollingCache(`${this.cacheDir}/code`, true); this.typesCache = new RollingCache(`${this.cacheDir}/types`, false); - this.diagnosticsCache = new RollingCache(`${this.cacheDir}/diagnostics`, false); + this.syntacticDiagnosticsCache = new RollingCache(`${this.cacheDir}/syntacticDiagnostics`, false); + this.semanticDiagnosticsCache = new RollingCache(`${this.cacheDir}/semanticDiagnostics`, false); } private markAsDirty(id: string, _snapshot: ts.IScriptSnapshot): void @@ -197,23 +236,4 @@ export class Cache let data = snapshot.getText(0, snapshot.getLength()); return hash.sha1({ data, id }); } - - private convert(data: ts.Diagnostic[]): IDiagnostics[] - { - return _.map(data, (diagnostic) => - { - let entry: IDiagnostics = - { - flatMessage: ts.flattenDiagnosticMessageText(diagnostic.messageText, "\n"), - }; - - if (diagnostic.file) - { - let { line, character } = diagnostic.file.getLineAndCharacterOfPosition(diagnostic.start); - entry.fileLine = `${diagnostic.file.fileName} (${line + 1},${character + 1})`; - } - - return entry; - }); - } } diff --git a/src/index.ts b/src/index.ts index b3c11db..1b3a686 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,6 +1,7 @@ +import { RollupContext } from "./rollupcontext"; import { IContext, ConsoleContext, IRollupContext, VerbosityLevel } from "./context"; import { LanguageServiceHost } from "./host"; -import { Cache, ICode, IDiagnostics } from "./cache"; +import { Cache, convertDiagnostic, ICode, IDiagnostics } from "./cache"; import * as ts from "typescript"; import * as fs from "fs-extra"; import * as path from "path"; @@ -72,14 +73,33 @@ function parseTsConfig() return configParseResult; } -function printDiagnostics(context: IContext | IRollupContext, diagnostics: IDiagnostics[]) +function printDiagnostics(context: IContext, diagnostics: IDiagnostics[]) { _.each(diagnostics, (diagnostic) => { + let print; + let color; + switch (diagnostic.category) + { + case ts.DiagnosticCategory.Message: + print = context.info; + color = colors.white; + break; + case ts.DiagnosticCategory.Error: + print = context.error; + color = colors.red; + break; + case ts.DiagnosticCategory.Warning: + default: + print = context.warn; + color = colors.yellow; + break; + } + if (diagnostic.fileLine) - context.warn(`${diagnostic.fileLine}: ${colors.yellow(diagnostic.flatMessage)}`); + print.call(context, [`${diagnostic.fileLine}: ${color(diagnostic.flatMessage)}`]); else - context.warn(colors.yellow(diagnostic.flatMessage)); + print.call(context, [color(diagnostic.flatMessage)]); }); }; @@ -91,6 +111,7 @@ interface IOptions verbosity: number; clean: boolean; cacheRoot: string; + abortOnError: boolean; } export default function typescript (options: IOptions) @@ -105,11 +126,12 @@ export default function typescript (options: IOptions) cacheRoot: `${process.cwd()}/.rts2_cache`, include: [ "*.ts+(|x)", "**/*.ts+(|x)" ], exclude: [ "*.d.ts", "**/*.d.ts" ], + abortOnError: true, }); const filter = createFilter(options.include, options.exclude); - let parsedConfig = parseTsConfig(); + const parsedConfig = parseTsConfig(); const servicesHost = new LanguageServiceHost(parsedConfig); @@ -163,26 +185,35 @@ export default function typescript (options: IOptions) if (!filter(id)) return undefined; + const contextWrapper = new RollupContext(options.verbosity, options.abortOnError, this, "rollup-plugin-typescript2: "); + + contextWrapper.debug(id); + const snapshot = servicesHost.setSnapshot(id, code); - let result = cache.getCompiled(id, snapshot, () => + + // getting compiled file from cache of from ts + const result = cache.getCompiled(id, snapshot, () => { const output = services.getEmitOutput(id); if (output.emitSkipped) { - const diagnostics = cache.getDiagnostics(id, snapshot, () => + if (options.check) { - return services - .getCompilerOptionsDiagnostics() - .concat(services.getSyntacticDiagnostics(id)) - .concat(services.getSemanticDiagnostics(id)); - }); - printDiagnostics(this, diagnostics); + const diagnostics = cache.getSyntacticDiagnostics(id, snapshot, () => + { + return services.getSyntacticDiagnostics(id); + }); + contextWrapper.debug("printDiagnostics"); + printDiagnostics(contextWrapper, diagnostics); + } + + // if no output was generated, aborting compilation this.error(colors.red(`failed to transpile ${id}`)); } - const transpiled = _.find(output.outputFiles, (entry: ts.OutputFile) => _.endsWith(entry.name, ".js") ); - const map = _.find(output.outputFiles, (entry: ts.OutputFile) => _.endsWith(entry.name, ".map") ); + const transpiled = _.find(output.outputFiles, (entry) => _.endsWith(entry.name, ".js") ); + const map = _.find(output.outputFiles, (entry) => _.endsWith(entry.name, ".map") ); return { code: transpiled ? transpiled.text : undefined, @@ -190,14 +221,36 @@ export default function typescript (options: IOptions) }; }); + // printing syntactic errors + if (options.check) + { + const diagnostics = cache.getSyntacticDiagnostics(id, snapshot, () => + { + return services.getSyntacticDiagnostics(id); + }); + contextWrapper.debug("printDiagnostics"); + printDiagnostics(contextWrapper, diagnostics); + } + return result; }, + intro(): void + { + context.debug("intro"); + + // printing compiler option errors + if (options.check) + printDiagnostics(context, convertDiagnostic(services.getCompilerOptionsDiagnostics())); + }, + outro(): void { context.debug("outro"); + cache.compileDone(); + // printing semantic errors if (options.check) { cache.walkTree((id: string) => @@ -210,12 +263,9 @@ export default function typescript (options: IOptions) return; } - const diagnostics = cache.getDiagnostics(id, snapshot, () => + const diagnostics = cache.getSemanticDiagnostics(id, snapshot, () => { - return services - .getCompilerOptionsDiagnostics() - .concat(services.getSyntacticDiagnostics(id)) - .concat(services.getSemanticDiagnostics(id)); + return services.getSemanticDiagnostics(id); }); printDiagnostics(context, diagnostics); diff --git a/src/rollupcontext.ts b/src/rollupcontext.ts new file mode 100644 index 0000000..240f1aa --- /dev/null +++ b/src/rollupcontext.ts @@ -0,0 +1,40 @@ +import { IContext, IRollupContext, VerbosityLevel } from "./context"; + +export class RollupContext implements IContext +{ + constructor(private verbosity: VerbosityLevel, private bail: boolean, private context: IRollupContext, private prefix: string = "") + { + } + + public warn(message: string): void + { + if (this.verbosity < VerbosityLevel.Warning) + return; + this.context.warn(`${this.prefix}${message}`); + } + + public error(message: string): void + { + if (this.verbosity < VerbosityLevel.Error) + return; + + if (this.bail) + this.context.error(`${this.prefix}${message}`); + else + this.context.warn(`${this.prefix}${message}`); + } + + public info(message: string): void + { + if (this.verbosity < VerbosityLevel.Info) + return; + this.context.warn(`${this.prefix}${message}`); + } + + public debug(message: string): void + { + if (this.verbosity < VerbosityLevel.Debug) + return; + this.context.warn(`${this.prefix}${message}`); + } +}