Skip to content

Commit b973b0f

Browse files
clydinangular-robot[bot]
authored andcommitted
refactor(@angular-devkit/build-angular): separate esbuild compiler plugin diagnostic utilities
The TypeScript diagnostic to esbuild diagnostic conversion utilities are now contained in a separate file. This lowers the line count of the main compiler plugin file and also removes an additional direct usage of the `typescript` dependency from the compiler plugin file.
1 parent a416b4e commit b973b0f

File tree

2 files changed

+100
-83
lines changed

2 files changed

+100
-83
lines changed

packages/angular_devkit/build_angular/src/builders/browser-esbuild/angular/compiler-plugin.ts

Lines changed: 1 addition & 83 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@ import type {
1111
OnStartResult,
1212
OutputFile,
1313
PartialMessage,
14-
PartialNote,
1514
Plugin,
1615
PluginBuild,
1716
} from 'esbuild';
@@ -34,91 +33,10 @@ import { BundleStylesheetOptions, bundleComponentStylesheet } from '../styleshee
3433
import { AngularCompilation, FileEmitter } from './angular-compilation';
3534
import { AngularHostOptions } from './angular-host';
3635
import { AotCompilation } from './aot-compilation';
36+
import { convertTypeScriptDiagnostic } from './diagnostics';
3737
import { JitCompilation } from './jit-compilation';
3838
import { setupJitPluginCallbacks } from './jit-plugin-callbacks';
3939

