mirror of
https://github.com/angular/angular-cli.git
synced 2025-05-22 23:15:56 +08:00
fix(@ngtools/webpack): diagnose generated files and resolve sourcemaps
Generated files were not diagnosed in AOT which led to errors not being shown properly. Also, in order to show the proper error source we now resolve the sourcemap of any errors we find. Fixes #5264 Fixed #4538
This commit is contained in:
parent
5c1593319e
commit
5acf10b7aa
@ -2,6 +2,7 @@
|
||||
import * as fs from 'fs';
|
||||
import * as path from 'path';
|
||||
import * as ts from 'typescript';
|
||||
import * as SourceMap from 'source-map';
|
||||
|
||||
const {__NGTOOLS_PRIVATE_API_2} = require('@angular/compiler-cli');
|
||||
const ContextElementDependency = require('webpack/lib/dependencies/ContextElementDependency');
|
||||
@ -36,6 +37,9 @@ export interface AotPluginOptions {
|
||||
}
|
||||
|
||||
|
||||
const inlineSourceMapRe = /\/\/# sourceMappingURL=data:application\/json;base64,([\s\S]+)$/;
|
||||
|
||||
|
||||
export class AotPlugin implements Tapable {
|
||||
private _options: AotPluginOptions;
|
||||
|
||||
@ -342,6 +346,30 @@ export class AotPlugin implements Tapable {
|
||||
});
|
||||
}
|
||||
|
||||
private _translateSourceMap(sourceText: string, fileName: string,
|
||||
{line, character}: {line: number, character: number}) {
|
||||
const match = sourceText.match(inlineSourceMapRe);
|
||||
|
||||
if (!match) {
|
||||
return {line, character, fileName};
|
||||
}
|
||||
|
||||
// On any error, return line and character.
|
||||
try {
|
||||
const sourceMapJson = JSON.parse(Buffer.from(match[1], 'base64').toString());
|
||||
const consumer = new SourceMap.SourceMapConsumer(sourceMapJson);
|
||||
|
||||
const original = consumer.originalPositionFor({ line, column: character });
|
||||
return {
|
||||
line: original.line,
|
||||
character: original.column,
|
||||
fileName: original.source || fileName
|
||||
};
|
||||
} catch (e) {
|
||||
return {line, character, fileName};
|
||||
}
|
||||
}
|
||||
|
||||
diagnose(fileName: string) {
|
||||
if (this._diagnoseFiles[fileName]) {
|
||||
return;
|
||||
@ -349,9 +377,9 @@ export class AotPlugin implements Tapable {
|
||||
this._diagnoseFiles[fileName] = true;
|
||||
|
||||
const sourceFile = this._program.getSourceFile(fileName);
|
||||
if (!sourceFile) {
|
||||
return;
|
||||
}
|
||||
if (!sourceFile) {
|
||||
return;
|
||||
}
|
||||
|
||||
const diagnostics: ts.Diagnostic[] = []
|
||||
.concat(
|
||||
@ -364,9 +392,14 @@ export class AotPlugin implements Tapable {
|
||||
if (diagnostics.length > 0) {
|
||||
const message = diagnostics
|
||||
.map(diagnostic => {
|
||||
const {line, character} = diagnostic.file.getLineAndCharacterOfPosition(diagnostic.start);
|
||||
const position = diagnostic.file.getLineAndCharacterOfPosition(diagnostic.start);
|
||||
|
||||
const sourceText = diagnostic.file.getFullText();
|
||||
let {line, character, fileName} = this._translateSourceMap(sourceText,
|
||||
diagnostic.file.fileName, position);
|
||||
|
||||
const message = ts.flattenDiagnosticMessageText(diagnostic.messageText, '\n');
|
||||
return `${diagnostic.file.fileName} (${line + 1},${character + 1}): ${message})`;
|
||||
return `${fileName} (${line + 1},${character + 1}): ${message}`;
|
||||
})
|
||||
.join('\n');
|
||||
this._compilation.errors.push(message);
|
||||
@ -404,6 +437,15 @@ export class AotPlugin implements Tapable {
|
||||
});
|
||||
})
|
||||
.then(() => {
|
||||
// Get the ngfactory that were created by the previous step, and add them to the root
|
||||
// file path (if those files exists).
|
||||
const newRootFilePath = this._compilerHost.getChangedFilePaths()
|
||||
.filter(x => x.match(/\.ngfactory\.ts$/));
|
||||
// Remove files that don't exist anymore, and add new files.
|
||||
this._rootFilePath = this._rootFilePath
|
||||
.filter(x => this._compilerHost.fileExists(x))
|
||||
.concat(newRootFilePath);
|
||||
|
||||
// Create a new Program, based on the old one. This will trigger a resolution of all
|
||||
// transitive modules, which include files that might just have been generated.
|
||||
// This needs to happen after the code generator has been created for generated files
|
||||
|
Loading…
x
Reference in New Issue
Block a user