Skip to content

Commit

Permalink
Add "Configure Intellisense" Status Bar Item (#10690)
Browse files Browse the repository at this point in the history
* change description for natvisDiagnostics

* Add "Configure Intellisense" Status Bar Item

* resolve PR
  • Loading branch information
browntarik authored Mar 24, 2023
1 parent 2ad0a95 commit c417da6
Show file tree
Hide file tree
Showing 7 changed files with 109 additions and 28 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,7 @@ export class CodeActionProvider implements vscode.CodeActionProvider {
} else if (command.command === 'C_Cpp.CreateDeclarationOrDefinition' && (command.arguments ?? []).length === 0) {
command.arguments = ['codeAction']; // We report the sender of the command
} else if (command.command === "C_Cpp.SelectDefaultCompiler") {
command.arguments = ['codeAction'];
hasSelectDefaultCompiler = true;
if (this.client.configuration.CurrentConfiguration?.rawCompilerPath !== undefined) {
hasConfigurationCompilerPath = true;
Expand Down
35 changes: 20 additions & 15 deletions Extension/src/LanguageServer/client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -760,7 +760,7 @@ export interface Client {
selectionChanged(selection: Range): void;
resetDatabase(): void;
deactivate(): void;
promptSelectCompiler(command: boolean): Promise<void>;
promptSelectCompiler(command: boolean, sender?: any): Promise<void>;
pauseParsing(): void;
resumeParsing(): void;
PauseCodeAnalysis(): void;
Expand Down Expand Up @@ -947,17 +947,17 @@ export class DefaultClient implements Client {
return (selection) ? selection.index : -1;
}

public async showPrompt(buttonMessage: string, showSecondPrompt: boolean): Promise<void> {
public async showPrompt(buttonMessage: string, showSecondPrompt: boolean, sender?: any): Promise<void> {
if (secondPromptCounter < 1) {
const value: string | undefined = await vscode.window.showInformationMessage(localize("setCompiler.message", "You do not have IntelliSense configured. Unless you set your own configurations, IntelliSense may not be functional."), buttonMessage);
secondPromptCounter++;
if (value === buttonMessage) {
this.handleCompilerQuickPick(showSecondPrompt);
this.handleCompilerQuickPick(showSecondPrompt, sender);
}
}
}

public async handleCompilerQuickPick(showSecondPrompt: boolean): Promise<void> {
public async handleCompilerQuickPick(showSecondPrompt: boolean, sender?: any): Promise<void> {
const settings: CppSettings = new CppSettings();
const selectCompiler: string = localize("selectCompiler.string", "Select Compiler");
const paths: string[] = [];
Expand Down Expand Up @@ -987,16 +987,17 @@ export class DefaultClient implements Client {
if (index === -1) {
action = "escaped";
if (showSecondPrompt && !compilerDefaults.trustedCompilerFound) {
this.showPrompt(selectCompiler, true);
this.showPrompt(selectCompiler, true, sender);
}
return;
}
if (index === paths.length - 1) {
action = "disable";
settings.defaultCompilerPath = "";
if (showSecondPrompt) {
this.showPrompt(selectCompiler, true);
this.showPrompt(selectCompiler, true, sender);
}
ui.showCompilerStatusIcon(false);
return;
}
if (index === paths.length - 2) {
Expand All @@ -1017,27 +1018,29 @@ export class DefaultClient implements Client {
const result: vscode.Uri[] | undefined = await vscode.window.showOpenDialog();
if (result === undefined || result.length === 0) {
if (showSecondPrompt && !compilerDefaults.trustedCompilerFound) {
this.showPrompt(selectCompiler, true);
this.showPrompt(selectCompiler, true, sender);
}
action = "browse dismissed";
return;
}
action = "compiler browsed";
settings.defaultCompilerPath = result[0].fsPath;
ui.showCompilerStatusIcon(false);
} else {
action = "select compiler";
settings.defaultCompilerPath = util.isCl(paths[index]) ? "cl.exe" : paths[index];
ui.showCompilerStatusIcon(false);
}

util.addTrustedCompiler(compilerPaths, settings.defaultCompilerPath);
compilerDefaults = await this.requestCompiler(compilerPaths);
DefaultClient.updateClientConfigurations();
} finally {
telemetry.logLanguageServerEvent('compilerSelection', { action }, { compilerCount: paths.length });
telemetry.logLanguageServerEvent('compilerSelection', { action, sender: util.getSenderType(sender)}, { compilerCount: paths.length });
}
}

async promptSelectCompiler(isCommand: boolean): Promise<void> {
async promptSelectCompiler(isCommand: boolean, sender?: any): Promise<void> {
secondPromptCounter = 0;
if (compilerDefaults === undefined) {
return;
Expand All @@ -1054,19 +1057,20 @@ export class DefaultClient implements Client {
settings.defaultCompilerPath = compilerDefaults.compilerPath;
compilerDefaults = await this.requestCompiler(compilerPaths);
DefaultClient.updateClientConfigurations();
ui.showCompilerStatusIcon(false);
action = "confirm compiler";
} else if (value === selectCompiler) {
this.handleCompilerQuickPick(true);
this.handleCompilerQuickPick(true, sender);
action = "show quickpick";
} else {
this.showPrompt(selectCompiler, true);
this.showPrompt(selectCompiler, true, sender);
action = "dismissed";
}
telemetry.logLanguageServerEvent('compilerNotification', { action });
} else if (!isCommand && (compilerDefaults.compilerPath === undefined)) {
this.showPrompt(selectCompiler, false);
this.showPrompt(selectCompiler, false, sender);
} else {
this.handleCompilerQuickPick(isCommand);
this.handleCompilerQuickPick(isCommand, sender);
}
}
}
Expand Down Expand Up @@ -1205,8 +1209,9 @@ export class DefaultClient implements Client {
compilerDefaults = await this.requestCompiler(compilerPaths);
DefaultClient.updateClientConfigurations();
if (!compilerDefaults.trustedCompilerFound && !displayedSelectCompiler && (compilerPaths.length !== 1 || compilerPaths[0] !== "")) {
await ui.showCompilerStatusIcon(true);
// if there is no compilerPath in c_cpp_properties.json, prompt user to configure a compiler
this.promptSelectCompiler(false);
this.promptSelectCompiler(false, 'initialization');
displayedSelectCompiler = true;
}
}
Expand Down Expand Up @@ -3547,7 +3552,7 @@ class NullClient implements Client {
activate(): void { }
selectionChanged(selection: Range): void { }
resetDatabase(): void { }
promptSelectCompiler(command: boolean): Promise<void> { return Promise.resolve(); }
promptSelectCompiler(command: boolean, sender?: any): Promise<void> { return Promise.resolve(); }
deactivate(): void { }
pauseParsing(): void { }
resumeParsing(): void { }
Expand Down
17 changes: 4 additions & 13 deletions Extension/src/LanguageServer/extension.ts
Original file line number Diff line number Diff line change
Expand Up @@ -434,20 +434,11 @@ function logForUIExperiment(command: string, sender?: any): void {
const properties: {[key: string]: string} = {
newUI: ui.isNewUI.toString(),
uiOverride: (settings.experimentalFeatures ?? false).toString(),
sender: getSenderType(sender)
sender: util.getSenderType(sender)
};
telemetry.logLanguageServerEvent(`experiment${command}`, properties);
}

function getSenderType(sender?: any): string {
if (util.isString(sender)) {
return sender;
} else if (util.isUri(sender)) {
return 'contextMenu';
}
return 'commandPalette';
}

function onDisabledCommand(): void {
const message: string = localize(
{
Expand Down Expand Up @@ -541,8 +532,8 @@ function onResetDatabase(): void {
clients.ActiveClient.resetDatabase();
}

function selectDefaultCompiler(): void {
clients.ActiveClient.promptSelectCompiler(true);
function selectDefaultCompiler(sender?: any): void {
clients.ActiveClient.promptSelectCompiler(true, sender);
}

function onSelectConfiguration(sender?: any): void {
Expand Down Expand Up @@ -690,7 +681,7 @@ async function onDisableAllTypeCodeAnalysisProblems(code: string, identifiersAnd

async function onCreateDeclarationOrDefinition(sender?: any): Promise<void> {
const properties: { [key: string]: string } = {
sender: getSenderType(sender)
sender: util.getSenderType(sender)
};
telemetry.logLanguageServerEvent('CreateDeclDefn', properties);
getActiveClient().handleCreateDeclarationOrDefinition();
Expand Down
33 changes: 33 additions & 0 deletions Extension/src/LanguageServer/ui.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ export interface UI {
activeDocumentChanged(): void;
bind(client: Client): void;
showConfigurations(configurationNames: string[]): Promise<number>;
showCompilerStatusIcon(show: boolean): Promise<void>;
showConfigurationProviders(currentProvider?: string): Promise<string | undefined>;
showCompileCommands(paths: string[]): Promise<number>;
showWorkspaces(workspaceNames: { name: string; key: string }[]): Promise<string>;
Expand Down Expand Up @@ -60,6 +61,7 @@ export class OldUI implements UI {
private configStatusBarItem: vscode.StatusBarItem;
private browseEngineStatusBarItem: vscode.StatusBarItem;
private intelliSenseStatusBarItem: vscode.StatusBarItem;
private compilerStatusItem: vscode.StatusBarItem;
private referencesStatusBarItem: vscode.StatusBarItem;
private curConfigurationStatus?: Promise<ConfigurationStatus>;
private isParsingWorkspace: boolean = false;
Expand Down Expand Up @@ -102,6 +104,17 @@ export class OldUI implements UI {
};
this.ShowReferencesIcon = false;

this.compilerStatusItem = vscode.window.createStatusBarItem(`c.cpp.compilerStatus.statusbar`, vscode.StatusBarAlignment.Right, 901);
this.compilerStatusItem.name = localize("c.cpp.compilerStatus.statusbar", "Configure IntelliSense");
this.compilerStatusItem.text = `$(warning) ${this.compilerStatusItem.name}`;
this.compilerStatusItem.backgroundColor = new vscode.ThemeColor('statusBarItem.warningBackground');
this.compilerStatusItem.command = {
command: "C_Cpp.SelectDefaultCompiler",
title: this.compilerStatusItem.name,
arguments: ['statusBar']
};
this.showCompilerStatusIcon(false);

this.intelliSenseStatusBarItem = vscode.window.createStatusBarItem("c.cpp.intellisense.statusbar", vscode.StatusBarAlignment.Right, 903);
this.intelliSenseStatusBarItem.name = localize("c.cpp.intellisense.statusbar", "C/C++ IntelliSense Status");
this.intelliSenseStatusBarItem.tooltip = this.updatingIntelliSenseTooltip;
Expand Down Expand Up @@ -294,6 +307,26 @@ export class OldUI implements UI {
}
}

private compilerTimout?: NodeJS.Timeout;
public async showCompilerStatusIcon(show: boolean): Promise<void> {
if (!telemetry.showStatusBarIntelliSenseIndicator()) {
return;
}
if (this.compilerTimout) {
clearTimeout(this.compilerTimout);
this.compilerTimout = undefined;
}
if (show) {
this.compilerTimout = setTimeout(() => {
this.compilerStatusItem.show();
telemetry.logLanguageServerEvent('compilerStatusBar');
this.compilerTimout = undefined;
}, 15000);
} else {
this.compilerStatusItem.hide();
}
}

public activeDocumentChanged(): void {
const activeEditor: vscode.TextEditor | undefined = vscode.window.activeTextEditor;
if (!activeEditor) {
Expand Down
33 changes: 33 additions & 0 deletions Extension/src/LanguageServer/ui_new.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import * as nls from 'vscode-nls';
import { setTimeout } from 'timers';
import { CppSettings } from './settings';
import { UI } from './ui';
import * as telemetry from '../telemetry';

nls.config({ messageFormat: nls.MessageFormat.bundle, bundleFormat: nls.BundleFormat.standalone })();
const localize: nls.LocalizeFunc = nls.loadMessageBundle();
Expand Down Expand Up @@ -49,6 +50,7 @@ export class NewUI implements UI {
private configStatusItem: vscode.LanguageStatusItem;
private browseEngineStatusItem: vscode.LanguageStatusItem;
private intelliSenseStatusItem: vscode.LanguageStatusItem;
private compilerStatusItem: vscode.StatusBarItem;
private referencesStatusBarItem: vscode.StatusBarItem;
private codeAnalysisStatusItem: vscode.LanguageStatusItem;
private configDocumentSelector: vscode.DocumentFilter[] = [
Expand Down Expand Up @@ -112,6 +114,17 @@ export class NewUI implements UI {
};
this.ShowReferencesIcon = false;

this.compilerStatusItem = vscode.window.createStatusBarItem(`c.cpp.compilerStatus.statusbar`, vscode.StatusBarAlignment.Right, 901);
this.compilerStatusItem.name = localize("c.cpp.compilerStatus.statusbar", "Configure IntelliSense");
this.compilerStatusItem.text = `$(warning) ${this.compilerStatusItem.name}`;
this.compilerStatusItem.backgroundColor = new vscode.ThemeColor('statusBarItem.warningBackground');
this.compilerStatusItem.command = {
command: "C_Cpp.SelectDefaultCompiler",
title: this.compilerStatusItem.name,
arguments: ['statusBar']
};
this.showCompilerStatusIcon(false);

this.intelliSenseStatusItem = vscode.languages.createLanguageStatusItem(`cpptools.status.${LanguageStatusPriority.Mid}.intellisense`, documentSelector);
this.intelliSenseStatusItem.name = localize("cpptools.status.intellisense", "C/C++ IntelliSense Status");
this.intelliSenseStatusItem.text = this.idleIntelliSenseText;
Expand Down Expand Up @@ -403,6 +416,26 @@ export class NewUI implements UI {
}
}

private compilerTimout?: NodeJS.Timeout;
public async showCompilerStatusIcon(show: boolean): Promise<void> {
if (!telemetry.showStatusBarIntelliSenseIndicator()) {
return;
}
if (this.compilerTimout) {
clearTimeout(this.compilerTimout);
this.compilerTimout = undefined;
}
if (show) {
this.compilerTimout = setTimeout(() => {
this.compilerStatusItem.show();
telemetry.logLanguageServerEvent('compilerStatusBar');
this.compilerTimout = undefined;
}, 15000);
} else {
this.compilerStatusItem.hide();
}
}

public activeDocumentChanged(): void {
const activeEditor: vscode.TextEditor | undefined = vscode.window.activeTextEditor;
if (activeEditor) {
Expand Down
9 changes: 9 additions & 0 deletions Extension/src/common.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1188,6 +1188,15 @@ export class BlockingTask<T> {
}
}

export function getSenderType(sender?: any): string {
if (isString(sender)) {
return sender;
} else if (isUri(sender)) {
return 'contextMenu';
}
return 'commandPalette';
}

function decodeUCS16(input: string): number[] {
const output: number[] = [];
let counter: number = 0;
Expand Down
9 changes: 9 additions & 0 deletions Extension/src/telemetry.ts
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,15 @@ export function logLanguageServerEvent(eventName: string, properties?: { [key: s
sendTelemetry();
}

export async function showStatusBarIntelliSenseIndicator(): Promise<boolean> {
if (new CppSettings().experimentalFeatures) {
return true;
}
const experimentationService: IExperimentationService | undefined = await getExperimentationService();
const useNewUI: boolean | undefined = experimentationService?.getTreatmentVariable<boolean>("vscode", "showStatusBarIntelliSenseIndicator");
return useNewUI ?? false;
}

function getPackageInfo(): IPackageInfo {
return {
name: util.packageJson.publisher + "." + util.packageJson.name,
Expand Down

0 comments on commit c417da6

Please sign in to comment.