type File … type Module … type Go … type Toolchain … type Godebug … type Exclude … type Replace … type Retract … type Tool … type VersionInterval … type Require … func (r *Require) markRemoved() { … } func (r *Require) setVersion(v string) { … } // setIndirect sets line to have (or not have) a "// indirect" comment. func (r *Require) setIndirect(indirect bool) { … } // isIndirect reports whether line has a "// indirect" comment, // meaning it is in go.mod only for its effect on indirect dependencies, // so that it can be dropped entirely once the effective version of the // indirect dependency reaches the given minimum version. func isIndirect(line *Line) bool { … } func (f *File) AddModuleStmt(path string) error { … } func (f *File) AddComment(text string) { … } type VersionFixer … var dontFixRetract … // Parse parses and returns a go.mod file. // // file is the name of the file, used in positions and errors. // // data is the content of the file. // // fix is an optional function that canonicalizes module versions. // If fix is nil, all module versions must be canonical ([module.CanonicalVersion] // must return the same string). func Parse(file string, data []byte, fix VersionFixer) (*File, error) { … } // ParseLax is like Parse but ignores unknown statements. // It is used when parsing go.mod files other than the main module, // under the theory that most statement types we add in the future will // only apply in the main module, like exclude and replace, // and so we get better gradual deployments if old go commands // simply ignore those statements when found in go.mod files // in dependencies. func ParseLax(file string, data []byte, fix VersionFixer) (*File, error) { … } func parseToFile(file string, data []byte, fix VersionFixer, strict bool) (parsed *File, err error) { … } var GoVersionRE … var laxGoVersionRE … var ToolchainRE … func (f *File) add(errs *ErrorList, block *LineBlock, line *Line, verb string, args []string, fix VersionFixer, strict bool) { … } func parseReplace(filename string, line *Line, verb string, args []string, fix VersionFixer) (*Replace, *Error) { … } // fixRetract applies fix to each retract directive in f, appending any errors // to errs. // // Most versions are fixed as we parse the file, but for retract directives, // the relevant module path is the one specified with the module directive, // and that might appear at the end of the file (or not at all). func (f *File) fixRetract(fix VersionFixer, errs *ErrorList) { … } func (f *WorkFile) add(errs *ErrorList, line *Line, verb string, args []string, fix VersionFixer) { … } // IsDirectoryPath reports whether the given path should be interpreted as a directory path. // Just like on the go command line, relative paths starting with a '.' or '..' path component // and rooted paths are directory paths; the rest are module paths. func IsDirectoryPath(ns string) bool { … } // MustQuote reports whether s must be quoted in order to appear as // a single token in a go.mod line. func MustQuote(s string) bool { … } // AutoQuote returns s or, if quoting is required for s to appear in a go.mod, // the quotation of s. func AutoQuote(s string) string { … } func parseVersionInterval(verb string, path string, args *[]string, fix VersionFixer) (VersionInterval, error) { … } func parseString(s *string) (string, error) { … } var deprecatedRE … // parseDeprecation extracts the text of comments on a "module" directive and // extracts a deprecation message from that. // // A deprecation message is contained in a paragraph within a block of comments // that starts with "Deprecated:" (case sensitive). The message runs until the // end of the paragraph and does not include the "Deprecated:" prefix. If the // comment block has multiple paragraphs that start with "Deprecated:", // parseDeprecation returns the message from the first. func parseDeprecation(block *LineBlock, line *Line) string { … } // parseDirectiveComment extracts the text of comments on a directive. // If the directive's line does not have comments and is part of a block that // does have comments, the block's comments are used. func parseDirectiveComment(block *LineBlock, line *Line) string { … } type ErrorList … func (e ErrorList) Error() string { … } type Error … func (e *Error) Error() string { … } func (e *Error) Unwrap() error { … } func parseVersion(verb string, path string, s *string, fix VersionFixer) (string, error) { … } func modulePathMajor(path string) (string, error) { … } func (f *File) Format() ([]byte, error) { … } // Cleanup cleans up the file f after any edit operations. // To avoid quadratic behavior, modifications like [File.DropRequire] // clear the entry but do not remove it from the slice. // Cleanup cleans out all the cleared entries. func (f *File) Cleanup() { … } func (f *File) AddGoStmt(version string) error { … } // DropGoStmt deletes the go statement from the file. func (f *File) DropGoStmt() { … } // DropToolchainStmt deletes the toolchain statement from the file. func (f *File) DropToolchainStmt() { … } func (f *File) AddToolchainStmt(name string) error { … } // AddGodebug sets the first godebug line for key to value, // preserving any existing comments for that line and removing all // other godebug lines for key. // // If no line currently exists for key, AddGodebug adds a new line // at the end of the last godebug block. func (f *File) AddGodebug(key, value string) error { … } // addNewGodebug adds a new godebug key=value line at the end // of the last godebug block, regardless of any existing godebug lines for key. func (f *File) addNewGodebug(key, value string) { … } // AddRequire sets the first require line for path to version vers, // preserving any existing comments for that line and removing all // other lines for path. // // If no line currently exists for path, AddRequire adds a new line // at the end of the last require block. func (f *File) AddRequire(path, vers string) error { … } // AddNewRequire adds a new require line for path at version vers at the end of // the last require block, regardless of any existing require lines for path. func (f *File) AddNewRequire(path, vers string, indirect bool) { … } // SetRequire updates the requirements of f to contain exactly req, preserving // the existing block structure and line comment contents (except for 'indirect' // markings) for the first requirement on each named module path. // // The Syntax field is ignored for the requirements in req. // // Any requirements not already present in the file are added to the block // containing the last require line. // // The requirements in req must specify at most one distinct version for each // module path. // // If any existing requirements may be removed, the caller should call // [File.Cleanup] after all edits are complete. func (f *File) SetRequire(req []*Require) { … } // SetRequireSeparateIndirect updates the requirements of f to contain the given // requirements. Comment contents (except for 'indirect' markings) are retained // from the first existing requirement for each module path. Like SetRequire, // SetRequireSeparateIndirect adds requirements for new paths in req, // updates the version and "// indirect" comment on existing requirements, // and deletes requirements on paths not in req. Existing duplicate requirements // are deleted. // // As its name suggests, SetRequireSeparateIndirect puts direct and indirect // requirements into two separate blocks, one containing only direct // requirements, and the other containing only indirect requirements. // SetRequireSeparateIndirect may move requirements between these two blocks // when their indirect markings change. However, SetRequireSeparateIndirect // won't move requirements from other blocks, especially blocks with comments. // // If the file initially has one uncommented block of requirements, // SetRequireSeparateIndirect will split it into a direct-only and indirect-only // block. This aids in the transition to separate blocks. func (f *File) SetRequireSeparateIndirect(req []*Require) { … } func (f *File) DropGodebug(key string) error { … } func (f *File) DropRequire(path string) error { … } // AddExclude adds a exclude statement to the mod file. Errors if the provided // version is not a canonical version string func (f *File) AddExclude(path, vers string) error { … } func (f *File) DropExclude(path, vers string) error { … } func (f *File) AddReplace(oldPath, oldVers, newPath, newVers string) error { … } func addReplace(syntax *FileSyntax, replace *[]*Replace, oldPath, oldVers, newPath, newVers string) error { … } func (f *File) DropReplace(oldPath, oldVers string) error { … } // AddRetract adds a retract statement to the mod file. Errors if the provided // version interval does not consist of canonical version strings func (f *File) AddRetract(vi VersionInterval, rationale string) error { … } func (f *File) DropRetract(vi VersionInterval) error { … } // AddTool adds a new tool directive with the given path. // It does nothing if the tool line already exists. func (f *File) AddTool(path string) error { … } // RemoveTool removes a tool directive with the given path. // It does nothing if no such tool directive exists. func (f *File) DropTool(path string) error { … } func (f *File) SortBlocks() { … } // removeDups removes duplicate exclude, replace and tool directives. // // Earlier exclude and tool directives take priority. // // Later replace directives take priority. // // require directives are not de-duplicated. That's left up to higher-level // logic (MVS). // // retract directives are not de-duplicated since comments are // meaningful, and versions may be retracted multiple times. func (f *File) removeDups() { … } func removeDups(syntax *FileSyntax, exclude *[]*Exclude, replace *[]*Replace, tool *[]*Tool) { … } // lineLess returns whether li should be sorted before lj. It sorts // lexicographically without assigning any special meaning to tokens. func lineLess(li, lj *Line) bool { … } // lineExcludeLess reports whether li should be sorted before lj for lines in // an "exclude" block. func lineExcludeLess(li, lj *Line) bool { … } // lineRetractLess returns whether li should be sorted before lj for lines in // a "retract" block. It treats each line as a version interval. Single versions // are compared as if they were intervals with the same low and high version. // Intervals are sorted in descending order, first by low version, then by // high version, using semver.Compare. func lineRetractLess(li, lj *Line) bool { … } // checkCanonicalVersion returns a non-nil error if vers is not a canonical // version string or does not match the major version of path. // // If path is non-empty, the error text suggests a format with a major version // corresponding to the path. func checkCanonicalVersion(path, vers string) error { … }