some deletions
[dotfiles/.git] / .config / coc / extensions / coc-go-data / tools / pkg / mod / golang.org / x / mod@v0.3.0 / modfile / read.go
diff --git a/.config/coc/extensions/coc-go-data/tools/pkg/mod/golang.org/x/mod@v0.3.0/modfile/read.go b/.config/coc/extensions/coc-go-data/tools/pkg/mod/golang.org/x/mod@v0.3.0/modfile/read.go
deleted file mode 100644 (file)
index c1f2008..0000000
+++ /dev/null
@@ -1,948 +0,0 @@
-// Copyright 2018 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package modfile
-
-import (
-       "bytes"
-       "errors"
-       "fmt"
-       "os"
-       "strconv"
-       "strings"
-       "unicode"
-       "unicode/utf8"
-)
-
-// A Position describes an arbitrary source position in a file, including the
-// file, line, column, and byte offset.
-type Position struct {
-       Line     int // line in input (starting at 1)
-       LineRune int // rune in line (starting at 1)
-       Byte     int // byte in input (starting at 0)
-}
-
-// add returns the position at the end of s, assuming it starts at p.
-func (p Position) add(s string) Position {
-       p.Byte += len(s)
-       if n := strings.Count(s, "\n"); n > 0 {
-               p.Line += n
-               s = s[strings.LastIndex(s, "\n")+1:]
-               p.LineRune = 1
-       }
-       p.LineRune += utf8.RuneCountInString(s)
-       return p
-}
-
-// An Expr represents an input element.
-type Expr interface {
-       // Span returns the start and end position of the expression,
-       // excluding leading or trailing comments.
-       Span() (start, end Position)
-
-       // Comment returns the comments attached to the expression.
-       // This method would normally be named 'Comments' but that
-       // would interfere with embedding a type of the same name.
-       Comment() *Comments
-}
-
-// A Comment represents a single // comment.
-type Comment struct {
-       Start  Position
-       Token  string // without trailing newline
-       Suffix bool   // an end of line (not whole line) comment
-}
-
-// Comments collects the comments associated with an expression.
-type Comments struct {
-       Before []Comment // whole-line comments before this expression
-       Suffix []Comment // end-of-line comments after this expression
-
-       // For top-level expressions only, After lists whole-line
-       // comments following the expression.
-       After []Comment
-}
-
-// Comment returns the receiver. This isn't useful by itself, but
-// a Comments struct is embedded into all the expression
-// implementation types, and this gives each of those a Comment
-// method to satisfy the Expr interface.
-func (c *Comments) Comment() *Comments {
-       return c
-}
-
-// A FileSyntax represents an entire go.mod file.
-type FileSyntax struct {
-       Name string // file path
-       Comments
-       Stmt []Expr
-}
-
-func (x *FileSyntax) Span() (start, end Position) {
-       if len(x.Stmt) == 0 {
-               return
-       }
-       start, _ = x.Stmt[0].Span()
-       _, end = x.Stmt[len(x.Stmt)-1].Span()
-       return start, end
-}
-
-// addLine adds a line containing the given tokens to the file.
-//
-// If the first token of the hint matches the first token of the
-// line, the new line is added at the end of the block containing hint,
-// extracting hint into a new block if it is not yet in one.
-//
-// If the hint is non-nil buts its first token does not match,
-// the new line is added after the block containing hint
-// (or hint itself, if not in a block).
-//
-// If no hint is provided, addLine appends the line to the end of
-// the last block with a matching first token,
-// or to the end of the file if no such block exists.
-func (x *FileSyntax) addLine(hint Expr, tokens ...string) *Line {
-       if hint == nil {
-               // If no hint given, add to the last statement of the given type.
-       Loop:
-               for i := len(x.Stmt) - 1; i >= 0; i-- {
-                       stmt := x.Stmt[i]
-                       switch stmt := stmt.(type) {
-                       case *Line:
-                               if stmt.Token != nil && stmt.Token[0] == tokens[0] {
-                                       hint = stmt
-                                       break Loop
-                               }
-                       case *LineBlock:
-                               if stmt.Token[0] == tokens[0] {
-                                       hint = stmt
-                                       break Loop
-                               }
-                       }
-               }
-       }
-
-       newLineAfter := func(i int) *Line {
-               new := &Line{Token: tokens}
-               if i == len(x.Stmt) {
-                       x.Stmt = append(x.Stmt, new)
-               } else {
-                       x.Stmt = append(x.Stmt, nil)
-                       copy(x.Stmt[i+2:], x.Stmt[i+1:])
-                       x.Stmt[i+1] = new
-               }
-               return new
-       }
-
-       if hint != nil {
-               for i, stmt := range x.Stmt {
-                       switch stmt := stmt.(type) {
-                       case *Line:
-                               if stmt == hint {
-                                       if stmt.Token == nil || stmt.Token[0] != tokens[0] {
-                                               return newLineAfter(i)
-                                       }
-
-                                       // Convert line to line block.
-                                       stmt.InBlock = true
-                                       block := &LineBlock{Token: stmt.Token[:1], Line: []*Line{stmt}}
-                                       stmt.Token = stmt.Token[1:]
-                                       x.Stmt[i] = block
-                                       new := &Line{Token: tokens[1:], InBlock: true}
-                                       block.Line = append(block.Line, new)
-                                       return new
-                               }
-
-                       case *LineBlock:
-                               if stmt == hint {
-                                       if stmt.Token[0] != tokens[0] {
-                                               return newLineAfter(i)
-                                       }
-
-                                       new := &Line{Token: tokens[1:], InBlock: true}
-                                       stmt.Line = append(stmt.Line, new)
-                                       return new
-                               }
-
-                               for j, line := range stmt.Line {
-                                       if line == hint {
-                                               if stmt.Token[0] != tokens[0] {
-                                                       return newLineAfter(i)
-                                               }
-
-                                               // Add new line after hint within the block.
-                                               stmt.Line = append(stmt.Line, nil)
-                                               copy(stmt.Line[j+2:], stmt.Line[j+1:])
-                                               new := &Line{Token: tokens[1:], InBlock: true}
-                                               stmt.Line[j+1] = new
-                                               return new
-                                       }
-                               }
-                       }
-               }
-       }
-
-       new := &Line{Token: tokens}
-       x.Stmt = append(x.Stmt, new)
-       return new
-}
-
-func (x *FileSyntax) updateLine(line *Line, tokens ...string) {
-       if line.InBlock {
-               tokens = tokens[1:]
-       }
-       line.Token = tokens
-}
-
-func (x *FileSyntax) removeLine(line *Line) {
-       line.Token = nil
-}
-
-// Cleanup cleans up the file syntax x after any edit operations.
-// To avoid quadratic behavior, removeLine marks the line as dead
-// by setting line.Token = nil but does not remove it from the slice
-// in which it appears. After edits have all been indicated,
-// calling Cleanup cleans out the dead lines.
-func (x *FileSyntax) Cleanup() {
-       w := 0
-       for _, stmt := range x.Stmt {
-               switch stmt := stmt.(type) {
-               case *Line:
-                       if stmt.Token == nil {
-                               continue
-                       }
-               case *LineBlock:
-                       ww := 0
-                       for _, line := range stmt.Line {
-                               if line.Token != nil {
-                                       stmt.Line[ww] = line
-                                       ww++
-                               }
-                       }
-                       if ww == 0 {
-                               continue
-                       }
-                       if ww == 1 {
-                               // Collapse block into single line.
-                               line := &Line{
-                                       Comments: Comments{
-                                               Before: commentsAdd(stmt.Before, stmt.Line[0].Before),
-                                               Suffix: commentsAdd(stmt.Line[0].Suffix, stmt.Suffix),
-                                               After:  commentsAdd(stmt.Line[0].After, stmt.After),
-                                       },
-                                       Token: stringsAdd(stmt.Token, stmt.Line[0].Token),
-                               }
-                               x.Stmt[w] = line
-                               w++
-                               continue
-                       }
-                       stmt.Line = stmt.Line[:ww]
-               }
-               x.Stmt[w] = stmt
-               w++
-       }
-       x.Stmt = x.Stmt[:w]
-}
-
-func commentsAdd(x, y []Comment) []Comment {
-       return append(x[:len(x):len(x)], y...)
-}
-
-func stringsAdd(x, y []string) []string {
-       return append(x[:len(x):len(x)], y...)
-}
-
-// A CommentBlock represents a top-level block of comments separate
-// from any rule.
-type CommentBlock struct {
-       Comments
-       Start Position
-}
-
-func (x *CommentBlock) Span() (start, end Position) {
-       return x.Start, x.Start
-}
-
-// A Line is a single line of tokens.
-type Line struct {
-       Comments
-       Start   Position
-       Token   []string
-       InBlock bool
-       End     Position
-}
-
-func (x *Line) Span() (start, end Position) {
-       return x.Start, x.End
-}
-
-// A LineBlock is a factored block of lines, like
-//
-//     require (
-//             "x"
-//             "y"
-//     )
-//
-type LineBlock struct {
-       Comments
-       Start  Position
-       LParen LParen
-       Token  []string
-       Line   []*Line
-       RParen RParen
-}
-
-func (x *LineBlock) Span() (start, end Position) {
-       return x.Start, x.RParen.Pos.add(")")
-}
-
-// An LParen represents the beginning of a parenthesized line block.
-// It is a place to store suffix comments.
-type LParen struct {
-       Comments
-       Pos Position
-}
-
-func (x *LParen) Span() (start, end Position) {
-       return x.Pos, x.Pos.add(")")
-}
-
-// An RParen represents the end of a parenthesized line block.
-// It is a place to store whole-line (before) comments.
-type RParen struct {
-       Comments
-       Pos Position
-}
-
-func (x *RParen) Span() (start, end Position) {
-       return x.Pos, x.Pos.add(")")
-}
-
-// An input represents a single input file being parsed.
-type input struct {
-       // Lexing state.
-       filename   string    // name of input file, for errors
-       complete   []byte    // entire input
-       remaining  []byte    // remaining input
-       tokenStart []byte    // token being scanned to end of input
-       token      token     // next token to be returned by lex, peek
-       pos        Position  // current input position
-       comments   []Comment // accumulated comments
-
-       // Parser state.
-       file        *FileSyntax // returned top-level syntax tree
-       parseErrors ErrorList   // errors encountered during parsing
-
-       // Comment assignment state.
-       pre  []Expr // all expressions, in preorder traversal
-       post []Expr // all expressions, in postorder traversal
-}
-
-func newInput(filename string, data []byte) *input {
-       return &input{
-               filename:  filename,
-               complete:  data,
-               remaining: data,
-               pos:       Position{Line: 1, LineRune: 1, Byte: 0},
-       }
-}
-
-// parse parses the input file.
-func parse(file string, data []byte) (f *FileSyntax, err error) {
-       // The parser panics for both routine errors like syntax errors
-       // and for programmer bugs like array index errors.
-       // Turn both into error returns. Catching bug panics is
-       // especially important when processing many files.
-       in := newInput(file, data)
-       defer func() {
-               if e := recover(); e != nil && e != &in.parseErrors {
-                       in.parseErrors = append(in.parseErrors, Error{
-                               Filename: in.filename,
-                               Pos:      in.pos,
-                               Err:      fmt.Errorf("internal error: %v", e),
-                       })
-               }
-               if err == nil && len(in.parseErrors) > 0 {
-                       err = in.parseErrors
-               }
-       }()
-
-       // Prime the lexer by reading in the first token. It will be available
-       // in the next peek() or lex() call.
-       in.readToken()
-
-       // Invoke the parser.
-       in.parseFile()
-       if len(in.parseErrors) > 0 {
-               return nil, in.parseErrors
-       }
-       in.file.Name = in.filename
-
-       // Assign comments to nearby syntax.
-       in.assignComments()
-
-       return in.file, nil
-}
-
-// Error is called to report an error.
-// Error does not return: it panics.
-func (in *input) Error(s string) {
-       in.parseErrors = append(in.parseErrors, Error{
-               Filename: in.filename,
-               Pos:      in.pos,
-               Err:      errors.New(s),
-       })
-       panic(&in.parseErrors)
-}
-
-// eof reports whether the input has reached end of file.
-func (in *input) eof() bool {
-       return len(in.remaining) == 0
-}
-
-// peekRune returns the next rune in the input without consuming it.
-func (in *input) peekRune() int {
-       if len(in.remaining) == 0 {
-               return 0
-       }
-       r, _ := utf8.DecodeRune(in.remaining)
-       return int(r)
-}
-
-// peekPrefix reports whether the remaining input begins with the given prefix.
-func (in *input) peekPrefix(prefix string) bool {
-       // This is like bytes.HasPrefix(in.remaining, []byte(prefix))
-       // but without the allocation of the []byte copy of prefix.
-       for i := 0; i < len(prefix); i++ {
-               if i >= len(in.remaining) || in.remaining[i] != prefix[i] {
-                       return false
-               }
-       }
-       return true
-}
-
-// readRune consumes and returns the next rune in the input.
-func (in *input) readRune() int {
-       if len(in.remaining) == 0 {
-               in.Error("internal lexer error: readRune at EOF")
-       }
-       r, size := utf8.DecodeRune(in.remaining)
-       in.remaining = in.remaining[size:]
-       if r == '\n' {
-               in.pos.Line++
-               in.pos.LineRune = 1
-       } else {
-               in.pos.LineRune++
-       }
-       in.pos.Byte += size
-       return int(r)
-}
-
-type token struct {
-       kind   tokenKind
-       pos    Position
-       endPos Position
-       text   string
-}
-
-type tokenKind int
-
-const (
-       _EOF tokenKind = -(iota + 1)
-       _EOLCOMMENT
-       _IDENT
-       _STRING
-       _COMMENT
-
-       // newlines and punctuation tokens are allowed as ASCII codes.
-)
-
-func (k tokenKind) isComment() bool {
-       return k == _COMMENT || k == _EOLCOMMENT
-}
-
-// isEOL returns whether a token terminates a line.
-func (k tokenKind) isEOL() bool {
-       return k == _EOF || k == _EOLCOMMENT || k == '\n'
-}
-
-// startToken marks the beginning of the next input token.
-// It must be followed by a call to endToken, once the token's text has
-// been consumed using readRune.
-func (in *input) startToken() {
-       in.tokenStart = in.remaining
-       in.token.text = ""
-       in.token.pos = in.pos
-}
-
-// endToken marks the end of an input token.
-// It records the actual token string in tok.text.
-func (in *input) endToken(kind tokenKind) {
-       in.token.kind = kind
-       text := string(in.tokenStart[:len(in.tokenStart)-len(in.remaining)])
-       in.token.text = text
-       in.token.endPos = in.pos
-}
-
-// peek returns the kind of the the next token returned by lex.
-func (in *input) peek() tokenKind {
-       return in.token.kind
-}
-
-// lex is called from the parser to obtain the next input token.
-func (in *input) lex() token {
-       tok := in.token
-       in.readToken()
-       return tok
-}
-
-// readToken lexes the next token from the text and stores it in in.token.
-func (in *input) readToken() {
-       // Skip past spaces, stopping at non-space or EOF.
-       for !in.eof() {
-               c := in.peekRune()
-               if c == ' ' || c == '\t' || c == '\r' {
-                       in.readRune()
-                       continue
-               }
-
-               // Comment runs to end of line.
-               if in.peekPrefix("//") {
-                       in.startToken()
-
-                       // Is this comment the only thing on its line?
-                       // Find the last \n before this // and see if it's all
-                       // spaces from there to here.
-                       i := bytes.LastIndex(in.complete[:in.pos.Byte], []byte("\n"))
-                       suffix := len(bytes.TrimSpace(in.complete[i+1:in.pos.Byte])) > 0
-                       in.readRune()
-                       in.readRune()
-
-                       // Consume comment.
-                       for len(in.remaining) > 0 && in.readRune() != '\n' {
-                       }
-
-                       // If we are at top level (not in a statement), hand the comment to
-                       // the parser as a _COMMENT token. The grammar is written
-                       // to handle top-level comments itself.
-                       if !suffix {
-                               in.endToken(_COMMENT)
-                               return
-                       }
-
-                       // Otherwise, save comment for later attachment to syntax tree.
-                       in.endToken(_EOLCOMMENT)
-                       in.comments = append(in.comments, Comment{in.token.pos, in.token.text, suffix})
-                       return
-               }
-
-               if in.peekPrefix("/*") {
-                       in.Error("mod files must use // comments (not /* */ comments)")
-               }
-
-               // Found non-space non-comment.
-               break
-       }
-
-       // Found the beginning of the next token.
-       in.startToken()
-
-       // End of file.
-       if in.eof() {
-               in.endToken(_EOF)
-               return
-       }
-
-       // Punctuation tokens.
-       switch c := in.peekRune(); c {
-       case '\n', '(', ')', '[', ']', '{', '}', ',':
-               in.readRune()
-               in.endToken(tokenKind(c))
-               return
-
-       case '"', '`': // quoted string
-               quote := c
-               in.readRune()
-               for {
-                       if in.eof() {
-                               in.pos = in.token.pos
-                               in.Error("unexpected EOF in string")
-                       }
-                       if in.peekRune() == '\n' {
-                               in.Error("unexpected newline in string")
-                       }
-                       c := in.readRune()
-                       if c == quote {
-                               break
-                       }
-                       if c == '\\' && quote != '`' {
-                               if in.eof() {
-                                       in.pos = in.token.pos
-                                       in.Error("unexpected EOF in string")
-                               }
-                               in.readRune()
-                       }
-               }
-               in.endToken(_STRING)
-               return
-       }
-
-       // Checked all punctuation. Must be identifier token.
-       if c := in.peekRune(); !isIdent(c) {
-               in.Error(fmt.Sprintf("unexpected input character %#q", c))
-       }
-
-       // Scan over identifier.
-       for isIdent(in.peekRune()) {
-               if in.peekPrefix("//") {
-                       break
-               }
-               if in.peekPrefix("/*") {
-                       in.Error("mod files must use // comments (not /* */ comments)")
-               }
-               in.readRune()
-       }
-       in.endToken(_IDENT)
-}
-
-// isIdent reports whether c is an identifier rune.
-// We treat most printable runes as identifier runes, except for a handful of
-// ASCII punctuation characters.
-func isIdent(c int) bool {
-       switch r := rune(c); r {
-       case ' ', '(', ')', '[', ']', '{', '}', ',':
-               return false
-       default:
-               return !unicode.IsSpace(r) && unicode.IsPrint(r)
-       }
-}
-
-// Comment assignment.
-// We build two lists of all subexpressions, preorder and postorder.
-// The preorder list is ordered by start location, with outer expressions first.
-// The postorder list is ordered by end location, with outer expressions last.
-// We use the preorder list to assign each whole-line comment to the syntax
-// immediately following it, and we use the postorder list to assign each
-// end-of-line comment to the syntax immediately preceding it.
-
-// order walks the expression adding it and its subexpressions to the
-// preorder and postorder lists.
-func (in *input) order(x Expr) {
-       if x != nil {
-               in.pre = append(in.pre, x)
-       }
-       switch x := x.(type) {
-       default:
-               panic(fmt.Errorf("order: unexpected type %T", x))
-       case nil:
-               // nothing
-       case *LParen, *RParen:
-               // nothing
-       case *CommentBlock:
-               // nothing
-       case *Line:
-               // nothing
-       case *FileSyntax:
-               for _, stmt := range x.Stmt {
-                       in.order(stmt)
-               }
-       case *LineBlock:
-               in.order(&x.LParen)
-               for _, l := range x.Line {
-                       in.order(l)
-               }
-               in.order(&x.RParen)
-       }
-       if x != nil {
-               in.post = append(in.post, x)
-       }
-}
-
-// assignComments attaches comments to nearby syntax.
-func (in *input) assignComments() {
-       const debug = false
-
-       // Generate preorder and postorder lists.
-       in.order(in.file)
-
-       // Split into whole-line comments and suffix comments.
-       var line, suffix []Comment
-       for _, com := range in.comments {
-               if com.Suffix {
-                       suffix = append(suffix, com)
-               } else {
-                       line = append(line, com)
-               }
-       }
-
-       if debug {
-               for _, c := range line {
-                       fmt.Fprintf(os.Stderr, "LINE %q :%d:%d #%d\n", c.Token, c.Start.Line, c.Start.LineRune, c.Start.Byte)
-               }
-       }
-
-       // Assign line comments to syntax immediately following.
-       for _, x := range in.pre {
-               start, _ := x.Span()
-               if debug {
-                       fmt.Fprintf(os.Stderr, "pre %T :%d:%d #%d\n", x, start.Line, start.LineRune, start.Byte)
-               }
-               xcom := x.Comment()
-               for len(line) > 0 && start.Byte >= line[0].Start.Byte {
-                       if debug {
-                               fmt.Fprintf(os.Stderr, "ASSIGN LINE %q #%d\n", line[0].Token, line[0].Start.Byte)
-                       }
-                       xcom.Before = append(xcom.Before, line[0])
-                       line = line[1:]
-               }
-       }
-
-       // Remaining line comments go at end of file.
-       in.file.After = append(in.file.After, line...)
-
-       if debug {
-               for _, c := range suffix {
-                       fmt.Fprintf(os.Stderr, "SUFFIX %q :%d:%d #%d\n", c.Token, c.Start.Line, c.Start.LineRune, c.Start.Byte)
-               }
-       }
-
-       // Assign suffix comments to syntax immediately before.
-       for i := len(in.post) - 1; i >= 0; i-- {
-               x := in.post[i]
-
-               start, end := x.Span()
-               if debug {
-                       fmt.Fprintf(os.Stderr, "post %T :%d:%d #%d :%d:%d #%d\n", x, start.Line, start.LineRune, start.Byte, end.Line, end.LineRune, end.Byte)
-               }
-
-               // Do not assign suffix comments to end of line block or whole file.
-               // Instead assign them to the last element inside.
-               switch x.(type) {
-               case *FileSyntax:
-                       continue
-               }
-
-               // Do not assign suffix comments to something that starts
-               // on an earlier line, so that in
-               //
-               //      x ( y
-               //              z ) // comment
-               //
-               // we assign the comment to z and not to x ( ... ).
-               if start.Line != end.Line {
-                       continue
-               }
-               xcom := x.Comment()
-               for len(suffix) > 0 && end.Byte <= suffix[len(suffix)-1].Start.Byte {
-                       if debug {
-                               fmt.Fprintf(os.Stderr, "ASSIGN SUFFIX %q #%d\n", suffix[len(suffix)-1].Token, suffix[len(suffix)-1].Start.Byte)
-                       }
-                       xcom.Suffix = append(xcom.Suffix, suffix[len(suffix)-1])
-                       suffix = suffix[:len(suffix)-1]
-               }
-       }
-
-       // We assigned suffix comments in reverse.
-       // If multiple suffix comments were appended to the same
-       // expression node, they are now in reverse. Fix that.
-       for _, x := range in.post {
-               reverseComments(x.Comment().Suffix)
-       }
-
-       // Remaining suffix comments go at beginning of file.
-       in.file.Before = append(in.file.Before, suffix...)
-}
-
-// reverseComments reverses the []Comment list.
-func reverseComments(list []Comment) {
-       for i, j := 0, len(list)-1; i < j; i, j = i+1, j-1 {
-               list[i], list[j] = list[j], list[i]
-       }
-}
-
-func (in *input) parseFile() {
-       in.file = new(FileSyntax)
-       var cb *CommentBlock
-       for {
-               switch in.peek() {
-               case '\n':
-                       in.lex()
-                       if cb != nil {
-                               in.file.Stmt = append(in.file.Stmt, cb)
-                               cb = nil
-                       }
-               case _COMMENT:
-                       tok := in.lex()
-                       if cb == nil {
-                               cb = &CommentBlock{Start: tok.pos}
-                       }
-                       com := cb.Comment()
-                       com.Before = append(com.Before, Comment{Start: tok.pos, Token: tok.text})
-               case _EOF:
-                       if cb != nil {
-                               in.file.Stmt = append(in.file.Stmt, cb)
-                       }
-                       return
-               default:
-                       in.parseStmt()
-                       if cb != nil {
-                               in.file.Stmt[len(in.file.Stmt)-1].Comment().Before = cb.Before
-                               cb = nil
-                       }
-               }
-       }
-}
-
-func (in *input) parseStmt() {
-       tok := in.lex()
-       start := tok.pos
-       end := tok.endPos
-       tokens := []string{tok.text}
-       for {
-               tok := in.lex()
-               switch {
-               case tok.kind.isEOL():
-                       in.file.Stmt = append(in.file.Stmt, &Line{
-                               Start: start,
-                               Token: tokens,
-                               End:   end,
-                       })
-                       return
-
-               case tok.kind == '(':
-                       if next := in.peek(); next.isEOL() {
-                               // Start of block: no more tokens on this line.
-                               in.file.Stmt = append(in.file.Stmt, in.parseLineBlock(start, tokens, tok))
-                               return
-                       } else if next == ')' {
-                               rparen := in.lex()
-                               if in.peek().isEOL() {
-                                       // Empty block.
-                                       in.lex()
-                                       in.file.Stmt = append(in.file.Stmt, &LineBlock{
-                                               Start:  start,
-                                               Token:  tokens,
-                                               LParen: LParen{Pos: tok.pos},
-                                               RParen: RParen{Pos: rparen.pos},
-                                       })
-                                       return
-                               }
-                               // '( )' in the middle of the line, not a block.
-                               tokens = append(tokens, tok.text, rparen.text)
-                       } else {
-                               // '(' in the middle of the line, not a block.
-                               tokens = append(tokens, tok.text)
-                       }
-
-               default:
-                       tokens = append(tokens, tok.text)
-                       end = tok.endPos
-               }
-       }
-}
-
-func (in *input) parseLineBlock(start Position, token []string, lparen token) *LineBlock {
-       x := &LineBlock{
-               Start:  start,
-               Token:  token,
-               LParen: LParen{Pos: lparen.pos},
-       }
-       var comments []Comment
-       for {
-               switch in.peek() {
-               case _EOLCOMMENT:
-                       // Suffix comment, will be attached later by assignComments.
-                       in.lex()
-               case '\n':
-                       // Blank line. Add an empty comment to preserve it.
-                       in.lex()
-                       if len(comments) == 0 && len(x.Line) > 0 || len(comments) > 0 && comments[len(comments)-1].Token != "" {
-                               comments = append(comments, Comment{})
-                       }
-               case _COMMENT:
-                       tok := in.lex()
-                       comments = append(comments, Comment{Start: tok.pos, Token: tok.text})
-               case _EOF:
-                       in.Error(fmt.Sprintf("syntax error (unterminated block started at %s:%d:%d)", in.filename, x.Start.Line, x.Start.LineRune))
-               case ')':
-                       rparen := in.lex()
-                       x.RParen.Before = comments
-                       x.RParen.Pos = rparen.pos
-                       if !in.peek().isEOL() {
-                               in.Error("syntax error (expected newline after closing paren)")
-                       }
-                       in.lex()
-                       return x
-               default:
-                       l := in.parseLine()
-                       x.Line = append(x.Line, l)
-                       l.Comment().Before = comments
-                       comments = nil
-               }
-       }
-}
-
-func (in *input) parseLine() *Line {
-       tok := in.lex()
-       if tok.kind.isEOL() {
-               in.Error("internal parse error: parseLine at end of line")
-       }
-       start := tok.pos
-       end := tok.endPos
-       tokens := []string{tok.text}
-       for {
-               tok := in.lex()
-               if tok.kind.isEOL() {
-                       return &Line{
-                               Start:   start,
-                               Token:   tokens,
-                               End:     end,
-                               InBlock: true,
-                       }
-               }
-               tokens = append(tokens, tok.text)
-               end = tok.endPos
-       }
-}
-
-var (
-       slashSlash = []byte("//")
-       moduleStr  = []byte("module")
-)
-
-// ModulePath returns the module path from the gomod file text.
-// If it cannot find a module path, it returns an empty string.
-// It is tolerant of unrelated problems in the go.mod file.
-func ModulePath(mod []byte) string {
-       for len(mod) > 0 {
-               line := mod
-               mod = nil
-               if i := bytes.IndexByte(line, '\n'); i >= 0 {
-                       line, mod = line[:i], line[i+1:]
-               }
-               if i := bytes.Index(line, slashSlash); i >= 0 {
-                       line = line[:i]
-               }
-               line = bytes.TrimSpace(line)
-               if !bytes.HasPrefix(line, moduleStr) {
-                       continue
-               }
-               line = line[len(moduleStr):]
-               n := len(line)
-               line = bytes.TrimSpace(line)
-               if len(line) == n || len(line) == 0 {
-                       continue
-               }
-
-               if line[0] == '"' || line[0] == '`' {
-                       p, err := strconv.Unquote(string(line))
-                       if err != nil {
-                               return "" // malformed quoted string or multiline module path
-                       }
-                       return p
-               }
-
-               return string(line)
-       }
-       return "" // missing module path
-}