You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

74 lines
2.0 KiB

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