Skip to content

Commit eb8d25c

Browse files
committed
fix: templates incorrectly identified as not in Angular project (#1373)
* fix: templates incorrectly identified as not in Angular project The fix from #1360 unfortunately did not quite work because LSP appears to return `null` rather than `undefined`. I have not yet found in the source code where this might happen, but the LSP spec does favor returning `null` over `undefined` - https://microsoft.github.io/language-server-protocol/specifications/specification-current/. * refactor: Prefer `null` instead of `undefined` in language server The LSP spec favors returning `null` over `undefined` - https://microsoft.github.io/language-server-protocol/specifications/specification-current/. This commit also updates other locations in the `session` which were returning `undefined` to be more consistent with LSP return values (`null`). There is an odd dicotomy here where the TS language service favors `undefined` instead but the LSP prefers `null`. (cherry picked from commit 601e2f9)
1 parent db44816 commit eb8d25c

File tree

3 files changed

+44
-44
lines changed

3 files changed

+44
-44
lines changed

client/src/client.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -146,7 +146,7 @@ export class AngularLanguageClient implements vscode.Disposable {
146146
const response = await this.client.sendRequest(IsInAngularProject, {
147147
textDocument: this.client.code2ProtocolConverter.asTextDocumentIdentifier(doc),
148148
});
149-
if (response === undefined) {
149+
if (response == null) {
150150
// If the response indicates the answer can't be determined at the moment, return `false`
151151
// but do not cache the result so we can try to get the real answer on follow-up requests.
152152
return false;

common/requests.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ export interface GetTcbResponse {
3131
}
3232

3333
export const IsInAngularProject =
34-
new lsp.RequestType<IsInAngularProjectParams, boolean|undefined, /* error */ void>(
34+
new lsp.RequestType<IsInAngularProjectParams, boolean|null, /* error */ void>(
3535
'angular/isAngularCoreInOwningProject');
3636

3737
export interface IsInAngularProjectParams {

server/src/session.ts

Lines changed: 42 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -175,42 +175,42 @@ export class Session {
175175
conn.onSignatureHelp(p => this.onSignatureHelp(p));
176176
}
177177

178-
private isInAngularProject(params: IsInAngularProjectParams): boolean|undefined {
178+
private isInAngularProject(params: IsInAngularProjectParams): boolean|null {
179179
const filePath = uriToFilePath(params.textDocument.uri);
180180
if (!filePath) {
181181
return false;
182182
}
183183
const lsAndScriptInfo = this.getLSAndScriptInfo(params.textDocument);
184184
if (!lsAndScriptInfo) {
185-
// If we cannot get language service / script info, return undefined to indicate we don't know
185+
// If we cannot get language service / script info, return null to indicate we don't know
186186
// the answer definitively.
187-
return undefined;
187+
return null;
188188
}
189189
const project = this.getDefaultProjectForScriptInfo(lsAndScriptInfo.scriptInfo);
190190
if (!project) {
191-
// If we cannot get project, return undefined to indicate we don't know
191+
// If we cannot get project, return null to indicate we don't know
192192
// the answer definitively.
193-
return undefined;
193+
return null;
194194
}
195195
const angularCore = project.getFileNames().find(isAngularCore);
196196
return angularCore !== undefined;
197197
}
198198

199-
private onGetTcb(params: GetTcbParams): GetTcbResponse|undefined {
199+
private onGetTcb(params: GetTcbParams): GetTcbResponse|null {
200200
const lsInfo = this.getLSAndScriptInfo(params.textDocument);
201-
if (lsInfo === undefined) {
202-
return undefined;
201+
if (lsInfo === null) {
202+
return null;
203203
}
204204
const {languageService, scriptInfo} = lsInfo;
205205
const offset = lspPositionToTsPosition(scriptInfo, params.position);
206206
const response = languageService.getTcb(scriptInfo.fileName, offset);
207207
if (response === undefined) {
208-
return undefined;
208+
return null;
209209
}
210210
const {fileName: tcfName} = response;
211211
const tcfScriptInfo = this.projectService.getScriptInfo(tcfName);
212212
if (!tcfScriptInfo) {
213-
return undefined;
213+
return null;
214214
}
215215
return {
216216
uri: filePathToUri(tcfName),
@@ -219,10 +219,10 @@ export class Session {
219219
};
220220
}
221221

222-
private onGetComponentsWithTemplateFile(params: any): lsp.Location[]|undefined {
222+
private onGetComponentsWithTemplateFile(params: any): lsp.Location[]|null {
223223
const lsInfo = this.getLSAndScriptInfo(params.textDocument);
224-
if (lsInfo === undefined) {
225-
return undefined;
224+
if (lsInfo === null) {
225+
return null;
226226
}
227227
const {languageService, scriptInfo} = lsInfo;
228228
const documentSpans = languageService.getComponentLocationsForTemplate(scriptInfo.fileName);
@@ -238,18 +238,18 @@ export class Session {
238238
return results;
239239
}
240240

241-
private onSignatureHelp(params: lsp.SignatureHelpParams): lsp.SignatureHelp|undefined {
241+
private onSignatureHelp(params: lsp.SignatureHelpParams): lsp.SignatureHelp|null {
242242
const lsInfo = this.getLSAndScriptInfo(params.textDocument);
243-
if (lsInfo === undefined) {
244-
return undefined;
243+
if (lsInfo === null) {
244+
return null;
245245
}
246246

247247
const {languageService, scriptInfo} = lsInfo;
248248
const offset = lspPositionToTsPosition(scriptInfo, params.position);
249249

250250
const help = languageService.getSignatureHelpItems(scriptInfo.fileName, offset, undefined);
251251
if (help === undefined) {
252-
return undefined;
252+
return null;
253253
}
254254

255255
return {
@@ -289,9 +289,9 @@ export class Session {
289289
};
290290
}
291291

292-
private onCodeLens(params: lsp.CodeLensParams): lsp.CodeLens[]|undefined {
292+
private onCodeLens(params: lsp.CodeLensParams): lsp.CodeLens[]|null {
293293
if (!params.textDocument.uri.endsWith('.html') || !this.isInAngularProject(params)) {
294-
return undefined;
294+
return null;
295295
}
296296
const position = lsp.Position.create(0, 0);
297297
const topOfDocument = lsp.Range.create(position, position);
@@ -307,7 +307,7 @@ export class Session {
307307

308308
private onCodeLensResolve(params: lsp.CodeLens): lsp.CodeLens {
309309
const components = this.onGetComponentsWithTemplateFile({textDocument: params.data});
310-
if (components === undefined || components.length === 0) {
310+
if (components === null || components.length === 0) {
311311
// While the command is supposed to be optional, vscode will show `!!MISSING: command!!` that
312312
// fails if you click on it when a command is not provided. Instead, throwing an error will
313313
// make vscode show the text "no commands" (and it's not a link).
@@ -752,7 +752,7 @@ export class Session {
752752

753753
private onDefinition(params: lsp.TextDocumentPositionParams): lsp.LocationLink[]|undefined {
754754
const lsInfo = this.getLSAndScriptInfo(params.textDocument);
755-
if (lsInfo === undefined) {
755+
if (lsInfo === null) {
756756
return;
757757
}
758758
const {languageService, scriptInfo} = lsInfo;
@@ -767,7 +767,7 @@ export class Session {
767767

768768
private onTypeDefinition(params: lsp.TextDocumentPositionParams): lsp.LocationLink[]|undefined {
769769
const lsInfo = this.getLSAndScriptInfo(params.textDocument);
770-
if (lsInfo === undefined) {
770+
if (lsInfo === null) {
771771
return;
772772
}
773773
const {languageService, scriptInfo} = lsInfo;
@@ -781,7 +781,7 @@ export class Session {
781781

782782
private onRenameRequest(params: lsp.RenameParams): lsp.WorkspaceEdit|undefined {
783783
const lsInfo = this.getLSAndScriptInfo(params.textDocument);
784-
if (lsInfo === undefined) {
784+
if (lsInfo === null) {
785785
return;
786786
}
787787
const {languageService, scriptInfo} = lsInfo;
@@ -810,7 +810,7 @@ export class Session {
810810
const fileEdits = changes[location.fileName];
811811

812812
const lsInfo = this.getLSAndScriptInfo(location.fileName);
813-
if (lsInfo === undefined) {
813+
if (lsInfo === null) {
814814
return changes;
815815
}
816816
const range = tsTextSpanToLspRange(lsInfo.scriptInfo, location.textSpan);
@@ -822,10 +822,10 @@ export class Session {
822822
}
823823

824824
private onPrepareRename(params: lsp.PrepareRenameParams):
825-
{range: lsp.Range, placeholder: string}|undefined {
825+
{range: lsp.Range, placeholder: string}|null {
826826
const lsInfo = this.getLSAndScriptInfo(params.textDocument);
827-
if (lsInfo === undefined) {
828-
return;
827+
if (lsInfo === null) {
828+
return null;
829829
}
830830
const {languageService, scriptInfo} = lsInfo;
831831
if (scriptInfo.scriptKind === ts.ScriptKind.TS) {
@@ -836,13 +836,13 @@ export class Session {
836836
}
837837
const project = this.getDefaultProjectForScriptInfo(scriptInfo);
838838
if (project === undefined || this.renameDisabledProjects.has(project)) {
839-
return;
839+
return null;
840840
}
841841

842842
const offset = lspPositionToTsPosition(scriptInfo, params.position);
843843
const renameInfo = languageService.getRenameInfo(scriptInfo.fileName, offset);
844844
if (!renameInfo.canRename) {
845-
return undefined;
845+
return null;
846846
}
847847
const range = tsTextSpanToLspRange(scriptInfo, renameInfo.triggerSpan);
848848
return {
@@ -853,7 +853,7 @@ export class Session {
853853

854854
private onReferences(params: lsp.TextDocumentPositionParams): lsp.Location[]|undefined {
855855
const lsInfo = this.getLSAndScriptInfo(params.textDocument);
856-
if (lsInfo === undefined) {
856+
if (lsInfo === null) {
857857
return;
858858
}
859859
const {languageService, scriptInfo} = lsInfo;
@@ -899,28 +899,28 @@ export class Session {
899899
}
900900

901901
private getLSAndScriptInfo(textDocumentOrFileName: lsp.TextDocumentIdentifier|string):
902-
{languageService: NgLanguageService, scriptInfo: ts.server.ScriptInfo}|undefined {
902+
{languageService: NgLanguageService, scriptInfo: ts.server.ScriptInfo}|null {
903903
const filePath = lsp.TextDocumentIdentifier.is(textDocumentOrFileName) ?
904904
uriToFilePath(textDocumentOrFileName.uri) :
905905
textDocumentOrFileName;
906906
const scriptInfo = this.projectService.getScriptInfo(filePath);
907907
if (!scriptInfo) {
908908
this.error(`Script info not found for ${filePath}`);
909-
return;
909+
return null;
910910
}
911911

912912
const project = this.getDefaultProjectForScriptInfo(scriptInfo);
913913
if (!project?.languageServiceEnabled) {
914-
return;
914+
return null;
915915
}
916916
if (project.isClosed()) {
917917
scriptInfo.detachFromProject(project);
918918
this.logger.info(`Failed to get language service for closed project ${project.projectName}.`);
919-
return undefined;
919+
return null;
920920
}
921921
const languageService = project.getLanguageService();
922922
if (!isNgLanguageService(languageService)) {
923-
return undefined;
923+
return null;
924924
}
925925
return {
926926
languageService,
@@ -930,7 +930,7 @@ export class Session {
930930

931931
private onHover(params: lsp.TextDocumentPositionParams) {
932932
const lsInfo = this.getLSAndScriptInfo(params.textDocument);
933-
if (lsInfo === undefined) {
933+
if (lsInfo === null) {
934934
return;
935935
}
936936
const {languageService, scriptInfo} = lsInfo;
@@ -965,7 +965,7 @@ export class Session {
965965

966966
private onCompletion(params: lsp.CompletionParams) {
967967
const lsInfo = this.getLSAndScriptInfo(params.textDocument);
968-
if (lsInfo === undefined) {
968+
if (lsInfo === null) {
969969
return;
970970
}
971971
const {languageService, scriptInfo} = lsInfo;
@@ -992,7 +992,7 @@ export class Session {
992992

993993
const {filePath, position} = data;
994994
const lsInfo = this.getLSAndScriptInfo(filePath);
995-
if (lsInfo === undefined) {
995+
if (lsInfo === null) {
996996
return item;
997997
}
998998
const {languageService, scriptInfo} = lsInfo;
@@ -1068,25 +1068,25 @@ export class Session {
10681068
*
10691069
* @returns main declaration file in `@angular/core`.
10701070
*/
1071-
private findAngularCore(project: ts.server.Project): string|undefined {
1071+
private findAngularCore(project: ts.server.Project): string|null {
10721072
const {projectName} = project;
10731073
if (!project.languageServiceEnabled) {
10741074
this.info(
10751075
`Language service is already disabled for ${projectName}. ` +
10761076
`This could be due to non-TS files that exceeded the size limit (${
10771077
ts.server.maxProgramSizeForNonTsFiles} bytes).` +
10781078
`Please check log file for details.`);
1079-
return;
1079+
return null;
10801080
}
10811081
if (!project.hasRoots() || project.isNonTsProject()) {
1082-
return undefined;
1082+
return null;
10831083
}
10841084
const angularCore = project.getFileNames().find(isAngularCore);
10851085
if (angularCore === undefined && project.getExcludedFiles().some(isAngularCore)) {
10861086
this.info(
10871087
`Please check your tsconfig.json to make sure 'node_modules' directory is not excluded.`);
10881088
}
1089-
return angularCore;
1089+
return angularCore ?? null;
10901090
}
10911091

10921092
/**

0 commit comments

Comments
 (0)