Summary
replace_symbol_body corrupts single Go type, var, and const declarations by duplicating the leading keyword. Replacing the body of a struct type with a keyword-inclusive body turns
type Resampler struct { ... }
into
type type Resampler struct { ... }
which no longer parses. The tool returns {"result": "OK"} for the corrupting edit (no error is reported), and the resulting syntax error wipes gopls's symbol tree, so subsequent symbolic edits on the same file fail with No symbol matching ... found for symbols that clearly exist.
Root cause
gopls reports the document-symbol range of a single type/var/const declaration starting at the identifier, i.e. after the keyword, whereas it reports a func declaration's range starting at the func keyword. Serena derives both the displayed body and the replacement range from that range, so for these declarations the keyword is excluded from both, while it is included for funcs. That asymmetry is the bug: a body that includes the declaration's signature line (as the docs describe, and as funcs already behave) cannot be round-tripped.
Reproduction
// resampler.go
package resampler
type Resampler struct {
inputRate int
outputRate int
}
find_symbol(name_path="Resampler", relative_path="resampler.go", include_body=True) returns the body Resampler struct { ... } (no type keyword, unlike funcs which include func).
replace_symbol_body(name_path="Resampler", relative_path="resampler.go", body="type Resampler struct {\n\tinputRate int\n}") returns {"result": "OK"} and writes type type Resampler struct { ... }.
- The file no longer parses; subsequent symbolic edits on it fail.
var and const single declarations are affected identically. Grouped declarations (var ( ... )) are not affected, because the keyword sits on its own line.
Relationship to prior fixes
This is the same class of range-vs-replacement mismatch as #1029 (fixed by #1030) and #1484. #1030 handled the trailing end_col for ten language servers but did not touch gopls, and it addressed the END of the range; this issue is about the START of the range (the leading keyword) for Go declarations specifically.
Environment
- gopls v0.22.0, go 1.26.1
- Serena
main
I have a fix with regression tests ready and will open a PR referencing this issue.
Summary
replace_symbol_bodycorrupts single Gotype,var, andconstdeclarations by duplicating the leading keyword. Replacing the body of a struct type with a keyword-inclusive body turnsinto
which no longer parses. The tool returns
{"result": "OK"}for the corrupting edit (no error is reported), and the resulting syntax error wipes gopls's symbol tree, so subsequent symbolic edits on the same file fail withNo symbol matching ... foundfor symbols that clearly exist.Root cause
gopls reports the document-symbol
rangeof a singletype/var/constdeclaration starting at the identifier, i.e. after the keyword, whereas it reports afuncdeclaration's range starting at thefunckeyword. Serena derives both the displayed body and the replacement range from that range, so for these declarations the keyword is excluded from both, while it is included for funcs. That asymmetry is the bug: a body that includes the declaration's signature line (as the docs describe, and as funcs already behave) cannot be round-tripped.Reproduction
find_symbol(name_path="Resampler", relative_path="resampler.go", include_body=True)returns the bodyResampler struct { ... }(notypekeyword, unlike funcs which includefunc).replace_symbol_body(name_path="Resampler", relative_path="resampler.go", body="type Resampler struct {\n\tinputRate int\n}")returns{"result": "OK"}and writestype type Resampler struct { ... }.varandconstsingle declarations are affected identically. Grouped declarations (var ( ... )) are not affected, because the keyword sits on its own line.Relationship to prior fixes
This is the same class of range-vs-replacement mismatch as #1029 (fixed by #1030) and #1484. #1030 handled the trailing
end_colfor ten language servers but did not touchgopls, and it addressed the END of the range; this issue is about the START of the range (the leading keyword) for Go declarations specifically.Environment
mainI have a fix with regression tests ready and will open a PR referencing this issue.