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

Conflict gofumpt and wsl for empty lines before if statement #1510

Closed
3 tasks done
velp opened this issue Nov 16, 2020 · 13 comments
Closed
3 tasks done

Conflict gofumpt and wsl for empty lines before if statement #1510

velp opened this issue Nov 16, 2020 · 13 comments
Labels
bug Something isn't working

Comments

@velp
Copy link

velp commented Nov 16, 2020

Thank you for creating the issue!

  • Yes, I'm using a binary release within 2 latest major releases. Only such installations are supported.
  • Yes, I've searched similar issues on GitHub and didn't find any.
  • Yes, I've included all information below (version, config, etc).

Please include the following information:

Version of golangci-lint
$ golangci-lint --version
golangci-lint has version v1.30.0 built from (unknown, mod sum: "h1:UhdK5WbO0GBd7W+k2lOD7BEJH4Wsa7zKfw8m3/aEJGQ=") on (unknown)
Config file
$ cat .golangci.yml
cat: .golangci.yml: No such file or directory
Go environment
$ go version && go env
go version go1.15 darwin/amd64
GO111MODULE=""
GOARCH="amd64"
GOBIN=""
GOCACHE="/Users/user/Library/Caches/go-build"
GOENV="/Users/user/Library/Application Support/go/env"
GOEXE=""
GOFLAGS=""
GOHOSTARCH="amd64"
GOHOSTOS="darwin"
GOINSECURE=""
GOMODCACHE="/Users/user/Work/go/pkg/mod"
GONOPROXY="github.com/user"
GONOSUMDB="github.com/user"
GOOS="darwin"
GOPATH="/Users/user/Work/go"
GOPROXY="https://proxy.golang.org,direct"
GOROOT="/usr/local/Cellar/go/1.15/libexec"
GOSUMDB="sum.golang.org"
GOTMPDIR=""
GOTOOLDIR="/usr/local/Cellar/go/1.15/libexec/pkg/tool/darwin_amd64"
GCCGO="gccgo"
AR="ar"
CC="clang"
CXX="clang++"
CGO_ENABLED="1"
GOMOD=""
CGO_CFLAGS="-g -O2"
CGO_CPPFLAGS=""
CGO_CXXFLAGS="-g -O2"
CGO_FFLAGS="-g -O2"
CGO_LDFLAGS="-g -O2"
PKG_CONFIG="pkg-config"
GOGCCFLAGS="-fPIC -m64 -pthread -fno-caret-diagnostics -Qunused-arguments -fmessage-length=0 -fdebug-prefix-map=/var/folders/sb/v5w11ncx5vscty2qslyqvx700000gn/T/go-build126064246=/tmp/go-build -gno-record-gcc-switches -fno-common"
Verbose output of running
$ golangci-lint cache clean
$ golangci-lint run -v
INFO [config_reader] Config search paths: [./ /Users/velp/Work/go/src/github.com/velp/test2 /Users/velp/Work/go/src/github.com/velp /Users/velp/Work/go/src/github.com /Users/velp/Work/go/src /Users/velp/Work/go /Users/velp/Work /Users/velp /Users /]
INFO [lintersdb] Active 10 linters: [deadcode errcheck gosimple govet ineffassign staticcheck structcheck typecheck unused varcheck]
INFO [loader] Go packages loading at mode 575 (exports_file|types_sizes|compiled_files|deps|files|imports|name) took 242.792256ms
INFO [runner/filename_unadjuster] Pre-built 0 adjustments in 293.194µs
INFO [linters context/goanalysis] analyzers took 18.81894ms with top 10 stages: buildir: 1.103903ms, S1020: 1.063927ms, ineffassign: 940.727µs, fact_deprecated: 847.572µs, S1024: 804.642µs, SA4019: 726.57µs, SA1019: 675.849µs, SA1012: 628.761µs, varcheck: 610.249µs, SA4003: 601.734µs
INFO [linters context/goanalysis] analyzers took 1.180983ms with top 10 stages: U1000: 656.494µs, buildir: 524.489µs
INFO [runner] processing took 3.378µs with stages: max_same_issues: 565ns, skip_dirs: 469ns, autogenerated_exclude: 294ns, cgo: 251ns, nolint: 235ns, filename_unadjuster: 221ns, max_from_linter: 208ns, uniq_by_line: 152ns, path_prettifier: 144ns, diff: 142ns, skip_files: 134ns, identifier_marker: 128ns, sort_results: 59ns, max_per_file_from_linter: 57ns, path_shortener: 55ns, source_code: 54ns, exclude: 54ns, exclude-rules: 53ns, severity-rules: 52ns, path_prefixer: 51ns
INFO [runner] linters took 107.323844ms with stages: goanalysis_metalinter: 70.414496ms, unused: 36.866632ms
INFO File cache stats: 0 entries of total size 0B
INFO Memory: 5 samples, avg is 72.0MB, max is 72.6MB
INFO Execution took 398.634797ms

Description of problem

The problem: gofumpt conflicts with wsl lister for empty lines before if statement with several assignments.

Example of code

package main

import (
	"encoding/base64"
	"log"
)

func main() {
	str := "just example of code for test"
	encodedStr := base64.StdEncoding.EncodeToString([]byte(str))
	_, err := base64.StdEncoding.DecodeString(encodedStr)
	if err != nil {
		log.Fatalf("Decodding error: %s", err)
	}
}

How to reproduce:

  1. run linting
