Skip to content

Commit 0301fed

Browse files
author
Andy Hanson
committed
Add type for diagnostics where location is defined
1 parent ec05f29 commit 0301fed

33 files changed

+141
-110
lines changed

src/compiler/binder.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -157,7 +157,7 @@ namespace ts {
157157
* If so, the node _must_ be in the current file (as that's the only way anything could have traversed to it to yield it as the error node)
158158
* This version of `createDiagnosticForNode` uses the binder's context to account for this, and always yields correct diagnostics even in these situations.
159159
*/
160-
function createDiagnosticForNode(node: Node, message: DiagnosticMessage, arg0?: string | number, arg1?: string | number, arg2?: string | number): Diagnostic {
160+
function createDiagnosticForNode(node: Node, message: DiagnosticMessage, arg0?: string | number, arg1?: string | number, arg2?: string | number): DiagnosticWithLocation {
161161
return createDiagnosticForNodeInSourceFile(getSourceFileOfNode(node) || file, node, message, arg0, arg1, arg2);
162162
}
163163

src/compiler/checker.ts

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -311,11 +311,11 @@ namespace ts {
311311

312312
getSuggestionDiagnostics: file => {
313313
return (suggestionDiagnostics.get(file.fileName) || emptyArray).concat(getUnusedDiagnostics());
314-
function getUnusedDiagnostics(): ReadonlyArray<Diagnostic> {
314+
function getUnusedDiagnostics(): ReadonlyArray<DiagnosticWithLocation> {
315315
if (file.isDeclarationFile) return emptyArray;
316316

317317
checkSourceFile(file);
318-
const diagnostics: Diagnostic[] = [];
318+
const diagnostics: DiagnosticWithLocation[] = [];
319319
Debug.assert(!!(getNodeLinks(file).flags & NodeCheckFlags.TypeChecked));
320320
checkUnusedIdentifiers(allPotentiallyUnusedIdentifiers.get(file.fileName)!, (kind, diag) => {
321321
if (!unusedIsError(kind)) {
@@ -479,7 +479,7 @@ namespace ts {
479479

480480
const diagnostics = createDiagnosticCollection();
481481
// Suggestion diagnostics must have a file. Keyed by source file name.
482-
const suggestionDiagnostics = createMultiMap<Diagnostic>();
482+
const suggestionDiagnostics = createMultiMap<DiagnosticWithLocation>();
483483

484484
const enum TypeFacts {
485485
None = 0,
@@ -642,7 +642,7 @@ namespace ts {
642642
Local,
643643
Parameter,
644644
}
645-
type AddUnusedDiagnostic = (type: UnusedKind, diagnostic: Diagnostic) => void;
645+
type AddUnusedDiagnostic = (type: UnusedKind, diagnostic: DiagnosticWithLocation) => void;
646646

647647
const builtinGlobals = createSymbolTable();
648648
builtinGlobals.set(undefinedSymbol.escapedName, undefinedSymbol);
@@ -838,7 +838,7 @@ namespace ts {
838838
diagnostics.add(diagnostic);
839839
}
840840

841-
function addErrorOrSuggestion(isError: boolean, diagnostic: Diagnostic) {
841+
function addErrorOrSuggestion(isError: boolean, diagnostic: DiagnosticWithLocation) {
842842
if (isError) {
843843
diagnostics.add(diagnostic);
844844
}

src/compiler/core.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,8 @@ namespace ts {
1414
return pathIsRelative(moduleName) || isRootedDiskPath(moduleName);
1515
}
1616

17-
export function sortAndDeduplicateDiagnostics(diagnostics: ReadonlyArray<Diagnostic>): Diagnostic[] {
18-
return sortAndDeduplicate(diagnostics, compareDiagnostics);
17+
export function sortAndDeduplicateDiagnostics<T extends Diagnostic>(diagnostics: ReadonlyArray<T>): T[] {
18+
return sortAndDeduplicate<T>(diagnostics, compareDiagnostics);
1919
}
2020
}
2121

@@ -1578,8 +1578,8 @@ namespace ts {
15781578
return localizedDiagnosticMessages && localizedDiagnosticMessages[message.key] || message.message;
15791579
}
15801580

1581-
export function createFileDiagnostic(file: SourceFile, start: number, length: number, message: DiagnosticMessage, ...args: (string | number)[]): Diagnostic;
1582-
export function createFileDiagnostic(file: SourceFile, start: number, length: number, message: DiagnosticMessage): Diagnostic {
1581+
export function createFileDiagnostic(file: SourceFile, start: number, length: number, message: DiagnosticMessage, ...args: (string | number)[]): DiagnosticWithLocation;
1582+
export function createFileDiagnostic(file: SourceFile, start: number, length: number, message: DiagnosticMessage): DiagnosticWithLocation {
15831583
Debug.assertGreaterThanOrEqual(start, 0);
15841584
Debug.assertGreaterThanOrEqual(length, 0);
15851585

src/compiler/parser.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -580,7 +580,7 @@ namespace ts {
580580
// tslint:enable variable-name
581581

582582
let sourceFile: SourceFile;
583-
let parseDiagnostics: Diagnostic[];
583+
let parseDiagnostics: DiagnosticWithLocation[];
584584
let syntaxCursor: IncrementalParser.SyntaxCursor;
585585

586586
let currentToken: SyntaxKind;

src/compiler/program.ts

Lines changed: 34 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -394,7 +394,7 @@ namespace ts {
394394
}
395395

396396
interface DiagnosticCache {
397-
perFile?: Map<Diagnostic[]>;
397+
perFile?: Map<DiagnosticWithLocation[]>;
398398
allDiagnostics?: Diagnostic[];
399399
}
400400

@@ -453,7 +453,7 @@ namespace ts {
453453

454454
export function getConfigFileParsingDiagnostics(configFileParseResult: ParsedCommandLine): ReadonlyArray<Diagnostic> {
455455
return configFileParseResult.options.configFile ?
456-
configFileParseResult.options.configFile.parseDiagnostics.concat(configFileParseResult.errors) :
456+
[...configFileParseResult.options.configFile.parseDiagnostics, ...configFileParseResult.errors] :
457457
configFileParseResult.errors;
458458
}
459459

@@ -1211,8 +1211,8 @@ namespace ts {
12111211

12121212
function getDiagnosticsHelper(
12131213
sourceFile: SourceFile,
1214-
getDiagnostics: (sourceFile: SourceFile, cancellationToken: CancellationToken) => ReadonlyArray<Diagnostic>,
1215-
cancellationToken: CancellationToken): ReadonlyArray<Diagnostic> {
1214+
getDiagnostics: (sourceFile: SourceFile, cancellationToken: CancellationToken) => ReadonlyArray<DiagnosticWithLocation>,
1215+
cancellationToken: CancellationToken): ReadonlyArray<DiagnosticWithLocation> {
12161216
if (sourceFile) {
12171217
return getDiagnostics(sourceFile, cancellationToken);
12181218
}
@@ -1224,15 +1224,15 @@ namespace ts {
12241224
}));
12251225
}
12261226

1227-
function getSyntacticDiagnostics(sourceFile: SourceFile, cancellationToken: CancellationToken): ReadonlyArray<Diagnostic> {
1227+
function getSyntacticDiagnostics(sourceFile: SourceFile, cancellationToken: CancellationToken): ReadonlyArray<DiagnosticWithLocation> {
12281228
return getDiagnosticsHelper(sourceFile, getSyntacticDiagnosticsForFile, cancellationToken);
12291229
}
12301230

1231-
function getSemanticDiagnostics(sourceFile: SourceFile, cancellationToken: CancellationToken): ReadonlyArray<Diagnostic> {
1231+
function getSemanticDiagnostics(sourceFile: SourceFile, cancellationToken: CancellationToken): ReadonlyArray<DiagnosticWithLocation> {
12321232
return getDiagnosticsHelper(sourceFile, getSemanticDiagnosticsForFile, cancellationToken);
12331233
}
12341234

1235-
function getDeclarationDiagnostics(sourceFile: SourceFile, cancellationToken: CancellationToken): ReadonlyArray<Diagnostic> {
1235+
function getDeclarationDiagnostics(sourceFile: SourceFile, cancellationToken: CancellationToken): ReadonlyArray<DiagnosticWithLocation> {
12361236
const options = program.getCompilerOptions();
12371237
// collect diagnostics from the program only once if either no source file was specified or out/outFile is set (bundled emit)
12381238
if (!sourceFile || options.out || options.outFile) {
@@ -1243,7 +1243,7 @@ namespace ts {
12431243
}
12441244
}
12451245

1246-
function getSyntacticDiagnosticsForFile(sourceFile: SourceFile): ReadonlyArray<Diagnostic> {
1246+
function getSyntacticDiagnosticsForFile(sourceFile: SourceFile): ReadonlyArray<DiagnosticWithLocation> {
12471247
// For JavaScript files, we report semantic errors for using TypeScript-only
12481248
// constructs from within a JavaScript file as syntactic errors.
12491249
if (isSourceFileJavaScript(sourceFile)) {
@@ -1278,11 +1278,11 @@ namespace ts {
12781278
}
12791279
}
12801280

1281-
function getSemanticDiagnosticsForFile(sourceFile: SourceFile, cancellationToken: CancellationToken): Diagnostic[] {
1281+
function getSemanticDiagnosticsForFile(sourceFile: SourceFile, cancellationToken: CancellationToken): ReadonlyArray<DiagnosticWithLocation> {
12821282
return getAndCacheDiagnostics(sourceFile, cancellationToken, cachedSemanticDiagnosticsForFile, getSemanticDiagnosticsForFileNoCache);
12831283
}
12841284

1285-
function getSemanticDiagnosticsForFileNoCache(sourceFile: SourceFile, cancellationToken: CancellationToken): Diagnostic[] {
1285+
function getSemanticDiagnosticsForFileNoCache(sourceFile: SourceFile, cancellationToken: CancellationToken): DiagnosticWithLocation[] {
12861286
return runWithCancellationToken(() => {
12871287
// If skipLibCheck is enabled, skip reporting errors if file is a declaration file.
12881288
// If skipDefaultLibCheck is enabled, skip reporting errors if file contains a
@@ -1300,14 +1300,15 @@ namespace ts {
13001300
const includeBindAndCheckDiagnostics = sourceFile.scriptKind === ScriptKind.TS || sourceFile.scriptKind === ScriptKind.TSX ||
13011301
sourceFile.scriptKind === ScriptKind.External || isCheckJs;
13021302
const bindDiagnostics = includeBindAndCheckDiagnostics ? sourceFile.bindDiagnostics : emptyArray;
1303-
const checkDiagnostics = includeBindAndCheckDiagnostics ? typeChecker.getDiagnostics(sourceFile, cancellationToken) : emptyArray;
1303+
// TODO: GH#18217
1304+
const checkDiagnostics = includeBindAndCheckDiagnostics ? typeChecker.getDiagnostics(sourceFile, cancellationToken) as ReadonlyArray<DiagnosticWithLocation> : emptyArray;
13041305
const fileProcessingDiagnosticsInFile = fileProcessingDiagnostics.getDiagnostics(sourceFile.fileName);
13051306
const programDiagnosticsInFile = programDiagnostics.getDiagnostics(sourceFile.fileName);
13061307
let diagnostics = bindDiagnostics.concat(checkDiagnostics, fileProcessingDiagnosticsInFile, programDiagnosticsInFile);
13071308
if (isCheckJs) {
13081309
diagnostics = concatenate(diagnostics, sourceFile.jsDocDiagnostics);
13091310
}
1310-
return filter(diagnostics, shouldReportDiagnostic);
1311+
return filter<DiagnosticWithLocation>(diagnostics, shouldReportDiagnostic);
13111312
});
13121313
}
13131314

@@ -1336,9 +1337,9 @@ namespace ts {
13361337
return true;
13371338
}
13381339

1339-
function getJavaScriptSyntacticDiagnosticsForFile(sourceFile: SourceFile): Diagnostic[] {
1340+
function getJavaScriptSyntacticDiagnosticsForFile(sourceFile: SourceFile): DiagnosticWithLocation[] {
13401341
return runWithCancellationToken(() => {
1341-
const diagnostics: Diagnostic[] = [];
1342+
const diagnostics: DiagnosticWithLocation[] = [];
13421343
let parent: Node = sourceFile;
13431344
walk(sourceFile);
13441345

@@ -1506,20 +1507,20 @@ namespace ts {
15061507
}
15071508
}
15081509

1509-
function createDiagnosticForNodeArray(nodes: NodeArray<Node>, message: DiagnosticMessage, arg0?: string | number, arg1?: string | number, arg2?: string | number): Diagnostic {
1510+
function createDiagnosticForNodeArray(nodes: NodeArray<Node>, message: DiagnosticMessage, arg0?: string | number, arg1?: string | number, arg2?: string | number): DiagnosticWithLocation {
15101511
const start = nodes.pos;
15111512
return createFileDiagnostic(sourceFile, start, nodes.end - start, message, arg0, arg1, arg2);
15121513
}
15131514

15141515
// Since these are syntactic diagnostics, parent might not have been set
15151516
// this means the sourceFile cannot be infered from the node
1516-
function createDiagnosticForNode(node: Node, message: DiagnosticMessage, arg0?: string | number, arg1?: string | number, arg2?: string | number): Diagnostic {
1517+
function createDiagnosticForNode(node: Node, message: DiagnosticMessage, arg0?: string | number, arg1?: string | number, arg2?: string | number): DiagnosticWithLocation {
15171518
return createDiagnosticForNodeInSourceFile(sourceFile, node, message, arg0, arg1, arg2);
15181519
}
15191520
});
15201521
}
15211522

1522-
function getDeclarationDiagnosticsWorker(sourceFile: SourceFile | undefined, cancellationToken: CancellationToken): Diagnostic[] {
1523+
function getDeclarationDiagnosticsWorker(sourceFile: SourceFile, cancellationToken: CancellationToken): ReadonlyArray<DiagnosticWithLocation> {
15231524
return getAndCacheDiagnostics(sourceFile, cancellationToken, cachedDeclarationDiagnosticsForFile, getDeclarationDiagnosticsForFileNoCache);
15241525
}
15251526

@@ -1530,12 +1531,24 @@ namespace ts {
15301531
return ts.getDeclarationDiagnostics(getEmitHost(noop), resolver, sourceFile);
15311532
});
15321533
}
1533-
1534+
function getAndCacheDiagnostics(
1535+
sourceFile: SourceFile,
1536+
cancellationToken: CancellationToken,
1537+
cache: DiagnosticCache,
1538+
getDiagnostics: (sourceFile: SourceFile, cancellationToken: CancellationToken) => DiagnosticWithLocation[]
1539+
): ReadonlyArray<DiagnosticWithLocation>;
1540+
function getAndCacheDiagnostics(
1541+
sourceFile: SourceFile | undefined,
1542+
cancellationToken: CancellationToken,
1543+
cache: DiagnosticCache,
1544+
getDiagnostics: (sourceFile: SourceFile, cancellationToken: CancellationToken) => DiagnosticWithLocation[],
1545+
): ReadonlyArray<Diagnostic>;
15341546
function getAndCacheDiagnostics(
15351547
sourceFile: SourceFile | undefined,
15361548
cancellationToken: CancellationToken,
15371549
cache: DiagnosticCache,
1538-
getDiagnostics: (sourceFile: SourceFile, cancellationToken: CancellationToken) => Diagnostic[]) {
1550+
getDiagnostics: (sourceFile: SourceFile, cancellationToken: CancellationToken) => DiagnosticWithLocation[],
1551+
): ReadonlyArray<Diagnostic> {
15391552

15401553
const cachedResult = sourceFile
15411554
? cache.perFile && cache.perFile.get(sourceFile.path)
@@ -1547,7 +1560,7 @@ namespace ts {
15471560
const result = getDiagnostics(sourceFile, cancellationToken) || emptyArray;
15481561
if (sourceFile) {
15491562
if (!cache.perFile) {
1550-
cache.perFile = createMap<Diagnostic[]>();
1563+
cache.perFile = createMap<DiagnosticWithLocation[]>();
15511564
}
15521565
cache.perFile.set(sourceFile.path, result);
15531566
}
@@ -1557,7 +1570,7 @@ namespace ts {
15571570
return result;
15581571
}
15591572

1560-
function getDeclarationDiagnosticsForFile(sourceFile: SourceFile, cancellationToken: CancellationToken): Diagnostic[] {
1573+
function getDeclarationDiagnosticsForFile(sourceFile: SourceFile, cancellationToken: CancellationToken): ReadonlyArray<DiagnosticWithLocation> {
15611574
return sourceFile.isDeclarationFile ? [] : getDeclarationDiagnosticsWorker(sourceFile, cancellationToken);
15621575
}
15631576

src/compiler/transformers/declarations.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
/*@internal*/
22
namespace ts {
3-
export function getDeclarationDiagnostics(host: EmitHost, resolver: EmitResolver, file: SourceFile | undefined): Diagnostic[] {
3+
export function getDeclarationDiagnostics(host: EmitHost, resolver: EmitResolver, file: SourceFile | undefined): DiagnosticWithLocation[] {
44
if (file && isSourceFileJavaScript(file)) {
55
return []; // No declaration diagnostics for js for now
66
}
77
const compilerOptions = host.getCompilerOptions();
88
const result = transformNodes(resolver, host, compilerOptions, file ? [file] : filter(host.getSourceFiles(), isSourceFileNotJavaScript), [transformDeclarations], /*allowDtsFiles*/ false);
9-
return result.diagnostics;
9+
return result.diagnostics as DiagnosticWithLocation[]; // TODO: GH#18217
1010
}
1111

1212
const declarationEmitNodeBuilderFlags = NodeBuilderFlags.MultilineObjectLiterals | TypeFormatFlags.WriteClassExpressionAsTypeLiteral | NodeBuilderFlags.UseTypeOfFunction | NodeBuilderFlags.UseStructuralFallback | NodeBuilderFlags.AllowEmptyTuple;

src/compiler/types.ts

Lines changed: 15 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2569,16 +2569,16 @@ namespace ts {
25692569

25702570
// File-level diagnostics reported by the parser (includes diagnostics about /// references
25712571
// as well as code diagnostics).
2572-
/* @internal */ parseDiagnostics: Diagnostic[];
2572+
/* @internal */ parseDiagnostics: DiagnosticWithLocation[];
25732573

25742574
// File-level diagnostics reported by the binder.
2575-
/* @internal */ bindDiagnostics: Diagnostic[];
2575+
/* @internal */ bindDiagnostics: DiagnosticWithLocation[];
25762576

25772577
// File-level JSDoc diagnostics reported by the JSDoc parser
2578-
/* @internal */ jsDocDiagnostics?: Diagnostic[];
2578+
/* @internal */ jsDocDiagnostics?: DiagnosticWithLocation[];
25792579

25802580
// Stores additional file-level diagnostics reported by the program
2581-
/* @internal */ additionalSyntacticDiagnostics?: ReadonlyArray<Diagnostic>;
2581+
/* @internal */ additionalSyntacticDiagnostics?: ReadonlyArray<DiagnosticWithLocation>;
25822582

25832583
// Stores a line map for the file.
25842584
// This field should never be used directly to obtain line map, use getLineMap function instead.
@@ -2685,9 +2685,9 @@ namespace ts {
26852685

26862686
getOptionsDiagnostics(cancellationToken?: CancellationToken): ReadonlyArray<Diagnostic>;
26872687
getGlobalDiagnostics(cancellationToken?: CancellationToken): ReadonlyArray<Diagnostic>;
2688-
getSyntacticDiagnostics(sourceFile?: SourceFile, cancellationToken?: CancellationToken): ReadonlyArray<Diagnostic>;
2689-
getSemanticDiagnostics(sourceFile?: SourceFile, cancellationToken?: CancellationToken): ReadonlyArray<Diagnostic>;
2690-
getDeclarationDiagnostics(sourceFile?: SourceFile, cancellationToken?: CancellationToken): ReadonlyArray<Diagnostic>;
2688+
getSyntacticDiagnostics(sourceFile?: SourceFile, cancellationToken?: CancellationToken): ReadonlyArray<DiagnosticWithLocation>;
2689+
getSemanticDiagnostics(sourceFile?: SourceFile, cancellationToken?: CancellationToken): ReadonlyArray<DiagnosticWithLocation>;
2690+
getDeclarationDiagnostics(sourceFile?: SourceFile, cancellationToken?: CancellationToken): ReadonlyArray<DiagnosticWithLocation>;
26912691
getConfigFileParsingDiagnostics(): ReadonlyArray<Diagnostic>;
26922692

26932693
/**
@@ -2999,7 +2999,7 @@ namespace ts {
29992999
* Does *not* get *all* suggestion diagnostics, just the ones that were convenient to report in the checker.
30003000
* Others are added in computeSuggestionDiagnostics.
30013001
*/
3002-
/* @internal */ getSuggestionDiagnostics(file: SourceFile): ReadonlyArray<Diagnostic>;
3002+
/* @internal */ getSuggestionDiagnostics(file: SourceFile): ReadonlyArray<DiagnosticWithLocation>;
30033003

30043004
/**
30053005
* Depending on the operation performed, it may be appropriate to throw away the checker
@@ -4115,6 +4115,11 @@ namespace ts {
41154115
code: number;
41164116
source?: string;
41174117
}
4118+
export interface DiagnosticWithLocation extends Diagnostic {
4119+
file: SourceFile;
4120+
start: number;
4121+
length: number;
4122+
}
41184123

41194124
export enum DiagnosticCategory {
41204125
Warning,
@@ -5136,7 +5141,8 @@ namespace ts {
51365141

51375142
// If fileName is provided, gets all the diagnostics associated with that file name.
51385143
// Otherwise, returns all the diagnostics (global and file associated) in this collection.
5139-
getDiagnostics(fileName?: string): Diagnostic[];
5144+
getDiagnostics(fileName: string): DiagnosticWithLocation[];
5145+
getDiagnostics(): Diagnostic[];
51405146

51415147
reattachFileDiagnostics(newFile: SourceFile): void;
51425148
}

0 commit comments

Comments
 (0)