type Example … // Examples returns the examples found in testFiles, sorted by Name field. // The Order fields record the order in which the examples were encountered. // The Suffix field is not populated when Examples is called directly, it is // only populated by [NewFromFiles] for examples it finds in _test.go files. // // Playable Examples must be in a package whose name ends in "_test". // An Example is "playable" (the Play field is non-nil) in either of these // circumstances: // - The example function is self-contained: the function references only // identifiers from other packages (or predeclared identifiers, such as // "int") and the test file does not include a dot import. // - The entire test file is the example: the file contains exactly one // example function, zero test, fuzz test, or benchmark function, and at // least one top-level function, type, variable, or constant declaration // other than the example function. func Examples(testFiles ...*ast.File) []*Example { … } var outputPrefix … // Extracts the expected output and whether there was a valid output comment. func exampleOutput(b *ast.BlockStmt, comments []*ast.CommentGroup) (output string, unordered, ok bool) { … } // isTest tells whether name looks like a test, example, fuzz test, or // benchmark. It is a Test (say) if there is a character after Test that is not // a lower-case letter. (We don't want Testiness.) func isTest(name, prefix string) bool { … } // playExample synthesizes a new *ast.File based on the provided // file with the provided function body as the body of main. func playExample(file *ast.File, f *ast.FuncDecl) *ast.File { … } // findDeclsAndUnresolved returns all the top-level declarations mentioned in // the body, and a set of unresolved symbols (those that appear in the body but // have no declaration in the program). // // topDecls maps objects to the top-level declaration declaring them (not // necessarily obj.Decl, as obj.Decl will be a Spec for GenDecls, but // topDecls[obj] will be the GenDecl itself). func findDeclsAndUnresolved(body ast.Node, topDecls map[*ast.Object]ast.Decl, typMethods map[string][]ast.Decl) ([]ast.Decl, map[string]bool) { … } func hasIota(s ast.Spec) bool { … } // findImportGroupStarts finds the start positions of each sequence of import // specs that are not separated by a blank line. func findImportGroupStarts(imps []*ast.ImportSpec) []token.Pos { … } // Helper for findImportGroupStarts to ease testing. func findImportGroupStarts1(origImps []*ast.ImportSpec) []*ast.ImportSpec { … } // playExampleFile takes a whole file example and synthesizes a new *ast.File // such that the example is function main in package main. func playExampleFile(file *ast.File) *ast.File { … } // stripOutputComment finds and removes the "Output:" or "Unordered output:" // comment from body and comments, and adjusts the body block's end position. func stripOutputComment(body *ast.BlockStmt, comments []*ast.CommentGroup) (*ast.BlockStmt, []*ast.CommentGroup) { … } // lastComment returns the last comment inside the provided block. func lastComment(b *ast.BlockStmt, c []*ast.CommentGroup) (i int, last *ast.CommentGroup) { … } // classifyExamples classifies examples and assigns them to the Examples field // of the relevant Func, Type, or Package that the example is associated with. // // The classification process is ambiguous in some cases: // // - ExampleFoo_Bar matches a type named Foo_Bar // or a method named Foo.Bar. // - ExampleFoo_bar matches a type named Foo_bar // or Foo (with a "bar" suffix). // // Examples with malformed names are not associated with anything. func classifyExamples(p *Package, examples []*Example) { … } // nameWithoutInst returns name if name has no brackets. If name contains // brackets, then it returns name with all the contents between (and including) // the outermost left and right bracket removed. // // Adapted from debug/gosym/symtab.go:Sym.nameWithoutInst. func nameWithoutInst(name string) string { … } // splitExampleName attempts to split example name s at index i, // and reports if that produces a valid split. The suffix may be // absent. Otherwise, it must start with a lower-case letter and // be preceded by '_'. // // One of i == len(s) or s[i] == '_' must be true. func splitExampleName(s string, i int) (prefix, suffix string, ok bool) { … } func isExampleSuffix(s string) bool { … }