...

Source file src/go/doc/doc.go

Documentation: go/doc

		 1  // Copyright 2009 The Go Authors. All rights reserved.
		 2  // Use of this source code is governed by a BSD-style
		 3  // license that can be found in the LICENSE file.
		 4  
		 5  // Package doc extracts source code documentation from a Go AST.
		 6  package doc
		 7  
		 8  import (
		 9  	"fmt"
		10  	"go/ast"
		11  	"go/token"
		12  	"strings"
		13  )
		14  
		15  // Package is the documentation for an entire package.
		16  type Package struct {
		17  	Doc				string
		18  	Name			 string
		19  	ImportPath string
		20  	Imports		[]string
		21  	Filenames	[]string
		22  	Notes			map[string][]*Note
		23  
		24  	// Deprecated: For backward compatibility Bugs is still populated,
		25  	// but all new code should use Notes instead.
		26  	Bugs []string
		27  
		28  	// declarations
		29  	Consts []*Value
		30  	Types	[]*Type
		31  	Vars	 []*Value
		32  	Funcs	[]*Func
		33  
		34  	// Examples is a sorted list of examples associated with
		35  	// the package. Examples are extracted from _test.go files
		36  	// provided to NewFromFiles.
		37  	Examples []*Example
		38  }
		39  
		40  // Value is the documentation for a (possibly grouped) var or const declaration.
		41  type Value struct {
		42  	Doc	 string
		43  	Names []string // var or const names in declaration order
		44  	Decl	*ast.GenDecl
		45  
		46  	order int
		47  }
		48  
		49  // Type is the documentation for a type declaration.
		50  type Type struct {
		51  	Doc	string
		52  	Name string
		53  	Decl *ast.GenDecl
		54  
		55  	// associated declarations
		56  	Consts	[]*Value // sorted list of constants of (mostly) this type
		57  	Vars		[]*Value // sorted list of variables of (mostly) this type
		58  	Funcs	 []*Func	// sorted list of functions returning this type
		59  	Methods []*Func	// sorted list of methods (including embedded ones) of this type
		60  
		61  	// Examples is a sorted list of examples associated with
		62  	// this type. Examples are extracted from _test.go files
		63  	// provided to NewFromFiles.
		64  	Examples []*Example
		65  }
		66  
		67  // Func is the documentation for a func declaration.
		68  type Func struct {
		69  	Doc	string
		70  	Name string
		71  	Decl *ast.FuncDecl
		72  
		73  	// methods
		74  	// (for functions, these fields have the respective zero value)
		75  	Recv	string // actual	 receiver "T" or "*T"
		76  	Orig	string // original receiver "T" or "*T"
		77  	Level int		// embedding level; 0 means not embedded
		78  
		79  	// Examples is a sorted list of examples associated with this
		80  	// function or method. Examples are extracted from _test.go files
		81  	// provided to NewFromFiles.
		82  	Examples []*Example
		83  }
		84  
		85  // A Note represents a marked comment starting with "MARKER(uid): note body".
		86  // Any note with a marker of 2 or more upper case [A-Z] letters and a uid of
		87  // at least one character is recognized. The ":" following the uid is optional.
		88  // Notes are collected in the Package.Notes map indexed by the notes marker.
		89  type Note struct {
		90  	Pos, End token.Pos // position range of the comment containing the marker
		91  	UID			string		// uid found with the marker
		92  	Body		 string		// note body text
		93  }
		94  
		95  // Mode values control the operation of New and NewFromFiles.
		96  type Mode int
		97  
		98  const (
		99  	// AllDecls says to extract documentation for all package-level
	 100  	// declarations, not just exported ones.
	 101  	AllDecls Mode = 1 << iota
	 102  
	 103  	// AllMethods says to show all embedded methods, not just the ones of
	 104  	// invisible (unexported) anonymous fields.
	 105  	AllMethods
	 106  
	 107  	// PreserveAST says to leave the AST unmodified. Originally, pieces of
	 108  	// the AST such as function bodies were nil-ed out to save memory in
	 109  	// godoc, but not all programs want that behavior.
	 110  	PreserveAST
	 111  )
	 112  
	 113  // New computes the package documentation for the given package AST.
	 114  // New takes ownership of the AST pkg and may edit or overwrite it.
	 115  // To have the Examples fields populated, use NewFromFiles and include
	 116  // the package's _test.go files.
	 117  //
	 118  func New(pkg *ast.Package, importPath string, mode Mode) *Package {
	 119  	var r reader
	 120  	r.readPackage(pkg, mode)
	 121  	r.computeMethodSets()
	 122  	r.cleanupTypes()
	 123  	return &Package{
	 124  		Doc:				r.doc,
	 125  		Name:			 pkg.Name,
	 126  		ImportPath: importPath,
	 127  		Imports:		sortedKeys(r.imports),
	 128  		Filenames:	r.filenames,
	 129  		Notes:			r.notes,
	 130  		Bugs:			 noteBodies(r.notes["BUG"]),
	 131  		Consts:		 sortedValues(r.values, token.CONST),
	 132  		Types:			sortedTypes(r.types, mode&AllMethods != 0),
	 133  		Vars:			 sortedValues(r.values, token.VAR),
	 134  		Funcs:			sortedFuncs(r.funcs, true),
	 135  	}
	 136  }
	 137  
	 138  // NewFromFiles computes documentation for a package.
	 139  //
	 140  // The package is specified by a list of *ast.Files and corresponding
	 141  // file set, which must not be nil.
	 142  // NewFromFiles uses all provided files when computing documentation,
	 143  // so it is the caller's responsibility to provide only the files that
	 144  // match the desired build context. "go/build".Context.MatchFile can
	 145  // be used for determining whether a file matches a build context with
	 146  // the desired GOOS and GOARCH values, and other build constraints.
	 147  // The import path of the package is specified by importPath.
	 148  //
	 149  // Examples found in _test.go files are associated with the corresponding
	 150  // type, function, method, or the package, based on their name.
	 151  // If the example has a suffix in its name, it is set in the
	 152  // Example.Suffix field. Examples with malformed names are skipped.
	 153  //
	 154  // Optionally, a single extra argument of type Mode can be provided to
	 155  // control low-level aspects of the documentation extraction behavior.
	 156  //
	 157  // NewFromFiles takes ownership of the AST files and may edit them,
	 158  // unless the PreserveAST Mode bit is on.
	 159  //
	 160  func NewFromFiles(fset *token.FileSet, files []*ast.File, importPath string, opts ...interface{}) (*Package, error) {
	 161  	// Check for invalid API usage.
	 162  	if fset == nil {
	 163  		panic(fmt.Errorf("doc.NewFromFiles: no token.FileSet provided (fset == nil)"))
	 164  	}
	 165  	var mode Mode
	 166  	switch len(opts) { // There can only be 0 or 1 options, so a simple switch works for now.
	 167  	case 0:
	 168  		// Nothing to do.
	 169  	case 1:
	 170  		m, ok := opts[0].(Mode)
	 171  		if !ok {
	 172  			panic(fmt.Errorf("doc.NewFromFiles: option argument type must be doc.Mode"))
	 173  		}
	 174  		mode = m
	 175  	default:
	 176  		panic(fmt.Errorf("doc.NewFromFiles: there must not be more than 1 option argument"))
	 177  	}
	 178  
	 179  	// Collect .go and _test.go files.
	 180  	var (
	 181  		goFiles		 = make(map[string]*ast.File)
	 182  		testGoFiles []*ast.File
	 183  	)
	 184  	for i := range files {
	 185  		f := fset.File(files[i].Pos())
	 186  		if f == nil {
	 187  			return nil, fmt.Errorf("file files[%d] is not found in the provided file set", i)
	 188  		}
	 189  		switch name := f.Name(); {
	 190  		case strings.HasSuffix(name, ".go") && !strings.HasSuffix(name, "_test.go"):
	 191  			goFiles[name] = files[i]
	 192  		case strings.HasSuffix(name, "_test.go"):
	 193  			testGoFiles = append(testGoFiles, files[i])
	 194  		default:
	 195  			return nil, fmt.Errorf("file files[%d] filename %q does not have a .go extension", i, name)
	 196  		}
	 197  	}
	 198  
	 199  	// TODO(dmitshur,gri): A relatively high level call to ast.NewPackage with a simpleImporter
	 200  	// ast.Importer implementation is made below. It might be possible to short-circuit and simplify.
	 201  
	 202  	// Compute package documentation.
	 203  	pkg, _ := ast.NewPackage(fset, goFiles, simpleImporter, nil) // Ignore errors that can happen due to unresolved identifiers.
	 204  	p := New(pkg, importPath, mode)
	 205  	classifyExamples(p, Examples(testGoFiles...))
	 206  	return p, nil
	 207  }
	 208  
	 209  // simpleImporter returns a (dummy) package object named by the last path
	 210  // component of the provided package path (as is the convention for packages).
	 211  // This is sufficient to resolve package identifiers without doing an actual
	 212  // import. It never returns an error.
	 213  func simpleImporter(imports map[string]*ast.Object, path string) (*ast.Object, error) {
	 214  	pkg := imports[path]
	 215  	if pkg == nil {
	 216  		// note that strings.LastIndex returns -1 if there is no "/"
	 217  		pkg = ast.NewObj(ast.Pkg, path[strings.LastIndex(path, "/")+1:])
	 218  		pkg.Data = ast.NewScope(nil) // required by ast.NewPackage for dot-import
	 219  		imports[path] = pkg
	 220  	}
	 221  	return pkg, nil
	 222  }
	 223  

View as plain text