// RemoveUnusedParameter computes a refactoring to remove the parameter // indicated by the given range, which must be contained within an unused // parameter name or field. // // This operation is a work in progress. Remaining TODO: // - Handle function assignment correctly. // - Improve the extra newlines in output. // - Stream type checking via ForEachPackage. // - Avoid unnecessary additional type checking. func RemoveUnusedParameter(ctx context.Context, fh file.Handle, rng protocol.Range, snapshot *cache.Snapshot) ([]protocol.DocumentChange, error) { … } // rewriteSignature rewrites the signature of the declIdx'th declaration in src // to use the signature of newDecl (described by fset). // // TODO(rfindley): I think this operation could be generalized, for example by // using a concept of a 'nodepath' to correlate nodes between two related // files. // // Note that with its current application, rewriteSignature is expected to // succeed. Separate bug.Errorf calls are used below (rather than one call at // the callsite) in order to have greater precision. func rewriteSignature(fset *token.FileSet, declIdx int, src0 []byte, newDecl *ast.FuncDecl) ([]byte, error) { … } type paramInfo … // findParam finds the parameter information spanned by the given range. func findParam(pgf *parsego.File, rng protocol.Range) (*paramInfo, error) { … } type signatureRewrite … // rewriteCalls returns the document changes required to rewrite the // signature of origDecl to that of newDecl. // // This is a rather complicated factoring of the rewrite operation, but is able // to describe arbitrary rewrites. Specifically, rewriteCalls creates a // synthetic copy of pkg, where the original function declaration is changed to // be a trivial wrapper around the new declaration. params and callArgs are // used to perform this delegation: params must have the same type as origDecl, // but may have renamed parameters (such as is required for delegating blank // parameters). callArgs are the arguments of the delegated call (i.e. using // params). // // For example, consider removing the unused 'b' parameter below, rewriting // // func Foo(a, b, c, _ int) int { // return a+c // } // // To // // func Foo(a, c, _ int) int { // return a+c // } // // In this case, rewriteCalls is parameterized as follows: // - origDecl is the original declaration // - newDecl is the new declaration, which is a copy of origDecl less the 'b' // parameter. // - params is a new parameter list (a, b, c, blank0 int) to be used for the // new wrapper. // - callArgs is the argument list (a, c, blank0), to be used to call the new // delegate. // // rewriting is expressed this way so that rewriteCalls can own the details // of *how* this rewriting is performed. For example, as of writing it names // the synthetic delegate G_o_p_l_s_foo, but the caller need not know this. // // By passing an entirely new declaration, rewriteCalls may be used for // signature refactorings that may affect the function body, such as removing // or adding return values. func rewriteCalls(ctx context.Context, rw signatureRewrite) (map[protocol.DocumentURI][]byte, error) { … } // reTypeCheck re-type checks orig with new file contents defined by fileMask. // // It expects that any newly added imports are already present in the // transitive imports of orig. // // If expectErrors is true, reTypeCheck allows errors in the new package. // TODO(rfindley): perhaps this should be a filter to specify which errors are // acceptable. func reTypeCheck(logf func(string, ...any), orig *cache.Package, fileMask map[protocol.DocumentURI]*ast.File, expectErrors bool) (*types.Package, *types.Info, error) { … } var goVersionRx … func remove[T any](s []T, i int) []T { … } // replaceFileDecl replaces old with new in the file described by pgf. // // TODO(rfindley): generalize, and combine with rewriteSignature. func replaceFileDecl(pgf *parsego.File, old, new ast.Decl) ([]byte, error) { … } // findDecl finds the index of decl in file.Decls. // // TODO: use slices.Index when it is available. func findDecl(file *ast.File, decl ast.Decl) int { … }