Skip to content

Commit c03da8b

Browse files
committed
Add consolidated IntelliSense status item
Fixes microsoft#133731
1 parent 74d4b33 commit c03da8b

File tree

3 files changed

+61
-91
lines changed

3 files changed

+61
-91
lines changed

extensions/typescript-language-features/src/typeScriptServiceClientHost.ts

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,7 @@ import { ILogDirectoryProvider } from './tsServer/logDirectoryProvider';
2020
import { TsServerProcessFactory } from './tsServer/server';
2121
import { ITypeScriptVersionProvider } from './tsServer/versionProvider';
2222
import TypeScriptServiceClient from './typescriptServiceClient';
23-
import { CapabilitiesStatus } from './ui/capabilitiesStatus';
24-
import { ProjectStatus } from './ui/projectStatus';
23+
import { IntellisenseStatus } from './ui/intellisenseStatus';
2524
import { VersionStatus } from './ui/versionStatus';
2625
import { ActiveJsTsEditorTracker } from './utils/activeJsTsEditorTracker';
2726
import { coalesce, flatten } from './utils/arrays';
@@ -94,9 +93,8 @@ export default class TypeScriptServiceClientHost extends Disposable {
9493
this.client.onConfigDiagnosticsReceived(diag => this.configFileDiagnosticsReceived(diag), null, this._disposables);
9594
this.client.onResendModelsRequested(() => this.populateService(), null, this._disposables);
9695

97-
this._register(new CapabilitiesStatus(this.client));
9896
this._register(new VersionStatus(this.client));
99-
this._register(new ProjectStatus(this.client, services.commandManager, services.activeJsTsEditorTracker));
97+
this._register(new IntellisenseStatus(this.client, services.commandManager, services.activeJsTsEditorTracker));
10098
this._register(new AtaProgressReporter(this.client));
10199
this.typingsStatus = this._register(new TypingsStatus(this.client));
102100
this._register(LargeProjectStatus.create(this.client));

extensions/typescript-language-features/src/ui/capabilitiesStatus.ts

Lines changed: 0 additions & 46 deletions
This file was deleted.

extensions/typescript-language-features/src/ui/projectStatus.ts renamed to extensions/typescript-language-features/src/ui/intellisenseStatus.ts

Lines changed: 59 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
import * as vscode from 'vscode';
77
import * as nls from 'vscode-nls';
88
import { CommandManager } from '../commands/commandManager';
9-
import { ITypeScriptServiceClient } from '../typescriptService';
9+
import { ClientCapability, ITypeScriptServiceClient } from '../typescriptService';
1010
import { ActiveJsTsEditorTracker } from '../utils/activeJsTsEditorTracker';
1111
import { Disposable } from '../utils/dispose';
1212
import { jsTsLanguageModes, isSupportedLanguageMode } from '../utils/languageModeIds';
@@ -15,11 +15,13 @@ import { isImplicitProjectConfigFile, openOrCreateConfig, openProjectConfigForFi
1515
const localize = nls.loadMessageBundle();
1616

1717

18-
namespace ProjectInfoState {
19-
export const enum Type { None, Pending, Resolved }
18+
namespace IntellisenseState {
19+
export const enum Type { None, Pending, Resolved, SyntaxOnly }
2020

2121
export const None = Object.freeze({ type: Type.None } as const);
2222

23+
export const SyntaxOnly = Object.freeze({ type: Type.SyntaxOnly } as const);
24+
2325
export class Pending {
2426
public readonly type = Type.Pending;
2527

@@ -39,18 +41,18 @@ namespace ProjectInfoState {
3941
) { }
4042
}
4143

42-
export type State = typeof None | Pending | Resolved;
44+
export type State = typeof None | Pending | Resolved | typeof SyntaxOnly;
4345
}
4446

45-
export class ProjectStatus extends Disposable {
47+
export class IntellisenseStatus extends Disposable {
4648

4749
public readonly openOpenConfigCommandId = '_typescript.openConfig';
4850
public readonly createConfigCommandId = '_typescript.createConfig';
4951

5052
private readonly _statusItem: vscode.LanguageStatusItem;
5153

5254
private _ready = false;
53-
private _state: ProjectInfoState.State = ProjectInfoState.None;
55+
private _state: IntellisenseState.State = IntellisenseState.None;
5456

5557
constructor(
5658
private readonly _client: ITypeScriptServiceClient,
@@ -60,15 +62,14 @@ export class ProjectStatus extends Disposable {
6062
super();
6163

6264
this._statusItem = this._register(vscode.languages.createLanguageStatusItem('typescript.projectStatus', jsTsLanguageModes));
63-
this._statusItem.name = localize('statusItem.name', "Project config");
64-
this._statusItem.text = 'TSConfig';
65+
this._statusItem.name = localize('statusItem.name', "JS/TS IntelliSense Status");
6566

6667
commandManager.register({
6768
id: this.openOpenConfigCommandId,
6869
execute: async (rootPath: string) => {
69-
if (this._state.type === ProjectInfoState.Type.Resolved) {
70+
if (this._state.type === IntellisenseState.Type.Resolved) {
7071
await openProjectConfigOrPromptToCreate(ProjectType.TypeScript, this._client, rootPath, this._state.configFile);
71-
} else if (this._state.type === ProjectInfoState.Type.Pending) {
72+
} else if (this._state.type === IntellisenseState.Type.Pending) {
7273
await openProjectConfigForFile(ProjectType.TypeScript, this._client, this._state.resource);
7374
}
7475
},
@@ -89,79 +90,96 @@ export class ProjectStatus extends Disposable {
8990
}
9091

9192
private async updateStatus() {
92-
const editor = this._activeTextEditorManager.activeJsTsEditor;
93-
if (!editor) {
94-
this.updateState(ProjectInfoState.None);
93+
const doc = this._activeTextEditorManager.activeJsTsEditor?.document;
94+
if (!doc || !isSupportedLanguageMode(doc)) {
95+
this.updateState(IntellisenseState.None);
9596
return;
9697
}
9798

98-
const doc = editor.document;
99-
if (isSupportedLanguageMode(doc)) {
100-
const file = this._client.toOpenedFilePath(doc, { suppressAlertOnFailure: true });
101-
if (file) {
102-
if (!this._ready) {
103-
return;
104-
}
99+
if (!this._client.hasCapabilityForResource(doc.uri, ClientCapability.Semantic)) {
100+
this.updateState(IntellisenseState.SyntaxOnly);
101+
return;
102+
}
105103

106-
const pendingState = new ProjectInfoState.Pending(doc.uri);
107-
this.updateState(pendingState);
104+
const file = this._client.toOpenedFilePath(doc, { suppressAlertOnFailure: true });
105+
if (!file) {
106+
this.updateState(IntellisenseState.None);
107+
return;
108+
}
108109

109-
const response = await this._client.execute('projectInfo', { file, needFileNameList: false }, pendingState.cancellation.token);
110-
if (response.type === 'response' && response.body) {
111-
if (this._state === pendingState) {
112-
this.updateState(new ProjectInfoState.Resolved(doc.uri, response.body.configFileName));
113-
}
114-
}
115-
return;
116-
}
110+
if (!this._ready) {
111+
return;
117112
}
118113

119-
this.updateState(ProjectInfoState.None);
114+
const pendingState = new IntellisenseState.Pending(doc.uri);
115+
this.updateState(pendingState);
116+
117+
const response = await this._client.execute('projectInfo', { file, needFileNameList: false }, pendingState.cancellation.token);
118+
if (response.type === 'response' && response.body) {
119+
if (this._state === pendingState) {
120+
this.updateState(new IntellisenseState.Resolved(doc.uri, response.body.configFileName));
121+
}
122+
}
120123
}
121124

122-
private updateState(newState: ProjectInfoState.State): void {
125+
private updateState(newState: IntellisenseState.State): void {
123126
if (this._state === newState) {
124127
return;
125128
}
126129

127-
if (this._state.type === ProjectInfoState.Type.Pending) {
130+
if (this._state.type === IntellisenseState.Type.Pending) {
128131
this._state.cancellation.cancel();
129132
this._state.cancellation.dispose();
130133
}
131134

132135
this._state = newState;
133136

134137
switch (this._state.type) {
135-
case ProjectInfoState.Type.None:
138+
case IntellisenseState.Type.None:
136139
break;
137140

138-
case ProjectInfoState.Type.Pending:
139-
this._statusItem.detail = '$(loading~spin)';
141+
case IntellisenseState.Type.Pending:
142+
this._statusItem.text = '$(loading~spin)';
143+
this._statusItem.detail = localize('pending.detail', 'Loading IntelliSense status');
140144
this._statusItem.command = undefined;
141145
break;
142146

143-
case ProjectInfoState.Type.Resolved:
147+
case IntellisenseState.Type.Resolved:
144148
const rootPath = this._client.getWorkspaceRootForResource(this._state.resource);
145149
if (!rootPath) {
146150
return;
147151
}
148152

149153
if (isImplicitProjectConfigFile(this._state.configFile)) {
150-
this._statusItem.detail = localize('item.noTsConfig.detail', "None");
154+
this._statusItem.text = localize('resolved.detail.noTsConfig', "No tsconfig");
155+
this._statusItem.detail = undefined;
151156
this._statusItem.command = {
152157
command: this.createConfigCommandId,
153-
title: localize('create.command', "Create tsconfig"),
158+
title: localize('resolved.command.title.create', "Create tsconfig"),
154159
arguments: [rootPath],
155160
};
156161
} else {
157-
this._statusItem.detail = vscode.workspace.asRelativePath(this._state.configFile);
162+
this._statusItem.text = vscode.workspace.asRelativePath(this._state.configFile);
163+
this._statusItem.detail = undefined;
158164
this._statusItem.command = {
159165
command: this.openOpenConfigCommandId,
160-
title: localize('item.command', "Open config file"),
166+
title: localize('resolved.command.title.open', "Open config file"),
161167
arguments: [rootPath],
162168
};
163169
}
164170
break;
171+
172+
case IntellisenseState.Type.SyntaxOnly:
173+
this._statusItem.text = localize('syntaxOnly.text', 'Partial Mode');
174+
this._statusItem.detail = localize('syntaxOnly.detail', 'Project Wide IntelliSense not available');
175+
this._statusItem.command = {
176+
title: localize('syntaxOnly.command.title.learnMore', "Learn More"),
177+
command: 'vscode.open',
178+
arguments: [
179+
vscode.Uri.parse('https://go.microsoft.com/fwlink/?linkid=2114477'), // TODO: add proper link once published
180+
]
181+
};
182+
break;
165183
}
166184
}
167185
}

0 commit comments

Comments
 (0)