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

x/tools/internal/analysisinternal: document need for alternative SuggestedFixes to have distinct Messages #72105

Open
yuhua2000 opened this issue Mar 5, 2025 · 4 comments
Labels
BugReport Issues describing a possible bug in the Go implementation. Documentation Issues describing a change to documentation. NeedsFix The path to resolution is known, but the work has not been done. Tools This label describes issues relating to any tools in the x/tools repository.
Milestone

Comments

@yuhua2000
Copy link

yuhua2000 commented Mar 5, 2025

Go version

go version go1.22.0 linux/amd64

Output of go env in your module/workspace:

AR='ar'
CC='gcc'
CGO_CFLAGS='-O2 -g'
CGO_CPPFLAGS=''
CGO_CXXFLAGS='-O2 -g'
CGO_ENABLED='1'
CGO_FFLAGS='-O2 -g'
CGO_LDFLAGS='-O2 -g'
CXX='g++'
GCCGO='gccgo'
GO111MODULE=''
GOAMD64='v1'
GOARCH='amd64'
GOAUTH='netrc'
GOBIN=''
GOCACHEPROG=''
GODEBUG=''
GOEXE=''
GOEXPERIMENT=''
GOFIPS140='off'
GOFLAGS=''
GOGCCFLAGS='-fPIC -m64 -pthread -Wl,--no-gc-sections -fmessage-length=0 -ffile-prefix-map=/tmp/go-build3973945400=/tmp/go-build -gno-record-gcc-switches'
GOHOSTARCH='amd64'
GOHOSTOS='linux'
GOINSECURE=''
GONOPROXY=''
GONOSUMDB=''
GOOS='linux'
GOPRIVATE=''
GOPROXY='https://goproxy.cn,direct'
GOSUMDB='sum.golang.org'
GOTELEMETRY='local'
GOTMPDIR=''
GOTOOLCHAIN='auto'
GOVCS=''
GOVERSION='go1.24.0'
GOWORK=''
PKG_CONFIG='pkg-config'

What did you do?

Invoked analysisutil.ValidateFixes with ‌multiple non-overlapping SuggestedFix entries sharing identical messages but distinct code positions‌, triggering a false validation error.

‌Validation Logic‌: ValidateFixes

func ValidateFixes(fset *token.FileSet, a *analysis.Analyzer, fixes []analysis.SuggestedFix) error {
	fixMessages := make(map[string]bool)
	for i := range fixes {
		fix := &fixes[i]
		if fixMessages[fix.Message] {
			return fmt.Errorf("analyzer %q suggests two fixes with same Message (%s)", a.Name, fix.Message)
		}
		fixMessages[fix.Message] = true
		if err := validateFix(fset, fix); err != nil {
			return fmt.Errorf("analyzer %q suggests invalid fix (%s): %v", a.Name, fix.Message, err)
		}
	}
	return nil
}

Trigger Condition‌:

SuggestedFix{
    Message:   "Fix example",  // Same message
    TextEdits: []TextEdit{{Pos: 100, End: 105}},  // Position A
},
SuggestedFix{
    Message:   "Fix example",  // Same message
    TextEdits: []TextEdit{{Pos: 200, End: 205}},  // Position B (non-overlapping)
}

Observed Error:

analyzer "demo" suggests two fixes with same Message ("Fix example")

What did you see happen?

Actual Output:‌

analyzer "demo" suggests two fixes with same Message (“Fix example”)

Key Observations:‌

  1. The validation fails even though the two fixes apply to different code locations (positions 100-105 vs 150-155)
  2. The current implementation uses only the message string for duplicate detection
  3. Legitimate multi-location fixes (common in bulk codebase repairs) get incorrectly blocked

What did you expect to see?

‌Expected Behavior:‌

Validation should accept multiple fixes with identical messages when:

  1. Their TextEdit ranges don't overlap
  2. ‌They target distinct positions

Technical Justification:‌

  1. Semantic Correctness:‌ The SuggestedFix documentation doesn't prohibit same-message fixes for different locations‌
  2. Practical Need:‌ Real-world analyzers like go vet need this for multi-location corrections (e.g., multiple %v→%w replacements in one diagnostic)‌
  3. Safety Preservation:‌ The existing position validation (validateFix) already prevents overlapping editsProposed Fix:‌
// Modified validation logic pseudocode
fixKeys := make(map[string]bool)
for _, fix := range fixes {
	for _, edit := range fix.TextEdits {
		key := fmt.Sprintf("%s-%d-%d", fix.Message, edit.Pos, edit.End)
		if fixKeys[key] {
			return error
		}
		fixKeys[key] = true
	}
}
@gopherbot gopherbot added the Tools This label describes issues relating to any tools in the x/tools repository. label Mar 5, 2025
@gopherbot gopherbot added this to the Unreleased milestone Mar 5, 2025
@gabyhelp gabyhelp added the BugReport Issues describing a possible bug in the Go implementation. label Mar 5, 2025
@adonovan
Copy link
Member

adonovan commented Mar 5, 2025

When a Diagnostic provides more than one SuggestedFix, they are intended as alternatives, and the client is expected to choose at most one of them to apply. To guide this choice, the messages associated with each fix should be distinct, so that, for example, they can be offered to the user as items on a menu.

In your program, if the fixes are indeed alternatives, then their titles should distinguish them; but if they are not alternatives but just several parts of one logic fix that affects multiple locations, then all the TextEdits should be grouped under a single SuggestedFix.

So I think the validation is working as intended, and is reporting a real problem with the analyzer. It is unfortunate that the assertions were only added recently, but the theory of SuggestedFix wasn't fully worked out when it was added.

The documentation could certainly be more explicit about the need for titles to be distinct.

@yuhua2000
Copy link
Author

@adonovan I agree with your suggestion. The titles of SuggestedFixes should be distinct when they are alternatives, and related fixes should be grouped under one fix. Clearer documentation on this would definitely help avoid confusion in the future.

@adonovan
Copy link
Member

adonovan commented Mar 6, 2025

Clearer documentation on this would definitely help avoid confusion in the future.

Re-opening as a doc fix.

@adonovan adonovan reopened this Mar 6, 2025
@adonovan adonovan changed the title x/tools/internal/analysisinternal: analysisinternal.ValidateFixes erroneously rejects valid SuggestedFixes with same message at different positions x/tools/internal/analysisinternal: document need for alternative SuggestedFixes to have distinct Messages Mar 6, 2025
@gopherbot gopherbot added the Documentation Issues describing a change to documentation. label Mar 6, 2025
@JunyangShao JunyangShao added the NeedsFix The path to resolution is known, but the work has not been done. label Mar 6, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
BugReport Issues describing a possible bug in the Go implementation. Documentation Issues describing a change to documentation. NeedsFix The path to resolution is known, but the work has not been done. Tools This label describes issues relating to any tools in the x/tools repository.
Projects
None yet
Development

No branches or pull requests

5 participants