40-
/**
41-
* Converts TypeScript Diagnostic related information into an esbuild compatible note object.
42-
* Related information is a subset of a full TypeScript Diagnostic and also used for diagnostic
43-
* notes associated with the main Diagnostic.
44-
* @param info The TypeScript diagnostic relative information to convert.
45-
* @returns An esbuild diagnostic message as a PartialMessage object
46-
*/
47-
function convertTypeScriptDiagnosticInfo(
48-
info: ts.DiagnosticRelatedInformation,
49-
textPrefix?: string,
50-
): PartialNote {
51-
const newLine = platform() === 'win32' ? '\r\n' : '\n';
52-
let text = ts.flattenDiagnosticMessageText(info.messageText, newLine);
53-
if (textPrefix) {
54-
text = textPrefix + text;
55-
}
56-
57-
const note: PartialNote = { text };
58-
59-
if (info.file) {
60-
note.location = {
61-
file: info.file.fileName,
62-
length: info.length,
63-
};
64-
65-
// Calculate the line/column location and extract the full line text that has the diagnostic
66-
if (info.start) {
67-
const { line, character } = ts.getLineAndCharacterOfPosition(info.file, info.start);
68-
note.location.line = line + 1;
69-
note.location.column = character;
70-
71-
// The start position for the slice is the first character of the error line
72-
const lineStartPosition = ts.getPositionOfLineAndCharacter(info.file, line, 0);
73-
74-
// The end position for the slice is the first character of the next line or the length of
75-
// the entire file if the line is the last line of the file (getPositionOfLineAndCharacter
76-
// will error if a nonexistent line is passed).
77-
const { line: lastLineOfFile } = ts.getLineAndCharacterOfPosition(
78-
info.file,
79-
info.file.text.length - 1,
80-
);
81-
const lineEndPosition =
82-
line < lastLineOfFile
83-
? ts.getPositionOfLineAndCharacter(info.file, line + 1, 0)
84-
: info.file.text.length;
85-
86-
note.location.lineText = info.file.text.slice(lineStartPosition, lineEndPosition).trimEnd();
87-
}
88-
}
89-
90-
return note;
91-
}
92-
93-
/**
94-
* Converts a TypeScript Diagnostic message into an esbuild compatible message object.
95-
* @param diagnostic The TypeScript diagnostic to convert.
96-
* @returns An esbuild diagnostic message as a PartialMessage object
97-
*/
98-
function convertTypeScriptDiagnostic(diagnostic: ts.Diagnostic): PartialMessage {
99-
let codePrefix = 'TS';
100-
let code = `${diagnostic.code}`;
101-
if (diagnostic.source === 'ngtsc') {
102-
codePrefix = 'NG';
103-
// Remove `-99` Angular prefix from diagnostic code
104-
code = code.slice(3);
105-
}
106-
107-
const message: PartialMessage = {
108-
...convertTypeScriptDiagnosticInfo(diagnostic, `${codePrefix}${code}: `),
109-
// Store original diagnostic for reference if needed downstream
110-
detail: diagnostic,
111-
};
112-
113-
if (diagnostic.relatedInformation?.length) {
114-
message.notes = diagnostic.relatedInformation.map((info) =>
115-
convertTypeScriptDiagnosticInfo(info),
116-
);
117-
}
118-
119-
return message;
120-
}
121-
12240
const USING_WINDOWS = platform() === 'win32';
12341
const WINDOWS_SEP_REGEXP = new RegExp(`\\${path.win32.sep}`, 'g');
12442

Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
/**
2+
* @license
3+
* Copyright Google LLC All Rights Reserved.
4+
*
5+
* Use of this source code is governed by an MIT-style license that can be
6+
* found in the LICENSE file at https://angular.io/license
7+
*/
8+
9+
import type { PartialMessage, PartialNote } from 'esbuild';
10+
import { platform } from 'node:os';
11+
import {
12+
Diagnostic,
13+
DiagnosticRelatedInformation,
14+
flattenDiagnosticMessageText,
15+
getLineAndCharacterOfPosition,
16+
getPositionOfLineAndCharacter,
17+
} from 'typescript';
18+
19+
/**
20+
* Converts TypeScript Diagnostic related information into an esbuild compatible note object.
21+
* Related information is a subset of a full TypeScript Diagnostic and also used for diagnostic
22+
* notes associated with the main Diagnostic.
23+
* @param info The TypeScript diagnostic relative information to convert.
24+
* @returns An esbuild diagnostic message as a PartialMessage object
25+
*/
26+
function convertTypeScriptDiagnosticInfo(
27+
info: DiagnosticRelatedInformation,
28+
textPrefix?: string,
29+
): PartialNote {
30+
const newLine = platform() === 'win32' ? '\r\n' : '\n';
31+
let text = flattenDiagnosticMessageText(info.messageText, newLine);
32+
if (textPrefix) {
33+
text = textPrefix + text;
34+
}
35+
36+
const note: PartialNote = { text };
37+
38+
if (info.file) {
39+
note.location = {
40+
file: info.file.fileName,
41+
length: info.length,
42+
};
43+
44+
// Calculate the line/column location and extract the full line text that has the diagnostic
45+
if (info.start) {
46+
const { line, character } = getLineAndCharacterOfPosition(info.file, info.start);
47+
note.location.line = line + 1;
48+
note.location.column = character;
49+
50+
// The start position for the slice is the first character of the error line
51+
const lineStartPosition = getPositionOfLineAndCharacter(info.file, line, 0);
52+
53+
// The end position for the slice is the first character of the next line or the length of
54+
// the entire file if the line is the last line of the file (getPositionOfLineAndCharacter
55+
// will error if a nonexistent line is passed).
56+
const { line: lastLineOfFile } = getLineAndCharacterOfPosition(
57+
info.file,
58+
info.file.text.length - 1,
59+
);
60+
const lineEndPosition =
61+
line < lastLineOfFile
62+
? getPositionOfLineAndCharacter(info.file, line + 1, 0)
63+
: info.file.text.length;
64+
65+
note.location.lineText = info.file.text.slice(lineStartPosition, lineEndPosition).trimEnd();
66+
}
67+
}
68+
69+
return note;
70+
}
71+
72+
/**
73+
* Converts a TypeScript Diagnostic message into an esbuild compatible message object.
74+
* @param diagnostic The TypeScript diagnostic to convert.
75+
* @returns An esbuild diagnostic message as a PartialMessage object
76+
*/
77+
export function convertTypeScriptDiagnostic(diagnostic: Diagnostic): PartialMessage {
78+
let codePrefix = 'TS';
79+
let code = `${diagnostic.code}`;
80+
if (diagnostic.source === 'ngtsc') {
81+
codePrefix = 'NG';
82+
// Remove `-99` Angular prefix from diagnostic code
83+
code = code.slice(3);
84+
}
85+
86+
const message: PartialMessage = {
87+
...convertTypeScriptDiagnosticInfo(diagnostic, `${codePrefix}${code}: `),
88+
// Store original diagnostic for reference if needed downstream
89+
detail: diagnostic,
90+
};
91+
92+
if (diagnostic.relatedInformation?.length) {
93+
message.notes = diagnostic.relatedInformation.map((info) =>
94+
convertTypeScriptDiagnosticInfo(info),
95+
);
96+
}
97+
98+
return message;
99+
}

0 commit comments

Comments
 (0)