golangci / golangci-lint

Fast linters runner for Go
https://golangci-lint.run
GNU General Public License v3.0
15.63k stars 1.39k forks source link

Enabling Gofumpt throws error `File is not `gofumpt`-ed` on properly formatted code #2711

Closed ArjunHariharan closed 2 years ago

ArjunHariharan commented 2 years ago

Welcome

Description of the problem

golangci-lint throws an error File is notgofumpt-ed on properly formatted code.

Running gofumpt on the same file doesn't throw an error.

Output of gofumpt linter

$ gofumpt -d cmd/main.go
$

Output of golangci-lint

$ golangci-lint run

cmd/main.go:6: File is not `gofumpt`-ed (gofumpt)

Version of golangci-lint

```console $ golangci-lint version golangci-lint has version 1.45.0 built from 1f4c1ed on 2022-03-18T14:35:36Z ```

Configuration file

```console $ cat .golangci.yml linters: enable: - gofumpt - lll ```

Go environment

```console $ go version && go env go version go1.18 darwin/amd64 ```

Verbose output of running

```console $ golangci-lint cache clean $ golangci-lint run -v INFO [config_reader] Config search paths: [./ /Users/arjun.hariharan/work/demo /Users/arjun.hariharan/work /Users/arjun.hariharan /Users /] INFO [config_reader] Used config file .golangci.yml INFO [lintersdb] Active 12 linters: [deadcode errcheck gofumpt gosimple govet ineffassign lll staticcheck structcheck typecheck unused varcheck] INFO [loader] Go packages loading at mode 575 (types_sizes|name|imports|compiled_files|deps|exports_file|files) took 5.332310465s INFO [runner/filename_unadjuster] Pre-built 0 adjustments in 7.674984ms INFO [linters context/goanalysis] analyzers took 34.311281838s with top 10 stages: buildir: 8.983443043s, ctrlflow: 4.229393871s, printf: 4.03035577s, SA5012: 3.952751797s, fact_purity: 3.538726635s, fact_deprecated: 3.083290609s, typedness: 3.040906702s, nilness: 2.93025081s, inspect: 245.003061ms, isgenerated: 79.376325ms INFO [runner] Processors filtering stat (out/in): skip_dirs: 2/2, uniq_by_line: 2/2, diff: 2/2, max_same_issues: 2/2, max_from_linter: 2/2, cgo: 2/2, path_prettifier: 2/2, identifier_marker: 2/2, max_per_file_from_linter: 2/2, source_code: 2/2, path_shortener: 2/2, filename_unadjuster: 2/2, skip_files: 2/2, exclude: 2/2, path_prefixer: 2/2, sort_results: 2/2, autogenerated_exclude: 2/2, exclude-rules: 2/2, nolint: 2/2, severity-rules: 2/2 INFO [runner] processing took 9.571066ms with stages: nolint: 3.137926ms, autogenerated_exclude: 3.10594ms, source_code: 3.102336ms, path_prettifier: 121.844µs, identifier_marker: 37.676µs, skip_dirs: 34.839µs, exclude-rules: 17.762µs, uniq_by_line: 3.08µs, max_same_issues: 2.324µs, path_shortener: 1.717µs, cgo: 1.131µs, max_from_linter: 1.077µs, filename_unadjuster: 872ns, max_per_file_from_linter: 692ns, sort_results: 457ns, diff: 375ns, exclude: 304ns, skip_files: 293ns, severity-rules: 284ns, path_prefixer: 137ns INFO [runner] linters took 7.525519805s with stages: goanalysis_metalinter: 7.515858513s cmd/main.go:6: File is not `gofumpt`-ed (gofumpt) src/infrastructure/database/database.go:5: File is not `gofumpt`-ed (gofumpt) INFO File cache stats: 2 entries of total size 1.7KiB INFO Memory: 130 samples, avg is 143.3MB, max is 399.1MB INFO Execution took 12.886057437s ```

Code example or link to a public repository

