Skip to content

Commit

Permalink
fix(jsii): show jsii diagnostics in watch mode and support $tsc probl…
Browse files Browse the repository at this point in the history
…em matcher (#383)

Emit jsii diagnostics error when in watch mode, and also format the errors with a
"TS9999" error code so that VSCode's $tsc problem matcher will show them as
"Problems". Prefix "JSII" in the message to distinguish that these are jsii errors.

Fixes #382
  • Loading branch information
Elad Ben-Israel committed Mar 13, 2019
1 parent 10242eb commit 0275944
Show file tree
Hide file tree
Showing 4 changed files with 32 additions and 26 deletions.
23 changes: 1 addition & 22 deletions packages/jsii/bin/jsii.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,8 @@
import log4js = require('log4js');
import path = require('path');
import process = require('process');
import ts = require('typescript');
import yargs = require('yargs');
import { Compiler, DIAGNOSTICS } from '../lib/compiler';
import { hasDomain } from '../lib/emitter';
import { loadProjectInfo } from '../lib/project-info';
import utils = require('../lib/utils');
import { VERSION } from '../lib/version';
Expand Down Expand Up @@ -33,7 +31,7 @@ import { VERSION } from '../lib/version';
return { projectRoot, emitResult: await compiler.emit() };
})().then(({ projectRoot, emitResult }) => {
for (const diagnostic of emitResult.diagnostics) {
_logDiagnostic(diagnostic, projectRoot);
utils.logDiagnostic(diagnostic, projectRoot);
}
if (emitResult.emitSkipped) {
process.exit(1);
Expand Down Expand Up @@ -72,22 +70,3 @@ function _configureLog4js(verbosity: number) {
}
}
}

function _logDiagnostic(diagnostic: ts.Diagnostic, projectRoot: string) {
const formatDiagnosticsHost = {
getCurrentDirectory: () => projectRoot,
getCanonicalFileName(fileName: string) { return fileName; },
getNewLine() { return '\n'; }
};

let message = diagnostic.file
? ts.formatDiagnosticsWithColorAndContext([diagnostic], formatDiagnosticsHost)
: ts.formatDiagnostics([diagnostic], formatDiagnosticsHost);
if (hasDomain(diagnostic)) {
// Make sure error codes don't render as ``TS123``, instead e.g: ``JSII123``.
message = message.replace(/([^\w])TS(\d+)([^\w])/, `$1${diagnostic.domain}$2$3`);
}
const logFunc = utils.diagnosticsLogger(log4js.getLogger(DIAGNOSTICS), diagnostic);
if (!logFunc) { return; }
logFunc(message.trim());
}
6 changes: 4 additions & 2 deletions packages/jsii/lib/assembler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import spec = require('jsii-spec');
import log4js = require('log4js');
import path = require('path');
import ts = require('typescript');
import { JSII_DIAGNOSTICS_CODE } from './compiler';
import { Diagnostic, Emitter } from './emitter';
import literate = require('./literate');
import { ProjectInfo } from './project-info';
Expand Down Expand Up @@ -223,8 +224,9 @@ export class Assembler implements Emitter {
private _diagnostic(node: ts.Node | null, category: ts.DiagnosticCategory, messageText: string) {
this._diagnostics.push({
domain: 'JSII',
category, code: 0,
messageText,
category,
code: JSII_DIAGNOSTICS_CODE,
messageText: `JSII: ${messageText}`,
file: node != null ? node.getSourceFile() : undefined,
start: node != null ? node.getStart() : undefined,
length: node != null ? node.getEnd() - node.getStart() : undefined
Expand Down
14 changes: 12 additions & 2 deletions packages/jsii/lib/compiler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ const COMPILER_OPTIONS: ts.CompilerOptions = {

const LOG = log4js.getLogger('jsii/compiler');
export const DIAGNOSTICS = 'diagnostics';
export const JSII_DIAGNOSTICS_CODE = 9999;

export interface CompilerOptions {
/** The information about the project to be built */
Expand Down Expand Up @@ -102,6 +103,7 @@ export class Compiler implements Emitter {
projectReferences: this.typescriptConfig.references && this.typescriptConfig.references.map(ref => ({ path: path.resolve(ref.path) })),
host: this.compilerHost
});

return await this._consumeProgram(prog, this.compilerHost.getDefaultLibLocation());
}

Expand All @@ -121,7 +123,12 @@ export class Compiler implements Emitter {
}
const orig = host.afterProgramCreate;
host.afterProgramCreate = async builderProgram => {
await this._consumeProgram(builderProgram.getProgram(), host.getDefaultLibLocation!());
const emitResult = await this._consumeProgram(builderProgram.getProgram(), host.getDefaultLibLocation!());

for (const diag of emitResult.diagnostics.filter(d => d.code === JSII_DIAGNOSTICS_CODE)) {
utils.logDiagnostic(diag, projectRoot);
}

if (orig) { orig.call(host, builderProgram); }
};
ts.createWatchProgram(host);
Expand All @@ -133,13 +140,16 @@ export class Compiler implements Emitter {
const emit = program.emit();
if (emit.emitSkipped) {
LOG.error('Compilation errors prevented the JSII assembly from being created');
return emit;
}

// we continue to do jsii checker even if there are compilation errors so that
// jsii warnings will appear.
const assembler = new Assembler(this.options.projectInfo, program, stdlib);
const assmEmit = await assembler.emit();
if (assmEmit.emitSkipped) {
LOG.error('Type model errors prevented the JSII assembly from being created');
}

return {
emitSkipped: assmEmit.emitSkipped,
diagnostics: [...emit.diagnostics, ...assmEmit.diagnostics]
Expand Down
15 changes: 15 additions & 0 deletions packages/jsii/lib/utils.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import log4js = require('log4js');
import ts = require('typescript');
import { DIAGNOSTICS } from './compiler';

/**
* Obtains the relevant logger to be used for a given diagnostic message.
Expand All @@ -24,6 +25,20 @@ export function diagnosticsLogger(logger: log4js.Logger, diagnostic: ts.Diagnost
return logger.debug.bind(logger);
}
}
export function logDiagnostic(diagnostic: ts.Diagnostic, projectRoot: string) {
const formatDiagnosticsHost = {
getCurrentDirectory: () => projectRoot,
getCanonicalFileName(fileName: string) { return fileName; },
getNewLine() { return '\n'; }
};

const message = diagnostic.file
? ts.formatDiagnosticsWithColorAndContext([diagnostic], formatDiagnosticsHost)
: ts.formatDiagnostics([diagnostic], formatDiagnosticsHost);
const logFunc = diagnosticsLogger(log4js.getLogger(DIAGNOSTICS), diagnostic);
if (!logFunc) { return; }
logFunc(message.trim());
}

/**
* A filter function for ``JSON.stringify`` that removes:
Expand Down

0 comments on commit 0275944

Please sign in to comment.