Skip to content

Commit 04b215b

Browse files
authored
feat(server): add related information to diagnostics (#1492)
Show related information in the diagnostics generated for the language service.
1 parent 4fcbdb7 commit 04b215b

File tree

3 files changed

+36
-1
lines changed

3 files changed

+36
-1
lines changed

integration/lsp/ivy_spec.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,11 @@ describe('Angular Ivy language server', () => {
9999
expect(diagnostics.length).toBe(1);
100100
expect(diagnostics[0].message)
101101
.toBe(`Property 'doesnotexist' does not exist on type 'FooComponent'.`);
102+
expect(diagnostics[0].relatedInformation).toBeDefined();
103+
expect(diagnostics[0].relatedInformation!.length).toBe(1);
104+
expect(diagnostics[0].relatedInformation![0].message)
105+
.toBe(`Error occurs in the template of component FooComponent.`);
106+
expect(diagnostics[0].relatedInformation![0].location.uri).toBe(FOO_COMPONENT_URI);
102107
});
103108

104109
it('should support request cancellation', async () => {

server/src/diagnostic.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88

99
import * as ts from 'typescript/lib/tsserverlibrary';
1010
import * as lsp from 'vscode-languageserver';
11-
import {tsTextSpanToLspRange} from './utils';
11+
import {tsRelatedInformationToLspRelatedInformation, tsTextSpanToLspRange} from './utils';
1212

1313
/**
1414
* Convert ts.DiagnosticCategory to lsp.DiagnosticSeverity
@@ -45,5 +45,6 @@ export function tsDiagnosticToLspDiagnostic(
4545
tsDiagnosticCategoryToLspDiagnosticSeverity(tsDiag.category),
4646
tsDiag.code,
4747
tsDiag.source,
48+
tsRelatedInformationToLspRelatedInformation(scriptInfo, tsDiag.relatedInformation),
4849
);
4950
}

server/src/utils.ts

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,35 @@ export function lspRangeToTsPositions(
7777
return [start, end];
7878
}
7979

80+
/**
81+
* Convert a ts.DiagnosticRelatedInformation array to a
82+
* lsp.DiagnosticRelatedInformation array
83+
* @param scriptInfo Used to determine the offsets.
84+
* @param relatedInfo
85+
*/
86+
export function tsRelatedInformationToLspRelatedInformation(
87+
scriptInfo: ts.server.ScriptInfo,
88+
relatedInfo?: ts.DiagnosticRelatedInformation[]): lsp.DiagnosticRelatedInformation[]|undefined {
89+
if (relatedInfo === undefined) return;
90+
const lspRelatedInfo: lsp.DiagnosticRelatedInformation[] = [];
91+
for (const info of relatedInfo) {
92+
if (info.file === undefined || info.start === undefined || info.length === undefined) continue;
93+
const textSpan: ts.TextSpan = {
94+
start: info.start,
95+
length: info.length,
96+
};
97+
const location = lsp.Location.create(
98+
filePathToUri(info.file.fileName),
99+
tsTextSpanToLspRange(scriptInfo, textSpan),
100+
);
101+
lspRelatedInfo.push(lsp.DiagnosticRelatedInformation.create(
102+
location,
103+
ts.flattenDiagnosticMessageText(info.messageText, '\n'),
104+
));
105+
}
106+
return lspRelatedInfo;
107+
}
108+
80109
export function isConfiguredProject(project: ts.server.Project):
81110
project is ts.server.ConfiguredProject {
82111
return project.projectKind === ts.server.ProjectKind.Configured;

0 commit comments

Comments
 (0)