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  }