Skip to content

Commit 0275944

Browse files
author
Elad Ben-Israel
authored
fix(jsii): show jsii diagnostics in watch mode and support $tsc problem 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
1 parent 10242eb commit 0275944

File tree

4 files changed

+32
-26
lines changed

4 files changed

+32
-26
lines changed

packages/jsii/bin/jsii.ts

Lines changed: 1 addition & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,8 @@
11
import log4js = require('log4js');
22
import path = require('path');
33
import process = require('process');
4-
import ts = require('typescript');
54
import yargs = require('yargs');
65
import { Compiler, DIAGNOSTICS } from '../lib/compiler';
7-
import { hasDomain } from '../lib/emitter';
86
import { loadProjectInfo } from '../lib/project-info';
97
import utils = require('../lib/utils');
108
import { VERSION } from '../lib/version';
@@ -33,7 +31,7 @@ import { VERSION } from '../lib/version';
3331
return { projectRoot, emitResult: await compiler.emit() };
3432
})().then(({ projectRoot, emitResult }) => {
3533
for (const diagnostic of emitResult.diagnostics) {
36-
_logDiagnostic(diagnostic, projectRoot);
34+
utils.logDiagnostic(diagnostic, projectRoot);
3735
}
3836
if (emitResult.emitSkipped) {
3937
process.exit(1);
@@ -72,22 +70,3 @@ function _configureLog4js(verbosity: number) {
7270
}
7371
}
7472
}
75-
76-
function _logDiagnostic(diagnostic: ts.Diagnostic, projectRoot: string) {
77-
const formatDiagnosticsHost = {
78-
getCurrentDirectory: () => projectRoot,
79-
getCanonicalFileName(fileName: string) { return fileName; },
80-
getNewLine() { return '\n'; }
81-
};
82-
83-
let message = diagnostic.file
84-
? ts.formatDiagnosticsWithColorAndContext([diagnostic], formatDiagnosticsHost)
85-
: ts.formatDiagnostics([diagnostic], formatDiagnosticsHost);
86-
if (hasDomain(diagnostic)) {
87-
// Make sure error codes don't render as ``TS123``, instead e.g: ``JSII123``.
88-
message = message.replace(/([^\w])TS(\d+)([^\w])/, `$1${diagnostic.domain}$2$3`);
89-
}
90-
const logFunc = utils.diagnosticsLogger(log4js.getLogger(DIAGNOSTICS), diagnostic);
91-
if (!logFunc) { return; }
92-
logFunc(message.trim());
93-
}

packages/jsii/lib/assembler.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import spec = require('jsii-spec');
66
import log4js = require('log4js');
77
import path = require('path');
88
import ts = require('typescript');
9+
import { JSII_DIAGNOSTICS_CODE } from './compiler';
910
import { Diagnostic, Emitter } from './emitter';
1011
import literate = require('./literate');
1112
import { ProjectInfo } from './project-info';
@@ -223,8 +224,9 @@ export class Assembler implements Emitter {
223224
private _diagnostic(node: ts.Node | null, category: ts.DiagnosticCategory, messageText: string) {
224225
this._diagnostics.push({
225226
domain: 'JSII',
226-
category, code: 0,
227-
messageText,
227+
category,
228+
code: JSII_DIAGNOSTICS_CODE,
229+
messageText: `JSII: ${messageText}`,
228230
file: node != null ? node.getSourceFile() : undefined,
229231
start: node != null ? node.getStart() : undefined,
230232
length: node != null ? node.getEnd() - node.getStart() : undefined

packages/jsii/lib/compiler.ts

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ const COMPILER_OPTIONS: ts.CompilerOptions = {
3434

3535
const LOG = log4js.getLogger('jsii/compiler');
3636
export const DIAGNOSTICS = 'diagnostics';
37+
export const JSII_DIAGNOSTICS_CODE = 9999;
3738

3839
export interface CompilerOptions {
3940
/** The information about the project to be built */
@@ -102,6 +103,7 @@ export class Compiler implements Emitter {
102103
projectReferences: this.typescriptConfig.references && this.typescriptConfig.references.map(ref => ({ path: path.resolve(ref.path) })),
103104
host: this.compilerHost
104105
});
106+
105107
return await this._consumeProgram(prog, this.compilerHost.getDefaultLibLocation());
106108
}
107109

@@ -121,7 +123,12 @@ export class Compiler implements Emitter {
121123
}
122124
const orig = host.afterProgramCreate;
123125
host.afterProgramCreate = async builderProgram => {
124-
await this._consumeProgram(builderProgram.getProgram(), host.getDefaultLibLocation!());
126+
const emitResult = await this._consumeProgram(builderProgram.getProgram(), host.getDefaultLibLocation!());
127+
128+
for (const diag of emitResult.diagnostics.filter(d => d.code === JSII_DIAGNOSTICS_CODE)) {
129+
utils.logDiagnostic(diag, projectRoot);
130+
}
131+
125132
if (orig) { orig.call(host, builderProgram); }
126133
};
127134
ts.createWatchProgram(host);
@@ -133,13 +140,16 @@ export class Compiler implements Emitter {
133140
const emit = program.emit();
134141
if (emit.emitSkipped) {
135142
LOG.error('Compilation errors prevented the JSII assembly from being created');
136-
return emit;
137143
}
144+
145+
// we continue to do jsii checker even if there are compilation errors so that
146+
// jsii warnings will appear.
138147
const assembler = new Assembler(this.options.projectInfo, program, stdlib);
139148
const assmEmit = await assembler.emit();
140149
if (assmEmit.emitSkipped) {
141150
LOG.error('Type model errors prevented the JSII assembly from being created');
142151
}
152+
143153
return {
144154
emitSkipped: assmEmit.emitSkipped,
145155
diagnostics: [...emit.diagnostics, ...assmEmit.diagnostics]

packages/jsii/lib/utils.ts

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import log4js = require('log4js');
22
import ts = require('typescript');
3+
import { DIAGNOSTICS } from './compiler';
34

45
/**
56
* Obtains the relevant logger to be used for a given diagnostic message.
@@ -24,6 +25,20 @@ export function diagnosticsLogger(logger: log4js.Logger, diagnostic: ts.Diagnost
2425
return logger.debug.bind(logger);
2526
}
2627
}
28+
export function logDiagnostic(diagnostic: ts.Diagnostic, projectRoot: string) {
29+
const formatDiagnosticsHost = {
30+
getCurrentDirectory: () => projectRoot,
31+
getCanonicalFileName(fileName: string) { return fileName; },
32+
getNewLine() { return '\n'; }
33+
};
34+
35+
const message = diagnostic.file
36+
? ts.formatDiagnosticsWithColorAndContext([diagnostic], formatDiagnosticsHost)
37+
: ts.formatDiagnostics([diagnostic], formatDiagnosticsHost);
38+
const logFunc = diagnosticsLogger(log4js.getLogger(DIAGNOSTICS), diagnostic);
39+
if (!logFunc) { return; }
40+
logFunc(message.trim());
41+
}
2742

2843
/**
2944
* A filter function for ``JSON.stringify`` that removes:

0 commit comments

Comments
 (0)