github.com/v2fly/tools@v0.100.0/godoc/parser.go (about) 1 // Copyright 2011 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 // This file contains support functions for parsing .go files 6 // accessed via godoc's file system fs. 7 8 package godoc 9 10 import ( 11 "bytes" 12 "go/ast" 13 "go/parser" 14 "go/token" 15 pathpkg "path" 16 17 "github.com/v2fly/tools/godoc/vfs" 18 ) 19 20 var linePrefix = []byte("//line ") 21 22 // This function replaces source lines starting with "//line " with a blank line. 23 // It does this irrespective of whether the line is truly a line comment or not; 24 // e.g., the line may be inside a string, or a /*-style comment; however that is 25 // rather unlikely (proper testing would require a full Go scan which we want to 26 // avoid for performance). 27 func replaceLinePrefixCommentsWithBlankLine(src []byte) { 28 for { 29 i := bytes.Index(src, linePrefix) 30 if i < 0 { 31 break // we're done 32 } 33 // 0 <= i && i+len(linePrefix) <= len(src) 34 if i == 0 || src[i-1] == '\n' { 35 // at beginning of line: blank out line 36 for i < len(src) && src[i] != '\n' { 37 src[i] = ' ' 38 i++ 39 } 40 } else { 41 // not at beginning of line: skip over prefix 42 i += len(linePrefix) 43 } 44 // i <= len(src) 45 src = src[i:] 46 } 47 } 48 49 func (c *Corpus) parseFile(fset *token.FileSet, filename string, mode parser.Mode) (*ast.File, error) { 50 src, err := vfs.ReadFile(c.fs, filename) 51 if err != nil { 52 return nil, err 53 } 54 55 // Temporary ad-hoc fix for issue 5247. 56 // TODO(gri,dmitshur) Remove this in favor of a better fix, eventually (see issue 32092). 57 replaceLinePrefixCommentsWithBlankLine(src) 58 59 return parser.ParseFile(fset, filename, src, mode) 60 } 61 62 func (c *Corpus) parseFiles(fset *token.FileSet, relpath string, abspath string, localnames []string) (map[string]*ast.File, error) { 63 files := make(map[string]*ast.File) 64 for _, f := range localnames { 65 absname := pathpkg.Join(abspath, f) 66 file, err := c.parseFile(fset, absname, parser.ParseComments) 67 if err != nil { 68 return nil, err 69 } 70 files[pathpkg.Join(relpath, f)] = file 71 } 72 73 return files, nil 74 }