// ParseFile parses the source code of a single Go source file and returns // the corresponding ast.File node. The source code may be provided via // the filename of the source file, or via the src parameter. // // If src != nil, ParseFile parses the source from src and the filename is // only used when recording position information. The type of the argument // for the src parameter must be string, []byte, or io.Reader. // If src == nil, ParseFile parses the file specified by filename. // // The mode parameter controls the amount of source text parsed and other // optional parser functionality. Position information is recorded in the // file set fset. // // If the source couldn't be read, the returned AST is nil and the error // indicates the specific failure. If the source was read but syntax // errors were found, the result is a partial AST (with ast.Bad* nodes // representing the fragments of erroneous source code). Multiple errors // are returned via a scanner.ErrorList which is sorted by file position. // func ParseFile(fset *token.FileSet, filename string, src interface{}, mode Mode) (f *ast.File, err error) { // get source text, err := readSource(filename, src) if err != nil { return nil, err } var p parser defer func() { if e := recover(); e != nil { _ = e.(bailout) // re-panics if it's not a bailout } // set result values if f == nil { // source is not a valid Go source file - satisfy // ParseFile API and return a valid (but) empty // *ast.File f = &ast.File{ Name: new(ast.Ident), Scope: ast.NewScope(nil), } } p.errors.Sort() err = p.errors.Err() }() // parse source p.init(fset, filename, text, mode) f = p.parseFile() return }
// poorMansImporter returns a (dummy) package object named // by the last path component of the provided package path // (as is the convention for packages). This is sufficient // to resolve package identifiers without doing an actual // import. It never returns an error. // func poorMansImporter(imports map[string]*ast.Object, path string) (*ast.Object, error) { pkg := imports[path] if pkg == nil { // note that strings.LastIndex returns -1 if there is no "/" pkg = ast.NewObj(ast.Pkg, path[strings.LastIndex(path, "/")+1:]) pkg.Data = ast.NewScope(nil) // required by ast.NewPackage for dot-import imports[path] = pkg } return pkg, nil }