Skip to content

Commit d027ee1

Browse files
committed
feat(language-service): enable auto-apply optional chaining on nullable symbol
1 parent babb0d3 commit d027ee1

File tree

7 files changed

+36
-5
lines changed

7 files changed

+36
-5
lines changed

client/src/client.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -428,6 +428,12 @@ function constructArgs(ctx: vscode.ExtensionContext): string[] {
428428
args.push('--viewEngine');
429429
}
430430

431+
const includeAutomaticOptionalChainCompletions =
432+
config.get<boolean>('angular.suggest.includeAutomaticOptionalChainCompletions');
433+
if (includeAutomaticOptionalChainCompletions) {
434+
args.push('--includeAutomaticOptionalChainCompletions');
435+
}
436+
431437
const tsdk: string|null = config.get('typescript.tsdk', null);
432438
const tsProbeLocations = getProbeLocations(tsdk, ctx.extensionPath);
433439
args.push('--tsProbeLocations', tsProbeLocations.join(','));

integration/lsp/viewengine_spec.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,7 @@ describe('Angular language server', () => {
6565
},
6666
newText: 'charAt()',
6767
},
68+
filterText: 'charAt()',
6869
// The 'data' field is only meaningful in Ivy mode.
6970
data: jasmine.anything(),
7071
});

package.json

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,11 @@
9999
],
100100
"default": "off",
101101
"description": "Traces the communication between VS Code and the Angular language server."
102+
},
103+
"angular.suggest.includeAutomaticOptionalChainCompletions": {
104+
"type": "boolean",
105+
"default": true,
106+
"description": "Enable/disable showing completions on potentially undefined values that insert an optional chain call. Requires TS 3.7+ and strict null checks to be enabled."
102107
}
103108
}
104109
},

server/src/cmdline_utils.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ interface CommandLineOptions {
3737
logToConsole: boolean;
3838
ngProbeLocations: string[];
3939
tsProbeLocations: string[];
40+
includeAutomaticOptionalChainCompletions: boolean;
4041
}
4142

4243
export function parseCommandLine(argv: string[]): CommandLineOptions {
@@ -48,6 +49,8 @@ export function parseCommandLine(argv: string[]): CommandLineOptions {
4849
logToConsole: hasArgument(argv, '--logToConsole'),
4950
ngProbeLocations: parseStringArray(argv, '--ngProbeLocations'),
5051
tsProbeLocations: parseStringArray(argv, '--tsProbeLocations'),
52+
includeAutomaticOptionalChainCompletions:
53+
hasArgument(argv, '--includeAutomaticOptionalChainCompletions'),
5154
};
5255
}
5356

server/src/completion.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,11 @@ export function tsCompletionEntryToLspCompletionItem(
120120
const insertText = entry.insertText || entry.name;
121121
item.textEdit = createTextEdit(scriptInfo, entry, position, insertText, insertReplaceSupport);
122122

123+
// If the user enables the config `includeAutomaticOptionalChainCompletions`, the `insertText`
124+
// range will include the dot. the `insertText` should be assigned to the `filterText` to filter
125+
// the completion items.
126+
item.filterText = entry.insertText;
127+
123128
item.data = {
124129
kind: 'ngCompletionOriginData',
125130
filePath: scriptInfo.fileName,

server/src/server.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ function main() {
4444
resolvedNgLsPath: ng.resolvedPath,
4545
ivy: isG3 ? true : options.ivy,
4646
logToConsole: options.logToConsole,
47+
includeAutomaticOptionalChainCompletions: options.includeAutomaticOptionalChainCompletions
4748
});
4849

4950
// Log initialization info

server/src/session.ts

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ export interface SessionOptions {
3030
resolvedNgLsPath: string;
3131
ivy: boolean;
3232
logToConsole: boolean;
33+
includeAutomaticOptionalChainCompletions: boolean;
3334
}
3435

3536
enum LanguageId {
@@ -53,6 +54,7 @@ export class Session {
5354
private readonly configuredProjToExternalProj = new Map<string, string>();
5455
private readonly logToConsole: boolean;
5556
private readonly openFiles = new MruTracker();
57+
private readonly includeAutomaticOptionalChainCompletions: boolean;
5658
// Tracks the spawn order and status of the `ngcc` processes. This allows us to ensure we enable
5759
// the LS in the same order the projects were created in.
5860
private projectNgccQueue: Array<{project: ts.server.Project, done: boolean}> = [];
@@ -68,6 +70,8 @@ export class Session {
6870
private clientCapabilities: lsp.ClientCapabilities = {};
6971

7072
constructor(options: SessionOptions) {
73+
this.includeAutomaticOptionalChainCompletions =
74+
options.includeAutomaticOptionalChainCompletions;
7175
this.logger = options.logger;
7276
this.ivy = options.ivy;
7377
this.logToConsole = options.logToConsole;
@@ -978,11 +982,17 @@ export class Session {
978982
}
979983
const {languageService, scriptInfo} = lsInfo;
980984
const offset = lspPositionToTsPosition(scriptInfo, params.position);
981-
const completions = languageService.getCompletionsAtPosition(
982-
scriptInfo.fileName, offset,
983-
{
984-
// options
985-
});
985+
986+
let options: ts.GetCompletionsAtPositionOptions = {};
987+
if (this.includeAutomaticOptionalChainCompletions) {
988+
options = {
989+
includeAutomaticOptionalChainCompletions: this.includeAutomaticOptionalChainCompletions,
990+
includeCompletionsWithInsertText: this.includeAutomaticOptionalChainCompletions,
991+
};
992+
}
993+
994+
const completions =
995+
languageService.getCompletionsAtPosition(scriptInfo.fileName, offset, options);
986996
if (!completions) {
987997
return;
988998
}

0 commit comments

Comments
 (0)