```go package main import ( "flag" "fmt" "demo/cmd/cmdopts" ) func isFlagPassed(name string) bool { found := false flag.Visit(func(f *flag.Flag) { if f.Name == name { found = true } }) return found } func main() { fmt.Println(cmdopts.MIGRATE_OPTS) migrate := flag.Bool( cmdopts.MIGRATE_OPTS.ToString(), false, "Indicates migration to be triggered", ) migrateTo := flag.String(cmdopts.MIGRATE_TO_OPTS.ToString(), "", "a string") rollbackLast := flag.String(cmdopts.MIGRATE_TO_OPTS.ToString(), "", "a string") rollbackTo := flag.String(cmdopts.MIGRATE_TO_OPTS.ToString(), "", "a string") flag.Parse() fmt.Println(*migrate) fmt.Println(*migrateTo) fmt.Println(*rollbackTo) fmt.Println(*rollbackLast) doMigrate := isFlagPassed(cmdopts.MIGRATE_OPTS.ToString()) || isFlagPassed(cmdopts.MIGRATE_TO_OPTS.ToString()) || isFlagPassed(cmdopts.MIGRATE_TO_OPTS.ToString()) || isFlagPassed(cmdopts.MIGRATE_TO_OPTS.ToString()) fmt.Println(doMigrate) } ```
boring-cyborg[bot] commented 2 years ago

Hey, thank you for opening your first Issue ! 🙂 If you would like to contribute we have a guide for contributors.

ldez commented 2 years ago

Hello,

I take your example code with your configuration, and I can't reproduce it.

You can try to use the following command to apply the changes from gofumpt:

golangci-lint run --fix

Also, I recommend using v1.45.2

hummerd commented 2 years ago

I have the same problem

dima@dima-mibook:badlint$ golangci-lint version
golangci-lint has version 1.46.1 built from 044f0a17 on 2022-05-12T09:23:45Z

And it is reporoduced with example above on my machine. I put example code at some dir (not under GOPATH), then added cmd/cmdopts/cmdopts.go file and run go mod init demo. When I run golangci-lint run

dima@dima-mibook:badlint$ golangci-lint run
cmd/cmdopts/opts.go:14: File is not `gofumpt`-ed (gofumpt)

