Skip to content

Support custom formatters with args #3729

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

Closed
palsivertsen opened this issue Mar 21, 2025 · 8 comments
Closed

Support custom formatters with args #3729

palsivertsen opened this issue Mar 21, 2025 · 8 comments

Comments

@palsivertsen
Copy link

I'm trying to set up gci as my formatter for more control over import arrangement. I think I've found the relevant extensions, but I can not get the arguments to work. Here's a configuration example:

{
  "go.alternateTools": {
    "customFormatter": "gci"
  },
  "go.formatFlags": [
    "print",
    "--custom-order",
    "--section=standard",
    "--section=default",
    "--section=blank",
    "--section=dot",
    "--section=alias",
    "--section=localmodule"
  ],
  "[go]": {
    "editor.defaultFormatter": "golang.go"
  },
  "go.formatTool": "custom"
}

Looking at the docs it seems like the args are just ignored:

Flags to pass to format tool (e.g. ["-s"]). Not applicable when using the language server.

I would have more control if I could configure formatting like so:

{
  "go.formatTool": {
    "command": "gci",
    "arguments": [
      "print",
      "--custom-order",
      "--section=standard",
      "--section=default",
      "--section=blank",
      "--section=dot",
      "--section=alias",
      "--section=localmodule"
    ],
    "passFileOn": "stdin"
  }
}
@gopherbot gopherbot added this to the Untriaged milestone Mar 21, 2025
@logica0419
Copy link
Contributor

logica0419 commented Mar 24, 2025

Looking at the docs it seems like the args are just ignored:

Flags to pass to format tool (e.g. ["-s"]). Not applicable when using the language server.

Reading the source code, the language server isn't used when you set "go.formatTool" to "custom".
https://github.com/golang/vscode-go/blob/master/extension/src/language/legacy/goFormat.ts#L121-L139
https://github.com/golang/vscode-go/blob/master/extension/src/language/goLanguageServer.ts#L1011-L1026
https://github.com/golang/vscode-go/blob/master/extension/src/language/goLanguageServer.ts#L628-L638

The arguments for custom formatter work for me properly.
ex. These flags work.
https://golangci-lint.run/usage/configuration/#fmt

  "go.formatTool": "custom",
  "go.alternateTools": {
    "customFormatter": "golangci-lint"
  },
  "go.formatFlags": [
    "fmt",
    "--stdin"
  ],

Could you check if this command prints out the full code to stdout, receiving the previous full code from stdin?

@palsivertsen
Copy link
Author

@logica0419 Are you sure this configuration work? When I copy paste your settings it does not work for me. There is a formatter running, and it might be golangci-lint, but it's not using the args. For example providing an illegal argument still works:

    "go.formatTool": "custom",
    "go.alternateTools": {
        "customFormatter": "golangci-lint"
    },
    "go.formatFlags": [
        "asd",
        "fmt",
        "--stdin"
    ]

Also when comparing the output when running the tool directly I get two different results.

I see that golangci-lint fmt has support for GCI as the formatter, so I would be happy to use that, but it is not picking up any for my config files (from projectDir/.golangci-lint.yaml or ~/.golangci-lint.yaml).

@logica0419
Copy link
Contributor

@palsivertsen
Umm... I'm sure the configuration does work. That's weird.
I tried the configuration you wrote in the issue description, and it worked with no problem in my environment.
Seems like this is not the configuration issue.

The format error may be displayed in the dev tools console (you can see it by clicking Help > Toggle Developer Tools), so could you check if some errors are displayed there?

@palsivertsen
Copy link
Author

There are no errors in the debug console.

I cleared all settings (user and workspace json files) and uninstalled all extensions except go. This is the only thing I have in my settings file:

{
    "go.formatTool": "custom",
    "go.alternateTools": {
        "customFormatter": "golangci-lint"
    },
    "go.formatFlags": [
        "fmt",
        "--stdin",
        "--no-config",
        "--enable",
        "gci"
    ]
}

Note I added --no-config to make testing this more consistent. I also explicitly enabled the gci formatter. Then I created the following file as a test case:

package example

import (

	"github.com/aws/aws-sdk-go-v2/aws"

	"fmt"

	"io"

	"log"

)

func Example() {
	var (
		_ = aws.SDKVersion
		_ = io.EOF
		_ = log.Print
		_ = fmt.Print
	)
}

When I run this through the formatter I get the expected results:

golangci-lint fmt --stdin --no-config --enable gci < example.go
package example

import (
	"fmt"
	"io"
	"log"

	"github.com/aws/aws-sdk-go-v2/aws"
)

func Example() {
	var (
		_ = aws.SDKVersion
		_ = io.EOF
		_ = log.Print
		_ = fmt.Print
	)
}

When I run the formatter in vscode I get a different result:

package example

import (
	"github.com/aws/aws-sdk-go-v2/aws"

	"fmt"

	"io"

	"log"
)

func Example() {
	var (
		_ = aws.SDKVersion
		_ = io.EOF
		_ = log.Print
		_ = fmt.Print
	)
}

This do match the results of running golangci-lint fmt --stdin --no-config < example.go, which matches the config that you have. Maybe these are the default args?

