Skip to content

Commit

Permalink
docs/settings: make the custom formatter support more visible
Browse files Browse the repository at this point in the history
Custom formatter support was added in #1238.
But due to the limitation in the VS Code setting UI (which assumes
the acceptable values list is static) and the setting validation
logic (VS Code thinks it's an error to use a value outside of the
supplied enum list is invalid), this is not visible to users.

Instead, this change introduces an extra enum 'custom' for the
"go.formatTool" setting. If this is chosen, the extension uses
the tool specified as `customFormatter` in the "go.alternateTools"
setting section for formatting.

The extension expects the custom formatter to accept input as STDIN
and output the result as STDOUT. Users can also supply "go.formatFlags".

Changed the descriptions to use markdown - which allows to reference
other settings ("`#...#`"). The document generation tool does not
handle this special syntax nicely but I hope this isn't too confusing.

I wish we could add an extra validation on the allowed value for
"go.formatTool" in favor of this new 'custom' option. I am not adding
the validation in this CL because there could be users who depend
on this behavior.

For #1238
For #1603
For #2503

Change-Id: I5d9564f331845b6b07f0b54148834118404f3553
Reviewed-on: https://go-review.googlesource.com/c/vscode-go/+/446298
Reviewed-by: Jamal Carvalho <jamal@golang.org>
Run-TryBot: Hyang-Ah Hana Kim <hyangah@gmail.com>
TryBot-Result: kokoro <noreply+kokoro@google.com>
  • Loading branch information
hyangah committed Nov 10, 2022
1 parent 752577e commit 8f81613
Show file tree
Hide file tree
Showing 4 changed files with 52 additions and 24 deletions.
14 changes: 11 additions & 3 deletions docs/settings.md
Original file line number Diff line number Diff line change
Expand Up @@ -51,9 +51,9 @@ Default:
Alternate tools or alternate paths for the same tools used by the Go extension. Provide either absolute path or the name of the binary in GOPATH/bin, GOROOT/bin or PATH. Useful when you want to use wrapper script for the Go tools.
| Properties | Description |
| --- | --- |
| `customFormatter` | Custom formatter to use instead of the language server. This should be used with the `custom` option in `#go.formatTool#`. <br/> Default: `""` |
| `dlv` | Alternate tool to use instead of the dlv binary or alternate path to use for the dlv binary. <br/> Default: `"dlv"` |
| `go` | Alternate tool to use instead of the go binary or alternate path to use for the go binary. <br/> Default: `"go"` |
| `go-outline` | Alternate tool to use instead of the go-outline binary or alternate path to use for the go-outline binary. <br/> Default: `"go-outline"` |
| `gopls` | Alternate tool to use instead of the gopls binary or alternate path to use for the gopls binary. <br/> Default: `"gopls"` |
### `go.autocompleteUnimportedPackages`

Expand Down Expand Up @@ -221,8 +221,16 @@ Default:
Flags to pass to format tool (e.g. ["-s"]). Not applicable when using the language server.
### `go.formatTool`

When the language server is enabled and one of default/gofmt/goimports/gofumpt is chosen, the language server will handle formatting. Otherwise, the extension will use the specified tool for formatting.<br/>
Allowed Options: `default`, `gofmt`, `goimports`, `goformat`, `gofumpt`
When the language server is enabled and one of `default`/`gofmt`/`goimports`/`gofumpt` is chosen, the language server will handle formatting. If `custom` tool is selected, the extension will use the `customFormatter` tool in the `#go.alternateTools#` section.<br/>
Allowed Options:

* `default`: If the language server is enabled, format via the language server, which already supports gofmt, goimports, goreturns, and gofumpt. Otherwise, goimports.
* `gofmt`: Formats the file according to the standard Go style. (not applicable when the language server is enabled)
* `goimports`: Organizes imports and formats the file with gofmt. (not applicable when the language server is enabled)
* `goformat`: Configurable gofmt, see https://github.com/mbenkmann/goformat.
* `gofumpt`: Stricter version of gofmt, see https://github.com/mvdan/gofumpt. . Use `#gopls.format.gofumpt#` instead)
* `custom`: Formats using the custom tool specified as `customFormatter` in the `#go.alternateTools#` setting. The tool should take the input as STDIN and output the formatted code as STDOUT.


