forked from vercel/next.js
/
diagnosticFormatter.ts
75 lines (67 loc) · 1.82 KB
/
diagnosticFormatter.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
import { codeFrameColumns } from '@babel/code-frame'
import chalk from 'next/dist/compiled/chalk'
import path from 'path'
export enum DiagnosticCategory {
Warning = 0,
Error = 1,
Suggestion = 2,
Message = 3,
}
export async function getFormattedDiagnostic(
ts: typeof import('typescript'),
baseDir: string,
diagnostic: import('typescript').Diagnostic
): Promise<string> {
let message = ''
const reason = ts.flattenDiagnosticMessageText(diagnostic.messageText, '\n')
const category = diagnostic.category
switch (category) {
// Warning
case DiagnosticCategory.Warning: {
message += chalk.yellow.bold('Type warning') + ': '
break
}
// Error
case DiagnosticCategory.Error: {
message += chalk.red.bold('Type error') + ': '
break
}
// 2 = Suggestion, 3 = Message
case DiagnosticCategory.Suggestion:
case DiagnosticCategory.Message:
default: {
message += chalk.cyan.bold(category === 2 ? 'Suggestion' : 'Info') + ': '
break
}
}
message += reason + '\n'
if (diagnostic.file) {
const pos = diagnostic.file.getLineAndCharacterOfPosition(diagnostic.start!)
const line = pos.line + 1
const character = pos.character + 1
let fileName = path.posix.normalize(
path.relative(baseDir, diagnostic.file.fileName).replace(/\\/g, '/')
)
if (!fileName.startsWith('.')) {
fileName = './' + fileName
}
message =
chalk.cyan(fileName) +
':' +
chalk.yellow(line.toString()) +
':' +
chalk.yellow(character.toString()) +
'\n' +
message
message +=
'\n' +
codeFrameColumns(
diagnostic.file.getFullText(diagnostic.file.getSourceFile()),
{
start: { line: line, column: character },
},
{ forceColor: true }
)
}
return message
}