$ golangci-lint run --enable wsl,gofumpt
main.go:12:2: only one cuddle assignment allowed before if statement (wsl)
	if err != nil {
	^
  1. add new line before if statement to fix wsl error:
package main

import (
	"encoding/base64"
	"log"
)

func main() {
	str := "just example of code for test"
	encodedStr := base64.StdEncoding.EncodeToString([]byte(str))
	_, err := base64.StdEncoding.DecodeString(encodedStr)

	if err != nil {
		log.Fatalf("Decodding error: %s", err)
	}
}
  1. run linting again:
$ golangci-lint run --enable wsl,gofumpt
main.go:12: File is not `gofumpt`-ed (gofumpt)
  1. run gofumpt -w main.go to fix this problem:
$ gofumpt -w main.go
$
  1. run linting again:
$ golangci-lint run --enable wsl,gofumpt
main.go:12:2: only one cuddle assignment allowed before if statement (wsl)
	if err != nil {
	^

Ooops! WSL returns the error, again.

@velp velp added the bug Something isn't working label Nov 16, 2020
@boring-cyborg
Copy link

boring-cyborg bot commented Nov 16, 2020

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

@bombsimon
Copy link
Member

bombsimon commented Nov 16, 2020

Hi! I'm the author of wsl and I'm not sure exactly how this should be tackled. In the mind of wsl, we should only cuddle one assignment with an if statement and we should encourage users to cuddle error checks. So to solve this, there's a third alternative which is what wsl would've made if the fixer was merged.

package main

import (
	"encoding/base64"
	"log"
)

func main() {
	str := "just example of code for test"
	encodedStr := base64.StdEncoding.EncodeToString([]byte(str))

	_, err := base64.StdEncoding.DecodeString(encodedStr)
	if err != nil {
		log.Fatalf("Decodding error: %s", err)
	}
}

I agree that it's not obvious and I understand that it's hard to argue about using wsl when there's no fixer. One of the reason the work for the fixer got stuck was because gofumpt did such a good job. Anyway, sorry for the inconvenience but at lest the code above will satisfy both linters. Feel free to raise an issue in the wsl.

EDIT not really the same but this is also valid according to both gofumpt and wsl:

Source code
package main

import (
	"encoding/base64"
	"log"
)

func main() {
	str := "just example of code for test"

	encodedStr := base64.StdEncoding.EncodeToString([]byte(str))
	if _, err := base64.StdEncoding.DecodeString(encodedStr); err != nil {
		log.Fatalf("Decodding error: %s", err)
	}
}

@velp
Copy link
Author

velp commented Nov 16, 2020

This code is just an example to describe the problem.

Hm, looks like gofumpt -w ... should add new line before nearest (for if statement) assignment (in my example it's _, err := base64.StdEncoding.DecodeString(encodedStr)) if found several assignments.

Let's ask gofumpt's author @mvdan

@mvdan
Copy link

mvdan commented Nov 16, 2020

I don't think gofumpt should fix anything here. The original source code is fine, as far as I can tell, and forcing the addition of an empty line feels out of scope for a generic formatter. If someone really wants to go the extra mile with empty lines, they can already use wsl. It seems like if that tool slightly improves its error message, or suggests the right change to make, then it won't enter into a conflict loop with gofumpt.

@mvdan
Copy link

mvdan commented Nov 16, 2020

I'm also not sure how useful it is to run two opinionated formatting/style tools at once. They'll probably run into conflicts sooner or later, unless both tools are compatible by design - just like gofumpt by design never fights gofmt.

@stale
Copy link

stale bot commented Jan 8, 2022

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

@stale stale bot added the stale No recent correspondence or work activity label Jan 8, 2022
@stale stale bot closed this as completed Apr 16, 2022
@mvdan
Copy link

mvdan commented Apr 16, 2022

I really disagree with the use of the stale bot. This bug is still very much valid, and time passing has not magically made it go away.

@ldez
Copy link
Member

ldez commented Apr 16, 2022

I will re-open. What is your solution to this problem?

@ldez ldez reopened this Apr 16, 2022
@stale stale bot removed the stale No recent correspondence or work activity label Apr 16, 2022
@mvdan
Copy link

mvdan commented Apr 17, 2022

Running both wsl and gofumpt at the same time is likely a bad idea; see #1510 (comment).

@vitsadecky

This comment was marked as duplicate.

@bombsimon
Copy link
Member

I feel like I'm the one that should try to sort this out. Personally I use gofumpt and wsl together so it shouldn't be a big problem but I agree that the error messages might be confusing and hard to know how to solve without a fixer. I can try to free up some time to get back to implementing the fixer but sadly I don't know when that would be.

I'm not sure what happens when two linters with a fixer reports a suggested fix on the same line but I guess worst case a solution would be to run the fixer one by one.

@bombsimon
Copy link
Member

I never got back to this but wsl had a fixer merged in v4.0.0 back in March 2023. It's not implemented in golangci-lint due to #1779 but can be run with the standalone linter.

I don't think there's much more here to address in this issue. golangci-lint is not designed to make all linters work together and as mentioned in #4661 we don't keep track of linters overlapping each other. There are similar situations reported in #2161, #1490 etc.

There's been plenty of discussions about presets (e.g. #3954, #1141, and more) and maybe such presets could avoid overlaps and conflicts. However right now we don't have such feature so until then the user must ensure compatibility between enabled linters.

@ldez I'd like to close this (and potentially all issues regarding linter conflicts) since I don't think they should be considered a bug per se but just a "limitation" of golangci-lint. Preferable we can direct issues and questions to #3954 for discussions about introducing stable presets without such conflicts. WDYT?

@ldez
Copy link
Member

ldez commented Jul 3, 2024

I agree with you 👍

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

5 participants