Default: `"default"`
### `go.generateTestsFlags`
Expand Down
22 changes: 11 additions & 11 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -1206,23 +1206,23 @@
"go.formatTool": {
"type": "string",
"default": "default",
"description": "When the language server is enabled and one of default/gofmt/goimports/gofumpt is chosen, the language server will handle formatting. Otherwise, the extension will use the specified tool for formatting.",
"markdownDescription": "When the language server is enabled and one of `default`/`gofmt`/`goimports`/`gofumpt` is chosen, the language server will handle formatting. If `custom` tool is selected, the extension will use the `customFormatter` tool in the `#go.alternateTools#` section.",
"scope": "resource",
"enum": [
"default",
"gofmt",
"goimports",
"goformat",
"gofumpt"
"gofumpt",
"custom"
],
"additionalItems": true,
"enumDescriptions": [
"markdownEnumDescriptions": [
"If the language server is enabled, format via the language server, which already supports gofmt, goimports, goreturns, and gofumpt. Otherwise, goimports.",
"Formats the file according to the standard Go style. (not applicable when the language server is enabled)",
"Organizes imports and formats the file with gofmt. (not applicable when the language server is enabled)",
"Configurable gofmt, see https://github.com/mbenkmann/goformat.",
"Stricter version of gofmt, see https://github.com/mvdan/gofumpt. (not applicable when the language server is enabled)",
"Applies gofumpt formatting and organizes imports."
"Stricter version of gofmt, see https://github.com/mvdan/gofumpt. . Use `#gopls.format.gofumpt#` instead)",
"Formats using the custom tool specified as `customFormatter` in the `#go.alternateTools#` setting. The tool should take the input as STDIN and output the formatted code as STDOUT."
]
},
"go.formatFlags": {
Expand Down Expand Up @@ -2030,15 +2030,15 @@
"default": "gopls",
"description": "Alternate tool to use instead of the gopls binary or alternate path to use for the gopls binary."
},
"go-outline": {
"type": "string",
"default": "go-outline",
"description": "Alternate tool to use instead of the go-outline binary or alternate path to use for the go-outline binary."
},
"dlv": {
"type": "string",
"default": "dlv",
"description": "Alternate tool to use instead of the dlv binary or alternate path to use for the dlv binary."
},
"customFormatter": {
"type": "string",
"default": "",
"markdownDescription": "Custom formatter to use instead of the language server. This should be used with the `custom` option in `#go.formatTool#`."
}
},
"additionalProperties": true
Expand Down
14 changes: 9 additions & 5 deletions src/language/legacy/goFormat.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ export class GoDocumentFormattingEditProvider implements vscode.DocumentFormatti
// Handle issues:
// https://github.com/Microsoft/vscode-go/issues/613
// https://github.com/Microsoft/vscode-go/issues/630
if (formatTool === 'goimports' || formatTool === 'goreturns' || formatTool === 'gofumports') {
if (formatTool === 'goimports' || formatTool === 'goreturns') {
formatFlags.push('-srcdir', filename);
}

Expand Down Expand Up @@ -75,10 +75,10 @@ export class GoDocumentFormattingEditProvider implements vscode.DocumentFormatti
): Thenable<vscode.TextEdit[]> {
const formatCommandBinPath = getBinPath(formatTool);
if (!path.isAbsolute(formatCommandBinPath)) {
// executable not found.
promptForMissingTool(formatTool);
return Promise.reject('failed to find tool ' + formatTool);
}

return new Promise<vscode.TextEdit[]>((resolve, reject) => {
const env = toolExecutionEnvironment();
const cwd = path.dirname(document.fileName);
Expand All @@ -94,7 +94,7 @@ export class GoDocumentFormattingEditProvider implements vscode.DocumentFormatti
p.on('error', (err) => {
if (err && (<any>err).code === 'ENOENT') {
promptForMissingTool(formatTool);
return reject();
return reject(`failed to find format tool: ${formatTool}`);
}
});
p.on('close', (code) => {
Expand Down Expand Up @@ -139,8 +139,12 @@ export function usingCustomFormatTool(goConfig: { [key: string]: any }): boolean
}

export function getFormatTool(goConfig: { [key: string]: any }): string {
if (goConfig['formatTool'] === 'default') {
const formatTool = goConfig['formatTool'];
if (formatTool === 'default') {
return 'goimports';
}
return goConfig['formatTool'];
if (formatTool === 'custom') {
return goConfig['alternateTools']['customFormatter'] || 'goimports';
}
return formatTool;
}
26 changes: 21 additions & 5 deletions test/gopls/extension.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -286,11 +286,8 @@ suite('Go Extension Tests With Gopls', function () {
}
});

test('Nonexistent formatter', async () => {
async function testCustomFormatter(goConfig: vscode.WorkspaceConfiguration, customFormatter: string) {
const config = require('../../src/config');
const goConfig = Object.create(getGoConfig(), {
formatTool: { value: 'nonexistent' } // this should make the formatter fail.
}) as vscode.WorkspaceConfiguration;
sandbox.stub(config, 'getGoConfig').returns(goConfig);

await env.startGopls(path.resolve(testdataDir, 'gogetdocTestData', 'test.go'), goConfig);
Expand All @@ -308,7 +305,26 @@ suite('Go Extension Tests With Gopls', function () {
);
assert.fail(`formatter unexpectedly succeeded and returned a result: ${JSON.stringify(result)}`);
} catch (e) {
assert(`${e}`.includes('errors when formatting with nonexistent'), `${e}`);
assert(`${e}`.includes(`errors when formatting with ${customFormatter}`), `${e}`);
}
}

test('Nonexistent formatter', async () => {
const customFormatter = 'nonexistent';
const goConfig = Object.create(getGoConfig(), {
formatTool: { value: customFormatter } // this should make the formatter fail.
}) as vscode.WorkspaceConfiguration;

await testCustomFormatter(goConfig, customFormatter);
});

test('Custom formatter', async () => {
const customFormatter = 'coolCustomFormatter';
const goConfig = Object.create(getGoConfig(), {
formatTool: { value: 'custom' }, // this should make the formatter fail.
alternateTools: { value: { customFormatter: customFormatter } } // this should make the formatter fail.
}) as vscode.WorkspaceConfiguration;

await testCustomFormatter(goConfig, customFormatter);
});
});

0 comments on commit 8f81613

Please sign in to comment.