Skip to content

[LS] replace_symbol_body corrupts Go type/var/const declarations by duplicating the leading keyword #1529

@tphakala

Description

@tphakala

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
}
  1. 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).
  2. 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 { ... }.
  3. 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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions