-
Notifications
You must be signed in to change notification settings - Fork 18.3k
Description
Description
Proposal to add a code action that refactors short variable declarations (:=) into explicit var declarations with separate assignment.
Example:
// Before
f := os.DirFS("/")
// After
var f fs.FS
f = os.DirFS("/")
Motivation
In some cases, a variable cannot be initialized immediately because its value depends on branching logic. For example:
var str string
switch fix.FixType {
case imports.AddImport:
str = fmt.Sprintf("Add import: %s %q", fix.StmtInfo.Name, fix.StmtInfo.ImportPath)
case imports.DeleteImport:
str = fmt.Sprintf("Delete import: %s %q", fix.StmtInfo.Name, fix.StmtInfo.ImportPath)
case imports.SetImportName:
str = fmt.Sprintf("Rename import: %s %q", fix.StmtInfo.Name, fix.StmtInfo.ImportPath)
}
If the variable was initially declared using a short declaration, its type is inferred and not visible in the source. Refactoring such a variable to a var declaration requires hovering over it or navigating to its definition to determine the type. A code action that performs this conversion automatically would streamline this process.
Concerns and Open Questions
There are a few edge cases where behavior is less clear or might need refinement:
- Multiple assignments
// Extract each individually
//
// var n int
// var err error
// n, err = fmt.Fprintln(os.Stdout)
n, err := fmt.Fprintln(os.Stdout)
- Shadowed variables
n1, err := fmt.Fprintln(os.Stdout)
// Keep shadowing
//
// var n2 int
// n2, err = fmt.Fprintln(os.Stdout)
n2, err := fmt.Fprintln(os.Stdout)
- Missing imports
// Should add import for fs.FS
//
// var f fs.FS
// f = os.DirFS("/")
f := os.DirFS("/")
- Unexported types
In some cases, the inferred type may be an unexported type from another package. Since such types cannot be named outside their defining package, there's no valid 'var' declaration that can reference them. In these situations, the code action should be suppressed, as there is no meaningful or compilable transformation.
I'd be happy to receive feedback, discuss expected behavior in more detail, and work on the implementation if this feature is considered useful and aligned with gopls's direction.