cmd/go/internal/modfile: go.mod file parser and printer
diff --git a/vendor/cmd/go/internal/modfile/print.go b/vendor/cmd/go/internal/modfile/print.go
new file mode 100644
index 0000000..cefc43b
--- /dev/null
+++ b/vendor/cmd/go/internal/modfile/print.go
@@ -0,0 +1,164 @@
+// 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.
+
+// Module file printer.
+
+package modfile
+
+import (
+	"bytes"
+	"fmt"
+	"strings"
+)
+
+func Format(f *FileSyntax) []byte {
+	pr := &printer{}
+	pr.file(f)
+	return pr.Bytes()
+}
+
+// A printer collects the state during printing of a file or expression.
+type printer struct {
+	bytes.Buffer           // output buffer
+	comment      []Comment // pending end-of-line comments
+	margin       int       // left margin (indent), a number of tabs
+}
+
+// printf prints to the buffer.
+func (p *printer) printf(format string, args ...interface{}) {
+	fmt.Fprintf(p, format, args...)
+}
+
+// indent returns the position on the current line, in bytes, 0-indexed.
+func (p *printer) indent() int {
+	b := p.Bytes()
+	n := 0
+	for n < len(b) && b[len(b)-1-n] != '\n' {
+		n++
+	}
+	return n
+}
+
+// newline ends the current line, flushing end-of-line comments.
+func (p *printer) newline() {
+	if len(p.comment) > 0 {
+		p.printf(" ")
+		for i, com := range p.comment {
+			if i > 0 {
+				p.trim()
+				p.printf("\n")
+				for i := 0; i < p.margin; i++ {
+					p.printf("\t")
+				}
+			}
+			p.printf("%s", strings.TrimSpace(com.Token))
+		}
+		p.comment = p.comment[:0]
+	}
+
+	p.trim()
+	p.printf("\n")
+	for i := 0; i < p.margin; i++ {
+		p.printf("\t")
+	}
+}
+
+// trim removes trailing spaces and tabs from the current line.
+func (p *printer) trim() {
+	// Remove trailing spaces and tabs from line we're about to end.
+	b := p.Bytes()
+	n := len(b)
+	for n > 0 && (b[n-1] == '\t' || b[n-1] == ' ') {
+		n--
+	}
+	p.Truncate(n)
+}
+
+// file formats the given file into the print buffer.
+func (p *printer) file(f *FileSyntax) {
+	for _, com := range f.Before {
+		p.printf("%s", strings.TrimSpace(com.Token))
+		p.newline()
+	}
+
+	for i, stmt := range f.Stmt {
+		switch x := stmt.(type) {
+		case *CommentBlock:
+			// comments already handled
+			p.expr(x)
+
+		default:
+			p.expr(x)
+			p.newline()
+		}
+
+		for _, com := range stmt.Comment().After {
+			p.printf("%s", strings.TrimSpace(com.Token))
+			p.newline()
+		}
+
+		if i+1 < len(f.Stmt) {
+			p.newline()
+		}
+	}
+}
+
+func (p *printer) expr(x Expr) {
+	// Emit line-comments preceding this expression.
+	if before := x.Comment().Before; len(before) > 0 {
+		// Want to print a line comment.
+		// Line comments must be at the current margin.
+		p.trim()
+		if p.indent() > 0 {
+			// There's other text on the line. Start a new line.
+			p.printf("\n")
+		}
+		// Re-indent to margin.
+		for i := 0; i < p.margin; i++ {
+			p.printf("\t")
+		}
+		for _, com := range before {
+			p.printf("%s", strings.TrimSpace(com.Token))
+			p.newline()
+		}
+	}
+
+	switch x := x.(type) {
+	default:
+		panic(fmt.Errorf("printer: unexpected type %T", x))
+
+	case *CommentBlock:
+		// done
+
+	case *LParen:
+		p.printf("(")
+	case *RParen:
+		p.printf(")")
+
+	case *Line:
+		sep := ""
+		for _, tok := range x.Token {
+			p.printf("%s%s", sep, tok)
+			sep = " "
+		}
+
+	case *LineBlock:
+		for _, tok := range x.Token {
+			p.printf("%s ", tok)
+		}
+		p.expr(&x.LParen)
+		p.margin++
+		for _, l := range x.Line {
+			p.newline()
+			p.expr(l)
+		}
+		p.margin--
+		p.newline()
+		p.expr(&x.RParen)
+	}
+
+	// Queue end-of-line comments for printing when we
+	// reach the end of the line.
+	p.comment = append(p.comment, x.Comment().Suffix...)
+}
diff --git a/vendor/cmd/go/internal/modfile/read.go b/vendor/cmd/go/internal/modfile/read.go
new file mode 100644
index 0000000..7fdf827
--- /dev/null
+++ b/vendor/cmd/go/internal/modfile/read.go
@@ -0,0 +1,683 @@
+// 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.
+
+// Module file parser.
+// This is a simplified copy of Google's buildifier parser.
+
+package modfile
+
+import (
+	"bytes"
+	"fmt"
+	"os"
+	"strings"
+	"unicode"
+	"unicode/utf8"
+)
+
+// A Position describes the position between two bytes of input.
+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
+}
+
+// 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
+	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
+	token     []byte    // token being scanned
+	lastToken string    // most recently returned token, for error messages
+	pos       Position  // current input position
+	comments  []Comment // accumulated comments
+	endRule   int       // position of end of current rule
+
+	// Parser state.
+	file       *FileSyntax // returned top-level syntax tree
+	parseError error       // error 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) {
+	in := newInput(file, data)
+	// 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.
+	defer func() {
+		if e := recover(); e != nil {
+			if e == in.parseError {
+				err = in.parseError
+			} else {
+				err = fmt.Errorf("%s:%d:%d: internal error: %v", in.filename, in.pos.Line, in.pos.LineRune, e)
+			}
+		}
+	}()
+
+	// Invoke the parser.
+	in.parseFile()
+	if in.parseError != nil {
+		return nil, in.parseError
+	}
+	in.file.Name = in.filename
+
+	// Assign comments to nearby syntax.
+	in.assignComments()
+
+	return in.file, nil
+}
+
+// Error is called to report an error.
+// The reason s is often "syntax error".
+// Error does not return: it panics.
+func (in *input) Error(s string) {
+	if s == "syntax error" && in.lastToken != "" {
+		s += " near " + in.lastToken
+	}
+	in.parseError = fmt.Errorf("%s:%d:%d: %v", in.filename, in.pos.Line, in.pos.LineRune, s)
+	panic(in.parseError)
+}
+
+// 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)
+}
+
+// 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 symType struct {
+	pos    Position
+	endPos Position
+	text   string
+}
+
+// startToken marks the beginning of the next input token.
+// It must be followed by a call to endToken, once the token has
+// been consumed using readRune.
+func (in *input) startToken(sym *symType) {
+	in.token = in.remaining
+	sym.text = ""
+	sym.pos = in.pos
+}
+
+// endToken marks the end of an input token.
+// It records the actual token string in sym.text if the caller
+// has not done that already.
+func (in *input) endToken(sym *symType) {
+	if sym.text == "" {
+		tok := string(in.token[:len(in.token)-len(in.remaining)])
+		sym.text = tok
+		in.lastToken = sym.text
+	}
+	sym.endPos = in.pos
+}
+
+// lex is called from the parser to obtain the next input token.
+// It returns the token value (either a rune like '+' or a symbolic token _FOR)
+// and sets val to the data associated with the token.
+// For all our input tokens, the associated data is
+// val.Pos (the position where the token begins)
+// and val.Token (the input string corresponding to the token).
+func (in *input) lex(sym *symType) int {
+	// Skip past spaces, stopping at non-space or EOF.
+	countNL := 0 // number of newlines we've skipped past
+	for !in.eof() {
+		// Skip over spaces. Count newlines so we can give the parser
+		// information about where top-level blank lines are,
+		// for top-level comment assignment.
+		c := in.peekRune()
+		if c == ' ' || c == '\t' || c == '\r' {
+			in.readRune()
+			continue
+		}
+
+		// Comment runs to end of line.
+		if c == '/' {
+			in.startToken(sym)
+
+			// 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()
+			c = in.peekRune()
+			if c == '*' {
+				in.Error(fmt.Sprintf("mod files must use // comments (not /* */ comments)"))
+			}
+			if c != '/' {
+				in.Error(fmt.Sprintf("unexpected input character %#q", c))
+			}
+
+			// Consume comment.
+			for len(in.remaining) > 0 && in.readRune() != '\n' {
+			}
+			in.endToken(sym)
+
+			sym.text = strings.TrimRight(sym.text, "\n")
+			in.lastToken = "comment"
+
+			// 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 {
+				// Not in a statement. Tell parser about top-level comment.
+				return _COMMENT
+			}
+
+			// Otherwise, save comment for later attachment to syntax tree.
+			if countNL > 1 {
+				in.comments = append(in.comments, Comment{sym.pos, "", false})
+			}
+			in.comments = append(in.comments, Comment{sym.pos, sym.text, suffix})
+			countNL = 1
+			return _EOL
+		}
+
+		// Found non-space non-comment.
+		break
+	}
+
+	// Found the beginning of the next token.
+	in.startToken(sym)
+	defer in.endToken(sym)
+
+	// End of file.
+	if in.eof() {
+		in.lastToken = "EOF"
+		return _EOF
+	}
+
+	// Punctuation tokens.
+	switch c := in.peekRune(); c {
+	case '\n':
+		in.readRune()
+		return c
+
+	case '(':
+		in.readRune()
+		return c
+
+	case ')':
+		in.readRune()
+		return c
+
+	case '"', '`': // quoted string
+		quote := c
+		in.readRune()
+		for {
+			if in.eof() {
+				in.pos = sym.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 = sym.pos
+					in.Error("unexpected EOF in string")
+				}
+				in.readRune()
+			}
+		}
+		in.endToken(sym)
+		return _STRING
+	}
+
+	// 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()) {
+		in.readRune()
+	}
+	return _IDENT
+}
+
+// isIdent reports whether c is an identifier rune.
+// We treat nearly all runes as identifier runes.
+func isIdent(c int) bool {
+	return c != 0 && !unicode.IsSpace(rune(c)) && c != '/' && c != '(' && c != ')' && c != '"' && c != '`'
+}
+
+// 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.Printf("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.Printf("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 sym symType
+	var cb *CommentBlock
+	for {
+		tok := in.lex(&sym)
+		switch tok {
+		case '\n':
+			if cb != nil {
+				in.file.Stmt = append(in.file.Stmt, cb)
+				cb = nil
+			}
+		case _COMMENT:
+			if cb == nil {
+				cb = &CommentBlock{Start: sym.pos}
+			}
+			com := cb.Comment()
+			com.Before = append(com.Before, Comment{Start: sym.pos, Token: sym.text})
+		case _EOF:
+			if cb != nil {
+				in.file.Stmt = append(in.file.Stmt, cb)
+			}
+			return
+		default:
+			in.parseStmt(&sym)
+			if cb != nil {
+				in.file.Stmt[len(in.file.Stmt)-1].Comment().Before = cb.Before
+				cb = nil
+			}
+		}
+	}
+}
+
+func (in *input) parseStmt(sym *symType) {
+	start := sym.pos
+	end := sym.endPos
+	token := []string{sym.text}
+	for {
+		tok := in.lex(sym)
+		switch tok {
+		case '\n', _EOF, _EOL:
+			in.file.Stmt = append(in.file.Stmt, &Line{
+				Start: start,
+				Token: token,
+				End:   end,
+			})
+			return
+		case '(':
+			in.file.Stmt = append(in.file.Stmt, in.parseLineBlock(start, token, sym))
+			return
+		default:
+			token = append(token, sym.text)
+			end = sym.endPos
+		}
+	}
+}
+
+func (in *input) parseLineBlock(start Position, token []string, sym *symType) *LineBlock {
+	x := &LineBlock{
+		Start:  start,
+		Token:  token,
+		LParen: LParen{Pos: sym.pos},
+	}
+	var comments []Comment
+	for {
+		tok := in.lex(sym)
+		switch tok {
+		case _EOL:
+			// ignore
+		case '\n':
+			if len(comments) == 0 && len(x.Line) > 0 || len(comments) > 0 && comments[len(comments)-1].Token != "" {
+				comments = append(comments, Comment{})
+			}
+		case _COMMENT:
+			comments = append(comments, Comment{Start: sym.pos, Token: sym.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 ')':
+			x.RParen.Before = comments
+			x.RParen.Pos = sym.pos
+			tok = in.lex(sym)
+			if tok != '\n' && tok != _EOF && tok != _EOL {
+				in.Error("syntax error (expected newline after closing paren)")
+			}
+			return x
+		default:
+			l := in.parseLine(sym)
+			x.Line = append(x.Line, l)
+			l.Comment().Before = comments
+			comments = nil
+		}
+	}
+}
+
+func (in *input) parseLine(sym *symType) *Line {
+	start := sym.pos
+	end := sym.endPos
+	token := []string{sym.text}
+	for {
+		tok := in.lex(sym)
+		switch tok {
+		case '\n', _EOF, _EOL:
+			return &Line{
+				Start: start,
+				Token: token,
+				End:   end,
+			}
+		default:
+			token = append(token, sym.text)
+			end = sym.endPos
+		}
+	}
+}
+
+const (
+	_EOF = -(1 + iota)
+	_EOL
+	_IDENT
+	_STRING
+	_COMMENT
+)
diff --git a/vendor/cmd/go/internal/modfile/read_test.go b/vendor/cmd/go/internal/modfile/read_test.go
new file mode 100644
index 0000000..004993d
--- /dev/null
+++ b/vendor/cmd/go/internal/modfile/read_test.go
@@ -0,0 +1,285 @@
+// 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"
+	"fmt"
+	"io/ioutil"
+	"os"
+	"os/exec"
+	"path/filepath"
+	"reflect"
+	"strings"
+	"testing"
+)
+
+// exists reports whether the named file exists.
+func exists(name string) bool {
+	_, err := os.Stat(name)
+	return err == nil
+}
+
+// Test that reading and then writing the golden files
+// does not change their output.
+func TestPrintGolden(t *testing.T) {
+	outs, err := filepath.Glob("testdata/*.golden")
+	if err != nil {
+		t.Fatal(err)
+	}
+	for _, out := range outs {
+		testPrint(t, out, out)
+	}
+}
+
+// testPrint is a helper for testing the printer.
+// It reads the file named in, reformats it, and compares
+// the result to the file named out.
+func testPrint(t *testing.T, in, out string) {
+	data, err := ioutil.ReadFile(in)
+	if err != nil {
+		t.Error(err)
+		return
+	}
+
+	golden, err := ioutil.ReadFile(out)
+	if err != nil {
+		t.Error(err)
+		return
+	}
+
+	base := "testdata/" + filepath.Base(in)
+	f, err := parse(in, data)
+	if err != nil {
+		t.Error(err)
+		return
+	}
+
+	ndata := Format(f)
+
+	if !bytes.Equal(ndata, golden) {
+		t.Errorf("formatted %s incorrectly: diff shows -golden, +ours", base)
+		tdiff(t, string(golden), string(ndata))
+		return
+	}
+}
+
+// Test that when files in the testdata directory are parsed
+// and printed and parsed again, we get the same parse tree
+// both times.
+func TestPrintParse(t *testing.T) {
+	outs, err := filepath.Glob("testdata/*")
+	if err != nil {
+		t.Fatal(err)
+	}
+	for _, out := range outs {
+		data, err := ioutil.ReadFile(out)
+		if err != nil {
+			t.Error(err)
+			continue
+		}
+
+		base := "testdata/" + filepath.Base(out)
+		f, err := parse(base, data)
+		if err != nil {
+			t.Errorf("parsing original: %v", err)
+			continue
+		}
+
+		ndata := Format(f)
+		f2, err := parse(base, ndata)
+		if err != nil {
+			t.Errorf("parsing reformatted: %v", err)
+			continue
+		}
+
+		eq := eqchecker{file: base}
+		if err := eq.check(f, f2); err != nil {
+			t.Errorf("not equal: %v", err)
+		}
+
+		pf1, err := Parse(base, data)
+		if err == nil {
+			pf2, err := Parse(base, ndata)
+			if err != nil {
+				t.Errorf("Parsing reformatted: %v", err)
+				continue
+			}
+			eq := eqchecker{file: base}
+			if err := eq.check(pf1, pf2); err != nil {
+				t.Errorf("not equal: %v", err)
+			}
+		}
+
+		if strings.HasSuffix(out, ".in") {
+			golden, err := ioutil.ReadFile(strings.TrimSuffix(out, ".in") + ".golden")
+			if err != nil {
+				t.Error(err)
+				continue
+			}
+			if !bytes.Equal(ndata, golden) {
+				t.Errorf("formatted %s incorrectly: diff shows -golden, +ours", base)
+				tdiff(t, string(golden), string(ndata))
+				return
+			}
+		}
+	}
+}
+
+// An eqchecker holds state for checking the equality of two parse trees.
+type eqchecker struct {
+	file string
+	pos  Position
+}
+
+// errorf returns an error described by the printf-style format and arguments,
+// inserting the current file position before the error text.
+func (eq *eqchecker) errorf(format string, args ...interface{}) error {
+	return fmt.Errorf("%s:%d: %s", eq.file, eq.pos.Line,
+		fmt.Sprintf(format, args...))
+}
+
+// check checks that v and w represent the same parse tree.
+// If not, it returns an error describing the first difference.
+func (eq *eqchecker) check(v, w interface{}) error {
+	return eq.checkValue(reflect.ValueOf(v), reflect.ValueOf(w))
+}
+
+var (
+	posType      = reflect.TypeOf(Position{})
+	commentsType = reflect.TypeOf(Comments{})
+)
+
+// checkValue checks that v and w represent the same parse tree.
+// If not, it returns an error describing the first difference.
+func (eq *eqchecker) checkValue(v, w reflect.Value) error {
+	// inner returns the innermost expression for v.
+	// if v is a non-nil interface value, it returns the concrete
+	// value in the interface.
+	inner := func(v reflect.Value) reflect.Value {
+		for {
+			if v.Kind() == reflect.Interface && !v.IsNil() {
+				v = v.Elem()
+				continue
+			}
+			break
+		}
+		return v
+	}
+
+	v = inner(v)
+	w = inner(w)
+	if v.Kind() == reflect.Invalid && w.Kind() == reflect.Invalid {
+		return nil
+	}
+	if v.Kind() == reflect.Invalid {
+		return eq.errorf("nil interface became %s", w.Type())
+	}
+	if w.Kind() == reflect.Invalid {
+		return eq.errorf("%s became nil interface", v.Type())
+	}
+
+	if v.Type() != w.Type() {
+		return eq.errorf("%s became %s", v.Type(), w.Type())
+	}
+
+	if p, ok := v.Interface().(Expr); ok {
+		eq.pos, _ = p.Span()
+	}
+
+	switch v.Kind() {
+	default:
+		return eq.errorf("unexpected type %s", v.Type())
+
+	case reflect.Bool, reflect.Int, reflect.String:
+		vi := v.Interface()
+		wi := w.Interface()
+		if vi != wi {
+			return eq.errorf("%v became %v", vi, wi)
+		}
+
+	case reflect.Slice:
+		vl := v.Len()
+		wl := w.Len()
+		for i := 0; i < vl || i < wl; i++ {
+			if i >= vl {
+				return eq.errorf("unexpected %s", w.Index(i).Type())
+			}
+			if i >= wl {
+				return eq.errorf("missing %s", v.Index(i).Type())
+			}
+			if err := eq.checkValue(v.Index(i), w.Index(i)); err != nil {
+				return err
+			}
+		}
+
+	case reflect.Struct:
+		// Fields in struct must match.
+		t := v.Type()
+		n := t.NumField()
+		for i := 0; i < n; i++ {
+			tf := t.Field(i)
+			switch {
+			default:
+				if err := eq.checkValue(v.Field(i), w.Field(i)); err != nil {
+					return err
+				}
+
+			case tf.Type == posType: // ignore positions
+			case tf.Type == commentsType: // ignore comment assignment
+			}
+		}
+
+	case reflect.Ptr, reflect.Interface:
+		if v.IsNil() != w.IsNil() {
+			if v.IsNil() {
+				return eq.errorf("unexpected %s", w.Elem().Type())
+			}
+			return eq.errorf("missing %s", v.Elem().Type())
+		}
+		if err := eq.checkValue(v.Elem(), w.Elem()); err != nil {
+			return err
+		}
+	}
+	return nil
+}
+
+// diff returns the output of running diff on b1 and b2.
+func diff(b1, b2 []byte) (data []byte, err error) {
+	f1, err := ioutil.TempFile("", "testdiff")
+	if err != nil {
+		return nil, err
+	}
+	defer os.Remove(f1.Name())
+	defer f1.Close()
+
+	f2, err := ioutil.TempFile("", "testdiff")
+	if err != nil {
+		return nil, err
+	}
+	defer os.Remove(f2.Name())
+	defer f2.Close()
+
+	f1.Write(b1)
+	f2.Write(b2)
+
+	data, err = exec.Command("diff", "-u", f1.Name(), f2.Name()).CombinedOutput()
+	if len(data) > 0 {
+		// diff exits with a non-zero status when the files don't match.
+		// Ignore that failure as long as we get output.
+		err = nil
+	}
+	return
+}
+
+// tdiff logs the diff output to t.Error.
+func tdiff(t *testing.T, a, b string) {
+	data, err := diff([]byte(a), []byte(b))
+	if err != nil {
+		t.Error(err)
+		return
+	}
+	t.Error(string(data))
+}
diff --git a/vendor/cmd/go/internal/modfile/rule.go b/vendor/cmd/go/internal/modfile/rule.go
new file mode 100644
index 0000000..73a52dc
--- /dev/null
+++ b/vendor/cmd/go/internal/modfile/rule.go
@@ -0,0 +1,458 @@
+// 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"
+	"path/filepath"
+	"sort"
+	"strconv"
+	"strings"
+
+	"cmd/go/internal/module"
+	"cmd/go/internal/semver"
+)
+
+type File struct {
+	Module  *Module
+	Require []*Require
+	Exclude []*Exclude
+	Replace []*Replace
+
+	Syntax *FileSyntax
+}
+
+type Module struct {
+	Mod   module.Version
+	Major string
+}
+
+type Require struct {
+	Mod    module.Version
+	Syntax *Line
+}
+
+type Exclude struct {
+	Mod    module.Version
+	Syntax *Line
+}
+
+type Replace struct {
+	Old module.Version
+	New module.Version
+
+	Syntax *Line
+}
+
+func (f *File) AddModuleStmt(path string) {
+	f.Module = &Module{
+		Mod: module.Version{Path: path},
+	}
+	if f.Syntax == nil {
+		f.Syntax = new(FileSyntax)
+	}
+	f.Syntax.Stmt = append(f.Syntax.Stmt, &Line{
+		Token: []string{"module", strconv.Quote(path)},
+	})
+}
+
+func Parse(file string, data []byte) (*File, error) {
+	fs, err := parse(file, data)
+	if err != nil {
+		return nil, err
+	}
+	f := &File{
+		Syntax: fs,
+	}
+
+	var errs bytes.Buffer
+	for _, x := range fs.Stmt {
+		switch x := x.(type) {
+		case *Line:
+			f.add(&errs, x, x.Token[0], x.Token[1:])
+
+		case *LineBlock:
+			if len(x.Token) > 1 {
+				fmt.Fprintf(&errs, "%s:%d: unknown block type: %s\n", file, x.Start.Line, strings.Join(x.Token, " "))
+				continue
+			}
+			switch x.Token[0] {
+			default:
+				fmt.Fprintf(&errs, "%s:%d: unknown block type: %s\n", file, x.Start.Line, strings.Join(x.Token, " "))
+				continue
+			case "module", "require", "exclude", "replace":
+				for _, l := range x.Line {
+					f.add(&errs, l, x.Token[0], l.Token)
+				}
+			}
+		}
+	}
+
+	if errs.Len() > 0 {
+		return nil, errors.New(strings.TrimRight(errs.String(), "\n"))
+	}
+	return f, nil
+}
+
+func (f *File) add(errs *bytes.Buffer, line *Line, verb string, args []string) {
+	// TODO: We should pass in a flag saying whether this module is a dependency.
+	// If so, we should ignore all unknown directives and not attempt to parse
+	// replace and exclude either. They don't matter, and it will work better for
+	// forward compatibility if we can depend on modules that have local changes.
+
+	// TODO: For the target module (not dependencies), maybe we should
+	// relax the semver requirement and rewrite the file with updated info
+	// after resolving any versions. That would let people type commit hashes
+	// or tags or branch names, and then vgo would fix them.
+
+	switch verb {
+	default:
+		fmt.Fprintf(errs, "%s:%d: unknown directive: %s\n", f.Syntax.Name, line.Start.Line, verb)
+	case "module":
+		if f.Module != nil {
+			fmt.Fprintf(errs, "%s:%d: repeated module statement\n", f.Syntax.Name, line.Start.Line)
+			return
+		}
+		f.Module = new(Module)
+		if len(args) != 1 || !isString(args[0]) {
+
+			fmt.Fprintf(errs, "%s:%d: usage: module \"module/path\" [version]\n", f.Syntax.Name, line.Start.Line)
+			return
+		}
+		s, err := parseString(&args[0])
+		if err != nil {
+			fmt.Fprintf(errs, "%s:%d: invalid quoted string: %v\n", f.Syntax.Name, line.Start.Line, err)
+			return
+		}
+		f.Module.Mod = module.Version{Path: s}
+	case "require", "exclude":
+		if len(args) != 2 || !isString(args[0]) || isString(args[1]) {
+			fmt.Fprintf(errs, "%s:%d: usage: %s \"module/path\" v1.2.3\n", f.Syntax.Name, line.Start.Line, verb)
+			return
+		}
+		s, err := parseString(&args[0])
+		if err != nil {
+			fmt.Fprintf(errs, "%s:%d: invalid quoted string: %v\n", f.Syntax.Name, line.Start.Line, err)
+			return
+		}
+		v, err := parseVersion(&args[1])
+		if err != nil {
+			fmt.Fprintf(errs, "%s:%d: invalid module version: %v\n", f.Syntax.Name, line.Start.Line, err)
+			return
+		}
+		v1, err := moduleMajorVersion(s)
+		if err != nil {
+			fmt.Fprintf(errs, "%s:%d: %v\n", f.Syntax.Name, line.Start.Line, err)
+			return
+		}
+		if v2 := semver.Major(v); v1 != v2 && (v1 != "v1" || v2 != "v0") {
+			fmt.Fprintf(errs, "%s:%d: invalid module: %s should be %s, not %s (%s)\n", f.Syntax.Name, line.Start.Line, s, v1, v2, v)
+			return
+		}
+		if verb == "require" {
+			f.Require = append(f.Require, &Require{
+				Mod:    module.Version{Path: s, Version: v},
+				Syntax: line,
+			})
+		} else {
+			f.Exclude = append(f.Exclude, &Exclude{
+				Mod:    module.Version{Path: s, Version: v},
+				Syntax: line,
+			})
+		}
+	case "replace":
+		if len(args) < 4 || len(args) > 5 || !isString(args[0]) || isString(args[1]) || args[2] != "=>" || !isString(args[3]) || len(args) == 5 && isString(args[4]) {
+			fmt.Fprintf(errs, "%s:%d: usage: %s \"module/path\" v1.2.3 -> \"other/module\" v1.4\n\t or %s \"module/path\" v1.2.3 -> \"../local/directory\"", f.Syntax.Name, line.Start.Line, verb, verb)
+			return
+		}
+		s, err := parseString(&args[0])
+		if err != nil {
+			fmt.Fprintf(errs, "%s:%d: invalid quoted string: %v\n", f.Syntax.Name, line.Start.Line, err)
+			return
+		}
+		v, err := parseVersion(&args[1])
+		if err != nil {
+			fmt.Fprintf(errs, "%s:%d: invalid module version: %v\n", f.Syntax.Name, line.Start.Line, err)
+			return
+		}
+		v1, err := moduleMajorVersion(s)
+		if err != nil {
+			fmt.Fprintf(errs, "%s:%d: %v\n", f.Syntax.Name, line.Start.Line, err)
+			return
+		}
+		if v2 := semver.Major(v); v1 != v2 && (v1 != "v1" || v2 != "v0") {
+			fmt.Fprintf(errs, "%s:%d: invalid module: %s should be %s, not %s (%s)\n", f.Syntax.Name, line.Start.Line, s, v1, v2, v)
+			return
+		}
+		ns, err := parseString(&args[3])
+		if err != nil {
+			fmt.Fprintf(errs, "%s:%d: invalid quoted string: %v\n", f.Syntax.Name, line.Start.Line, err)
+			return
+		}
+		nv := ""
+		if len(args) == 4 {
+			if !isDirectoryPath(ns) {
+				fmt.Fprintf(errs, "%s:%d: replacement module without version must be directory path (rooted or starting with ./ or ../)", f.Syntax.Name, line.Start.Line)
+				return
+			}
+			if filepath.Separator == '/' && strings.Contains(ns, `\`) {
+				fmt.Fprintf(errs, "%s:%d: replacement directory appears to be Windows path (on a non-windows system)", f.Syntax.Name, line.Start.Line)
+				return
+			}
+		}
+		if len(args) == 5 {
+			nv, err = parseVersion(&args[4])
+			if err != nil {
+				fmt.Fprintf(errs, "%s:%d: invalid module version: %v\n", f.Syntax.Name, line.Start.Line, err)
+				return
+			}
+			if isDirectoryPath(ns) {
+				fmt.Fprintf(errs, "%s:%d: replacement module directory path %q cannot have version", f.Syntax.Name, line.Start.Line, ns)
+				return
+			}
+		}
+		// TODO: More sanity checks about directories vs module paths.
+		f.Replace = append(f.Replace, &Replace{
+			Old:    module.Version{Path: s, Version: v},
+			New:    module.Version{Path: ns, Version: nv},
+			Syntax: line,
+		})
+	}
+}
+
+func isDirectoryPath(ns string) bool {
+	// Because go.mod files can move from one system to another,
+	// we check all known path syntaxes, both Unix and Windows.
+	return strings.HasPrefix(ns, "./") || strings.HasPrefix(ns, "../") || strings.HasPrefix(ns, "/") ||
+		strings.HasPrefix(ns, `.\`) || strings.HasPrefix(ns, `..\`) || strings.HasPrefix(ns, `\`) ||
+		len(ns) >= 2 && ('A' <= ns[0] && ns[0] <= 'Z' || 'a' <= ns[0] && ns[0] <= 'z') && ns[1] == ':'
+}
+
+func isString(s string) bool {
+	return s != "" && s[0] == '"'
+}
+
+func parseString(s *string) (string, error) {
+	t, err := strconv.Unquote(*s)
+	if err != nil {
+		return "", err
+	}
+	*s = strconv.Quote(t)
+	return t, nil
+}
+
+func parseVersion(s *string) (string, error) {
+	t := *s
+	// TODO: Actual version syntax check.
+	if t[0] != 'v' {
+		return "", fmt.Errorf("version must be of the form v1.2.3")
+	}
+	return *s, nil
+}
+
+func moduleMajorVersion(p string) (string, error) {
+	start := 0
+	for i := 0; i < len(p); i++ {
+		if p[i] == '/' {
+			if isMajorVersion(p[start:i]) {
+				return "", fmt.Errorf("module path contains non-final version element %s", p[start:i])
+			}
+			start = i + 1
+		}
+	}
+	v := p[start:]
+	if !isMajorVersion(v) {
+		return "v1", nil
+	}
+	if v[1] == '0' || v == "v1" {
+		return "", fmt.Errorf("module path has invalid version number %s", v)
+	}
+	return v, nil
+}
+
+func isMajorVersion(v string) bool {
+	if len(v) < 2 || v[0] != 'v' {
+		return false
+	}
+	for i := 1; i < len(v); i++ {
+		if v[i] < '0' || '9' < v[i] {
+			return false
+		}
+	}
+	return true
+}
+
+func (f *File) Format() ([]byte, error) {
+	return Format(f.Syntax), nil
+}
+
+func (x *File) AddRequire(path, vers string) {
+	var syntax *Line
+
+	for i, stmt := range x.Syntax.Stmt {
+		switch stmt := stmt.(type) {
+		case *LineBlock:
+			if len(stmt.Token) > 0 && stmt.Token[0] == "require" {
+				syntax = &Line{Token: []string{strconv.Quote(path), vers}}
+				stmt.Line = append(stmt.Line, syntax)
+				goto End
+			}
+		case *Line:
+			if len(stmt.Token) > 0 && stmt.Token[0] == "require" {
+				stmt.Token = stmt.Token[1:]
+				syntax = &Line{Token: []string{strconv.Quote(path), vers}}
+				x.Syntax.Stmt[i] = &LineBlock{
+					Comments: stmt.Comments,
+					Token:    []string{"require"},
+					Line: []*Line{
+						stmt,
+						syntax,
+					},
+				}
+				goto End
+			}
+		}
+	}
+
+	syntax = &Line{Token: []string{"require", strconv.Quote(path), vers}}
+	x.Syntax.Stmt = append(x.Syntax.Stmt, syntax)
+
+End:
+	x.Require = append(x.Require, &Require{module.Version{path, vers}, syntax})
+}
+
+func (f *File) SetRequire(req []module.Version) {
+	need := make(map[string]string)
+	for _, m := range req {
+		need[m.Path] = m.Version
+	}
+
+	for _, r := range f.Require {
+		if v, ok := need[r.Mod.Path]; ok {
+			r.Mod.Version = v
+		}
+	}
+
+	var newStmts []Expr
+	for _, stmt := range f.Syntax.Stmt {
+		switch stmt := stmt.(type) {
+		case *LineBlock:
+			if len(stmt.Token) > 0 && stmt.Token[0] == "require" {
+				var newLines []*Line
+				for _, line := range stmt.Line {
+					if p, err := strconv.Unquote(line.Token[0]); err == nil && need[p] != "" {
+						line.Token[1] = need[p]
+						delete(need, p)
+						newLines = append(newLines, line)
+					}
+				}
+				if len(newLines) == 0 {
+					continue // drop stmt
+				}
+				stmt.Line = newLines
+			}
+
+		case *Line:
+			if len(stmt.Token) > 0 && stmt.Token[0] == "require" {
+				if p, err := strconv.Unquote(stmt.Token[1]); err == nil && need[p] != "" {
+					stmt.Token[2] = need[p]
+					delete(need, p)
+				} else {
+					continue // drop stmt
+				}
+			}
+		}
+		newStmts = append(newStmts, stmt)
+	}
+	f.Syntax.Stmt = newStmts
+
+	for path, vers := range need {
+		f.AddRequire(path, vers)
+	}
+	f.SortBlocks()
+}
+
+func (f *File) SortBlocks() {
+	f.removeDups() // otherwise sorting is unsafe
+
+	for _, stmt := range f.Syntax.Stmt {
+		block, ok := stmt.(*LineBlock)
+		if !ok {
+			continue
+		}
+		sort.Slice(block.Line, func(i, j int) bool {
+			li := block.Line[i]
+			lj := block.Line[j]
+			for k := 0; k < len(li.Token) && k < len(lj.Token); k++ {
+				if li.Token[k] != lj.Token[k] {
+					return li.Token[k] < lj.Token[k]
+				}
+			}
+			return len(li.Token) < len(lj.Token)
+		})
+	}
+}
+
+func (f *File) removeDups() {
+	have := make(map[module.Version]bool)
+	kill := make(map[*Line]bool)
+	for _, x := range f.Exclude {
+		if have[x.Mod] {
+			kill[x.Syntax] = true
+			continue
+		}
+		have[x.Mod] = true
+	}
+	var excl []*Exclude
+	for _, x := range f.Exclude {
+		if !kill[x.Syntax] {
+			excl = append(excl, x)
+		}
+	}
+	f.Exclude = excl
+
+	have = make(map[module.Version]bool)
+	// Later replacements take priority over earlier ones.
+	for i := len(f.Replace) - 1; i >= 0; i-- {
+		x := f.Replace[i]
+		if have[x.Old] {
+			kill[x.Syntax] = true
+			continue
+		}
+		have[x.Old] = true
+	}
+	var repl []*Replace
+	for _, x := range f.Replace {
+		if !kill[x.Syntax] {
+			repl = append(repl, x)
+		}
+	}
+	f.Replace = repl
+
+	var stmts []Expr
+	for _, stmt := range f.Syntax.Stmt {
+		switch stmt := stmt.(type) {
+		case *Line:
+			if kill[stmt] {
+				continue
+			}
+		case *LineBlock:
+			var lines []*Line
+			for _, line := range stmt.Line {
+				if !kill[line] {
+					lines = append(lines, line)
+				}
+			}
+			stmt.Line = lines
+			if len(lines) == 0 {
+				continue
+			}
+		}
+		stmts = append(stmts, stmt)
+	}
+	f.Syntax.Stmt = stmts
+}
diff --git a/vendor/cmd/go/internal/modfile/testdata/block.golden b/vendor/cmd/go/internal/modfile/testdata/block.golden
new file mode 100644
index 0000000..4aa2d63
--- /dev/null
+++ b/vendor/cmd/go/internal/modfile/testdata/block.golden
@@ -0,0 +1,29 @@
+// comment
+x "y" z
+
+// block
+block ( // block-eol
+	// x-before-line
+
+	"x" ( y // x-eol
+	"x1"
+	"x2"
+	// line
+	"x3"
+	"x4"
+
+	"x5"
+
+	// y-line
+	"y" //  y-eol
+
+	"z" // z-eol
+) // block-eol2
+
+block2 (
+	x
+	y
+	z
+)
+
+// eof
diff --git a/vendor/cmd/go/internal/modfile/testdata/block.in b/vendor/cmd/go/internal/modfile/testdata/block.in
new file mode 100644
index 0000000..1dfae65
--- /dev/null
+++ b/vendor/cmd/go/internal/modfile/testdata/block.in
@@ -0,0 +1,29 @@
+// comment
+x "y" z
+
+// block
+block ( // block-eol
+	// x-before-line
+	
+	"x" ( y // x-eol
+	"x1"
+	"x2"
+	// line
+	"x3"
+	"x4"
+	
+	"x5"
+	
+	// y-line
+	"y" //  y-eol
+	
+	"z" // z-eol
+) // block-eol2
+
+
+block2 (x
+	y
+	z
+)
+
+// eof
diff --git a/vendor/cmd/go/internal/modfile/testdata/comment.golden b/vendor/cmd/go/internal/modfile/testdata/comment.golden
new file mode 100644
index 0000000..75f3b84
--- /dev/null
+++ b/vendor/cmd/go/internal/modfile/testdata/comment.golden
@@ -0,0 +1,10 @@
+// comment
+module "x" // eol
+
+// mid comment
+
+// comment 2
+// comment 2 line 2
+module "y" // eoy
+
+// comment 3
diff --git a/vendor/cmd/go/internal/modfile/testdata/comment.in b/vendor/cmd/go/internal/modfile/testdata/comment.in
new file mode 100644
index 0000000..bfc2492
--- /dev/null
+++ b/vendor/cmd/go/internal/modfile/testdata/comment.in
@@ -0,0 +1,8 @@
+// comment
+module "x" // eol
+// mid comment
+
+// comment 2
+// comment 2 line 2
+module "y" // eoy
+// comment 3
diff --git a/vendor/cmd/go/internal/modfile/testdata/empty.golden b/vendor/cmd/go/internal/modfile/testdata/empty.golden
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/vendor/cmd/go/internal/modfile/testdata/empty.golden
diff --git a/vendor/cmd/go/internal/modfile/testdata/empty.in b/vendor/cmd/go/internal/modfile/testdata/empty.in
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/vendor/cmd/go/internal/modfile/testdata/empty.in
diff --git a/vendor/cmd/go/internal/modfile/testdata/module.golden b/vendor/cmd/go/internal/modfile/testdata/module.golden
new file mode 100644
index 0000000..08f3836
--- /dev/null
+++ b/vendor/cmd/go/internal/modfile/testdata/module.golden
@@ -0,0 +1 @@
+module "abc"
diff --git a/vendor/cmd/go/internal/modfile/testdata/module.in b/vendor/cmd/go/internal/modfile/testdata/module.in
new file mode 100644
index 0000000..08f3836
--- /dev/null
+++ b/vendor/cmd/go/internal/modfile/testdata/module.in
@@ -0,0 +1 @@
+module "abc"
diff --git a/vendor/cmd/go/internal/modfile/testdata/replace.golden b/vendor/cmd/go/internal/modfile/testdata/replace.golden
new file mode 100644
index 0000000..6852499
--- /dev/null
+++ b/vendor/cmd/go/internal/modfile/testdata/replace.golden
@@ -0,0 +1,5 @@
+module "abc"
+
+replace "xyz" v1.2.3 => "/tmp/z"
+
+replace "xyz" v1.3.4 => "my/xyz" v1.3.4-me
diff --git a/vendor/cmd/go/internal/modfile/testdata/replace.in b/vendor/cmd/go/internal/modfile/testdata/replace.in
new file mode 100644
index 0000000..6852499
--- /dev/null
+++ b/vendor/cmd/go/internal/modfile/testdata/replace.in
@@ -0,0 +1,5 @@
+module "abc"
+
+replace "xyz" v1.2.3 => "/tmp/z"
+
+replace "xyz" v1.3.4 => "my/xyz" v1.3.4-me
diff --git a/vendor/cmd/go/internal/modfile/testdata/replace2.golden b/vendor/cmd/go/internal/modfile/testdata/replace2.golden
new file mode 100644
index 0000000..e80962e
--- /dev/null
+++ b/vendor/cmd/go/internal/modfile/testdata/replace2.golden
@@ -0,0 +1,6 @@
+module "abc"
+
+replace (
+	"xyz" v1.2.3 => "/tmp/z"
+	"xyz" v1.3.4 => "my/xyz" v1.3.4-me
+)
diff --git a/vendor/cmd/go/internal/modfile/testdata/replace2.in b/vendor/cmd/go/internal/modfile/testdata/replace2.in
new file mode 100644
index 0000000..e80962e
--- /dev/null
+++ b/vendor/cmd/go/internal/modfile/testdata/replace2.in
@@ -0,0 +1,6 @@
+module "abc"
+
+replace (
+	"xyz" v1.2.3 => "/tmp/z"
+	"xyz" v1.3.4 => "my/xyz" v1.3.4-me
+)
diff --git a/vendor/cmd/go/internal/modfile/testdata/rule1.golden b/vendor/cmd/go/internal/modfile/testdata/rule1.golden
new file mode 100644
index 0000000..8a5c725
--- /dev/null
+++ b/vendor/cmd/go/internal/modfile/testdata/rule1.golden
@@ -0,0 +1,7 @@
+module "x"
+
+module "y"
+
+require "x"
+
+require x