main.go:3: File is not `gofumpt`-ed (gofumpt)
import (
main.go:6: File is not `gofumpt`-ed (gofumpt)

    "demo/cmd/cmdopts"

If I run with -fix flag it reorders imports in strange way

import (
    "demo/cmd/cmdopts"
    "flag"
    "fmt"
)

If I run gofumpt -d main.go it shows that everything is fine, and no changes needed. Gofumpt is v0.3.1.

ddpmz commented 2 years ago

I have the same problem

astronaut0131 commented 2 years ago

same here

root@icx34:~/zhenhui/polaris-security# gofumpt -w -l .
bootstrap/bootstrap.go
cmd/root.go
server/ca_server.go
root@icx34:~/zhenhui/polaris-security# golangci-lint run -c .golangci.yaml
server/ca_server.go:11: File is not `gofumpt`-ed (gofumpt)
        "net/http"
server/ca_server.go:13: File is not `gofumpt`-ed (gofumpt)

        "polaris-security/util"
bootstrap/bootstrap.go:9: File is not `gofumpt`-ed (gofumpt)

cmd/root.go:5: File is not `gofumpt`-ed (gofumpt)

looks like golangci-lint and gofumpt are having conflict decision in formatting imports?

Integralist commented 2 years ago

Same here. I also opened a discussion for golangci-lint here and also opened a corresponding issue on nvim-lint repo here with more details (summary of which is "goimports, gofumpt and revive all have problems").

adrianlungu commented 2 years ago

@ldez I also have the same issue and I've tested versions 1.45.2 as you recommended, as well as 1.46 and the latest 1.47.2. The issue is still there.

The issue has already been outlined by other people in this thread. I.e. golangci-lint sorts imports differently than gofumpt yet complains if the file is gofumpt-ed directly.

If I run golangci-lint run --fix my main.go file has the imports sorted as follows:

import (
    "adrian/pkg/sql"
    ...
    "adrian/pkg/redis"
    "context"
    ...
    "time"

However, if I do gofumpt, the imports will be sorted as follows:

import (
    "context"
    ...
    "time"

    "adrian/pkg/sql"
    ...
    "adrian/pkg/redis"

The behavior is consistent throughout the different versions of golangci-lint I've outlined, while gofumpt is on v0.3.1.

This particular rule in gofumpt that golangci-lint seems to ignore seems to be std imports must be in a separate group at the top with an example in the gofumpt repo here.

After investigating a bit more, it seems gofumpt might be the culprit, as the format_test.go that tests the function that golangci-lint is using does the same thing that golangci-lint does; suggesting there's a discrepancy between the gofumpt binary and the format package although the formatting rules are specified to be part of the format package.

I'll open an issue over there as well to see if we can get more eyes on this issue.

adrianlungu commented 2 years ago

Made some progress with the help of the gofumpt maintainer.

By adding //gofumpt:diagnose to my files, I realized that golangci-lint was running without the modpath being set.

Gofumpt by default detects the modpath, so this was the reason gofumpt was running different to golangci-lint.

I've left //gofumpt:diagnose in my file, run gofumpt -l -w main.go so it would give me some details, including the modpath, and then set the modpath in .golangci.yml as per the documentation. After this, golangci-lint was doing gofumpt the same way gofumpt was.

I guess it would be nice to have the same modpath detection inside golangci-lint as gofumpt has, but till then, hope this helps anyone else in solving their File is not gofumpt-ed issues.

Edit: based on https://github.com/mvdan/gofumpt/issues/238#issuecomment-1196739009 maybe it would be helpful for golangci-lint to use a default similar to what gofumpt uses instead of an empty default ?

mvdan commented 2 years ago

For the sake of completeness, this is how the gofumpt tool sets its formatting defaults:

https://github.com/mvdan/gofumpt/blob/8dda8068d9f339047fc1777b688afb66a0a0db17/gofmt.go#L292-L307

In other words, -lang defaults to the go 1.X version set in the current go.mod, and -modpath defaults to the module some/path set in the current go.mod.

tamj0rd2 commented 2 years ago

and then set the modpath in .golangci.yml as per the documentation

Where did you read this? I can't find anything about it. Where does this setting need to be added?

adrianlungu commented 2 years ago

and then set the modpath in .golangci.yml as per the documentation

Where did you read this? I can't find anything about it. Where does this setting need to be added?

@tamj0rd2 https://golangci-lint.run/usage/linters/#gofumpt

ldez commented 2 years ago

lang-version: is now handled globally by run.go:

https://golangci-lint.run/usage/configuration/#run-configuration

use Go version from the go.mod file, fallback on the env var GOVERSION, fallback on 1.18

wiegell commented 1 year ago

@ldez Can this be reopened? Not solved yet, and it clashes with vscode, that uses vanilla gofumpt setting the modpath in .golangci.yaml dictates that each module needs a .golangci.yaml file, which is not very DRY

ldez commented 1 year ago

For me the problem is fixed: the option has been added. I suggest to open a new issue with a reproducible example if the use of run.go doesn't fix your problem.

wiegell commented 1 year ago

For me the problem is fixed: the option has been added. I suggest to open a new issue with a reproducible example if the use of run.go doesn't fix your problem.

The option of what - selecting go version? The problem that is at the core of this issue is that golangci-lint does not automatically detect the modpath, and that has still not been solved. The question of how the go version is resolved was secondary. This issue has valuable research on the problem, so it seems more appropriate to reopen this one.

ldez commented 1 year ago

please open a new issue https://github.com/golangci/golangci-lint/issues/new/choose

FYI golangci-lint automatically detects go version inside the go.mod.

https://golangci-lint.run/usage/configuration/#run-configuration

thekostya commented 8 months ago

for lazy people

linters-settings:
  gofumpt:
    module-path: <your module path>
wufei-png commented 8 months ago

I fix this in this way:https://freethreads.wordpress.com/2020/07/28/how-to-fix-file-is-not-gofumpt-ed-gofumpt-error/