@h9jiang
Copy link
Member

h9jiang commented Apr 4, 2025

Hi @palsivertsen

Thank you for raising this issue. I will focus on why the configuration you mentioned in description does not work:

  "go.alternateTools": {
    "customFormatter": "gci"
  },
  "go.formatFlags": [
    "print",
    "--custom-order",
    "--section=standard",
    "--section=default",
    "--section=blank",
    "--section=dot",
    "--section=alias",
    "--section=localmodule"
  ],
  "[go]": {
    "editor.defaultFormatter": "golang.go"
  },
  "go.formatTool": "custom"

The flag is propagated to the gci binary successful but the binary failed with the error below.

Error: finding local modules for `localModule` configuration: reading go.mod: open go.mod: no such file or directory
Usage:
  gci print path... [flags]

Aliases:
  print, output

Flags:
      --custom-order          Enable custom order of sections
  -d, --debug                 Enables debug output from the formatter
  -h, --help                  help for print
      --no-lex-order          Drops lexical ordering for custom sections
  -s, --section stringArray   Sections define how inputs will be processed. Section names are case-insensitive and may contain parameters in (). The section order is standard > default > custom > blank > dot > alias > localmodule. The default value is [standard,default].
                              standard - standard section that Go provides officially, like "fmt"
                              Prefix(github.com/daixiang0) - custom section, groups all imports with the specified Prefix. Imports will be matched to the longest Prefix. Multiple custom prefixes may be provided, they will be rendered as distinct sections separated by newline. You can regroup multiple prefixes by separating them with comma: Prefix(github.com/daixiang0,gitlab.com/daixiang0,daixiang0)
                              default - default section, contains all rest imports
                              blank - blank section, contains all blank imports.
                              dot - dot section, contains all dot imports.
                              alias - alias section, contains all alias imports.
                              localmodule: localmodule section, contains all imports from local packages (default [standard,default])
      --skip-generated        Skip generated files
      --skip-vendor           Skip files inside vendor directory

Why you cant find the error message from terminal:

looks like the log is being sent to terminal in webview developer tool, a correct way to do is to create a terminal first and attach the log to that terminal. See the screenshot in developer tool: This is a bug, there is TODO here, I will fix it.

For now, you need to go to Developer: Toggle Developer Tool and find terminal there.

Image

@h9jiang
Copy link
Member

h9jiang commented Apr 4, 2025

With the configuration here

  "go.formatTool": "custom",
  "go.alternateTools": {
      "customFormatter": "golangci-lint-v2"
  },
  "go.formatFlags": [
      "fmt",
      "--stdin",
      "--no-config",
      "--enable",
      "gci"
  ],

One thing to note here is, golangci-lint v1 does not support fmt. So at the beginning, I saw error from terminal saying the fmt command not recoganized. So I think the reason you do not see any change after using --enable gci is the golangci-lint version is v1.

@logica0419 is currently making some change to support golangci-lint v2. Until that is released, you have to manage golangci-lint-v2 yourself.

Try

// create a tmp dir
mkdir $GOPATH/bin/tmp
// install golangci-lint v2 into GOPATH/bin/tmp
GOBIN=$GOPATH/bin/tmp go install github.com/golangci/golangci-lint/v2/cmd/golangci-lint@latest
// move it out side of GOPATH/bin/tmp and rename to -v2
mv $GOPATH/bin/tmp/golangci-lint $GOPATH/bin/golangci-lint-v2
// cleanup the tmp dir
rm -rf $GOPATH/bin/tmp

Before Save:

Image

After Save:

Image

Let me know if this fixes your problem.

@palsivertsen
Copy link
Author

@h9jiang Thank you so much! This solved my issue.

For anyone who encounters this issue
I did not get gci working, but since it's now built in to golanci-lint (v2), which supports multiple formatters, I'd rather run that.

My goal for formatting is to format the code, add missing imports and divide imports. I'm using goimports and gci to achieve this with the following golangci config:

version: "2"
formatters:
  enable:
    - goimports
    - gci
  settings:
    gci:
      sections:
        - standard
        - default
        - blank
        - dot
        - alias
        - localmodule
      custom-order: true

To get this working I had to make golangci-lint version 2 available to vscode. Since vscode with the go extension manages it's own version of golangci-lint and it's currently using v1 I sat a custom name for the binary (golangci-lint-v2) using a symbolic link:

ln -s <path-to-v2> ~/bin/golangci-lint-v2

I then updated my vscode settings and everything worked:

{
    "go.alternateTools": {
        "customFormatter": "golangci-lint-v2"
    },
    "go.formatFlags": [
        "fmt",
        "--stdin"
    ],
    "go.formatTool": "custom"
}

@ccoVeille
Copy link

For anyone who used an hack like the ones that were suggested, I would like to share that vscode now supports golangci-lint v1 and v2

The documentation of golangci-lint has been updated lately.

https://golangci-lint.run/welcome/integrations/#visual-studio-code

I was also using the hack, and I don't need it anymore.

Here is the PR that brought the change in the documentation

You might find more information and some GitHub links to bounce on.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

6 participants