Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

improvement: New inlay hints options #1475

Merged
merged 1 commit into from Apr 15, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
52 changes: 36 additions & 16 deletions packages/metals-vscode/package.json
Expand Up @@ -249,23 +249,25 @@
"default": [],
"markdownDescription": "List of packages you'd like to be left out of completions, symbol searches, and code actions.\n\nEx. `akka.actor.typed.javadsl` will ensure nothing in the `javadsl` package gets recommended to you.\n\nYou can find the list of default exclusions [here on the Metals website](https://scalameta.org/metals/docs/editors/user-configuration/#excluded-packages).\n\nIf you need to remove one of the defaults, you can simply include it and preface it with `--`."
},
"metals.showInferredType": {
"type": "string",
"default": "false",
"enum": [
"false",
"true",
"minimal"
],
"markdownDescription": "When this option is set to true inferred type in all possible places will be shown. This includes types for values, definitions, cases, type parameters. With 'minimal' option Metals will not show inferred type for type parameters and more complicated pattern matches."
"metals.inlayHints.inferredTypes.enable": {
tgodzik marked this conversation as resolved.
Show resolved Hide resolved
"type": "boolean",
jkciesluk marked this conversation as resolved.
Show resolved Hide resolved
"markdownDescription": "Enable/disable inlay hints for inferred variable types and method return types.\n```scala \n\n val x/*: List[Int]*/ = List(1)\n def foo(x: Int)/*: Option[Int]*/ = Some(x)\n```"
},
"metals.inlayHints.implicitArguments.enable": {
"type": "boolean",
"markdownDescription": "Enable/disable inlay hints for implicit arguments. \n```scala \n\n given bar: Int = 123\n def foo(x: Int)(using Int) = ??? \n foo(1)/*(using bar)*/\n```"
},
"metals.inlayHints.implicitConversions.enable": {
"type": "boolean",
"markdownDescription": "Enable/disable inlay hints for implicit conversions. \n```scala \n\n implicit class MInt(i: Int) {\n def incr: Int = i + 1\n }\n val x = /*MInt(*/1/*)*/.incr \n```"
},
"metals.showImplicitArguments": {
"metals.inlayHints.typeParameters.enable": {
"type": "boolean",
"markdownDescription": "When this option is enabled, for each method that has implicit arguments they are displayed as additional decorations."
"markdownDescription": "Enable/disable inlay hints for type parameters. \n```scala \n\n val x = List[Int](1)\n def foo[T](x: T) = x\n foo/*[Int]*/(1)\n```"
},
"metals.showImplicitConversionsAndClasses": {
"metals.inlayHints.hintsInPatternMatch.enable": {
"type": "boolean",
"markdownDescription": "When this option is enabled, each implicit method and class is displayed as additional decorations at the usage site."
"markdownDescription": "Enable/disable inlay hints in pattern matches. \n```scala \n\n case class Foo(a: Int, b: Int)\n val foo = Foo(1, 2)\n foo match {\n case Foo(a/*: Int*/, b/*: Int*/) =>\n }\n```"
},
"metals.javaHome": {
"type": "string",
Expand Down Expand Up @@ -653,17 +655,27 @@
{
"command": "metals.toggle-implicit-conversions-and-classes",
"category": "Metals",
"title": "Toggle showing implicit conversions and classes"
"title": "Toggle inlay hints for implicit conversions"
},
{
"command": "metals.toggle-implicit-parameters",
"category": "Metals",
"title": "Toggle showing implicit parameters"
"title": "Toggle inlay hints for implicit parameters"
},
{
"command": "metals.toggle-show-inferred-type",
"category": "Metals",
"title": "Toggle showing inferred type"
"title": "Toggle inlay hints for inferred type"
},
{
"command": "metals.toggle-type-parameters",
jkciesluk marked this conversation as resolved.
Show resolved Hide resolved
"category": "Metals",
"title": "Toggle inlay hints for type parameters"
},
{
"command": "metals.toggle-hints-in-pattern-match",
"category": "Metals",
"title": "Toggle inlay hints in pattern matches"
},
{
"command": "metals.copy-worksheet-output",
Expand Down Expand Up @@ -771,6 +783,14 @@
"command": "metals.toggle-show-inferred-type",
"when": "metals:enabled"
},
{
"command": "metals.toggle-type-parameters",
"when": "metals:enabled"
},
{
"command": "metals.toggle-hints-in-pattern-match",
"when": "metals:enabled"
},
{
"command": "metals.restartServer",
"when": "metals:enabled"
Expand Down
82 changes: 48 additions & 34 deletions packages/metals-vscode/src/extension.ts
Expand Up @@ -155,15 +155,33 @@ export async function activate(context: ExtensionContext): Promise<void> {
}

function migrateOldSettings(): void {
const setting = "showInferredType";
const oldBooleanProperty = config.inspect<boolean>(setting)?.workspaceValue;
if (oldBooleanProperty !== undefined) {
config.update(
setting,
`${oldBooleanProperty}`,
ConfigurationTarget.Workspace
);
}
const inferredTypeSetting = "showInferredType";
const oldStringProperty =
config.inspect<string>(inferredTypeSetting)?.workspaceValue;
const inferredType =
oldStringProperty === "true" || oldStringProperty === "minimal";
const typeParameters = oldStringProperty === "true";
const implicitArgsSetting = "showImplicitArguments";
const implicitArgs = config.get<boolean>(implicitArgsSetting) ?? false;
const implicitConvSetting = "showImplicitConversionsAndClasses";
const implicitConversions = config.get<boolean>(implicitConvSetting) ?? false;
[inferredTypeSetting, implicitArgsSetting, implicitConvSetting].forEach(
(setting) =>
config.update(setting, undefined, ConfigurationTarget.Workspace)
);
type SettingTuple = [string, boolean];
const settings: SettingTuple[] = [
["inferredTypes", inferredType],
["typeParameters", typeParameters],
["implicitArguments", implicitArgs],
["implicitConversions", implicitConversions],
];
settings.forEach(([key, enabled]: SettingTuple) => {
const newKey = `inlayHints.${key}.enable`;
if (enabled) {
config.update(newKey, true, ConfigurationTarget.Workspace);
}
});
}
export function deactivate(): Thenable<void> | undefined {
return currentClient?.stop();
Expand Down Expand Up @@ -944,32 +962,24 @@ function launchMetals(
});
});

registerCommand("metals.toggle-implicit-conversions-and-classes", () => {
toggleBooleanWorkspaceSetting("showImplicitConversionsAndClasses");
registerCommand("metals.toggle-implicit-parameters", () => {
toggleInlayHintsSetting("implicitArguments");
});

registerCommand("metals.toggle-implicit-parameters", () => {
toggleBooleanWorkspaceSetting("showImplicitArguments");
registerCommand("metals.toggle-implicit-conversions-and-classes", () => {
toggleInlayHintsSetting("implicitConversions");
});

registerCommand("metals.toggle-show-inferred-type", () => {
const setting = "showInferredType";
const config = workspace.getConfiguration("metals");
const configProperty = config.inspect<string>(setting);
const currentValue = configProperty?.workspaceValue ?? "false";
let newValue = "true";
switch (currentValue) {
case "true":
newValue = "minimal";
break;
case "minimal":
newValue = "false";
break;
case "false":
newValue = "true";
break;
}
config.update(setting, newValue, ConfigurationTarget.Workspace);
toggleInlayHintsSetting("inferredTypes");
});

registerCommand("metals.toggle-type-parameters", () => {
toggleInlayHintsSetting("typeParameters");
});

registerCommand("metals.toggle-hints-in-pattern-match", () => {
toggleInlayHintsSetting("hintsInPatternMatch");
});

registerCommand(
Expand Down Expand Up @@ -1368,11 +1378,15 @@ function configureSettingsDefaults() {
);
}

function toggleBooleanWorkspaceSetting(setting: string) {
const config = workspace.getConfiguration("metals");
const configProperty = config.inspect<boolean>(setting);
function toggleInlayHintsSetting(setting: string) {
const config = workspace.getConfiguration("metals.inlayHints");
const configProperty = config.inspect<boolean>(`${setting}.enable`);
const currentValues = configProperty?.workspaceValue ?? false;
config.update(setting, !currentValues, ConfigurationTarget.Workspace);
config.update(
`${setting}.enable`,
!currentValues,
ConfigurationTarget.Workspace
);
}

function registerDebugEventListener(context: ExtensionContext) {
Expand Down