Merge pull request #28204 from thockin/cleanup-third_party
Automatic merge from submit-queue Cleanup third party (pt 2) Move forked-and-hacked golang code to the forked/ directory. Remove ast/build/parse code that is now in stdlib. Remove unused shell2junit
This commit is contained in:
		@@ -18,14 +18,13 @@ package protobuf
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
import (
 | 
					import (
 | 
				
			||||||
	"fmt"
 | 
						"fmt"
 | 
				
			||||||
 | 
						"go/ast"
 | 
				
			||||||
	"log"
 | 
						"log"
 | 
				
			||||||
	"os"
 | 
						"os"
 | 
				
			||||||
	"path/filepath"
 | 
						"path/filepath"
 | 
				
			||||||
	"reflect"
 | 
						"reflect"
 | 
				
			||||||
	"strings"
 | 
						"strings"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	"k8s.io/kubernetes/third_party/golang/go/ast"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	"k8s.io/kubernetes/cmd/libs/go2idl/generator"
 | 
						"k8s.io/kubernetes/cmd/libs/go2idl/generator"
 | 
				
			||||||
	"k8s.io/kubernetes/cmd/libs/go2idl/types"
 | 
						"k8s.io/kubernetes/cmd/libs/go2idl/types"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -20,17 +20,17 @@ import (
 | 
				
			|||||||
	"bytes"
 | 
						"bytes"
 | 
				
			||||||
	"errors"
 | 
						"errors"
 | 
				
			||||||
	"fmt"
 | 
						"fmt"
 | 
				
			||||||
 | 
						"go/ast"
 | 
				
			||||||
	"go/format"
 | 
						"go/format"
 | 
				
			||||||
 | 
						"go/parser"
 | 
				
			||||||
 | 
						"go/printer"
 | 
				
			||||||
 | 
						"go/token"
 | 
				
			||||||
	"io/ioutil"
 | 
						"io/ioutil"
 | 
				
			||||||
	"os"
 | 
						"os"
 | 
				
			||||||
	"reflect"
 | 
						"reflect"
 | 
				
			||||||
	"strings"
 | 
						"strings"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	"k8s.io/kubernetes/third_party/golang/go/ast"
 | 
						customreflect "k8s.io/kubernetes/third_party/forked/golang/reflect"
 | 
				
			||||||
	"k8s.io/kubernetes/third_party/golang/go/parser"
 | 
					 | 
				
			||||||
	"k8s.io/kubernetes/third_party/golang/go/printer"
 | 
					 | 
				
			||||||
	"k8s.io/kubernetes/third_party/golang/go/token"
 | 
					 | 
				
			||||||
	customreflect "k8s.io/kubernetes/third_party/golang/reflect"
 | 
					 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func rewriteFile(name string, header []byte, rewriteFn func(*token.FileSet, *ast.File) error) error {
 | 
					func rewriteFile(name string, header []byte, rewriteFn func(*token.FileSet, *ast.File) error) error {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -18,20 +18,19 @@ package parser
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
import (
 | 
					import (
 | 
				
			||||||
	"fmt"
 | 
						"fmt"
 | 
				
			||||||
 | 
						"go/ast"
 | 
				
			||||||
 | 
						"go/build"
 | 
				
			||||||
 | 
						"go/parser"
 | 
				
			||||||
 | 
						"go/token"
 | 
				
			||||||
 | 
						tc "go/types"
 | 
				
			||||||
	"io/ioutil"
 | 
						"io/ioutil"
 | 
				
			||||||
	"os"
 | 
						"os"
 | 
				
			||||||
	"os/exec"
 | 
						"os/exec"
 | 
				
			||||||
	"path/filepath"
 | 
						"path/filepath"
 | 
				
			||||||
	"strings"
 | 
						"strings"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	"k8s.io/kubernetes/cmd/libs/go2idl/types"
 | 
					 | 
				
			||||||
	"k8s.io/kubernetes/third_party/golang/go/ast"
 | 
					 | 
				
			||||||
	"k8s.io/kubernetes/third_party/golang/go/build"
 | 
					 | 
				
			||||||
	"k8s.io/kubernetes/third_party/golang/go/parser"
 | 
					 | 
				
			||||||
	"k8s.io/kubernetes/third_party/golang/go/token"
 | 
					 | 
				
			||||||
	tc "k8s.io/kubernetes/third_party/golang/go/types"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	"github.com/golang/glog"
 | 
						"github.com/golang/glog"
 | 
				
			||||||
 | 
						"k8s.io/kubernetes/cmd/libs/go2idl/types"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Builder lets you add all the go files in all the packages that you care
 | 
					// Builder lets you add all the go files in all the packages that you care
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -17,7 +17,7 @@ limitations under the License.
 | 
				
			|||||||
package conversion
 | 
					package conversion
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import (
 | 
					import (
 | 
				
			||||||
	"k8s.io/kubernetes/third_party/forked/reflect"
 | 
						"k8s.io/kubernetes/third_party/forked/golang/reflect"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// The code for this type must be located in third_party, since it forks from
 | 
					// The code for this type must be located in third_party, since it forks from
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -27,7 +27,7 @@ import (
 | 
				
			|||||||
	"k8s.io/kubernetes/pkg/runtime"
 | 
						"k8s.io/kubernetes/pkg/runtime"
 | 
				
			||||||
	"k8s.io/kubernetes/pkg/types"
 | 
						"k8s.io/kubernetes/pkg/types"
 | 
				
			||||||
	hashutil "k8s.io/kubernetes/pkg/util/hash"
 | 
						hashutil "k8s.io/kubernetes/pkg/util/hash"
 | 
				
			||||||
	"k8s.io/kubernetes/third_party/golang/expansion"
 | 
						"k8s.io/kubernetes/third_party/forked/golang/expansion"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	"github.com/golang/glog"
 | 
						"github.com/golang/glog"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -97,7 +97,7 @@ import (
 | 
				
			|||||||
	"k8s.io/kubernetes/pkg/watch"
 | 
						"k8s.io/kubernetes/pkg/watch"
 | 
				
			||||||
	"k8s.io/kubernetes/plugin/pkg/scheduler/algorithm/predicates"
 | 
						"k8s.io/kubernetes/plugin/pkg/scheduler/algorithm/predicates"
 | 
				
			||||||
	"k8s.io/kubernetes/plugin/pkg/scheduler/schedulercache"
 | 
						"k8s.io/kubernetes/plugin/pkg/scheduler/schedulercache"
 | 
				
			||||||
	"k8s.io/kubernetes/third_party/golang/expansion"
 | 
						"k8s.io/kubernetes/third_party/forked/golang/expansion"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const (
 | 
					const (
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -32,7 +32,7 @@ import (
 | 
				
			|||||||
	apierrors "k8s.io/kubernetes/pkg/api/errors"
 | 
						apierrors "k8s.io/kubernetes/pkg/api/errors"
 | 
				
			||||||
	"k8s.io/kubernetes/pkg/api/unversioned"
 | 
						"k8s.io/kubernetes/pkg/api/unversioned"
 | 
				
			||||||
	"k8s.io/kubernetes/pkg/util/httpstream"
 | 
						"k8s.io/kubernetes/pkg/util/httpstream"
 | 
				
			||||||
	"k8s.io/kubernetes/third_party/golang/netutil"
 | 
						"k8s.io/kubernetes/third_party/forked/golang/netutil"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// SpdyRoundTripper knows how to upgrade an HTTP request to one that supports
 | 
					// SpdyRoundTripper knows how to upgrade an HTTP request to one that supports
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -23,7 +23,7 @@ import (
 | 
				
			|||||||
	"reflect"
 | 
						"reflect"
 | 
				
			||||||
	"strings"
 | 
						"strings"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	"k8s.io/kubernetes/third_party/golang/template"
 | 
						"k8s.io/kubernetes/third_party/forked/golang/template"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type JSONPath struct {
 | 
					type JSONPath struct {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -26,7 +26,7 @@ import (
 | 
				
			|||||||
	"github.com/golang/glog"
 | 
						"github.com/golang/glog"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	utilnet "k8s.io/kubernetes/pkg/util/net"
 | 
						utilnet "k8s.io/kubernetes/pkg/util/net"
 | 
				
			||||||
	"k8s.io/kubernetes/third_party/golang/netutil"
 | 
						"k8s.io/kubernetes/third_party/forked/golang/netutil"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func DialURL(url *url.URL, transport http.RoundTripper) (net.Conn, error) {
 | 
					func DialURL(url *url.URL, transport http.RoundTripper) (net.Conn, error) {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -22,7 +22,7 @@ import (
 | 
				
			|||||||
	"sort"
 | 
						"sort"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	"k8s.io/kubernetes/pkg/util/json"
 | 
						"k8s.io/kubernetes/pkg/util/json"
 | 
				
			||||||
	forkedjson "k8s.io/kubernetes/third_party/forked/json"
 | 
						forkedjson "k8s.io/kubernetes/third_party/forked/golang/json"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	"github.com/davecgh/go-spew/spew"
 | 
						"github.com/davecgh/go-spew/spew"
 | 
				
			||||||
	"github.com/ghodss/yaml"
 | 
						"github.com/ghodss/yaml"
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										27
									
								
								third_party/forked/reflect/LICENSE
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										27
									
								
								third_party/forked/reflect/LICENSE
									
									
									
									
										vendored
									
									
								
							@@ -1,27 +0,0 @@
 | 
				
			|||||||
Copyright (c) 2012 The Go Authors. All rights reserved.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
Redistribution and use in source and binary forms, with or without
 | 
					 | 
				
			||||||
modification, are permitted provided that the following conditions are
 | 
					 | 
				
			||||||
met:
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
   * Redistributions of source code must retain the above copyright
 | 
					 | 
				
			||||||
notice, this list of conditions and the following disclaimer.
 | 
					 | 
				
			||||||
   * Redistributions in binary form must reproduce the above
 | 
					 | 
				
			||||||
copyright notice, this list of conditions and the following disclaimer
 | 
					 | 
				
			||||||
in the documentation and/or other materials provided with the
 | 
					 | 
				
			||||||
distribution.
 | 
					 | 
				
			||||||
   * Neither the name of Google Inc. nor the names of its
 | 
					 | 
				
			||||||
contributors may be used to endorse or promote products derived from
 | 
					 | 
				
			||||||
this software without specific prior written permission.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 | 
					 | 
				
			||||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 | 
					 | 
				
			||||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 | 
					 | 
				
			||||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 | 
					 | 
				
			||||||
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 | 
					 | 
				
			||||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 | 
					 | 
				
			||||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 | 
					 | 
				
			||||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 | 
					 | 
				
			||||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 | 
					 | 
				
			||||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 | 
					 | 
				
			||||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 | 
					 | 
				
			||||||
							
								
								
									
										27
									
								
								third_party/golang/LICENSE
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										27
									
								
								third_party/golang/LICENSE
									
									
									
									
										vendored
									
									
								
							@@ -1,27 +0,0 @@
 | 
				
			|||||||
Copyright (c) 2012 The Go Authors. All rights reserved.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
Redistribution and use in source and binary forms, with or without
 | 
					 | 
				
			||||||
modification, are permitted provided that the following conditions are
 | 
					 | 
				
			||||||
met:
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
   * Redistributions of source code must retain the above copyright
 | 
					 | 
				
			||||||
notice, this list of conditions and the following disclaimer.
 | 
					 | 
				
			||||||
   * Redistributions in binary form must reproduce the above
 | 
					 | 
				
			||||||
copyright notice, this list of conditions and the following disclaimer
 | 
					 | 
				
			||||||
in the documentation and/or other materials provided with the
 | 
					 | 
				
			||||||
distribution.
 | 
					 | 
				
			||||||
   * Neither the name of Google Inc. nor the names of its
 | 
					 | 
				
			||||||
contributors may be used to endorse or promote products derived from
 | 
					 | 
				
			||||||
this software without specific prior written permission.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 | 
					 | 
				
			||||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 | 
					 | 
				
			||||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 | 
					 | 
				
			||||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 | 
					 | 
				
			||||||
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 | 
					 | 
				
			||||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 | 
					 | 
				
			||||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 | 
					 | 
				
			||||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 | 
					 | 
				
			||||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 | 
					 | 
				
			||||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 | 
					 | 
				
			||||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 | 
					 | 
				
			||||||
							
								
								
									
										15
									
								
								third_party/golang/go/README.md
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										15
									
								
								third_party/golang/go/README.md
									
									
									
									
										vendored
									
									
								
							@@ -1,15 +0,0 @@
 | 
				
			|||||||
# Vendored copy of go1.5.1's standard library's go/... packages.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
Q: Why did you do this awful vendoring?
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
A: We need to build under go 1.3 and go 1.4 (soon to be go 1.4 and go 1.5.1). A
 | 
					 | 
				
			||||||
version of the go/types package existed for go 1.4, but it does not have the
 | 
					 | 
				
			||||||
same interface as the go 1.5 package, and @lavalamp had much better luck with
 | 
					 | 
				
			||||||
the 1.5.1 package anyway.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
We will get rid of this as soon as there's a more standard way to do this, or
 | 
					 | 
				
			||||||
when we roll over to supporting go 1.5 and go 1.6.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
Note that the packages here were not very happy about being transplated like
 | 
					 | 
				
			||||||
this and if you do a diff you will see the changes made to get everything to
 | 
					 | 
				
			||||||
compile.
 | 
					 | 
				
			||||||
							
								
								
									
										999
									
								
								third_party/golang/go/ast/ast.go
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										999
									
								
								third_party/golang/go/ast/ast.go
									
									
									
									
										vendored
									
									
								
							@@ -1,999 +0,0 @@
 | 
				
			|||||||
// Copyright 2009 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 ast declares the types used to represent syntax trees for Go
 | 
					 | 
				
			||||||
// packages.
 | 
					 | 
				
			||||||
//
 | 
					 | 
				
			||||||
package ast
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
import (
 | 
					 | 
				
			||||||
	"k8s.io/kubernetes/third_party/golang/go/token"
 | 
					 | 
				
			||||||
	"strings"
 | 
					 | 
				
			||||||
	"unicode"
 | 
					 | 
				
			||||||
	"unicode/utf8"
 | 
					 | 
				
			||||||
)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// ----------------------------------------------------------------------------
 | 
					 | 
				
			||||||
// Interfaces
 | 
					 | 
				
			||||||
//
 | 
					 | 
				
			||||||
// There are 3 main classes of nodes: Expressions and type nodes,
 | 
					 | 
				
			||||||
// statement nodes, and declaration nodes. The node names usually
 | 
					 | 
				
			||||||
// match the corresponding Go spec production names to which they
 | 
					 | 
				
			||||||
// correspond. The node fields correspond to the individual parts
 | 
					 | 
				
			||||||
// of the respective productions.
 | 
					 | 
				
			||||||
//
 | 
					 | 
				
			||||||
// All nodes contain position information marking the beginning of
 | 
					 | 
				
			||||||
// the corresponding source text segment; it is accessible via the
 | 
					 | 
				
			||||||
// Pos accessor method. Nodes may contain additional position info
 | 
					 | 
				
			||||||
// for language constructs where comments may be found between parts
 | 
					 | 
				
			||||||
// of the construct (typically any larger, parenthesized subpart).
 | 
					 | 
				
			||||||
// That position information is needed to properly position comments
 | 
					 | 
				
			||||||
// when printing the construct.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// All node types implement the Node interface.
 | 
					 | 
				
			||||||
type Node interface {
 | 
					 | 
				
			||||||
	Pos() token.Pos // position of first character belonging to the node
 | 
					 | 
				
			||||||
	End() token.Pos // position of first character immediately after the node
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// All expression nodes implement the Expr interface.
 | 
					 | 
				
			||||||
type Expr interface {
 | 
					 | 
				
			||||||
	Node
 | 
					 | 
				
			||||||
	exprNode()
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// All statement nodes implement the Stmt interface.
 | 
					 | 
				
			||||||
type Stmt interface {
 | 
					 | 
				
			||||||
	Node
 | 
					 | 
				
			||||||
	stmtNode()
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// All declaration nodes implement the Decl interface.
 | 
					 | 
				
			||||||
type Decl interface {
 | 
					 | 
				
			||||||
	Node
 | 
					 | 
				
			||||||
	declNode()
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// ----------------------------------------------------------------------------
 | 
					 | 
				
			||||||
// Comments
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// A Comment node represents a single //-style or /*-style comment.
 | 
					 | 
				
			||||||
type Comment struct {
 | 
					 | 
				
			||||||
	Slash token.Pos // position of "/" starting the comment
 | 
					 | 
				
			||||||
	Text  string    // comment text (excluding '\n' for //-style comments)
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (c *Comment) Pos() token.Pos { return c.Slash }
 | 
					 | 
				
			||||||
func (c *Comment) End() token.Pos { return token.Pos(int(c.Slash) + len(c.Text)) }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// A CommentGroup represents a sequence of comments
 | 
					 | 
				
			||||||
// with no other tokens and no empty lines between.
 | 
					 | 
				
			||||||
//
 | 
					 | 
				
			||||||
type CommentGroup struct {
 | 
					 | 
				
			||||||
	List []*Comment // len(List) > 0
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (g *CommentGroup) Pos() token.Pos { return g.List[0].Pos() }
 | 
					 | 
				
			||||||
func (g *CommentGroup) End() token.Pos { return g.List[len(g.List)-1].End() }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func isWhitespace(ch byte) bool { return ch == ' ' || ch == '\t' || ch == '\n' || ch == '\r' }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func stripTrailingWhitespace(s string) string {
 | 
					 | 
				
			||||||
	i := len(s)
 | 
					 | 
				
			||||||
	for i > 0 && isWhitespace(s[i-1]) {
 | 
					 | 
				
			||||||
		i--
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return s[0:i]
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// Text returns the text of the comment.
 | 
					 | 
				
			||||||
// Comment markers (//, /*, and */), the first space of a line comment, and
 | 
					 | 
				
			||||||
// leading and trailing empty lines are removed. Multiple empty lines are
 | 
					 | 
				
			||||||
// reduced to one, and trailing space on lines is trimmed. Unless the result
 | 
					 | 
				
			||||||
// is empty, it is newline-terminated.
 | 
					 | 
				
			||||||
//
 | 
					 | 
				
			||||||
func (g *CommentGroup) Text() string {
 | 
					 | 
				
			||||||
	if g == nil {
 | 
					 | 
				
			||||||
		return ""
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	comments := make([]string, len(g.List))
 | 
					 | 
				
			||||||
	for i, c := range g.List {
 | 
					 | 
				
			||||||
		comments[i] = string(c.Text)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	lines := make([]string, 0, 10) // most comments are less than 10 lines
 | 
					 | 
				
			||||||
	for _, c := range comments {
 | 
					 | 
				
			||||||
		// Remove comment markers.
 | 
					 | 
				
			||||||
		// The parser has given us exactly the comment text.
 | 
					 | 
				
			||||||
		switch c[1] {
 | 
					 | 
				
			||||||
		case '/':
 | 
					 | 
				
			||||||
			//-style comment (no newline at the end)
 | 
					 | 
				
			||||||
			c = c[2:]
 | 
					 | 
				
			||||||
			// strip first space - required for Example tests
 | 
					 | 
				
			||||||
			if len(c) > 0 && c[0] == ' ' {
 | 
					 | 
				
			||||||
				c = c[1:]
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		case '*':
 | 
					 | 
				
			||||||
			/*-style comment */
 | 
					 | 
				
			||||||
			c = c[2 : len(c)-2]
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		// Split on newlines.
 | 
					 | 
				
			||||||
		cl := strings.Split(c, "\n")
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		// Walk lines, stripping trailing white space and adding to list.
 | 
					 | 
				
			||||||
		for _, l := range cl {
 | 
					 | 
				
			||||||
			lines = append(lines, stripTrailingWhitespace(l))
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// Remove leading blank lines; convert runs of
 | 
					 | 
				
			||||||
	// interior blank lines to a single blank line.
 | 
					 | 
				
			||||||
	n := 0
 | 
					 | 
				
			||||||
	for _, line := range lines {
 | 
					 | 
				
			||||||
		if line != "" || n > 0 && lines[n-1] != "" {
 | 
					 | 
				
			||||||
			lines[n] = line
 | 
					 | 
				
			||||||
			n++
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	lines = lines[0:n]
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// Add final "" entry to get trailing newline from Join.
 | 
					 | 
				
			||||||
	if n > 0 && lines[n-1] != "" {
 | 
					 | 
				
			||||||
		lines = append(lines, "")
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return strings.Join(lines, "\n")
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// ----------------------------------------------------------------------------
 | 
					 | 
				
			||||||
// Expressions and types
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// A Field represents a Field declaration list in a struct type,
 | 
					 | 
				
			||||||
// a method list in an interface type, or a parameter/result declaration
 | 
					 | 
				
			||||||
// in a signature.
 | 
					 | 
				
			||||||
//
 | 
					 | 
				
			||||||
type Field struct {
 | 
					 | 
				
			||||||
	Doc     *CommentGroup // associated documentation; or nil
 | 
					 | 
				
			||||||
	Names   []*Ident      // field/method/parameter names; or nil if anonymous field
 | 
					 | 
				
			||||||
	Type    Expr          // field/method/parameter type
 | 
					 | 
				
			||||||
	Tag     *BasicLit     // field tag; or nil
 | 
					 | 
				
			||||||
	Comment *CommentGroup // line comments; or nil
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (f *Field) Pos() token.Pos {
 | 
					 | 
				
			||||||
	if len(f.Names) > 0 {
 | 
					 | 
				
			||||||
		return f.Names[0].Pos()
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return f.Type.Pos()
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (f *Field) End() token.Pos {
 | 
					 | 
				
			||||||
	if f.Tag != nil {
 | 
					 | 
				
			||||||
		return f.Tag.End()
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return f.Type.End()
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// A FieldList represents a list of Fields, enclosed by parentheses or braces.
 | 
					 | 
				
			||||||
type FieldList struct {
 | 
					 | 
				
			||||||
	Opening token.Pos // position of opening parenthesis/brace, if any
 | 
					 | 
				
			||||||
	List    []*Field  // field list; or nil
 | 
					 | 
				
			||||||
	Closing token.Pos // position of closing parenthesis/brace, if any
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (f *FieldList) Pos() token.Pos {
 | 
					 | 
				
			||||||
	if f.Opening.IsValid() {
 | 
					 | 
				
			||||||
		return f.Opening
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	// the list should not be empty in this case;
 | 
					 | 
				
			||||||
	// be conservative and guard against bad ASTs
 | 
					 | 
				
			||||||
	if len(f.List) > 0 {
 | 
					 | 
				
			||||||
		return f.List[0].Pos()
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return token.NoPos
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (f *FieldList) End() token.Pos {
 | 
					 | 
				
			||||||
	if f.Closing.IsValid() {
 | 
					 | 
				
			||||||
		return f.Closing + 1
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	// the list should not be empty in this case;
 | 
					 | 
				
			||||||
	// be conservative and guard against bad ASTs
 | 
					 | 
				
			||||||
	if n := len(f.List); n > 0 {
 | 
					 | 
				
			||||||
		return f.List[n-1].End()
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return token.NoPos
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// NumFields returns the number of (named and anonymous fields) in a FieldList.
 | 
					 | 
				
			||||||
func (f *FieldList) NumFields() int {
 | 
					 | 
				
			||||||
	n := 0
 | 
					 | 
				
			||||||
	if f != nil {
 | 
					 | 
				
			||||||
		for _, g := range f.List {
 | 
					 | 
				
			||||||
			m := len(g.Names)
 | 
					 | 
				
			||||||
			if m == 0 {
 | 
					 | 
				
			||||||
				m = 1 // anonymous field
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
			n += m
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return n
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// An expression is represented by a tree consisting of one
 | 
					 | 
				
			||||||
// or more of the following concrete expression nodes.
 | 
					 | 
				
			||||||
//
 | 
					 | 
				
			||||||
type (
 | 
					 | 
				
			||||||
	// A BadExpr node is a placeholder for expressions containing
 | 
					 | 
				
			||||||
	// syntax errors for which no correct expression nodes can be
 | 
					 | 
				
			||||||
	// created.
 | 
					 | 
				
			||||||
	//
 | 
					 | 
				
			||||||
	BadExpr struct {
 | 
					 | 
				
			||||||
		From, To token.Pos // position range of bad expression
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// An Ident node represents an identifier.
 | 
					 | 
				
			||||||
	Ident struct {
 | 
					 | 
				
			||||||
		NamePos token.Pos // identifier position
 | 
					 | 
				
			||||||
		Name    string    // identifier name
 | 
					 | 
				
			||||||
		Obj     *Object   // denoted object; or nil
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// An Ellipsis node stands for the "..." type in a
 | 
					 | 
				
			||||||
	// parameter list or the "..." length in an array type.
 | 
					 | 
				
			||||||
	//
 | 
					 | 
				
			||||||
	Ellipsis struct {
 | 
					 | 
				
			||||||
		Ellipsis token.Pos // position of "..."
 | 
					 | 
				
			||||||
		Elt      Expr      // ellipsis element type (parameter lists only); or nil
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// A BasicLit node represents a literal of basic type.
 | 
					 | 
				
			||||||
	BasicLit struct {
 | 
					 | 
				
			||||||
		ValuePos token.Pos   // literal position
 | 
					 | 
				
			||||||
		Kind     token.Token // token.INT, token.FLOAT, token.IMAG, token.CHAR, or token.STRING
 | 
					 | 
				
			||||||
		Value    string      // literal string; e.g. 42, 0x7f, 3.14, 1e-9, 2.4i, 'a', '\x7f', "foo" or `\m\n\o`
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// A FuncLit node represents a function literal.
 | 
					 | 
				
			||||||
	FuncLit struct {
 | 
					 | 
				
			||||||
		Type *FuncType  // function type
 | 
					 | 
				
			||||||
		Body *BlockStmt // function body
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// A CompositeLit node represents a composite literal.
 | 
					 | 
				
			||||||
	CompositeLit struct {
 | 
					 | 
				
			||||||
		Type   Expr      // literal type; or nil
 | 
					 | 
				
			||||||
		Lbrace token.Pos // position of "{"
 | 
					 | 
				
			||||||
		Elts   []Expr    // list of composite elements; or nil
 | 
					 | 
				
			||||||
		Rbrace token.Pos // position of "}"
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// A ParenExpr node represents a parenthesized expression.
 | 
					 | 
				
			||||||
	ParenExpr struct {
 | 
					 | 
				
			||||||
		Lparen token.Pos // position of "("
 | 
					 | 
				
			||||||
		X      Expr      // parenthesized expression
 | 
					 | 
				
			||||||
		Rparen token.Pos // position of ")"
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// A SelectorExpr node represents an expression followed by a selector.
 | 
					 | 
				
			||||||
	SelectorExpr struct {
 | 
					 | 
				
			||||||
		X   Expr   // expression
 | 
					 | 
				
			||||||
		Sel *Ident // field selector
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// An IndexExpr node represents an expression followed by an index.
 | 
					 | 
				
			||||||
	IndexExpr struct {
 | 
					 | 
				
			||||||
		X      Expr      // expression
 | 
					 | 
				
			||||||
		Lbrack token.Pos // position of "["
 | 
					 | 
				
			||||||
		Index  Expr      // index expression
 | 
					 | 
				
			||||||
		Rbrack token.Pos // position of "]"
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// An SliceExpr node represents an expression followed by slice indices.
 | 
					 | 
				
			||||||
	SliceExpr struct {
 | 
					 | 
				
			||||||
		X      Expr      // expression
 | 
					 | 
				
			||||||
		Lbrack token.Pos // position of "["
 | 
					 | 
				
			||||||
		Low    Expr      // begin of slice range; or nil
 | 
					 | 
				
			||||||
		High   Expr      // end of slice range; or nil
 | 
					 | 
				
			||||||
		Max    Expr      // maximum capacity of slice; or nil
 | 
					 | 
				
			||||||
		Slice3 bool      // true if 3-index slice (2 colons present)
 | 
					 | 
				
			||||||
		Rbrack token.Pos // position of "]"
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// A TypeAssertExpr node represents an expression followed by a
 | 
					 | 
				
			||||||
	// type assertion.
 | 
					 | 
				
			||||||
	//
 | 
					 | 
				
			||||||
	TypeAssertExpr struct {
 | 
					 | 
				
			||||||
		X      Expr      // expression
 | 
					 | 
				
			||||||
		Lparen token.Pos // position of "("
 | 
					 | 
				
			||||||
		Type   Expr      // asserted type; nil means type switch X.(type)
 | 
					 | 
				
			||||||
		Rparen token.Pos // position of ")"
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// A CallExpr node represents an expression followed by an argument list.
 | 
					 | 
				
			||||||
	CallExpr struct {
 | 
					 | 
				
			||||||
		Fun      Expr      // function expression
 | 
					 | 
				
			||||||
		Lparen   token.Pos // position of "("
 | 
					 | 
				
			||||||
		Args     []Expr    // function arguments; or nil
 | 
					 | 
				
			||||||
		Ellipsis token.Pos // position of "...", if any
 | 
					 | 
				
			||||||
		Rparen   token.Pos // position of ")"
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// A StarExpr node represents an expression of the form "*" Expression.
 | 
					 | 
				
			||||||
	// Semantically it could be a unary "*" expression, or a pointer type.
 | 
					 | 
				
			||||||
	//
 | 
					 | 
				
			||||||
	StarExpr struct {
 | 
					 | 
				
			||||||
		Star token.Pos // position of "*"
 | 
					 | 
				
			||||||
		X    Expr      // operand
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// A UnaryExpr node represents a unary expression.
 | 
					 | 
				
			||||||
	// Unary "*" expressions are represented via StarExpr nodes.
 | 
					 | 
				
			||||||
	//
 | 
					 | 
				
			||||||
	UnaryExpr struct {
 | 
					 | 
				
			||||||
		OpPos token.Pos   // position of Op
 | 
					 | 
				
			||||||
		Op    token.Token // operator
 | 
					 | 
				
			||||||
		X     Expr        // operand
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// A BinaryExpr node represents a binary expression.
 | 
					 | 
				
			||||||
	BinaryExpr struct {
 | 
					 | 
				
			||||||
		X     Expr        // left operand
 | 
					 | 
				
			||||||
		OpPos token.Pos   // position of Op
 | 
					 | 
				
			||||||
		Op    token.Token // operator
 | 
					 | 
				
			||||||
		Y     Expr        // right operand
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// A KeyValueExpr node represents (key : value) pairs
 | 
					 | 
				
			||||||
	// in composite literals.
 | 
					 | 
				
			||||||
	//
 | 
					 | 
				
			||||||
	KeyValueExpr struct {
 | 
					 | 
				
			||||||
		Key   Expr
 | 
					 | 
				
			||||||
		Colon token.Pos // position of ":"
 | 
					 | 
				
			||||||
		Value Expr
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// The direction of a channel type is indicated by one
 | 
					 | 
				
			||||||
// of the following constants.
 | 
					 | 
				
			||||||
//
 | 
					 | 
				
			||||||
type ChanDir int
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
const (
 | 
					 | 
				
			||||||
	SEND ChanDir = 1 << iota
 | 
					 | 
				
			||||||
	RECV
 | 
					 | 
				
			||||||
)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// A type is represented by a tree consisting of one
 | 
					 | 
				
			||||||
// or more of the following type-specific expression
 | 
					 | 
				
			||||||
// nodes.
 | 
					 | 
				
			||||||
//
 | 
					 | 
				
			||||||
type (
 | 
					 | 
				
			||||||
	// An ArrayType node represents an array or slice type.
 | 
					 | 
				
			||||||
	ArrayType struct {
 | 
					 | 
				
			||||||
		Lbrack token.Pos // position of "["
 | 
					 | 
				
			||||||
		Len    Expr      // Ellipsis node for [...]T array types, nil for slice types
 | 
					 | 
				
			||||||
		Elt    Expr      // element type
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// A StructType node represents a struct type.
 | 
					 | 
				
			||||||
	StructType struct {
 | 
					 | 
				
			||||||
		Struct     token.Pos  // position of "struct" keyword
 | 
					 | 
				
			||||||
		Fields     *FieldList // list of field declarations
 | 
					 | 
				
			||||||
		Incomplete bool       // true if (source) fields are missing in the Fields list
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// Pointer types are represented via StarExpr nodes.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// A FuncType node represents a function type.
 | 
					 | 
				
			||||||
	FuncType struct {
 | 
					 | 
				
			||||||
		Func    token.Pos  // position of "func" keyword (token.NoPos if there is no "func")
 | 
					 | 
				
			||||||
		Params  *FieldList // (incoming) parameters; non-nil
 | 
					 | 
				
			||||||
		Results *FieldList // (outgoing) results; or nil
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// An InterfaceType node represents an interface type.
 | 
					 | 
				
			||||||
	InterfaceType struct {
 | 
					 | 
				
			||||||
		Interface  token.Pos  // position of "interface" keyword
 | 
					 | 
				
			||||||
		Methods    *FieldList // list of methods
 | 
					 | 
				
			||||||
		Incomplete bool       // true if (source) methods are missing in the Methods list
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// A MapType node represents a map type.
 | 
					 | 
				
			||||||
	MapType struct {
 | 
					 | 
				
			||||||
		Map   token.Pos // position of "map" keyword
 | 
					 | 
				
			||||||
		Key   Expr
 | 
					 | 
				
			||||||
		Value Expr
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// A ChanType node represents a channel type.
 | 
					 | 
				
			||||||
	ChanType struct {
 | 
					 | 
				
			||||||
		Begin token.Pos // position of "chan" keyword or "<-" (whichever comes first)
 | 
					 | 
				
			||||||
		Arrow token.Pos // position of "<-" (token.NoPos if there is no "<-")
 | 
					 | 
				
			||||||
		Dir   ChanDir   // channel direction
 | 
					 | 
				
			||||||
		Value Expr      // value type
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// Pos and End implementations for expression/type nodes.
 | 
					 | 
				
			||||||
//
 | 
					 | 
				
			||||||
func (x *BadExpr) Pos() token.Pos  { return x.From }
 | 
					 | 
				
			||||||
func (x *Ident) Pos() token.Pos    { return x.NamePos }
 | 
					 | 
				
			||||||
func (x *Ellipsis) Pos() token.Pos { return x.Ellipsis }
 | 
					 | 
				
			||||||
func (x *BasicLit) Pos() token.Pos { return x.ValuePos }
 | 
					 | 
				
			||||||
func (x *FuncLit) Pos() token.Pos  { return x.Type.Pos() }
 | 
					 | 
				
			||||||
func (x *CompositeLit) Pos() token.Pos {
 | 
					 | 
				
			||||||
	if x.Type != nil {
 | 
					 | 
				
			||||||
		return x.Type.Pos()
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return x.Lbrace
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
func (x *ParenExpr) Pos() token.Pos      { return x.Lparen }
 | 
					 | 
				
			||||||
func (x *SelectorExpr) Pos() token.Pos   { return x.X.Pos() }
 | 
					 | 
				
			||||||
func (x *IndexExpr) Pos() token.Pos      { return x.X.Pos() }
 | 
					 | 
				
			||||||
func (x *SliceExpr) Pos() token.Pos      { return x.X.Pos() }
 | 
					 | 
				
			||||||
func (x *TypeAssertExpr) Pos() token.Pos { return x.X.Pos() }
 | 
					 | 
				
			||||||
func (x *CallExpr) Pos() token.Pos       { return x.Fun.Pos() }
 | 
					 | 
				
			||||||
func (x *StarExpr) Pos() token.Pos       { return x.Star }
 | 
					 | 
				
			||||||
func (x *UnaryExpr) Pos() token.Pos      { return x.OpPos }
 | 
					 | 
				
			||||||
func (x *BinaryExpr) Pos() token.Pos     { return x.X.Pos() }
 | 
					 | 
				
			||||||
func (x *KeyValueExpr) Pos() token.Pos   { return x.Key.Pos() }
 | 
					 | 
				
			||||||
func (x *ArrayType) Pos() token.Pos      { return x.Lbrack }
 | 
					 | 
				
			||||||
func (x *StructType) Pos() token.Pos     { return x.Struct }
 | 
					 | 
				
			||||||
func (x *FuncType) Pos() token.Pos {
 | 
					 | 
				
			||||||
	if x.Func.IsValid() || x.Params == nil { // see issue 3870
 | 
					 | 
				
			||||||
		return x.Func
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return x.Params.Pos() // interface method declarations have no "func" keyword
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
func (x *InterfaceType) Pos() token.Pos { return x.Interface }
 | 
					 | 
				
			||||||
func (x *MapType) Pos() token.Pos       { return x.Map }
 | 
					 | 
				
			||||||
func (x *ChanType) Pos() token.Pos      { return x.Begin }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (x *BadExpr) End() token.Pos { return x.To }
 | 
					 | 
				
			||||||
func (x *Ident) End() token.Pos   { return token.Pos(int(x.NamePos) + len(x.Name)) }
 | 
					 | 
				
			||||||
func (x *Ellipsis) End() token.Pos {
 | 
					 | 
				
			||||||
	if x.Elt != nil {
 | 
					 | 
				
			||||||
		return x.Elt.End()
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return x.Ellipsis + 3 // len("...")
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
func (x *BasicLit) End() token.Pos       { return token.Pos(int(x.ValuePos) + len(x.Value)) }
 | 
					 | 
				
			||||||
func (x *FuncLit) End() token.Pos        { return x.Body.End() }
 | 
					 | 
				
			||||||
func (x *CompositeLit) End() token.Pos   { return x.Rbrace + 1 }
 | 
					 | 
				
			||||||
func (x *ParenExpr) End() token.Pos      { return x.Rparen + 1 }
 | 
					 | 
				
			||||||
func (x *SelectorExpr) End() token.Pos   { return x.Sel.End() }
 | 
					 | 
				
			||||||
func (x *IndexExpr) End() token.Pos      { return x.Rbrack + 1 }
 | 
					 | 
				
			||||||
func (x *SliceExpr) End() token.Pos      { return x.Rbrack + 1 }
 | 
					 | 
				
			||||||
func (x *TypeAssertExpr) End() token.Pos { return x.Rparen + 1 }
 | 
					 | 
				
			||||||
func (x *CallExpr) End() token.Pos       { return x.Rparen + 1 }
 | 
					 | 
				
			||||||
func (x *StarExpr) End() token.Pos       { return x.X.End() }
 | 
					 | 
				
			||||||
func (x *UnaryExpr) End() token.Pos      { return x.X.End() }
 | 
					 | 
				
			||||||
func (x *BinaryExpr) End() token.Pos     { return x.Y.End() }
 | 
					 | 
				
			||||||
func (x *KeyValueExpr) End() token.Pos   { return x.Value.End() }
 | 
					 | 
				
			||||||
func (x *ArrayType) End() token.Pos      { return x.Elt.End() }
 | 
					 | 
				
			||||||
func (x *StructType) End() token.Pos     { return x.Fields.End() }
 | 
					 | 
				
			||||||
func (x *FuncType) End() token.Pos {
 | 
					 | 
				
			||||||
	if x.Results != nil {
 | 
					 | 
				
			||||||
		return x.Results.End()
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return x.Params.End()
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
func (x *InterfaceType) End() token.Pos { return x.Methods.End() }
 | 
					 | 
				
			||||||
func (x *MapType) End() token.Pos       { return x.Value.End() }
 | 
					 | 
				
			||||||
func (x *ChanType) End() token.Pos      { return x.Value.End() }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// exprNode() ensures that only expression/type nodes can be
 | 
					 | 
				
			||||||
// assigned to an Expr.
 | 
					 | 
				
			||||||
//
 | 
					 | 
				
			||||||
func (*BadExpr) exprNode()        {}
 | 
					 | 
				
			||||||
func (*Ident) exprNode()          {}
 | 
					 | 
				
			||||||
func (*Ellipsis) exprNode()       {}
 | 
					 | 
				
			||||||
func (*BasicLit) exprNode()       {}
 | 
					 | 
				
			||||||
func (*FuncLit) exprNode()        {}
 | 
					 | 
				
			||||||
func (*CompositeLit) exprNode()   {}
 | 
					 | 
				
			||||||
func (*ParenExpr) exprNode()      {}
 | 
					 | 
				
			||||||
func (*SelectorExpr) exprNode()   {}
 | 
					 | 
				
			||||||
func (*IndexExpr) exprNode()      {}
 | 
					 | 
				
			||||||
func (*SliceExpr) exprNode()      {}
 | 
					 | 
				
			||||||
func (*TypeAssertExpr) exprNode() {}
 | 
					 | 
				
			||||||
func (*CallExpr) exprNode()       {}
 | 
					 | 
				
			||||||
func (*StarExpr) exprNode()       {}
 | 
					 | 
				
			||||||
func (*UnaryExpr) exprNode()      {}
 | 
					 | 
				
			||||||
func (*BinaryExpr) exprNode()     {}
 | 
					 | 
				
			||||||
func (*KeyValueExpr) exprNode()   {}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (*ArrayType) exprNode()     {}
 | 
					 | 
				
			||||||
func (*StructType) exprNode()    {}
 | 
					 | 
				
			||||||
func (*FuncType) exprNode()      {}
 | 
					 | 
				
			||||||
func (*InterfaceType) exprNode() {}
 | 
					 | 
				
			||||||
func (*MapType) exprNode()       {}
 | 
					 | 
				
			||||||
func (*ChanType) exprNode()      {}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// ----------------------------------------------------------------------------
 | 
					 | 
				
			||||||
// Convenience functions for Idents
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// NewIdent creates a new Ident without position.
 | 
					 | 
				
			||||||
// Useful for ASTs generated by code other than the Go parser.
 | 
					 | 
				
			||||||
//
 | 
					 | 
				
			||||||
func NewIdent(name string) *Ident { return &Ident{token.NoPos, name, nil} }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// IsExported reports whether name is an exported Go symbol
 | 
					 | 
				
			||||||
// (that is, whether it begins with an upper-case letter).
 | 
					 | 
				
			||||||
//
 | 
					 | 
				
			||||||
func IsExported(name string) bool {
 | 
					 | 
				
			||||||
	ch, _ := utf8.DecodeRuneInString(name)
 | 
					 | 
				
			||||||
	return unicode.IsUpper(ch)
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// IsExported reports whether id is an exported Go symbol
 | 
					 | 
				
			||||||
// (that is, whether it begins with an uppercase letter).
 | 
					 | 
				
			||||||
//
 | 
					 | 
				
			||||||
func (id *Ident) IsExported() bool { return IsExported(id.Name) }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (id *Ident) String() string {
 | 
					 | 
				
			||||||
	if id != nil {
 | 
					 | 
				
			||||||
		return id.Name
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return "<nil>"
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// ----------------------------------------------------------------------------
 | 
					 | 
				
			||||||
// Statements
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// A statement is represented by a tree consisting of one
 | 
					 | 
				
			||||||
// or more of the following concrete statement nodes.
 | 
					 | 
				
			||||||
//
 | 
					 | 
				
			||||||
type (
 | 
					 | 
				
			||||||
	// A BadStmt node is a placeholder for statements containing
 | 
					 | 
				
			||||||
	// syntax errors for which no correct statement nodes can be
 | 
					 | 
				
			||||||
	// created.
 | 
					 | 
				
			||||||
	//
 | 
					 | 
				
			||||||
	BadStmt struct {
 | 
					 | 
				
			||||||
		From, To token.Pos // position range of bad statement
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// A DeclStmt node represents a declaration in a statement list.
 | 
					 | 
				
			||||||
	DeclStmt struct {
 | 
					 | 
				
			||||||
		Decl Decl // *GenDecl with CONST, TYPE, or VAR token
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// An EmptyStmt node represents an empty statement.
 | 
					 | 
				
			||||||
	// The "position" of the empty statement is the position
 | 
					 | 
				
			||||||
	// of the immediately following (explicit or implicit) semicolon.
 | 
					 | 
				
			||||||
	//
 | 
					 | 
				
			||||||
	EmptyStmt struct {
 | 
					 | 
				
			||||||
		Semicolon token.Pos // position of following ";"
 | 
					 | 
				
			||||||
		Implicit  bool      // if set, ";" was omitted in the source
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// A LabeledStmt node represents a labeled statement.
 | 
					 | 
				
			||||||
	LabeledStmt struct {
 | 
					 | 
				
			||||||
		Label *Ident
 | 
					 | 
				
			||||||
		Colon token.Pos // position of ":"
 | 
					 | 
				
			||||||
		Stmt  Stmt
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// An ExprStmt node represents a (stand-alone) expression
 | 
					 | 
				
			||||||
	// in a statement list.
 | 
					 | 
				
			||||||
	//
 | 
					 | 
				
			||||||
	ExprStmt struct {
 | 
					 | 
				
			||||||
		X Expr // expression
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// A SendStmt node represents a send statement.
 | 
					 | 
				
			||||||
	SendStmt struct {
 | 
					 | 
				
			||||||
		Chan  Expr
 | 
					 | 
				
			||||||
		Arrow token.Pos // position of "<-"
 | 
					 | 
				
			||||||
		Value Expr
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// An IncDecStmt node represents an increment or decrement statement.
 | 
					 | 
				
			||||||
	IncDecStmt struct {
 | 
					 | 
				
			||||||
		X      Expr
 | 
					 | 
				
			||||||
		TokPos token.Pos   // position of Tok
 | 
					 | 
				
			||||||
		Tok    token.Token // INC or DEC
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// An AssignStmt node represents an assignment or
 | 
					 | 
				
			||||||
	// a short variable declaration.
 | 
					 | 
				
			||||||
	//
 | 
					 | 
				
			||||||
	AssignStmt struct {
 | 
					 | 
				
			||||||
		Lhs    []Expr
 | 
					 | 
				
			||||||
		TokPos token.Pos   // position of Tok
 | 
					 | 
				
			||||||
		Tok    token.Token // assignment token, DEFINE
 | 
					 | 
				
			||||||
		Rhs    []Expr
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// A GoStmt node represents a go statement.
 | 
					 | 
				
			||||||
	GoStmt struct {
 | 
					 | 
				
			||||||
		Go   token.Pos // position of "go" keyword
 | 
					 | 
				
			||||||
		Call *CallExpr
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// A DeferStmt node represents a defer statement.
 | 
					 | 
				
			||||||
	DeferStmt struct {
 | 
					 | 
				
			||||||
		Defer token.Pos // position of "defer" keyword
 | 
					 | 
				
			||||||
		Call  *CallExpr
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// A ReturnStmt node represents a return statement.
 | 
					 | 
				
			||||||
	ReturnStmt struct {
 | 
					 | 
				
			||||||
		Return  token.Pos // position of "return" keyword
 | 
					 | 
				
			||||||
		Results []Expr    // result expressions; or nil
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// A BranchStmt node represents a break, continue, goto,
 | 
					 | 
				
			||||||
	// or fallthrough statement.
 | 
					 | 
				
			||||||
	//
 | 
					 | 
				
			||||||
	BranchStmt struct {
 | 
					 | 
				
			||||||
		TokPos token.Pos   // position of Tok
 | 
					 | 
				
			||||||
		Tok    token.Token // keyword token (BREAK, CONTINUE, GOTO, FALLTHROUGH)
 | 
					 | 
				
			||||||
		Label  *Ident      // label name; or nil
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// A BlockStmt node represents a braced statement list.
 | 
					 | 
				
			||||||
	BlockStmt struct {
 | 
					 | 
				
			||||||
		Lbrace token.Pos // position of "{"
 | 
					 | 
				
			||||||
		List   []Stmt
 | 
					 | 
				
			||||||
		Rbrace token.Pos // position of "}"
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// An IfStmt node represents an if statement.
 | 
					 | 
				
			||||||
	IfStmt struct {
 | 
					 | 
				
			||||||
		If   token.Pos // position of "if" keyword
 | 
					 | 
				
			||||||
		Init Stmt      // initialization statement; or nil
 | 
					 | 
				
			||||||
		Cond Expr      // condition
 | 
					 | 
				
			||||||
		Body *BlockStmt
 | 
					 | 
				
			||||||
		Else Stmt // else branch; or nil
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// A CaseClause represents a case of an expression or type switch statement.
 | 
					 | 
				
			||||||
	CaseClause struct {
 | 
					 | 
				
			||||||
		Case  token.Pos // position of "case" or "default" keyword
 | 
					 | 
				
			||||||
		List  []Expr    // list of expressions or types; nil means default case
 | 
					 | 
				
			||||||
		Colon token.Pos // position of ":"
 | 
					 | 
				
			||||||
		Body  []Stmt    // statement list; or nil
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// A SwitchStmt node represents an expression switch statement.
 | 
					 | 
				
			||||||
	SwitchStmt struct {
 | 
					 | 
				
			||||||
		Switch token.Pos  // position of "switch" keyword
 | 
					 | 
				
			||||||
		Init   Stmt       // initialization statement; or nil
 | 
					 | 
				
			||||||
		Tag    Expr       // tag expression; or nil
 | 
					 | 
				
			||||||
		Body   *BlockStmt // CaseClauses only
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// An TypeSwitchStmt node represents a type switch statement.
 | 
					 | 
				
			||||||
	TypeSwitchStmt struct {
 | 
					 | 
				
			||||||
		Switch token.Pos  // position of "switch" keyword
 | 
					 | 
				
			||||||
		Init   Stmt       // initialization statement; or nil
 | 
					 | 
				
			||||||
		Assign Stmt       // x := y.(type) or y.(type)
 | 
					 | 
				
			||||||
		Body   *BlockStmt // CaseClauses only
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// A CommClause node represents a case of a select statement.
 | 
					 | 
				
			||||||
	CommClause struct {
 | 
					 | 
				
			||||||
		Case  token.Pos // position of "case" or "default" keyword
 | 
					 | 
				
			||||||
		Comm  Stmt      // send or receive statement; nil means default case
 | 
					 | 
				
			||||||
		Colon token.Pos // position of ":"
 | 
					 | 
				
			||||||
		Body  []Stmt    // statement list; or nil
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// An SelectStmt node represents a select statement.
 | 
					 | 
				
			||||||
	SelectStmt struct {
 | 
					 | 
				
			||||||
		Select token.Pos  // position of "select" keyword
 | 
					 | 
				
			||||||
		Body   *BlockStmt // CommClauses only
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// A ForStmt represents a for statement.
 | 
					 | 
				
			||||||
	ForStmt struct {
 | 
					 | 
				
			||||||
		For  token.Pos // position of "for" keyword
 | 
					 | 
				
			||||||
		Init Stmt      // initialization statement; or nil
 | 
					 | 
				
			||||||
		Cond Expr      // condition; or nil
 | 
					 | 
				
			||||||
		Post Stmt      // post iteration statement; or nil
 | 
					 | 
				
			||||||
		Body *BlockStmt
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// A RangeStmt represents a for statement with a range clause.
 | 
					 | 
				
			||||||
	RangeStmt struct {
 | 
					 | 
				
			||||||
		For        token.Pos   // position of "for" keyword
 | 
					 | 
				
			||||||
		Key, Value Expr        // Key, Value may be nil
 | 
					 | 
				
			||||||
		TokPos     token.Pos   // position of Tok; invalid if Key == nil
 | 
					 | 
				
			||||||
		Tok        token.Token // ILLEGAL if Key == nil, ASSIGN, DEFINE
 | 
					 | 
				
			||||||
		X          Expr        // value to range over
 | 
					 | 
				
			||||||
		Body       *BlockStmt
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// Pos and End implementations for statement nodes.
 | 
					 | 
				
			||||||
//
 | 
					 | 
				
			||||||
func (s *BadStmt) Pos() token.Pos        { return s.From }
 | 
					 | 
				
			||||||
func (s *DeclStmt) Pos() token.Pos       { return s.Decl.Pos() }
 | 
					 | 
				
			||||||
func (s *EmptyStmt) Pos() token.Pos      { return s.Semicolon }
 | 
					 | 
				
			||||||
func (s *LabeledStmt) Pos() token.Pos    { return s.Label.Pos() }
 | 
					 | 
				
			||||||
func (s *ExprStmt) Pos() token.Pos       { return s.X.Pos() }
 | 
					 | 
				
			||||||
func (s *SendStmt) Pos() token.Pos       { return s.Chan.Pos() }
 | 
					 | 
				
			||||||
func (s *IncDecStmt) Pos() token.Pos     { return s.X.Pos() }
 | 
					 | 
				
			||||||
func (s *AssignStmt) Pos() token.Pos     { return s.Lhs[0].Pos() }
 | 
					 | 
				
			||||||
func (s *GoStmt) Pos() token.Pos         { return s.Go }
 | 
					 | 
				
			||||||
func (s *DeferStmt) Pos() token.Pos      { return s.Defer }
 | 
					 | 
				
			||||||
func (s *ReturnStmt) Pos() token.Pos     { return s.Return }
 | 
					 | 
				
			||||||
func (s *BranchStmt) Pos() token.Pos     { return s.TokPos }
 | 
					 | 
				
			||||||
func (s *BlockStmt) Pos() token.Pos      { return s.Lbrace }
 | 
					 | 
				
			||||||
func (s *IfStmt) Pos() token.Pos         { return s.If }
 | 
					 | 
				
			||||||
func (s *CaseClause) Pos() token.Pos     { return s.Case }
 | 
					 | 
				
			||||||
func (s *SwitchStmt) Pos() token.Pos     { return s.Switch }
 | 
					 | 
				
			||||||
func (s *TypeSwitchStmt) Pos() token.Pos { return s.Switch }
 | 
					 | 
				
			||||||
func (s *CommClause) Pos() token.Pos     { return s.Case }
 | 
					 | 
				
			||||||
func (s *SelectStmt) Pos() token.Pos     { return s.Select }
 | 
					 | 
				
			||||||
func (s *ForStmt) Pos() token.Pos        { return s.For }
 | 
					 | 
				
			||||||
func (s *RangeStmt) Pos() token.Pos      { return s.For }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (s *BadStmt) End() token.Pos  { return s.To }
 | 
					 | 
				
			||||||
func (s *DeclStmt) End() token.Pos { return s.Decl.End() }
 | 
					 | 
				
			||||||
func (s *EmptyStmt) End() token.Pos {
 | 
					 | 
				
			||||||
	if s.Implicit {
 | 
					 | 
				
			||||||
		return s.Semicolon
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return s.Semicolon + 1 /* len(";") */
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
func (s *LabeledStmt) End() token.Pos { return s.Stmt.End() }
 | 
					 | 
				
			||||||
func (s *ExprStmt) End() token.Pos    { return s.X.End() }
 | 
					 | 
				
			||||||
func (s *SendStmt) End() token.Pos    { return s.Value.End() }
 | 
					 | 
				
			||||||
func (s *IncDecStmt) End() token.Pos {
 | 
					 | 
				
			||||||
	return s.TokPos + 2 /* len("++") */
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
func (s *AssignStmt) End() token.Pos { return s.Rhs[len(s.Rhs)-1].End() }
 | 
					 | 
				
			||||||
func (s *GoStmt) End() token.Pos     { return s.Call.End() }
 | 
					 | 
				
			||||||
func (s *DeferStmt) End() token.Pos  { return s.Call.End() }
 | 
					 | 
				
			||||||
func (s *ReturnStmt) End() token.Pos {
 | 
					 | 
				
			||||||
	if n := len(s.Results); n > 0 {
 | 
					 | 
				
			||||||
		return s.Results[n-1].End()
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return s.Return + 6 // len("return")
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
func (s *BranchStmt) End() token.Pos {
 | 
					 | 
				
			||||||
	if s.Label != nil {
 | 
					 | 
				
			||||||
		return s.Label.End()
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return token.Pos(int(s.TokPos) + len(s.Tok.String()))
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
func (s *BlockStmt) End() token.Pos { return s.Rbrace + 1 }
 | 
					 | 
				
			||||||
func (s *IfStmt) End() token.Pos {
 | 
					 | 
				
			||||||
	if s.Else != nil {
 | 
					 | 
				
			||||||
		return s.Else.End()
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return s.Body.End()
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
func (s *CaseClause) End() token.Pos {
 | 
					 | 
				
			||||||
	if n := len(s.Body); n > 0 {
 | 
					 | 
				
			||||||
		return s.Body[n-1].End()
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return s.Colon + 1
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
func (s *SwitchStmt) End() token.Pos     { return s.Body.End() }
 | 
					 | 
				
			||||||
func (s *TypeSwitchStmt) End() token.Pos { return s.Body.End() }
 | 
					 | 
				
			||||||
func (s *CommClause) End() token.Pos {
 | 
					 | 
				
			||||||
	if n := len(s.Body); n > 0 {
 | 
					 | 
				
			||||||
		return s.Body[n-1].End()
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return s.Colon + 1
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
func (s *SelectStmt) End() token.Pos { return s.Body.End() }
 | 
					 | 
				
			||||||
func (s *ForStmt) End() token.Pos    { return s.Body.End() }
 | 
					 | 
				
			||||||
func (s *RangeStmt) End() token.Pos  { return s.Body.End() }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// stmtNode() ensures that only statement nodes can be
 | 
					 | 
				
			||||||
// assigned to a Stmt.
 | 
					 | 
				
			||||||
//
 | 
					 | 
				
			||||||
func (*BadStmt) stmtNode()        {}
 | 
					 | 
				
			||||||
func (*DeclStmt) stmtNode()       {}
 | 
					 | 
				
			||||||
func (*EmptyStmt) stmtNode()      {}
 | 
					 | 
				
			||||||
func (*LabeledStmt) stmtNode()    {}
 | 
					 | 
				
			||||||
func (*ExprStmt) stmtNode()       {}
 | 
					 | 
				
			||||||
func (*SendStmt) stmtNode()       {}
 | 
					 | 
				
			||||||
func (*IncDecStmt) stmtNode()     {}
 | 
					 | 
				
			||||||
func (*AssignStmt) stmtNode()     {}
 | 
					 | 
				
			||||||
func (*GoStmt) stmtNode()         {}
 | 
					 | 
				
			||||||
func (*DeferStmt) stmtNode()      {}
 | 
					 | 
				
			||||||
func (*ReturnStmt) stmtNode()     {}
 | 
					 | 
				
			||||||
func (*BranchStmt) stmtNode()     {}
 | 
					 | 
				
			||||||
func (*BlockStmt) stmtNode()      {}
 | 
					 | 
				
			||||||
func (*IfStmt) stmtNode()         {}
 | 
					 | 
				
			||||||
func (*CaseClause) stmtNode()     {}
 | 
					 | 
				
			||||||
func (*SwitchStmt) stmtNode()     {}
 | 
					 | 
				
			||||||
func (*TypeSwitchStmt) stmtNode() {}
 | 
					 | 
				
			||||||
func (*CommClause) stmtNode()     {}
 | 
					 | 
				
			||||||
func (*SelectStmt) stmtNode()     {}
 | 
					 | 
				
			||||||
func (*ForStmt) stmtNode()        {}
 | 
					 | 
				
			||||||
func (*RangeStmt) stmtNode()      {}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// ----------------------------------------------------------------------------
 | 
					 | 
				
			||||||
// Declarations
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// A Spec node represents a single (non-parenthesized) import,
 | 
					 | 
				
			||||||
// constant, type, or variable declaration.
 | 
					 | 
				
			||||||
//
 | 
					 | 
				
			||||||
type (
 | 
					 | 
				
			||||||
	// The Spec type stands for any of *ImportSpec, *ValueSpec, and *TypeSpec.
 | 
					 | 
				
			||||||
	Spec interface {
 | 
					 | 
				
			||||||
		Node
 | 
					 | 
				
			||||||
		specNode()
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// An ImportSpec node represents a single package import.
 | 
					 | 
				
			||||||
	ImportSpec struct {
 | 
					 | 
				
			||||||
		Doc     *CommentGroup // associated documentation; or nil
 | 
					 | 
				
			||||||
		Name    *Ident        // local package name (including "."); or nil
 | 
					 | 
				
			||||||
		Path    *BasicLit     // import path
 | 
					 | 
				
			||||||
		Comment *CommentGroup // line comments; or nil
 | 
					 | 
				
			||||||
		EndPos  token.Pos     // end of spec (overrides Path.Pos if nonzero)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// A ValueSpec node represents a constant or variable declaration
 | 
					 | 
				
			||||||
	// (ConstSpec or VarSpec production).
 | 
					 | 
				
			||||||
	//
 | 
					 | 
				
			||||||
	ValueSpec struct {
 | 
					 | 
				
			||||||
		Doc     *CommentGroup // associated documentation; or nil
 | 
					 | 
				
			||||||
		Names   []*Ident      // value names (len(Names) > 0)
 | 
					 | 
				
			||||||
		Type    Expr          // value type; or nil
 | 
					 | 
				
			||||||
		Values  []Expr        // initial values; or nil
 | 
					 | 
				
			||||||
		Comment *CommentGroup // line comments; or nil
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// A TypeSpec node represents a type declaration (TypeSpec production).
 | 
					 | 
				
			||||||
	TypeSpec struct {
 | 
					 | 
				
			||||||
		Doc     *CommentGroup // associated documentation; or nil
 | 
					 | 
				
			||||||
		Name    *Ident        // type name
 | 
					 | 
				
			||||||
		Type    Expr          // *Ident, *ParenExpr, *SelectorExpr, *StarExpr, or any of the *XxxTypes
 | 
					 | 
				
			||||||
		Comment *CommentGroup // line comments; or nil
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// Pos and End implementations for spec nodes.
 | 
					 | 
				
			||||||
//
 | 
					 | 
				
			||||||
func (s *ImportSpec) Pos() token.Pos {
 | 
					 | 
				
			||||||
	if s.Name != nil {
 | 
					 | 
				
			||||||
		return s.Name.Pos()
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return s.Path.Pos()
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
func (s *ValueSpec) Pos() token.Pos { return s.Names[0].Pos() }
 | 
					 | 
				
			||||||
func (s *TypeSpec) Pos() token.Pos  { return s.Name.Pos() }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (s *ImportSpec) End() token.Pos {
 | 
					 | 
				
			||||||
	if s.EndPos != 0 {
 | 
					 | 
				
			||||||
		return s.EndPos
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return s.Path.End()
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (s *ValueSpec) End() token.Pos {
 | 
					 | 
				
			||||||
	if n := len(s.Values); n > 0 {
 | 
					 | 
				
			||||||
		return s.Values[n-1].End()
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	if s.Type != nil {
 | 
					 | 
				
			||||||
		return s.Type.End()
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return s.Names[len(s.Names)-1].End()
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
func (s *TypeSpec) End() token.Pos { return s.Type.End() }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// specNode() ensures that only spec nodes can be
 | 
					 | 
				
			||||||
// assigned to a Spec.
 | 
					 | 
				
			||||||
//
 | 
					 | 
				
			||||||
func (*ImportSpec) specNode() {}
 | 
					 | 
				
			||||||
func (*ValueSpec) specNode()  {}
 | 
					 | 
				
			||||||
func (*TypeSpec) specNode()   {}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// A declaration is represented by one of the following declaration nodes.
 | 
					 | 
				
			||||||
//
 | 
					 | 
				
			||||||
type (
 | 
					 | 
				
			||||||
	// A BadDecl node is a placeholder for declarations containing
 | 
					 | 
				
			||||||
	// syntax errors for which no correct declaration nodes can be
 | 
					 | 
				
			||||||
	// created.
 | 
					 | 
				
			||||||
	//
 | 
					 | 
				
			||||||
	BadDecl struct {
 | 
					 | 
				
			||||||
		From, To token.Pos // position range of bad declaration
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// A GenDecl node (generic declaration node) represents an import,
 | 
					 | 
				
			||||||
	// constant, type or variable declaration. A valid Lparen position
 | 
					 | 
				
			||||||
	// (Lparen.Line > 0) indicates a parenthesized declaration.
 | 
					 | 
				
			||||||
	//
 | 
					 | 
				
			||||||
	// Relationship between Tok value and Specs element type:
 | 
					 | 
				
			||||||
	//
 | 
					 | 
				
			||||||
	//	token.IMPORT  *ImportSpec
 | 
					 | 
				
			||||||
	//	token.CONST   *ValueSpec
 | 
					 | 
				
			||||||
	//	token.TYPE    *TypeSpec
 | 
					 | 
				
			||||||
	//	token.VAR     *ValueSpec
 | 
					 | 
				
			||||||
	//
 | 
					 | 
				
			||||||
	GenDecl struct {
 | 
					 | 
				
			||||||
		Doc    *CommentGroup // associated documentation; or nil
 | 
					 | 
				
			||||||
		TokPos token.Pos     // position of Tok
 | 
					 | 
				
			||||||
		Tok    token.Token   // IMPORT, CONST, TYPE, VAR
 | 
					 | 
				
			||||||
		Lparen token.Pos     // position of '(', if any
 | 
					 | 
				
			||||||
		Specs  []Spec
 | 
					 | 
				
			||||||
		Rparen token.Pos // position of ')', if any
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// A FuncDecl node represents a function declaration.
 | 
					 | 
				
			||||||
	FuncDecl struct {
 | 
					 | 
				
			||||||
		Doc  *CommentGroup // associated documentation; or nil
 | 
					 | 
				
			||||||
		Recv *FieldList    // receiver (methods); or nil (functions)
 | 
					 | 
				
			||||||
		Name *Ident        // function/method name
 | 
					 | 
				
			||||||
		Type *FuncType     // function signature: parameters, results, and position of "func" keyword
 | 
					 | 
				
			||||||
		Body *BlockStmt    // function body; or nil (forward declaration)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// Pos and End implementations for declaration nodes.
 | 
					 | 
				
			||||||
//
 | 
					 | 
				
			||||||
func (d *BadDecl) Pos() token.Pos  { return d.From }
 | 
					 | 
				
			||||||
func (d *GenDecl) Pos() token.Pos  { return d.TokPos }
 | 
					 | 
				
			||||||
func (d *FuncDecl) Pos() token.Pos { return d.Type.Pos() }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (d *BadDecl) End() token.Pos { return d.To }
 | 
					 | 
				
			||||||
func (d *GenDecl) End() token.Pos {
 | 
					 | 
				
			||||||
	if d.Rparen.IsValid() {
 | 
					 | 
				
			||||||
		return d.Rparen + 1
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return d.Specs[0].End()
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
func (d *FuncDecl) End() token.Pos {
 | 
					 | 
				
			||||||
	if d.Body != nil {
 | 
					 | 
				
			||||||
		return d.Body.End()
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return d.Type.End()
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// declNode() ensures that only declaration nodes can be
 | 
					 | 
				
			||||||
// assigned to a Decl.
 | 
					 | 
				
			||||||
//
 | 
					 | 
				
			||||||
func (*BadDecl) declNode()  {}
 | 
					 | 
				
			||||||
func (*GenDecl) declNode()  {}
 | 
					 | 
				
			||||||
func (*FuncDecl) declNode() {}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// ----------------------------------------------------------------------------
 | 
					 | 
				
			||||||
// Files and packages
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// A File node represents a Go source file.
 | 
					 | 
				
			||||||
//
 | 
					 | 
				
			||||||
// The Comments list contains all comments in the source file in order of
 | 
					 | 
				
			||||||
// appearance, including the comments that are pointed to from other nodes
 | 
					 | 
				
			||||||
// via Doc and Comment fields.
 | 
					 | 
				
			||||||
//
 | 
					 | 
				
			||||||
type File struct {
 | 
					 | 
				
			||||||
	Doc        *CommentGroup   // associated documentation; or nil
 | 
					 | 
				
			||||||
	Package    token.Pos       // position of "package" keyword
 | 
					 | 
				
			||||||
	Name       *Ident          // package name
 | 
					 | 
				
			||||||
	Decls      []Decl          // top-level declarations; or nil
 | 
					 | 
				
			||||||
	Scope      *Scope          // package scope (this file only)
 | 
					 | 
				
			||||||
	Imports    []*ImportSpec   // imports in this file
 | 
					 | 
				
			||||||
	Unresolved []*Ident        // unresolved identifiers in this file
 | 
					 | 
				
			||||||
	Comments   []*CommentGroup // list of all comments in the source file
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (f *File) Pos() token.Pos { return f.Package }
 | 
					 | 
				
			||||||
func (f *File) End() token.Pos {
 | 
					 | 
				
			||||||
	if n := len(f.Decls); n > 0 {
 | 
					 | 
				
			||||||
		return f.Decls[n-1].End()
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return f.Name.End()
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// A Package node represents a set of source files
 | 
					 | 
				
			||||||
// collectively building a Go package.
 | 
					 | 
				
			||||||
//
 | 
					 | 
				
			||||||
type Package struct {
 | 
					 | 
				
			||||||
	Name    string             // package name
 | 
					 | 
				
			||||||
	Scope   *Scope             // package scope across all files
 | 
					 | 
				
			||||||
	Imports map[string]*Object // map of package id -> package object
 | 
					 | 
				
			||||||
	Files   map[string]*File   // Go source files by filename
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (p *Package) Pos() token.Pos { return token.NoPos }
 | 
					 | 
				
			||||||
func (p *Package) End() token.Pos { return token.NoPos }
 | 
					 | 
				
			||||||
							
								
								
									
										50
									
								
								third_party/golang/go/ast/ast_test.go
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										50
									
								
								third_party/golang/go/ast/ast_test.go
									
									
									
									
										vendored
									
									
								
							@@ -1,50 +0,0 @@
 | 
				
			|||||||
// Copyright 2012 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 ast
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
import (
 | 
					 | 
				
			||||||
	"testing"
 | 
					 | 
				
			||||||
)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
var comments = []struct {
 | 
					 | 
				
			||||||
	list []string
 | 
					 | 
				
			||||||
	text string
 | 
					 | 
				
			||||||
}{
 | 
					 | 
				
			||||||
	{[]string{"//"}, ""},
 | 
					 | 
				
			||||||
	{[]string{"//   "}, ""},
 | 
					 | 
				
			||||||
	{[]string{"//", "//", "//   "}, ""},
 | 
					 | 
				
			||||||
	{[]string{"// foo   "}, "foo\n"},
 | 
					 | 
				
			||||||
	{[]string{"//", "//", "// foo"}, "foo\n"},
 | 
					 | 
				
			||||||
	{[]string{"// foo  bar  "}, "foo  bar\n"},
 | 
					 | 
				
			||||||
	{[]string{"// foo", "// bar"}, "foo\nbar\n"},
 | 
					 | 
				
			||||||
	{[]string{"// foo", "//", "//", "//", "// bar"}, "foo\n\nbar\n"},
 | 
					 | 
				
			||||||
	{[]string{"// foo", "/* bar */"}, "foo\n bar\n"},
 | 
					 | 
				
			||||||
	{[]string{"//", "//", "//", "// foo", "//", "//", "//"}, "foo\n"},
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	{[]string{"/**/"}, ""},
 | 
					 | 
				
			||||||
	{[]string{"/*   */"}, ""},
 | 
					 | 
				
			||||||
	{[]string{"/**/", "/**/", "/*   */"}, ""},
 | 
					 | 
				
			||||||
	{[]string{"/* Foo   */"}, " Foo\n"},
 | 
					 | 
				
			||||||
	{[]string{"/* Foo  Bar  */"}, " Foo  Bar\n"},
 | 
					 | 
				
			||||||
	{[]string{"/* Foo*/", "/* Bar*/"}, " Foo\n Bar\n"},
 | 
					 | 
				
			||||||
	{[]string{"/* Foo*/", "/**/", "/**/", "/**/", "// Bar"}, " Foo\n\nBar\n"},
 | 
					 | 
				
			||||||
	{[]string{"/* Foo*/", "/*\n*/", "//", "/*\n*/", "// Bar"}, " Foo\n\nBar\n"},
 | 
					 | 
				
			||||||
	{[]string{"/* Foo*/", "// Bar"}, " Foo\nBar\n"},
 | 
					 | 
				
			||||||
	{[]string{"/* Foo\n Bar*/"}, " Foo\n Bar\n"},
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func TestCommentText(t *testing.T) {
 | 
					 | 
				
			||||||
	for i, c := range comments {
 | 
					 | 
				
			||||||
		list := make([]*Comment, len(c.list))
 | 
					 | 
				
			||||||
		for i, s := range c.list {
 | 
					 | 
				
			||||||
			list[i] = &Comment{Text: s}
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		text := (&CommentGroup{list}).Text()
 | 
					 | 
				
			||||||
		if text != c.text {
 | 
					 | 
				
			||||||
			t.Errorf("case %d: got %q; expected %q", i, text, c.text)
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
							
								
								
									
										332
									
								
								third_party/golang/go/ast/commentmap.go
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										332
									
								
								third_party/golang/go/ast/commentmap.go
									
									
									
									
										vendored
									
									
								
							@@ -1,332 +0,0 @@
 | 
				
			|||||||
// Copyright 2012 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 ast
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
import (
 | 
					 | 
				
			||||||
	"bytes"
 | 
					 | 
				
			||||||
	"fmt"
 | 
					 | 
				
			||||||
	"k8s.io/kubernetes/third_party/golang/go/token"
 | 
					 | 
				
			||||||
	"sort"
 | 
					 | 
				
			||||||
)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
type byPos []*CommentGroup
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (a byPos) Len() int           { return len(a) }
 | 
					 | 
				
			||||||
func (a byPos) Less(i, j int) bool { return a[i].Pos() < a[j].Pos() }
 | 
					 | 
				
			||||||
func (a byPos) Swap(i, j int)      { a[i], a[j] = a[j], a[i] }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// sortComments sorts the list of comment groups in source order.
 | 
					 | 
				
			||||||
//
 | 
					 | 
				
			||||||
func sortComments(list []*CommentGroup) {
 | 
					 | 
				
			||||||
	// TODO(gri): Does it make sense to check for sorted-ness
 | 
					 | 
				
			||||||
	//            first (because we know that sorted-ness is
 | 
					 | 
				
			||||||
	//            very likely)?
 | 
					 | 
				
			||||||
	if orderedList := byPos(list); !sort.IsSorted(orderedList) {
 | 
					 | 
				
			||||||
		sort.Sort(orderedList)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// A CommentMap maps an AST node to a list of comment groups
 | 
					 | 
				
			||||||
// associated with it. See NewCommentMap for a description of
 | 
					 | 
				
			||||||
// the association.
 | 
					 | 
				
			||||||
//
 | 
					 | 
				
			||||||
type CommentMap map[Node][]*CommentGroup
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (cmap CommentMap) addComment(n Node, c *CommentGroup) {
 | 
					 | 
				
			||||||
	list := cmap[n]
 | 
					 | 
				
			||||||
	if len(list) == 0 {
 | 
					 | 
				
			||||||
		list = []*CommentGroup{c}
 | 
					 | 
				
			||||||
	} else {
 | 
					 | 
				
			||||||
		list = append(list, c)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	cmap[n] = list
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
type byInterval []Node
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (a byInterval) Len() int { return len(a) }
 | 
					 | 
				
			||||||
func (a byInterval) Less(i, j int) bool {
 | 
					 | 
				
			||||||
	pi, pj := a[i].Pos(), a[j].Pos()
 | 
					 | 
				
			||||||
	return pi < pj || pi == pj && a[i].End() > a[j].End()
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
func (a byInterval) Swap(i, j int) { a[i], a[j] = a[j], a[i] }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// nodeList returns the list of nodes of the AST n in source order.
 | 
					 | 
				
			||||||
//
 | 
					 | 
				
			||||||
func nodeList(n Node) []Node {
 | 
					 | 
				
			||||||
	var list []Node
 | 
					 | 
				
			||||||
	Inspect(n, func(n Node) bool {
 | 
					 | 
				
			||||||
		// don't collect comments
 | 
					 | 
				
			||||||
		switch n.(type) {
 | 
					 | 
				
			||||||
		case nil, *CommentGroup, *Comment:
 | 
					 | 
				
			||||||
			return false
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		list = append(list, n)
 | 
					 | 
				
			||||||
		return true
 | 
					 | 
				
			||||||
	})
 | 
					 | 
				
			||||||
	// Note: The current implementation assumes that Inspect traverses the
 | 
					 | 
				
			||||||
	//       AST in depth-first and thus _source_ order. If AST traversal
 | 
					 | 
				
			||||||
	//       does not follow source order, the sorting call below will be
 | 
					 | 
				
			||||||
	//       required.
 | 
					 | 
				
			||||||
	// sort.Sort(byInterval(list))
 | 
					 | 
				
			||||||
	return list
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// A commentListReader helps iterating through a list of comment groups.
 | 
					 | 
				
			||||||
//
 | 
					 | 
				
			||||||
type commentListReader struct {
 | 
					 | 
				
			||||||
	fset     *token.FileSet
 | 
					 | 
				
			||||||
	list     []*CommentGroup
 | 
					 | 
				
			||||||
	index    int
 | 
					 | 
				
			||||||
	comment  *CommentGroup  // comment group at current index
 | 
					 | 
				
			||||||
	pos, end token.Position // source interval of comment group at current index
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (r *commentListReader) eol() bool {
 | 
					 | 
				
			||||||
	return r.index >= len(r.list)
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (r *commentListReader) next() {
 | 
					 | 
				
			||||||
	if !r.eol() {
 | 
					 | 
				
			||||||
		r.comment = r.list[r.index]
 | 
					 | 
				
			||||||
		r.pos = r.fset.Position(r.comment.Pos())
 | 
					 | 
				
			||||||
		r.end = r.fset.Position(r.comment.End())
 | 
					 | 
				
			||||||
		r.index++
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// A nodeStack keeps track of nested nodes.
 | 
					 | 
				
			||||||
// A node lower on the stack lexically contains the nodes higher on the stack.
 | 
					 | 
				
			||||||
//
 | 
					 | 
				
			||||||
type nodeStack []Node
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// push pops all nodes that appear lexically before n
 | 
					 | 
				
			||||||
// and then pushes n on the stack.
 | 
					 | 
				
			||||||
//
 | 
					 | 
				
			||||||
func (s *nodeStack) push(n Node) {
 | 
					 | 
				
			||||||
	s.pop(n.Pos())
 | 
					 | 
				
			||||||
	*s = append((*s), n)
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// pop pops all nodes that appear lexically before pos
 | 
					 | 
				
			||||||
// (i.e., whose lexical extent has ended before or at pos).
 | 
					 | 
				
			||||||
// It returns the last node popped.
 | 
					 | 
				
			||||||
//
 | 
					 | 
				
			||||||
func (s *nodeStack) pop(pos token.Pos) (top Node) {
 | 
					 | 
				
			||||||
	i := len(*s)
 | 
					 | 
				
			||||||
	for i > 0 && (*s)[i-1].End() <= pos {
 | 
					 | 
				
			||||||
		top = (*s)[i-1]
 | 
					 | 
				
			||||||
		i--
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	*s = (*s)[0:i]
 | 
					 | 
				
			||||||
	return top
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// NewCommentMap creates a new comment map by associating comment groups
 | 
					 | 
				
			||||||
// of the comments list with the nodes of the AST specified by node.
 | 
					 | 
				
			||||||
//
 | 
					 | 
				
			||||||
// A comment group g is associated with a node n if:
 | 
					 | 
				
			||||||
//
 | 
					 | 
				
			||||||
//   - g starts on the same line as n ends
 | 
					 | 
				
			||||||
//   - g starts on the line immediately following n, and there is
 | 
					 | 
				
			||||||
//     at least one empty line after g and before the next node
 | 
					 | 
				
			||||||
//   - g starts before n and is not associated to the node before n
 | 
					 | 
				
			||||||
//     via the previous rules
 | 
					 | 
				
			||||||
//
 | 
					 | 
				
			||||||
// NewCommentMap tries to associate a comment group to the "largest"
 | 
					 | 
				
			||||||
// node possible: For instance, if the comment is a line comment
 | 
					 | 
				
			||||||
// trailing an assignment, the comment is associated with the entire
 | 
					 | 
				
			||||||
// assignment rather than just the last operand in the assignment.
 | 
					 | 
				
			||||||
//
 | 
					 | 
				
			||||||
func NewCommentMap(fset *token.FileSet, node Node, comments []*CommentGroup) CommentMap {
 | 
					 | 
				
			||||||
	if len(comments) == 0 {
 | 
					 | 
				
			||||||
		return nil // no comments to map
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	cmap := make(CommentMap)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// set up comment reader r
 | 
					 | 
				
			||||||
	tmp := make([]*CommentGroup, len(comments))
 | 
					 | 
				
			||||||
	copy(tmp, comments) // don't change incoming comments
 | 
					 | 
				
			||||||
	sortComments(tmp)
 | 
					 | 
				
			||||||
	r := commentListReader{fset: fset, list: tmp} // !r.eol() because len(comments) > 0
 | 
					 | 
				
			||||||
	r.next()
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// create node list in lexical order
 | 
					 | 
				
			||||||
	nodes := nodeList(node)
 | 
					 | 
				
			||||||
	nodes = append(nodes, nil) // append sentinel
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// set up iteration variables
 | 
					 | 
				
			||||||
	var (
 | 
					 | 
				
			||||||
		p     Node           // previous node
 | 
					 | 
				
			||||||
		pend  token.Position // end of p
 | 
					 | 
				
			||||||
		pg    Node           // previous node group (enclosing nodes of "importance")
 | 
					 | 
				
			||||||
		pgend token.Position // end of pg
 | 
					 | 
				
			||||||
		stack nodeStack      // stack of node groups
 | 
					 | 
				
			||||||
	)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	for _, q := range nodes {
 | 
					 | 
				
			||||||
		var qpos token.Position
 | 
					 | 
				
			||||||
		if q != nil {
 | 
					 | 
				
			||||||
			qpos = fset.Position(q.Pos()) // current node position
 | 
					 | 
				
			||||||
		} else {
 | 
					 | 
				
			||||||
			// set fake sentinel position to infinity so that
 | 
					 | 
				
			||||||
			// all comments get processed before the sentinel
 | 
					 | 
				
			||||||
			const infinity = 1 << 30
 | 
					 | 
				
			||||||
			qpos.Offset = infinity
 | 
					 | 
				
			||||||
			qpos.Line = infinity
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		// process comments before current node
 | 
					 | 
				
			||||||
		for r.end.Offset <= qpos.Offset {
 | 
					 | 
				
			||||||
			// determine recent node group
 | 
					 | 
				
			||||||
			if top := stack.pop(r.comment.Pos()); top != nil {
 | 
					 | 
				
			||||||
				pg = top
 | 
					 | 
				
			||||||
				pgend = fset.Position(pg.End())
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
			// Try to associate a comment first with a node group
 | 
					 | 
				
			||||||
			// (i.e., a node of "importance" such as a declaration);
 | 
					 | 
				
			||||||
			// if that fails, try to associate it with the most recent
 | 
					 | 
				
			||||||
			// node.
 | 
					 | 
				
			||||||
			// TODO(gri) try to simplify the logic below
 | 
					 | 
				
			||||||
			var assoc Node
 | 
					 | 
				
			||||||
			switch {
 | 
					 | 
				
			||||||
			case pg != nil &&
 | 
					 | 
				
			||||||
				(pgend.Line == r.pos.Line ||
 | 
					 | 
				
			||||||
					pgend.Line+1 == r.pos.Line && r.end.Line+1 < qpos.Line):
 | 
					 | 
				
			||||||
				// 1) comment starts on same line as previous node group ends, or
 | 
					 | 
				
			||||||
				// 2) comment starts on the line immediately after the
 | 
					 | 
				
			||||||
				//    previous node group and there is an empty line before
 | 
					 | 
				
			||||||
				//    the current node
 | 
					 | 
				
			||||||
				// => associate comment with previous node group
 | 
					 | 
				
			||||||
				assoc = pg
 | 
					 | 
				
			||||||
			case p != nil &&
 | 
					 | 
				
			||||||
				(pend.Line == r.pos.Line ||
 | 
					 | 
				
			||||||
					pend.Line+1 == r.pos.Line && r.end.Line+1 < qpos.Line ||
 | 
					 | 
				
			||||||
					q == nil):
 | 
					 | 
				
			||||||
				// same rules apply as above for p rather than pg,
 | 
					 | 
				
			||||||
				// but also associate with p if we are at the end (q == nil)
 | 
					 | 
				
			||||||
				assoc = p
 | 
					 | 
				
			||||||
			default:
 | 
					 | 
				
			||||||
				// otherwise, associate comment with current node
 | 
					 | 
				
			||||||
				if q == nil {
 | 
					 | 
				
			||||||
					// we can only reach here if there was no p
 | 
					 | 
				
			||||||
					// which would imply that there were no nodes
 | 
					 | 
				
			||||||
					panic("internal error: no comments should be associated with sentinel")
 | 
					 | 
				
			||||||
				}
 | 
					 | 
				
			||||||
				assoc = q
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
			cmap.addComment(assoc, r.comment)
 | 
					 | 
				
			||||||
			if r.eol() {
 | 
					 | 
				
			||||||
				return cmap
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
			r.next()
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		// update previous node
 | 
					 | 
				
			||||||
		p = q
 | 
					 | 
				
			||||||
		pend = fset.Position(p.End())
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		// update previous node group if we see an "important" node
 | 
					 | 
				
			||||||
		switch q.(type) {
 | 
					 | 
				
			||||||
		case *File, *Field, Decl, Spec, Stmt:
 | 
					 | 
				
			||||||
			stack.push(q)
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return cmap
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// Update replaces an old node in the comment map with the new node
 | 
					 | 
				
			||||||
// and returns the new node. Comments that were associated with the
 | 
					 | 
				
			||||||
// old node are associated with the new node.
 | 
					 | 
				
			||||||
//
 | 
					 | 
				
			||||||
func (cmap CommentMap) Update(old, new Node) Node {
 | 
					 | 
				
			||||||
	if list := cmap[old]; len(list) > 0 {
 | 
					 | 
				
			||||||
		delete(cmap, old)
 | 
					 | 
				
			||||||
		cmap[new] = append(cmap[new], list...)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return new
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// Filter returns a new comment map consisting of only those
 | 
					 | 
				
			||||||
// entries of cmap for which a corresponding node exists in
 | 
					 | 
				
			||||||
// the AST specified by node.
 | 
					 | 
				
			||||||
//
 | 
					 | 
				
			||||||
func (cmap CommentMap) Filter(node Node) CommentMap {
 | 
					 | 
				
			||||||
	umap := make(CommentMap)
 | 
					 | 
				
			||||||
	Inspect(node, func(n Node) bool {
 | 
					 | 
				
			||||||
		if g := cmap[n]; len(g) > 0 {
 | 
					 | 
				
			||||||
			umap[n] = g
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		return true
 | 
					 | 
				
			||||||
	})
 | 
					 | 
				
			||||||
	return umap
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// Comments returns the list of comment groups in the comment map.
 | 
					 | 
				
			||||||
// The result is sorted is source order.
 | 
					 | 
				
			||||||
//
 | 
					 | 
				
			||||||
func (cmap CommentMap) Comments() []*CommentGroup {
 | 
					 | 
				
			||||||
	list := make([]*CommentGroup, 0, len(cmap))
 | 
					 | 
				
			||||||
	for _, e := range cmap {
 | 
					 | 
				
			||||||
		list = append(list, e...)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	sortComments(list)
 | 
					 | 
				
			||||||
	return list
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func summary(list []*CommentGroup) string {
 | 
					 | 
				
			||||||
	const maxLen = 40
 | 
					 | 
				
			||||||
	var buf bytes.Buffer
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// collect comments text
 | 
					 | 
				
			||||||
loop:
 | 
					 | 
				
			||||||
	for _, group := range list {
 | 
					 | 
				
			||||||
		// Note: CommentGroup.Text() does too much work for what we
 | 
					 | 
				
			||||||
		//       need and would only replace this innermost loop.
 | 
					 | 
				
			||||||
		//       Just do it explicitly.
 | 
					 | 
				
			||||||
		for _, comment := range group.List {
 | 
					 | 
				
			||||||
			if buf.Len() >= maxLen {
 | 
					 | 
				
			||||||
				break loop
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
			buf.WriteString(comment.Text)
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// truncate if too long
 | 
					 | 
				
			||||||
	if buf.Len() > maxLen {
 | 
					 | 
				
			||||||
		buf.Truncate(maxLen - 3)
 | 
					 | 
				
			||||||
		buf.WriteString("...")
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// replace any invisibles with blanks
 | 
					 | 
				
			||||||
	bytes := buf.Bytes()
 | 
					 | 
				
			||||||
	for i, b := range bytes {
 | 
					 | 
				
			||||||
		switch b {
 | 
					 | 
				
			||||||
		case '\t', '\n', '\r':
 | 
					 | 
				
			||||||
			bytes[i] = ' '
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return string(bytes)
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (cmap CommentMap) String() string {
 | 
					 | 
				
			||||||
	var buf bytes.Buffer
 | 
					 | 
				
			||||||
	fmt.Fprintln(&buf, "CommentMap {")
 | 
					 | 
				
			||||||
	for node, comment := range cmap {
 | 
					 | 
				
			||||||
		// print name of identifiers; print node type for other nodes
 | 
					 | 
				
			||||||
		var s string
 | 
					 | 
				
			||||||
		if ident, ok := node.(*Ident); ok {
 | 
					 | 
				
			||||||
			s = ident.Name
 | 
					 | 
				
			||||||
		} else {
 | 
					 | 
				
			||||||
			s = fmt.Sprintf("%T", node)
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		fmt.Fprintf(&buf, "\t%p  %20s:  %s\n", node, s, summary(comment))
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	fmt.Fprintln(&buf, "}")
 | 
					 | 
				
			||||||
	return buf.String()
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
							
								
								
									
										143
									
								
								third_party/golang/go/ast/commentmap_test.go
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										143
									
								
								third_party/golang/go/ast/commentmap_test.go
									
									
									
									
										vendored
									
									
								
							@@ -1,143 +0,0 @@
 | 
				
			|||||||
// Copyright 2012 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.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// To avoid a cyclic dependency with go/parser, this file is in a separate package.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
package ast_test
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
import (
 | 
					 | 
				
			||||||
	"bytes"
 | 
					 | 
				
			||||||
	"fmt"
 | 
					 | 
				
			||||||
	. "k8s.io/kubernetes/third_party/golang/go/ast"
 | 
					 | 
				
			||||||
	"k8s.io/kubernetes/third_party/golang/go/parser"
 | 
					 | 
				
			||||||
	"k8s.io/kubernetes/third_party/golang/go/token"
 | 
					 | 
				
			||||||
	"sort"
 | 
					 | 
				
			||||||
	"testing"
 | 
					 | 
				
			||||||
)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
const src = `
 | 
					 | 
				
			||||||
// the very first comment
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// package p
 | 
					 | 
				
			||||||
package p /* the name is p */
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// imports
 | 
					 | 
				
			||||||
import (
 | 
					 | 
				
			||||||
	"bytes"     // bytes
 | 
					 | 
				
			||||||
	"fmt"       // fmt
 | 
					 | 
				
			||||||
	"k8s.io/kubernetes/third_party/golang/go/ast"
 | 
					 | 
				
			||||||
	"k8s.io/kubernetes/third_party/golang/go/parser"
 | 
					 | 
				
			||||||
)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// T
 | 
					 | 
				
			||||||
type T struct {
 | 
					 | 
				
			||||||
	a, b, c int // associated with a, b, c
 | 
					 | 
				
			||||||
	// associated with x, y
 | 
					 | 
				
			||||||
	x, y float64    // float values
 | 
					 | 
				
			||||||
	z    complex128 // complex value
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
// also associated with T
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// x
 | 
					 | 
				
			||||||
var x = 0 // x = 0
 | 
					 | 
				
			||||||
// also associated with x
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// f1
 | 
					 | 
				
			||||||
func f1() {
 | 
					 | 
				
			||||||
	/* associated with s1 */
 | 
					 | 
				
			||||||
	s1()
 | 
					 | 
				
			||||||
	// also associated with s1
 | 
					 | 
				
			||||||
	
 | 
					 | 
				
			||||||
	// associated with s2
 | 
					 | 
				
			||||||
	
 | 
					 | 
				
			||||||
	// also associated with s2
 | 
					 | 
				
			||||||
	s2() // line comment for s2
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
// associated with f1
 | 
					 | 
				
			||||||
// also associated with f1
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// associated with f2
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// f2
 | 
					 | 
				
			||||||
func f2() {
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func f3() {
 | 
					 | 
				
			||||||
	i := 1 /* 1 */ + 2 // addition
 | 
					 | 
				
			||||||
	_ = i
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// the very last comment
 | 
					 | 
				
			||||||
`
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// res maps a key of the form "line number: node type"
 | 
					 | 
				
			||||||
// to the associated comments' text.
 | 
					 | 
				
			||||||
//
 | 
					 | 
				
			||||||
var res = map[string]string{
 | 
					 | 
				
			||||||
	" 5: *ast.File":       "the very first comment\npackage p\n",
 | 
					 | 
				
			||||||
	" 5: *ast.Ident":      " the name is p\n",
 | 
					 | 
				
			||||||
	" 8: *ast.GenDecl":    "imports\n",
 | 
					 | 
				
			||||||
	" 9: *ast.ImportSpec": "bytes\n",
 | 
					 | 
				
			||||||
	"10: *ast.ImportSpec": "fmt\n",
 | 
					 | 
				
			||||||
	"16: *ast.GenDecl":    "T\nalso associated with T\n",
 | 
					 | 
				
			||||||
	"17: *ast.Field":      "associated with a, b, c\n",
 | 
					 | 
				
			||||||
	"19: *ast.Field":      "associated with x, y\nfloat values\n",
 | 
					 | 
				
			||||||
	"20: *ast.Field":      "complex value\n",
 | 
					 | 
				
			||||||
	"25: *ast.GenDecl":    "x\nx = 0\nalso associated with x\n",
 | 
					 | 
				
			||||||
	"29: *ast.FuncDecl":   "f1\nassociated with f1\nalso associated with f1\n",
 | 
					 | 
				
			||||||
	"31: *ast.ExprStmt":   " associated with s1\nalso associated with s1\n",
 | 
					 | 
				
			||||||
	"37: *ast.ExprStmt":   "associated with s2\nalso associated with s2\nline comment for s2\n",
 | 
					 | 
				
			||||||
	"45: *ast.FuncDecl":   "associated with f2\nf2\n",
 | 
					 | 
				
			||||||
	"49: *ast.AssignStmt": "addition\n",
 | 
					 | 
				
			||||||
	"49: *ast.BasicLit":   " 1\n",
 | 
					 | 
				
			||||||
	"50: *ast.Ident":      "the very last comment\n",
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func ctext(list []*CommentGroup) string {
 | 
					 | 
				
			||||||
	var buf bytes.Buffer
 | 
					 | 
				
			||||||
	for _, g := range list {
 | 
					 | 
				
			||||||
		buf.WriteString(g.Text())
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return buf.String()
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func TestCommentMap(t *testing.T) {
 | 
					 | 
				
			||||||
	fset := token.NewFileSet()
 | 
					 | 
				
			||||||
	f, err := parser.ParseFile(fset, "", src, parser.ParseComments)
 | 
					 | 
				
			||||||
	if err != nil {
 | 
					 | 
				
			||||||
		t.Fatal(err)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	cmap := NewCommentMap(fset, f, f.Comments)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// very correct association of comments
 | 
					 | 
				
			||||||
	for n, list := range cmap {
 | 
					 | 
				
			||||||
		key := fmt.Sprintf("%2d: %T", fset.Position(n.Pos()).Line, n)
 | 
					 | 
				
			||||||
		got := ctext(list)
 | 
					 | 
				
			||||||
		want := res[key]
 | 
					 | 
				
			||||||
		if got != want {
 | 
					 | 
				
			||||||
			t.Errorf("%s: got %q; want %q", key, got, want)
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// verify that no comments got lost
 | 
					 | 
				
			||||||
	if n := len(cmap.Comments()); n != len(f.Comments) {
 | 
					 | 
				
			||||||
		t.Errorf("got %d comment groups in map; want %d", n, len(f.Comments))
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// support code to update test:
 | 
					 | 
				
			||||||
	// set genMap to true to generate res map
 | 
					 | 
				
			||||||
	const genMap = false
 | 
					 | 
				
			||||||
	if genMap {
 | 
					 | 
				
			||||||
		out := make([]string, 0, len(cmap))
 | 
					 | 
				
			||||||
		for n, list := range cmap {
 | 
					 | 
				
			||||||
			out = append(out, fmt.Sprintf("\t\"%2d: %T\":\t%q,", fset.Position(n.Pos()).Line, n, ctext(list)))
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		sort.Strings(out)
 | 
					 | 
				
			||||||
		for _, s := range out {
 | 
					 | 
				
			||||||
			fmt.Println(s)
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// TODO(gri): add tests for Filter.
 | 
					 | 
				
			||||||
							
								
								
									
										210
									
								
								third_party/golang/go/ast/example_test.go
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										210
									
								
								third_party/golang/go/ast/example_test.go
									
									
									
									
										vendored
									
									
								
							@@ -1,210 +0,0 @@
 | 
				
			|||||||
// Copyright 2012 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 ast_test
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
import (
 | 
					 | 
				
			||||||
	"bytes"
 | 
					 | 
				
			||||||
	"fmt"
 | 
					 | 
				
			||||||
	"go/ast"
 | 
					 | 
				
			||||||
	"go/format"
 | 
					 | 
				
			||||||
	"go/parser"
 | 
					 | 
				
			||||||
	"go/token"
 | 
					 | 
				
			||||||
)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// This example demonstrates how to inspect the AST of a Go program.
 | 
					 | 
				
			||||||
func ExampleInspect() {
 | 
					 | 
				
			||||||
	// src is the input for which we want to inspect the AST.
 | 
					 | 
				
			||||||
	src := `
 | 
					 | 
				
			||||||
package p
 | 
					 | 
				
			||||||
const c = 1.0
 | 
					 | 
				
			||||||
var X = f(3.14)*2 + c
 | 
					 | 
				
			||||||
`
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// Create the AST by parsing src.
 | 
					 | 
				
			||||||
	fset := token.NewFileSet() // positions are relative to fset
 | 
					 | 
				
			||||||
	f, err := parser.ParseFile(fset, "src.go", src, 0)
 | 
					 | 
				
			||||||
	if err != nil {
 | 
					 | 
				
			||||||
		panic(err)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// Inspect the AST and print all identifiers and literals.
 | 
					 | 
				
			||||||
	ast.Inspect(f, func(n ast.Node) bool {
 | 
					 | 
				
			||||||
		var s string
 | 
					 | 
				
			||||||
		switch x := n.(type) {
 | 
					 | 
				
			||||||
		case *ast.BasicLit:
 | 
					 | 
				
			||||||
			s = x.Value
 | 
					 | 
				
			||||||
		case *ast.Ident:
 | 
					 | 
				
			||||||
			s = x.Name
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		if s != "" {
 | 
					 | 
				
			||||||
			fmt.Printf("%s:\t%s\n", fset.Position(n.Pos()), s)
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		return true
 | 
					 | 
				
			||||||
	})
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// output:
 | 
					 | 
				
			||||||
	// src.go:2:9:	p
 | 
					 | 
				
			||||||
	// src.go:3:7:	c
 | 
					 | 
				
			||||||
	// src.go:3:11:	1.0
 | 
					 | 
				
			||||||
	// src.go:4:5:	X
 | 
					 | 
				
			||||||
	// src.go:4:9:	f
 | 
					 | 
				
			||||||
	// src.go:4:11:	3.14
 | 
					 | 
				
			||||||
	// src.go:4:17:	2
 | 
					 | 
				
			||||||
	// src.go:4:21:	c
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// This example shows what an AST looks like when printed for debugging.
 | 
					 | 
				
			||||||
func ExamplePrint() {
 | 
					 | 
				
			||||||
	// src is the input for which we want to print the AST.
 | 
					 | 
				
			||||||
	src := `
 | 
					 | 
				
			||||||
package main
 | 
					 | 
				
			||||||
func main() {
 | 
					 | 
				
			||||||
	println("Hello, World!")
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
`
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// Create the AST by parsing src.
 | 
					 | 
				
			||||||
	fset := token.NewFileSet() // positions are relative to fset
 | 
					 | 
				
			||||||
	f, err := parser.ParseFile(fset, "", src, 0)
 | 
					 | 
				
			||||||
	if err != nil {
 | 
					 | 
				
			||||||
		panic(err)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// Print the AST.
 | 
					 | 
				
			||||||
	ast.Print(fset, f)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// output:
 | 
					 | 
				
			||||||
	//      0  *ast.File {
 | 
					 | 
				
			||||||
	//      1  .  Package: 2:1
 | 
					 | 
				
			||||||
	//      2  .  Name: *ast.Ident {
 | 
					 | 
				
			||||||
	//      3  .  .  NamePos: 2:9
 | 
					 | 
				
			||||||
	//      4  .  .  Name: "main"
 | 
					 | 
				
			||||||
	//      5  .  }
 | 
					 | 
				
			||||||
	//      6  .  Decls: []ast.Decl (len = 1) {
 | 
					 | 
				
			||||||
	//      7  .  .  0: *ast.FuncDecl {
 | 
					 | 
				
			||||||
	//      8  .  .  .  Name: *ast.Ident {
 | 
					 | 
				
			||||||
	//      9  .  .  .  .  NamePos: 3:6
 | 
					 | 
				
			||||||
	//     10  .  .  .  .  Name: "main"
 | 
					 | 
				
			||||||
	//     11  .  .  .  .  Obj: *ast.Object {
 | 
					 | 
				
			||||||
	//     12  .  .  .  .  .  Kind: func
 | 
					 | 
				
			||||||
	//     13  .  .  .  .  .  Name: "main"
 | 
					 | 
				
			||||||
	//     14  .  .  .  .  .  Decl: *(obj @ 7)
 | 
					 | 
				
			||||||
	//     15  .  .  .  .  }
 | 
					 | 
				
			||||||
	//     16  .  .  .  }
 | 
					 | 
				
			||||||
	//     17  .  .  .  Type: *ast.FuncType {
 | 
					 | 
				
			||||||
	//     18  .  .  .  .  Func: 3:1
 | 
					 | 
				
			||||||
	//     19  .  .  .  .  Params: *ast.FieldList {
 | 
					 | 
				
			||||||
	//     20  .  .  .  .  .  Opening: 3:10
 | 
					 | 
				
			||||||
	//     21  .  .  .  .  .  Closing: 3:11
 | 
					 | 
				
			||||||
	//     22  .  .  .  .  }
 | 
					 | 
				
			||||||
	//     23  .  .  .  }
 | 
					 | 
				
			||||||
	//     24  .  .  .  Body: *ast.BlockStmt {
 | 
					 | 
				
			||||||
	//     25  .  .  .  .  Lbrace: 3:13
 | 
					 | 
				
			||||||
	//     26  .  .  .  .  List: []ast.Stmt (len = 1) {
 | 
					 | 
				
			||||||
	//     27  .  .  .  .  .  0: *ast.ExprStmt {
 | 
					 | 
				
			||||||
	//     28  .  .  .  .  .  .  X: *ast.CallExpr {
 | 
					 | 
				
			||||||
	//     29  .  .  .  .  .  .  .  Fun: *ast.Ident {
 | 
					 | 
				
			||||||
	//     30  .  .  .  .  .  .  .  .  NamePos: 4:2
 | 
					 | 
				
			||||||
	//     31  .  .  .  .  .  .  .  .  Name: "println"
 | 
					 | 
				
			||||||
	//     32  .  .  .  .  .  .  .  }
 | 
					 | 
				
			||||||
	//     33  .  .  .  .  .  .  .  Lparen: 4:9
 | 
					 | 
				
			||||||
	//     34  .  .  .  .  .  .  .  Args: []ast.Expr (len = 1) {
 | 
					 | 
				
			||||||
	//     35  .  .  .  .  .  .  .  .  0: *ast.BasicLit {
 | 
					 | 
				
			||||||
	//     36  .  .  .  .  .  .  .  .  .  ValuePos: 4:10
 | 
					 | 
				
			||||||
	//     37  .  .  .  .  .  .  .  .  .  Kind: STRING
 | 
					 | 
				
			||||||
	//     38  .  .  .  .  .  .  .  .  .  Value: "\"Hello, World!\""
 | 
					 | 
				
			||||||
	//     39  .  .  .  .  .  .  .  .  }
 | 
					 | 
				
			||||||
	//     40  .  .  .  .  .  .  .  }
 | 
					 | 
				
			||||||
	//     41  .  .  .  .  .  .  .  Ellipsis: -
 | 
					 | 
				
			||||||
	//     42  .  .  .  .  .  .  .  Rparen: 4:25
 | 
					 | 
				
			||||||
	//     43  .  .  .  .  .  .  }
 | 
					 | 
				
			||||||
	//     44  .  .  .  .  .  }
 | 
					 | 
				
			||||||
	//     45  .  .  .  .  }
 | 
					 | 
				
			||||||
	//     46  .  .  .  .  Rbrace: 5:1
 | 
					 | 
				
			||||||
	//     47  .  .  .  }
 | 
					 | 
				
			||||||
	//     48  .  .  }
 | 
					 | 
				
			||||||
	//     49  .  }
 | 
					 | 
				
			||||||
	//     50  .  Scope: *ast.Scope {
 | 
					 | 
				
			||||||
	//     51  .  .  Objects: map[string]*ast.Object (len = 1) {
 | 
					 | 
				
			||||||
	//     52  .  .  .  "main": *(obj @ 11)
 | 
					 | 
				
			||||||
	//     53  .  .  }
 | 
					 | 
				
			||||||
	//     54  .  }
 | 
					 | 
				
			||||||
	//     55  .  Unresolved: []*ast.Ident (len = 1) {
 | 
					 | 
				
			||||||
	//     56  .  .  0: *(obj @ 29)
 | 
					 | 
				
			||||||
	//     57  .  }
 | 
					 | 
				
			||||||
	//     58  }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// This example illustrates how to remove a variable declaration
 | 
					 | 
				
			||||||
// in a Go program while maintaining correct comment association
 | 
					 | 
				
			||||||
// using an ast.CommentMap.
 | 
					 | 
				
			||||||
func ExampleCommentMap() {
 | 
					 | 
				
			||||||
	// src is the input for which we create the AST that we
 | 
					 | 
				
			||||||
	// are going to manipulate.
 | 
					 | 
				
			||||||
	src := `
 | 
					 | 
				
			||||||
// This is the package comment.
 | 
					 | 
				
			||||||
package main
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// This comment is associated with the hello constant.
 | 
					 | 
				
			||||||
const hello = "Hello, World!" // line comment 1
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// This comment is associated with the foo variable.
 | 
					 | 
				
			||||||
var foo = hello // line comment 2 
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// This comment is associated with the main function.
 | 
					 | 
				
			||||||
func main() {
 | 
					 | 
				
			||||||
	fmt.Println(hello) // line comment 3
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
`
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// Create the AST by parsing src.
 | 
					 | 
				
			||||||
	fset := token.NewFileSet() // positions are relative to fset
 | 
					 | 
				
			||||||
	f, err := parser.ParseFile(fset, "src.go", src, parser.ParseComments)
 | 
					 | 
				
			||||||
	if err != nil {
 | 
					 | 
				
			||||||
		panic(err)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// Create an ast.CommentMap from the ast.File's comments.
 | 
					 | 
				
			||||||
	// This helps keeping the association between comments
 | 
					 | 
				
			||||||
	// and AST nodes.
 | 
					 | 
				
			||||||
	cmap := ast.NewCommentMap(fset, f, f.Comments)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// Remove the first variable declaration from the list of declarations.
 | 
					 | 
				
			||||||
	f.Decls = removeFirstVarDecl(f.Decls)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// Use the comment map to filter comments that don't belong anymore
 | 
					 | 
				
			||||||
	// (the comments associated with the variable declaration), and create
 | 
					 | 
				
			||||||
	// the new comments list.
 | 
					 | 
				
			||||||
	f.Comments = cmap.Filter(f).Comments()
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// Print the modified AST.
 | 
					 | 
				
			||||||
	var buf bytes.Buffer
 | 
					 | 
				
			||||||
	if err := format.Node(&buf, fset, f); err != nil {
 | 
					 | 
				
			||||||
		panic(err)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	fmt.Printf("%s", buf.Bytes())
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// output:
 | 
					 | 
				
			||||||
	// // This is the package comment.
 | 
					 | 
				
			||||||
	// package main
 | 
					 | 
				
			||||||
	//
 | 
					 | 
				
			||||||
	// // This comment is associated with the hello constant.
 | 
					 | 
				
			||||||
	// const hello = "Hello, World!" // line comment 1
 | 
					 | 
				
			||||||
	//
 | 
					 | 
				
			||||||
	// // This comment is associated with the main function.
 | 
					 | 
				
			||||||
	// func main() {
 | 
					 | 
				
			||||||
	// 	fmt.Println(hello) // line comment 3
 | 
					 | 
				
			||||||
	// }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func removeFirstVarDecl(list []ast.Decl) []ast.Decl {
 | 
					 | 
				
			||||||
	for i, decl := range list {
 | 
					 | 
				
			||||||
		if gen, ok := decl.(*ast.GenDecl); ok && gen.Tok == token.VAR {
 | 
					 | 
				
			||||||
			copy(list[i:], list[i+1:])
 | 
					 | 
				
			||||||
			return list[:len(list)-1]
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	panic("variable declaration not found")
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
							
								
								
									
										465
									
								
								third_party/golang/go/ast/filter.go
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										465
									
								
								third_party/golang/go/ast/filter.go
									
									
									
									
										vendored
									
									
								
							@@ -1,465 +0,0 @@
 | 
				
			|||||||
// Copyright 2009 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 ast
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
import (
 | 
					 | 
				
			||||||
	"k8s.io/kubernetes/third_party/golang/go/token"
 | 
					 | 
				
			||||||
	"sort"
 | 
					 | 
				
			||||||
)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// ----------------------------------------------------------------------------
 | 
					 | 
				
			||||||
// Export filtering
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// exportFilter is a special filter function to extract exported nodes.
 | 
					 | 
				
			||||||
func exportFilter(name string) bool {
 | 
					 | 
				
			||||||
	return IsExported(name)
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// FileExports trims the AST for a Go source file in place such that
 | 
					 | 
				
			||||||
// only exported nodes remain: all top-level identifiers which are not exported
 | 
					 | 
				
			||||||
// and their associated information (such as type, initial value, or function
 | 
					 | 
				
			||||||
// body) are removed. Non-exported fields and methods of exported types are
 | 
					 | 
				
			||||||
// stripped. The File.Comments list is not changed.
 | 
					 | 
				
			||||||
//
 | 
					 | 
				
			||||||
// FileExports reports whether there are exported declarations.
 | 
					 | 
				
			||||||
//
 | 
					 | 
				
			||||||
func FileExports(src *File) bool {
 | 
					 | 
				
			||||||
	return filterFile(src, exportFilter, true)
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// PackageExports trims the AST for a Go package in place such that
 | 
					 | 
				
			||||||
// only exported nodes remain. The pkg.Files list is not changed, so that
 | 
					 | 
				
			||||||
// file names and top-level package comments don't get lost.
 | 
					 | 
				
			||||||
//
 | 
					 | 
				
			||||||
// PackageExports reports whether there are exported declarations;
 | 
					 | 
				
			||||||
// it returns false otherwise.
 | 
					 | 
				
			||||||
//
 | 
					 | 
				
			||||||
func PackageExports(pkg *Package) bool {
 | 
					 | 
				
			||||||
	return filterPackage(pkg, exportFilter, true)
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// ----------------------------------------------------------------------------
 | 
					 | 
				
			||||||
// General filtering
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
type Filter func(string) bool
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func filterIdentList(list []*Ident, f Filter) []*Ident {
 | 
					 | 
				
			||||||
	j := 0
 | 
					 | 
				
			||||||
	for _, x := range list {
 | 
					 | 
				
			||||||
		if f(x.Name) {
 | 
					 | 
				
			||||||
			list[j] = x
 | 
					 | 
				
			||||||
			j++
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return list[0:j]
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// fieldName assumes that x is the type of an anonymous field and
 | 
					 | 
				
			||||||
// returns the corresponding field name. If x is not an acceptable
 | 
					 | 
				
			||||||
// anonymous field, the result is nil.
 | 
					 | 
				
			||||||
//
 | 
					 | 
				
			||||||
func fieldName(x Expr) *Ident {
 | 
					 | 
				
			||||||
	switch t := x.(type) {
 | 
					 | 
				
			||||||
	case *Ident:
 | 
					 | 
				
			||||||
		return t
 | 
					 | 
				
			||||||
	case *SelectorExpr:
 | 
					 | 
				
			||||||
		if _, ok := t.X.(*Ident); ok {
 | 
					 | 
				
			||||||
			return t.Sel
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	case *StarExpr:
 | 
					 | 
				
			||||||
		return fieldName(t.X)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return nil
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func filterFieldList(fields *FieldList, filter Filter, export bool) (removedFields bool) {
 | 
					 | 
				
			||||||
	if fields == nil {
 | 
					 | 
				
			||||||
		return false
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	list := fields.List
 | 
					 | 
				
			||||||
	j := 0
 | 
					 | 
				
			||||||
	for _, f := range list {
 | 
					 | 
				
			||||||
		keepField := false
 | 
					 | 
				
			||||||
		if len(f.Names) == 0 {
 | 
					 | 
				
			||||||
			// anonymous field
 | 
					 | 
				
			||||||
			name := fieldName(f.Type)
 | 
					 | 
				
			||||||
			keepField = name != nil && filter(name.Name)
 | 
					 | 
				
			||||||
		} else {
 | 
					 | 
				
			||||||
			n := len(f.Names)
 | 
					 | 
				
			||||||
			f.Names = filterIdentList(f.Names, filter)
 | 
					 | 
				
			||||||
			if len(f.Names) < n {
 | 
					 | 
				
			||||||
				removedFields = true
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
			keepField = len(f.Names) > 0
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		if keepField {
 | 
					 | 
				
			||||||
			if export {
 | 
					 | 
				
			||||||
				filterType(f.Type, filter, export)
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
			list[j] = f
 | 
					 | 
				
			||||||
			j++
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	if j < len(list) {
 | 
					 | 
				
			||||||
		removedFields = true
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	fields.List = list[0:j]
 | 
					 | 
				
			||||||
	return
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func filterParamList(fields *FieldList, filter Filter, export bool) bool {
 | 
					 | 
				
			||||||
	if fields == nil {
 | 
					 | 
				
			||||||
		return false
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	var b bool
 | 
					 | 
				
			||||||
	for _, f := range fields.List {
 | 
					 | 
				
			||||||
		if filterType(f.Type, filter, export) {
 | 
					 | 
				
			||||||
			b = true
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return b
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func filterType(typ Expr, f Filter, export bool) bool {
 | 
					 | 
				
			||||||
	switch t := typ.(type) {
 | 
					 | 
				
			||||||
	case *Ident:
 | 
					 | 
				
			||||||
		return f(t.Name)
 | 
					 | 
				
			||||||
	case *ParenExpr:
 | 
					 | 
				
			||||||
		return filterType(t.X, f, export)
 | 
					 | 
				
			||||||
	case *ArrayType:
 | 
					 | 
				
			||||||
		return filterType(t.Elt, f, export)
 | 
					 | 
				
			||||||
	case *StructType:
 | 
					 | 
				
			||||||
		if filterFieldList(t.Fields, f, export) {
 | 
					 | 
				
			||||||
			t.Incomplete = true
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		return len(t.Fields.List) > 0
 | 
					 | 
				
			||||||
	case *FuncType:
 | 
					 | 
				
			||||||
		b1 := filterParamList(t.Params, f, export)
 | 
					 | 
				
			||||||
		b2 := filterParamList(t.Results, f, export)
 | 
					 | 
				
			||||||
		return b1 || b2
 | 
					 | 
				
			||||||
	case *InterfaceType:
 | 
					 | 
				
			||||||
		if filterFieldList(t.Methods, f, export) {
 | 
					 | 
				
			||||||
			t.Incomplete = true
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		return len(t.Methods.List) > 0
 | 
					 | 
				
			||||||
	case *MapType:
 | 
					 | 
				
			||||||
		b1 := filterType(t.Key, f, export)
 | 
					 | 
				
			||||||
		b2 := filterType(t.Value, f, export)
 | 
					 | 
				
			||||||
		return b1 || b2
 | 
					 | 
				
			||||||
	case *ChanType:
 | 
					 | 
				
			||||||
		return filterType(t.Value, f, export)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return false
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func filterSpec(spec Spec, f Filter, export bool) bool {
 | 
					 | 
				
			||||||
	switch s := spec.(type) {
 | 
					 | 
				
			||||||
	case *ValueSpec:
 | 
					 | 
				
			||||||
		s.Names = filterIdentList(s.Names, f)
 | 
					 | 
				
			||||||
		if len(s.Names) > 0 {
 | 
					 | 
				
			||||||
			if export {
 | 
					 | 
				
			||||||
				filterType(s.Type, f, export)
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
			return true
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	case *TypeSpec:
 | 
					 | 
				
			||||||
		if f(s.Name.Name) {
 | 
					 | 
				
			||||||
			if export {
 | 
					 | 
				
			||||||
				filterType(s.Type, f, export)
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
			return true
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		if !export {
 | 
					 | 
				
			||||||
			// For general filtering (not just exports),
 | 
					 | 
				
			||||||
			// filter type even if name is not filtered
 | 
					 | 
				
			||||||
			// out.
 | 
					 | 
				
			||||||
			// If the type contains filtered elements,
 | 
					 | 
				
			||||||
			// keep the declaration.
 | 
					 | 
				
			||||||
			return filterType(s.Type, f, export)
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return false
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func filterSpecList(list []Spec, f Filter, export bool) []Spec {
 | 
					 | 
				
			||||||
	j := 0
 | 
					 | 
				
			||||||
	for _, s := range list {
 | 
					 | 
				
			||||||
		if filterSpec(s, f, export) {
 | 
					 | 
				
			||||||
			list[j] = s
 | 
					 | 
				
			||||||
			j++
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return list[0:j]
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// FilterDecl trims the AST for a Go declaration in place by removing
 | 
					 | 
				
			||||||
// all names (including struct field and interface method names, but
 | 
					 | 
				
			||||||
// not from parameter lists) that don't pass through the filter f.
 | 
					 | 
				
			||||||
//
 | 
					 | 
				
			||||||
// FilterDecl reports whether there are any declared names left after
 | 
					 | 
				
			||||||
// filtering.
 | 
					 | 
				
			||||||
//
 | 
					 | 
				
			||||||
func FilterDecl(decl Decl, f Filter) bool {
 | 
					 | 
				
			||||||
	return filterDecl(decl, f, false)
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func filterDecl(decl Decl, f Filter, export bool) bool {
 | 
					 | 
				
			||||||
	switch d := decl.(type) {
 | 
					 | 
				
			||||||
	case *GenDecl:
 | 
					 | 
				
			||||||
		d.Specs = filterSpecList(d.Specs, f, export)
 | 
					 | 
				
			||||||
		return len(d.Specs) > 0
 | 
					 | 
				
			||||||
	case *FuncDecl:
 | 
					 | 
				
			||||||
		return f(d.Name.Name)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return false
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// FilterFile trims the AST for a Go file in place by removing all
 | 
					 | 
				
			||||||
// names from top-level declarations (including struct field and
 | 
					 | 
				
			||||||
// interface method names, but not from parameter lists) that don't
 | 
					 | 
				
			||||||
// pass through the filter f. If the declaration is empty afterwards,
 | 
					 | 
				
			||||||
// the declaration is removed from the AST. Import declarations are
 | 
					 | 
				
			||||||
// always removed. The File.Comments list is not changed.
 | 
					 | 
				
			||||||
//
 | 
					 | 
				
			||||||
// FilterFile reports whether there are any top-level declarations
 | 
					 | 
				
			||||||
// left after filtering.
 | 
					 | 
				
			||||||
//
 | 
					 | 
				
			||||||
func FilterFile(src *File, f Filter) bool {
 | 
					 | 
				
			||||||
	return filterFile(src, f, false)
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func filterFile(src *File, f Filter, export bool) bool {
 | 
					 | 
				
			||||||
	j := 0
 | 
					 | 
				
			||||||
	for _, d := range src.Decls {
 | 
					 | 
				
			||||||
		if filterDecl(d, f, export) {
 | 
					 | 
				
			||||||
			src.Decls[j] = d
 | 
					 | 
				
			||||||
			j++
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	src.Decls = src.Decls[0:j]
 | 
					 | 
				
			||||||
	return j > 0
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// FilterPackage trims the AST for a Go package in place by removing
 | 
					 | 
				
			||||||
// all names from top-level declarations (including struct field and
 | 
					 | 
				
			||||||
// interface method names, but not from parameter lists) that don't
 | 
					 | 
				
			||||||
// pass through the filter f. If the declaration is empty afterwards,
 | 
					 | 
				
			||||||
// the declaration is removed from the AST. The pkg.Files list is not
 | 
					 | 
				
			||||||
// changed, so that file names and top-level package comments don't get
 | 
					 | 
				
			||||||
// lost.
 | 
					 | 
				
			||||||
//
 | 
					 | 
				
			||||||
// FilterPackage reports whether there are any top-level declarations
 | 
					 | 
				
			||||||
// left after filtering.
 | 
					 | 
				
			||||||
//
 | 
					 | 
				
			||||||
func FilterPackage(pkg *Package, f Filter) bool {
 | 
					 | 
				
			||||||
	return filterPackage(pkg, f, false)
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func filterPackage(pkg *Package, f Filter, export bool) bool {
 | 
					 | 
				
			||||||
	hasDecls := false
 | 
					 | 
				
			||||||
	for _, src := range pkg.Files {
 | 
					 | 
				
			||||||
		if filterFile(src, f, export) {
 | 
					 | 
				
			||||||
			hasDecls = true
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return hasDecls
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// ----------------------------------------------------------------------------
 | 
					 | 
				
			||||||
// Merging of package files
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// The MergeMode flags control the behavior of MergePackageFiles.
 | 
					 | 
				
			||||||
type MergeMode uint
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
const (
 | 
					 | 
				
			||||||
	// If set, duplicate function declarations are excluded.
 | 
					 | 
				
			||||||
	FilterFuncDuplicates MergeMode = 1 << iota
 | 
					 | 
				
			||||||
	// If set, comments that are not associated with a specific
 | 
					 | 
				
			||||||
	// AST node (as Doc or Comment) are excluded.
 | 
					 | 
				
			||||||
	FilterUnassociatedComments
 | 
					 | 
				
			||||||
	// If set, duplicate import declarations are excluded.
 | 
					 | 
				
			||||||
	FilterImportDuplicates
 | 
					 | 
				
			||||||
)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// nameOf returns the function (foo) or method name (foo.bar) for
 | 
					 | 
				
			||||||
// the given function declaration. If the AST is incorrect for the
 | 
					 | 
				
			||||||
// receiver, it assumes a function instead.
 | 
					 | 
				
			||||||
//
 | 
					 | 
				
			||||||
func nameOf(f *FuncDecl) string {
 | 
					 | 
				
			||||||
	if r := f.Recv; r != nil && len(r.List) == 1 {
 | 
					 | 
				
			||||||
		// looks like a correct receiver declaration
 | 
					 | 
				
			||||||
		t := r.List[0].Type
 | 
					 | 
				
			||||||
		// dereference pointer receiver types
 | 
					 | 
				
			||||||
		if p, _ := t.(*StarExpr); p != nil {
 | 
					 | 
				
			||||||
			t = p.X
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		// the receiver type must be a type name
 | 
					 | 
				
			||||||
		if p, _ := t.(*Ident); p != nil {
 | 
					 | 
				
			||||||
			return p.Name + "." + f.Name.Name
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		// otherwise assume a function instead
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return f.Name.Name
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// separator is an empty //-style comment that is interspersed between
 | 
					 | 
				
			||||||
// different comment groups when they are concatenated into a single group
 | 
					 | 
				
			||||||
//
 | 
					 | 
				
			||||||
var separator = &Comment{token.NoPos, "//"}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// MergePackageFiles creates a file AST by merging the ASTs of the
 | 
					 | 
				
			||||||
// files belonging to a package. The mode flags control merging behavior.
 | 
					 | 
				
			||||||
//
 | 
					 | 
				
			||||||
func MergePackageFiles(pkg *Package, mode MergeMode) *File {
 | 
					 | 
				
			||||||
	// Count the number of package docs, comments and declarations across
 | 
					 | 
				
			||||||
	// all package files. Also, compute sorted list of filenames, so that
 | 
					 | 
				
			||||||
	// subsequent iterations can always iterate in the same order.
 | 
					 | 
				
			||||||
	ndocs := 0
 | 
					 | 
				
			||||||
	ncomments := 0
 | 
					 | 
				
			||||||
	ndecls := 0
 | 
					 | 
				
			||||||
	filenames := make([]string, len(pkg.Files))
 | 
					 | 
				
			||||||
	i := 0
 | 
					 | 
				
			||||||
	for filename, f := range pkg.Files {
 | 
					 | 
				
			||||||
		filenames[i] = filename
 | 
					 | 
				
			||||||
		i++
 | 
					 | 
				
			||||||
		if f.Doc != nil {
 | 
					 | 
				
			||||||
			ndocs += len(f.Doc.List) + 1 // +1 for separator
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		ncomments += len(f.Comments)
 | 
					 | 
				
			||||||
		ndecls += len(f.Decls)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	sort.Strings(filenames)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// Collect package comments from all package files into a single
 | 
					 | 
				
			||||||
	// CommentGroup - the collected package documentation. In general
 | 
					 | 
				
			||||||
	// there should be only one file with a package comment; but it's
 | 
					 | 
				
			||||||
	// better to collect extra comments than drop them on the floor.
 | 
					 | 
				
			||||||
	var doc *CommentGroup
 | 
					 | 
				
			||||||
	var pos token.Pos
 | 
					 | 
				
			||||||
	if ndocs > 0 {
 | 
					 | 
				
			||||||
		list := make([]*Comment, ndocs-1) // -1: no separator before first group
 | 
					 | 
				
			||||||
		i := 0
 | 
					 | 
				
			||||||
		for _, filename := range filenames {
 | 
					 | 
				
			||||||
			f := pkg.Files[filename]
 | 
					 | 
				
			||||||
			if f.Doc != nil {
 | 
					 | 
				
			||||||
				if i > 0 {
 | 
					 | 
				
			||||||
					// not the first group - add separator
 | 
					 | 
				
			||||||
					list[i] = separator
 | 
					 | 
				
			||||||
					i++
 | 
					 | 
				
			||||||
				}
 | 
					 | 
				
			||||||
				for _, c := range f.Doc.List {
 | 
					 | 
				
			||||||
					list[i] = c
 | 
					 | 
				
			||||||
					i++
 | 
					 | 
				
			||||||
				}
 | 
					 | 
				
			||||||
				if f.Package > pos {
 | 
					 | 
				
			||||||
					// Keep the maximum package clause position as
 | 
					 | 
				
			||||||
					// position for the package clause of the merged
 | 
					 | 
				
			||||||
					// files.
 | 
					 | 
				
			||||||
					pos = f.Package
 | 
					 | 
				
			||||||
				}
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		doc = &CommentGroup{list}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// Collect declarations from all package files.
 | 
					 | 
				
			||||||
	var decls []Decl
 | 
					 | 
				
			||||||
	if ndecls > 0 {
 | 
					 | 
				
			||||||
		decls = make([]Decl, ndecls)
 | 
					 | 
				
			||||||
		funcs := make(map[string]int) // map of func name -> decls index
 | 
					 | 
				
			||||||
		i := 0                        // current index
 | 
					 | 
				
			||||||
		n := 0                        // number of filtered entries
 | 
					 | 
				
			||||||
		for _, filename := range filenames {
 | 
					 | 
				
			||||||
			f := pkg.Files[filename]
 | 
					 | 
				
			||||||
			for _, d := range f.Decls {
 | 
					 | 
				
			||||||
				if mode&FilterFuncDuplicates != 0 {
 | 
					 | 
				
			||||||
					// A language entity may be declared multiple
 | 
					 | 
				
			||||||
					// times in different package files; only at
 | 
					 | 
				
			||||||
					// build time declarations must be unique.
 | 
					 | 
				
			||||||
					// For now, exclude multiple declarations of
 | 
					 | 
				
			||||||
					// functions - keep the one with documentation.
 | 
					 | 
				
			||||||
					//
 | 
					 | 
				
			||||||
					// TODO(gri): Expand this filtering to other
 | 
					 | 
				
			||||||
					//            entities (const, type, vars) if
 | 
					 | 
				
			||||||
					//            multiple declarations are common.
 | 
					 | 
				
			||||||
					if f, isFun := d.(*FuncDecl); isFun {
 | 
					 | 
				
			||||||
						name := nameOf(f)
 | 
					 | 
				
			||||||
						if j, exists := funcs[name]; exists {
 | 
					 | 
				
			||||||
							// function declared already
 | 
					 | 
				
			||||||
							if decls[j] != nil && decls[j].(*FuncDecl).Doc == nil {
 | 
					 | 
				
			||||||
								// existing declaration has no documentation;
 | 
					 | 
				
			||||||
								// ignore the existing declaration
 | 
					 | 
				
			||||||
								decls[j] = nil
 | 
					 | 
				
			||||||
							} else {
 | 
					 | 
				
			||||||
								// ignore the new declaration
 | 
					 | 
				
			||||||
								d = nil
 | 
					 | 
				
			||||||
							}
 | 
					 | 
				
			||||||
							n++ // filtered an entry
 | 
					 | 
				
			||||||
						} else {
 | 
					 | 
				
			||||||
							funcs[name] = i
 | 
					 | 
				
			||||||
						}
 | 
					 | 
				
			||||||
					}
 | 
					 | 
				
			||||||
				}
 | 
					 | 
				
			||||||
				decls[i] = d
 | 
					 | 
				
			||||||
				i++
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		// Eliminate nil entries from the decls list if entries were
 | 
					 | 
				
			||||||
		// filtered. We do this using a 2nd pass in order to not disturb
 | 
					 | 
				
			||||||
		// the original declaration order in the source (otherwise, this
 | 
					 | 
				
			||||||
		// would also invalidate the monotonically increasing position
 | 
					 | 
				
			||||||
		// info within a single file).
 | 
					 | 
				
			||||||
		if n > 0 {
 | 
					 | 
				
			||||||
			i = 0
 | 
					 | 
				
			||||||
			for _, d := range decls {
 | 
					 | 
				
			||||||
				if d != nil {
 | 
					 | 
				
			||||||
					decls[i] = d
 | 
					 | 
				
			||||||
					i++
 | 
					 | 
				
			||||||
				}
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
			decls = decls[0:i]
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// Collect import specs from all package files.
 | 
					 | 
				
			||||||
	var imports []*ImportSpec
 | 
					 | 
				
			||||||
	if mode&FilterImportDuplicates != 0 {
 | 
					 | 
				
			||||||
		seen := make(map[string]bool)
 | 
					 | 
				
			||||||
		for _, filename := range filenames {
 | 
					 | 
				
			||||||
			f := pkg.Files[filename]
 | 
					 | 
				
			||||||
			for _, imp := range f.Imports {
 | 
					 | 
				
			||||||
				if path := imp.Path.Value; !seen[path] {
 | 
					 | 
				
			||||||
					// TODO: consider handling cases where:
 | 
					 | 
				
			||||||
					// - 2 imports exist with the same import path but
 | 
					 | 
				
			||||||
					//   have different local names (one should probably
 | 
					 | 
				
			||||||
					//   keep both of them)
 | 
					 | 
				
			||||||
					// - 2 imports exist but only one has a comment
 | 
					 | 
				
			||||||
					// - 2 imports exist and they both have (possibly
 | 
					 | 
				
			||||||
					//   different) comments
 | 
					 | 
				
			||||||
					imports = append(imports, imp)
 | 
					 | 
				
			||||||
					seen[path] = true
 | 
					 | 
				
			||||||
				}
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	} else {
 | 
					 | 
				
			||||||
		for _, f := range pkg.Files {
 | 
					 | 
				
			||||||
			imports = append(imports, f.Imports...)
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// Collect comments from all package files.
 | 
					 | 
				
			||||||
	var comments []*CommentGroup
 | 
					 | 
				
			||||||
	if mode&FilterUnassociatedComments == 0 {
 | 
					 | 
				
			||||||
		comments = make([]*CommentGroup, ncomments)
 | 
					 | 
				
			||||||
		i := 0
 | 
					 | 
				
			||||||
		for _, f := range pkg.Files {
 | 
					 | 
				
			||||||
			i += copy(comments[i:], f.Comments)
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// TODO(gri) need to compute unresolved identifiers!
 | 
					 | 
				
			||||||
	return &File{doc, pos, NewIdent(pkg.Name), decls, pkg.Scope, imports, nil, comments}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
							
								
								
									
										86
									
								
								third_party/golang/go/ast/filter_test.go
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										86
									
								
								third_party/golang/go/ast/filter_test.go
									
									
									
									
										vendored
									
									
								
							@@ -1,86 +0,0 @@
 | 
				
			|||||||
// Copyright 2013 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.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// To avoid a cyclic dependency with go/parser, this file is in a separate package.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
package ast_test
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
import (
 | 
					 | 
				
			||||||
	"bytes"
 | 
					 | 
				
			||||||
	"go/ast"
 | 
					 | 
				
			||||||
	"go/format"
 | 
					 | 
				
			||||||
	"go/parser"
 | 
					 | 
				
			||||||
	"go/token"
 | 
					 | 
				
			||||||
	"testing"
 | 
					 | 
				
			||||||
)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
const input = `package p
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
type t1 struct{}
 | 
					 | 
				
			||||||
type t2 struct{}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func f1() {}
 | 
					 | 
				
			||||||
func f1() {}
 | 
					 | 
				
			||||||
func f2() {}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (*t1) f1() {}
 | 
					 | 
				
			||||||
func (t1) f1() {}
 | 
					 | 
				
			||||||
func (t1) f2() {}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (t2) f1() {}
 | 
					 | 
				
			||||||
func (t2) f2() {}
 | 
					 | 
				
			||||||
func (x *t2) f2() {}
 | 
					 | 
				
			||||||
`
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// Calling ast.MergePackageFiles with ast.FilterFuncDuplicates
 | 
					 | 
				
			||||||
// keeps a duplicate entry with attached documentation in favor
 | 
					 | 
				
			||||||
// of one without, and it favors duplicate entries appearing
 | 
					 | 
				
			||||||
// later in the source over ones appearing earlier. This is why
 | 
					 | 
				
			||||||
// (*t2).f2 is kept and t2.f2 is eliminated in this test case.
 | 
					 | 
				
			||||||
//
 | 
					 | 
				
			||||||
const golden = `package p
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
type t1 struct{}
 | 
					 | 
				
			||||||
type t2 struct{}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func f1() {}
 | 
					 | 
				
			||||||
func f2() {}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (t1) f1() {}
 | 
					 | 
				
			||||||
func (t1) f2() {}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (t2) f1() {}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (x *t2) f2() {}
 | 
					 | 
				
			||||||
`
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func TestFilterDuplicates(t *testing.T) {
 | 
					 | 
				
			||||||
	// parse input
 | 
					 | 
				
			||||||
	fset := token.NewFileSet()
 | 
					 | 
				
			||||||
	file, err := parser.ParseFile(fset, "", input, 0)
 | 
					 | 
				
			||||||
	if err != nil {
 | 
					 | 
				
			||||||
		t.Fatal(err)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// create package
 | 
					 | 
				
			||||||
	files := map[string]*ast.File{"": file}
 | 
					 | 
				
			||||||
	pkg, err := ast.NewPackage(fset, files, nil, nil)
 | 
					 | 
				
			||||||
	if err != nil {
 | 
					 | 
				
			||||||
		t.Fatal(err)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// filter
 | 
					 | 
				
			||||||
	merged := ast.MergePackageFiles(pkg, ast.FilterFuncDuplicates)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// pretty-print
 | 
					 | 
				
			||||||
	var buf bytes.Buffer
 | 
					 | 
				
			||||||
	if err := format.Node(&buf, fset, merged); err != nil {
 | 
					 | 
				
			||||||
		t.Fatal(err)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	output := buf.String()
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if output != golden {
 | 
					 | 
				
			||||||
		t.Errorf("incorrect output:\n%s", output)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
							
								
								
									
										196
									
								
								third_party/golang/go/ast/import.go
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										196
									
								
								third_party/golang/go/ast/import.go
									
									
									
									
										vendored
									
									
								
							@@ -1,196 +0,0 @@
 | 
				
			|||||||
// Copyright 2011 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 ast
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
import (
 | 
					 | 
				
			||||||
	"k8s.io/kubernetes/third_party/golang/go/token"
 | 
					 | 
				
			||||||
	"sort"
 | 
					 | 
				
			||||||
	"strconv"
 | 
					 | 
				
			||||||
)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// SortImports sorts runs of consecutive import lines in import blocks in f.
 | 
					 | 
				
			||||||
// It also removes duplicate imports when it is possible to do so without data loss.
 | 
					 | 
				
			||||||
func SortImports(fset *token.FileSet, f *File) {
 | 
					 | 
				
			||||||
	for _, d := range f.Decls {
 | 
					 | 
				
			||||||
		d, ok := d.(*GenDecl)
 | 
					 | 
				
			||||||
		if !ok || d.Tok != token.IMPORT {
 | 
					 | 
				
			||||||
			// Not an import declaration, so we're done.
 | 
					 | 
				
			||||||
			// Imports are always first.
 | 
					 | 
				
			||||||
			break
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		if !d.Lparen.IsValid() {
 | 
					 | 
				
			||||||
			// Not a block: sorted by default.
 | 
					 | 
				
			||||||
			continue
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		// Identify and sort runs of specs on successive lines.
 | 
					 | 
				
			||||||
		i := 0
 | 
					 | 
				
			||||||
		specs := d.Specs[:0]
 | 
					 | 
				
			||||||
		for j, s := range d.Specs {
 | 
					 | 
				
			||||||
			if j > i && fset.Position(s.Pos()).Line > 1+fset.Position(d.Specs[j-1].End()).Line {
 | 
					 | 
				
			||||||
				// j begins a new run.  End this one.
 | 
					 | 
				
			||||||
				specs = append(specs, sortSpecs(fset, f, d.Specs[i:j])...)
 | 
					 | 
				
			||||||
				i = j
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		specs = append(specs, sortSpecs(fset, f, d.Specs[i:])...)
 | 
					 | 
				
			||||||
		d.Specs = specs
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		// Deduping can leave a blank line before the rparen; clean that up.
 | 
					 | 
				
			||||||
		if len(d.Specs) > 0 {
 | 
					 | 
				
			||||||
			lastSpec := d.Specs[len(d.Specs)-1]
 | 
					 | 
				
			||||||
			lastLine := fset.Position(lastSpec.Pos()).Line
 | 
					 | 
				
			||||||
			if rParenLine := fset.Position(d.Rparen).Line; rParenLine > lastLine+1 {
 | 
					 | 
				
			||||||
				fset.File(d.Rparen).MergeLine(rParenLine - 1)
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func importPath(s Spec) string {
 | 
					 | 
				
			||||||
	t, err := strconv.Unquote(s.(*ImportSpec).Path.Value)
 | 
					 | 
				
			||||||
	if err == nil {
 | 
					 | 
				
			||||||
		return t
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return ""
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func importName(s Spec) string {
 | 
					 | 
				
			||||||
	n := s.(*ImportSpec).Name
 | 
					 | 
				
			||||||
	if n == nil {
 | 
					 | 
				
			||||||
		return ""
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return n.Name
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func importComment(s Spec) string {
 | 
					 | 
				
			||||||
	c := s.(*ImportSpec).Comment
 | 
					 | 
				
			||||||
	if c == nil {
 | 
					 | 
				
			||||||
		return ""
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return c.Text()
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// collapse indicates whether prev may be removed, leaving only next.
 | 
					 | 
				
			||||||
func collapse(prev, next Spec) bool {
 | 
					 | 
				
			||||||
	if importPath(next) != importPath(prev) || importName(next) != importName(prev) {
 | 
					 | 
				
			||||||
		return false
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return prev.(*ImportSpec).Comment == nil
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
type posSpan struct {
 | 
					 | 
				
			||||||
	Start token.Pos
 | 
					 | 
				
			||||||
	End   token.Pos
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func sortSpecs(fset *token.FileSet, f *File, specs []Spec) []Spec {
 | 
					 | 
				
			||||||
	// Can't short-circuit here even if specs are already sorted,
 | 
					 | 
				
			||||||
	// since they might yet need deduplication.
 | 
					 | 
				
			||||||
	// A lone import, however, may be safely ignored.
 | 
					 | 
				
			||||||
	if len(specs) <= 1 {
 | 
					 | 
				
			||||||
		return specs
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// Record positions for specs.
 | 
					 | 
				
			||||||
	pos := make([]posSpan, len(specs))
 | 
					 | 
				
			||||||
	for i, s := range specs {
 | 
					 | 
				
			||||||
		pos[i] = posSpan{s.Pos(), s.End()}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// Identify comments in this range.
 | 
					 | 
				
			||||||
	// Any comment from pos[0].Start to the final line counts.
 | 
					 | 
				
			||||||
	lastLine := fset.Position(pos[len(pos)-1].End).Line
 | 
					 | 
				
			||||||
	cstart := len(f.Comments)
 | 
					 | 
				
			||||||
	cend := len(f.Comments)
 | 
					 | 
				
			||||||
	for i, g := range f.Comments {
 | 
					 | 
				
			||||||
		if g.Pos() < pos[0].Start {
 | 
					 | 
				
			||||||
			continue
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		if i < cstart {
 | 
					 | 
				
			||||||
			cstart = i
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		if fset.Position(g.End()).Line > lastLine {
 | 
					 | 
				
			||||||
			cend = i
 | 
					 | 
				
			||||||
			break
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	comments := f.Comments[cstart:cend]
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// Assign each comment to the import spec preceding it.
 | 
					 | 
				
			||||||
	importComment := map[*ImportSpec][]*CommentGroup{}
 | 
					 | 
				
			||||||
	specIndex := 0
 | 
					 | 
				
			||||||
	for _, g := range comments {
 | 
					 | 
				
			||||||
		for specIndex+1 < len(specs) && pos[specIndex+1].Start <= g.Pos() {
 | 
					 | 
				
			||||||
			specIndex++
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		s := specs[specIndex].(*ImportSpec)
 | 
					 | 
				
			||||||
		importComment[s] = append(importComment[s], g)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// Sort the import specs by import path.
 | 
					 | 
				
			||||||
	// Remove duplicates, when possible without data loss.
 | 
					 | 
				
			||||||
	// Reassign the import paths to have the same position sequence.
 | 
					 | 
				
			||||||
	// Reassign each comment to abut the end of its spec.
 | 
					 | 
				
			||||||
	// Sort the comments by new position.
 | 
					 | 
				
			||||||
	sort.Sort(byImportSpec(specs))
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// Dedup. Thanks to our sorting, we can just consider
 | 
					 | 
				
			||||||
	// adjacent pairs of imports.
 | 
					 | 
				
			||||||
	deduped := specs[:0]
 | 
					 | 
				
			||||||
	for i, s := range specs {
 | 
					 | 
				
			||||||
		if i == len(specs)-1 || !collapse(s, specs[i+1]) {
 | 
					 | 
				
			||||||
			deduped = append(deduped, s)
 | 
					 | 
				
			||||||
		} else {
 | 
					 | 
				
			||||||
			p := s.Pos()
 | 
					 | 
				
			||||||
			fset.File(p).MergeLine(fset.Position(p).Line)
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	specs = deduped
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// Fix up comment positions
 | 
					 | 
				
			||||||
	for i, s := range specs {
 | 
					 | 
				
			||||||
		s := s.(*ImportSpec)
 | 
					 | 
				
			||||||
		if s.Name != nil {
 | 
					 | 
				
			||||||
			s.Name.NamePos = pos[i].Start
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		s.Path.ValuePos = pos[i].Start
 | 
					 | 
				
			||||||
		s.EndPos = pos[i].End
 | 
					 | 
				
			||||||
		for _, g := range importComment[s] {
 | 
					 | 
				
			||||||
			for _, c := range g.List {
 | 
					 | 
				
			||||||
				c.Slash = pos[i].End
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	sort.Sort(byCommentPos(comments))
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return specs
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
type byImportSpec []Spec // slice of *ImportSpec
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (x byImportSpec) Len() int      { return len(x) }
 | 
					 | 
				
			||||||
func (x byImportSpec) Swap(i, j int) { x[i], x[j] = x[j], x[i] }
 | 
					 | 
				
			||||||
func (x byImportSpec) Less(i, j int) bool {
 | 
					 | 
				
			||||||
	ipath := importPath(x[i])
 | 
					 | 
				
			||||||
	jpath := importPath(x[j])
 | 
					 | 
				
			||||||
	if ipath != jpath {
 | 
					 | 
				
			||||||
		return ipath < jpath
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	iname := importName(x[i])
 | 
					 | 
				
			||||||
	jname := importName(x[j])
 | 
					 | 
				
			||||||
	if iname != jname {
 | 
					 | 
				
			||||||
		return iname < jname
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return importComment(x[i]) < importComment(x[j])
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
type byCommentPos []*CommentGroup
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (x byCommentPos) Len() int           { return len(x) }
 | 
					 | 
				
			||||||
func (x byCommentPos) Swap(i, j int)      { x[i], x[j] = x[j], x[i] }
 | 
					 | 
				
			||||||
func (x byCommentPos) Less(i, j int) bool { return x[i].Pos() < x[j].Pos() }
 | 
					 | 
				
			||||||
							
								
								
									
										252
									
								
								third_party/golang/go/ast/print.go
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										252
									
								
								third_party/golang/go/ast/print.go
									
									
									
									
										vendored
									
									
								
							@@ -1,252 +0,0 @@
 | 
				
			|||||||
// Copyright 2010 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.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// This file contains printing support for ASTs.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
package ast
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
import (
 | 
					 | 
				
			||||||
	"fmt"
 | 
					 | 
				
			||||||
	"io"
 | 
					 | 
				
			||||||
	"os"
 | 
					 | 
				
			||||||
	"reflect"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	"k8s.io/kubernetes/third_party/golang/go/token"
 | 
					 | 
				
			||||||
)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// A FieldFilter may be provided to Fprint to control the output.
 | 
					 | 
				
			||||||
type FieldFilter func(name string, value reflect.Value) bool
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// NotNilFilter returns true for field values that are not nil;
 | 
					 | 
				
			||||||
// it returns false otherwise.
 | 
					 | 
				
			||||||
func NotNilFilter(_ string, v reflect.Value) bool {
 | 
					 | 
				
			||||||
	switch v.Kind() {
 | 
					 | 
				
			||||||
	case reflect.Chan, reflect.Func, reflect.Interface, reflect.Map, reflect.Ptr, reflect.Slice:
 | 
					 | 
				
			||||||
		return !v.IsNil()
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return true
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// Fprint prints the (sub-)tree starting at AST node x to w.
 | 
					 | 
				
			||||||
// If fset != nil, position information is interpreted relative
 | 
					 | 
				
			||||||
// to that file set. Otherwise positions are printed as integer
 | 
					 | 
				
			||||||
// values (file set specific offsets).
 | 
					 | 
				
			||||||
//
 | 
					 | 
				
			||||||
// A non-nil FieldFilter f may be provided to control the output:
 | 
					 | 
				
			||||||
// struct fields for which f(fieldname, fieldvalue) is true are
 | 
					 | 
				
			||||||
// printed; all others are filtered from the output. Unexported
 | 
					 | 
				
			||||||
// struct fields are never printed.
 | 
					 | 
				
			||||||
//
 | 
					 | 
				
			||||||
func Fprint(w io.Writer, fset *token.FileSet, x interface{}, f FieldFilter) (err error) {
 | 
					 | 
				
			||||||
	// setup printer
 | 
					 | 
				
			||||||
	p := printer{
 | 
					 | 
				
			||||||
		output: w,
 | 
					 | 
				
			||||||
		fset:   fset,
 | 
					 | 
				
			||||||
		filter: f,
 | 
					 | 
				
			||||||
		ptrmap: make(map[interface{}]int),
 | 
					 | 
				
			||||||
		last:   '\n', // force printing of line number on first line
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// install error handler
 | 
					 | 
				
			||||||
	defer func() {
 | 
					 | 
				
			||||||
		if e := recover(); e != nil {
 | 
					 | 
				
			||||||
			err = e.(localError).err // re-panics if it's not a localError
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}()
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// print x
 | 
					 | 
				
			||||||
	if x == nil {
 | 
					 | 
				
			||||||
		p.printf("nil\n")
 | 
					 | 
				
			||||||
		return
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	p.print(reflect.ValueOf(x))
 | 
					 | 
				
			||||||
	p.printf("\n")
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// Print prints x to standard output, skipping nil fields.
 | 
					 | 
				
			||||||
// Print(fset, x) is the same as Fprint(os.Stdout, fset, x, NotNilFilter).
 | 
					 | 
				
			||||||
func Print(fset *token.FileSet, x interface{}) error {
 | 
					 | 
				
			||||||
	return Fprint(os.Stdout, fset, x, NotNilFilter)
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
type printer struct {
 | 
					 | 
				
			||||||
	output io.Writer
 | 
					 | 
				
			||||||
	fset   *token.FileSet
 | 
					 | 
				
			||||||
	filter FieldFilter
 | 
					 | 
				
			||||||
	ptrmap map[interface{}]int // *T -> line number
 | 
					 | 
				
			||||||
	indent int                 // current indentation level
 | 
					 | 
				
			||||||
	last   byte                // the last byte processed by Write
 | 
					 | 
				
			||||||
	line   int                 // current line number
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
var indent = []byte(".  ")
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (p *printer) Write(data []byte) (n int, err error) {
 | 
					 | 
				
			||||||
	var m int
 | 
					 | 
				
			||||||
	for i, b := range data {
 | 
					 | 
				
			||||||
		// invariant: data[0:n] has been written
 | 
					 | 
				
			||||||
		if b == '\n' {
 | 
					 | 
				
			||||||
			m, err = p.output.Write(data[n : i+1])
 | 
					 | 
				
			||||||
			n += m
 | 
					 | 
				
			||||||
			if err != nil {
 | 
					 | 
				
			||||||
				return
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
			p.line++
 | 
					 | 
				
			||||||
		} else if p.last == '\n' {
 | 
					 | 
				
			||||||
			_, err = fmt.Fprintf(p.output, "%6d  ", p.line)
 | 
					 | 
				
			||||||
			if err != nil {
 | 
					 | 
				
			||||||
				return
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
			for j := p.indent; j > 0; j-- {
 | 
					 | 
				
			||||||
				_, err = p.output.Write(indent)
 | 
					 | 
				
			||||||
				if err != nil {
 | 
					 | 
				
			||||||
					return
 | 
					 | 
				
			||||||
				}
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		p.last = b
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	if len(data) > n {
 | 
					 | 
				
			||||||
		m, err = p.output.Write(data[n:])
 | 
					 | 
				
			||||||
		n += m
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// localError wraps locally caught errors so we can distinguish
 | 
					 | 
				
			||||||
// them from genuine panics which we don't want to return as errors.
 | 
					 | 
				
			||||||
type localError struct {
 | 
					 | 
				
			||||||
	err error
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// printf is a convenience wrapper that takes care of print errors.
 | 
					 | 
				
			||||||
func (p *printer) printf(format string, args ...interface{}) {
 | 
					 | 
				
			||||||
	if _, err := fmt.Fprintf(p, format, args...); err != nil {
 | 
					 | 
				
			||||||
		panic(localError{err})
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// Implementation note: Print is written for AST nodes but could be
 | 
					 | 
				
			||||||
// used to print arbitrary data structures; such a version should
 | 
					 | 
				
			||||||
// probably be in a different package.
 | 
					 | 
				
			||||||
//
 | 
					 | 
				
			||||||
// Note: This code detects (some) cycles created via pointers but
 | 
					 | 
				
			||||||
// not cycles that are created via slices or maps containing the
 | 
					 | 
				
			||||||
// same slice or map. Code for general data structures probably
 | 
					 | 
				
			||||||
// should catch those as well.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (p *printer) print(x reflect.Value) {
 | 
					 | 
				
			||||||
	if !NotNilFilter("", x) {
 | 
					 | 
				
			||||||
		p.printf("nil")
 | 
					 | 
				
			||||||
		return
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	switch x.Kind() {
 | 
					 | 
				
			||||||
	case reflect.Interface:
 | 
					 | 
				
			||||||
		p.print(x.Elem())
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	case reflect.Map:
 | 
					 | 
				
			||||||
		p.printf("%s (len = %d) {", x.Type(), x.Len())
 | 
					 | 
				
			||||||
		if x.Len() > 0 {
 | 
					 | 
				
			||||||
			p.indent++
 | 
					 | 
				
			||||||
			p.printf("\n")
 | 
					 | 
				
			||||||
			for _, key := range x.MapKeys() {
 | 
					 | 
				
			||||||
				p.print(key)
 | 
					 | 
				
			||||||
				p.printf(": ")
 | 
					 | 
				
			||||||
				p.print(x.MapIndex(key))
 | 
					 | 
				
			||||||
				p.printf("\n")
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
			p.indent--
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		p.printf("}")
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	case reflect.Ptr:
 | 
					 | 
				
			||||||
		p.printf("*")
 | 
					 | 
				
			||||||
		// type-checked ASTs may contain cycles - use ptrmap
 | 
					 | 
				
			||||||
		// to keep track of objects that have been printed
 | 
					 | 
				
			||||||
		// already and print the respective line number instead
 | 
					 | 
				
			||||||
		ptr := x.Interface()
 | 
					 | 
				
			||||||
		if line, exists := p.ptrmap[ptr]; exists {
 | 
					 | 
				
			||||||
			p.printf("(obj @ %d)", line)
 | 
					 | 
				
			||||||
		} else {
 | 
					 | 
				
			||||||
			p.ptrmap[ptr] = p.line
 | 
					 | 
				
			||||||
			p.print(x.Elem())
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	case reflect.Array:
 | 
					 | 
				
			||||||
		p.printf("%s {", x.Type())
 | 
					 | 
				
			||||||
		if x.Len() > 0 {
 | 
					 | 
				
			||||||
			p.indent++
 | 
					 | 
				
			||||||
			p.printf("\n")
 | 
					 | 
				
			||||||
			for i, n := 0, x.Len(); i < n; i++ {
 | 
					 | 
				
			||||||
				p.printf("%d: ", i)
 | 
					 | 
				
			||||||
				p.print(x.Index(i))
 | 
					 | 
				
			||||||
				p.printf("\n")
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
			p.indent--
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		p.printf("}")
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	case reflect.Slice:
 | 
					 | 
				
			||||||
		if s, ok := x.Interface().([]byte); ok {
 | 
					 | 
				
			||||||
			p.printf("%#q", s)
 | 
					 | 
				
			||||||
			return
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		p.printf("%s (len = %d) {", x.Type(), x.Len())
 | 
					 | 
				
			||||||
		if x.Len() > 0 {
 | 
					 | 
				
			||||||
			p.indent++
 | 
					 | 
				
			||||||
			p.printf("\n")
 | 
					 | 
				
			||||||
			for i, n := 0, x.Len(); i < n; i++ {
 | 
					 | 
				
			||||||
				p.printf("%d: ", i)
 | 
					 | 
				
			||||||
				p.print(x.Index(i))
 | 
					 | 
				
			||||||
				p.printf("\n")
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
			p.indent--
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		p.printf("}")
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	case reflect.Struct:
 | 
					 | 
				
			||||||
		t := x.Type()
 | 
					 | 
				
			||||||
		p.printf("%s {", t)
 | 
					 | 
				
			||||||
		p.indent++
 | 
					 | 
				
			||||||
		first := true
 | 
					 | 
				
			||||||
		for i, n := 0, t.NumField(); i < n; i++ {
 | 
					 | 
				
			||||||
			// exclude non-exported fields because their
 | 
					 | 
				
			||||||
			// values cannot be accessed via reflection
 | 
					 | 
				
			||||||
			if name := t.Field(i).Name; IsExported(name) {
 | 
					 | 
				
			||||||
				value := x.Field(i)
 | 
					 | 
				
			||||||
				if p.filter == nil || p.filter(name, value) {
 | 
					 | 
				
			||||||
					if first {
 | 
					 | 
				
			||||||
						p.printf("\n")
 | 
					 | 
				
			||||||
						first = false
 | 
					 | 
				
			||||||
					}
 | 
					 | 
				
			||||||
					p.printf("%s: ", name)
 | 
					 | 
				
			||||||
					p.print(value)
 | 
					 | 
				
			||||||
					p.printf("\n")
 | 
					 | 
				
			||||||
				}
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		p.indent--
 | 
					 | 
				
			||||||
		p.printf("}")
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	default:
 | 
					 | 
				
			||||||
		v := x.Interface()
 | 
					 | 
				
			||||||
		switch v := v.(type) {
 | 
					 | 
				
			||||||
		case string:
 | 
					 | 
				
			||||||
			// print strings in quotes
 | 
					 | 
				
			||||||
			p.printf("%q", v)
 | 
					 | 
				
			||||||
			return
 | 
					 | 
				
			||||||
		case token.Pos:
 | 
					 | 
				
			||||||
			// position values can be printed nicely if we have a file set
 | 
					 | 
				
			||||||
			if p.fset != nil {
 | 
					 | 
				
			||||||
				p.printf("%s", p.fset.Position(v))
 | 
					 | 
				
			||||||
				return
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		// default
 | 
					 | 
				
			||||||
		p.printf("%v", v)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
							
								
								
									
										97
									
								
								third_party/golang/go/ast/print_test.go
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										97
									
								
								third_party/golang/go/ast/print_test.go
									
									
									
									
										vendored
									
									
								
							@@ -1,97 +0,0 @@
 | 
				
			|||||||
// Copyright 2011 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 ast
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
import (
 | 
					 | 
				
			||||||
	"bytes"
 | 
					 | 
				
			||||||
	"strings"
 | 
					 | 
				
			||||||
	"testing"
 | 
					 | 
				
			||||||
)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
var tests = []struct {
 | 
					 | 
				
			||||||
	x interface{} // x is printed as s
 | 
					 | 
				
			||||||
	s string
 | 
					 | 
				
			||||||
}{
 | 
					 | 
				
			||||||
	// basic types
 | 
					 | 
				
			||||||
	{nil, "0  nil"},
 | 
					 | 
				
			||||||
	{true, "0  true"},
 | 
					 | 
				
			||||||
	{42, "0  42"},
 | 
					 | 
				
			||||||
	{3.14, "0  3.14"},
 | 
					 | 
				
			||||||
	{1 + 2.718i, "0  (1+2.718i)"},
 | 
					 | 
				
			||||||
	{"foobar", "0  \"foobar\""},
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// maps
 | 
					 | 
				
			||||||
	{map[Expr]string{}, `0  map[ast.Expr]string (len = 0) {}`},
 | 
					 | 
				
			||||||
	{map[string]int{"a": 1},
 | 
					 | 
				
			||||||
		`0  map[string]int (len = 1) {
 | 
					 | 
				
			||||||
		1  .  "a": 1
 | 
					 | 
				
			||||||
		2  }`},
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// pointers
 | 
					 | 
				
			||||||
	{new(int), "0  *0"},
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// arrays
 | 
					 | 
				
			||||||
	{[0]int{}, `0  [0]int {}`},
 | 
					 | 
				
			||||||
	{[3]int{1, 2, 3},
 | 
					 | 
				
			||||||
		`0  [3]int {
 | 
					 | 
				
			||||||
		1  .  0: 1
 | 
					 | 
				
			||||||
		2  .  1: 2
 | 
					 | 
				
			||||||
		3  .  2: 3
 | 
					 | 
				
			||||||
		4  }`},
 | 
					 | 
				
			||||||
	{[...]int{42},
 | 
					 | 
				
			||||||
		`0  [1]int {
 | 
					 | 
				
			||||||
		1  .  0: 42
 | 
					 | 
				
			||||||
		2  }`},
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// slices
 | 
					 | 
				
			||||||
	{[]int{}, `0  []int (len = 0) {}`},
 | 
					 | 
				
			||||||
	{[]int{1, 2, 3},
 | 
					 | 
				
			||||||
		`0  []int (len = 3) {
 | 
					 | 
				
			||||||
		1  .  0: 1
 | 
					 | 
				
			||||||
		2  .  1: 2
 | 
					 | 
				
			||||||
		3  .  2: 3
 | 
					 | 
				
			||||||
		4  }`},
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// structs
 | 
					 | 
				
			||||||
	{struct{}{}, `0  struct {} {}`},
 | 
					 | 
				
			||||||
	{struct{ x int }{007}, `0  struct { x int } {}`},
 | 
					 | 
				
			||||||
	{struct{ X, y int }{42, 991},
 | 
					 | 
				
			||||||
		`0  struct { X int; y int } {
 | 
					 | 
				
			||||||
		1  .  X: 42
 | 
					 | 
				
			||||||
		2  }`},
 | 
					 | 
				
			||||||
	{struct{ X, Y int }{42, 991},
 | 
					 | 
				
			||||||
		`0  struct { X int; Y int } {
 | 
					 | 
				
			||||||
		1  .  X: 42
 | 
					 | 
				
			||||||
		2  .  Y: 991
 | 
					 | 
				
			||||||
		3  }`},
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// Split s into lines, trim whitespace from all lines, and return
 | 
					 | 
				
			||||||
// the concatenated non-empty lines.
 | 
					 | 
				
			||||||
func trim(s string) string {
 | 
					 | 
				
			||||||
	lines := strings.Split(s, "\n")
 | 
					 | 
				
			||||||
	i := 0
 | 
					 | 
				
			||||||
	for _, line := range lines {
 | 
					 | 
				
			||||||
		line = strings.TrimSpace(line)
 | 
					 | 
				
			||||||
		if line != "" {
 | 
					 | 
				
			||||||
			lines[i] = line
 | 
					 | 
				
			||||||
			i++
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return strings.Join(lines[0:i], "\n")
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func TestPrint(t *testing.T) {
 | 
					 | 
				
			||||||
	var buf bytes.Buffer
 | 
					 | 
				
			||||||
	for _, test := range tests {
 | 
					 | 
				
			||||||
		buf.Reset()
 | 
					 | 
				
			||||||
		if err := Fprint(&buf, nil, test.x, nil); err != nil {
 | 
					 | 
				
			||||||
			t.Errorf("Fprint failed: %s", err)
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		if s, ts := trim(buf.String()), trim(test.s); s != ts {
 | 
					 | 
				
			||||||
			t.Errorf("got:\n%s\nexpected:\n%s\n", s, ts)
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
							
								
								
									
										174
									
								
								third_party/golang/go/ast/resolve.go
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										174
									
								
								third_party/golang/go/ast/resolve.go
									
									
									
									
										vendored
									
									
								
							@@ -1,174 +0,0 @@
 | 
				
			|||||||
// Copyright 2011 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.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// This file implements NewPackage.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
package ast
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
import (
 | 
					 | 
				
			||||||
	"fmt"
 | 
					 | 
				
			||||||
	"k8s.io/kubernetes/third_party/golang/go/scanner"
 | 
					 | 
				
			||||||
	"k8s.io/kubernetes/third_party/golang/go/token"
 | 
					 | 
				
			||||||
	"strconv"
 | 
					 | 
				
			||||||
)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
type pkgBuilder struct {
 | 
					 | 
				
			||||||
	fset   *token.FileSet
 | 
					 | 
				
			||||||
	errors scanner.ErrorList
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (p *pkgBuilder) error(pos token.Pos, msg string) {
 | 
					 | 
				
			||||||
	p.errors.Add(p.fset.Position(pos), msg)
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (p *pkgBuilder) errorf(pos token.Pos, format string, args ...interface{}) {
 | 
					 | 
				
			||||||
	p.error(pos, fmt.Sprintf(format, args...))
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (p *pkgBuilder) declare(scope, altScope *Scope, obj *Object) {
 | 
					 | 
				
			||||||
	alt := scope.Insert(obj)
 | 
					 | 
				
			||||||
	if alt == nil && altScope != nil {
 | 
					 | 
				
			||||||
		// see if there is a conflicting declaration in altScope
 | 
					 | 
				
			||||||
		alt = altScope.Lookup(obj.Name)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	if alt != nil {
 | 
					 | 
				
			||||||
		prevDecl := ""
 | 
					 | 
				
			||||||
		if pos := alt.Pos(); pos.IsValid() {
 | 
					 | 
				
			||||||
			prevDecl = fmt.Sprintf("\n\tprevious declaration at %s", p.fset.Position(pos))
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		p.error(obj.Pos(), fmt.Sprintf("%s redeclared in this block%s", obj.Name, prevDecl))
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func resolve(scope *Scope, ident *Ident) bool {
 | 
					 | 
				
			||||||
	for ; scope != nil; scope = scope.Outer {
 | 
					 | 
				
			||||||
		if obj := scope.Lookup(ident.Name); obj != nil {
 | 
					 | 
				
			||||||
			ident.Obj = obj
 | 
					 | 
				
			||||||
			return true
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return false
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// An Importer resolves import paths to package Objects.
 | 
					 | 
				
			||||||
// The imports map records the packages already imported,
 | 
					 | 
				
			||||||
// indexed by package id (canonical import path).
 | 
					 | 
				
			||||||
// An Importer must determine the canonical import path and
 | 
					 | 
				
			||||||
// check the map to see if it is already present in the imports map.
 | 
					 | 
				
			||||||
// If so, the Importer can return the map entry.  Otherwise, the
 | 
					 | 
				
			||||||
// Importer should load the package data for the given path into
 | 
					 | 
				
			||||||
// a new *Object (pkg), record pkg in the imports map, and then
 | 
					 | 
				
			||||||
// return pkg.
 | 
					 | 
				
			||||||
type Importer func(imports map[string]*Object, path string) (pkg *Object, err error)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// NewPackage creates a new Package node from a set of File nodes. It resolves
 | 
					 | 
				
			||||||
// unresolved identifiers across files and updates each file's Unresolved list
 | 
					 | 
				
			||||||
// accordingly. If a non-nil importer and universe scope are provided, they are
 | 
					 | 
				
			||||||
// used to resolve identifiers not declared in any of the package files. Any
 | 
					 | 
				
			||||||
// remaining unresolved identifiers are reported as undeclared. If the files
 | 
					 | 
				
			||||||
// belong to different packages, one package name is selected and files with
 | 
					 | 
				
			||||||
// different package names are reported and then ignored.
 | 
					 | 
				
			||||||
// The result is a package node and a scanner.ErrorList if there were errors.
 | 
					 | 
				
			||||||
//
 | 
					 | 
				
			||||||
func NewPackage(fset *token.FileSet, files map[string]*File, importer Importer, universe *Scope) (*Package, error) {
 | 
					 | 
				
			||||||
	var p pkgBuilder
 | 
					 | 
				
			||||||
	p.fset = fset
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// complete package scope
 | 
					 | 
				
			||||||
	pkgName := ""
 | 
					 | 
				
			||||||
	pkgScope := NewScope(universe)
 | 
					 | 
				
			||||||
	for _, file := range files {
 | 
					 | 
				
			||||||
		// package names must match
 | 
					 | 
				
			||||||
		switch name := file.Name.Name; {
 | 
					 | 
				
			||||||
		case pkgName == "":
 | 
					 | 
				
			||||||
			pkgName = name
 | 
					 | 
				
			||||||
		case name != pkgName:
 | 
					 | 
				
			||||||
			p.errorf(file.Package, "package %s; expected %s", name, pkgName)
 | 
					 | 
				
			||||||
			continue // ignore this file
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		// collect top-level file objects in package scope
 | 
					 | 
				
			||||||
		for _, obj := range file.Scope.Objects {
 | 
					 | 
				
			||||||
			p.declare(pkgScope, nil, obj)
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// package global mapping of imported package ids to package objects
 | 
					 | 
				
			||||||
	imports := make(map[string]*Object)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// complete file scopes with imports and resolve identifiers
 | 
					 | 
				
			||||||
	for _, file := range files {
 | 
					 | 
				
			||||||
		// ignore file if it belongs to a different package
 | 
					 | 
				
			||||||
		// (error has already been reported)
 | 
					 | 
				
			||||||
		if file.Name.Name != pkgName {
 | 
					 | 
				
			||||||
			continue
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		// build file scope by processing all imports
 | 
					 | 
				
			||||||
		importErrors := false
 | 
					 | 
				
			||||||
		fileScope := NewScope(pkgScope)
 | 
					 | 
				
			||||||
		for _, spec := range file.Imports {
 | 
					 | 
				
			||||||
			if importer == nil {
 | 
					 | 
				
			||||||
				importErrors = true
 | 
					 | 
				
			||||||
				continue
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
			path, _ := strconv.Unquote(spec.Path.Value)
 | 
					 | 
				
			||||||
			pkg, err := importer(imports, path)
 | 
					 | 
				
			||||||
			if err != nil {
 | 
					 | 
				
			||||||
				p.errorf(spec.Path.Pos(), "could not import %s (%s)", path, err)
 | 
					 | 
				
			||||||
				importErrors = true
 | 
					 | 
				
			||||||
				continue
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
			// TODO(gri) If a local package name != "." is provided,
 | 
					 | 
				
			||||||
			// global identifier resolution could proceed even if the
 | 
					 | 
				
			||||||
			// import failed. Consider adjusting the logic here a bit.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			// local name overrides imported package name
 | 
					 | 
				
			||||||
			name := pkg.Name
 | 
					 | 
				
			||||||
			if spec.Name != nil {
 | 
					 | 
				
			||||||
				name = spec.Name.Name
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			// add import to file scope
 | 
					 | 
				
			||||||
			if name == "." {
 | 
					 | 
				
			||||||
				// merge imported scope with file scope
 | 
					 | 
				
			||||||
				for _, obj := range pkg.Data.(*Scope).Objects {
 | 
					 | 
				
			||||||
					p.declare(fileScope, pkgScope, obj)
 | 
					 | 
				
			||||||
				}
 | 
					 | 
				
			||||||
			} else if name != "_" {
 | 
					 | 
				
			||||||
				// declare imported package object in file scope
 | 
					 | 
				
			||||||
				// (do not re-use pkg in the file scope but create
 | 
					 | 
				
			||||||
				// a new object instead; the Decl field is different
 | 
					 | 
				
			||||||
				// for different files)
 | 
					 | 
				
			||||||
				obj := NewObj(Pkg, name)
 | 
					 | 
				
			||||||
				obj.Decl = spec
 | 
					 | 
				
			||||||
				obj.Data = pkg.Data
 | 
					 | 
				
			||||||
				p.declare(fileScope, pkgScope, obj)
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		// resolve identifiers
 | 
					 | 
				
			||||||
		if importErrors {
 | 
					 | 
				
			||||||
			// don't use the universe scope without correct imports
 | 
					 | 
				
			||||||
			// (objects in the universe may be shadowed by imports;
 | 
					 | 
				
			||||||
			// with missing imports, identifiers might get resolved
 | 
					 | 
				
			||||||
			// incorrectly to universe objects)
 | 
					 | 
				
			||||||
			pkgScope.Outer = nil
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		i := 0
 | 
					 | 
				
			||||||
		for _, ident := range file.Unresolved {
 | 
					 | 
				
			||||||
			if !resolve(fileScope, ident) {
 | 
					 | 
				
			||||||
				p.errorf(ident.Pos(), "undeclared name: %s", ident.Name)
 | 
					 | 
				
			||||||
				file.Unresolved[i] = ident
 | 
					 | 
				
			||||||
				i++
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		file.Unresolved = file.Unresolved[0:i]
 | 
					 | 
				
			||||||
		pkgScope.Outer = universe // reset universe scope
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	p.errors.Sort()
 | 
					 | 
				
			||||||
	return &Package{pkgName, pkgScope, imports, files}, p.errors.Err()
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
							
								
								
									
										163
									
								
								third_party/golang/go/ast/scope.go
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										163
									
								
								third_party/golang/go/ast/scope.go
									
									
									
									
										vendored
									
									
								
							@@ -1,163 +0,0 @@
 | 
				
			|||||||
// Copyright 2009 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.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// This file implements scopes and the objects they contain.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
package ast
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
import (
 | 
					 | 
				
			||||||
	"bytes"
 | 
					 | 
				
			||||||
	"fmt"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	"k8s.io/kubernetes/third_party/golang/go/token"
 | 
					 | 
				
			||||||
)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// A Scope maintains the set of named language entities declared
 | 
					 | 
				
			||||||
// in the scope and a link to the immediately surrounding (outer)
 | 
					 | 
				
			||||||
// scope.
 | 
					 | 
				
			||||||
//
 | 
					 | 
				
			||||||
type Scope struct {
 | 
					 | 
				
			||||||
	Outer   *Scope
 | 
					 | 
				
			||||||
	Objects map[string]*Object
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// NewScope creates a new scope nested in the outer scope.
 | 
					 | 
				
			||||||
func NewScope(outer *Scope) *Scope {
 | 
					 | 
				
			||||||
	const n = 4 // initial scope capacity
 | 
					 | 
				
			||||||
	return &Scope{outer, make(map[string]*Object, n)}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// Lookup returns the object with the given name if it is
 | 
					 | 
				
			||||||
// found in scope s, otherwise it returns nil. Outer scopes
 | 
					 | 
				
			||||||
// are ignored.
 | 
					 | 
				
			||||||
//
 | 
					 | 
				
			||||||
func (s *Scope) Lookup(name string) *Object {
 | 
					 | 
				
			||||||
	return s.Objects[name]
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// Insert attempts to insert a named object obj into the scope s.
 | 
					 | 
				
			||||||
// If the scope already contains an object alt with the same name,
 | 
					 | 
				
			||||||
// Insert leaves the scope unchanged and returns alt. Otherwise
 | 
					 | 
				
			||||||
// it inserts obj and returns nil.
 | 
					 | 
				
			||||||
//
 | 
					 | 
				
			||||||
func (s *Scope) Insert(obj *Object) (alt *Object) {
 | 
					 | 
				
			||||||
	if alt = s.Objects[obj.Name]; alt == nil {
 | 
					 | 
				
			||||||
		s.Objects[obj.Name] = obj
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// Debugging support
 | 
					 | 
				
			||||||
func (s *Scope) String() string {
 | 
					 | 
				
			||||||
	var buf bytes.Buffer
 | 
					 | 
				
			||||||
	fmt.Fprintf(&buf, "scope %p {", s)
 | 
					 | 
				
			||||||
	if s != nil && len(s.Objects) > 0 {
 | 
					 | 
				
			||||||
		fmt.Fprintln(&buf)
 | 
					 | 
				
			||||||
		for _, obj := range s.Objects {
 | 
					 | 
				
			||||||
			fmt.Fprintf(&buf, "\t%s %s\n", obj.Kind, obj.Name)
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	fmt.Fprintf(&buf, "}\n")
 | 
					 | 
				
			||||||
	return buf.String()
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// ----------------------------------------------------------------------------
 | 
					 | 
				
			||||||
// Objects
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// An Object describes a named language entity such as a package,
 | 
					 | 
				
			||||||
// constant, type, variable, function (incl. methods), or label.
 | 
					 | 
				
			||||||
//
 | 
					 | 
				
			||||||
// The Data fields contains object-specific data:
 | 
					 | 
				
			||||||
//
 | 
					 | 
				
			||||||
//	Kind    Data type         Data value
 | 
					 | 
				
			||||||
//	Pkg	*types.Package    package scope
 | 
					 | 
				
			||||||
//	Con     int               iota for the respective declaration
 | 
					 | 
				
			||||||
//	Con     != nil            constant value
 | 
					 | 
				
			||||||
//	Typ     *Scope            (used as method scope during type checking - transient)
 | 
					 | 
				
			||||||
//
 | 
					 | 
				
			||||||
type Object struct {
 | 
					 | 
				
			||||||
	Kind ObjKind
 | 
					 | 
				
			||||||
	Name string      // declared name
 | 
					 | 
				
			||||||
	Decl interface{} // corresponding Field, XxxSpec, FuncDecl, LabeledStmt, AssignStmt, Scope; or nil
 | 
					 | 
				
			||||||
	Data interface{} // object-specific data; or nil
 | 
					 | 
				
			||||||
	Type interface{} // placeholder for type information; may be nil
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// NewObj creates a new object of a given kind and name.
 | 
					 | 
				
			||||||
func NewObj(kind ObjKind, name string) *Object {
 | 
					 | 
				
			||||||
	return &Object{Kind: kind, Name: name}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// Pos computes the source position of the declaration of an object name.
 | 
					 | 
				
			||||||
// The result may be an invalid position if it cannot be computed
 | 
					 | 
				
			||||||
// (obj.Decl may be nil or not correct).
 | 
					 | 
				
			||||||
func (obj *Object) Pos() token.Pos {
 | 
					 | 
				
			||||||
	name := obj.Name
 | 
					 | 
				
			||||||
	switch d := obj.Decl.(type) {
 | 
					 | 
				
			||||||
	case *Field:
 | 
					 | 
				
			||||||
		for _, n := range d.Names {
 | 
					 | 
				
			||||||
			if n.Name == name {
 | 
					 | 
				
			||||||
				return n.Pos()
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	case *ImportSpec:
 | 
					 | 
				
			||||||
		if d.Name != nil && d.Name.Name == name {
 | 
					 | 
				
			||||||
			return d.Name.Pos()
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		return d.Path.Pos()
 | 
					 | 
				
			||||||
	case *ValueSpec:
 | 
					 | 
				
			||||||
		for _, n := range d.Names {
 | 
					 | 
				
			||||||
			if n.Name == name {
 | 
					 | 
				
			||||||
				return n.Pos()
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	case *TypeSpec:
 | 
					 | 
				
			||||||
		if d.Name.Name == name {
 | 
					 | 
				
			||||||
			return d.Name.Pos()
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	case *FuncDecl:
 | 
					 | 
				
			||||||
		if d.Name.Name == name {
 | 
					 | 
				
			||||||
			return d.Name.Pos()
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	case *LabeledStmt:
 | 
					 | 
				
			||||||
		if d.Label.Name == name {
 | 
					 | 
				
			||||||
			return d.Label.Pos()
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	case *AssignStmt:
 | 
					 | 
				
			||||||
		for _, x := range d.Lhs {
 | 
					 | 
				
			||||||
			if ident, isIdent := x.(*Ident); isIdent && ident.Name == name {
 | 
					 | 
				
			||||||
				return ident.Pos()
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	case *Scope:
 | 
					 | 
				
			||||||
		// predeclared object - nothing to do for now
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return token.NoPos
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// ObjKind describes what an object represents.
 | 
					 | 
				
			||||||
type ObjKind int
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// The list of possible Object kinds.
 | 
					 | 
				
			||||||
const (
 | 
					 | 
				
			||||||
	Bad ObjKind = iota // for error handling
 | 
					 | 
				
			||||||
	Pkg                // package
 | 
					 | 
				
			||||||
	Con                // constant
 | 
					 | 
				
			||||||
	Typ                // type
 | 
					 | 
				
			||||||
	Var                // variable
 | 
					 | 
				
			||||||
	Fun                // function or method
 | 
					 | 
				
			||||||
	Lbl                // label
 | 
					 | 
				
			||||||
)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
var objKindStrings = [...]string{
 | 
					 | 
				
			||||||
	Bad: "bad",
 | 
					 | 
				
			||||||
	Pkg: "package",
 | 
					 | 
				
			||||||
	Con: "const",
 | 
					 | 
				
			||||||
	Typ: "type",
 | 
					 | 
				
			||||||
	Var: "var",
 | 
					 | 
				
			||||||
	Fun: "func",
 | 
					 | 
				
			||||||
	Lbl: "label",
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (kind ObjKind) String() string { return objKindStrings[kind] }
 | 
					 | 
				
			||||||
							
								
								
									
										386
									
								
								third_party/golang/go/ast/walk.go
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										386
									
								
								third_party/golang/go/ast/walk.go
									
									
									
									
										vendored
									
									
								
							@@ -1,386 +0,0 @@
 | 
				
			|||||||
// Copyright 2009 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 ast
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
import "fmt"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// A Visitor's Visit method is invoked for each node encountered by Walk.
 | 
					 | 
				
			||||||
// If the result visitor w is not nil, Walk visits each of the children
 | 
					 | 
				
			||||||
// of node with the visitor w, followed by a call of w.Visit(nil).
 | 
					 | 
				
			||||||
type Visitor interface {
 | 
					 | 
				
			||||||
	Visit(node Node) (w Visitor)
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// Helper functions for common node lists. They may be empty.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func walkIdentList(v Visitor, list []*Ident) {
 | 
					 | 
				
			||||||
	for _, x := range list {
 | 
					 | 
				
			||||||
		Walk(v, x)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func walkExprList(v Visitor, list []Expr) {
 | 
					 | 
				
			||||||
	for _, x := range list {
 | 
					 | 
				
			||||||
		Walk(v, x)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func walkStmtList(v Visitor, list []Stmt) {
 | 
					 | 
				
			||||||
	for _, x := range list {
 | 
					 | 
				
			||||||
		Walk(v, x)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func walkDeclList(v Visitor, list []Decl) {
 | 
					 | 
				
			||||||
	for _, x := range list {
 | 
					 | 
				
			||||||
		Walk(v, x)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// TODO(gri): Investigate if providing a closure to Walk leads to
 | 
					 | 
				
			||||||
//            simpler use (and may help eliminate Inspect in turn).
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// Walk traverses an AST in depth-first order: It starts by calling
 | 
					 | 
				
			||||||
// v.Visit(node); node must not be nil. If the visitor w returned by
 | 
					 | 
				
			||||||
// v.Visit(node) is not nil, Walk is invoked recursively with visitor
 | 
					 | 
				
			||||||
// w for each of the non-nil children of node, followed by a call of
 | 
					 | 
				
			||||||
// w.Visit(nil).
 | 
					 | 
				
			||||||
//
 | 
					 | 
				
			||||||
func Walk(v Visitor, node Node) {
 | 
					 | 
				
			||||||
	if v = v.Visit(node); v == nil {
 | 
					 | 
				
			||||||
		return
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// walk children
 | 
					 | 
				
			||||||
	// (the order of the cases matches the order
 | 
					 | 
				
			||||||
	// of the corresponding node types in ast.go)
 | 
					 | 
				
			||||||
	switch n := node.(type) {
 | 
					 | 
				
			||||||
	// Comments and fields
 | 
					 | 
				
			||||||
	case *Comment:
 | 
					 | 
				
			||||||
		// nothing to do
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	case *CommentGroup:
 | 
					 | 
				
			||||||
		for _, c := range n.List {
 | 
					 | 
				
			||||||
			Walk(v, c)
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	case *Field:
 | 
					 | 
				
			||||||
		if n.Doc != nil {
 | 
					 | 
				
			||||||
			Walk(v, n.Doc)
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		walkIdentList(v, n.Names)
 | 
					 | 
				
			||||||
		Walk(v, n.Type)
 | 
					 | 
				
			||||||
		if n.Tag != nil {
 | 
					 | 
				
			||||||
			Walk(v, n.Tag)
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		if n.Comment != nil {
 | 
					 | 
				
			||||||
			Walk(v, n.Comment)
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	case *FieldList:
 | 
					 | 
				
			||||||
		for _, f := range n.List {
 | 
					 | 
				
			||||||
			Walk(v, f)
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// Expressions
 | 
					 | 
				
			||||||
	case *BadExpr, *Ident, *BasicLit:
 | 
					 | 
				
			||||||
		// nothing to do
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	case *Ellipsis:
 | 
					 | 
				
			||||||
		if n.Elt != nil {
 | 
					 | 
				
			||||||
			Walk(v, n.Elt)
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	case *FuncLit:
 | 
					 | 
				
			||||||
		Walk(v, n.Type)
 | 
					 | 
				
			||||||
		Walk(v, n.Body)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	case *CompositeLit:
 | 
					 | 
				
			||||||
		if n.Type != nil {
 | 
					 | 
				
			||||||
			Walk(v, n.Type)
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		walkExprList(v, n.Elts)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	case *ParenExpr:
 | 
					 | 
				
			||||||
		Walk(v, n.X)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	case *SelectorExpr:
 | 
					 | 
				
			||||||
		Walk(v, n.X)
 | 
					 | 
				
			||||||
		Walk(v, n.Sel)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	case *IndexExpr:
 | 
					 | 
				
			||||||
		Walk(v, n.X)
 | 
					 | 
				
			||||||
		Walk(v, n.Index)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	case *SliceExpr:
 | 
					 | 
				
			||||||
		Walk(v, n.X)
 | 
					 | 
				
			||||||
		if n.Low != nil {
 | 
					 | 
				
			||||||
			Walk(v, n.Low)
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		if n.High != nil {
 | 
					 | 
				
			||||||
			Walk(v, n.High)
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		if n.Max != nil {
 | 
					 | 
				
			||||||
			Walk(v, n.Max)
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	case *TypeAssertExpr:
 | 
					 | 
				
			||||||
		Walk(v, n.X)
 | 
					 | 
				
			||||||
		if n.Type != nil {
 | 
					 | 
				
			||||||
			Walk(v, n.Type)
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	case *CallExpr:
 | 
					 | 
				
			||||||
		Walk(v, n.Fun)
 | 
					 | 
				
			||||||
		walkExprList(v, n.Args)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	case *StarExpr:
 | 
					 | 
				
			||||||
		Walk(v, n.X)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	case *UnaryExpr:
 | 
					 | 
				
			||||||
		Walk(v, n.X)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	case *BinaryExpr:
 | 
					 | 
				
			||||||
		Walk(v, n.X)
 | 
					 | 
				
			||||||
		Walk(v, n.Y)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	case *KeyValueExpr:
 | 
					 | 
				
			||||||
		Walk(v, n.Key)
 | 
					 | 
				
			||||||
		Walk(v, n.Value)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// Types
 | 
					 | 
				
			||||||
	case *ArrayType:
 | 
					 | 
				
			||||||
		if n.Len != nil {
 | 
					 | 
				
			||||||
			Walk(v, n.Len)
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		Walk(v, n.Elt)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	case *StructType:
 | 
					 | 
				
			||||||
		Walk(v, n.Fields)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	case *FuncType:
 | 
					 | 
				
			||||||
		if n.Params != nil {
 | 
					 | 
				
			||||||
			Walk(v, n.Params)
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		if n.Results != nil {
 | 
					 | 
				
			||||||
			Walk(v, n.Results)
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	case *InterfaceType:
 | 
					 | 
				
			||||||
		Walk(v, n.Methods)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	case *MapType:
 | 
					 | 
				
			||||||
		Walk(v, n.Key)
 | 
					 | 
				
			||||||
		Walk(v, n.Value)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	case *ChanType:
 | 
					 | 
				
			||||||
		Walk(v, n.Value)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// Statements
 | 
					 | 
				
			||||||
	case *BadStmt:
 | 
					 | 
				
			||||||
		// nothing to do
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	case *DeclStmt:
 | 
					 | 
				
			||||||
		Walk(v, n.Decl)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	case *EmptyStmt:
 | 
					 | 
				
			||||||
		// nothing to do
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	case *LabeledStmt:
 | 
					 | 
				
			||||||
		Walk(v, n.Label)
 | 
					 | 
				
			||||||
		Walk(v, n.Stmt)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	case *ExprStmt:
 | 
					 | 
				
			||||||
		Walk(v, n.X)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	case *SendStmt:
 | 
					 | 
				
			||||||
		Walk(v, n.Chan)
 | 
					 | 
				
			||||||
		Walk(v, n.Value)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	case *IncDecStmt:
 | 
					 | 
				
			||||||
		Walk(v, n.X)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	case *AssignStmt:
 | 
					 | 
				
			||||||
		walkExprList(v, n.Lhs)
 | 
					 | 
				
			||||||
		walkExprList(v, n.Rhs)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	case *GoStmt:
 | 
					 | 
				
			||||||
		Walk(v, n.Call)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	case *DeferStmt:
 | 
					 | 
				
			||||||
		Walk(v, n.Call)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	case *ReturnStmt:
 | 
					 | 
				
			||||||
		walkExprList(v, n.Results)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	case *BranchStmt:
 | 
					 | 
				
			||||||
		if n.Label != nil {
 | 
					 | 
				
			||||||
			Walk(v, n.Label)
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	case *BlockStmt:
 | 
					 | 
				
			||||||
		walkStmtList(v, n.List)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	case *IfStmt:
 | 
					 | 
				
			||||||
		if n.Init != nil {
 | 
					 | 
				
			||||||
			Walk(v, n.Init)
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		Walk(v, n.Cond)
 | 
					 | 
				
			||||||
		Walk(v, n.Body)
 | 
					 | 
				
			||||||
		if n.Else != nil {
 | 
					 | 
				
			||||||
			Walk(v, n.Else)
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	case *CaseClause:
 | 
					 | 
				
			||||||
		walkExprList(v, n.List)
 | 
					 | 
				
			||||||
		walkStmtList(v, n.Body)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	case *SwitchStmt:
 | 
					 | 
				
			||||||
		if n.Init != nil {
 | 
					 | 
				
			||||||
			Walk(v, n.Init)
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		if n.Tag != nil {
 | 
					 | 
				
			||||||
			Walk(v, n.Tag)
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		Walk(v, n.Body)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	case *TypeSwitchStmt:
 | 
					 | 
				
			||||||
		if n.Init != nil {
 | 
					 | 
				
			||||||
			Walk(v, n.Init)
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		Walk(v, n.Assign)
 | 
					 | 
				
			||||||
		Walk(v, n.Body)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	case *CommClause:
 | 
					 | 
				
			||||||
		if n.Comm != nil {
 | 
					 | 
				
			||||||
			Walk(v, n.Comm)
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		walkStmtList(v, n.Body)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	case *SelectStmt:
 | 
					 | 
				
			||||||
		Walk(v, n.Body)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	case *ForStmt:
 | 
					 | 
				
			||||||
		if n.Init != nil {
 | 
					 | 
				
			||||||
			Walk(v, n.Init)
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		if n.Cond != nil {
 | 
					 | 
				
			||||||
			Walk(v, n.Cond)
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		if n.Post != nil {
 | 
					 | 
				
			||||||
			Walk(v, n.Post)
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		Walk(v, n.Body)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	case *RangeStmt:
 | 
					 | 
				
			||||||
		if n.Key != nil {
 | 
					 | 
				
			||||||
			Walk(v, n.Key)
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		if n.Value != nil {
 | 
					 | 
				
			||||||
			Walk(v, n.Value)
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		Walk(v, n.X)
 | 
					 | 
				
			||||||
		Walk(v, n.Body)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// Declarations
 | 
					 | 
				
			||||||
	case *ImportSpec:
 | 
					 | 
				
			||||||
		if n.Doc != nil {
 | 
					 | 
				
			||||||
			Walk(v, n.Doc)
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		if n.Name != nil {
 | 
					 | 
				
			||||||
			Walk(v, n.Name)
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		Walk(v, n.Path)
 | 
					 | 
				
			||||||
		if n.Comment != nil {
 | 
					 | 
				
			||||||
			Walk(v, n.Comment)
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	case *ValueSpec:
 | 
					 | 
				
			||||||
		if n.Doc != nil {
 | 
					 | 
				
			||||||
			Walk(v, n.Doc)
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		walkIdentList(v, n.Names)
 | 
					 | 
				
			||||||
		if n.Type != nil {
 | 
					 | 
				
			||||||
			Walk(v, n.Type)
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		walkExprList(v, n.Values)
 | 
					 | 
				
			||||||
		if n.Comment != nil {
 | 
					 | 
				
			||||||
			Walk(v, n.Comment)
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	case *TypeSpec:
 | 
					 | 
				
			||||||
		if n.Doc != nil {
 | 
					 | 
				
			||||||
			Walk(v, n.Doc)
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		Walk(v, n.Name)
 | 
					 | 
				
			||||||
		Walk(v, n.Type)
 | 
					 | 
				
			||||||
		if n.Comment != nil {
 | 
					 | 
				
			||||||
			Walk(v, n.Comment)
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	case *BadDecl:
 | 
					 | 
				
			||||||
		// nothing to do
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	case *GenDecl:
 | 
					 | 
				
			||||||
		if n.Doc != nil {
 | 
					 | 
				
			||||||
			Walk(v, n.Doc)
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		for _, s := range n.Specs {
 | 
					 | 
				
			||||||
			Walk(v, s)
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	case *FuncDecl:
 | 
					 | 
				
			||||||
		if n.Doc != nil {
 | 
					 | 
				
			||||||
			Walk(v, n.Doc)
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		if n.Recv != nil {
 | 
					 | 
				
			||||||
			Walk(v, n.Recv)
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		Walk(v, n.Name)
 | 
					 | 
				
			||||||
		Walk(v, n.Type)
 | 
					 | 
				
			||||||
		if n.Body != nil {
 | 
					 | 
				
			||||||
			Walk(v, n.Body)
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// Files and packages
 | 
					 | 
				
			||||||
	case *File:
 | 
					 | 
				
			||||||
		if n.Doc != nil {
 | 
					 | 
				
			||||||
			Walk(v, n.Doc)
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		Walk(v, n.Name)
 | 
					 | 
				
			||||||
		walkDeclList(v, n.Decls)
 | 
					 | 
				
			||||||
		// don't walk n.Comments - they have been
 | 
					 | 
				
			||||||
		// visited already through the individual
 | 
					 | 
				
			||||||
		// nodes
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	case *Package:
 | 
					 | 
				
			||||||
		for _, f := range n.Files {
 | 
					 | 
				
			||||||
			Walk(v, f)
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	default:
 | 
					 | 
				
			||||||
		panic(fmt.Sprintf("ast.Walk: unexpected node type %T", n))
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	v.Visit(nil)
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
type inspector func(Node) bool
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (f inspector) Visit(node Node) Visitor {
 | 
					 | 
				
			||||||
	if f(node) {
 | 
					 | 
				
			||||||
		return f
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return nil
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// Inspect traverses an AST in depth-first order: It starts by calling
 | 
					 | 
				
			||||||
// f(node); node must not be nil. If f returns true, Inspect invokes f
 | 
					 | 
				
			||||||
// recursively for each of the non-nil children of node, followed by a
 | 
					 | 
				
			||||||
// call of f(nil).
 | 
					 | 
				
			||||||
//
 | 
					 | 
				
			||||||
func Inspect(node Node, f func(Node) bool) {
 | 
					 | 
				
			||||||
	Walk(inspector(f), node)
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
							
								
								
									
										1523
									
								
								third_party/golang/go/build/build.go
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										1523
									
								
								third_party/golang/go/build/build.go
									
									
									
									
										vendored
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										348
									
								
								third_party/golang/go/build/build_test.go
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										348
									
								
								third_party/golang/go/build/build_test.go
									
									
									
									
										vendored
									
									
								
							@@ -1,348 +0,0 @@
 | 
				
			|||||||
// Copyright 2011 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 build
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
import (
 | 
					 | 
				
			||||||
	"internal/testenv"
 | 
					 | 
				
			||||||
	"io"
 | 
					 | 
				
			||||||
	"os"
 | 
					 | 
				
			||||||
	"path/filepath"
 | 
					 | 
				
			||||||
	"reflect"
 | 
					 | 
				
			||||||
	"runtime"
 | 
					 | 
				
			||||||
	"strings"
 | 
					 | 
				
			||||||
	"testing"
 | 
					 | 
				
			||||||
)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func TestMatch(t *testing.T) {
 | 
					 | 
				
			||||||
	ctxt := Default
 | 
					 | 
				
			||||||
	what := "default"
 | 
					 | 
				
			||||||
	match := func(tag string, want map[string]bool) {
 | 
					 | 
				
			||||||
		m := make(map[string]bool)
 | 
					 | 
				
			||||||
		if !ctxt.match(tag, m) {
 | 
					 | 
				
			||||||
			t.Errorf("%s context should match %s, does not", what, tag)
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		if !reflect.DeepEqual(m, want) {
 | 
					 | 
				
			||||||
			t.Errorf("%s tags = %v, want %v", tag, m, want)
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	nomatch := func(tag string, want map[string]bool) {
 | 
					 | 
				
			||||||
		m := make(map[string]bool)
 | 
					 | 
				
			||||||
		if ctxt.match(tag, m) {
 | 
					 | 
				
			||||||
			t.Errorf("%s context should NOT match %s, does", what, tag)
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		if !reflect.DeepEqual(m, want) {
 | 
					 | 
				
			||||||
			t.Errorf("%s tags = %v, want %v", tag, m, want)
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	match(runtime.GOOS+","+runtime.GOARCH, map[string]bool{runtime.GOOS: true, runtime.GOARCH: true})
 | 
					 | 
				
			||||||
	match(runtime.GOOS+","+runtime.GOARCH+",!foo", map[string]bool{runtime.GOOS: true, runtime.GOARCH: true, "foo": true})
 | 
					 | 
				
			||||||
	nomatch(runtime.GOOS+","+runtime.GOARCH+",foo", map[string]bool{runtime.GOOS: true, runtime.GOARCH: true, "foo": true})
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	what = "modified"
 | 
					 | 
				
			||||||
	ctxt.BuildTags = []string{"foo"}
 | 
					 | 
				
			||||||
	match(runtime.GOOS+","+runtime.GOARCH, map[string]bool{runtime.GOOS: true, runtime.GOARCH: true})
 | 
					 | 
				
			||||||
	match(runtime.GOOS+","+runtime.GOARCH+",foo", map[string]bool{runtime.GOOS: true, runtime.GOARCH: true, "foo": true})
 | 
					 | 
				
			||||||
	nomatch(runtime.GOOS+","+runtime.GOARCH+",!foo", map[string]bool{runtime.GOOS: true, runtime.GOARCH: true, "foo": true})
 | 
					 | 
				
			||||||
	match(runtime.GOOS+","+runtime.GOARCH+",!bar", map[string]bool{runtime.GOOS: true, runtime.GOARCH: true, "bar": true})
 | 
					 | 
				
			||||||
	nomatch(runtime.GOOS+","+runtime.GOARCH+",bar", map[string]bool{runtime.GOOS: true, runtime.GOARCH: true, "bar": true})
 | 
					 | 
				
			||||||
	nomatch("!", map[string]bool{})
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func TestDotSlashImport(t *testing.T) {
 | 
					 | 
				
			||||||
	p, err := ImportDir("testdata/other", 0)
 | 
					 | 
				
			||||||
	if err != nil {
 | 
					 | 
				
			||||||
		t.Fatal(err)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	if len(p.Imports) != 1 || p.Imports[0] != "./file" {
 | 
					 | 
				
			||||||
		t.Fatalf("testdata/other: Imports=%v, want [./file]", p.Imports)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	p1, err := Import("./file", "testdata/other", 0)
 | 
					 | 
				
			||||||
	if err != nil {
 | 
					 | 
				
			||||||
		t.Fatal(err)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	if p1.Name != "file" {
 | 
					 | 
				
			||||||
		t.Fatalf("./file: Name=%q, want %q", p1.Name, "file")
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	dir := filepath.Clean("testdata/other/file") // Clean to use \ on Windows
 | 
					 | 
				
			||||||
	if p1.Dir != dir {
 | 
					 | 
				
			||||||
		t.Fatalf("./file: Dir=%q, want %q", p1.Name, dir)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func TestEmptyImport(t *testing.T) {
 | 
					 | 
				
			||||||
	p, err := Import("", Default.GOROOT, FindOnly)
 | 
					 | 
				
			||||||
	if err == nil {
 | 
					 | 
				
			||||||
		t.Fatal(`Import("") returned nil error.`)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	if p == nil {
 | 
					 | 
				
			||||||
		t.Fatal(`Import("") returned nil package.`)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	if p.ImportPath != "" {
 | 
					 | 
				
			||||||
		t.Fatalf("ImportPath=%q, want %q.", p.ImportPath, "")
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func TestEmptyFolderImport(t *testing.T) {
 | 
					 | 
				
			||||||
	_, err := Import(".", "testdata/empty", 0)
 | 
					 | 
				
			||||||
	if _, ok := err.(*NoGoError); !ok {
 | 
					 | 
				
			||||||
		t.Fatal(`Import("testdata/empty") did not return NoGoError.`)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func TestMultiplePackageImport(t *testing.T) {
 | 
					 | 
				
			||||||
	_, err := Import(".", "testdata/multi", 0)
 | 
					 | 
				
			||||||
	mpe, ok := err.(*MultiplePackageError)
 | 
					 | 
				
			||||||
	if !ok {
 | 
					 | 
				
			||||||
		t.Fatal(`Import("testdata/multi") did not return MultiplePackageError.`)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	want := &MultiplePackageError{
 | 
					 | 
				
			||||||
		Dir:      filepath.FromSlash("testdata/multi"),
 | 
					 | 
				
			||||||
		Packages: []string{"main", "test_package"},
 | 
					 | 
				
			||||||
		Files:    []string{"file.go", "file_appengine.go"},
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	if !reflect.DeepEqual(mpe, want) {
 | 
					 | 
				
			||||||
		t.Errorf("got %#v; want %#v", mpe, want)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func TestLocalDirectory(t *testing.T) {
 | 
					 | 
				
			||||||
	if runtime.GOOS == "darwin" {
 | 
					 | 
				
			||||||
		switch runtime.GOARCH {
 | 
					 | 
				
			||||||
		case "arm", "arm64":
 | 
					 | 
				
			||||||
			t.Skipf("skipping on %s/%s, no valid GOROOT", runtime.GOOS, runtime.GOARCH)
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	cwd, err := os.Getwd()
 | 
					 | 
				
			||||||
	if err != nil {
 | 
					 | 
				
			||||||
		t.Fatal(err)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	p, err := ImportDir(cwd, 0)
 | 
					 | 
				
			||||||
	if err != nil {
 | 
					 | 
				
			||||||
		t.Fatal(err)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	if p.ImportPath != "go/build" {
 | 
					 | 
				
			||||||
		t.Fatalf("ImportPath=%q, want %q", p.ImportPath, "go/build")
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func TestShouldBuild(t *testing.T) {
 | 
					 | 
				
			||||||
	const file1 = "// +build tag1\n\n" +
 | 
					 | 
				
			||||||
		"package main\n"
 | 
					 | 
				
			||||||
	want1 := map[string]bool{"tag1": true}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	const file2 = "// +build cgo\n\n" +
 | 
					 | 
				
			||||||
		"// This package implements parsing of tags like\n" +
 | 
					 | 
				
			||||||
		"// +build tag1\n" +
 | 
					 | 
				
			||||||
		"package build"
 | 
					 | 
				
			||||||
	want2 := map[string]bool{"cgo": true}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	const file3 = "// Copyright The Go Authors.\n\n" +
 | 
					 | 
				
			||||||
		"package build\n\n" +
 | 
					 | 
				
			||||||
		"// shouldBuild checks tags given by lines of the form\n" +
 | 
					 | 
				
			||||||
		"// +build tag\n" +
 | 
					 | 
				
			||||||
		"func shouldBuild(content []byte)\n"
 | 
					 | 
				
			||||||
	want3 := map[string]bool{}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	ctx := &Context{BuildTags: []string{"tag1"}}
 | 
					 | 
				
			||||||
	m := map[string]bool{}
 | 
					 | 
				
			||||||
	if !ctx.shouldBuild([]byte(file1), m) {
 | 
					 | 
				
			||||||
		t.Errorf("shouldBuild(file1) = false, want true")
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	if !reflect.DeepEqual(m, want1) {
 | 
					 | 
				
			||||||
		t.Errorf("shoudBuild(file1) tags = %v, want %v", m, want1)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	m = map[string]bool{}
 | 
					 | 
				
			||||||
	if ctx.shouldBuild([]byte(file2), m) {
 | 
					 | 
				
			||||||
		t.Errorf("shouldBuild(file2) = true, want fakse")
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	if !reflect.DeepEqual(m, want2) {
 | 
					 | 
				
			||||||
		t.Errorf("shoudBuild(file2) tags = %v, want %v", m, want2)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	m = map[string]bool{}
 | 
					 | 
				
			||||||
	ctx = &Context{BuildTags: nil}
 | 
					 | 
				
			||||||
	if !ctx.shouldBuild([]byte(file3), m) {
 | 
					 | 
				
			||||||
		t.Errorf("shouldBuild(file3) = false, want true")
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	if !reflect.DeepEqual(m, want3) {
 | 
					 | 
				
			||||||
		t.Errorf("shoudBuild(file3) tags = %v, want %v", m, want3)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
type readNopCloser struct {
 | 
					 | 
				
			||||||
	io.Reader
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (r readNopCloser) Close() error {
 | 
					 | 
				
			||||||
	return nil
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
var (
 | 
					 | 
				
			||||||
	ctxtP9      = Context{GOARCH: "arm", GOOS: "plan9"}
 | 
					 | 
				
			||||||
	ctxtAndroid = Context{GOARCH: "arm", GOOS: "android"}
 | 
					 | 
				
			||||||
)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
var matchFileTests = []struct {
 | 
					 | 
				
			||||||
	ctxt  Context
 | 
					 | 
				
			||||||
	name  string
 | 
					 | 
				
			||||||
	data  string
 | 
					 | 
				
			||||||
	match bool
 | 
					 | 
				
			||||||
}{
 | 
					 | 
				
			||||||
	{ctxtP9, "foo_arm.go", "", true},
 | 
					 | 
				
			||||||
	{ctxtP9, "foo1_arm.go", "// +build linux\n\npackage main\n", false},
 | 
					 | 
				
			||||||
	{ctxtP9, "foo_darwin.go", "", false},
 | 
					 | 
				
			||||||
	{ctxtP9, "foo.go", "", true},
 | 
					 | 
				
			||||||
	{ctxtP9, "foo1.go", "// +build linux\n\npackage main\n", false},
 | 
					 | 
				
			||||||
	{ctxtP9, "foo.badsuffix", "", false},
 | 
					 | 
				
			||||||
	{ctxtAndroid, "foo_linux.go", "", true},
 | 
					 | 
				
			||||||
	{ctxtAndroid, "foo_android.go", "", true},
 | 
					 | 
				
			||||||
	{ctxtAndroid, "foo_plan9.go", "", false},
 | 
					 | 
				
			||||||
	{ctxtAndroid, "android.go", "", true},
 | 
					 | 
				
			||||||
	{ctxtAndroid, "plan9.go", "", true},
 | 
					 | 
				
			||||||
	{ctxtAndroid, "plan9_test.go", "", true},
 | 
					 | 
				
			||||||
	{ctxtAndroid, "arm.s", "", true},
 | 
					 | 
				
			||||||
	{ctxtAndroid, "amd64.s", "", true},
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func TestMatchFile(t *testing.T) {
 | 
					 | 
				
			||||||
	for _, tt := range matchFileTests {
 | 
					 | 
				
			||||||
		ctxt := tt.ctxt
 | 
					 | 
				
			||||||
		ctxt.OpenFile = func(path string) (r io.ReadCloser, err error) {
 | 
					 | 
				
			||||||
			if path != "x+"+tt.name {
 | 
					 | 
				
			||||||
				t.Fatalf("OpenFile asked for %q, expected %q", path, "x+"+tt.name)
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
			return &readNopCloser{strings.NewReader(tt.data)}, nil
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		ctxt.JoinPath = func(elem ...string) string {
 | 
					 | 
				
			||||||
			return strings.Join(elem, "+")
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		match, err := ctxt.MatchFile("x", tt.name)
 | 
					 | 
				
			||||||
		if match != tt.match || err != nil {
 | 
					 | 
				
			||||||
			t.Fatalf("MatchFile(%q) = %v, %v, want %v, nil", tt.name, match, err, tt.match)
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func TestImportCmd(t *testing.T) {
 | 
					 | 
				
			||||||
	if runtime.GOOS == "darwin" {
 | 
					 | 
				
			||||||
		switch runtime.GOARCH {
 | 
					 | 
				
			||||||
		case "arm", "arm64":
 | 
					 | 
				
			||||||
			t.Skipf("skipping on %s/%s, no valid GOROOT", runtime.GOOS, runtime.GOARCH)
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	p, err := Import("cmd/internal/objfile", "", 0)
 | 
					 | 
				
			||||||
	if err != nil {
 | 
					 | 
				
			||||||
		t.Fatal(err)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	if !strings.HasSuffix(filepath.ToSlash(p.Dir), "src/cmd/internal/objfile") {
 | 
					 | 
				
			||||||
		t.Fatalf("Import cmd/internal/objfile returned Dir=%q, want %q", filepath.ToSlash(p.Dir), ".../src/cmd/internal/objfile")
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
var (
 | 
					 | 
				
			||||||
	expandSrcDirPath = filepath.Join(string(filepath.Separator)+"projects", "src", "add")
 | 
					 | 
				
			||||||
)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
var expandSrcDirTests = []struct {
 | 
					 | 
				
			||||||
	input, expected string
 | 
					 | 
				
			||||||
}{
 | 
					 | 
				
			||||||
	{"-L ${SRCDIR}/libs -ladd", "-L /projects/src/add/libs -ladd"},
 | 
					 | 
				
			||||||
	{"${SRCDIR}/add_linux_386.a -pthread -lstdc++", "/projects/src/add/add_linux_386.a -pthread -lstdc++"},
 | 
					 | 
				
			||||||
	{"Nothing to expand here!", "Nothing to expand here!"},
 | 
					 | 
				
			||||||
	{"$", "$"},
 | 
					 | 
				
			||||||
	{"$$", "$$"},
 | 
					 | 
				
			||||||
	{"${", "${"},
 | 
					 | 
				
			||||||
	{"$}", "$}"},
 | 
					 | 
				
			||||||
	{"$FOO ${BAR}", "$FOO ${BAR}"},
 | 
					 | 
				
			||||||
	{"Find me the $SRCDIRECTORY.", "Find me the $SRCDIRECTORY."},
 | 
					 | 
				
			||||||
	{"$SRCDIR is missing braces", "$SRCDIR is missing braces"},
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func TestExpandSrcDir(t *testing.T) {
 | 
					 | 
				
			||||||
	for _, test := range expandSrcDirTests {
 | 
					 | 
				
			||||||
		output, _ := expandSrcDir(test.input, expandSrcDirPath)
 | 
					 | 
				
			||||||
		if output != test.expected {
 | 
					 | 
				
			||||||
			t.Errorf("%q expands to %q with SRCDIR=%q when %q is expected", test.input, output, expandSrcDirPath, test.expected)
 | 
					 | 
				
			||||||
		} else {
 | 
					 | 
				
			||||||
			t.Logf("%q expands to %q with SRCDIR=%q", test.input, output, expandSrcDirPath)
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func TestShellSafety(t *testing.T) {
 | 
					 | 
				
			||||||
	tests := []struct {
 | 
					 | 
				
			||||||
		input, srcdir, expected string
 | 
					 | 
				
			||||||
		result                  bool
 | 
					 | 
				
			||||||
	}{
 | 
					 | 
				
			||||||
		{"-I${SRCDIR}/../include", "/projects/src/issue 11868", "-I/projects/src/issue 11868/../include", true},
 | 
					 | 
				
			||||||
		{"-X${SRCDIR}/1,${SRCDIR}/2", "/projects/src/issue 11868", "-X/projects/src/issue 11868/1,/projects/src/issue 11868/2", true},
 | 
					 | 
				
			||||||
		{"-I/tmp -I/tmp", "/tmp2", "-I/tmp -I/tmp", false},
 | 
					 | 
				
			||||||
		{"-I/tmp", "/tmp/[0]", "-I/tmp", true},
 | 
					 | 
				
			||||||
		{"-I${SRCDIR}/dir", "/tmp/[0]", "-I/tmp/[0]/dir", false},
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	for _, test := range tests {
 | 
					 | 
				
			||||||
		output, ok := expandSrcDir(test.input, test.srcdir)
 | 
					 | 
				
			||||||
		if ok != test.result {
 | 
					 | 
				
			||||||
			t.Errorf("Expected %t while %q expands to %q with SRCDIR=%q; got %t", test.result, test.input, output, test.srcdir, ok)
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		if output != test.expected {
 | 
					 | 
				
			||||||
			t.Errorf("Expected %q while %q expands with SRCDIR=%q; got %q", test.expected, test.input, test.srcdir, output)
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func TestImportVendor(t *testing.T) {
 | 
					 | 
				
			||||||
	t.Skip("skipping; hpack has moved to internal for now; golang.org/issue/14047")
 | 
					 | 
				
			||||||
	testenv.MustHaveGoBuild(t) // really must just have source
 | 
					 | 
				
			||||||
	ctxt := Default
 | 
					 | 
				
			||||||
	ctxt.GOPATH = ""
 | 
					 | 
				
			||||||
	p, err := ctxt.Import("golang.org/x/net/http2/hpack", filepath.Join(ctxt.GOROOT, "src/net/http"), 0)
 | 
					 | 
				
			||||||
	if err != nil {
 | 
					 | 
				
			||||||
		t.Fatalf("cannot find vendored golang.org/x/net/http2/hpack from net/http directory: %v", err)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	want := "vendor/golang.org/x/net/http2/hpack"
 | 
					 | 
				
			||||||
	if p.ImportPath != want {
 | 
					 | 
				
			||||||
		t.Fatalf("Import succeeded but found %q, want %q", p.ImportPath, want)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func TestImportVendorFailure(t *testing.T) {
 | 
					 | 
				
			||||||
	testenv.MustHaveGoBuild(t) // really must just have source
 | 
					 | 
				
			||||||
	ctxt := Default
 | 
					 | 
				
			||||||
	ctxt.GOPATH = ""
 | 
					 | 
				
			||||||
	p, err := ctxt.Import("x.com/y/z", filepath.Join(ctxt.GOROOT, "src/net/http"), 0)
 | 
					 | 
				
			||||||
	if err == nil {
 | 
					 | 
				
			||||||
		t.Fatalf("found made-up package x.com/y/z in %s", p.Dir)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	e := err.Error()
 | 
					 | 
				
			||||||
	if !strings.Contains(e, " (vendor tree)") {
 | 
					 | 
				
			||||||
		t.Fatalf("error on failed import does not mention GOROOT/src/vendor directory:\n%s", e)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func TestImportVendorParentFailure(t *testing.T) {
 | 
					 | 
				
			||||||
	testenv.MustHaveGoBuild(t) // really must just have source
 | 
					 | 
				
			||||||
	ctxt := Default
 | 
					 | 
				
			||||||
	ctxt.GOPATH = ""
 | 
					 | 
				
			||||||
	// This import should fail because the vendor/golang.org/x/net/http2 directory has no source code.
 | 
					 | 
				
			||||||
	p, err := ctxt.Import("golang.org/x/net/http2", filepath.Join(ctxt.GOROOT, "src/net/http"), 0)
 | 
					 | 
				
			||||||
	if err == nil {
 | 
					 | 
				
			||||||
		t.Fatalf("found empty parent in %s", p.Dir)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	if p != nil && p.Dir != "" {
 | 
					 | 
				
			||||||
		t.Fatalf("decided to use %s", p.Dir)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	e := err.Error()
 | 
					 | 
				
			||||||
	if !strings.Contains(e, " (vendor tree)") {
 | 
					 | 
				
			||||||
		t.Fatalf("error on failed import does not mention GOROOT/src/vendor directory:\n%s", e)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
							
								
								
									
										525
									
								
								third_party/golang/go/build/deps_test.go
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										525
									
								
								third_party/golang/go/build/deps_test.go
									
									
									
									
										vendored
									
									
								
							@@ -1,525 +0,0 @@
 | 
				
			|||||||
// Copyright 2012 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.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// This file exercises the import parser but also checks that
 | 
					 | 
				
			||||||
// some low-level packages do not have new dependencies added.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
package build
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
import (
 | 
					 | 
				
			||||||
	"bytes"
 | 
					 | 
				
			||||||
	"fmt"
 | 
					 | 
				
			||||||
	"io/ioutil"
 | 
					 | 
				
			||||||
	"os"
 | 
					 | 
				
			||||||
	"path/filepath"
 | 
					 | 
				
			||||||
	"runtime"
 | 
					 | 
				
			||||||
	"sort"
 | 
					 | 
				
			||||||
	"strconv"
 | 
					 | 
				
			||||||
	"strings"
 | 
					 | 
				
			||||||
	"testing"
 | 
					 | 
				
			||||||
)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// pkgDeps defines the expected dependencies between packages in
 | 
					 | 
				
			||||||
// the Go source tree.  It is a statement of policy.
 | 
					 | 
				
			||||||
// Changes should not be made to this map without prior discussion.
 | 
					 | 
				
			||||||
//
 | 
					 | 
				
			||||||
// The map contains two kinds of entries:
 | 
					 | 
				
			||||||
// 1) Lower-case keys are standard import paths and list the
 | 
					 | 
				
			||||||
// allowed imports in that package.
 | 
					 | 
				
			||||||
// 2) Upper-case keys define aliases for package sets, which can then
 | 
					 | 
				
			||||||
// be used as dependencies by other rules.
 | 
					 | 
				
			||||||
//
 | 
					 | 
				
			||||||
// DO NOT CHANGE THIS DATA TO FIX BUILDS.
 | 
					 | 
				
			||||||
//
 | 
					 | 
				
			||||||
var pkgDeps = map[string][]string{
 | 
					 | 
				
			||||||
	// L0 is the lowest level, core, nearly unavoidable packages.
 | 
					 | 
				
			||||||
	"errors":                  {},
 | 
					 | 
				
			||||||
	"io":                      {"errors", "sync"},
 | 
					 | 
				
			||||||
	"runtime":                 {"unsafe", "runtime/internal/atomic", "runtime/internal/sys"},
 | 
					 | 
				
			||||||
	"runtime/internal/sys":    {},
 | 
					 | 
				
			||||||
	"runtime/internal/atomic": {"unsafe", "runtime/internal/sys"},
 | 
					 | 
				
			||||||
	"internal/race":           {"runtime", "unsafe"},
 | 
					 | 
				
			||||||
	"sync":                    {"internal/race", "runtime", "sync/atomic", "unsafe"},
 | 
					 | 
				
			||||||
	"sync/atomic":             {"unsafe"},
 | 
					 | 
				
			||||||
	"unsafe":                  {},
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	"L0": {
 | 
					 | 
				
			||||||
		"errors",
 | 
					 | 
				
			||||||
		"io",
 | 
					 | 
				
			||||||
		"runtime",
 | 
					 | 
				
			||||||
		"runtime/internal/atomic",
 | 
					 | 
				
			||||||
		"sync",
 | 
					 | 
				
			||||||
		"sync/atomic",
 | 
					 | 
				
			||||||
		"unsafe",
 | 
					 | 
				
			||||||
	},
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// L1 adds simple functions and strings processing,
 | 
					 | 
				
			||||||
	// but not Unicode tables.
 | 
					 | 
				
			||||||
	"math":          {"unsafe"},
 | 
					 | 
				
			||||||
	"math/cmplx":    {"math"},
 | 
					 | 
				
			||||||
	"math/rand":     {"L0", "math"},
 | 
					 | 
				
			||||||
	"sort":          {},
 | 
					 | 
				
			||||||
	"strconv":       {"L0", "unicode/utf8", "math"},
 | 
					 | 
				
			||||||
	"unicode/utf16": {},
 | 
					 | 
				
			||||||
	"unicode/utf8":  {},
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	"L1": {
 | 
					 | 
				
			||||||
		"L0",
 | 
					 | 
				
			||||||
		"math",
 | 
					 | 
				
			||||||
		"math/cmplx",
 | 
					 | 
				
			||||||
		"math/rand",
 | 
					 | 
				
			||||||
		"sort",
 | 
					 | 
				
			||||||
		"strconv",
 | 
					 | 
				
			||||||
		"unicode/utf16",
 | 
					 | 
				
			||||||
		"unicode/utf8",
 | 
					 | 
				
			||||||
	},
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// L2 adds Unicode and strings processing.
 | 
					 | 
				
			||||||
	"bufio":   {"L0", "unicode/utf8", "bytes"},
 | 
					 | 
				
			||||||
	"bytes":   {"L0", "unicode", "unicode/utf8"},
 | 
					 | 
				
			||||||
	"path":    {"L0", "unicode/utf8", "strings"},
 | 
					 | 
				
			||||||
	"strings": {"L0", "unicode", "unicode/utf8"},
 | 
					 | 
				
			||||||
	"unicode": {},
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	"L2": {
 | 
					 | 
				
			||||||
		"L1",
 | 
					 | 
				
			||||||
		"bufio",
 | 
					 | 
				
			||||||
		"bytes",
 | 
					 | 
				
			||||||
		"path",
 | 
					 | 
				
			||||||
		"strings",
 | 
					 | 
				
			||||||
		"unicode",
 | 
					 | 
				
			||||||
	},
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// L3 adds reflection and some basic utility packages
 | 
					 | 
				
			||||||
	// and interface definitions, but nothing that makes
 | 
					 | 
				
			||||||
	// system calls.
 | 
					 | 
				
			||||||
	"crypto":              {"L2", "hash"},          // interfaces
 | 
					 | 
				
			||||||
	"crypto/cipher":       {"L2", "crypto/subtle"}, // interfaces
 | 
					 | 
				
			||||||
	"crypto/subtle":       {},
 | 
					 | 
				
			||||||
	"encoding/base32":     {"L2"},
 | 
					 | 
				
			||||||
	"encoding/base64":     {"L2"},
 | 
					 | 
				
			||||||
	"encoding/binary":     {"L2", "reflect"},
 | 
					 | 
				
			||||||
	"hash":                {"L2"}, // interfaces
 | 
					 | 
				
			||||||
	"hash/adler32":        {"L2", "hash"},
 | 
					 | 
				
			||||||
	"hash/crc32":          {"L2", "hash"},
 | 
					 | 
				
			||||||
	"hash/crc64":          {"L2", "hash"},
 | 
					 | 
				
			||||||
	"hash/fnv":            {"L2", "hash"},
 | 
					 | 
				
			||||||
	"image":               {"L2", "image/color"}, // interfaces
 | 
					 | 
				
			||||||
	"image/color":         {"L2"},                // interfaces
 | 
					 | 
				
			||||||
	"image/color/palette": {"L2", "image/color"},
 | 
					 | 
				
			||||||
	"reflect":             {"L2"},
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	"L3": {
 | 
					 | 
				
			||||||
		"L2",
 | 
					 | 
				
			||||||
		"crypto",
 | 
					 | 
				
			||||||
		"crypto/cipher",
 | 
					 | 
				
			||||||
		"crypto/subtle",
 | 
					 | 
				
			||||||
		"encoding/base32",
 | 
					 | 
				
			||||||
		"encoding/base64",
 | 
					 | 
				
			||||||
		"encoding/binary",
 | 
					 | 
				
			||||||
		"hash",
 | 
					 | 
				
			||||||
		"hash/adler32",
 | 
					 | 
				
			||||||
		"hash/crc32",
 | 
					 | 
				
			||||||
		"hash/crc64",
 | 
					 | 
				
			||||||
		"hash/fnv",
 | 
					 | 
				
			||||||
		"image",
 | 
					 | 
				
			||||||
		"image/color",
 | 
					 | 
				
			||||||
		"image/color/palette",
 | 
					 | 
				
			||||||
		"reflect",
 | 
					 | 
				
			||||||
	},
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// End of linear dependency definitions.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// Operating system access.
 | 
					 | 
				
			||||||
	"syscall":                           {"L0", "internal/race", "internal/syscall/windows/sysdll", "unicode/utf16"},
 | 
					 | 
				
			||||||
	"internal/syscall/unix":             {"L0", "syscall"},
 | 
					 | 
				
			||||||
	"internal/syscall/windows":          {"L0", "syscall", "internal/syscall/windows/sysdll"},
 | 
					 | 
				
			||||||
	"internal/syscall/windows/registry": {"L0", "syscall", "internal/syscall/windows/sysdll", "unicode/utf16"},
 | 
					 | 
				
			||||||
	"time":          {"L0", "syscall", "internal/syscall/windows/registry"},
 | 
					 | 
				
			||||||
	"os":            {"L1", "os", "syscall", "time", "internal/syscall/windows"},
 | 
					 | 
				
			||||||
	"path/filepath": {"L2", "os", "syscall"},
 | 
					 | 
				
			||||||
	"io/ioutil":     {"L2", "os", "path/filepath", "time"},
 | 
					 | 
				
			||||||
	"os/exec":       {"L2", "os", "path/filepath", "syscall"},
 | 
					 | 
				
			||||||
	"os/signal":     {"L2", "os", "syscall"},
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// OS enables basic operating system functionality,
 | 
					 | 
				
			||||||
	// but not direct use of package syscall, nor os/signal.
 | 
					 | 
				
			||||||
	"OS": {
 | 
					 | 
				
			||||||
		"io/ioutil",
 | 
					 | 
				
			||||||
		"os",
 | 
					 | 
				
			||||||
		"os/exec",
 | 
					 | 
				
			||||||
		"path/filepath",
 | 
					 | 
				
			||||||
		"time",
 | 
					 | 
				
			||||||
	},
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// Formatted I/O: few dependencies (L1) but we must add reflect.
 | 
					 | 
				
			||||||
	"fmt": {"L1", "os", "reflect"},
 | 
					 | 
				
			||||||
	"log": {"L1", "os", "fmt", "time"},
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// Packages used by testing must be low-level (L2+fmt).
 | 
					 | 
				
			||||||
	"regexp":         {"L2", "regexp/syntax"},
 | 
					 | 
				
			||||||
	"regexp/syntax":  {"L2"},
 | 
					 | 
				
			||||||
	"runtime/debug":  {"L2", "fmt", "io/ioutil", "os", "time"},
 | 
					 | 
				
			||||||
	"runtime/pprof":  {"L2", "fmt", "text/tabwriter"},
 | 
					 | 
				
			||||||
	"runtime/trace":  {"L0"},
 | 
					 | 
				
			||||||
	"text/tabwriter": {"L2"},
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	"testing":          {"L2", "flag", "fmt", "os", "runtime/debug", "runtime/pprof", "runtime/trace", "time"},
 | 
					 | 
				
			||||||
	"testing/iotest":   {"L2", "log"},
 | 
					 | 
				
			||||||
	"testing/quick":    {"L2", "flag", "fmt", "reflect"},
 | 
					 | 
				
			||||||
	"internal/testenv": {"L2", "os", "testing"},
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// L4 is defined as L3+fmt+log+time, because in general once
 | 
					 | 
				
			||||||
	// you're using L3 packages, use of fmt, log, or time is not a big deal.
 | 
					 | 
				
			||||||
	"L4": {
 | 
					 | 
				
			||||||
		"L3",
 | 
					 | 
				
			||||||
		"fmt",
 | 
					 | 
				
			||||||
		"log",
 | 
					 | 
				
			||||||
		"time",
 | 
					 | 
				
			||||||
	},
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// Go parser.
 | 
					 | 
				
			||||||
	"go/ast":     {"L4", "OS", "go/scanner", "go/token"},
 | 
					 | 
				
			||||||
	"go/doc":     {"L4", "go/ast", "go/token", "regexp", "text/template"},
 | 
					 | 
				
			||||||
	"go/parser":  {"L4", "OS", "go/ast", "go/scanner", "go/token"},
 | 
					 | 
				
			||||||
	"go/printer": {"L4", "OS", "go/ast", "go/scanner", "go/token", "text/tabwriter"},
 | 
					 | 
				
			||||||
	"go/scanner": {"L4", "OS", "go/token"},
 | 
					 | 
				
			||||||
	"go/token":   {"L4"},
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	"GOPARSER": {
 | 
					 | 
				
			||||||
		"go/ast",
 | 
					 | 
				
			||||||
		"go/doc",
 | 
					 | 
				
			||||||
		"go/parser",
 | 
					 | 
				
			||||||
		"go/printer",
 | 
					 | 
				
			||||||
		"go/scanner",
 | 
					 | 
				
			||||||
		"go/token",
 | 
					 | 
				
			||||||
	},
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	"go/format":       {"L4", "GOPARSER", "internal/format"},
 | 
					 | 
				
			||||||
	"internal/format": {"L4", "GOPARSER"},
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// Go type checking.
 | 
					 | 
				
			||||||
	"go/constant":               {"L4", "go/token", "math/big"},
 | 
					 | 
				
			||||||
	"go/importer":               {"L4", "go/internal/gcimporter", "go/internal/gccgoimporter", "go/types"},
 | 
					 | 
				
			||||||
	"go/internal/gcimporter":    {"L4", "OS", "go/build", "go/constant", "go/token", "go/types", "text/scanner"},
 | 
					 | 
				
			||||||
	"go/internal/gccgoimporter": {"L4", "OS", "debug/elf", "go/constant", "go/token", "go/types", "text/scanner"},
 | 
					 | 
				
			||||||
	"go/types":                  {"L4", "GOPARSER", "container/heap", "go/constant"},
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// One of a kind.
 | 
					 | 
				
			||||||
	"archive/tar":              {"L4", "OS", "syscall"},
 | 
					 | 
				
			||||||
	"archive/zip":              {"L4", "OS", "compress/flate"},
 | 
					 | 
				
			||||||
	"container/heap":           {"sort"},
 | 
					 | 
				
			||||||
	"compress/bzip2":           {"L4"},
 | 
					 | 
				
			||||||
	"compress/flate":           {"L4"},
 | 
					 | 
				
			||||||
	"compress/gzip":            {"L4", "compress/flate"},
 | 
					 | 
				
			||||||
	"compress/lzw":             {"L4"},
 | 
					 | 
				
			||||||
	"compress/zlib":            {"L4", "compress/flate"},
 | 
					 | 
				
			||||||
	"database/sql":             {"L4", "container/list", "database/sql/driver"},
 | 
					 | 
				
			||||||
	"database/sql/driver":      {"L4", "time"},
 | 
					 | 
				
			||||||
	"debug/dwarf":              {"L4"},
 | 
					 | 
				
			||||||
	"debug/elf":                {"L4", "OS", "debug/dwarf", "compress/zlib"},
 | 
					 | 
				
			||||||
	"debug/gosym":              {"L4"},
 | 
					 | 
				
			||||||
	"debug/macho":              {"L4", "OS", "debug/dwarf"},
 | 
					 | 
				
			||||||
	"debug/pe":                 {"L4", "OS", "debug/dwarf"},
 | 
					 | 
				
			||||||
	"debug/plan9obj":           {"L4", "OS"},
 | 
					 | 
				
			||||||
	"encoding":                 {"L4"},
 | 
					 | 
				
			||||||
	"encoding/ascii85":         {"L4"},
 | 
					 | 
				
			||||||
	"encoding/asn1":            {"L4", "math/big"},
 | 
					 | 
				
			||||||
	"encoding/csv":             {"L4"},
 | 
					 | 
				
			||||||
	"encoding/gob":             {"L4", "OS", "encoding"},
 | 
					 | 
				
			||||||
	"encoding/hex":             {"L4"},
 | 
					 | 
				
			||||||
	"encoding/json":            {"L4", "encoding"},
 | 
					 | 
				
			||||||
	"encoding/pem":             {"L4"},
 | 
					 | 
				
			||||||
	"encoding/xml":             {"L4", "encoding"},
 | 
					 | 
				
			||||||
	"flag":                     {"L4", "OS"},
 | 
					 | 
				
			||||||
	"go/build":                 {"L4", "OS", "GOPARSER"},
 | 
					 | 
				
			||||||
	"html":                     {"L4"},
 | 
					 | 
				
			||||||
	"image/draw":               {"L4", "image/internal/imageutil"},
 | 
					 | 
				
			||||||
	"image/gif":                {"L4", "compress/lzw", "image/color/palette", "image/draw"},
 | 
					 | 
				
			||||||
	"image/internal/imageutil": {"L4"},
 | 
					 | 
				
			||||||
	"image/jpeg":               {"L4", "image/internal/imageutil"},
 | 
					 | 
				
			||||||
	"image/png":                {"L4", "compress/zlib"},
 | 
					 | 
				
			||||||
	"index/suffixarray":        {"L4", "regexp"},
 | 
					 | 
				
			||||||
	"internal/singleflight":    {"sync"},
 | 
					 | 
				
			||||||
	"internal/trace":           {"L4", "OS"},
 | 
					 | 
				
			||||||
	"math/big":                 {"L4"},
 | 
					 | 
				
			||||||
	"mime":                     {"L4", "OS", "syscall", "internal/syscall/windows/registry"},
 | 
					 | 
				
			||||||
	"mime/quotedprintable":     {"L4"},
 | 
					 | 
				
			||||||
	"net/internal/socktest":    {"L4", "OS", "syscall"},
 | 
					 | 
				
			||||||
	"net/url":                  {"L4"},
 | 
					 | 
				
			||||||
	"text/scanner":             {"L4", "OS"},
 | 
					 | 
				
			||||||
	"text/template/parse":      {"L4"},
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	"html/template": {
 | 
					 | 
				
			||||||
		"L4", "OS", "encoding/json", "html", "text/template",
 | 
					 | 
				
			||||||
		"text/template/parse",
 | 
					 | 
				
			||||||
	},
 | 
					 | 
				
			||||||
	"text/template": {
 | 
					 | 
				
			||||||
		"L4", "OS", "net/url", "text/template/parse",
 | 
					 | 
				
			||||||
	},
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// Cgo.
 | 
					 | 
				
			||||||
	// If you add a dependency on CGO, you must add the package to
 | 
					 | 
				
			||||||
	// cgoPackages in cmd/dist/test.go.
 | 
					 | 
				
			||||||
	"runtime/cgo": {"L0", "C"},
 | 
					 | 
				
			||||||
	"CGO":         {"C", "runtime/cgo"},
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// Fake entry to satisfy the pseudo-import "C"
 | 
					 | 
				
			||||||
	// that shows up in programs that use cgo.
 | 
					 | 
				
			||||||
	"C": {},
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// Race detector/MSan uses cgo.
 | 
					 | 
				
			||||||
	"runtime/race": {"C"},
 | 
					 | 
				
			||||||
	"runtime/msan": {"C"},
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// Plan 9 alone needs io/ioutil and os.
 | 
					 | 
				
			||||||
	"os/user": {"L4", "CGO", "io/ioutil", "os", "syscall"},
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// Basic networking.
 | 
					 | 
				
			||||||
	// Because net must be used by any package that wants to
 | 
					 | 
				
			||||||
	// do networking portably, it must have a small dependency set: just L0+basic os.
 | 
					 | 
				
			||||||
	"net": {"L0", "CGO", "math/rand", "os", "sort", "syscall", "time", "internal/syscall/windows", "internal/singleflight", "internal/race"},
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// NET enables use of basic network-related packages.
 | 
					 | 
				
			||||||
	"NET": {
 | 
					 | 
				
			||||||
		"net",
 | 
					 | 
				
			||||||
		"mime",
 | 
					 | 
				
			||||||
		"net/textproto",
 | 
					 | 
				
			||||||
		"net/url",
 | 
					 | 
				
			||||||
	},
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// Uses of networking.
 | 
					 | 
				
			||||||
	"log/syslog":    {"L4", "OS", "net"},
 | 
					 | 
				
			||||||
	"net/mail":      {"L4", "NET", "OS", "mime"},
 | 
					 | 
				
			||||||
	"net/textproto": {"L4", "OS", "net"},
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// Core crypto.
 | 
					 | 
				
			||||||
	"crypto/aes":    {"L3"},
 | 
					 | 
				
			||||||
	"crypto/des":    {"L3"},
 | 
					 | 
				
			||||||
	"crypto/hmac":   {"L3"},
 | 
					 | 
				
			||||||
	"crypto/md5":    {"L3"},
 | 
					 | 
				
			||||||
	"crypto/rc4":    {"L3"},
 | 
					 | 
				
			||||||
	"crypto/sha1":   {"L3"},
 | 
					 | 
				
			||||||
	"crypto/sha256": {"L3"},
 | 
					 | 
				
			||||||
	"crypto/sha512": {"L3"},
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	"CRYPTO": {
 | 
					 | 
				
			||||||
		"crypto/aes",
 | 
					 | 
				
			||||||
		"crypto/des",
 | 
					 | 
				
			||||||
		"crypto/hmac",
 | 
					 | 
				
			||||||
		"crypto/md5",
 | 
					 | 
				
			||||||
		"crypto/rc4",
 | 
					 | 
				
			||||||
		"crypto/sha1",
 | 
					 | 
				
			||||||
		"crypto/sha256",
 | 
					 | 
				
			||||||
		"crypto/sha512",
 | 
					 | 
				
			||||||
	},
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// Random byte, number generation.
 | 
					 | 
				
			||||||
	// This would be part of core crypto except that it imports
 | 
					 | 
				
			||||||
	// math/big, which imports fmt.
 | 
					 | 
				
			||||||
	"crypto/rand": {"L4", "CRYPTO", "OS", "math/big", "syscall", "internal/syscall/unix"},
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// Mathematical crypto: dependencies on fmt (L4) and math/big.
 | 
					 | 
				
			||||||
	// We could avoid some of the fmt, but math/big imports fmt anyway.
 | 
					 | 
				
			||||||
	"crypto/dsa":      {"L4", "CRYPTO", "math/big"},
 | 
					 | 
				
			||||||
	"crypto/ecdsa":    {"L4", "CRYPTO", "crypto/elliptic", "math/big", "encoding/asn1"},
 | 
					 | 
				
			||||||
	"crypto/elliptic": {"L4", "CRYPTO", "math/big"},
 | 
					 | 
				
			||||||
	"crypto/rsa":      {"L4", "CRYPTO", "crypto/rand", "math/big"},
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	"CRYPTO-MATH": {
 | 
					 | 
				
			||||||
		"CRYPTO",
 | 
					 | 
				
			||||||
		"crypto/dsa",
 | 
					 | 
				
			||||||
		"crypto/ecdsa",
 | 
					 | 
				
			||||||
		"crypto/elliptic",
 | 
					 | 
				
			||||||
		"crypto/rand",
 | 
					 | 
				
			||||||
		"crypto/rsa",
 | 
					 | 
				
			||||||
		"encoding/asn1",
 | 
					 | 
				
			||||||
		"math/big",
 | 
					 | 
				
			||||||
	},
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// SSL/TLS.
 | 
					 | 
				
			||||||
	"crypto/tls": {
 | 
					 | 
				
			||||||
		"L4", "CRYPTO-MATH", "OS",
 | 
					 | 
				
			||||||
		"container/list", "crypto/x509", "encoding/pem", "net", "syscall",
 | 
					 | 
				
			||||||
	},
 | 
					 | 
				
			||||||
	"crypto/x509": {
 | 
					 | 
				
			||||||
		"L4", "CRYPTO-MATH", "OS", "CGO",
 | 
					 | 
				
			||||||
		"crypto/x509/pkix", "encoding/pem", "encoding/hex", "net", "syscall",
 | 
					 | 
				
			||||||
	},
 | 
					 | 
				
			||||||
	"crypto/x509/pkix": {"L4", "CRYPTO-MATH"},
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// Simple net+crypto-aware packages.
 | 
					 | 
				
			||||||
	"mime/multipart": {"L4", "OS", "mime", "crypto/rand", "net/textproto", "mime/quotedprintable"},
 | 
					 | 
				
			||||||
	"net/smtp":       {"L4", "CRYPTO", "NET", "crypto/tls"},
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// HTTP, kingpin of dependencies.
 | 
					 | 
				
			||||||
	"net/http": {
 | 
					 | 
				
			||||||
		"L4", "NET", "OS",
 | 
					 | 
				
			||||||
		"compress/gzip", "crypto/tls", "mime/multipart", "runtime/debug",
 | 
					 | 
				
			||||||
		"net/http/internal",
 | 
					 | 
				
			||||||
		"internal/golang.org/x/net/http2/hpack",
 | 
					 | 
				
			||||||
	},
 | 
					 | 
				
			||||||
	"net/http/internal": {"L4"},
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// HTTP-using packages.
 | 
					 | 
				
			||||||
	"expvar":             {"L4", "OS", "encoding/json", "net/http"},
 | 
					 | 
				
			||||||
	"net/http/cgi":       {"L4", "NET", "OS", "crypto/tls", "net/http", "regexp"},
 | 
					 | 
				
			||||||
	"net/http/cookiejar": {"L4", "NET", "net/http"},
 | 
					 | 
				
			||||||
	"net/http/fcgi":      {"L4", "NET", "OS", "net/http", "net/http/cgi"},
 | 
					 | 
				
			||||||
	"net/http/httptest":  {"L4", "NET", "OS", "crypto/tls", "flag", "net/http", "net/http/internal"},
 | 
					 | 
				
			||||||
	"net/http/httputil":  {"L4", "NET", "OS", "net/http", "net/http/internal"},
 | 
					 | 
				
			||||||
	"net/http/pprof":     {"L4", "OS", "html/template", "net/http", "runtime/pprof", "runtime/trace"},
 | 
					 | 
				
			||||||
	"net/rpc":            {"L4", "NET", "encoding/gob", "html/template", "net/http"},
 | 
					 | 
				
			||||||
	"net/rpc/jsonrpc":    {"L4", "NET", "encoding/json", "net/rpc"},
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// isMacro reports whether p is a package dependency macro
 | 
					 | 
				
			||||||
// (uppercase name).
 | 
					 | 
				
			||||||
func isMacro(p string) bool {
 | 
					 | 
				
			||||||
	return 'A' <= p[0] && p[0] <= 'Z'
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func allowed(pkg string) map[string]bool {
 | 
					 | 
				
			||||||
	m := map[string]bool{}
 | 
					 | 
				
			||||||
	var allow func(string)
 | 
					 | 
				
			||||||
	allow = func(p string) {
 | 
					 | 
				
			||||||
		if m[p] {
 | 
					 | 
				
			||||||
			return
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		m[p] = true // set even for macros, to avoid loop on cycle
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		// Upper-case names are macro-expanded.
 | 
					 | 
				
			||||||
		if isMacro(p) {
 | 
					 | 
				
			||||||
			for _, pp := range pkgDeps[p] {
 | 
					 | 
				
			||||||
				allow(pp)
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	for _, pp := range pkgDeps[pkg] {
 | 
					 | 
				
			||||||
		allow(pp)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return m
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
var bools = []bool{false, true}
 | 
					 | 
				
			||||||
var geese = []string{"android", "darwin", "dragonfly", "freebsd", "linux", "nacl", "netbsd", "openbsd", "plan9", "solaris", "windows"}
 | 
					 | 
				
			||||||
var goarches = []string{"386", "amd64", "arm"}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
type osPkg struct {
 | 
					 | 
				
			||||||
	goos, pkg string
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// allowedErrors are the operating systems and packages known to contain errors
 | 
					 | 
				
			||||||
// (currently just "no Go source files")
 | 
					 | 
				
			||||||
var allowedErrors = map[osPkg]bool{
 | 
					 | 
				
			||||||
	osPkg{"windows", "log/syslog"}: true,
 | 
					 | 
				
			||||||
	osPkg{"plan9", "log/syslog"}:   true,
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// listStdPkgs returns the same list of packages as "go list std".
 | 
					 | 
				
			||||||
func listStdPkgs(goroot string) ([]string, error) {
 | 
					 | 
				
			||||||
	// Based on cmd/go's matchPackages function.
 | 
					 | 
				
			||||||
	var pkgs []string
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	src := filepath.Join(goroot, "src") + string(filepath.Separator)
 | 
					 | 
				
			||||||
	walkFn := func(path string, fi os.FileInfo, err error) error {
 | 
					 | 
				
			||||||
		if err != nil || !fi.IsDir() || path == src {
 | 
					 | 
				
			||||||
			return nil
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		base := filepath.Base(path)
 | 
					 | 
				
			||||||
		if strings.HasPrefix(base, ".") || strings.HasPrefix(base, "_") || base == "testdata" {
 | 
					 | 
				
			||||||
			return filepath.SkipDir
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		name := filepath.ToSlash(path[len(src):])
 | 
					 | 
				
			||||||
		if name == "builtin" || name == "cmd" || strings.Contains(name, ".") {
 | 
					 | 
				
			||||||
			return filepath.SkipDir
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		pkgs = append(pkgs, name)
 | 
					 | 
				
			||||||
		return nil
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	if err := filepath.Walk(src, walkFn); err != nil {
 | 
					 | 
				
			||||||
		return nil, err
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return pkgs, nil
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func TestDependencies(t *testing.T) {
 | 
					 | 
				
			||||||
	iOS := runtime.GOOS == "darwin" && (runtime.GOARCH == "arm" || runtime.GOARCH == "arm64")
 | 
					 | 
				
			||||||
	if runtime.GOOS == "nacl" || iOS {
 | 
					 | 
				
			||||||
		// Tests run in a limited file system and we do not
 | 
					 | 
				
			||||||
		// provide access to every source file.
 | 
					 | 
				
			||||||
		t.Skipf("skipping on %s/%s, missing full GOROOT", runtime.GOOS, runtime.GOARCH)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	ctxt := Default
 | 
					 | 
				
			||||||
	all, err := listStdPkgs(ctxt.GOROOT)
 | 
					 | 
				
			||||||
	if err != nil {
 | 
					 | 
				
			||||||
		t.Fatal(err)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	sort.Strings(all)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	for _, pkg := range all {
 | 
					 | 
				
			||||||
		imports, err := findImports(pkg)
 | 
					 | 
				
			||||||
		if err != nil {
 | 
					 | 
				
			||||||
			t.Error(err)
 | 
					 | 
				
			||||||
			continue
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		ok := allowed(pkg)
 | 
					 | 
				
			||||||
		var bad []string
 | 
					 | 
				
			||||||
		for _, imp := range imports {
 | 
					 | 
				
			||||||
			if !ok[imp] {
 | 
					 | 
				
			||||||
				bad = append(bad, imp)
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		if bad != nil {
 | 
					 | 
				
			||||||
			t.Errorf("unexpected dependency: %s imports %v", pkg, bad)
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
var buildIgnore = []byte("\n// +build ignore")
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func findImports(pkg string) ([]string, error) {
 | 
					 | 
				
			||||||
	dir := filepath.Join(Default.GOROOT, "src", pkg)
 | 
					 | 
				
			||||||
	files, err := ioutil.ReadDir(dir)
 | 
					 | 
				
			||||||
	if err != nil {
 | 
					 | 
				
			||||||
		return nil, err
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	var imports []string
 | 
					 | 
				
			||||||
	var haveImport = map[string]bool{}
 | 
					 | 
				
			||||||
	for _, file := range files {
 | 
					 | 
				
			||||||
		name := file.Name()
 | 
					 | 
				
			||||||
		if !strings.HasSuffix(name, ".go") || strings.HasSuffix(name, "_test.go") {
 | 
					 | 
				
			||||||
			continue
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		f, err := os.Open(filepath.Join(dir, name))
 | 
					 | 
				
			||||||
		if err != nil {
 | 
					 | 
				
			||||||
			return nil, err
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		var imp []string
 | 
					 | 
				
			||||||
		data, err := readImports(f, false, &imp)
 | 
					 | 
				
			||||||
		f.Close()
 | 
					 | 
				
			||||||
		if err != nil {
 | 
					 | 
				
			||||||
			return nil, fmt.Errorf("reading %v: %v", name, err)
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		if bytes.Contains(data, buildIgnore) {
 | 
					 | 
				
			||||||
			continue
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		for _, quoted := range imp {
 | 
					 | 
				
			||||||
			path, err := strconv.Unquote(quoted)
 | 
					 | 
				
			||||||
			if err != nil {
 | 
					 | 
				
			||||||
				continue
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
			if !haveImport[path] {
 | 
					 | 
				
			||||||
				haveImport[path] = true
 | 
					 | 
				
			||||||
				imports = append(imports, path)
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	sort.Strings(imports)
 | 
					 | 
				
			||||||
	return imports, nil
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
							
								
								
									
										141
									
								
								third_party/golang/go/build/doc.go
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										141
									
								
								third_party/golang/go/build/doc.go
									
									
									
									
										vendored
									
									
								
							@@ -1,141 +0,0 @@
 | 
				
			|||||||
// Copyright 2011 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 build gathers information about Go packages.
 | 
					 | 
				
			||||||
//
 | 
					 | 
				
			||||||
// Go Path
 | 
					 | 
				
			||||||
//
 | 
					 | 
				
			||||||
// The Go path is a list of directory trees containing Go source code.
 | 
					 | 
				
			||||||
// It is consulted to resolve imports that cannot be found in the standard
 | 
					 | 
				
			||||||
// Go tree.  The default path is the value of the GOPATH environment
 | 
					 | 
				
			||||||
// variable, interpreted as a path list appropriate to the operating system
 | 
					 | 
				
			||||||
// (on Unix, the variable is a colon-separated string;
 | 
					 | 
				
			||||||
// on Windows, a semicolon-separated string;
 | 
					 | 
				
			||||||
// on Plan 9, a list).
 | 
					 | 
				
			||||||
//
 | 
					 | 
				
			||||||
// Each directory listed in the Go path must have a prescribed structure:
 | 
					 | 
				
			||||||
//
 | 
					 | 
				
			||||||
// The src/ directory holds source code.  The path below 'src' determines
 | 
					 | 
				
			||||||
// the import path or executable name.
 | 
					 | 
				
			||||||
//
 | 
					 | 
				
			||||||
// The pkg/ directory holds installed package objects.
 | 
					 | 
				
			||||||
// As in the Go tree, each target operating system and
 | 
					 | 
				
			||||||
// architecture pair has its own subdirectory of pkg
 | 
					 | 
				
			||||||
// (pkg/GOOS_GOARCH).
 | 
					 | 
				
			||||||
//
 | 
					 | 
				
			||||||
// If DIR is a directory listed in the Go path, a package with
 | 
					 | 
				
			||||||
// source in DIR/src/foo/bar can be imported as "foo/bar" and
 | 
					 | 
				
			||||||
// has its compiled form installed to "DIR/pkg/GOOS_GOARCH/foo/bar.a"
 | 
					 | 
				
			||||||
// (or, for gccgo, "DIR/pkg/gccgo/foo/libbar.a").
 | 
					 | 
				
			||||||
//
 | 
					 | 
				
			||||||
// The bin/ directory holds compiled commands.
 | 
					 | 
				
			||||||
// Each command is named for its source directory, but only
 | 
					 | 
				
			||||||
// using the final element, not the entire path.  That is, the
 | 
					 | 
				
			||||||
// command with source in DIR/src/foo/quux is installed into
 | 
					 | 
				
			||||||
// DIR/bin/quux, not DIR/bin/foo/quux.  The foo/ is stripped
 | 
					 | 
				
			||||||
// so that you can add DIR/bin to your PATH to get at the
 | 
					 | 
				
			||||||
// installed commands.
 | 
					 | 
				
			||||||
//
 | 
					 | 
				
			||||||
// Here's an example directory layout:
 | 
					 | 
				
			||||||
//
 | 
					 | 
				
			||||||
//	GOPATH=/home/user/gocode
 | 
					 | 
				
			||||||
//
 | 
					 | 
				
			||||||
//	/home/user/gocode/
 | 
					 | 
				
			||||||
//	    src/
 | 
					 | 
				
			||||||
//	        foo/
 | 
					 | 
				
			||||||
//	            bar/               (go code in package bar)
 | 
					 | 
				
			||||||
//	                x.go
 | 
					 | 
				
			||||||
//	            quux/              (go code in package main)
 | 
					 | 
				
			||||||
//	                y.go
 | 
					 | 
				
			||||||
//	    bin/
 | 
					 | 
				
			||||||
//	        quux                   (installed command)
 | 
					 | 
				
			||||||
//	    pkg/
 | 
					 | 
				
			||||||
//	        linux_amd64/
 | 
					 | 
				
			||||||
//	            foo/
 | 
					 | 
				
			||||||
//	                bar.a          (installed package object)
 | 
					 | 
				
			||||||
//
 | 
					 | 
				
			||||||
// Build Constraints
 | 
					 | 
				
			||||||
//
 | 
					 | 
				
			||||||
// A build constraint, also known as a build tag, is a line comment that begins
 | 
					 | 
				
			||||||
//
 | 
					 | 
				
			||||||
//	// +build
 | 
					 | 
				
			||||||
//
 | 
					 | 
				
			||||||
// that lists the conditions under which a file should be included in the package.
 | 
					 | 
				
			||||||
// Constraints may appear in any kind of source file (not just Go), but
 | 
					 | 
				
			||||||
// they must appear near the top of the file, preceded
 | 
					 | 
				
			||||||
// only by blank lines and other line comments. These rules mean that in Go
 | 
					 | 
				
			||||||
// files a build constraint must appear before the package clause.
 | 
					 | 
				
			||||||
//
 | 
					 | 
				
			||||||
// To distinguish build constraints from package documentation, a series of
 | 
					 | 
				
			||||||
// build constraints must be followed by a blank line.
 | 
					 | 
				
			||||||
//
 | 
					 | 
				
			||||||
// A build constraint is evaluated as the OR of space-separated options;
 | 
					 | 
				
			||||||
// each option evaluates as the AND of its comma-separated terms;
 | 
					 | 
				
			||||||
// and each term is an alphanumeric word or, preceded by !, its negation.
 | 
					 | 
				
			||||||
// That is, the build constraint:
 | 
					 | 
				
			||||||
//
 | 
					 | 
				
			||||||
//	// +build linux,386 darwin,!cgo
 | 
					 | 
				
			||||||
//
 | 
					 | 
				
			||||||
// corresponds to the boolean formula:
 | 
					 | 
				
			||||||
//
 | 
					 | 
				
			||||||
//	(linux AND 386) OR (darwin AND (NOT cgo))
 | 
					 | 
				
			||||||
//
 | 
					 | 
				
			||||||
// A file may have multiple build constraints. The overall constraint is the AND
 | 
					 | 
				
			||||||
// of the individual constraints. That is, the build constraints:
 | 
					 | 
				
			||||||
//
 | 
					 | 
				
			||||||
//	// +build linux darwin
 | 
					 | 
				
			||||||
//	// +build 386
 | 
					 | 
				
			||||||
//
 | 
					 | 
				
			||||||
// corresponds to the boolean formula:
 | 
					 | 
				
			||||||
//
 | 
					 | 
				
			||||||
//	(linux OR darwin) AND 386
 | 
					 | 
				
			||||||
//
 | 
					 | 
				
			||||||
// During a particular build, the following words are satisfied:
 | 
					 | 
				
			||||||
//
 | 
					 | 
				
			||||||
//	- the target operating system, as spelled by runtime.GOOS
 | 
					 | 
				
			||||||
//	- the target architecture, as spelled by runtime.GOARCH
 | 
					 | 
				
			||||||
//	- the compiler being used, either "gc" or "gccgo"
 | 
					 | 
				
			||||||
//	- "cgo", if ctxt.CgoEnabled is true
 | 
					 | 
				
			||||||
//	- "go1.1", from Go version 1.1 onward
 | 
					 | 
				
			||||||
//	- "go1.2", from Go version 1.2 onward
 | 
					 | 
				
			||||||
//	- "go1.3", from Go version 1.3 onward
 | 
					 | 
				
			||||||
//	- "go1.4", from Go version 1.4 onward
 | 
					 | 
				
			||||||
//	- "go1.5", from Go version 1.5 onward
 | 
					 | 
				
			||||||
//	- "go1.6", from Go version 1.6 onward
 | 
					 | 
				
			||||||
//	- any additional words listed in ctxt.BuildTags
 | 
					 | 
				
			||||||
//
 | 
					 | 
				
			||||||
// If a file's name, after stripping the extension and a possible _test suffix,
 | 
					 | 
				
			||||||
// matches any of the following patterns:
 | 
					 | 
				
			||||||
//	*_GOOS
 | 
					 | 
				
			||||||
// 	*_GOARCH
 | 
					 | 
				
			||||||
// 	*_GOOS_GOARCH
 | 
					 | 
				
			||||||
// (example: source_windows_amd64.go) where GOOS and GOARCH represent
 | 
					 | 
				
			||||||
// any known operating system and architecture values respectively, then
 | 
					 | 
				
			||||||
// the file is considered to have an implicit build constraint requiring
 | 
					 | 
				
			||||||
// those terms (in addition to any explicit constraints in the file).
 | 
					 | 
				
			||||||
//
 | 
					 | 
				
			||||||
// To keep a file from being considered for the build:
 | 
					 | 
				
			||||||
//
 | 
					 | 
				
			||||||
//	// +build ignore
 | 
					 | 
				
			||||||
//
 | 
					 | 
				
			||||||
// (any other unsatisfied word will work as well, but ``ignore'' is conventional.)
 | 
					 | 
				
			||||||
//
 | 
					 | 
				
			||||||
// To build a file only when using cgo, and only on Linux and OS X:
 | 
					 | 
				
			||||||
//
 | 
					 | 
				
			||||||
//	// +build linux,cgo darwin,cgo
 | 
					 | 
				
			||||||
//
 | 
					 | 
				
			||||||
// Such a file is usually paired with another file implementing the
 | 
					 | 
				
			||||||
// default functionality for other systems, which in this case would
 | 
					 | 
				
			||||||
// carry the constraint:
 | 
					 | 
				
			||||||
//
 | 
					 | 
				
			||||||
//	// +build !linux,!darwin !cgo
 | 
					 | 
				
			||||||
//
 | 
					 | 
				
			||||||
// Naming a file dns_windows.go will cause it to be included only when
 | 
					 | 
				
			||||||
// building the package for Windows; similarly, math_386.s will be included
 | 
					 | 
				
			||||||
// only when building the package for 32-bit x86.
 | 
					 | 
				
			||||||
//
 | 
					 | 
				
			||||||
// Using GOOS=android matches build tags and files as for GOOS=linux
 | 
					 | 
				
			||||||
// in addition to android tags and files.
 | 
					 | 
				
			||||||
//
 | 
					 | 
				
			||||||
package build
 | 
					 | 
				
			||||||
							
								
								
									
										246
									
								
								third_party/golang/go/build/read.go
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										246
									
								
								third_party/golang/go/build/read.go
									
									
									
									
										vendored
									
									
								
							@@ -1,246 +0,0 @@
 | 
				
			|||||||
// Copyright 2012 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 build
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
import (
 | 
					 | 
				
			||||||
	"bufio"
 | 
					 | 
				
			||||||
	"errors"
 | 
					 | 
				
			||||||
	"io"
 | 
					 | 
				
			||||||
)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
type importReader struct {
 | 
					 | 
				
			||||||
	b    *bufio.Reader
 | 
					 | 
				
			||||||
	buf  []byte
 | 
					 | 
				
			||||||
	peek byte
 | 
					 | 
				
			||||||
	err  error
 | 
					 | 
				
			||||||
	eof  bool
 | 
					 | 
				
			||||||
	nerr int
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func isIdent(c byte) bool {
 | 
					 | 
				
			||||||
	return 'A' <= c && c <= 'Z' || 'a' <= c && c <= 'z' || '0' <= c && c <= '9' || c == '_' || c >= 0x80
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
var (
 | 
					 | 
				
			||||||
	errSyntax = errors.New("syntax error")
 | 
					 | 
				
			||||||
	errNUL    = errors.New("unexpected NUL in input")
 | 
					 | 
				
			||||||
)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// syntaxError records a syntax error, but only if an I/O error has not already been recorded.
 | 
					 | 
				
			||||||
func (r *importReader) syntaxError() {
 | 
					 | 
				
			||||||
	if r.err == nil {
 | 
					 | 
				
			||||||
		r.err = errSyntax
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// readByte reads the next byte from the input, saves it in buf, and returns it.
 | 
					 | 
				
			||||||
// If an error occurs, readByte records the error in r.err and returns 0.
 | 
					 | 
				
			||||||
func (r *importReader) readByte() byte {
 | 
					 | 
				
			||||||
	c, err := r.b.ReadByte()
 | 
					 | 
				
			||||||
	if err == nil {
 | 
					 | 
				
			||||||
		r.buf = append(r.buf, c)
 | 
					 | 
				
			||||||
		if c == 0 {
 | 
					 | 
				
			||||||
			err = errNUL
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	if err != nil {
 | 
					 | 
				
			||||||
		if err == io.EOF {
 | 
					 | 
				
			||||||
			r.eof = true
 | 
					 | 
				
			||||||
		} else if r.err == nil {
 | 
					 | 
				
			||||||
			r.err = err
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		c = 0
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return c
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// peekByte returns the next byte from the input reader but does not advance beyond it.
 | 
					 | 
				
			||||||
// If skipSpace is set, peekByte skips leading spaces and comments.
 | 
					 | 
				
			||||||
func (r *importReader) peekByte(skipSpace bool) byte {
 | 
					 | 
				
			||||||
	if r.err != nil {
 | 
					 | 
				
			||||||
		if r.nerr++; r.nerr > 10000 {
 | 
					 | 
				
			||||||
			panic("go/build: import reader looping")
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		return 0
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// Use r.peek as first input byte.
 | 
					 | 
				
			||||||
	// Don't just return r.peek here: it might have been left by peekByte(false)
 | 
					 | 
				
			||||||
	// and this might be peekByte(true).
 | 
					 | 
				
			||||||
	c := r.peek
 | 
					 | 
				
			||||||
	if c == 0 {
 | 
					 | 
				
			||||||
		c = r.readByte()
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	for r.err == nil && !r.eof {
 | 
					 | 
				
			||||||
		if skipSpace {
 | 
					 | 
				
			||||||
			// For the purposes of this reader, semicolons are never necessary to
 | 
					 | 
				
			||||||
			// understand the input and are treated as spaces.
 | 
					 | 
				
			||||||
			switch c {
 | 
					 | 
				
			||||||
			case ' ', '\f', '\t', '\r', '\n', ';':
 | 
					 | 
				
			||||||
				c = r.readByte()
 | 
					 | 
				
			||||||
				continue
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			case '/':
 | 
					 | 
				
			||||||
				c = r.readByte()
 | 
					 | 
				
			||||||
				if c == '/' {
 | 
					 | 
				
			||||||
					for c != '\n' && r.err == nil && !r.eof {
 | 
					 | 
				
			||||||
						c = r.readByte()
 | 
					 | 
				
			||||||
					}
 | 
					 | 
				
			||||||
				} else if c == '*' {
 | 
					 | 
				
			||||||
					var c1 byte
 | 
					 | 
				
			||||||
					for (c != '*' || c1 != '/') && r.err == nil {
 | 
					 | 
				
			||||||
						if r.eof {
 | 
					 | 
				
			||||||
							r.syntaxError()
 | 
					 | 
				
			||||||
						}
 | 
					 | 
				
			||||||
						c, c1 = c1, r.readByte()
 | 
					 | 
				
			||||||
					}
 | 
					 | 
				
			||||||
				} else {
 | 
					 | 
				
			||||||
					r.syntaxError()
 | 
					 | 
				
			||||||
				}
 | 
					 | 
				
			||||||
				c = r.readByte()
 | 
					 | 
				
			||||||
				continue
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		break
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	r.peek = c
 | 
					 | 
				
			||||||
	return r.peek
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// nextByte is like peekByte but advances beyond the returned byte.
 | 
					 | 
				
			||||||
func (r *importReader) nextByte(skipSpace bool) byte {
 | 
					 | 
				
			||||||
	c := r.peekByte(skipSpace)
 | 
					 | 
				
			||||||
	r.peek = 0
 | 
					 | 
				
			||||||
	return c
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// readKeyword reads the given keyword from the input.
 | 
					 | 
				
			||||||
// If the keyword is not present, readKeyword records a syntax error.
 | 
					 | 
				
			||||||
func (r *importReader) readKeyword(kw string) {
 | 
					 | 
				
			||||||
	r.peekByte(true)
 | 
					 | 
				
			||||||
	for i := 0; i < len(kw); i++ {
 | 
					 | 
				
			||||||
		if r.nextByte(false) != kw[i] {
 | 
					 | 
				
			||||||
			r.syntaxError()
 | 
					 | 
				
			||||||
			return
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	if isIdent(r.peekByte(false)) {
 | 
					 | 
				
			||||||
		r.syntaxError()
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// readIdent reads an identifier from the input.
 | 
					 | 
				
			||||||
// If an identifier is not present, readIdent records a syntax error.
 | 
					 | 
				
			||||||
func (r *importReader) readIdent() {
 | 
					 | 
				
			||||||
	c := r.peekByte(true)
 | 
					 | 
				
			||||||
	if !isIdent(c) {
 | 
					 | 
				
			||||||
		r.syntaxError()
 | 
					 | 
				
			||||||
		return
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	for isIdent(r.peekByte(false)) {
 | 
					 | 
				
			||||||
		r.peek = 0
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// readString reads a quoted string literal from the input.
 | 
					 | 
				
			||||||
// If an identifier is not present, readString records a syntax error.
 | 
					 | 
				
			||||||
func (r *importReader) readString(save *[]string) {
 | 
					 | 
				
			||||||
	switch r.nextByte(true) {
 | 
					 | 
				
			||||||
	case '`':
 | 
					 | 
				
			||||||
		start := len(r.buf) - 1
 | 
					 | 
				
			||||||
		for r.err == nil {
 | 
					 | 
				
			||||||
			if r.nextByte(false) == '`' {
 | 
					 | 
				
			||||||
				if save != nil {
 | 
					 | 
				
			||||||
					*save = append(*save, string(r.buf[start:]))
 | 
					 | 
				
			||||||
				}
 | 
					 | 
				
			||||||
				break
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
			if r.eof {
 | 
					 | 
				
			||||||
				r.syntaxError()
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	case '"':
 | 
					 | 
				
			||||||
		start := len(r.buf) - 1
 | 
					 | 
				
			||||||
		for r.err == nil {
 | 
					 | 
				
			||||||
			c := r.nextByte(false)
 | 
					 | 
				
			||||||
			if c == '"' {
 | 
					 | 
				
			||||||
				if save != nil {
 | 
					 | 
				
			||||||
					*save = append(*save, string(r.buf[start:]))
 | 
					 | 
				
			||||||
				}
 | 
					 | 
				
			||||||
				break
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
			if r.eof || c == '\n' {
 | 
					 | 
				
			||||||
				r.syntaxError()
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
			if c == '\\' {
 | 
					 | 
				
			||||||
				r.nextByte(false)
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	default:
 | 
					 | 
				
			||||||
		r.syntaxError()
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// readImport reads an import clause - optional identifier followed by quoted string -
 | 
					 | 
				
			||||||
// from the input.
 | 
					 | 
				
			||||||
func (r *importReader) readImport(imports *[]string) {
 | 
					 | 
				
			||||||
	c := r.peekByte(true)
 | 
					 | 
				
			||||||
	if c == '.' {
 | 
					 | 
				
			||||||
		r.peek = 0
 | 
					 | 
				
			||||||
	} else if isIdent(c) {
 | 
					 | 
				
			||||||
		r.readIdent()
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	r.readString(imports)
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// readComments is like ioutil.ReadAll, except that it only reads the leading
 | 
					 | 
				
			||||||
// block of comments in the file.
 | 
					 | 
				
			||||||
func readComments(f io.Reader) ([]byte, error) {
 | 
					 | 
				
			||||||
	r := &importReader{b: bufio.NewReader(f)}
 | 
					 | 
				
			||||||
	r.peekByte(true)
 | 
					 | 
				
			||||||
	if r.err == nil && !r.eof {
 | 
					 | 
				
			||||||
		// Didn't reach EOF, so must have found a non-space byte. Remove it.
 | 
					 | 
				
			||||||
		r.buf = r.buf[:len(r.buf)-1]
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return r.buf, r.err
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// readImports is like ioutil.ReadAll, except that it expects a Go file as input
 | 
					 | 
				
			||||||
// and stops reading the input once the imports have completed.
 | 
					 | 
				
			||||||
func readImports(f io.Reader, reportSyntaxError bool, imports *[]string) ([]byte, error) {
 | 
					 | 
				
			||||||
	r := &importReader{b: bufio.NewReader(f)}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	r.readKeyword("package")
 | 
					 | 
				
			||||||
	r.readIdent()
 | 
					 | 
				
			||||||
	for r.peekByte(true) == 'i' {
 | 
					 | 
				
			||||||
		r.readKeyword("import")
 | 
					 | 
				
			||||||
		if r.peekByte(true) == '(' {
 | 
					 | 
				
			||||||
			r.nextByte(false)
 | 
					 | 
				
			||||||
			for r.peekByte(true) != ')' && r.err == nil {
 | 
					 | 
				
			||||||
				r.readImport(imports)
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
			r.nextByte(false)
 | 
					 | 
				
			||||||
		} else {
 | 
					 | 
				
			||||||
			r.readImport(imports)
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// If we stopped successfully before EOF, we read a byte that told us we were done.
 | 
					 | 
				
			||||||
	// Return all but that last byte, which would cause a syntax error if we let it through.
 | 
					 | 
				
			||||||
	if r.err == nil && !r.eof {
 | 
					 | 
				
			||||||
		return r.buf[:len(r.buf)-1], nil
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// If we stopped for a syntax error, consume the whole file so that
 | 
					 | 
				
			||||||
	// we are sure we don't change the errors that go/parser returns.
 | 
					 | 
				
			||||||
	if r.err == errSyntax && !reportSyntaxError {
 | 
					 | 
				
			||||||
		r.err = nil
 | 
					 | 
				
			||||||
		for r.err == nil && !r.eof {
 | 
					 | 
				
			||||||
			r.readByte()
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return r.buf, r.err
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
							
								
								
									
										226
									
								
								third_party/golang/go/build/read_test.go
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										226
									
								
								third_party/golang/go/build/read_test.go
									
									
									
									
										vendored
									
									
								
							@@ -1,226 +0,0 @@
 | 
				
			|||||||
// Copyright 2012 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 build
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
import (
 | 
					 | 
				
			||||||
	"io"
 | 
					 | 
				
			||||||
	"strings"
 | 
					 | 
				
			||||||
	"testing"
 | 
					 | 
				
			||||||
)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
const quote = "`"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
type readTest struct {
 | 
					 | 
				
			||||||
	// Test input contains ℙ where readImports should stop.
 | 
					 | 
				
			||||||
	in  string
 | 
					 | 
				
			||||||
	err string
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
var readImportsTests = []readTest{
 | 
					 | 
				
			||||||
	{
 | 
					 | 
				
			||||||
		`package p`,
 | 
					 | 
				
			||||||
		"",
 | 
					 | 
				
			||||||
	},
 | 
					 | 
				
			||||||
	{
 | 
					 | 
				
			||||||
		`package p; import "x"`,
 | 
					 | 
				
			||||||
		"",
 | 
					 | 
				
			||||||
	},
 | 
					 | 
				
			||||||
	{
 | 
					 | 
				
			||||||
		`package p; import . "x"`,
 | 
					 | 
				
			||||||
		"",
 | 
					 | 
				
			||||||
	},
 | 
					 | 
				
			||||||
	{
 | 
					 | 
				
			||||||
		`package p; import "x";ℙvar x = 1`,
 | 
					 | 
				
			||||||
		"",
 | 
					 | 
				
			||||||
	},
 | 
					 | 
				
			||||||
	{
 | 
					 | 
				
			||||||
		`package p
 | 
					 | 
				
			||||||
		
 | 
					 | 
				
			||||||
		// comment
 | 
					 | 
				
			||||||
		
 | 
					 | 
				
			||||||
		import "x"
 | 
					 | 
				
			||||||
		import _ "x"
 | 
					 | 
				
			||||||
		import a "x"
 | 
					 | 
				
			||||||
		
 | 
					 | 
				
			||||||
		/* comment */
 | 
					 | 
				
			||||||
		
 | 
					 | 
				
			||||||
		import (
 | 
					 | 
				
			||||||
			"x" /* comment */
 | 
					 | 
				
			||||||
			_ "x"
 | 
					 | 
				
			||||||
			a "x" // comment
 | 
					 | 
				
			||||||
			` + quote + `x` + quote + `
 | 
					 | 
				
			||||||
			_ /*comment*/ ` + quote + `x` + quote + `
 | 
					 | 
				
			||||||
			a ` + quote + `x` + quote + `
 | 
					 | 
				
			||||||
		)
 | 
					 | 
				
			||||||
		import (
 | 
					 | 
				
			||||||
		)
 | 
					 | 
				
			||||||
		import ()
 | 
					 | 
				
			||||||
		import()import()import()
 | 
					 | 
				
			||||||
		import();import();import()
 | 
					 | 
				
			||||||
		
 | 
					 | 
				
			||||||
		ℙvar x = 1
 | 
					 | 
				
			||||||
		`,
 | 
					 | 
				
			||||||
		"",
 | 
					 | 
				
			||||||
	},
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
var readCommentsTests = []readTest{
 | 
					 | 
				
			||||||
	{
 | 
					 | 
				
			||||||
		`ℙpackage p`,
 | 
					 | 
				
			||||||
		"",
 | 
					 | 
				
			||||||
	},
 | 
					 | 
				
			||||||
	{
 | 
					 | 
				
			||||||
		`ℙpackage p; import "x"`,
 | 
					 | 
				
			||||||
		"",
 | 
					 | 
				
			||||||
	},
 | 
					 | 
				
			||||||
	{
 | 
					 | 
				
			||||||
		`ℙpackage p; import . "x"`,
 | 
					 | 
				
			||||||
		"",
 | 
					 | 
				
			||||||
	},
 | 
					 | 
				
			||||||
	{
 | 
					 | 
				
			||||||
		`// foo
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		/* bar */
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		/* quux */ // baz
 | 
					 | 
				
			||||||
		
 | 
					 | 
				
			||||||
		/*/ zot */
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		// asdf
 | 
					 | 
				
			||||||
		ℙHello, world`,
 | 
					 | 
				
			||||||
		"",
 | 
					 | 
				
			||||||
	},
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func testRead(t *testing.T, tests []readTest, read func(io.Reader) ([]byte, error)) {
 | 
					 | 
				
			||||||
	for i, tt := range tests {
 | 
					 | 
				
			||||||
		var in, testOut string
 | 
					 | 
				
			||||||
		j := strings.Index(tt.in, "ℙ")
 | 
					 | 
				
			||||||
		if j < 0 {
 | 
					 | 
				
			||||||
			in = tt.in
 | 
					 | 
				
			||||||
			testOut = tt.in
 | 
					 | 
				
			||||||
		} else {
 | 
					 | 
				
			||||||
			in = tt.in[:j] + tt.in[j+len("ℙ"):]
 | 
					 | 
				
			||||||
			testOut = tt.in[:j]
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		r := strings.NewReader(in)
 | 
					 | 
				
			||||||
		buf, err := read(r)
 | 
					 | 
				
			||||||
		if err != nil {
 | 
					 | 
				
			||||||
			if tt.err == "" {
 | 
					 | 
				
			||||||
				t.Errorf("#%d: err=%q, expected success (%q)", i, err, string(buf))
 | 
					 | 
				
			||||||
				continue
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
			if !strings.Contains(err.Error(), tt.err) {
 | 
					 | 
				
			||||||
				t.Errorf("#%d: err=%q, expected %q", i, err, tt.err)
 | 
					 | 
				
			||||||
				continue
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
			continue
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		if err == nil && tt.err != "" {
 | 
					 | 
				
			||||||
			t.Errorf("#%d: success, expected %q", i, tt.err)
 | 
					 | 
				
			||||||
			continue
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		out := string(buf)
 | 
					 | 
				
			||||||
		if out != testOut {
 | 
					 | 
				
			||||||
			t.Errorf("#%d: wrong output:\nhave %q\nwant %q\n", i, out, testOut)
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func TestReadImports(t *testing.T) {
 | 
					 | 
				
			||||||
	testRead(t, readImportsTests, func(r io.Reader) ([]byte, error) { return readImports(r, true, nil) })
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func TestReadComments(t *testing.T) {
 | 
					 | 
				
			||||||
	testRead(t, readCommentsTests, readComments)
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
var readFailuresTests = []readTest{
 | 
					 | 
				
			||||||
	{
 | 
					 | 
				
			||||||
		`package`,
 | 
					 | 
				
			||||||
		"syntax error",
 | 
					 | 
				
			||||||
	},
 | 
					 | 
				
			||||||
	{
 | 
					 | 
				
			||||||
		"package p\n\x00\nimport `math`\n",
 | 
					 | 
				
			||||||
		"unexpected NUL in input",
 | 
					 | 
				
			||||||
	},
 | 
					 | 
				
			||||||
	{
 | 
					 | 
				
			||||||
		`package p; import`,
 | 
					 | 
				
			||||||
		"syntax error",
 | 
					 | 
				
			||||||
	},
 | 
					 | 
				
			||||||
	{
 | 
					 | 
				
			||||||
		`package p; import "`,
 | 
					 | 
				
			||||||
		"syntax error",
 | 
					 | 
				
			||||||
	},
 | 
					 | 
				
			||||||
	{
 | 
					 | 
				
			||||||
		"package p; import ` \n\n",
 | 
					 | 
				
			||||||
		"syntax error",
 | 
					 | 
				
			||||||
	},
 | 
					 | 
				
			||||||
	{
 | 
					 | 
				
			||||||
		`package p; import "x`,
 | 
					 | 
				
			||||||
		"syntax error",
 | 
					 | 
				
			||||||
	},
 | 
					 | 
				
			||||||
	{
 | 
					 | 
				
			||||||
		`package p; import _`,
 | 
					 | 
				
			||||||
		"syntax error",
 | 
					 | 
				
			||||||
	},
 | 
					 | 
				
			||||||
	{
 | 
					 | 
				
			||||||
		`package p; import _ "`,
 | 
					 | 
				
			||||||
		"syntax error",
 | 
					 | 
				
			||||||
	},
 | 
					 | 
				
			||||||
	{
 | 
					 | 
				
			||||||
		`package p; import _ "x`,
 | 
					 | 
				
			||||||
		"syntax error",
 | 
					 | 
				
			||||||
	},
 | 
					 | 
				
			||||||
	{
 | 
					 | 
				
			||||||
		`package p; import .`,
 | 
					 | 
				
			||||||
		"syntax error",
 | 
					 | 
				
			||||||
	},
 | 
					 | 
				
			||||||
	{
 | 
					 | 
				
			||||||
		`package p; import . "`,
 | 
					 | 
				
			||||||
		"syntax error",
 | 
					 | 
				
			||||||
	},
 | 
					 | 
				
			||||||
	{
 | 
					 | 
				
			||||||
		`package p; import . "x`,
 | 
					 | 
				
			||||||
		"syntax error",
 | 
					 | 
				
			||||||
	},
 | 
					 | 
				
			||||||
	{
 | 
					 | 
				
			||||||
		`package p; import (`,
 | 
					 | 
				
			||||||
		"syntax error",
 | 
					 | 
				
			||||||
	},
 | 
					 | 
				
			||||||
	{
 | 
					 | 
				
			||||||
		`package p; import ("`,
 | 
					 | 
				
			||||||
		"syntax error",
 | 
					 | 
				
			||||||
	},
 | 
					 | 
				
			||||||
	{
 | 
					 | 
				
			||||||
		`package p; import ("x`,
 | 
					 | 
				
			||||||
		"syntax error",
 | 
					 | 
				
			||||||
	},
 | 
					 | 
				
			||||||
	{
 | 
					 | 
				
			||||||
		`package p; import ("x"`,
 | 
					 | 
				
			||||||
		"syntax error",
 | 
					 | 
				
			||||||
	},
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func TestReadFailures(t *testing.T) {
 | 
					 | 
				
			||||||
	// Errors should be reported (true arg to readImports).
 | 
					 | 
				
			||||||
	testRead(t, readFailuresTests, func(r io.Reader) ([]byte, error) { return readImports(r, true, nil) })
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func TestReadFailuresIgnored(t *testing.T) {
 | 
					 | 
				
			||||||
	// Syntax errors should not be reported (false arg to readImports).
 | 
					 | 
				
			||||||
	// Instead, entire file should be the output and no error.
 | 
					 | 
				
			||||||
	// Convert tests not to return syntax errors.
 | 
					 | 
				
			||||||
	tests := make([]readTest, len(readFailuresTests))
 | 
					 | 
				
			||||||
	copy(tests, readFailuresTests)
 | 
					 | 
				
			||||||
	for i := range tests {
 | 
					 | 
				
			||||||
		tt := &tests[i]
 | 
					 | 
				
			||||||
		if !strings.Contains(tt.err, "NUL") {
 | 
					 | 
				
			||||||
			tt.err = ""
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	testRead(t, tests, func(r io.Reader) ([]byte, error) { return readImports(r, false, nil) })
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
							
								
								
									
										8
									
								
								third_party/golang/go/build/syslist.go
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										8
									
								
								third_party/golang/go/build/syslist.go
									
									
									
									
										vendored
									
									
								
							@@ -1,8 +0,0 @@
 | 
				
			|||||||
// Copyright 2011 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 build
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
const goosList = "android darwin dragonfly freebsd linux nacl netbsd openbsd plan9 solaris windows "
 | 
					 | 
				
			||||||
const goarchList = "386 amd64 amd64p32 arm armbe arm64 arm64be ppc64 ppc64le mips mipsle mips64 mips64le mips64p32 mips64p32le ppc s390 s390x sparc sparc64 "
 | 
					 | 
				
			||||||
							
								
								
									
										62
									
								
								third_party/golang/go/build/syslist_test.go
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										62
									
								
								third_party/golang/go/build/syslist_test.go
									
									
									
									
										vendored
									
									
								
							@@ -1,62 +0,0 @@
 | 
				
			|||||||
// Copyright 2011 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 build
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
import (
 | 
					 | 
				
			||||||
	"runtime"
 | 
					 | 
				
			||||||
	"testing"
 | 
					 | 
				
			||||||
)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
var (
 | 
					 | 
				
			||||||
	thisOS    = runtime.GOOS
 | 
					 | 
				
			||||||
	thisArch  = runtime.GOARCH
 | 
					 | 
				
			||||||
	otherOS   = anotherOS()
 | 
					 | 
				
			||||||
	otherArch = anotherArch()
 | 
					 | 
				
			||||||
)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func anotherOS() string {
 | 
					 | 
				
			||||||
	if thisOS != "darwin" {
 | 
					 | 
				
			||||||
		return "darwin"
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return "linux"
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func anotherArch() string {
 | 
					 | 
				
			||||||
	if thisArch != "amd64" {
 | 
					 | 
				
			||||||
		return "amd64"
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return "386"
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
type GoodFileTest struct {
 | 
					 | 
				
			||||||
	name   string
 | 
					 | 
				
			||||||
	result bool
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
var tests = []GoodFileTest{
 | 
					 | 
				
			||||||
	{"file.go", true},
 | 
					 | 
				
			||||||
	{"file.c", true},
 | 
					 | 
				
			||||||
	{"file_foo.go", true},
 | 
					 | 
				
			||||||
	{"file_" + thisArch + ".go", true},
 | 
					 | 
				
			||||||
	{"file_" + otherArch + ".go", false},
 | 
					 | 
				
			||||||
	{"file_" + thisOS + ".go", true},
 | 
					 | 
				
			||||||
	{"file_" + otherOS + ".go", false},
 | 
					 | 
				
			||||||
	{"file_" + thisOS + "_" + thisArch + ".go", true},
 | 
					 | 
				
			||||||
	{"file_" + otherOS + "_" + thisArch + ".go", false},
 | 
					 | 
				
			||||||
	{"file_" + thisOS + "_" + otherArch + ".go", false},
 | 
					 | 
				
			||||||
	{"file_" + otherOS + "_" + otherArch + ".go", false},
 | 
					 | 
				
			||||||
	{"file_foo_" + thisArch + ".go", true},
 | 
					 | 
				
			||||||
	{"file_foo_" + otherArch + ".go", false},
 | 
					 | 
				
			||||||
	{"file_" + thisOS + ".c", true},
 | 
					 | 
				
			||||||
	{"file_" + otherOS + ".c", false},
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func TestGoodOSArch(t *testing.T) {
 | 
					 | 
				
			||||||
	for _, test := range tests {
 | 
					 | 
				
			||||||
		if Default.goodOSArchFile(test.name, make(map[string]bool)) != test.result {
 | 
					 | 
				
			||||||
			t.Fatalf("goodOSArchFile(%q) != %v", test.name, test.result)
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
@@ -1,5 +0,0 @@
 | 
				
			|||||||
// Test data - not compiled.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
package main
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func main() {}
 | 
					 | 
				
			||||||
@@ -1,5 +0,0 @@
 | 
				
			|||||||
// Test data - not compiled.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
package test_package
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func init() {}
 | 
					 | 
				
			||||||
@@ -1,5 +0,0 @@
 | 
				
			|||||||
// Test data - not compiled.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
package file
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func F() {}
 | 
					 | 
				
			||||||
@@ -1,11 +0,0 @@
 | 
				
			|||||||
// Test data - not compiled.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
package main
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
import (
 | 
					 | 
				
			||||||
	"./file"
 | 
					 | 
				
			||||||
)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func main() {
 | 
					 | 
				
			||||||
	file.F()
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
							
								
								
									
										24
									
								
								third_party/golang/go/constant/go13.go
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										24
									
								
								third_party/golang/go/constant/go13.go
									
									
									
									
										vendored
									
									
								
							@@ -1,24 +0,0 @@
 | 
				
			|||||||
// Copyright 2014 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.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// +build !go1.4
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
package constant
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
import (
 | 
					 | 
				
			||||||
	"math"
 | 
					 | 
				
			||||||
	"math/big"
 | 
					 | 
				
			||||||
)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func ratToFloat32(x *big.Rat) (float32, bool) {
 | 
					 | 
				
			||||||
	// Before 1.4, there's no Rat.Float32.
 | 
					 | 
				
			||||||
	// Emulate it, albeit at the cost of
 | 
					 | 
				
			||||||
	// imprecision in corner cases.
 | 
					 | 
				
			||||||
	x64, exact := x.Float64()
 | 
					 | 
				
			||||||
	x32 := float32(x64)
 | 
					 | 
				
			||||||
	if math.IsInf(float64(x32), 0) {
 | 
					 | 
				
			||||||
		exact = false
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return x32, exact
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
							
								
								
									
										13
									
								
								third_party/golang/go/constant/go14.go
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										13
									
								
								third_party/golang/go/constant/go14.go
									
									
									
									
										vendored
									
									
								
							@@ -1,13 +0,0 @@
 | 
				
			|||||||
// Copyright 2014 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.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// +build go1.4
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
package constant
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
import "math/big"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func ratToFloat32(x *big.Rat) (float32, bool) {
 | 
					 | 
				
			||||||
	return x.Float32()
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
							
								
								
									
										925
									
								
								third_party/golang/go/constant/value.go
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										925
									
								
								third_party/golang/go/constant/value.go
									
									
									
									
										vendored
									
									
								
							@@ -1,925 +0,0 @@
 | 
				
			|||||||
// Copyright 2013 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 constant implements Values representing untyped
 | 
					 | 
				
			||||||
// Go constants and the corresponding operations. Values
 | 
					 | 
				
			||||||
// and operations may have arbitrary or unlimited precision.
 | 
					 | 
				
			||||||
//
 | 
					 | 
				
			||||||
// A special Unknown value may be used when a value
 | 
					 | 
				
			||||||
// is unknown due to an error. Operations on unknown
 | 
					 | 
				
			||||||
// values produce unknown values unless specified
 | 
					 | 
				
			||||||
// otherwise.
 | 
					 | 
				
			||||||
//
 | 
					 | 
				
			||||||
package constant
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
import (
 | 
					 | 
				
			||||||
	"fmt"
 | 
					 | 
				
			||||||
	"k8s.io/kubernetes/third_party/golang/go/token"
 | 
					 | 
				
			||||||
	"math/big"
 | 
					 | 
				
			||||||
	"strconv"
 | 
					 | 
				
			||||||
)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// Kind specifies the kind of value represented by a Value.
 | 
					 | 
				
			||||||
type Kind int
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// Implementation note: Kinds must be enumerated in
 | 
					 | 
				
			||||||
// order of increasing "complexity" (used by match).
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
const (
 | 
					 | 
				
			||||||
	// unknown values
 | 
					 | 
				
			||||||
	Unknown Kind = iota
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// non-numeric values
 | 
					 | 
				
			||||||
	Bool
 | 
					 | 
				
			||||||
	String
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// numeric values
 | 
					 | 
				
			||||||
	Int
 | 
					 | 
				
			||||||
	Float
 | 
					 | 
				
			||||||
	Complex
 | 
					 | 
				
			||||||
)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// A Value represents a mathematically exact value of a given Kind.
 | 
					 | 
				
			||||||
type Value interface {
 | 
					 | 
				
			||||||
	// Kind returns the value kind; it is always the smallest
 | 
					 | 
				
			||||||
	// kind in which the value can be represented exactly.
 | 
					 | 
				
			||||||
	Kind() Kind
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// String returns a human-readable form of the value.
 | 
					 | 
				
			||||||
	String() string
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// Prevent external implementations.
 | 
					 | 
				
			||||||
	implementsValue()
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// ----------------------------------------------------------------------------
 | 
					 | 
				
			||||||
// Implementations
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
type (
 | 
					 | 
				
			||||||
	unknownVal struct{}
 | 
					 | 
				
			||||||
	boolVal    bool
 | 
					 | 
				
			||||||
	stringVal  string
 | 
					 | 
				
			||||||
	int64Val   int64
 | 
					 | 
				
			||||||
	intVal     struct{ val *big.Int }
 | 
					 | 
				
			||||||
	floatVal   struct{ val *big.Rat }
 | 
					 | 
				
			||||||
	complexVal struct{ re, im *big.Rat }
 | 
					 | 
				
			||||||
)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (unknownVal) Kind() Kind { return Unknown }
 | 
					 | 
				
			||||||
func (boolVal) Kind() Kind    { return Bool }
 | 
					 | 
				
			||||||
func (stringVal) Kind() Kind  { return String }
 | 
					 | 
				
			||||||
func (int64Val) Kind() Kind   { return Int }
 | 
					 | 
				
			||||||
func (intVal) Kind() Kind     { return Int }
 | 
					 | 
				
			||||||
func (floatVal) Kind() Kind   { return Float }
 | 
					 | 
				
			||||||
func (complexVal) Kind() Kind { return Complex }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (unknownVal) String() string   { return "unknown" }
 | 
					 | 
				
			||||||
func (x boolVal) String() string    { return fmt.Sprintf("%v", bool(x)) }
 | 
					 | 
				
			||||||
func (x stringVal) String() string  { return strconv.Quote(string(x)) }
 | 
					 | 
				
			||||||
func (x int64Val) String() string   { return strconv.FormatInt(int64(x), 10) }
 | 
					 | 
				
			||||||
func (x intVal) String() string     { return x.val.String() }
 | 
					 | 
				
			||||||
func (x floatVal) String() string   { return x.val.String() }
 | 
					 | 
				
			||||||
func (x complexVal) String() string { return fmt.Sprintf("(%s + %si)", x.re, x.im) }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (unknownVal) implementsValue() {}
 | 
					 | 
				
			||||||
func (boolVal) implementsValue()    {}
 | 
					 | 
				
			||||||
func (stringVal) implementsValue()  {}
 | 
					 | 
				
			||||||
func (int64Val) implementsValue()   {}
 | 
					 | 
				
			||||||
func (intVal) implementsValue()     {}
 | 
					 | 
				
			||||||
func (floatVal) implementsValue()   {}
 | 
					 | 
				
			||||||
func (complexVal) implementsValue() {}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// int64 bounds
 | 
					 | 
				
			||||||
var (
 | 
					 | 
				
			||||||
	minInt64 = big.NewInt(-1 << 63)
 | 
					 | 
				
			||||||
	maxInt64 = big.NewInt(1<<63 - 1)
 | 
					 | 
				
			||||||
)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func normInt(x *big.Int) Value {
 | 
					 | 
				
			||||||
	if minInt64.Cmp(x) <= 0 && x.Cmp(maxInt64) <= 0 {
 | 
					 | 
				
			||||||
		return int64Val(x.Int64())
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return intVal{x}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func normFloat(x *big.Rat) Value {
 | 
					 | 
				
			||||||
	if x.IsInt() {
 | 
					 | 
				
			||||||
		return normInt(x.Num())
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return floatVal{x}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func normComplex(re, im *big.Rat) Value {
 | 
					 | 
				
			||||||
	if im.Sign() == 0 {
 | 
					 | 
				
			||||||
		return normFloat(re)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return complexVal{re, im}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// ----------------------------------------------------------------------------
 | 
					 | 
				
			||||||
// Factories
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// MakeUnknown returns the Unknown value.
 | 
					 | 
				
			||||||
func MakeUnknown() Value { return unknownVal{} }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// MakeBool returns the Bool value for x.
 | 
					 | 
				
			||||||
func MakeBool(b bool) Value { return boolVal(b) }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// MakeString returns the String value for x.
 | 
					 | 
				
			||||||
func MakeString(s string) Value { return stringVal(s) }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// MakeInt64 returns the Int value for x.
 | 
					 | 
				
			||||||
func MakeInt64(x int64) Value { return int64Val(x) }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// MakeUint64 returns the Int value for x.
 | 
					 | 
				
			||||||
func MakeUint64(x uint64) Value { return normInt(new(big.Int).SetUint64(x)) }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// MakeFloat64 returns the numeric value for x.
 | 
					 | 
				
			||||||
// If x is not finite, the result is unknown.
 | 
					 | 
				
			||||||
func MakeFloat64(x float64) Value {
 | 
					 | 
				
			||||||
	if f := new(big.Rat).SetFloat64(x); f != nil {
 | 
					 | 
				
			||||||
		return normFloat(f)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return unknownVal{}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// MakeFromLiteral returns the corresponding integer, floating-point,
 | 
					 | 
				
			||||||
// imaginary, character, or string value for a Go literal string.
 | 
					 | 
				
			||||||
// If prec > 0, prec specifies an upper limit for the precision of
 | 
					 | 
				
			||||||
// a numeric value. If the literal string is invalid, the result is
 | 
					 | 
				
			||||||
// nil.
 | 
					 | 
				
			||||||
// BUG(gri) Only prec == 0 is supported at the moment.
 | 
					 | 
				
			||||||
func MakeFromLiteral(lit string, tok token.Token, prec uint) Value {
 | 
					 | 
				
			||||||
	if prec != 0 {
 | 
					 | 
				
			||||||
		panic("limited precision not supported")
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	switch tok {
 | 
					 | 
				
			||||||
	case token.INT:
 | 
					 | 
				
			||||||
		if x, err := strconv.ParseInt(lit, 0, 64); err == nil {
 | 
					 | 
				
			||||||
			return int64Val(x)
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		if x, ok := new(big.Int).SetString(lit, 0); ok {
 | 
					 | 
				
			||||||
			return intVal{x}
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	case token.FLOAT:
 | 
					 | 
				
			||||||
		if x, ok := new(big.Rat).SetString(lit); ok {
 | 
					 | 
				
			||||||
			return normFloat(x)
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	case token.IMAG:
 | 
					 | 
				
			||||||
		if n := len(lit); n > 0 && lit[n-1] == 'i' {
 | 
					 | 
				
			||||||
			if im, ok := new(big.Rat).SetString(lit[0 : n-1]); ok {
 | 
					 | 
				
			||||||
				return normComplex(big.NewRat(0, 1), im)
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	case token.CHAR:
 | 
					 | 
				
			||||||
		if n := len(lit); n >= 2 {
 | 
					 | 
				
			||||||
			if code, _, _, err := strconv.UnquoteChar(lit[1:n-1], '\''); err == nil {
 | 
					 | 
				
			||||||
				return int64Val(code)
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	case token.STRING:
 | 
					 | 
				
			||||||
		if s, err := strconv.Unquote(lit); err == nil {
 | 
					 | 
				
			||||||
			return stringVal(s)
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return nil
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// ----------------------------------------------------------------------------
 | 
					 | 
				
			||||||
// Accessors
 | 
					 | 
				
			||||||
//
 | 
					 | 
				
			||||||
// For unknown arguments the result is the zero value for the respective
 | 
					 | 
				
			||||||
// accessor type, except for Sign, where the result is 1.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// BoolVal returns the Go boolean value of x, which must be a Bool or an Unknown.
 | 
					 | 
				
			||||||
// If x is Unknown, the result is false.
 | 
					 | 
				
			||||||
func BoolVal(x Value) bool {
 | 
					 | 
				
			||||||
	switch x := x.(type) {
 | 
					 | 
				
			||||||
	case boolVal:
 | 
					 | 
				
			||||||
		return bool(x)
 | 
					 | 
				
			||||||
	case unknownVal:
 | 
					 | 
				
			||||||
		return false
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	panic(fmt.Sprintf("%v not a Bool", x))
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// StringVal returns the Go string value of x, which must be a String or an Unknown.
 | 
					 | 
				
			||||||
// If x is Unknown, the result is "".
 | 
					 | 
				
			||||||
func StringVal(x Value) string {
 | 
					 | 
				
			||||||
	switch x := x.(type) {
 | 
					 | 
				
			||||||
	case stringVal:
 | 
					 | 
				
			||||||
		return string(x)
 | 
					 | 
				
			||||||
	case unknownVal:
 | 
					 | 
				
			||||||
		return ""
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	panic(fmt.Sprintf("%v not a String", x))
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// Int64Val returns the Go int64 value of x and whether the result is exact;
 | 
					 | 
				
			||||||
// x must be an Int or an Unknown. If the result is not exact, its value is undefined.
 | 
					 | 
				
			||||||
// If x is Unknown, the result is (0, false).
 | 
					 | 
				
			||||||
func Int64Val(x Value) (int64, bool) {
 | 
					 | 
				
			||||||
	switch x := x.(type) {
 | 
					 | 
				
			||||||
	case int64Val:
 | 
					 | 
				
			||||||
		return int64(x), true
 | 
					 | 
				
			||||||
	case intVal:
 | 
					 | 
				
			||||||
		return x.val.Int64(), x.val.BitLen() <= 63
 | 
					 | 
				
			||||||
	case unknownVal:
 | 
					 | 
				
			||||||
		return 0, false
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	panic(fmt.Sprintf("%v not an Int", x))
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// Uint64Val returns the Go uint64 value of x and whether the result is exact;
 | 
					 | 
				
			||||||
// x must be an Int or an Unknown. If the result is not exact, its value is undefined.
 | 
					 | 
				
			||||||
// If x is Unknown, the result is (0, false).
 | 
					 | 
				
			||||||
func Uint64Val(x Value) (uint64, bool) {
 | 
					 | 
				
			||||||
	switch x := x.(type) {
 | 
					 | 
				
			||||||
	case int64Val:
 | 
					 | 
				
			||||||
		return uint64(x), x >= 0
 | 
					 | 
				
			||||||
	case intVal:
 | 
					 | 
				
			||||||
		return x.val.Uint64(), x.val.Sign() >= 0 && x.val.BitLen() <= 64
 | 
					 | 
				
			||||||
	case unknownVal:
 | 
					 | 
				
			||||||
		return 0, false
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	panic(fmt.Sprintf("%v not an Int", x))
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// Float32Val is like Float64Val but for float32 instead of float64.
 | 
					 | 
				
			||||||
func Float32Val(x Value) (float32, bool) {
 | 
					 | 
				
			||||||
	switch x := x.(type) {
 | 
					 | 
				
			||||||
	case int64Val:
 | 
					 | 
				
			||||||
		f := float32(x)
 | 
					 | 
				
			||||||
		return f, int64Val(f) == x
 | 
					 | 
				
			||||||
	case intVal:
 | 
					 | 
				
			||||||
		return ratToFloat32(new(big.Rat).SetFrac(x.val, int1))
 | 
					 | 
				
			||||||
	case floatVal:
 | 
					 | 
				
			||||||
		return ratToFloat32(x.val)
 | 
					 | 
				
			||||||
	case unknownVal:
 | 
					 | 
				
			||||||
		return 0, false
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	panic(fmt.Sprintf("%v not a Float", x))
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// Float64Val returns the nearest Go float64 value of x and whether the result is exact;
 | 
					 | 
				
			||||||
// x must be numeric but not Complex, or Unknown. For values too small (too close to 0)
 | 
					 | 
				
			||||||
// to represent as float64, Float64Val silently underflows to 0. The result sign always
 | 
					 | 
				
			||||||
// matches the sign of x, even for 0.
 | 
					 | 
				
			||||||
// If x is Unknown, the result is (0, false).
 | 
					 | 
				
			||||||
func Float64Val(x Value) (float64, bool) {
 | 
					 | 
				
			||||||
	switch x := x.(type) {
 | 
					 | 
				
			||||||
	case int64Val:
 | 
					 | 
				
			||||||
		f := float64(int64(x))
 | 
					 | 
				
			||||||
		return f, int64Val(f) == x
 | 
					 | 
				
			||||||
	case intVal:
 | 
					 | 
				
			||||||
		return new(big.Rat).SetFrac(x.val, int1).Float64()
 | 
					 | 
				
			||||||
	case floatVal:
 | 
					 | 
				
			||||||
		return x.val.Float64()
 | 
					 | 
				
			||||||
	case unknownVal:
 | 
					 | 
				
			||||||
		return 0, false
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	panic(fmt.Sprintf("%v not a Float", x))
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// BitLen returns the number of bits required to represent
 | 
					 | 
				
			||||||
// the absolute value x in binary representation; x must be an Int or an Unknown.
 | 
					 | 
				
			||||||
// If x is Unknown, the result is 0.
 | 
					 | 
				
			||||||
func BitLen(x Value) int {
 | 
					 | 
				
			||||||
	switch x := x.(type) {
 | 
					 | 
				
			||||||
	case int64Val:
 | 
					 | 
				
			||||||
		return new(big.Int).SetInt64(int64(x)).BitLen()
 | 
					 | 
				
			||||||
	case intVal:
 | 
					 | 
				
			||||||
		return x.val.BitLen()
 | 
					 | 
				
			||||||
	case unknownVal:
 | 
					 | 
				
			||||||
		return 0
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	panic(fmt.Sprintf("%v not an Int", x))
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// Sign returns -1, 0, or 1 depending on whether x < 0, x == 0, or x > 0;
 | 
					 | 
				
			||||||
// x must be numeric or Unknown. For complex values x, the sign is 0 if x == 0,
 | 
					 | 
				
			||||||
// otherwise it is != 0. If x is Unknown, the result is 1.
 | 
					 | 
				
			||||||
func Sign(x Value) int {
 | 
					 | 
				
			||||||
	switch x := x.(type) {
 | 
					 | 
				
			||||||
	case int64Val:
 | 
					 | 
				
			||||||
		switch {
 | 
					 | 
				
			||||||
		case x < 0:
 | 
					 | 
				
			||||||
			return -1
 | 
					 | 
				
			||||||
		case x > 0:
 | 
					 | 
				
			||||||
			return 1
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		return 0
 | 
					 | 
				
			||||||
	case intVal:
 | 
					 | 
				
			||||||
		return x.val.Sign()
 | 
					 | 
				
			||||||
	case floatVal:
 | 
					 | 
				
			||||||
		return x.val.Sign()
 | 
					 | 
				
			||||||
	case complexVal:
 | 
					 | 
				
			||||||
		return x.re.Sign() | x.im.Sign()
 | 
					 | 
				
			||||||
	case unknownVal:
 | 
					 | 
				
			||||||
		return 1 // avoid spurious division by zero errors
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	panic(fmt.Sprintf("%v not numeric", x))
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// ----------------------------------------------------------------------------
 | 
					 | 
				
			||||||
// Support for serializing/deserializing integers
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
const (
 | 
					 | 
				
			||||||
	// Compute the size of a Word in bytes.
 | 
					 | 
				
			||||||
	_m       = ^big.Word(0)
 | 
					 | 
				
			||||||
	_log     = _m>>8&1 + _m>>16&1 + _m>>32&1
 | 
					 | 
				
			||||||
	wordSize = 1 << _log
 | 
					 | 
				
			||||||
)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// Bytes returns the bytes for the absolute value of x in little-
 | 
					 | 
				
			||||||
// endian binary representation; x must be an Int.
 | 
					 | 
				
			||||||
func Bytes(x Value) []byte {
 | 
					 | 
				
			||||||
	var val *big.Int
 | 
					 | 
				
			||||||
	switch x := x.(type) {
 | 
					 | 
				
			||||||
	case int64Val:
 | 
					 | 
				
			||||||
		val = new(big.Int).SetInt64(int64(x))
 | 
					 | 
				
			||||||
	case intVal:
 | 
					 | 
				
			||||||
		val = x.val
 | 
					 | 
				
			||||||
	default:
 | 
					 | 
				
			||||||
		panic(fmt.Sprintf("%v not an Int", x))
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	words := val.Bits()
 | 
					 | 
				
			||||||
	bytes := make([]byte, len(words)*wordSize)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	i := 0
 | 
					 | 
				
			||||||
	for _, w := range words {
 | 
					 | 
				
			||||||
		for j := 0; j < wordSize; j++ {
 | 
					 | 
				
			||||||
			bytes[i] = byte(w)
 | 
					 | 
				
			||||||
			w >>= 8
 | 
					 | 
				
			||||||
			i++
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	// remove leading 0's
 | 
					 | 
				
			||||||
	for i > 0 && bytes[i-1] == 0 {
 | 
					 | 
				
			||||||
		i--
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return bytes[:i]
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// MakeFromBytes returns the Int value given the bytes of its little-endian
 | 
					 | 
				
			||||||
// binary representation. An empty byte slice argument represents 0.
 | 
					 | 
				
			||||||
func MakeFromBytes(bytes []byte) Value {
 | 
					 | 
				
			||||||
	words := make([]big.Word, (len(bytes)+(wordSize-1))/wordSize)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	i := 0
 | 
					 | 
				
			||||||
	var w big.Word
 | 
					 | 
				
			||||||
	var s uint
 | 
					 | 
				
			||||||
	for _, b := range bytes {
 | 
					 | 
				
			||||||
		w |= big.Word(b) << s
 | 
					 | 
				
			||||||
		if s += 8; s == wordSize*8 {
 | 
					 | 
				
			||||||
			words[i] = w
 | 
					 | 
				
			||||||
			i++
 | 
					 | 
				
			||||||
			w = 0
 | 
					 | 
				
			||||||
			s = 0
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	// store last word
 | 
					 | 
				
			||||||
	if i < len(words) {
 | 
					 | 
				
			||||||
		words[i] = w
 | 
					 | 
				
			||||||
		i++
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	// remove leading 0's
 | 
					 | 
				
			||||||
	for i > 0 && words[i-1] == 0 {
 | 
					 | 
				
			||||||
		i--
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return normInt(new(big.Int).SetBits(words[:i]))
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// ----------------------------------------------------------------------------
 | 
					 | 
				
			||||||
// Support for disassembling fractions
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// Num returns the numerator of x; x must be Int, Float, or Unknown.
 | 
					 | 
				
			||||||
// If x is Unknown, the result is Unknown, otherwise it is an Int
 | 
					 | 
				
			||||||
// with the same sign as x.
 | 
					 | 
				
			||||||
func Num(x Value) Value {
 | 
					 | 
				
			||||||
	switch x := x.(type) {
 | 
					 | 
				
			||||||
	case unknownVal, int64Val, intVal:
 | 
					 | 
				
			||||||
		return x
 | 
					 | 
				
			||||||
	case floatVal:
 | 
					 | 
				
			||||||
		return normInt(x.val.Num())
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	panic(fmt.Sprintf("%v not Int or Float", x))
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// Denom returns the denominator of x; x must be Int, Float, or Unknown.
 | 
					 | 
				
			||||||
// If x is Unknown, the result is Unknown, otherwise it is an Int >= 1.
 | 
					 | 
				
			||||||
func Denom(x Value) Value {
 | 
					 | 
				
			||||||
	switch x := x.(type) {
 | 
					 | 
				
			||||||
	case unknownVal:
 | 
					 | 
				
			||||||
		return x
 | 
					 | 
				
			||||||
	case int64Val, intVal:
 | 
					 | 
				
			||||||
		return int64Val(1)
 | 
					 | 
				
			||||||
	case floatVal:
 | 
					 | 
				
			||||||
		return normInt(x.val.Denom())
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	panic(fmt.Sprintf("%v not Int or Float", x))
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// ----------------------------------------------------------------------------
 | 
					 | 
				
			||||||
// Support for assembling/disassembling complex numbers
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// MakeImag returns the numeric value x*i (possibly 0);
 | 
					 | 
				
			||||||
// x must be Int, Float, or Unknown.
 | 
					 | 
				
			||||||
// If x is Unknown, the result is Unknown.
 | 
					 | 
				
			||||||
func MakeImag(x Value) Value {
 | 
					 | 
				
			||||||
	var im *big.Rat
 | 
					 | 
				
			||||||
	switch x := x.(type) {
 | 
					 | 
				
			||||||
	case unknownVal:
 | 
					 | 
				
			||||||
		return x
 | 
					 | 
				
			||||||
	case int64Val:
 | 
					 | 
				
			||||||
		im = big.NewRat(int64(x), 1)
 | 
					 | 
				
			||||||
	case intVal:
 | 
					 | 
				
			||||||
		im = new(big.Rat).SetFrac(x.val, int1)
 | 
					 | 
				
			||||||
	case floatVal:
 | 
					 | 
				
			||||||
		im = x.val
 | 
					 | 
				
			||||||
	default:
 | 
					 | 
				
			||||||
		panic(fmt.Sprintf("%v not Int or Float", x))
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return normComplex(rat0, im)
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// Real returns the real part of x, which must be a numeric or unknown value.
 | 
					 | 
				
			||||||
// If x is Unknown, the result is Unknown.
 | 
					 | 
				
			||||||
func Real(x Value) Value {
 | 
					 | 
				
			||||||
	switch x := x.(type) {
 | 
					 | 
				
			||||||
	case unknownVal, int64Val, intVal, floatVal:
 | 
					 | 
				
			||||||
		return x
 | 
					 | 
				
			||||||
	case complexVal:
 | 
					 | 
				
			||||||
		return normFloat(x.re)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	panic(fmt.Sprintf("%v not numeric", x))
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// Imag returns the imaginary part of x, which must be a numeric or unknown value.
 | 
					 | 
				
			||||||
// If x is Unknown, the result is Unknown.
 | 
					 | 
				
			||||||
func Imag(x Value) Value {
 | 
					 | 
				
			||||||
	switch x := x.(type) {
 | 
					 | 
				
			||||||
	case unknownVal:
 | 
					 | 
				
			||||||
		return x
 | 
					 | 
				
			||||||
	case int64Val, intVal, floatVal:
 | 
					 | 
				
			||||||
		return int64Val(0)
 | 
					 | 
				
			||||||
	case complexVal:
 | 
					 | 
				
			||||||
		return normFloat(x.im)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	panic(fmt.Sprintf("%v not numeric", x))
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// ----------------------------------------------------------------------------
 | 
					 | 
				
			||||||
// Operations
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// is32bit reports whether x can be represented using 32 bits.
 | 
					 | 
				
			||||||
func is32bit(x int64) bool {
 | 
					 | 
				
			||||||
	const s = 32
 | 
					 | 
				
			||||||
	return -1<<(s-1) <= x && x <= 1<<(s-1)-1
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// is63bit reports whether x can be represented using 63 bits.
 | 
					 | 
				
			||||||
func is63bit(x int64) bool {
 | 
					 | 
				
			||||||
	const s = 63
 | 
					 | 
				
			||||||
	return -1<<(s-1) <= x && x <= 1<<(s-1)-1
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// UnaryOp returns the result of the unary expression op y.
 | 
					 | 
				
			||||||
// The operation must be defined for the operand.
 | 
					 | 
				
			||||||
// If prec > 0 it specifies the ^ (xor) result size in bits.
 | 
					 | 
				
			||||||
// If y is Unknown, the result is Unknown.
 | 
					 | 
				
			||||||
//
 | 
					 | 
				
			||||||
func UnaryOp(op token.Token, y Value, prec uint) Value {
 | 
					 | 
				
			||||||
	switch op {
 | 
					 | 
				
			||||||
	case token.ADD:
 | 
					 | 
				
			||||||
		switch y.(type) {
 | 
					 | 
				
			||||||
		case unknownVal, int64Val, intVal, floatVal, complexVal:
 | 
					 | 
				
			||||||
			return y
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	case token.SUB:
 | 
					 | 
				
			||||||
		switch y := y.(type) {
 | 
					 | 
				
			||||||
		case unknownVal:
 | 
					 | 
				
			||||||
			return y
 | 
					 | 
				
			||||||
		case int64Val:
 | 
					 | 
				
			||||||
			if z := -y; z != y {
 | 
					 | 
				
			||||||
				return z // no overflow
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
			return normInt(new(big.Int).Neg(big.NewInt(int64(y))))
 | 
					 | 
				
			||||||
		case intVal:
 | 
					 | 
				
			||||||
			return normInt(new(big.Int).Neg(y.val))
 | 
					 | 
				
			||||||
		case floatVal:
 | 
					 | 
				
			||||||
			return normFloat(new(big.Rat).Neg(y.val))
 | 
					 | 
				
			||||||
		case complexVal:
 | 
					 | 
				
			||||||
			return normComplex(new(big.Rat).Neg(y.re), new(big.Rat).Neg(y.im))
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	case token.XOR:
 | 
					 | 
				
			||||||
		var z big.Int
 | 
					 | 
				
			||||||
		switch y := y.(type) {
 | 
					 | 
				
			||||||
		case unknownVal:
 | 
					 | 
				
			||||||
			return y
 | 
					 | 
				
			||||||
		case int64Val:
 | 
					 | 
				
			||||||
			z.Not(big.NewInt(int64(y)))
 | 
					 | 
				
			||||||
		case intVal:
 | 
					 | 
				
			||||||
			z.Not(y.val)
 | 
					 | 
				
			||||||
		default:
 | 
					 | 
				
			||||||
			goto Error
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		// For unsigned types, the result will be negative and
 | 
					 | 
				
			||||||
		// thus "too large": We must limit the result precision
 | 
					 | 
				
			||||||
		// to the type's precision.
 | 
					 | 
				
			||||||
		if prec > 0 {
 | 
					 | 
				
			||||||
			z.AndNot(&z, new(big.Int).Lsh(big.NewInt(-1), prec)) // z &^= (-1)<<prec
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		return normInt(&z)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	case token.NOT:
 | 
					 | 
				
			||||||
		switch y := y.(type) {
 | 
					 | 
				
			||||||
		case unknownVal:
 | 
					 | 
				
			||||||
			return y
 | 
					 | 
				
			||||||
		case boolVal:
 | 
					 | 
				
			||||||
			return !y
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
Error:
 | 
					 | 
				
			||||||
	panic(fmt.Sprintf("invalid unary operation %s%v", op, y))
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
var (
 | 
					 | 
				
			||||||
	int1 = big.NewInt(1)
 | 
					 | 
				
			||||||
	rat0 = big.NewRat(0, 1)
 | 
					 | 
				
			||||||
)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func ord(x Value) int {
 | 
					 | 
				
			||||||
	switch x.(type) {
 | 
					 | 
				
			||||||
	default:
 | 
					 | 
				
			||||||
		return 0
 | 
					 | 
				
			||||||
	case boolVal, stringVal:
 | 
					 | 
				
			||||||
		return 1
 | 
					 | 
				
			||||||
	case int64Val:
 | 
					 | 
				
			||||||
		return 2
 | 
					 | 
				
			||||||
	case intVal:
 | 
					 | 
				
			||||||
		return 3
 | 
					 | 
				
			||||||
	case floatVal:
 | 
					 | 
				
			||||||
		return 4
 | 
					 | 
				
			||||||
	case complexVal:
 | 
					 | 
				
			||||||
		return 5
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// match returns the matching representation (same type) with the
 | 
					 | 
				
			||||||
// smallest complexity for two values x and y. If one of them is
 | 
					 | 
				
			||||||
// numeric, both of them must be numeric. If one of them is Unknown,
 | 
					 | 
				
			||||||
// both results are Unknown.
 | 
					 | 
				
			||||||
//
 | 
					 | 
				
			||||||
func match(x, y Value) (_, _ Value) {
 | 
					 | 
				
			||||||
	if ord(x) > ord(y) {
 | 
					 | 
				
			||||||
		y, x = match(y, x)
 | 
					 | 
				
			||||||
		return x, y
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	// ord(x) <= ord(y)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	switch x := x.(type) {
 | 
					 | 
				
			||||||
	case unknownVal:
 | 
					 | 
				
			||||||
		return x, x
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	case boolVal, stringVal, complexVal:
 | 
					 | 
				
			||||||
		return x, y
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	case int64Val:
 | 
					 | 
				
			||||||
		switch y := y.(type) {
 | 
					 | 
				
			||||||
		case int64Val:
 | 
					 | 
				
			||||||
			return x, y
 | 
					 | 
				
			||||||
		case intVal:
 | 
					 | 
				
			||||||
			return intVal{big.NewInt(int64(x))}, y
 | 
					 | 
				
			||||||
		case floatVal:
 | 
					 | 
				
			||||||
			return floatVal{big.NewRat(int64(x), 1)}, y
 | 
					 | 
				
			||||||
		case complexVal:
 | 
					 | 
				
			||||||
			return complexVal{big.NewRat(int64(x), 1), rat0}, y
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	case intVal:
 | 
					 | 
				
			||||||
		switch y := y.(type) {
 | 
					 | 
				
			||||||
		case intVal:
 | 
					 | 
				
			||||||
			return x, y
 | 
					 | 
				
			||||||
		case floatVal:
 | 
					 | 
				
			||||||
			return floatVal{new(big.Rat).SetFrac(x.val, int1)}, y
 | 
					 | 
				
			||||||
		case complexVal:
 | 
					 | 
				
			||||||
			return complexVal{new(big.Rat).SetFrac(x.val, int1), rat0}, y
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	case floatVal:
 | 
					 | 
				
			||||||
		switch y := y.(type) {
 | 
					 | 
				
			||||||
		case floatVal:
 | 
					 | 
				
			||||||
			return x, y
 | 
					 | 
				
			||||||
		case complexVal:
 | 
					 | 
				
			||||||
			return complexVal{x.val, rat0}, y
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	panic("unreachable")
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// BinaryOp returns the result of the binary expression x op y.
 | 
					 | 
				
			||||||
// The operation must be defined for the operands. If one of the
 | 
					 | 
				
			||||||
// operands is Unknown, the result is Unknown.
 | 
					 | 
				
			||||||
// To force integer division of Int operands, use op == token.QUO_ASSIGN
 | 
					 | 
				
			||||||
// instead of token.QUO; the result is guaranteed to be Int in this case.
 | 
					 | 
				
			||||||
// Division by zero leads to a run-time panic.
 | 
					 | 
				
			||||||
//
 | 
					 | 
				
			||||||
func BinaryOp(x Value, op token.Token, y Value) Value {
 | 
					 | 
				
			||||||
	x, y = match(x, y)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	switch x := x.(type) {
 | 
					 | 
				
			||||||
	case unknownVal:
 | 
					 | 
				
			||||||
		return x
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	case boolVal:
 | 
					 | 
				
			||||||
		y := y.(boolVal)
 | 
					 | 
				
			||||||
		switch op {
 | 
					 | 
				
			||||||
		case token.LAND:
 | 
					 | 
				
			||||||
			return x && y
 | 
					 | 
				
			||||||
		case token.LOR:
 | 
					 | 
				
			||||||
			return x || y
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	case int64Val:
 | 
					 | 
				
			||||||
		a := int64(x)
 | 
					 | 
				
			||||||
		b := int64(y.(int64Val))
 | 
					 | 
				
			||||||
		var c int64
 | 
					 | 
				
			||||||
		switch op {
 | 
					 | 
				
			||||||
		case token.ADD:
 | 
					 | 
				
			||||||
			if !is63bit(a) || !is63bit(b) {
 | 
					 | 
				
			||||||
				return normInt(new(big.Int).Add(big.NewInt(a), big.NewInt(b)))
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
			c = a + b
 | 
					 | 
				
			||||||
		case token.SUB:
 | 
					 | 
				
			||||||
			if !is63bit(a) || !is63bit(b) {
 | 
					 | 
				
			||||||
				return normInt(new(big.Int).Sub(big.NewInt(a), big.NewInt(b)))
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
			c = a - b
 | 
					 | 
				
			||||||
		case token.MUL:
 | 
					 | 
				
			||||||
			if !is32bit(a) || !is32bit(b) {
 | 
					 | 
				
			||||||
				return normInt(new(big.Int).Mul(big.NewInt(a), big.NewInt(b)))
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
			c = a * b
 | 
					 | 
				
			||||||
		case token.QUO:
 | 
					 | 
				
			||||||
			return normFloat(new(big.Rat).SetFrac(big.NewInt(a), big.NewInt(b)))
 | 
					 | 
				
			||||||
		case token.QUO_ASSIGN: // force integer division
 | 
					 | 
				
			||||||
			c = a / b
 | 
					 | 
				
			||||||
		case token.REM:
 | 
					 | 
				
			||||||
			c = a % b
 | 
					 | 
				
			||||||
		case token.AND:
 | 
					 | 
				
			||||||
			c = a & b
 | 
					 | 
				
			||||||
		case token.OR:
 | 
					 | 
				
			||||||
			c = a | b
 | 
					 | 
				
			||||||
		case token.XOR:
 | 
					 | 
				
			||||||
			c = a ^ b
 | 
					 | 
				
			||||||
		case token.AND_NOT:
 | 
					 | 
				
			||||||
			c = a &^ b
 | 
					 | 
				
			||||||
		default:
 | 
					 | 
				
			||||||
			goto Error
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		return int64Val(c)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	case intVal:
 | 
					 | 
				
			||||||
		a := x.val
 | 
					 | 
				
			||||||
		b := y.(intVal).val
 | 
					 | 
				
			||||||
		var c big.Int
 | 
					 | 
				
			||||||
		switch op {
 | 
					 | 
				
			||||||
		case token.ADD:
 | 
					 | 
				
			||||||
			c.Add(a, b)
 | 
					 | 
				
			||||||
		case token.SUB:
 | 
					 | 
				
			||||||
			c.Sub(a, b)
 | 
					 | 
				
			||||||
		case token.MUL:
 | 
					 | 
				
			||||||
			c.Mul(a, b)
 | 
					 | 
				
			||||||
		case token.QUO:
 | 
					 | 
				
			||||||
			return normFloat(new(big.Rat).SetFrac(a, b))
 | 
					 | 
				
			||||||
		case token.QUO_ASSIGN: // force integer division
 | 
					 | 
				
			||||||
			c.Quo(a, b)
 | 
					 | 
				
			||||||
		case token.REM:
 | 
					 | 
				
			||||||
			c.Rem(a, b)
 | 
					 | 
				
			||||||
		case token.AND:
 | 
					 | 
				
			||||||
			c.And(a, b)
 | 
					 | 
				
			||||||
		case token.OR:
 | 
					 | 
				
			||||||
			c.Or(a, b)
 | 
					 | 
				
			||||||
		case token.XOR:
 | 
					 | 
				
			||||||
			c.Xor(a, b)
 | 
					 | 
				
			||||||
		case token.AND_NOT:
 | 
					 | 
				
			||||||
			c.AndNot(a, b)
 | 
					 | 
				
			||||||
		default:
 | 
					 | 
				
			||||||
			goto Error
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		return normInt(&c)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	case floatVal:
 | 
					 | 
				
			||||||
		a := x.val
 | 
					 | 
				
			||||||
		b := y.(floatVal).val
 | 
					 | 
				
			||||||
		var c big.Rat
 | 
					 | 
				
			||||||
		switch op {
 | 
					 | 
				
			||||||
		case token.ADD:
 | 
					 | 
				
			||||||
			c.Add(a, b)
 | 
					 | 
				
			||||||
		case token.SUB:
 | 
					 | 
				
			||||||
			c.Sub(a, b)
 | 
					 | 
				
			||||||
		case token.MUL:
 | 
					 | 
				
			||||||
			c.Mul(a, b)
 | 
					 | 
				
			||||||
		case token.QUO:
 | 
					 | 
				
			||||||
			c.Quo(a, b)
 | 
					 | 
				
			||||||
		default:
 | 
					 | 
				
			||||||
			goto Error
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		return normFloat(&c)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	case complexVal:
 | 
					 | 
				
			||||||
		y := y.(complexVal)
 | 
					 | 
				
			||||||
		a, b := x.re, x.im
 | 
					 | 
				
			||||||
		c, d := y.re, y.im
 | 
					 | 
				
			||||||
		var re, im big.Rat
 | 
					 | 
				
			||||||
		switch op {
 | 
					 | 
				
			||||||
		case token.ADD:
 | 
					 | 
				
			||||||
			// (a+c) + i(b+d)
 | 
					 | 
				
			||||||
			re.Add(a, c)
 | 
					 | 
				
			||||||
			im.Add(b, d)
 | 
					 | 
				
			||||||
		case token.SUB:
 | 
					 | 
				
			||||||
			// (a-c) + i(b-d)
 | 
					 | 
				
			||||||
			re.Sub(a, c)
 | 
					 | 
				
			||||||
			im.Sub(b, d)
 | 
					 | 
				
			||||||
		case token.MUL:
 | 
					 | 
				
			||||||
			// (ac-bd) + i(bc+ad)
 | 
					 | 
				
			||||||
			var ac, bd, bc, ad big.Rat
 | 
					 | 
				
			||||||
			ac.Mul(a, c)
 | 
					 | 
				
			||||||
			bd.Mul(b, d)
 | 
					 | 
				
			||||||
			bc.Mul(b, c)
 | 
					 | 
				
			||||||
			ad.Mul(a, d)
 | 
					 | 
				
			||||||
			re.Sub(&ac, &bd)
 | 
					 | 
				
			||||||
			im.Add(&bc, &ad)
 | 
					 | 
				
			||||||
		case token.QUO:
 | 
					 | 
				
			||||||
			// (ac+bd)/s + i(bc-ad)/s, with s = cc + dd
 | 
					 | 
				
			||||||
			var ac, bd, bc, ad, s, cc, dd big.Rat
 | 
					 | 
				
			||||||
			ac.Mul(a, c)
 | 
					 | 
				
			||||||
			bd.Mul(b, d)
 | 
					 | 
				
			||||||
			bc.Mul(b, c)
 | 
					 | 
				
			||||||
			ad.Mul(a, d)
 | 
					 | 
				
			||||||
			cc.Mul(c, c)
 | 
					 | 
				
			||||||
			dd.Mul(d, d)
 | 
					 | 
				
			||||||
			s.Add(&cc, &dd)
 | 
					 | 
				
			||||||
			re.Add(&ac, &bd)
 | 
					 | 
				
			||||||
			re.Quo(&re, &s)
 | 
					 | 
				
			||||||
			im.Sub(&bc, &ad)
 | 
					 | 
				
			||||||
			im.Quo(&im, &s)
 | 
					 | 
				
			||||||
		default:
 | 
					 | 
				
			||||||
			goto Error
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		return normComplex(&re, &im)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	case stringVal:
 | 
					 | 
				
			||||||
		if op == token.ADD {
 | 
					 | 
				
			||||||
			return x + y.(stringVal)
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
Error:
 | 
					 | 
				
			||||||
	panic(fmt.Sprintf("invalid binary operation %v %s %v", x, op, y))
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// Shift returns the result of the shift expression x op s
 | 
					 | 
				
			||||||
// with op == token.SHL or token.SHR (<< or >>). x must be
 | 
					 | 
				
			||||||
// an Int or an Unknown. If x is Unknown, the result is x.
 | 
					 | 
				
			||||||
//
 | 
					 | 
				
			||||||
func Shift(x Value, op token.Token, s uint) Value {
 | 
					 | 
				
			||||||
	switch x := x.(type) {
 | 
					 | 
				
			||||||
	case unknownVal:
 | 
					 | 
				
			||||||
		return x
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	case int64Val:
 | 
					 | 
				
			||||||
		if s == 0 {
 | 
					 | 
				
			||||||
			return x
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		switch op {
 | 
					 | 
				
			||||||
		case token.SHL:
 | 
					 | 
				
			||||||
			z := big.NewInt(int64(x))
 | 
					 | 
				
			||||||
			return normInt(z.Lsh(z, s))
 | 
					 | 
				
			||||||
		case token.SHR:
 | 
					 | 
				
			||||||
			return x >> s
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	case intVal:
 | 
					 | 
				
			||||||
		if s == 0 {
 | 
					 | 
				
			||||||
			return x
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		var z big.Int
 | 
					 | 
				
			||||||
		switch op {
 | 
					 | 
				
			||||||
		case token.SHL:
 | 
					 | 
				
			||||||
			return normInt(z.Lsh(x.val, s))
 | 
					 | 
				
			||||||
		case token.SHR:
 | 
					 | 
				
			||||||
			return normInt(z.Rsh(x.val, s))
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	panic(fmt.Sprintf("invalid shift %v %s %d", x, op, s))
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func cmpZero(x int, op token.Token) bool {
 | 
					 | 
				
			||||||
	switch op {
 | 
					 | 
				
			||||||
	case token.EQL:
 | 
					 | 
				
			||||||
		return x == 0
 | 
					 | 
				
			||||||
	case token.NEQ:
 | 
					 | 
				
			||||||
		return x != 0
 | 
					 | 
				
			||||||
	case token.LSS:
 | 
					 | 
				
			||||||
		return x < 0
 | 
					 | 
				
			||||||
	case token.LEQ:
 | 
					 | 
				
			||||||
		return x <= 0
 | 
					 | 
				
			||||||
	case token.GTR:
 | 
					 | 
				
			||||||
		return x > 0
 | 
					 | 
				
			||||||
	case token.GEQ:
 | 
					 | 
				
			||||||
		return x >= 0
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	panic("unreachable")
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// Compare returns the result of the comparison x op y.
 | 
					 | 
				
			||||||
// The comparison must be defined for the operands.
 | 
					 | 
				
			||||||
// If one of the operands is Unknown, the result is
 | 
					 | 
				
			||||||
// false.
 | 
					 | 
				
			||||||
//
 | 
					 | 
				
			||||||
func Compare(x Value, op token.Token, y Value) bool {
 | 
					 | 
				
			||||||
	x, y = match(x, y)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	switch x := x.(type) {
 | 
					 | 
				
			||||||
	case unknownVal:
 | 
					 | 
				
			||||||
		return false
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	case boolVal:
 | 
					 | 
				
			||||||
		y := y.(boolVal)
 | 
					 | 
				
			||||||
		switch op {
 | 
					 | 
				
			||||||
		case token.EQL:
 | 
					 | 
				
			||||||
			return x == y
 | 
					 | 
				
			||||||
		case token.NEQ:
 | 
					 | 
				
			||||||
			return x != y
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	case int64Val:
 | 
					 | 
				
			||||||
		y := y.(int64Val)
 | 
					 | 
				
			||||||
		switch op {
 | 
					 | 
				
			||||||
		case token.EQL:
 | 
					 | 
				
			||||||
			return x == y
 | 
					 | 
				
			||||||
		case token.NEQ:
 | 
					 | 
				
			||||||
			return x != y
 | 
					 | 
				
			||||||
		case token.LSS:
 | 
					 | 
				
			||||||
			return x < y
 | 
					 | 
				
			||||||
		case token.LEQ:
 | 
					 | 
				
			||||||
			return x <= y
 | 
					 | 
				
			||||||
		case token.GTR:
 | 
					 | 
				
			||||||
			return x > y
 | 
					 | 
				
			||||||
		case token.GEQ:
 | 
					 | 
				
			||||||
			return x >= y
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	case intVal:
 | 
					 | 
				
			||||||
		return cmpZero(x.val.Cmp(y.(intVal).val), op)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	case floatVal:
 | 
					 | 
				
			||||||
		return cmpZero(x.val.Cmp(y.(floatVal).val), op)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	case complexVal:
 | 
					 | 
				
			||||||
		y := y.(complexVal)
 | 
					 | 
				
			||||||
		re := x.re.Cmp(y.re)
 | 
					 | 
				
			||||||
		im := x.im.Cmp(y.im)
 | 
					 | 
				
			||||||
		switch op {
 | 
					 | 
				
			||||||
		case token.EQL:
 | 
					 | 
				
			||||||
			return re == 0 && im == 0
 | 
					 | 
				
			||||||
		case token.NEQ:
 | 
					 | 
				
			||||||
			return re != 0 || im != 0
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	case stringVal:
 | 
					 | 
				
			||||||
		y := y.(stringVal)
 | 
					 | 
				
			||||||
		switch op {
 | 
					 | 
				
			||||||
		case token.EQL:
 | 
					 | 
				
			||||||
			return x == y
 | 
					 | 
				
			||||||
		case token.NEQ:
 | 
					 | 
				
			||||||
			return x != y
 | 
					 | 
				
			||||||
		case token.LSS:
 | 
					 | 
				
			||||||
			return x < y
 | 
					 | 
				
			||||||
		case token.LEQ:
 | 
					 | 
				
			||||||
			return x <= y
 | 
					 | 
				
			||||||
		case token.GTR:
 | 
					 | 
				
			||||||
			return x > y
 | 
					 | 
				
			||||||
		case token.GEQ:
 | 
					 | 
				
			||||||
			return x >= y
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	panic(fmt.Sprintf("invalid comparison %v %s %v", x, op, y))
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
							
								
								
									
										375
									
								
								third_party/golang/go/constant/value_test.go
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										375
									
								
								third_party/golang/go/constant/value_test.go
									
									
									
									
										vendored
									
									
								
							@@ -1,375 +0,0 @@
 | 
				
			|||||||
// Copyright 2013 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 constant
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
import (
 | 
					 | 
				
			||||||
	"k8s.io/kubernetes/third_party/golang/go/token"
 | 
					 | 
				
			||||||
	"strings"
 | 
					 | 
				
			||||||
	"testing"
 | 
					 | 
				
			||||||
)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// TODO(gri) expand this test framework
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
var opTests = []string{
 | 
					 | 
				
			||||||
	// unary operations
 | 
					 | 
				
			||||||
	`+ 0 = 0`,
 | 
					 | 
				
			||||||
	`+ ? = ?`,
 | 
					 | 
				
			||||||
	`- 1 = -1`,
 | 
					 | 
				
			||||||
	`- ? = ?`,
 | 
					 | 
				
			||||||
	`^ 0 = -1`,
 | 
					 | 
				
			||||||
	`^ ? = ?`,
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	`! true = false`,
 | 
					 | 
				
			||||||
	`! false = true`,
 | 
					 | 
				
			||||||
	`! ? = ?`,
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// etc.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// binary operations
 | 
					 | 
				
			||||||
	`"" + "" = ""`,
 | 
					 | 
				
			||||||
	`"foo" + "" = "foo"`,
 | 
					 | 
				
			||||||
	`"" + "bar" = "bar"`,
 | 
					 | 
				
			||||||
	`"foo" + "bar" = "foobar"`,
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	`0 + 0 = 0`,
 | 
					 | 
				
			||||||
	`0 + 0.1 = 0.1`,
 | 
					 | 
				
			||||||
	`0 + 0.1i = 0.1i`,
 | 
					 | 
				
			||||||
	`0.1 + 0.9 = 1`,
 | 
					 | 
				
			||||||
	`1e100 + 1e100 = 2e100`,
 | 
					 | 
				
			||||||
	`? + 0 = ?`,
 | 
					 | 
				
			||||||
	`0 + ? = ?`,
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	`0 - 0 = 0`,
 | 
					 | 
				
			||||||
	`0 - 0.1 = -0.1`,
 | 
					 | 
				
			||||||
	`0 - 0.1i = -0.1i`,
 | 
					 | 
				
			||||||
	`1e100 - 1e100 = 0`,
 | 
					 | 
				
			||||||
	`? - 0 = ?`,
 | 
					 | 
				
			||||||
	`0 - ? = ?`,
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	`0 * 0 = 0`,
 | 
					 | 
				
			||||||
	`1 * 0.1 = 0.1`,
 | 
					 | 
				
			||||||
	`1 * 0.1i = 0.1i`,
 | 
					 | 
				
			||||||
	`1i * 1i = -1`,
 | 
					 | 
				
			||||||
	`? * 0 = ?`,
 | 
					 | 
				
			||||||
	`0 * ? = ?`,
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	`0 / 0 = "division_by_zero"`,
 | 
					 | 
				
			||||||
	`10 / 2 = 5`,
 | 
					 | 
				
			||||||
	`5 / 3 = 5/3`,
 | 
					 | 
				
			||||||
	`5i / 3i = 5/3`,
 | 
					 | 
				
			||||||
	`? / 0 = ?`,
 | 
					 | 
				
			||||||
	`0 / ? = ?`,
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	`0 % 0 = "runtime_error:_integer_divide_by_zero"`, // TODO(gri) should be the same as for /
 | 
					 | 
				
			||||||
	`10 % 3 = 1`,
 | 
					 | 
				
			||||||
	`? % 0 = ?`,
 | 
					 | 
				
			||||||
	`0 % ? = ?`,
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	`0 & 0 = 0`,
 | 
					 | 
				
			||||||
	`12345 & 0 = 0`,
 | 
					 | 
				
			||||||
	`0xff & 0xf = 0xf`,
 | 
					 | 
				
			||||||
	`? & 0 = ?`,
 | 
					 | 
				
			||||||
	`0 & ? = ?`,
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	`0 | 0 = 0`,
 | 
					 | 
				
			||||||
	`12345 | 0 = 12345`,
 | 
					 | 
				
			||||||
	`0xb | 0xa0 = 0xab`,
 | 
					 | 
				
			||||||
	`? | 0 = ?`,
 | 
					 | 
				
			||||||
	`0 | ? = ?`,
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	`0 ^ 0 = 0`,
 | 
					 | 
				
			||||||
	`1 ^ -1 = -2`,
 | 
					 | 
				
			||||||
	`? ^ 0 = ?`,
 | 
					 | 
				
			||||||
	`0 ^ ? = ?`,
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	`0 &^ 0 = 0`,
 | 
					 | 
				
			||||||
	`0xf &^ 1 = 0xe`,
 | 
					 | 
				
			||||||
	`1 &^ 0xf = 0`,
 | 
					 | 
				
			||||||
	// etc.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// shifts
 | 
					 | 
				
			||||||
	`0 << 0 = 0`,
 | 
					 | 
				
			||||||
	`1 << 10 = 1024`,
 | 
					 | 
				
			||||||
	`0 >> 0 = 0`,
 | 
					 | 
				
			||||||
	`1024 >> 10 == 1`,
 | 
					 | 
				
			||||||
	`? << 0 == ?`,
 | 
					 | 
				
			||||||
	`? >> 10 == ?`,
 | 
					 | 
				
			||||||
	// etc.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// comparisons
 | 
					 | 
				
			||||||
	`false == false = true`,
 | 
					 | 
				
			||||||
	`false == true = false`,
 | 
					 | 
				
			||||||
	`true == false = false`,
 | 
					 | 
				
			||||||
	`true == true = true`,
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	`false != false = false`,
 | 
					 | 
				
			||||||
	`false != true = true`,
 | 
					 | 
				
			||||||
	`true != false = true`,
 | 
					 | 
				
			||||||
	`true != true = false`,
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	`"foo" == "bar" = false`,
 | 
					 | 
				
			||||||
	`"foo" != "bar" = true`,
 | 
					 | 
				
			||||||
	`"foo" < "bar" = false`,
 | 
					 | 
				
			||||||
	`"foo" <= "bar" = false`,
 | 
					 | 
				
			||||||
	`"foo" > "bar" = true`,
 | 
					 | 
				
			||||||
	`"foo" >= "bar" = true`,
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	`0 == 0 = true`,
 | 
					 | 
				
			||||||
	`0 != 0 = false`,
 | 
					 | 
				
			||||||
	`0 < 10 = true`,
 | 
					 | 
				
			||||||
	`10 <= 10 = true`,
 | 
					 | 
				
			||||||
	`0 > 10 = false`,
 | 
					 | 
				
			||||||
	`10 >= 10 = true`,
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	`1/123456789 == 1/123456789 == true`,
 | 
					 | 
				
			||||||
	`1/123456789 != 1/123456789 == false`,
 | 
					 | 
				
			||||||
	`1/123456789 < 1/123456788 == true`,
 | 
					 | 
				
			||||||
	`1/123456788 <= 1/123456789 == false`,
 | 
					 | 
				
			||||||
	`0.11 > 0.11 = false`,
 | 
					 | 
				
			||||||
	`0.11 >= 0.11 = true`,
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	`? == 0 = false`,
 | 
					 | 
				
			||||||
	`? != 0 = false`,
 | 
					 | 
				
			||||||
	`? < 10 = false`,
 | 
					 | 
				
			||||||
	`? <= 10 = false`,
 | 
					 | 
				
			||||||
	`? > 10 = false`,
 | 
					 | 
				
			||||||
	`? >= 10 = false`,
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	`0 == ? = false`,
 | 
					 | 
				
			||||||
	`0 != ? = false`,
 | 
					 | 
				
			||||||
	`0 < ? = false`,
 | 
					 | 
				
			||||||
	`10 <= ? = false`,
 | 
					 | 
				
			||||||
	`0 > ? = false`,
 | 
					 | 
				
			||||||
	`10 >= ? = false`,
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// etc.
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func TestOps(t *testing.T) {
 | 
					 | 
				
			||||||
	for _, test := range opTests {
 | 
					 | 
				
			||||||
		a := strings.Split(test, " ")
 | 
					 | 
				
			||||||
		i := 0 // operator index
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		var x, x0 Value
 | 
					 | 
				
			||||||
		switch len(a) {
 | 
					 | 
				
			||||||
		case 4:
 | 
					 | 
				
			||||||
			// unary operation
 | 
					 | 
				
			||||||
		case 5:
 | 
					 | 
				
			||||||
			// binary operation
 | 
					 | 
				
			||||||
			x, x0 = val(a[0]), val(a[0])
 | 
					 | 
				
			||||||
			i = 1
 | 
					 | 
				
			||||||
		default:
 | 
					 | 
				
			||||||
			t.Errorf("invalid test case: %s", test)
 | 
					 | 
				
			||||||
			continue
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		op, ok := optab[a[i]]
 | 
					 | 
				
			||||||
		if !ok {
 | 
					 | 
				
			||||||
			panic("missing optab entry for " + a[i])
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		y, y0 := val(a[i+1]), val(a[i+1])
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		got := doOp(x, op, y)
 | 
					 | 
				
			||||||
		want := val(a[i+3])
 | 
					 | 
				
			||||||
		if !eql(got, want) {
 | 
					 | 
				
			||||||
			t.Errorf("%s: got %s; want %s", test, got, want)
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		if x0 != nil && !eql(x, x0) {
 | 
					 | 
				
			||||||
			t.Errorf("%s: x changed to %s", test, x)
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		if !eql(y, y0) {
 | 
					 | 
				
			||||||
			t.Errorf("%s: y changed to %s", test, y)
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func eql(x, y Value) bool {
 | 
					 | 
				
			||||||
	_, ux := x.(unknownVal)
 | 
					 | 
				
			||||||
	_, uy := y.(unknownVal)
 | 
					 | 
				
			||||||
	if ux || uy {
 | 
					 | 
				
			||||||
		return ux == uy
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return Compare(x, token.EQL, y)
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// ----------------------------------------------------------------------------
 | 
					 | 
				
			||||||
// Support functions
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func val(lit string) Value {
 | 
					 | 
				
			||||||
	if len(lit) == 0 {
 | 
					 | 
				
			||||||
		return MakeUnknown()
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	switch lit {
 | 
					 | 
				
			||||||
	case "?":
 | 
					 | 
				
			||||||
		return MakeUnknown()
 | 
					 | 
				
			||||||
	case "true":
 | 
					 | 
				
			||||||
		return MakeBool(true)
 | 
					 | 
				
			||||||
	case "false":
 | 
					 | 
				
			||||||
		return MakeBool(false)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	tok := token.INT
 | 
					 | 
				
			||||||
	switch first, last := lit[0], lit[len(lit)-1]; {
 | 
					 | 
				
			||||||
	case first == '"' || first == '`':
 | 
					 | 
				
			||||||
		tok = token.STRING
 | 
					 | 
				
			||||||
		lit = strings.Replace(lit, "_", " ", -1)
 | 
					 | 
				
			||||||
	case first == '\'':
 | 
					 | 
				
			||||||
		tok = token.CHAR
 | 
					 | 
				
			||||||
	case last == 'i':
 | 
					 | 
				
			||||||
		tok = token.IMAG
 | 
					 | 
				
			||||||
	default:
 | 
					 | 
				
			||||||
		if !strings.HasPrefix(lit, "0x") && strings.ContainsAny(lit, "./Ee") {
 | 
					 | 
				
			||||||
			tok = token.FLOAT
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return MakeFromLiteral(lit, tok, 0)
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
var optab = map[string]token.Token{
 | 
					 | 
				
			||||||
	"!": token.NOT,
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	"+": token.ADD,
 | 
					 | 
				
			||||||
	"-": token.SUB,
 | 
					 | 
				
			||||||
	"*": token.MUL,
 | 
					 | 
				
			||||||
	"/": token.QUO,
 | 
					 | 
				
			||||||
	"%": token.REM,
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	"<<": token.SHL,
 | 
					 | 
				
			||||||
	">>": token.SHR,
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	"&":  token.AND,
 | 
					 | 
				
			||||||
	"|":  token.OR,
 | 
					 | 
				
			||||||
	"^":  token.XOR,
 | 
					 | 
				
			||||||
	"&^": token.AND_NOT,
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	"==": token.EQL,
 | 
					 | 
				
			||||||
	"!=": token.NEQ,
 | 
					 | 
				
			||||||
	"<":  token.LSS,
 | 
					 | 
				
			||||||
	"<=": token.LEQ,
 | 
					 | 
				
			||||||
	">":  token.GTR,
 | 
					 | 
				
			||||||
	">=": token.GEQ,
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func panicHandler(v *Value) {
 | 
					 | 
				
			||||||
	switch p := recover().(type) {
 | 
					 | 
				
			||||||
	case nil:
 | 
					 | 
				
			||||||
		// nothing to do
 | 
					 | 
				
			||||||
	case string:
 | 
					 | 
				
			||||||
		*v = MakeString(p)
 | 
					 | 
				
			||||||
	case error:
 | 
					 | 
				
			||||||
		*v = MakeString(p.Error())
 | 
					 | 
				
			||||||
	default:
 | 
					 | 
				
			||||||
		panic(p)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func doOp(x Value, op token.Token, y Value) (z Value) {
 | 
					 | 
				
			||||||
	defer panicHandler(&z)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if x == nil {
 | 
					 | 
				
			||||||
		return UnaryOp(op, y, 0)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	switch op {
 | 
					 | 
				
			||||||
	case token.EQL, token.NEQ, token.LSS, token.LEQ, token.GTR, token.GEQ:
 | 
					 | 
				
			||||||
		return MakeBool(Compare(x, op, y))
 | 
					 | 
				
			||||||
	case token.SHL, token.SHR:
 | 
					 | 
				
			||||||
		s, _ := Int64Val(y)
 | 
					 | 
				
			||||||
		return Shift(x, op, uint(s))
 | 
					 | 
				
			||||||
	default:
 | 
					 | 
				
			||||||
		return BinaryOp(x, op, y)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// ----------------------------------------------------------------------------
 | 
					 | 
				
			||||||
// Other tests
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
var fracTests = []string{
 | 
					 | 
				
			||||||
	"0 0 1",
 | 
					 | 
				
			||||||
	"1 1 1",
 | 
					 | 
				
			||||||
	"-1 -1 1",
 | 
					 | 
				
			||||||
	"1.2 6 5",
 | 
					 | 
				
			||||||
	"-0.991 -991 1000",
 | 
					 | 
				
			||||||
	"1e100 1e100 1",
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func TestFractions(t *testing.T) {
 | 
					 | 
				
			||||||
	for _, test := range fracTests {
 | 
					 | 
				
			||||||
		a := strings.Split(test, " ")
 | 
					 | 
				
			||||||
		if len(a) != 3 {
 | 
					 | 
				
			||||||
			t.Errorf("invalid test case: %s", test)
 | 
					 | 
				
			||||||
			continue
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		x := val(a[0])
 | 
					 | 
				
			||||||
		n := val(a[1])
 | 
					 | 
				
			||||||
		d := val(a[2])
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		if got := Num(x); !eql(got, n) {
 | 
					 | 
				
			||||||
			t.Errorf("%s: got num = %s; want %s", test, got, n)
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		if got := Denom(x); !eql(got, d) {
 | 
					 | 
				
			||||||
			t.Errorf("%s: got denom = %s; want %s", test, got, d)
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
var bytesTests = []string{
 | 
					 | 
				
			||||||
	"0",
 | 
					 | 
				
			||||||
	"1",
 | 
					 | 
				
			||||||
	"123456789",
 | 
					 | 
				
			||||||
	"123456789012345678901234567890123456789012345678901234567890",
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func TestBytes(t *testing.T) {
 | 
					 | 
				
			||||||
	for _, test := range bytesTests {
 | 
					 | 
				
			||||||
		x := val(test)
 | 
					 | 
				
			||||||
		bytes := Bytes(x)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		// special case 0
 | 
					 | 
				
			||||||
		if Sign(x) == 0 && len(bytes) != 0 {
 | 
					 | 
				
			||||||
			t.Errorf("%s: got %v; want empty byte slice", test, bytes)
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		if n := len(bytes); n > 0 && bytes[n-1] == 0 {
 | 
					 | 
				
			||||||
			t.Errorf("%s: got %v; want no leading 0 byte", test, bytes)
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		if got := MakeFromBytes(bytes); !eql(got, x) {
 | 
					 | 
				
			||||||
			t.Errorf("%s: got %s; want %s (bytes = %v)", test, got, x, bytes)
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func TestUnknown(t *testing.T) {
 | 
					 | 
				
			||||||
	u := MakeUnknown()
 | 
					 | 
				
			||||||
	var values = []Value{
 | 
					 | 
				
			||||||
		u,
 | 
					 | 
				
			||||||
		MakeBool(false), // token.ADD ok below, operation is never considered
 | 
					 | 
				
			||||||
		MakeString(""),
 | 
					 | 
				
			||||||
		MakeInt64(1),
 | 
					 | 
				
			||||||
		MakeFromLiteral("-1234567890123456789012345678901234567890", token.INT, 0),
 | 
					 | 
				
			||||||
		MakeFloat64(1.2),
 | 
					 | 
				
			||||||
		MakeImag(MakeFloat64(1.2)),
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	for _, val := range values {
 | 
					 | 
				
			||||||
		x, y := val, u
 | 
					 | 
				
			||||||
		for i := range [2]int{} {
 | 
					 | 
				
			||||||
			if i == 1 {
 | 
					 | 
				
			||||||
				x, y = y, x
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
			if got := BinaryOp(x, token.ADD, y); got.Kind() != Unknown {
 | 
					 | 
				
			||||||
				t.Errorf("%s + %s: got %s; want %s", x, y, got, u)
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
			if got := Compare(x, token.EQL, y); got {
 | 
					 | 
				
			||||||
				t.Errorf("%s == %s: got true; want false", x, y)
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
							
								
								
									
										7
									
								
								third_party/golang/go/doc/Makefile
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										7
									
								
								third_party/golang/go/doc/Makefile
									
									
									
									
										vendored
									
									
								
							@@ -1,7 +0,0 @@
 | 
				
			|||||||
# Copyright 2009 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.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# Script to test heading detection heuristic
 | 
					 | 
				
			||||||
headscan: headscan.go
 | 
					 | 
				
			||||||
	go build headscan.go
 | 
					 | 
				
			||||||
							
								
								
									
										480
									
								
								third_party/golang/go/doc/comment.go
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										480
									
								
								third_party/golang/go/doc/comment.go
									
									
									
									
										vendored
									
									
								
							@@ -1,480 +0,0 @@
 | 
				
			|||||||
// Copyright 2009 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.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// Godoc comment extraction and comment -> HTML formatting.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
package doc
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
import (
 | 
					 | 
				
			||||||
	"io"
 | 
					 | 
				
			||||||
	"regexp"
 | 
					 | 
				
			||||||
	"strings"
 | 
					 | 
				
			||||||
	"text/template" // for HTMLEscape
 | 
					 | 
				
			||||||
	"unicode"
 | 
					 | 
				
			||||||
	"unicode/utf8"
 | 
					 | 
				
			||||||
)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
var (
 | 
					 | 
				
			||||||
	ldquo = []byte("“")
 | 
					 | 
				
			||||||
	rdquo = []byte("”")
 | 
					 | 
				
			||||||
)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// Escape comment text for HTML. If nice is set,
 | 
					 | 
				
			||||||
// also turn `` into “ and '' into ”.
 | 
					 | 
				
			||||||
func commentEscape(w io.Writer, text string, nice bool) {
 | 
					 | 
				
			||||||
	last := 0
 | 
					 | 
				
			||||||
	if nice {
 | 
					 | 
				
			||||||
		for i := 0; i < len(text)-1; i++ {
 | 
					 | 
				
			||||||
			ch := text[i]
 | 
					 | 
				
			||||||
			if ch == text[i+1] && (ch == '`' || ch == '\'') {
 | 
					 | 
				
			||||||
				template.HTMLEscape(w, []byte(text[last:i]))
 | 
					 | 
				
			||||||
				last = i + 2
 | 
					 | 
				
			||||||
				switch ch {
 | 
					 | 
				
			||||||
				case '`':
 | 
					 | 
				
			||||||
					w.Write(ldquo)
 | 
					 | 
				
			||||||
				case '\'':
 | 
					 | 
				
			||||||
					w.Write(rdquo)
 | 
					 | 
				
			||||||
				}
 | 
					 | 
				
			||||||
				i++ // loop will add one more
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	template.HTMLEscape(w, []byte(text[last:]))
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
const (
 | 
					 | 
				
			||||||
	// Regexp for Go identifiers
 | 
					 | 
				
			||||||
	identRx = `[\pL_][\pL_0-9]*`
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// Regexp for URLs
 | 
					 | 
				
			||||||
	protocol = `https?|ftp|file|gopher|mailto|news|nntp|telnet|wais|prospero`
 | 
					 | 
				
			||||||
	hostPart = `[a-zA-Z0-9_@\-]+`
 | 
					 | 
				
			||||||
	filePart = `[a-zA-Z0-9_?%#~&/\-+=()]+` // parentheses may not be matching; see pairedParensPrefixLen
 | 
					 | 
				
			||||||
	urlRx    = `(` + protocol + `)://` +   // http://
 | 
					 | 
				
			||||||
		hostPart + `([.:]` + hostPart + `)*/?` + // //www.google.com:8080/
 | 
					 | 
				
			||||||
		filePart + `([:.,]` + filePart + `)*`
 | 
					 | 
				
			||||||
)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
var matchRx = regexp.MustCompile(`(` + urlRx + `)|(` + identRx + `)`)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
var (
 | 
					 | 
				
			||||||
	html_a      = []byte(`<a href="`)
 | 
					 | 
				
			||||||
	html_aq     = []byte(`">`)
 | 
					 | 
				
			||||||
	html_enda   = []byte("</a>")
 | 
					 | 
				
			||||||
	html_i      = []byte("<i>")
 | 
					 | 
				
			||||||
	html_endi   = []byte("</i>")
 | 
					 | 
				
			||||||
	html_p      = []byte("<p>\n")
 | 
					 | 
				
			||||||
	html_endp   = []byte("</p>\n")
 | 
					 | 
				
			||||||
	html_pre    = []byte("<pre>")
 | 
					 | 
				
			||||||
	html_endpre = []byte("</pre>\n")
 | 
					 | 
				
			||||||
	html_h      = []byte(`<h3 id="`)
 | 
					 | 
				
			||||||
	html_hq     = []byte(`">`)
 | 
					 | 
				
			||||||
	html_endh   = []byte("</h3>\n")
 | 
					 | 
				
			||||||
)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// pairedParensPrefixLen returns the length of the longest prefix of s containing paired parentheses.
 | 
					 | 
				
			||||||
func pairedParensPrefixLen(s string) int {
 | 
					 | 
				
			||||||
	parens := 0
 | 
					 | 
				
			||||||
	l := len(s)
 | 
					 | 
				
			||||||
	for i, ch := range s {
 | 
					 | 
				
			||||||
		switch ch {
 | 
					 | 
				
			||||||
		case '(':
 | 
					 | 
				
			||||||
			if parens == 0 {
 | 
					 | 
				
			||||||
				l = i
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
			parens++
 | 
					 | 
				
			||||||
		case ')':
 | 
					 | 
				
			||||||
			parens--
 | 
					 | 
				
			||||||
			if parens == 0 {
 | 
					 | 
				
			||||||
				l = len(s)
 | 
					 | 
				
			||||||
			} else if parens < 0 {
 | 
					 | 
				
			||||||
				return i
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return l
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// Emphasize and escape a line of text for HTML. URLs are converted into links;
 | 
					 | 
				
			||||||
// if the URL also appears in the words map, the link is taken from the map (if
 | 
					 | 
				
			||||||
// the corresponding map value is the empty string, the URL is not converted
 | 
					 | 
				
			||||||
// into a link). Go identifiers that appear in the words map are italicized; if
 | 
					 | 
				
			||||||
// the corresponding map value is not the empty string, it is considered a URL
 | 
					 | 
				
			||||||
// and the word is converted into a link. If nice is set, the remaining text's
 | 
					 | 
				
			||||||
// appearance is improved where it makes sense (e.g., `` is turned into “
 | 
					 | 
				
			||||||
// and '' into ”).
 | 
					 | 
				
			||||||
func emphasize(w io.Writer, line string, words map[string]string, nice bool) {
 | 
					 | 
				
			||||||
	for {
 | 
					 | 
				
			||||||
		m := matchRx.FindStringSubmatchIndex(line)
 | 
					 | 
				
			||||||
		if m == nil {
 | 
					 | 
				
			||||||
			break
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		// m >= 6 (two parenthesized sub-regexps in matchRx, 1st one is urlRx)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		// write text before match
 | 
					 | 
				
			||||||
		commentEscape(w, line[0:m[0]], nice)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		// adjust match if necessary
 | 
					 | 
				
			||||||
		match := line[m[0]:m[1]]
 | 
					 | 
				
			||||||
		if n := pairedParensPrefixLen(match); n < len(match) {
 | 
					 | 
				
			||||||
			// match contains unpaired parentheses (rare);
 | 
					 | 
				
			||||||
			// redo matching with shortened line for correct indices
 | 
					 | 
				
			||||||
			m = matchRx.FindStringSubmatchIndex(line[:m[0]+n])
 | 
					 | 
				
			||||||
			match = match[:n]
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		// analyze match
 | 
					 | 
				
			||||||
		url := ""
 | 
					 | 
				
			||||||
		italics := false
 | 
					 | 
				
			||||||
		if words != nil {
 | 
					 | 
				
			||||||
			url, italics = words[match]
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		if m[2] >= 0 {
 | 
					 | 
				
			||||||
			// match against first parenthesized sub-regexp; must be match against urlRx
 | 
					 | 
				
			||||||
			if !italics {
 | 
					 | 
				
			||||||
				// no alternative URL in words list, use match instead
 | 
					 | 
				
			||||||
				url = match
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
			italics = false // don't italicize URLs
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		// write match
 | 
					 | 
				
			||||||
		if len(url) > 0 {
 | 
					 | 
				
			||||||
			w.Write(html_a)
 | 
					 | 
				
			||||||
			template.HTMLEscape(w, []byte(url))
 | 
					 | 
				
			||||||
			w.Write(html_aq)
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		if italics {
 | 
					 | 
				
			||||||
			w.Write(html_i)
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		commentEscape(w, match, nice)
 | 
					 | 
				
			||||||
		if italics {
 | 
					 | 
				
			||||||
			w.Write(html_endi)
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		if len(url) > 0 {
 | 
					 | 
				
			||||||
			w.Write(html_enda)
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		// advance
 | 
					 | 
				
			||||||
		line = line[m[1]:]
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	commentEscape(w, line, nice)
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func indentLen(s string) int {
 | 
					 | 
				
			||||||
	i := 0
 | 
					 | 
				
			||||||
	for i < len(s) && (s[i] == ' ' || s[i] == '\t') {
 | 
					 | 
				
			||||||
		i++
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return i
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func isBlank(s string) bool {
 | 
					 | 
				
			||||||
	return len(s) == 0 || (len(s) == 1 && s[0] == '\n')
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func commonPrefix(a, b string) string {
 | 
					 | 
				
			||||||
	i := 0
 | 
					 | 
				
			||||||
	for i < len(a) && i < len(b) && a[i] == b[i] {
 | 
					 | 
				
			||||||
		i++
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return a[0:i]
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func unindent(block []string) {
 | 
					 | 
				
			||||||
	if len(block) == 0 {
 | 
					 | 
				
			||||||
		return
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// compute maximum common white prefix
 | 
					 | 
				
			||||||
	prefix := block[0][0:indentLen(block[0])]
 | 
					 | 
				
			||||||
	for _, line := range block {
 | 
					 | 
				
			||||||
		if !isBlank(line) {
 | 
					 | 
				
			||||||
			prefix = commonPrefix(prefix, line[0:indentLen(line)])
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	n := len(prefix)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// remove
 | 
					 | 
				
			||||||
	for i, line := range block {
 | 
					 | 
				
			||||||
		if !isBlank(line) {
 | 
					 | 
				
			||||||
			block[i] = line[n:]
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// heading returns the trimmed line if it passes as a section heading;
 | 
					 | 
				
			||||||
// otherwise it returns the empty string.
 | 
					 | 
				
			||||||
func heading(line string) string {
 | 
					 | 
				
			||||||
	line = strings.TrimSpace(line)
 | 
					 | 
				
			||||||
	if len(line) == 0 {
 | 
					 | 
				
			||||||
		return ""
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// a heading must start with an uppercase letter
 | 
					 | 
				
			||||||
	r, _ := utf8.DecodeRuneInString(line)
 | 
					 | 
				
			||||||
	if !unicode.IsLetter(r) || !unicode.IsUpper(r) {
 | 
					 | 
				
			||||||
		return ""
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// it must end in a letter or digit:
 | 
					 | 
				
			||||||
	r, _ = utf8.DecodeLastRuneInString(line)
 | 
					 | 
				
			||||||
	if !unicode.IsLetter(r) && !unicode.IsDigit(r) {
 | 
					 | 
				
			||||||
		return ""
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// exclude lines with illegal characters
 | 
					 | 
				
			||||||
	if strings.IndexAny(line, ",.;:!?+*/=()[]{}_^°&§~%#@<\">\\") >= 0 {
 | 
					 | 
				
			||||||
		return ""
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// allow "'" for possessive "'s" only
 | 
					 | 
				
			||||||
	for b := line; ; {
 | 
					 | 
				
			||||||
		i := strings.IndexRune(b, '\'')
 | 
					 | 
				
			||||||
		if i < 0 {
 | 
					 | 
				
			||||||
			break
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		if i+1 >= len(b) || b[i+1] != 's' || (i+2 < len(b) && b[i+2] != ' ') {
 | 
					 | 
				
			||||||
			return "" // not followed by "s "
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		b = b[i+2:]
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return line
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
type op int
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
const (
 | 
					 | 
				
			||||||
	opPara op = iota
 | 
					 | 
				
			||||||
	opHead
 | 
					 | 
				
			||||||
	opPre
 | 
					 | 
				
			||||||
)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
type block struct {
 | 
					 | 
				
			||||||
	op    op
 | 
					 | 
				
			||||||
	lines []string
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
var nonAlphaNumRx = regexp.MustCompile(`[^a-zA-Z0-9]`)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func anchorID(line string) string {
 | 
					 | 
				
			||||||
	// Add a "hdr-" prefix to avoid conflicting with IDs used for package symbols.
 | 
					 | 
				
			||||||
	return "hdr-" + nonAlphaNumRx.ReplaceAllString(line, "_")
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// ToHTML converts comment text to formatted HTML.
 | 
					 | 
				
			||||||
// The comment was prepared by DocReader,
 | 
					 | 
				
			||||||
// so it is known not to have leading, trailing blank lines
 | 
					 | 
				
			||||||
// nor to have trailing spaces at the end of lines.
 | 
					 | 
				
			||||||
// The comment markers have already been removed.
 | 
					 | 
				
			||||||
//
 | 
					 | 
				
			||||||
// Each span of unindented non-blank lines is converted into
 | 
					 | 
				
			||||||
// a single paragraph. There is one exception to the rule: a span that
 | 
					 | 
				
			||||||
// consists of a single line, is followed by another paragraph span,
 | 
					 | 
				
			||||||
// begins with a capital letter, and contains no punctuation
 | 
					 | 
				
			||||||
// is formatted as a heading.
 | 
					 | 
				
			||||||
//
 | 
					 | 
				
			||||||
// A span of indented lines is converted into a <pre> block,
 | 
					 | 
				
			||||||
// with the common indent prefix removed.
 | 
					 | 
				
			||||||
//
 | 
					 | 
				
			||||||
// URLs in the comment text are converted into links; if the URL also appears
 | 
					 | 
				
			||||||
// in the words map, the link is taken from the map (if the corresponding map
 | 
					 | 
				
			||||||
// value is the empty string, the URL is not converted into a link).
 | 
					 | 
				
			||||||
//
 | 
					 | 
				
			||||||
// Go identifiers that appear in the words map are italicized; if the corresponding
 | 
					 | 
				
			||||||
// map value is not the empty string, it is considered a URL and the word is converted
 | 
					 | 
				
			||||||
// into a link.
 | 
					 | 
				
			||||||
func ToHTML(w io.Writer, text string, words map[string]string) {
 | 
					 | 
				
			||||||
	for _, b := range blocks(text) {
 | 
					 | 
				
			||||||
		switch b.op {
 | 
					 | 
				
			||||||
		case opPara:
 | 
					 | 
				
			||||||
			w.Write(html_p)
 | 
					 | 
				
			||||||
			for _, line := range b.lines {
 | 
					 | 
				
			||||||
				emphasize(w, line, words, true)
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
			w.Write(html_endp)
 | 
					 | 
				
			||||||
		case opHead:
 | 
					 | 
				
			||||||
			w.Write(html_h)
 | 
					 | 
				
			||||||
			id := ""
 | 
					 | 
				
			||||||
			for _, line := range b.lines {
 | 
					 | 
				
			||||||
				if id == "" {
 | 
					 | 
				
			||||||
					id = anchorID(line)
 | 
					 | 
				
			||||||
					w.Write([]byte(id))
 | 
					 | 
				
			||||||
					w.Write(html_hq)
 | 
					 | 
				
			||||||
				}
 | 
					 | 
				
			||||||
				commentEscape(w, line, true)
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
			if id == "" {
 | 
					 | 
				
			||||||
				w.Write(html_hq)
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
			w.Write(html_endh)
 | 
					 | 
				
			||||||
		case opPre:
 | 
					 | 
				
			||||||
			w.Write(html_pre)
 | 
					 | 
				
			||||||
			for _, line := range b.lines {
 | 
					 | 
				
			||||||
				emphasize(w, line, nil, false)
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
			w.Write(html_endpre)
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func blocks(text string) []block {
 | 
					 | 
				
			||||||
	var (
 | 
					 | 
				
			||||||
		out  []block
 | 
					 | 
				
			||||||
		para []string
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		lastWasBlank   = false
 | 
					 | 
				
			||||||
		lastWasHeading = false
 | 
					 | 
				
			||||||
	)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	close := func() {
 | 
					 | 
				
			||||||
		if para != nil {
 | 
					 | 
				
			||||||
			out = append(out, block{opPara, para})
 | 
					 | 
				
			||||||
			para = nil
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	lines := strings.SplitAfter(text, "\n")
 | 
					 | 
				
			||||||
	unindent(lines)
 | 
					 | 
				
			||||||
	for i := 0; i < len(lines); {
 | 
					 | 
				
			||||||
		line := lines[i]
 | 
					 | 
				
			||||||
		if isBlank(line) {
 | 
					 | 
				
			||||||
			// close paragraph
 | 
					 | 
				
			||||||
			close()
 | 
					 | 
				
			||||||
			i++
 | 
					 | 
				
			||||||
			lastWasBlank = true
 | 
					 | 
				
			||||||
			continue
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		if indentLen(line) > 0 {
 | 
					 | 
				
			||||||
			// close paragraph
 | 
					 | 
				
			||||||
			close()
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			// count indented or blank lines
 | 
					 | 
				
			||||||
			j := i + 1
 | 
					 | 
				
			||||||
			for j < len(lines) && (isBlank(lines[j]) || indentLen(lines[j]) > 0) {
 | 
					 | 
				
			||||||
				j++
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
			// but not trailing blank lines
 | 
					 | 
				
			||||||
			for j > i && isBlank(lines[j-1]) {
 | 
					 | 
				
			||||||
				j--
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
			pre := lines[i:j]
 | 
					 | 
				
			||||||
			i = j
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			unindent(pre)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			// put those lines in a pre block
 | 
					 | 
				
			||||||
			out = append(out, block{opPre, pre})
 | 
					 | 
				
			||||||
			lastWasHeading = false
 | 
					 | 
				
			||||||
			continue
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		if lastWasBlank && !lastWasHeading && i+2 < len(lines) &&
 | 
					 | 
				
			||||||
			isBlank(lines[i+1]) && !isBlank(lines[i+2]) && indentLen(lines[i+2]) == 0 {
 | 
					 | 
				
			||||||
			// current line is non-blank, surrounded by blank lines
 | 
					 | 
				
			||||||
			// and the next non-blank line is not indented: this
 | 
					 | 
				
			||||||
			// might be a heading.
 | 
					 | 
				
			||||||
			if head := heading(line); head != "" {
 | 
					 | 
				
			||||||
				close()
 | 
					 | 
				
			||||||
				out = append(out, block{opHead, []string{head}})
 | 
					 | 
				
			||||||
				i += 2
 | 
					 | 
				
			||||||
				lastWasHeading = true
 | 
					 | 
				
			||||||
				continue
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		// open paragraph
 | 
					 | 
				
			||||||
		lastWasBlank = false
 | 
					 | 
				
			||||||
		lastWasHeading = false
 | 
					 | 
				
			||||||
		para = append(para, lines[i])
 | 
					 | 
				
			||||||
		i++
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	close()
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return out
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// ToText prepares comment text for presentation in textual output.
 | 
					 | 
				
			||||||
// It wraps paragraphs of text to width or fewer Unicode code points
 | 
					 | 
				
			||||||
// and then prefixes each line with the indent.  In preformatted sections
 | 
					 | 
				
			||||||
// (such as program text), it prefixes each non-blank line with preIndent.
 | 
					 | 
				
			||||||
func ToText(w io.Writer, text string, indent, preIndent string, width int) {
 | 
					 | 
				
			||||||
	l := lineWrapper{
 | 
					 | 
				
			||||||
		out:    w,
 | 
					 | 
				
			||||||
		width:  width,
 | 
					 | 
				
			||||||
		indent: indent,
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	for _, b := range blocks(text) {
 | 
					 | 
				
			||||||
		switch b.op {
 | 
					 | 
				
			||||||
		case opPara:
 | 
					 | 
				
			||||||
			// l.write will add leading newline if required
 | 
					 | 
				
			||||||
			for _, line := range b.lines {
 | 
					 | 
				
			||||||
				l.write(line)
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
			l.flush()
 | 
					 | 
				
			||||||
		case opHead:
 | 
					 | 
				
			||||||
			w.Write(nl)
 | 
					 | 
				
			||||||
			for _, line := range b.lines {
 | 
					 | 
				
			||||||
				l.write(line + "\n")
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
			l.flush()
 | 
					 | 
				
			||||||
		case opPre:
 | 
					 | 
				
			||||||
			w.Write(nl)
 | 
					 | 
				
			||||||
			for _, line := range b.lines {
 | 
					 | 
				
			||||||
				if isBlank(line) {
 | 
					 | 
				
			||||||
					w.Write([]byte("\n"))
 | 
					 | 
				
			||||||
				} else {
 | 
					 | 
				
			||||||
					w.Write([]byte(preIndent))
 | 
					 | 
				
			||||||
					w.Write([]byte(line))
 | 
					 | 
				
			||||||
				}
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
type lineWrapper struct {
 | 
					 | 
				
			||||||
	out       io.Writer
 | 
					 | 
				
			||||||
	printed   bool
 | 
					 | 
				
			||||||
	width     int
 | 
					 | 
				
			||||||
	indent    string
 | 
					 | 
				
			||||||
	n         int
 | 
					 | 
				
			||||||
	pendSpace int
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
var nl = []byte("\n")
 | 
					 | 
				
			||||||
var space = []byte(" ")
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (l *lineWrapper) write(text string) {
 | 
					 | 
				
			||||||
	if l.n == 0 && l.printed {
 | 
					 | 
				
			||||||
		l.out.Write(nl) // blank line before new paragraph
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	l.printed = true
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	for _, f := range strings.Fields(text) {
 | 
					 | 
				
			||||||
		w := utf8.RuneCountInString(f)
 | 
					 | 
				
			||||||
		// wrap if line is too long
 | 
					 | 
				
			||||||
		if l.n > 0 && l.n+l.pendSpace+w > l.width {
 | 
					 | 
				
			||||||
			l.out.Write(nl)
 | 
					 | 
				
			||||||
			l.n = 0
 | 
					 | 
				
			||||||
			l.pendSpace = 0
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		if l.n == 0 {
 | 
					 | 
				
			||||||
			l.out.Write([]byte(l.indent))
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		l.out.Write(space[:l.pendSpace])
 | 
					 | 
				
			||||||
		l.out.Write([]byte(f))
 | 
					 | 
				
			||||||
		l.n += l.pendSpace + w
 | 
					 | 
				
			||||||
		l.pendSpace = 1
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (l *lineWrapper) flush() {
 | 
					 | 
				
			||||||
	if l.n == 0 {
 | 
					 | 
				
			||||||
		return
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	l.out.Write(nl)
 | 
					 | 
				
			||||||
	l.pendSpace = 0
 | 
					 | 
				
			||||||
	l.n = 0
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
							
								
								
									
										207
									
								
								third_party/golang/go/doc/comment_test.go
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										207
									
								
								third_party/golang/go/doc/comment_test.go
									
									
									
									
										vendored
									
									
								
							@@ -1,207 +0,0 @@
 | 
				
			|||||||
// Copyright 2011 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 doc
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
import (
 | 
					 | 
				
			||||||
	"bytes"
 | 
					 | 
				
			||||||
	"reflect"
 | 
					 | 
				
			||||||
	"testing"
 | 
					 | 
				
			||||||
)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
var headingTests = []struct {
 | 
					 | 
				
			||||||
	line string
 | 
					 | 
				
			||||||
	ok   bool
 | 
					 | 
				
			||||||
}{
 | 
					 | 
				
			||||||
	{"Section", true},
 | 
					 | 
				
			||||||
	{"A typical usage", true},
 | 
					 | 
				
			||||||
	{"ΔΛΞ is Greek", true},
 | 
					 | 
				
			||||||
	{"Foo 42", true},
 | 
					 | 
				
			||||||
	{"", false},
 | 
					 | 
				
			||||||
	{"section", false},
 | 
					 | 
				
			||||||
	{"A typical usage:", false},
 | 
					 | 
				
			||||||
	{"This code:", false},
 | 
					 | 
				
			||||||
	{"δ is Greek", false},
 | 
					 | 
				
			||||||
	{"Foo §", false},
 | 
					 | 
				
			||||||
	{"Fermat's Last Sentence", true},
 | 
					 | 
				
			||||||
	{"Fermat's", true},
 | 
					 | 
				
			||||||
	{"'sX", false},
 | 
					 | 
				
			||||||
	{"Ted 'Too' Bar", false},
 | 
					 | 
				
			||||||
	{"Use n+m", false},
 | 
					 | 
				
			||||||
	{"Scanning:", false},
 | 
					 | 
				
			||||||
	{"N:M", false},
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func TestIsHeading(t *testing.T) {
 | 
					 | 
				
			||||||
	for _, tt := range headingTests {
 | 
					 | 
				
			||||||
		if h := heading(tt.line); (len(h) > 0) != tt.ok {
 | 
					 | 
				
			||||||
			t.Errorf("isHeading(%q) = %v, want %v", tt.line, h, tt.ok)
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
var blocksTests = []struct {
 | 
					 | 
				
			||||||
	in   string
 | 
					 | 
				
			||||||
	out  []block
 | 
					 | 
				
			||||||
	text string
 | 
					 | 
				
			||||||
}{
 | 
					 | 
				
			||||||
	{
 | 
					 | 
				
			||||||
		in: `Para 1.
 | 
					 | 
				
			||||||
Para 1 line 2.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
Para 2.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
Section
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
Para 3.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	pre
 | 
					 | 
				
			||||||
	pre1
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
Para 4.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	pre
 | 
					 | 
				
			||||||
	pre1
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	pre2
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
Para 5.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	pre
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	pre1
 | 
					 | 
				
			||||||
	pre2
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
Para 6.
 | 
					 | 
				
			||||||
	pre
 | 
					 | 
				
			||||||
	pre2
 | 
					 | 
				
			||||||
`,
 | 
					 | 
				
			||||||
		out: []block{
 | 
					 | 
				
			||||||
			{opPara, []string{"Para 1.\n", "Para 1 line 2.\n"}},
 | 
					 | 
				
			||||||
			{opPara, []string{"Para 2.\n"}},
 | 
					 | 
				
			||||||
			{opHead, []string{"Section"}},
 | 
					 | 
				
			||||||
			{opPara, []string{"Para 3.\n"}},
 | 
					 | 
				
			||||||
			{opPre, []string{"pre\n", "pre1\n"}},
 | 
					 | 
				
			||||||
			{opPara, []string{"Para 4.\n"}},
 | 
					 | 
				
			||||||
			{opPre, []string{"pre\n", "pre1\n", "\n", "pre2\n"}},
 | 
					 | 
				
			||||||
			{opPara, []string{"Para 5.\n"}},
 | 
					 | 
				
			||||||
			{opPre, []string{"pre\n", "\n", "\n", "pre1\n", "pre2\n"}},
 | 
					 | 
				
			||||||
			{opPara, []string{"Para 6.\n"}},
 | 
					 | 
				
			||||||
			{opPre, []string{"pre\n", "pre2\n"}},
 | 
					 | 
				
			||||||
		},
 | 
					 | 
				
			||||||
		text: `.   Para 1. Para 1 line 2.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
.   Para 2.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
.   Section
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
.   Para 3.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
$	pre
 | 
					 | 
				
			||||||
$	pre1
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
.   Para 4.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
$	pre
 | 
					 | 
				
			||||||
$	pre1
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
$	pre2
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
.   Para 5.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
$	pre
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
$	pre1
 | 
					 | 
				
			||||||
$	pre2
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
.   Para 6.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
$	pre
 | 
					 | 
				
			||||||
$	pre2
 | 
					 | 
				
			||||||
`,
 | 
					 | 
				
			||||||
	},
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func TestBlocks(t *testing.T) {
 | 
					 | 
				
			||||||
	for i, tt := range blocksTests {
 | 
					 | 
				
			||||||
		b := blocks(tt.in)
 | 
					 | 
				
			||||||
		if !reflect.DeepEqual(b, tt.out) {
 | 
					 | 
				
			||||||
			t.Errorf("#%d: mismatch\nhave: %v\nwant: %v", i, b, tt.out)
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func TestToText(t *testing.T) {
 | 
					 | 
				
			||||||
	var buf bytes.Buffer
 | 
					 | 
				
			||||||
	for i, tt := range blocksTests {
 | 
					 | 
				
			||||||
		ToText(&buf, tt.in, ".   ", "$\t", 40)
 | 
					 | 
				
			||||||
		if have := buf.String(); have != tt.text {
 | 
					 | 
				
			||||||
			t.Errorf("#%d: mismatch\nhave: %s\nwant: %s\nhave vs want:\n%q\n%q", i, have, tt.text, have, tt.text)
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		buf.Reset()
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
var emphasizeTests = []struct {
 | 
					 | 
				
			||||||
	in, out string
 | 
					 | 
				
			||||||
}{
 | 
					 | 
				
			||||||
	{"http://www.google.com/", `<a href="http://www.google.com/">http://www.google.com/</a>`},
 | 
					 | 
				
			||||||
	{"https://www.google.com/", `<a href="https://www.google.com/">https://www.google.com/</a>`},
 | 
					 | 
				
			||||||
	{"http://www.google.com/path.", `<a href="http://www.google.com/path">http://www.google.com/path</a>.`},
 | 
					 | 
				
			||||||
	{"http://en.wikipedia.org/wiki/Camellia_(cipher)", `<a href="http://en.wikipedia.org/wiki/Camellia_(cipher)">http://en.wikipedia.org/wiki/Camellia_(cipher)</a>`},
 | 
					 | 
				
			||||||
	{"(http://www.google.com/)", `(<a href="http://www.google.com/">http://www.google.com/</a>)`},
 | 
					 | 
				
			||||||
	{"http://gmail.com)", `<a href="http://gmail.com">http://gmail.com</a>)`},
 | 
					 | 
				
			||||||
	{"((http://gmail.com))", `((<a href="http://gmail.com">http://gmail.com</a>))`},
 | 
					 | 
				
			||||||
	{"http://gmail.com ((http://gmail.com)) ()", `<a href="http://gmail.com">http://gmail.com</a> ((<a href="http://gmail.com">http://gmail.com</a>)) ()`},
 | 
					 | 
				
			||||||
	{"Foo bar http://example.com/ quux!", `Foo bar <a href="http://example.com/">http://example.com/</a> quux!`},
 | 
					 | 
				
			||||||
	{"Hello http://example.com/%2f/ /world.", `Hello <a href="http://example.com/%2f/">http://example.com/%2f/</a> /world.`},
 | 
					 | 
				
			||||||
	{"Lorem http: ipsum //host/path", "Lorem http: ipsum //host/path"},
 | 
					 | 
				
			||||||
	{"javascript://is/not/linked", "javascript://is/not/linked"},
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func TestEmphasize(t *testing.T) {
 | 
					 | 
				
			||||||
	for i, tt := range emphasizeTests {
 | 
					 | 
				
			||||||
		var buf bytes.Buffer
 | 
					 | 
				
			||||||
		emphasize(&buf, tt.in, nil, true)
 | 
					 | 
				
			||||||
		out := buf.String()
 | 
					 | 
				
			||||||
		if out != tt.out {
 | 
					 | 
				
			||||||
			t.Errorf("#%d: mismatch\nhave: %v\nwant: %v", i, out, tt.out)
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
var pairedParensPrefixLenTests = []struct {
 | 
					 | 
				
			||||||
	in, out string
 | 
					 | 
				
			||||||
}{
 | 
					 | 
				
			||||||
	{"", ""},
 | 
					 | 
				
			||||||
	{"foo", "foo"},
 | 
					 | 
				
			||||||
	{"()", "()"},
 | 
					 | 
				
			||||||
	{"foo()", "foo()"},
 | 
					 | 
				
			||||||
	{"foo()()()", "foo()()()"},
 | 
					 | 
				
			||||||
	{"foo()((()()))", "foo()((()()))"},
 | 
					 | 
				
			||||||
	{"foo()((()()))bar", "foo()((()()))bar"},
 | 
					 | 
				
			||||||
	{"foo)", "foo"},
 | 
					 | 
				
			||||||
	{"foo))", "foo"},
 | 
					 | 
				
			||||||
	{"foo)))))", "foo"},
 | 
					 | 
				
			||||||
	{"(foo", ""},
 | 
					 | 
				
			||||||
	{"((foo", ""},
 | 
					 | 
				
			||||||
	{"(((((foo", ""},
 | 
					 | 
				
			||||||
	{"(foo)", "(foo)"},
 | 
					 | 
				
			||||||
	{"((((foo))))", "((((foo))))"},
 | 
					 | 
				
			||||||
	{"foo()())", "foo()()"},
 | 
					 | 
				
			||||||
	{"foo((()())", "foo"},
 | 
					 | 
				
			||||||
	{"foo((()())) (() foo ", "foo((()())) "},
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func TestPairedParensPrefixLen(t *testing.T) {
 | 
					 | 
				
			||||||
	for i, tt := range pairedParensPrefixLenTests {
 | 
					 | 
				
			||||||
		if out := tt.in[:pairedParensPrefixLen(tt.in)]; out != tt.out {
 | 
					 | 
				
			||||||
			t.Errorf("#%d: mismatch\nhave: %q\nwant: %q", i, out, tt.out)
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
							
								
								
									
										112
									
								
								third_party/golang/go/doc/doc.go
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										112
									
								
								third_party/golang/go/doc/doc.go
									
									
									
									
										vendored
									
									
								
							@@ -1,112 +0,0 @@
 | 
				
			|||||||
// Copyright 2009 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 doc extracts source code documentation from a Go AST.
 | 
					 | 
				
			||||||
package doc
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
import (
 | 
					 | 
				
			||||||
	"k8s.io/kubernetes/third_party/golang/go/ast"
 | 
					 | 
				
			||||||
	"k8s.io/kubernetes/third_party/golang/go/token"
 | 
					 | 
				
			||||||
)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// Package is the documentation for an entire package.
 | 
					 | 
				
			||||||
type Package struct {
 | 
					 | 
				
			||||||
	Doc        string
 | 
					 | 
				
			||||||
	Name       string
 | 
					 | 
				
			||||||
	ImportPath string
 | 
					 | 
				
			||||||
	Imports    []string
 | 
					 | 
				
			||||||
	Filenames  []string
 | 
					 | 
				
			||||||
	Notes      map[string][]*Note
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// Deprecated: For backward compatibility Bugs is still populated,
 | 
					 | 
				
			||||||
	// but all new code should use Notes instead.
 | 
					 | 
				
			||||||
	Bugs []string
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// declarations
 | 
					 | 
				
			||||||
	Consts []*Value
 | 
					 | 
				
			||||||
	Types  []*Type
 | 
					 | 
				
			||||||
	Vars   []*Value
 | 
					 | 
				
			||||||
	Funcs  []*Func
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// Value is the documentation for a (possibly grouped) var or const declaration.
 | 
					 | 
				
			||||||
type Value struct {
 | 
					 | 
				
			||||||
	Doc   string
 | 
					 | 
				
			||||||
	Names []string // var or const names in declaration order
 | 
					 | 
				
			||||||
	Decl  *ast.GenDecl
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	order int
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// Type is the documentation for a type declaration.
 | 
					 | 
				
			||||||
type Type struct {
 | 
					 | 
				
			||||||
	Doc  string
 | 
					 | 
				
			||||||
	Name string
 | 
					 | 
				
			||||||
	Decl *ast.GenDecl
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// associated declarations
 | 
					 | 
				
			||||||
	Consts  []*Value // sorted list of constants of (mostly) this type
 | 
					 | 
				
			||||||
	Vars    []*Value // sorted list of variables of (mostly) this type
 | 
					 | 
				
			||||||
	Funcs   []*Func  // sorted list of functions returning this type
 | 
					 | 
				
			||||||
	Methods []*Func  // sorted list of methods (including embedded ones) of this type
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// Func is the documentation for a func declaration.
 | 
					 | 
				
			||||||
type Func struct {
 | 
					 | 
				
			||||||
	Doc  string
 | 
					 | 
				
			||||||
	Name string
 | 
					 | 
				
			||||||
	Decl *ast.FuncDecl
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// methods
 | 
					 | 
				
			||||||
	// (for functions, these fields have the respective zero value)
 | 
					 | 
				
			||||||
	Recv  string // actual   receiver "T" or "*T"
 | 
					 | 
				
			||||||
	Orig  string // original receiver "T" or "*T"
 | 
					 | 
				
			||||||
	Level int    // embedding level; 0 means not embedded
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// A Note represents a marked comment starting with "MARKER(uid): note body".
 | 
					 | 
				
			||||||
// Any note with a marker of 2 or more upper case [A-Z] letters and a uid of
 | 
					 | 
				
			||||||
// at least one character is recognized. The ":" following the uid is optional.
 | 
					 | 
				
			||||||
// Notes are collected in the Package.Notes map indexed by the notes marker.
 | 
					 | 
				
			||||||
type Note struct {
 | 
					 | 
				
			||||||
	Pos, End token.Pos // position range of the comment containing the marker
 | 
					 | 
				
			||||||
	UID      string    // uid found with the marker
 | 
					 | 
				
			||||||
	Body     string    // note body text
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// Mode values control the operation of New.
 | 
					 | 
				
			||||||
type Mode int
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
const (
 | 
					 | 
				
			||||||
	// extract documentation for all package-level declarations,
 | 
					 | 
				
			||||||
	// not just exported ones
 | 
					 | 
				
			||||||
	AllDecls Mode = 1 << iota
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// show all embedded methods, not just the ones of
 | 
					 | 
				
			||||||
	// invisible (unexported) anonymous fields
 | 
					 | 
				
			||||||
	AllMethods
 | 
					 | 
				
			||||||
)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// New computes the package documentation for the given package AST.
 | 
					 | 
				
			||||||
// New takes ownership of the AST pkg and may edit or overwrite it.
 | 
					 | 
				
			||||||
//
 | 
					 | 
				
			||||||
func New(pkg *ast.Package, importPath string, mode Mode) *Package {
 | 
					 | 
				
			||||||
	var r reader
 | 
					 | 
				
			||||||
	r.readPackage(pkg, mode)
 | 
					 | 
				
			||||||
	r.computeMethodSets()
 | 
					 | 
				
			||||||
	r.cleanupTypes()
 | 
					 | 
				
			||||||
	return &Package{
 | 
					 | 
				
			||||||
		Doc:        r.doc,
 | 
					 | 
				
			||||||
		Name:       pkg.Name,
 | 
					 | 
				
			||||||
		ImportPath: importPath,
 | 
					 | 
				
			||||||
		Imports:    sortedKeys(r.imports),
 | 
					 | 
				
			||||||
		Filenames:  r.filenames,
 | 
					 | 
				
			||||||
		Notes:      r.notes,
 | 
					 | 
				
			||||||
		Bugs:       noteBodies(r.notes["BUG"]),
 | 
					 | 
				
			||||||
		Consts:     sortedValues(r.values, token.CONST),
 | 
					 | 
				
			||||||
		Types:      sortedTypes(r.types, mode&AllMethods != 0),
 | 
					 | 
				
			||||||
		Vars:       sortedValues(r.values, token.VAR),
 | 
					 | 
				
			||||||
		Funcs:      sortedFuncs(r.funcs, true),
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
							
								
								
									
										147
									
								
								third_party/golang/go/doc/doc_test.go
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										147
									
								
								third_party/golang/go/doc/doc_test.go
									
									
									
									
										vendored
									
									
								
							@@ -1,147 +0,0 @@
 | 
				
			|||||||
// Copyright 2012 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 doc
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
import (
 | 
					 | 
				
			||||||
	"bytes"
 | 
					 | 
				
			||||||
	"flag"
 | 
					 | 
				
			||||||
	"fmt"
 | 
					 | 
				
			||||||
	"io/ioutil"
 | 
					 | 
				
			||||||
	"os"
 | 
					 | 
				
			||||||
	"path/filepath"
 | 
					 | 
				
			||||||
	"regexp"
 | 
					 | 
				
			||||||
	"strings"
 | 
					 | 
				
			||||||
	"testing"
 | 
					 | 
				
			||||||
	"text/template"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	"k8s.io/kubernetes/third_party/golang/go/parser"
 | 
					 | 
				
			||||||
	"k8s.io/kubernetes/third_party/golang/go/printer"
 | 
					 | 
				
			||||||
	"k8s.io/kubernetes/third_party/golang/go/token"
 | 
					 | 
				
			||||||
)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
var update = flag.Bool("update", false, "update golden (.out) files")
 | 
					 | 
				
			||||||
var files = flag.String("files", "", "consider only Go test files matching this regular expression")
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
const dataDir = "testdata"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
var templateTxt = readTemplate("template.txt")
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func readTemplate(filename string) *template.Template {
 | 
					 | 
				
			||||||
	t := template.New(filename)
 | 
					 | 
				
			||||||
	t.Funcs(template.FuncMap{
 | 
					 | 
				
			||||||
		"node":     nodeFmt,
 | 
					 | 
				
			||||||
		"synopsis": synopsisFmt,
 | 
					 | 
				
			||||||
		"indent":   indentFmt,
 | 
					 | 
				
			||||||
	})
 | 
					 | 
				
			||||||
	return template.Must(t.ParseFiles(filepath.Join(dataDir, filename)))
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func nodeFmt(node interface{}, fset *token.FileSet) string {
 | 
					 | 
				
			||||||
	var buf bytes.Buffer
 | 
					 | 
				
			||||||
	printer.Fprint(&buf, fset, node)
 | 
					 | 
				
			||||||
	return strings.Replace(strings.TrimSpace(buf.String()), "\n", "\n\t", -1)
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func synopsisFmt(s string) string {
 | 
					 | 
				
			||||||
	const n = 64
 | 
					 | 
				
			||||||
	if len(s) > n {
 | 
					 | 
				
			||||||
		// cut off excess text and go back to a word boundary
 | 
					 | 
				
			||||||
		s = s[0:n]
 | 
					 | 
				
			||||||
		if i := strings.LastIndexAny(s, "\t\n "); i >= 0 {
 | 
					 | 
				
			||||||
			s = s[0:i]
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		s = strings.TrimSpace(s) + " ..."
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return "// " + strings.Replace(s, "\n", " ", -1)
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func indentFmt(indent, s string) string {
 | 
					 | 
				
			||||||
	end := ""
 | 
					 | 
				
			||||||
	if strings.HasSuffix(s, "\n") {
 | 
					 | 
				
			||||||
		end = "\n"
 | 
					 | 
				
			||||||
		s = s[:len(s)-1]
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return indent + strings.Replace(s, "\n", "\n"+indent, -1) + end
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func isGoFile(fi os.FileInfo) bool {
 | 
					 | 
				
			||||||
	name := fi.Name()
 | 
					 | 
				
			||||||
	return !fi.IsDir() &&
 | 
					 | 
				
			||||||
		len(name) > 0 && name[0] != '.' && // ignore .files
 | 
					 | 
				
			||||||
		filepath.Ext(name) == ".go"
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
type bundle struct {
 | 
					 | 
				
			||||||
	*Package
 | 
					 | 
				
			||||||
	FSet *token.FileSet
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func test(t *testing.T, mode Mode) {
 | 
					 | 
				
			||||||
	// determine file filter
 | 
					 | 
				
			||||||
	filter := isGoFile
 | 
					 | 
				
			||||||
	if *files != "" {
 | 
					 | 
				
			||||||
		rx, err := regexp.Compile(*files)
 | 
					 | 
				
			||||||
		if err != nil {
 | 
					 | 
				
			||||||
			t.Fatal(err)
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		filter = func(fi os.FileInfo) bool {
 | 
					 | 
				
			||||||
			return isGoFile(fi) && rx.MatchString(fi.Name())
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// get packages
 | 
					 | 
				
			||||||
	fset := token.NewFileSet()
 | 
					 | 
				
			||||||
	pkgs, err := parser.ParseDir(fset, dataDir, filter, parser.ParseComments)
 | 
					 | 
				
			||||||
	if err != nil {
 | 
					 | 
				
			||||||
		t.Fatal(err)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// test packages
 | 
					 | 
				
			||||||
	for _, pkg := range pkgs {
 | 
					 | 
				
			||||||
		importpath := dataDir + "/" + pkg.Name
 | 
					 | 
				
			||||||
		doc := New(pkg, importpath, mode)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		// golden files always use / in filenames - canonicalize them
 | 
					 | 
				
			||||||
		for i, filename := range doc.Filenames {
 | 
					 | 
				
			||||||
			doc.Filenames[i] = filepath.ToSlash(filename)
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		// print documentation
 | 
					 | 
				
			||||||
		var buf bytes.Buffer
 | 
					 | 
				
			||||||
		if err := templateTxt.Execute(&buf, bundle{doc, fset}); err != nil {
 | 
					 | 
				
			||||||
			t.Error(err)
 | 
					 | 
				
			||||||
			continue
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		got := buf.Bytes()
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		// update golden file if necessary
 | 
					 | 
				
			||||||
		golden := filepath.Join(dataDir, fmt.Sprintf("%s.%d.golden", pkg.Name, mode))
 | 
					 | 
				
			||||||
		if *update {
 | 
					 | 
				
			||||||
			err := ioutil.WriteFile(golden, got, 0644)
 | 
					 | 
				
			||||||
			if err != nil {
 | 
					 | 
				
			||||||
				t.Error(err)
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
			continue
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		// get golden file
 | 
					 | 
				
			||||||
		want, err := ioutil.ReadFile(golden)
 | 
					 | 
				
			||||||
		if err != nil {
 | 
					 | 
				
			||||||
			t.Error(err)
 | 
					 | 
				
			||||||
			continue
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		// compare
 | 
					 | 
				
			||||||
		if !bytes.Equal(got, want) {
 | 
					 | 
				
			||||||
			t.Errorf("package %s\n\tgot:\n%s\n\twant:\n%s", pkg.Name, got, want)
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func Test(t *testing.T) {
 | 
					 | 
				
			||||||
	test(t, 0)
 | 
					 | 
				
			||||||
	test(t, AllDecls)
 | 
					 | 
				
			||||||
	test(t, AllMethods)
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
							
								
								
									
										355
									
								
								third_party/golang/go/doc/example.go
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										355
									
								
								third_party/golang/go/doc/example.go
									
									
									
									
										vendored
									
									
								
							@@ -1,355 +0,0 @@
 | 
				
			|||||||
// Copyright 2011 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.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// Extract example functions from file ASTs.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
package doc
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
import (
 | 
					 | 
				
			||||||
	"k8s.io/kubernetes/third_party/golang/go/ast"
 | 
					 | 
				
			||||||
	"k8s.io/kubernetes/third_party/golang/go/token"
 | 
					 | 
				
			||||||
	"path"
 | 
					 | 
				
			||||||
	"regexp"
 | 
					 | 
				
			||||||
	"sort"
 | 
					 | 
				
			||||||
	"strconv"
 | 
					 | 
				
			||||||
	"strings"
 | 
					 | 
				
			||||||
	"unicode"
 | 
					 | 
				
			||||||
	"unicode/utf8"
 | 
					 | 
				
			||||||
)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// An Example represents an example function found in a source files.
 | 
					 | 
				
			||||||
type Example struct {
 | 
					 | 
				
			||||||
	Name        string // name of the item being exemplified
 | 
					 | 
				
			||||||
	Doc         string // example function doc string
 | 
					 | 
				
			||||||
	Code        ast.Node
 | 
					 | 
				
			||||||
	Play        *ast.File // a whole program version of the example
 | 
					 | 
				
			||||||
	Comments    []*ast.CommentGroup
 | 
					 | 
				
			||||||
	Output      string // expected output
 | 
					 | 
				
			||||||
	EmptyOutput bool   // expect empty output
 | 
					 | 
				
			||||||
	Order       int    // original source code order
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// Examples returns the examples found in the files, sorted by Name field.
 | 
					 | 
				
			||||||
// The Order fields record the order in which the examples were encountered.
 | 
					 | 
				
			||||||
//
 | 
					 | 
				
			||||||
// Playable Examples must be in a package whose name ends in "_test".
 | 
					 | 
				
			||||||
// An Example is "playable" (the Play field is non-nil) in either of these
 | 
					 | 
				
			||||||
// circumstances:
 | 
					 | 
				
			||||||
//   - The example function is self-contained: the function references only
 | 
					 | 
				
			||||||
//     identifiers from other packages (or predeclared identifiers, such as
 | 
					 | 
				
			||||||
//     "int") and the test file does not include a dot import.
 | 
					 | 
				
			||||||
//   - The entire test file is the example: the file contains exactly one
 | 
					 | 
				
			||||||
//     example function, zero test or benchmark functions, and at least one
 | 
					 | 
				
			||||||
//     top-level function, type, variable, or constant declaration other
 | 
					 | 
				
			||||||
//     than the example function.
 | 
					 | 
				
			||||||
func Examples(files ...*ast.File) []*Example {
 | 
					 | 
				
			||||||
	var list []*Example
 | 
					 | 
				
			||||||
	for _, file := range files {
 | 
					 | 
				
			||||||
		hasTests := false // file contains tests or benchmarks
 | 
					 | 
				
			||||||
		numDecl := 0      // number of non-import declarations in the file
 | 
					 | 
				
			||||||
		var flist []*Example
 | 
					 | 
				
			||||||
		for _, decl := range file.Decls {
 | 
					 | 
				
			||||||
			if g, ok := decl.(*ast.GenDecl); ok && g.Tok != token.IMPORT {
 | 
					 | 
				
			||||||
				numDecl++
 | 
					 | 
				
			||||||
				continue
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
			f, ok := decl.(*ast.FuncDecl)
 | 
					 | 
				
			||||||
			if !ok {
 | 
					 | 
				
			||||||
				continue
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
			numDecl++
 | 
					 | 
				
			||||||
			name := f.Name.Name
 | 
					 | 
				
			||||||
			if isTest(name, "Test") || isTest(name, "Benchmark") {
 | 
					 | 
				
			||||||
				hasTests = true
 | 
					 | 
				
			||||||
				continue
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
			if !isTest(name, "Example") {
 | 
					 | 
				
			||||||
				continue
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
			var doc string
 | 
					 | 
				
			||||||
			if f.Doc != nil {
 | 
					 | 
				
			||||||
				doc = f.Doc.Text()
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
			output, hasOutput := exampleOutput(f.Body, file.Comments)
 | 
					 | 
				
			||||||
			flist = append(flist, &Example{
 | 
					 | 
				
			||||||
				Name:        name[len("Example"):],
 | 
					 | 
				
			||||||
				Doc:         doc,
 | 
					 | 
				
			||||||
				Code:        f.Body,
 | 
					 | 
				
			||||||
				Play:        playExample(file, f.Body),
 | 
					 | 
				
			||||||
				Comments:    file.Comments,
 | 
					 | 
				
			||||||
				Output:      output,
 | 
					 | 
				
			||||||
				EmptyOutput: output == "" && hasOutput,
 | 
					 | 
				
			||||||
				Order:       len(flist),
 | 
					 | 
				
			||||||
			})
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		if !hasTests && numDecl > 1 && len(flist) == 1 {
 | 
					 | 
				
			||||||
			// If this file only has one example function, some
 | 
					 | 
				
			||||||
			// other top-level declarations, and no tests or
 | 
					 | 
				
			||||||
			// benchmarks, use the whole file as the example.
 | 
					 | 
				
			||||||
			flist[0].Code = file
 | 
					 | 
				
			||||||
			flist[0].Play = playExampleFile(file)
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		list = append(list, flist...)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	sort.Sort(exampleByName(list))
 | 
					 | 
				
			||||||
	return list
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
var outputPrefix = regexp.MustCompile(`(?i)^[[:space:]]*output:`)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// Extracts the expected output and whether there was a valid output comment
 | 
					 | 
				
			||||||
func exampleOutput(b *ast.BlockStmt, comments []*ast.CommentGroup) (output string, ok bool) {
 | 
					 | 
				
			||||||
	if _, last := lastComment(b, comments); last != nil {
 | 
					 | 
				
			||||||
		// test that it begins with the correct prefix
 | 
					 | 
				
			||||||
		text := last.Text()
 | 
					 | 
				
			||||||
		if loc := outputPrefix.FindStringIndex(text); loc != nil {
 | 
					 | 
				
			||||||
			text = text[loc[1]:]
 | 
					 | 
				
			||||||
			// Strip zero or more spaces followed by \n or a single space.
 | 
					 | 
				
			||||||
			text = strings.TrimLeft(text, " ")
 | 
					 | 
				
			||||||
			if len(text) > 0 && text[0] == '\n' {
 | 
					 | 
				
			||||||
				text = text[1:]
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
			return text, true
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return "", false // no suitable comment found
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// isTest tells whether name looks like a test, example, or benchmark.
 | 
					 | 
				
			||||||
// It is a Test (say) if there is a character after Test that is not a
 | 
					 | 
				
			||||||
// lower-case letter. (We don't want Testiness.)
 | 
					 | 
				
			||||||
func isTest(name, prefix string) bool {
 | 
					 | 
				
			||||||
	if !strings.HasPrefix(name, prefix) {
 | 
					 | 
				
			||||||
		return false
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	if len(name) == len(prefix) { // "Test" is ok
 | 
					 | 
				
			||||||
		return true
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	rune, _ := utf8.DecodeRuneInString(name[len(prefix):])
 | 
					 | 
				
			||||||
	return !unicode.IsLower(rune)
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
type exampleByName []*Example
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (s exampleByName) Len() int           { return len(s) }
 | 
					 | 
				
			||||||
func (s exampleByName) Swap(i, j int)      { s[i], s[j] = s[j], s[i] }
 | 
					 | 
				
			||||||
func (s exampleByName) Less(i, j int) bool { return s[i].Name < s[j].Name }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// playExample synthesizes a new *ast.File based on the provided
 | 
					 | 
				
			||||||
// file with the provided function body as the body of main.
 | 
					 | 
				
			||||||
func playExample(file *ast.File, body *ast.BlockStmt) *ast.File {
 | 
					 | 
				
			||||||
	if !strings.HasSuffix(file.Name.Name, "_test") {
 | 
					 | 
				
			||||||
		// We don't support examples that are part of the
 | 
					 | 
				
			||||||
		// greater package (yet).
 | 
					 | 
				
			||||||
		return nil
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// Find top-level declarations in the file.
 | 
					 | 
				
			||||||
	topDecls := make(map[*ast.Object]bool)
 | 
					 | 
				
			||||||
	for _, decl := range file.Decls {
 | 
					 | 
				
			||||||
		switch d := decl.(type) {
 | 
					 | 
				
			||||||
		case *ast.FuncDecl:
 | 
					 | 
				
			||||||
			topDecls[d.Name.Obj] = true
 | 
					 | 
				
			||||||
		case *ast.GenDecl:
 | 
					 | 
				
			||||||
			for _, spec := range d.Specs {
 | 
					 | 
				
			||||||
				switch s := spec.(type) {
 | 
					 | 
				
			||||||
				case *ast.TypeSpec:
 | 
					 | 
				
			||||||
					topDecls[s.Name.Obj] = true
 | 
					 | 
				
			||||||
				case *ast.ValueSpec:
 | 
					 | 
				
			||||||
					for _, id := range s.Names {
 | 
					 | 
				
			||||||
						topDecls[id.Obj] = true
 | 
					 | 
				
			||||||
					}
 | 
					 | 
				
			||||||
				}
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// Find unresolved identifiers and uses of top-level declarations.
 | 
					 | 
				
			||||||
	unresolved := make(map[string]bool)
 | 
					 | 
				
			||||||
	usesTopDecl := false
 | 
					 | 
				
			||||||
	var inspectFunc func(ast.Node) bool
 | 
					 | 
				
			||||||
	inspectFunc = func(n ast.Node) bool {
 | 
					 | 
				
			||||||
		// For selector expressions, only inspect the left hand side.
 | 
					 | 
				
			||||||
		// (For an expression like fmt.Println, only add "fmt" to the
 | 
					 | 
				
			||||||
		// set of unresolved names, not "Println".)
 | 
					 | 
				
			||||||
		if e, ok := n.(*ast.SelectorExpr); ok {
 | 
					 | 
				
			||||||
			ast.Inspect(e.X, inspectFunc)
 | 
					 | 
				
			||||||
			return false
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		// For key value expressions, only inspect the value
 | 
					 | 
				
			||||||
		// as the key should be resolved by the type of the
 | 
					 | 
				
			||||||
		// composite literal.
 | 
					 | 
				
			||||||
		if e, ok := n.(*ast.KeyValueExpr); ok {
 | 
					 | 
				
			||||||
			ast.Inspect(e.Value, inspectFunc)
 | 
					 | 
				
			||||||
			return false
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		if id, ok := n.(*ast.Ident); ok {
 | 
					 | 
				
			||||||
			if id.Obj == nil {
 | 
					 | 
				
			||||||
				unresolved[id.Name] = true
 | 
					 | 
				
			||||||
			} else if topDecls[id.Obj] {
 | 
					 | 
				
			||||||
				usesTopDecl = true
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		return true
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	ast.Inspect(body, inspectFunc)
 | 
					 | 
				
			||||||
	if usesTopDecl {
 | 
					 | 
				
			||||||
		// We don't support examples that are not self-contained (yet).
 | 
					 | 
				
			||||||
		return nil
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// Remove predeclared identifiers from unresolved list.
 | 
					 | 
				
			||||||
	for n := range unresolved {
 | 
					 | 
				
			||||||
		if predeclaredTypes[n] || predeclaredConstants[n] || predeclaredFuncs[n] {
 | 
					 | 
				
			||||||
			delete(unresolved, n)
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// Use unresolved identifiers to determine the imports used by this
 | 
					 | 
				
			||||||
	// example. The heuristic assumes package names match base import
 | 
					 | 
				
			||||||
	// paths for imports w/o renames (should be good enough most of the time).
 | 
					 | 
				
			||||||
	namedImports := make(map[string]string) // [name]path
 | 
					 | 
				
			||||||
	var blankImports []ast.Spec             // _ imports
 | 
					 | 
				
			||||||
	for _, s := range file.Imports {
 | 
					 | 
				
			||||||
		p, err := strconv.Unquote(s.Path.Value)
 | 
					 | 
				
			||||||
		if err != nil {
 | 
					 | 
				
			||||||
			continue
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		n := path.Base(p)
 | 
					 | 
				
			||||||
		if s.Name != nil {
 | 
					 | 
				
			||||||
			n = s.Name.Name
 | 
					 | 
				
			||||||
			switch n {
 | 
					 | 
				
			||||||
			case "_":
 | 
					 | 
				
			||||||
				blankImports = append(blankImports, s)
 | 
					 | 
				
			||||||
				continue
 | 
					 | 
				
			||||||
			case ".":
 | 
					 | 
				
			||||||
				// We can't resolve dot imports (yet).
 | 
					 | 
				
			||||||
				return nil
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		if unresolved[n] {
 | 
					 | 
				
			||||||
			namedImports[n] = p
 | 
					 | 
				
			||||||
			delete(unresolved, n)
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// If there are other unresolved identifiers, give up because this
 | 
					 | 
				
			||||||
	// synthesized file is not going to build.
 | 
					 | 
				
			||||||
	if len(unresolved) > 0 {
 | 
					 | 
				
			||||||
		return nil
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// Include documentation belonging to blank imports.
 | 
					 | 
				
			||||||
	var comments []*ast.CommentGroup
 | 
					 | 
				
			||||||
	for _, s := range blankImports {
 | 
					 | 
				
			||||||
		if c := s.(*ast.ImportSpec).Doc; c != nil {
 | 
					 | 
				
			||||||
			comments = append(comments, c)
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// Include comments that are inside the function body.
 | 
					 | 
				
			||||||
	for _, c := range file.Comments {
 | 
					 | 
				
			||||||
		if body.Pos() <= c.Pos() && c.End() <= body.End() {
 | 
					 | 
				
			||||||
			comments = append(comments, c)
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// Strip "Output:" comment and adjust body end position.
 | 
					 | 
				
			||||||
	body, comments = stripOutputComment(body, comments)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// Synthesize import declaration.
 | 
					 | 
				
			||||||
	importDecl := &ast.GenDecl{
 | 
					 | 
				
			||||||
		Tok:    token.IMPORT,
 | 
					 | 
				
			||||||
		Lparen: 1, // Need non-zero Lparen and Rparen so that printer
 | 
					 | 
				
			||||||
		Rparen: 1, // treats this as a factored import.
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	for n, p := range namedImports {
 | 
					 | 
				
			||||||
		s := &ast.ImportSpec{Path: &ast.BasicLit{Value: strconv.Quote(p)}}
 | 
					 | 
				
			||||||
		if path.Base(p) != n {
 | 
					 | 
				
			||||||
			s.Name = ast.NewIdent(n)
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		importDecl.Specs = append(importDecl.Specs, s)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	importDecl.Specs = append(importDecl.Specs, blankImports...)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// Synthesize main function.
 | 
					 | 
				
			||||||
	funcDecl := &ast.FuncDecl{
 | 
					 | 
				
			||||||
		Name: ast.NewIdent("main"),
 | 
					 | 
				
			||||||
		Type: &ast.FuncType{Params: &ast.FieldList{}}, // FuncType.Params must be non-nil
 | 
					 | 
				
			||||||
		Body: body,
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// Synthesize file.
 | 
					 | 
				
			||||||
	return &ast.File{
 | 
					 | 
				
			||||||
		Name:     ast.NewIdent("main"),
 | 
					 | 
				
			||||||
		Decls:    []ast.Decl{importDecl, funcDecl},
 | 
					 | 
				
			||||||
		Comments: comments,
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// playExampleFile takes a whole file example and synthesizes a new *ast.File
 | 
					 | 
				
			||||||
// such that the example is function main in package main.
 | 
					 | 
				
			||||||
func playExampleFile(file *ast.File) *ast.File {
 | 
					 | 
				
			||||||
	// Strip copyright comment if present.
 | 
					 | 
				
			||||||
	comments := file.Comments
 | 
					 | 
				
			||||||
	if len(comments) > 0 && strings.HasPrefix(comments[0].Text(), "Copyright") {
 | 
					 | 
				
			||||||
		comments = comments[1:]
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// Copy declaration slice, rewriting the ExampleX function to main.
 | 
					 | 
				
			||||||
	var decls []ast.Decl
 | 
					 | 
				
			||||||
	for _, d := range file.Decls {
 | 
					 | 
				
			||||||
		if f, ok := d.(*ast.FuncDecl); ok && isTest(f.Name.Name, "Example") {
 | 
					 | 
				
			||||||
			// Copy the FuncDecl, as it may be used elsewhere.
 | 
					 | 
				
			||||||
			newF := *f
 | 
					 | 
				
			||||||
			newF.Name = ast.NewIdent("main")
 | 
					 | 
				
			||||||
			newF.Body, comments = stripOutputComment(f.Body, comments)
 | 
					 | 
				
			||||||
			d = &newF
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		decls = append(decls, d)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// Copy the File, as it may be used elsewhere.
 | 
					 | 
				
			||||||
	f := *file
 | 
					 | 
				
			||||||
	f.Name = ast.NewIdent("main")
 | 
					 | 
				
			||||||
	f.Decls = decls
 | 
					 | 
				
			||||||
	f.Comments = comments
 | 
					 | 
				
			||||||
	return &f
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// stripOutputComment finds and removes an "Output:" comment from body
 | 
					 | 
				
			||||||
// and comments, and adjusts the body block's end position.
 | 
					 | 
				
			||||||
func stripOutputComment(body *ast.BlockStmt, comments []*ast.CommentGroup) (*ast.BlockStmt, []*ast.CommentGroup) {
 | 
					 | 
				
			||||||
	// Do nothing if no "Output:" comment found.
 | 
					 | 
				
			||||||
	i, last := lastComment(body, comments)
 | 
					 | 
				
			||||||
	if last == nil || !outputPrefix.MatchString(last.Text()) {
 | 
					 | 
				
			||||||
		return body, comments
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// Copy body and comments, as the originals may be used elsewhere.
 | 
					 | 
				
			||||||
	newBody := &ast.BlockStmt{
 | 
					 | 
				
			||||||
		Lbrace: body.Lbrace,
 | 
					 | 
				
			||||||
		List:   body.List,
 | 
					 | 
				
			||||||
		Rbrace: last.Pos(),
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	newComments := make([]*ast.CommentGroup, len(comments)-1)
 | 
					 | 
				
			||||||
	copy(newComments, comments[:i])
 | 
					 | 
				
			||||||
	copy(newComments[i:], comments[i+1:])
 | 
					 | 
				
			||||||
	return newBody, newComments
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// lastComment returns the last comment inside the provided block.
 | 
					 | 
				
			||||||
func lastComment(b *ast.BlockStmt, c []*ast.CommentGroup) (i int, last *ast.CommentGroup) {
 | 
					 | 
				
			||||||
	pos, end := b.Pos(), b.End()
 | 
					 | 
				
			||||||
	for j, cg := range c {
 | 
					 | 
				
			||||||
		if cg.Pos() < pos {
 | 
					 | 
				
			||||||
			continue
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		if cg.End() > end {
 | 
					 | 
				
			||||||
			break
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		i, last = j, cg
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
							
								
								
									
										191
									
								
								third_party/golang/go/doc/example_test.go
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										191
									
								
								third_party/golang/go/doc/example_test.go
									
									
									
									
										vendored
									
									
								
							@@ -1,191 +0,0 @@
 | 
				
			|||||||
// Copyright 2013 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 doc_test
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
import (
 | 
					 | 
				
			||||||
	"bytes"
 | 
					 | 
				
			||||||
	"go/doc"
 | 
					 | 
				
			||||||
	"go/format"
 | 
					 | 
				
			||||||
	"go/parser"
 | 
					 | 
				
			||||||
	"go/token"
 | 
					 | 
				
			||||||
	"strings"
 | 
					 | 
				
			||||||
	"testing"
 | 
					 | 
				
			||||||
)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
const exampleTestFile = `
 | 
					 | 
				
			||||||
package foo_test
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
import (
 | 
					 | 
				
			||||||
	"flag"
 | 
					 | 
				
			||||||
	"fmt"
 | 
					 | 
				
			||||||
	"log"
 | 
					 | 
				
			||||||
	"os/exec"
 | 
					 | 
				
			||||||
)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func ExampleHello() {
 | 
					 | 
				
			||||||
	fmt.Println("Hello, world!")
 | 
					 | 
				
			||||||
	// Output: Hello, world!
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func ExampleImport() {
 | 
					 | 
				
			||||||
	out, err := exec.Command("date").Output()
 | 
					 | 
				
			||||||
	if err != nil {
 | 
					 | 
				
			||||||
		log.Fatal(err)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	fmt.Printf("The date is %s\n", out)
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func ExampleKeyValue() {
 | 
					 | 
				
			||||||
	v := struct {
 | 
					 | 
				
			||||||
		a string
 | 
					 | 
				
			||||||
		b int
 | 
					 | 
				
			||||||
	}{
 | 
					 | 
				
			||||||
		a: "A",
 | 
					 | 
				
			||||||
		b: 1,
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	fmt.Print(v)
 | 
					 | 
				
			||||||
	// Output: a: "A", b: 1
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func ExampleKeyValueImport() {
 | 
					 | 
				
			||||||
	f := flag.Flag{
 | 
					 | 
				
			||||||
		Name: "play",
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	fmt.Print(f)
 | 
					 | 
				
			||||||
	// Output: Name: "play"
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
var keyValueTopDecl = struct {
 | 
					 | 
				
			||||||
	a string
 | 
					 | 
				
			||||||
	b int
 | 
					 | 
				
			||||||
}{
 | 
					 | 
				
			||||||
	a: "B",
 | 
					 | 
				
			||||||
	b: 2,
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func ExampleKeyValueTopDecl() {
 | 
					 | 
				
			||||||
	fmt.Print(keyValueTopDecl)
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
`
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
var exampleTestCases = []struct {
 | 
					 | 
				
			||||||
	Name, Play, Output string
 | 
					 | 
				
			||||||
}{
 | 
					 | 
				
			||||||
	{
 | 
					 | 
				
			||||||
		Name:   "Hello",
 | 
					 | 
				
			||||||
		Play:   exampleHelloPlay,
 | 
					 | 
				
			||||||
		Output: "Hello, world!\n",
 | 
					 | 
				
			||||||
	},
 | 
					 | 
				
			||||||
	{
 | 
					 | 
				
			||||||
		Name: "Import",
 | 
					 | 
				
			||||||
		Play: exampleImportPlay,
 | 
					 | 
				
			||||||
	},
 | 
					 | 
				
			||||||
	{
 | 
					 | 
				
			||||||
		Name:   "KeyValue",
 | 
					 | 
				
			||||||
		Play:   exampleKeyValuePlay,
 | 
					 | 
				
			||||||
		Output: "a: \"A\", b: 1\n",
 | 
					 | 
				
			||||||
	},
 | 
					 | 
				
			||||||
	{
 | 
					 | 
				
			||||||
		Name:   "KeyValueImport",
 | 
					 | 
				
			||||||
		Play:   exampleKeyValueImportPlay,
 | 
					 | 
				
			||||||
		Output: "Name: \"play\"\n",
 | 
					 | 
				
			||||||
	},
 | 
					 | 
				
			||||||
	{
 | 
					 | 
				
			||||||
		Name: "KeyValueTopDecl",
 | 
					 | 
				
			||||||
		Play: "<nil>",
 | 
					 | 
				
			||||||
	},
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
const exampleHelloPlay = `package main
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
import (
 | 
					 | 
				
			||||||
	"fmt"
 | 
					 | 
				
			||||||
)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func main() {
 | 
					 | 
				
			||||||
	fmt.Println("Hello, world!")
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
`
 | 
					 | 
				
			||||||
const exampleImportPlay = `package main
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
import (
 | 
					 | 
				
			||||||
	"fmt"
 | 
					 | 
				
			||||||
	"log"
 | 
					 | 
				
			||||||
	"os/exec"
 | 
					 | 
				
			||||||
)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func main() {
 | 
					 | 
				
			||||||
	out, err := exec.Command("date").Output()
 | 
					 | 
				
			||||||
	if err != nil {
 | 
					 | 
				
			||||||
		log.Fatal(err)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	fmt.Printf("The date is %s\n", out)
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
`
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
const exampleKeyValuePlay = `package main
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
import (
 | 
					 | 
				
			||||||
	"fmt"
 | 
					 | 
				
			||||||
)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func main() {
 | 
					 | 
				
			||||||
	v := struct {
 | 
					 | 
				
			||||||
		a string
 | 
					 | 
				
			||||||
		b int
 | 
					 | 
				
			||||||
	}{
 | 
					 | 
				
			||||||
		a: "A",
 | 
					 | 
				
			||||||
		b: 1,
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	fmt.Print(v)
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
`
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
const exampleKeyValueImportPlay = `package main
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
import (
 | 
					 | 
				
			||||||
	"flag"
 | 
					 | 
				
			||||||
	"fmt"
 | 
					 | 
				
			||||||
)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func main() {
 | 
					 | 
				
			||||||
	f := flag.Flag{
 | 
					 | 
				
			||||||
		Name: "play",
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	fmt.Print(f)
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
`
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func TestExamples(t *testing.T) {
 | 
					 | 
				
			||||||
	fset := token.NewFileSet()
 | 
					 | 
				
			||||||
	file, err := parser.ParseFile(fset, "test.go", strings.NewReader(exampleTestFile), parser.ParseComments)
 | 
					 | 
				
			||||||
	if err != nil {
 | 
					 | 
				
			||||||
		t.Fatal(err)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	for i, e := range doc.Examples(file) {
 | 
					 | 
				
			||||||
		c := exampleTestCases[i]
 | 
					 | 
				
			||||||
		if e.Name != c.Name {
 | 
					 | 
				
			||||||
			t.Errorf("got Name == %q, want %q", e.Name, c.Name)
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		if w := c.Play; w != "" {
 | 
					 | 
				
			||||||
			var g string // hah
 | 
					 | 
				
			||||||
			if e.Play == nil {
 | 
					 | 
				
			||||||
				g = "<nil>"
 | 
					 | 
				
			||||||
			} else {
 | 
					 | 
				
			||||||
				var buf bytes.Buffer
 | 
					 | 
				
			||||||
				if err := format.Node(&buf, fset, e.Play); err != nil {
 | 
					 | 
				
			||||||
					t.Fatal(err)
 | 
					 | 
				
			||||||
				}
 | 
					 | 
				
			||||||
				g = buf.String()
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
			if g != w {
 | 
					 | 
				
			||||||
				t.Errorf("%s: got Play == %q, want %q", c.Name, g, w)
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		if g, w := e.Output, c.Output; g != w {
 | 
					 | 
				
			||||||
			t.Errorf("%s: got Output == %q, want %q", c.Name, g, w)
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
							
								
								
									
										252
									
								
								third_party/golang/go/doc/exports.go
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										252
									
								
								third_party/golang/go/doc/exports.go
									
									
									
									
										vendored
									
									
								
							@@ -1,252 +0,0 @@
 | 
				
			|||||||
// Copyright 2011 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.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// This file implements export filtering of an AST.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
package doc
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
import (
 | 
					 | 
				
			||||||
	"k8s.io/kubernetes/third_party/golang/go/ast"
 | 
					 | 
				
			||||||
	"k8s.io/kubernetes/third_party/golang/go/token"
 | 
					 | 
				
			||||||
)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// filterIdentList removes unexported names from list in place
 | 
					 | 
				
			||||||
// and returns the resulting list.
 | 
					 | 
				
			||||||
//
 | 
					 | 
				
			||||||
func filterIdentList(list []*ast.Ident) []*ast.Ident {
 | 
					 | 
				
			||||||
	j := 0
 | 
					 | 
				
			||||||
	for _, x := range list {
 | 
					 | 
				
			||||||
		if ast.IsExported(x.Name) {
 | 
					 | 
				
			||||||
			list[j] = x
 | 
					 | 
				
			||||||
			j++
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return list[0:j]
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// hasExportedName reports whether list contains any exported names.
 | 
					 | 
				
			||||||
//
 | 
					 | 
				
			||||||
func hasExportedName(list []*ast.Ident) bool {
 | 
					 | 
				
			||||||
	for _, x := range list {
 | 
					 | 
				
			||||||
		if x.IsExported() {
 | 
					 | 
				
			||||||
			return true
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return false
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// removeErrorField removes anonymous fields named "error" from an interface.
 | 
					 | 
				
			||||||
// This is called when "error" has been determined to be a local name,
 | 
					 | 
				
			||||||
// not the predeclared type.
 | 
					 | 
				
			||||||
//
 | 
					 | 
				
			||||||
func removeErrorField(ityp *ast.InterfaceType) {
 | 
					 | 
				
			||||||
	list := ityp.Methods.List // we know that ityp.Methods != nil
 | 
					 | 
				
			||||||
	j := 0
 | 
					 | 
				
			||||||
	for _, field := range list {
 | 
					 | 
				
			||||||
		keepField := true
 | 
					 | 
				
			||||||
		if n := len(field.Names); n == 0 {
 | 
					 | 
				
			||||||
			// anonymous field
 | 
					 | 
				
			||||||
			if fname, _ := baseTypeName(field.Type); fname == "error" {
 | 
					 | 
				
			||||||
				keepField = false
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		if keepField {
 | 
					 | 
				
			||||||
			list[j] = field
 | 
					 | 
				
			||||||
			j++
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	if j < len(list) {
 | 
					 | 
				
			||||||
		ityp.Incomplete = true
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	ityp.Methods.List = list[0:j]
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// filterFieldList removes unexported fields (field names) from the field list
 | 
					 | 
				
			||||||
// in place and reports whether fields were removed. Anonymous fields are
 | 
					 | 
				
			||||||
// recorded with the parent type. filterType is called with the types of
 | 
					 | 
				
			||||||
// all remaining fields.
 | 
					 | 
				
			||||||
//
 | 
					 | 
				
			||||||
func (r *reader) filterFieldList(parent *namedType, fields *ast.FieldList, ityp *ast.InterfaceType) (removedFields bool) {
 | 
					 | 
				
			||||||
	if fields == nil {
 | 
					 | 
				
			||||||
		return
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	list := fields.List
 | 
					 | 
				
			||||||
	j := 0
 | 
					 | 
				
			||||||
	for _, field := range list {
 | 
					 | 
				
			||||||
		keepField := false
 | 
					 | 
				
			||||||
		if n := len(field.Names); n == 0 {
 | 
					 | 
				
			||||||
			// anonymous field
 | 
					 | 
				
			||||||
			fname := r.recordAnonymousField(parent, field.Type)
 | 
					 | 
				
			||||||
			if ast.IsExported(fname) {
 | 
					 | 
				
			||||||
				keepField = true
 | 
					 | 
				
			||||||
			} else if ityp != nil && fname == "error" {
 | 
					 | 
				
			||||||
				// possibly the predeclared error interface; keep
 | 
					 | 
				
			||||||
				// it for now but remember this interface so that
 | 
					 | 
				
			||||||
				// it can be fixed if error is also defined locally
 | 
					 | 
				
			||||||
				keepField = true
 | 
					 | 
				
			||||||
				r.remember(ityp)
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		} else {
 | 
					 | 
				
			||||||
			field.Names = filterIdentList(field.Names)
 | 
					 | 
				
			||||||
			if len(field.Names) < n {
 | 
					 | 
				
			||||||
				removedFields = true
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
			if len(field.Names) > 0 {
 | 
					 | 
				
			||||||
				keepField = true
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		if keepField {
 | 
					 | 
				
			||||||
			r.filterType(nil, field.Type)
 | 
					 | 
				
			||||||
			list[j] = field
 | 
					 | 
				
			||||||
			j++
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	if j < len(list) {
 | 
					 | 
				
			||||||
		removedFields = true
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	fields.List = list[0:j]
 | 
					 | 
				
			||||||
	return
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// filterParamList applies filterType to each parameter type in fields.
 | 
					 | 
				
			||||||
//
 | 
					 | 
				
			||||||
func (r *reader) filterParamList(fields *ast.FieldList) {
 | 
					 | 
				
			||||||
	if fields != nil {
 | 
					 | 
				
			||||||
		for _, f := range fields.List {
 | 
					 | 
				
			||||||
			r.filterType(nil, f.Type)
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// filterType strips any unexported struct fields or method types from typ
 | 
					 | 
				
			||||||
// in place. If fields (or methods) have been removed, the corresponding
 | 
					 | 
				
			||||||
// struct or interface type has the Incomplete field set to true.
 | 
					 | 
				
			||||||
//
 | 
					 | 
				
			||||||
func (r *reader) filterType(parent *namedType, typ ast.Expr) {
 | 
					 | 
				
			||||||
	switch t := typ.(type) {
 | 
					 | 
				
			||||||
	case *ast.Ident:
 | 
					 | 
				
			||||||
		// nothing to do
 | 
					 | 
				
			||||||
	case *ast.ParenExpr:
 | 
					 | 
				
			||||||
		r.filterType(nil, t.X)
 | 
					 | 
				
			||||||
	case *ast.ArrayType:
 | 
					 | 
				
			||||||
		r.filterType(nil, t.Elt)
 | 
					 | 
				
			||||||
	case *ast.StructType:
 | 
					 | 
				
			||||||
		if r.filterFieldList(parent, t.Fields, nil) {
 | 
					 | 
				
			||||||
			t.Incomplete = true
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	case *ast.FuncType:
 | 
					 | 
				
			||||||
		r.filterParamList(t.Params)
 | 
					 | 
				
			||||||
		r.filterParamList(t.Results)
 | 
					 | 
				
			||||||
	case *ast.InterfaceType:
 | 
					 | 
				
			||||||
		if r.filterFieldList(parent, t.Methods, t) {
 | 
					 | 
				
			||||||
			t.Incomplete = true
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	case *ast.MapType:
 | 
					 | 
				
			||||||
		r.filterType(nil, t.Key)
 | 
					 | 
				
			||||||
		r.filterType(nil, t.Value)
 | 
					 | 
				
			||||||
	case *ast.ChanType:
 | 
					 | 
				
			||||||
		r.filterType(nil, t.Value)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (r *reader) filterSpec(spec ast.Spec, tok token.Token) bool {
 | 
					 | 
				
			||||||
	switch s := spec.(type) {
 | 
					 | 
				
			||||||
	case *ast.ImportSpec:
 | 
					 | 
				
			||||||
		// always keep imports so we can collect them
 | 
					 | 
				
			||||||
		return true
 | 
					 | 
				
			||||||
	case *ast.ValueSpec:
 | 
					 | 
				
			||||||
		s.Names = filterIdentList(s.Names)
 | 
					 | 
				
			||||||
		if len(s.Names) > 0 {
 | 
					 | 
				
			||||||
			r.filterType(nil, s.Type)
 | 
					 | 
				
			||||||
			return true
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	case *ast.TypeSpec:
 | 
					 | 
				
			||||||
		if name := s.Name.Name; ast.IsExported(name) {
 | 
					 | 
				
			||||||
			r.filterType(r.lookupType(s.Name.Name), s.Type)
 | 
					 | 
				
			||||||
			return true
 | 
					 | 
				
			||||||
		} else if name == "error" {
 | 
					 | 
				
			||||||
			// special case: remember that error is declared locally
 | 
					 | 
				
			||||||
			r.errorDecl = true
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return false
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// copyConstType returns a copy of typ with position pos.
 | 
					 | 
				
			||||||
// typ must be a valid constant type.
 | 
					 | 
				
			||||||
// In practice, only (possibly qualified) identifiers are possible.
 | 
					 | 
				
			||||||
//
 | 
					 | 
				
			||||||
func copyConstType(typ ast.Expr, pos token.Pos) ast.Expr {
 | 
					 | 
				
			||||||
	switch typ := typ.(type) {
 | 
					 | 
				
			||||||
	case *ast.Ident:
 | 
					 | 
				
			||||||
		return &ast.Ident{Name: typ.Name, NamePos: pos}
 | 
					 | 
				
			||||||
	case *ast.SelectorExpr:
 | 
					 | 
				
			||||||
		if id, ok := typ.X.(*ast.Ident); ok {
 | 
					 | 
				
			||||||
			// presumably a qualified identifier
 | 
					 | 
				
			||||||
			return &ast.SelectorExpr{
 | 
					 | 
				
			||||||
				Sel: ast.NewIdent(typ.Sel.Name),
 | 
					 | 
				
			||||||
				X:   &ast.Ident{Name: id.Name, NamePos: pos},
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return nil // shouldn't happen, but be conservative and don't panic
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (r *reader) filterSpecList(list []ast.Spec, tok token.Token) []ast.Spec {
 | 
					 | 
				
			||||||
	if tok == token.CONST {
 | 
					 | 
				
			||||||
		// Propagate any type information that would get lost otherwise
 | 
					 | 
				
			||||||
		// when unexported constants are filtered.
 | 
					 | 
				
			||||||
		var prevType ast.Expr
 | 
					 | 
				
			||||||
		for _, spec := range list {
 | 
					 | 
				
			||||||
			spec := spec.(*ast.ValueSpec)
 | 
					 | 
				
			||||||
			if spec.Type == nil && prevType != nil {
 | 
					 | 
				
			||||||
				// provide current spec with an explicit type
 | 
					 | 
				
			||||||
				spec.Type = copyConstType(prevType, spec.Pos())
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
			if hasExportedName(spec.Names) {
 | 
					 | 
				
			||||||
				// exported names are preserved so there's no need to propagate the type
 | 
					 | 
				
			||||||
				prevType = nil
 | 
					 | 
				
			||||||
			} else {
 | 
					 | 
				
			||||||
				prevType = spec.Type
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	j := 0
 | 
					 | 
				
			||||||
	for _, s := range list {
 | 
					 | 
				
			||||||
		if r.filterSpec(s, tok) {
 | 
					 | 
				
			||||||
			list[j] = s
 | 
					 | 
				
			||||||
			j++
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return list[0:j]
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (r *reader) filterDecl(decl ast.Decl) bool {
 | 
					 | 
				
			||||||
	switch d := decl.(type) {
 | 
					 | 
				
			||||||
	case *ast.GenDecl:
 | 
					 | 
				
			||||||
		d.Specs = r.filterSpecList(d.Specs, d.Tok)
 | 
					 | 
				
			||||||
		return len(d.Specs) > 0
 | 
					 | 
				
			||||||
	case *ast.FuncDecl:
 | 
					 | 
				
			||||||
		// ok to filter these methods early because any
 | 
					 | 
				
			||||||
		// conflicting method will be filtered here, too -
 | 
					 | 
				
			||||||
		// thus, removing these methods early will not lead
 | 
					 | 
				
			||||||
		// to the false removal of possible conflicts
 | 
					 | 
				
			||||||
		return ast.IsExported(d.Name.Name)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return false
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// fileExports removes unexported declarations from src in place.
 | 
					 | 
				
			||||||
//
 | 
					 | 
				
			||||||
func (r *reader) fileExports(src *ast.File) {
 | 
					 | 
				
			||||||
	j := 0
 | 
					 | 
				
			||||||
	for _, d := range src.Decls {
 | 
					 | 
				
			||||||
		if r.filterDecl(d) {
 | 
					 | 
				
			||||||
			src.Decls[j] = d
 | 
					 | 
				
			||||||
			j++
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	src.Decls = src.Decls[0:j]
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
							
								
								
									
										105
									
								
								third_party/golang/go/doc/filter.go
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										105
									
								
								third_party/golang/go/doc/filter.go
									
									
									
									
										vendored
									
									
								
							@@ -1,105 +0,0 @@
 | 
				
			|||||||
// Copyright 2009 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 doc
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
import "k8s.io/kubernetes/third_party/golang/go/ast"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
type Filter func(string) bool
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func matchFields(fields *ast.FieldList, f Filter) bool {
 | 
					 | 
				
			||||||
	if fields != nil {
 | 
					 | 
				
			||||||
		for _, field := range fields.List {
 | 
					 | 
				
			||||||
			for _, name := range field.Names {
 | 
					 | 
				
			||||||
				if f(name.Name) {
 | 
					 | 
				
			||||||
					return true
 | 
					 | 
				
			||||||
				}
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return false
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func matchDecl(d *ast.GenDecl, f Filter) bool {
 | 
					 | 
				
			||||||
	for _, d := range d.Specs {
 | 
					 | 
				
			||||||
		switch v := d.(type) {
 | 
					 | 
				
			||||||
		case *ast.ValueSpec:
 | 
					 | 
				
			||||||
			for _, name := range v.Names {
 | 
					 | 
				
			||||||
				if f(name.Name) {
 | 
					 | 
				
			||||||
					return true
 | 
					 | 
				
			||||||
				}
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		case *ast.TypeSpec:
 | 
					 | 
				
			||||||
			if f(v.Name.Name) {
 | 
					 | 
				
			||||||
				return true
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
			switch t := v.Type.(type) {
 | 
					 | 
				
			||||||
			case *ast.StructType:
 | 
					 | 
				
			||||||
				if matchFields(t.Fields, f) {
 | 
					 | 
				
			||||||
					return true
 | 
					 | 
				
			||||||
				}
 | 
					 | 
				
			||||||
			case *ast.InterfaceType:
 | 
					 | 
				
			||||||
				if matchFields(t.Methods, f) {
 | 
					 | 
				
			||||||
					return true
 | 
					 | 
				
			||||||
				}
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return false
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func filterValues(a []*Value, f Filter) []*Value {
 | 
					 | 
				
			||||||
	w := 0
 | 
					 | 
				
			||||||
	for _, vd := range a {
 | 
					 | 
				
			||||||
		if matchDecl(vd.Decl, f) {
 | 
					 | 
				
			||||||
			a[w] = vd
 | 
					 | 
				
			||||||
			w++
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return a[0:w]
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func filterFuncs(a []*Func, f Filter) []*Func {
 | 
					 | 
				
			||||||
	w := 0
 | 
					 | 
				
			||||||
	for _, fd := range a {
 | 
					 | 
				
			||||||
		if f(fd.Name) {
 | 
					 | 
				
			||||||
			a[w] = fd
 | 
					 | 
				
			||||||
			w++
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return a[0:w]
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func filterTypes(a []*Type, f Filter) []*Type {
 | 
					 | 
				
			||||||
	w := 0
 | 
					 | 
				
			||||||
	for _, td := range a {
 | 
					 | 
				
			||||||
		n := 0 // number of matches
 | 
					 | 
				
			||||||
		if matchDecl(td.Decl, f) {
 | 
					 | 
				
			||||||
			n = 1
 | 
					 | 
				
			||||||
		} else {
 | 
					 | 
				
			||||||
			// type name doesn't match, but we may have matching consts, vars, factories or methods
 | 
					 | 
				
			||||||
			td.Consts = filterValues(td.Consts, f)
 | 
					 | 
				
			||||||
			td.Vars = filterValues(td.Vars, f)
 | 
					 | 
				
			||||||
			td.Funcs = filterFuncs(td.Funcs, f)
 | 
					 | 
				
			||||||
			td.Methods = filterFuncs(td.Methods, f)
 | 
					 | 
				
			||||||
			n += len(td.Consts) + len(td.Vars) + len(td.Funcs) + len(td.Methods)
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		if n > 0 {
 | 
					 | 
				
			||||||
			a[w] = td
 | 
					 | 
				
			||||||
			w++
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return a[0:w]
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// Filter eliminates documentation for names that don't pass through the filter f.
 | 
					 | 
				
			||||||
// TODO(gri): Recognize "Type.Method" as a name.
 | 
					 | 
				
			||||||
//
 | 
					 | 
				
			||||||
func (p *Package) Filter(f Filter) {
 | 
					 | 
				
			||||||
	p.Consts = filterValues(p.Consts, f)
 | 
					 | 
				
			||||||
	p.Vars = filterValues(p.Vars, f)
 | 
					 | 
				
			||||||
	p.Types = filterTypes(p.Types, f)
 | 
					 | 
				
			||||||
	p.Funcs = filterFuncs(p.Funcs, f)
 | 
					 | 
				
			||||||
	p.Doc = "" // don't show top-level package doc
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
							
								
								
									
										114
									
								
								third_party/golang/go/doc/headscan.go
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										114
									
								
								third_party/golang/go/doc/headscan.go
									
									
									
									
										vendored
									
									
								
							@@ -1,114 +0,0 @@
 | 
				
			|||||||
// Copyright 2011 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.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// +build ignore
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/*
 | 
					 | 
				
			||||||
	The headscan command extracts comment headings from package files;
 | 
					 | 
				
			||||||
	it is used to detect false positives which may require an adjustment
 | 
					 | 
				
			||||||
	to the comment formatting heuristics in comment.go.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	Usage: headscan [-root root_directory]
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	By default, the $GOROOT/src directory is scanned.
 | 
					 | 
				
			||||||
*/
 | 
					 | 
				
			||||||
package main
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
import (
 | 
					 | 
				
			||||||
	"bytes"
 | 
					 | 
				
			||||||
	"flag"
 | 
					 | 
				
			||||||
	"fmt"
 | 
					 | 
				
			||||||
	"k8s.io/kubernetes/third_party/golang/go/doc"
 | 
					 | 
				
			||||||
	"k8s.io/kubernetes/third_party/golang/go/parser"
 | 
					 | 
				
			||||||
	"k8s.io/kubernetes/third_party/golang/go/token"
 | 
					 | 
				
			||||||
	"os"
 | 
					 | 
				
			||||||
	"path/filepath"
 | 
					 | 
				
			||||||
	"regexp"
 | 
					 | 
				
			||||||
	"runtime"
 | 
					 | 
				
			||||||
	"strings"
 | 
					 | 
				
			||||||
)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
var (
 | 
					 | 
				
			||||||
	root    = flag.String("root", filepath.Join(runtime.GOROOT(), "src"), "root of filesystem tree to scan")
 | 
					 | 
				
			||||||
	verbose = flag.Bool("v", false, "verbose mode")
 | 
					 | 
				
			||||||
)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// ToHTML in comment.go assigns a (possibly blank) ID to each heading
 | 
					 | 
				
			||||||
var html_h = regexp.MustCompile(`<h3 id="[^"]*">`)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
const html_endh = "</h3>\n"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func isGoFile(fi os.FileInfo) bool {
 | 
					 | 
				
			||||||
	return strings.HasSuffix(fi.Name(), ".go") &&
 | 
					 | 
				
			||||||
		!strings.HasSuffix(fi.Name(), "_test.go")
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func appendHeadings(list []string, comment string) []string {
 | 
					 | 
				
			||||||
	var buf bytes.Buffer
 | 
					 | 
				
			||||||
	doc.ToHTML(&buf, comment, nil)
 | 
					 | 
				
			||||||
	for s := buf.String(); ; {
 | 
					 | 
				
			||||||
		loc := html_h.FindStringIndex(s)
 | 
					 | 
				
			||||||
		if len(loc) == 0 {
 | 
					 | 
				
			||||||
			break
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		i := loc[1]
 | 
					 | 
				
			||||||
		j := strings.Index(s, html_endh)
 | 
					 | 
				
			||||||
		if j < 0 {
 | 
					 | 
				
			||||||
			list = append(list, s[i:]) // incorrect HTML
 | 
					 | 
				
			||||||
			break
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		list = append(list, s[i:j])
 | 
					 | 
				
			||||||
		s = s[j+len(html_endh):]
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return list
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func main() {
 | 
					 | 
				
			||||||
	flag.Parse()
 | 
					 | 
				
			||||||
	fset := token.NewFileSet()
 | 
					 | 
				
			||||||
	nheadings := 0
 | 
					 | 
				
			||||||
	err := filepath.Walk(*root, func(path string, fi os.FileInfo, err error) error {
 | 
					 | 
				
			||||||
		if !fi.IsDir() {
 | 
					 | 
				
			||||||
			return nil
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		pkgs, err := parser.ParseDir(fset, path, isGoFile, parser.ParseComments)
 | 
					 | 
				
			||||||
		if err != nil {
 | 
					 | 
				
			||||||
			if *verbose {
 | 
					 | 
				
			||||||
				fmt.Fprintln(os.Stderr, err)
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
			return nil
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		for _, pkg := range pkgs {
 | 
					 | 
				
			||||||
			d := doc.New(pkg, path, doc.Mode(0))
 | 
					 | 
				
			||||||
			list := appendHeadings(nil, d.Doc)
 | 
					 | 
				
			||||||
			for _, d := range d.Consts {
 | 
					 | 
				
			||||||
				list = appendHeadings(list, d.Doc)
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
			for _, d := range d.Types {
 | 
					 | 
				
			||||||
				list = appendHeadings(list, d.Doc)
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
			for _, d := range d.Vars {
 | 
					 | 
				
			||||||
				list = appendHeadings(list, d.Doc)
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
			for _, d := range d.Funcs {
 | 
					 | 
				
			||||||
				list = appendHeadings(list, d.Doc)
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
			if len(list) > 0 {
 | 
					 | 
				
			||||||
				// directories may contain multiple packages;
 | 
					 | 
				
			||||||
				// print path and package name
 | 
					 | 
				
			||||||
				fmt.Printf("%s (package %s)\n", path, pkg.Name)
 | 
					 | 
				
			||||||
				for _, h := range list {
 | 
					 | 
				
			||||||
					fmt.Printf("\t%s\n", h)
 | 
					 | 
				
			||||||
				}
 | 
					 | 
				
			||||||
				nheadings += len(list)
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		return nil
 | 
					 | 
				
			||||||
	})
 | 
					 | 
				
			||||||
	if err != nil {
 | 
					 | 
				
			||||||
		fmt.Fprintln(os.Stderr, err)
 | 
					 | 
				
			||||||
		os.Exit(1)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	fmt.Println(nheadings, "headings found")
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
							
								
								
									
										853
									
								
								third_party/golang/go/doc/reader.go
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										853
									
								
								third_party/golang/go/doc/reader.go
									
									
									
									
										vendored
									
									
								
							@@ -1,853 +0,0 @@
 | 
				
			|||||||
// Copyright 2009 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 doc
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
import (
 | 
					 | 
				
			||||||
	"k8s.io/kubernetes/third_party/golang/go/ast"
 | 
					 | 
				
			||||||
	"k8s.io/kubernetes/third_party/golang/go/token"
 | 
					 | 
				
			||||||
	"regexp"
 | 
					 | 
				
			||||||
	"sort"
 | 
					 | 
				
			||||||
	"strconv"
 | 
					 | 
				
			||||||
)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// ----------------------------------------------------------------------------
 | 
					 | 
				
			||||||
// function/method sets
 | 
					 | 
				
			||||||
//
 | 
					 | 
				
			||||||
// Internally, we treat functions like methods and collect them in method sets.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// A methodSet describes a set of methods. Entries where Decl == nil are conflict
 | 
					 | 
				
			||||||
// entries (more then one method with the same name at the same embedding level).
 | 
					 | 
				
			||||||
//
 | 
					 | 
				
			||||||
type methodSet map[string]*Func
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// recvString returns a string representation of recv of the
 | 
					 | 
				
			||||||
// form "T", "*T", or "BADRECV" (if not a proper receiver type).
 | 
					 | 
				
			||||||
//
 | 
					 | 
				
			||||||
func recvString(recv ast.Expr) string {
 | 
					 | 
				
			||||||
	switch t := recv.(type) {
 | 
					 | 
				
			||||||
	case *ast.Ident:
 | 
					 | 
				
			||||||
		return t.Name
 | 
					 | 
				
			||||||
	case *ast.StarExpr:
 | 
					 | 
				
			||||||
		return "*" + recvString(t.X)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return "BADRECV"
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// set creates the corresponding Func for f and adds it to mset.
 | 
					 | 
				
			||||||
// If there are multiple f's with the same name, set keeps the first
 | 
					 | 
				
			||||||
// one with documentation; conflicts are ignored.
 | 
					 | 
				
			||||||
//
 | 
					 | 
				
			||||||
func (mset methodSet) set(f *ast.FuncDecl) {
 | 
					 | 
				
			||||||
	name := f.Name.Name
 | 
					 | 
				
			||||||
	if g := mset[name]; g != nil && g.Doc != "" {
 | 
					 | 
				
			||||||
		// A function with the same name has already been registered;
 | 
					 | 
				
			||||||
		// since it has documentation, assume f is simply another
 | 
					 | 
				
			||||||
		// implementation and ignore it. This does not happen if the
 | 
					 | 
				
			||||||
		// caller is using go/build.ScanDir to determine the list of
 | 
					 | 
				
			||||||
		// files implementing a package.
 | 
					 | 
				
			||||||
		return
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	// function doesn't exist or has no documentation; use f
 | 
					 | 
				
			||||||
	recv := ""
 | 
					 | 
				
			||||||
	if f.Recv != nil {
 | 
					 | 
				
			||||||
		var typ ast.Expr
 | 
					 | 
				
			||||||
		// be careful in case of incorrect ASTs
 | 
					 | 
				
			||||||
		if list := f.Recv.List; len(list) == 1 {
 | 
					 | 
				
			||||||
			typ = list[0].Type
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		recv = recvString(typ)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	mset[name] = &Func{
 | 
					 | 
				
			||||||
		Doc:  f.Doc.Text(),
 | 
					 | 
				
			||||||
		Name: name,
 | 
					 | 
				
			||||||
		Decl: f,
 | 
					 | 
				
			||||||
		Recv: recv,
 | 
					 | 
				
			||||||
		Orig: recv,
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	f.Doc = nil // doc consumed - remove from AST
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// add adds method m to the method set; m is ignored if the method set
 | 
					 | 
				
			||||||
// already contains a method with the same name at the same or a higher
 | 
					 | 
				
			||||||
// level then m.
 | 
					 | 
				
			||||||
//
 | 
					 | 
				
			||||||
func (mset methodSet) add(m *Func) {
 | 
					 | 
				
			||||||
	old := mset[m.Name]
 | 
					 | 
				
			||||||
	if old == nil || m.Level < old.Level {
 | 
					 | 
				
			||||||
		mset[m.Name] = m
 | 
					 | 
				
			||||||
		return
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	if old != nil && m.Level == old.Level {
 | 
					 | 
				
			||||||
		// conflict - mark it using a method with nil Decl
 | 
					 | 
				
			||||||
		mset[m.Name] = &Func{
 | 
					 | 
				
			||||||
			Name:  m.Name,
 | 
					 | 
				
			||||||
			Level: m.Level,
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// ----------------------------------------------------------------------------
 | 
					 | 
				
			||||||
// Named types
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// baseTypeName returns the name of the base type of x (or "")
 | 
					 | 
				
			||||||
// and whether the type is imported or not.
 | 
					 | 
				
			||||||
//
 | 
					 | 
				
			||||||
func baseTypeName(x ast.Expr) (name string, imported bool) {
 | 
					 | 
				
			||||||
	switch t := x.(type) {
 | 
					 | 
				
			||||||
	case *ast.Ident:
 | 
					 | 
				
			||||||
		return t.Name, false
 | 
					 | 
				
			||||||
	case *ast.SelectorExpr:
 | 
					 | 
				
			||||||
		if _, ok := t.X.(*ast.Ident); ok {
 | 
					 | 
				
			||||||
			// only possible for qualified type names;
 | 
					 | 
				
			||||||
			// assume type is imported
 | 
					 | 
				
			||||||
			return t.Sel.Name, true
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	case *ast.StarExpr:
 | 
					 | 
				
			||||||
		return baseTypeName(t.X)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// An embeddedSet describes a set of embedded types.
 | 
					 | 
				
			||||||
type embeddedSet map[*namedType]bool
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// A namedType represents a named unqualified (package local, or possibly
 | 
					 | 
				
			||||||
// predeclared) type. The namedType for a type name is always found via
 | 
					 | 
				
			||||||
// reader.lookupType.
 | 
					 | 
				
			||||||
//
 | 
					 | 
				
			||||||
type namedType struct {
 | 
					 | 
				
			||||||
	doc  string       // doc comment for type
 | 
					 | 
				
			||||||
	name string       // type name
 | 
					 | 
				
			||||||
	decl *ast.GenDecl // nil if declaration hasn't been seen yet
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	isEmbedded bool        // true if this type is embedded
 | 
					 | 
				
			||||||
	isStruct   bool        // true if this type is a struct
 | 
					 | 
				
			||||||
	embedded   embeddedSet // true if the embedded type is a pointer
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// associated declarations
 | 
					 | 
				
			||||||
	values  []*Value // consts and vars
 | 
					 | 
				
			||||||
	funcs   methodSet
 | 
					 | 
				
			||||||
	methods methodSet
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// ----------------------------------------------------------------------------
 | 
					 | 
				
			||||||
// AST reader
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// reader accumulates documentation for a single package.
 | 
					 | 
				
			||||||
// It modifies the AST: Comments (declaration documentation)
 | 
					 | 
				
			||||||
// that have been collected by the reader are set to nil
 | 
					 | 
				
			||||||
// in the respective AST nodes so that they are not printed
 | 
					 | 
				
			||||||
// twice (once when printing the documentation and once when
 | 
					 | 
				
			||||||
// printing the corresponding AST node).
 | 
					 | 
				
			||||||
//
 | 
					 | 
				
			||||||
type reader struct {
 | 
					 | 
				
			||||||
	mode Mode
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// package properties
 | 
					 | 
				
			||||||
	doc       string // package documentation, if any
 | 
					 | 
				
			||||||
	filenames []string
 | 
					 | 
				
			||||||
	notes     map[string][]*Note
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// declarations
 | 
					 | 
				
			||||||
	imports map[string]int
 | 
					 | 
				
			||||||
	values  []*Value // consts and vars
 | 
					 | 
				
			||||||
	types   map[string]*namedType
 | 
					 | 
				
			||||||
	funcs   methodSet
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// support for package-local error type declarations
 | 
					 | 
				
			||||||
	errorDecl bool                 // if set, type "error" was declared locally
 | 
					 | 
				
			||||||
	fixlist   []*ast.InterfaceType // list of interfaces containing anonymous field "error"
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (r *reader) isVisible(name string) bool {
 | 
					 | 
				
			||||||
	return r.mode&AllDecls != 0 || ast.IsExported(name)
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// lookupType returns the base type with the given name.
 | 
					 | 
				
			||||||
// If the base type has not been encountered yet, a new
 | 
					 | 
				
			||||||
// type with the given name but no associated declaration
 | 
					 | 
				
			||||||
// is added to the type map.
 | 
					 | 
				
			||||||
//
 | 
					 | 
				
			||||||
func (r *reader) lookupType(name string) *namedType {
 | 
					 | 
				
			||||||
	if name == "" || name == "_" {
 | 
					 | 
				
			||||||
		return nil // no type docs for anonymous types
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	if typ, found := r.types[name]; found {
 | 
					 | 
				
			||||||
		return typ
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	// type not found - add one without declaration
 | 
					 | 
				
			||||||
	typ := &namedType{
 | 
					 | 
				
			||||||
		name:     name,
 | 
					 | 
				
			||||||
		embedded: make(embeddedSet),
 | 
					 | 
				
			||||||
		funcs:    make(methodSet),
 | 
					 | 
				
			||||||
		methods:  make(methodSet),
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	r.types[name] = typ
 | 
					 | 
				
			||||||
	return typ
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// recordAnonymousField registers fieldType as the type of an
 | 
					 | 
				
			||||||
// anonymous field in the parent type. If the field is imported
 | 
					 | 
				
			||||||
// (qualified name) or the parent is nil, the field is ignored.
 | 
					 | 
				
			||||||
// The function returns the field name.
 | 
					 | 
				
			||||||
//
 | 
					 | 
				
			||||||
func (r *reader) recordAnonymousField(parent *namedType, fieldType ast.Expr) (fname string) {
 | 
					 | 
				
			||||||
	fname, imp := baseTypeName(fieldType)
 | 
					 | 
				
			||||||
	if parent == nil || imp {
 | 
					 | 
				
			||||||
		return
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	if ftype := r.lookupType(fname); ftype != nil {
 | 
					 | 
				
			||||||
		ftype.isEmbedded = true
 | 
					 | 
				
			||||||
		_, ptr := fieldType.(*ast.StarExpr)
 | 
					 | 
				
			||||||
		parent.embedded[ftype] = ptr
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (r *reader) readDoc(comment *ast.CommentGroup) {
 | 
					 | 
				
			||||||
	// By convention there should be only one package comment
 | 
					 | 
				
			||||||
	// but collect all of them if there are more then one.
 | 
					 | 
				
			||||||
	text := comment.Text()
 | 
					 | 
				
			||||||
	if r.doc == "" {
 | 
					 | 
				
			||||||
		r.doc = text
 | 
					 | 
				
			||||||
		return
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	r.doc += "\n" + text
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (r *reader) remember(typ *ast.InterfaceType) {
 | 
					 | 
				
			||||||
	r.fixlist = append(r.fixlist, typ)
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func specNames(specs []ast.Spec) []string {
 | 
					 | 
				
			||||||
	names := make([]string, 0, len(specs)) // reasonable estimate
 | 
					 | 
				
			||||||
	for _, s := range specs {
 | 
					 | 
				
			||||||
		// s guaranteed to be an *ast.ValueSpec by readValue
 | 
					 | 
				
			||||||
		for _, ident := range s.(*ast.ValueSpec).Names {
 | 
					 | 
				
			||||||
			names = append(names, ident.Name)
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return names
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// readValue processes a const or var declaration.
 | 
					 | 
				
			||||||
//
 | 
					 | 
				
			||||||
func (r *reader) readValue(decl *ast.GenDecl) {
 | 
					 | 
				
			||||||
	// determine if decl should be associated with a type
 | 
					 | 
				
			||||||
	// Heuristic: For each typed entry, determine the type name, if any.
 | 
					 | 
				
			||||||
	//            If there is exactly one type name that is sufficiently
 | 
					 | 
				
			||||||
	//            frequent, associate the decl with the respective type.
 | 
					 | 
				
			||||||
	domName := ""
 | 
					 | 
				
			||||||
	domFreq := 0
 | 
					 | 
				
			||||||
	prev := ""
 | 
					 | 
				
			||||||
	n := 0
 | 
					 | 
				
			||||||
	for _, spec := range decl.Specs {
 | 
					 | 
				
			||||||
		s, ok := spec.(*ast.ValueSpec)
 | 
					 | 
				
			||||||
		if !ok {
 | 
					 | 
				
			||||||
			continue // should not happen, but be conservative
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		name := ""
 | 
					 | 
				
			||||||
		switch {
 | 
					 | 
				
			||||||
		case s.Type != nil:
 | 
					 | 
				
			||||||
			// a type is present; determine its name
 | 
					 | 
				
			||||||
			if n, imp := baseTypeName(s.Type); !imp {
 | 
					 | 
				
			||||||
				name = n
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		case decl.Tok == token.CONST:
 | 
					 | 
				
			||||||
			// no type is present but we have a constant declaration;
 | 
					 | 
				
			||||||
			// use the previous type name (w/o more type information
 | 
					 | 
				
			||||||
			// we cannot handle the case of unnamed variables with
 | 
					 | 
				
			||||||
			// initializer expressions except for some trivial cases)
 | 
					 | 
				
			||||||
			name = prev
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		if name != "" {
 | 
					 | 
				
			||||||
			// entry has a named type
 | 
					 | 
				
			||||||
			if domName != "" && domName != name {
 | 
					 | 
				
			||||||
				// more than one type name - do not associate
 | 
					 | 
				
			||||||
				// with any type
 | 
					 | 
				
			||||||
				domName = ""
 | 
					 | 
				
			||||||
				break
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
			domName = name
 | 
					 | 
				
			||||||
			domFreq++
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		prev = name
 | 
					 | 
				
			||||||
		n++
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// nothing to do w/o a legal declaration
 | 
					 | 
				
			||||||
	if n == 0 {
 | 
					 | 
				
			||||||
		return
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// determine values list with which to associate the Value for this decl
 | 
					 | 
				
			||||||
	values := &r.values
 | 
					 | 
				
			||||||
	const threshold = 0.75
 | 
					 | 
				
			||||||
	if domName != "" && r.isVisible(domName) && domFreq >= int(float64(len(decl.Specs))*threshold) {
 | 
					 | 
				
			||||||
		// typed entries are sufficiently frequent
 | 
					 | 
				
			||||||
		if typ := r.lookupType(domName); typ != nil {
 | 
					 | 
				
			||||||
			values = &typ.values // associate with that type
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	*values = append(*values, &Value{
 | 
					 | 
				
			||||||
		Doc:   decl.Doc.Text(),
 | 
					 | 
				
			||||||
		Names: specNames(decl.Specs),
 | 
					 | 
				
			||||||
		Decl:  decl,
 | 
					 | 
				
			||||||
		order: len(*values),
 | 
					 | 
				
			||||||
	})
 | 
					 | 
				
			||||||
	decl.Doc = nil // doc consumed - remove from AST
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// fields returns a struct's fields or an interface's methods.
 | 
					 | 
				
			||||||
//
 | 
					 | 
				
			||||||
func fields(typ ast.Expr) (list []*ast.Field, isStruct bool) {
 | 
					 | 
				
			||||||
	var fields *ast.FieldList
 | 
					 | 
				
			||||||
	switch t := typ.(type) {
 | 
					 | 
				
			||||||
	case *ast.StructType:
 | 
					 | 
				
			||||||
		fields = t.Fields
 | 
					 | 
				
			||||||
		isStruct = true
 | 
					 | 
				
			||||||
	case *ast.InterfaceType:
 | 
					 | 
				
			||||||
		fields = t.Methods
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	if fields != nil {
 | 
					 | 
				
			||||||
		list = fields.List
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// readType processes a type declaration.
 | 
					 | 
				
			||||||
//
 | 
					 | 
				
			||||||
func (r *reader) readType(decl *ast.GenDecl, spec *ast.TypeSpec) {
 | 
					 | 
				
			||||||
	typ := r.lookupType(spec.Name.Name)
 | 
					 | 
				
			||||||
	if typ == nil {
 | 
					 | 
				
			||||||
		return // no name or blank name - ignore the type
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// A type should be added at most once, so typ.decl
 | 
					 | 
				
			||||||
	// should be nil - if it is not, simply overwrite it.
 | 
					 | 
				
			||||||
	typ.decl = decl
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// compute documentation
 | 
					 | 
				
			||||||
	doc := spec.Doc
 | 
					 | 
				
			||||||
	spec.Doc = nil // doc consumed - remove from AST
 | 
					 | 
				
			||||||
	if doc == nil {
 | 
					 | 
				
			||||||
		// no doc associated with the spec, use the declaration doc, if any
 | 
					 | 
				
			||||||
		doc = decl.Doc
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	decl.Doc = nil // doc consumed - remove from AST
 | 
					 | 
				
			||||||
	typ.doc = doc.Text()
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// record anonymous fields (they may contribute methods)
 | 
					 | 
				
			||||||
	// (some fields may have been recorded already when filtering
 | 
					 | 
				
			||||||
	// exports, but that's ok)
 | 
					 | 
				
			||||||
	var list []*ast.Field
 | 
					 | 
				
			||||||
	list, typ.isStruct = fields(spec.Type)
 | 
					 | 
				
			||||||
	for _, field := range list {
 | 
					 | 
				
			||||||
		if len(field.Names) == 0 {
 | 
					 | 
				
			||||||
			r.recordAnonymousField(typ, field.Type)
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// readFunc processes a func or method declaration.
 | 
					 | 
				
			||||||
//
 | 
					 | 
				
			||||||
func (r *reader) readFunc(fun *ast.FuncDecl) {
 | 
					 | 
				
			||||||
	// strip function body
 | 
					 | 
				
			||||||
	fun.Body = nil
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// associate methods with the receiver type, if any
 | 
					 | 
				
			||||||
	if fun.Recv != nil {
 | 
					 | 
				
			||||||
		// method
 | 
					 | 
				
			||||||
		recvTypeName, imp := baseTypeName(fun.Recv.List[0].Type)
 | 
					 | 
				
			||||||
		if imp {
 | 
					 | 
				
			||||||
			// should not happen (incorrect AST);
 | 
					 | 
				
			||||||
			// don't show this method
 | 
					 | 
				
			||||||
			return
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		if typ := r.lookupType(recvTypeName); typ != nil {
 | 
					 | 
				
			||||||
			typ.methods.set(fun)
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		// otherwise ignore the method
 | 
					 | 
				
			||||||
		// TODO(gri): There may be exported methods of non-exported types
 | 
					 | 
				
			||||||
		// that can be called because of exported values (consts, vars, or
 | 
					 | 
				
			||||||
		// function results) of that type. Could determine if that is the
 | 
					 | 
				
			||||||
		// case and then show those methods in an appropriate section.
 | 
					 | 
				
			||||||
		return
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// associate factory functions with the first visible result type, if any
 | 
					 | 
				
			||||||
	if fun.Type.Results.NumFields() >= 1 {
 | 
					 | 
				
			||||||
		res := fun.Type.Results.List[0]
 | 
					 | 
				
			||||||
		if len(res.Names) <= 1 {
 | 
					 | 
				
			||||||
			// exactly one (named or anonymous) result associated
 | 
					 | 
				
			||||||
			// with the first type in result signature (there may
 | 
					 | 
				
			||||||
			// be more than one result)
 | 
					 | 
				
			||||||
			if n, imp := baseTypeName(res.Type); !imp && r.isVisible(n) {
 | 
					 | 
				
			||||||
				if typ := r.lookupType(n); typ != nil {
 | 
					 | 
				
			||||||
					// associate function with typ
 | 
					 | 
				
			||||||
					typ.funcs.set(fun)
 | 
					 | 
				
			||||||
					return
 | 
					 | 
				
			||||||
				}
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// just an ordinary function
 | 
					 | 
				
			||||||
	r.funcs.set(fun)
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
var (
 | 
					 | 
				
			||||||
	noteMarker    = `([A-Z][A-Z]+)\(([^)]+)\):?`                    // MARKER(uid), MARKER at least 2 chars, uid at least 1 char
 | 
					 | 
				
			||||||
	noteMarkerRx  = regexp.MustCompile(`^[ \t]*` + noteMarker)      // MARKER(uid) at text start
 | 
					 | 
				
			||||||
	noteCommentRx = regexp.MustCompile(`^/[/*][ \t]*` + noteMarker) // MARKER(uid) at comment start
 | 
					 | 
				
			||||||
)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// readNote collects a single note from a sequence of comments.
 | 
					 | 
				
			||||||
//
 | 
					 | 
				
			||||||
func (r *reader) readNote(list []*ast.Comment) {
 | 
					 | 
				
			||||||
	text := (&ast.CommentGroup{List: list}).Text()
 | 
					 | 
				
			||||||
	if m := noteMarkerRx.FindStringSubmatchIndex(text); m != nil {
 | 
					 | 
				
			||||||
		// The note body starts after the marker.
 | 
					 | 
				
			||||||
		// We remove any formatting so that we don't
 | 
					 | 
				
			||||||
		// get spurious line breaks/indentation when
 | 
					 | 
				
			||||||
		// showing the TODO body.
 | 
					 | 
				
			||||||
		body := clean(text[m[1]:], keepNL)
 | 
					 | 
				
			||||||
		if body != "" {
 | 
					 | 
				
			||||||
			marker := text[m[2]:m[3]]
 | 
					 | 
				
			||||||
			r.notes[marker] = append(r.notes[marker], &Note{
 | 
					 | 
				
			||||||
				Pos:  list[0].Pos(),
 | 
					 | 
				
			||||||
				End:  list[len(list)-1].End(),
 | 
					 | 
				
			||||||
				UID:  text[m[4]:m[5]],
 | 
					 | 
				
			||||||
				Body: body,
 | 
					 | 
				
			||||||
			})
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// readNotes extracts notes from comments.
 | 
					 | 
				
			||||||
// A note must start at the beginning of a comment with "MARKER(uid):"
 | 
					 | 
				
			||||||
// and is followed by the note body (e.g., "// BUG(gri): fix this").
 | 
					 | 
				
			||||||
// The note ends at the end of the comment group or at the start of
 | 
					 | 
				
			||||||
// another note in the same comment group, whichever comes first.
 | 
					 | 
				
			||||||
//
 | 
					 | 
				
			||||||
func (r *reader) readNotes(comments []*ast.CommentGroup) {
 | 
					 | 
				
			||||||
	for _, group := range comments {
 | 
					 | 
				
			||||||
		i := -1 // comment index of most recent note start, valid if >= 0
 | 
					 | 
				
			||||||
		list := group.List
 | 
					 | 
				
			||||||
		for j, c := range list {
 | 
					 | 
				
			||||||
			if noteCommentRx.MatchString(c.Text) {
 | 
					 | 
				
			||||||
				if i >= 0 {
 | 
					 | 
				
			||||||
					r.readNote(list[i:j])
 | 
					 | 
				
			||||||
				}
 | 
					 | 
				
			||||||
				i = j
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		if i >= 0 {
 | 
					 | 
				
			||||||
			r.readNote(list[i:])
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// readFile adds the AST for a source file to the reader.
 | 
					 | 
				
			||||||
//
 | 
					 | 
				
			||||||
func (r *reader) readFile(src *ast.File) {
 | 
					 | 
				
			||||||
	// add package documentation
 | 
					 | 
				
			||||||
	if src.Doc != nil {
 | 
					 | 
				
			||||||
		r.readDoc(src.Doc)
 | 
					 | 
				
			||||||
		src.Doc = nil // doc consumed - remove from AST
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// add all declarations
 | 
					 | 
				
			||||||
	for _, decl := range src.Decls {
 | 
					 | 
				
			||||||
		switch d := decl.(type) {
 | 
					 | 
				
			||||||
		case *ast.GenDecl:
 | 
					 | 
				
			||||||
			switch d.Tok {
 | 
					 | 
				
			||||||
			case token.IMPORT:
 | 
					 | 
				
			||||||
				// imports are handled individually
 | 
					 | 
				
			||||||
				for _, spec := range d.Specs {
 | 
					 | 
				
			||||||
					if s, ok := spec.(*ast.ImportSpec); ok {
 | 
					 | 
				
			||||||
						if import_, err := strconv.Unquote(s.Path.Value); err == nil {
 | 
					 | 
				
			||||||
							r.imports[import_] = 1
 | 
					 | 
				
			||||||
						}
 | 
					 | 
				
			||||||
					}
 | 
					 | 
				
			||||||
				}
 | 
					 | 
				
			||||||
			case token.CONST, token.VAR:
 | 
					 | 
				
			||||||
				// constants and variables are always handled as a group
 | 
					 | 
				
			||||||
				r.readValue(d)
 | 
					 | 
				
			||||||
			case token.TYPE:
 | 
					 | 
				
			||||||
				// types are handled individually
 | 
					 | 
				
			||||||
				if len(d.Specs) == 1 && !d.Lparen.IsValid() {
 | 
					 | 
				
			||||||
					// common case: single declaration w/o parentheses
 | 
					 | 
				
			||||||
					// (if a single declaration is parenthesized,
 | 
					 | 
				
			||||||
					// create a new fake declaration below, so that
 | 
					 | 
				
			||||||
					// go/doc type declarations always appear w/o
 | 
					 | 
				
			||||||
					// parentheses)
 | 
					 | 
				
			||||||
					if s, ok := d.Specs[0].(*ast.TypeSpec); ok {
 | 
					 | 
				
			||||||
						r.readType(d, s)
 | 
					 | 
				
			||||||
					}
 | 
					 | 
				
			||||||
					break
 | 
					 | 
				
			||||||
				}
 | 
					 | 
				
			||||||
				for _, spec := range d.Specs {
 | 
					 | 
				
			||||||
					if s, ok := spec.(*ast.TypeSpec); ok {
 | 
					 | 
				
			||||||
						// use an individual (possibly fake) declaration
 | 
					 | 
				
			||||||
						// for each type; this also ensures that each type
 | 
					 | 
				
			||||||
						// gets to (re-)use the declaration documentation
 | 
					 | 
				
			||||||
						// if there's none associated with the spec itself
 | 
					 | 
				
			||||||
						fake := &ast.GenDecl{
 | 
					 | 
				
			||||||
							Doc: d.Doc,
 | 
					 | 
				
			||||||
							// don't use the existing TokPos because it
 | 
					 | 
				
			||||||
							// will lead to the wrong selection range for
 | 
					 | 
				
			||||||
							// the fake declaration if there are more
 | 
					 | 
				
			||||||
							// than one type in the group (this affects
 | 
					 | 
				
			||||||
							// src/cmd/godoc/godoc.go's posLink_urlFunc)
 | 
					 | 
				
			||||||
							TokPos: s.Pos(),
 | 
					 | 
				
			||||||
							Tok:    token.TYPE,
 | 
					 | 
				
			||||||
							Specs:  []ast.Spec{s},
 | 
					 | 
				
			||||||
						}
 | 
					 | 
				
			||||||
						r.readType(fake, s)
 | 
					 | 
				
			||||||
					}
 | 
					 | 
				
			||||||
				}
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		case *ast.FuncDecl:
 | 
					 | 
				
			||||||
			r.readFunc(d)
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// collect MARKER(...): annotations
 | 
					 | 
				
			||||||
	r.readNotes(src.Comments)
 | 
					 | 
				
			||||||
	src.Comments = nil // consumed unassociated comments - remove from AST
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (r *reader) readPackage(pkg *ast.Package, mode Mode) {
 | 
					 | 
				
			||||||
	// initialize reader
 | 
					 | 
				
			||||||
	r.filenames = make([]string, len(pkg.Files))
 | 
					 | 
				
			||||||
	r.imports = make(map[string]int)
 | 
					 | 
				
			||||||
	r.mode = mode
 | 
					 | 
				
			||||||
	r.types = make(map[string]*namedType)
 | 
					 | 
				
			||||||
	r.funcs = make(methodSet)
 | 
					 | 
				
			||||||
	r.notes = make(map[string][]*Note)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// sort package files before reading them so that the
 | 
					 | 
				
			||||||
	// result does not depend on map iteration order
 | 
					 | 
				
			||||||
	i := 0
 | 
					 | 
				
			||||||
	for filename := range pkg.Files {
 | 
					 | 
				
			||||||
		r.filenames[i] = filename
 | 
					 | 
				
			||||||
		i++
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	sort.Strings(r.filenames)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// process files in sorted order
 | 
					 | 
				
			||||||
	for _, filename := range r.filenames {
 | 
					 | 
				
			||||||
		f := pkg.Files[filename]
 | 
					 | 
				
			||||||
		if mode&AllDecls == 0 {
 | 
					 | 
				
			||||||
			r.fileExports(f)
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		r.readFile(f)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// ----------------------------------------------------------------------------
 | 
					 | 
				
			||||||
// Types
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func customizeRecv(f *Func, recvTypeName string, embeddedIsPtr bool, level int) *Func {
 | 
					 | 
				
			||||||
	if f == nil || f.Decl == nil || f.Decl.Recv == nil || len(f.Decl.Recv.List) != 1 {
 | 
					 | 
				
			||||||
		return f // shouldn't happen, but be safe
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// copy existing receiver field and set new type
 | 
					 | 
				
			||||||
	newField := *f.Decl.Recv.List[0]
 | 
					 | 
				
			||||||
	origPos := newField.Type.Pos()
 | 
					 | 
				
			||||||
	_, origRecvIsPtr := newField.Type.(*ast.StarExpr)
 | 
					 | 
				
			||||||
	newIdent := &ast.Ident{NamePos: origPos, Name: recvTypeName}
 | 
					 | 
				
			||||||
	var typ ast.Expr = newIdent
 | 
					 | 
				
			||||||
	if !embeddedIsPtr && origRecvIsPtr {
 | 
					 | 
				
			||||||
		newIdent.NamePos++ // '*' is one character
 | 
					 | 
				
			||||||
		typ = &ast.StarExpr{Star: origPos, X: newIdent}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	newField.Type = typ
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// copy existing receiver field list and set new receiver field
 | 
					 | 
				
			||||||
	newFieldList := *f.Decl.Recv
 | 
					 | 
				
			||||||
	newFieldList.List = []*ast.Field{&newField}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// copy existing function declaration and set new receiver field list
 | 
					 | 
				
			||||||
	newFuncDecl := *f.Decl
 | 
					 | 
				
			||||||
	newFuncDecl.Recv = &newFieldList
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// copy existing function documentation and set new declaration
 | 
					 | 
				
			||||||
	newF := *f
 | 
					 | 
				
			||||||
	newF.Decl = &newFuncDecl
 | 
					 | 
				
			||||||
	newF.Recv = recvString(typ)
 | 
					 | 
				
			||||||
	// the Orig field never changes
 | 
					 | 
				
			||||||
	newF.Level = level
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return &newF
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// collectEmbeddedMethods collects the embedded methods of typ in mset.
 | 
					 | 
				
			||||||
//
 | 
					 | 
				
			||||||
func (r *reader) collectEmbeddedMethods(mset methodSet, typ *namedType, recvTypeName string, embeddedIsPtr bool, level int, visited embeddedSet) {
 | 
					 | 
				
			||||||
	visited[typ] = true
 | 
					 | 
				
			||||||
	for embedded, isPtr := range typ.embedded {
 | 
					 | 
				
			||||||
		// Once an embedded type is embedded as a pointer type
 | 
					 | 
				
			||||||
		// all embedded types in those types are treated like
 | 
					 | 
				
			||||||
		// pointer types for the purpose of the receiver type
 | 
					 | 
				
			||||||
		// computation; i.e., embeddedIsPtr is sticky for this
 | 
					 | 
				
			||||||
		// embedding hierarchy.
 | 
					 | 
				
			||||||
		thisEmbeddedIsPtr := embeddedIsPtr || isPtr
 | 
					 | 
				
			||||||
		for _, m := range embedded.methods {
 | 
					 | 
				
			||||||
			// only top-level methods are embedded
 | 
					 | 
				
			||||||
			if m.Level == 0 {
 | 
					 | 
				
			||||||
				mset.add(customizeRecv(m, recvTypeName, thisEmbeddedIsPtr, level))
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		if !visited[embedded] {
 | 
					 | 
				
			||||||
			r.collectEmbeddedMethods(mset, embedded, recvTypeName, thisEmbeddedIsPtr, level+1, visited)
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	delete(visited, typ)
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// computeMethodSets determines the actual method sets for each type encountered.
 | 
					 | 
				
			||||||
//
 | 
					 | 
				
			||||||
func (r *reader) computeMethodSets() {
 | 
					 | 
				
			||||||
	for _, t := range r.types {
 | 
					 | 
				
			||||||
		// collect embedded methods for t
 | 
					 | 
				
			||||||
		if t.isStruct {
 | 
					 | 
				
			||||||
			// struct
 | 
					 | 
				
			||||||
			r.collectEmbeddedMethods(t.methods, t, t.name, false, 1, make(embeddedSet))
 | 
					 | 
				
			||||||
		} else {
 | 
					 | 
				
			||||||
			// interface
 | 
					 | 
				
			||||||
			// TODO(gri) fix this
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// if error was declared locally, don't treat it as exported field anymore
 | 
					 | 
				
			||||||
	if r.errorDecl {
 | 
					 | 
				
			||||||
		for _, ityp := range r.fixlist {
 | 
					 | 
				
			||||||
			removeErrorField(ityp)
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// cleanupTypes removes the association of functions and methods with
 | 
					 | 
				
			||||||
// types that have no declaration. Instead, these functions and methods
 | 
					 | 
				
			||||||
// are shown at the package level. It also removes types with missing
 | 
					 | 
				
			||||||
// declarations or which are not visible.
 | 
					 | 
				
			||||||
//
 | 
					 | 
				
			||||||
func (r *reader) cleanupTypes() {
 | 
					 | 
				
			||||||
	for _, t := range r.types {
 | 
					 | 
				
			||||||
		visible := r.isVisible(t.name)
 | 
					 | 
				
			||||||
		if t.decl == nil && (predeclaredTypes[t.name] || t.isEmbedded && visible) {
 | 
					 | 
				
			||||||
			// t.name is a predeclared type (and was not redeclared in this package),
 | 
					 | 
				
			||||||
			// or it was embedded somewhere but its declaration is missing (because
 | 
					 | 
				
			||||||
			// the AST is incomplete): move any associated values, funcs, and methods
 | 
					 | 
				
			||||||
			// back to the top-level so that they are not lost.
 | 
					 | 
				
			||||||
			// 1) move values
 | 
					 | 
				
			||||||
			r.values = append(r.values, t.values...)
 | 
					 | 
				
			||||||
			// 2) move factory functions
 | 
					 | 
				
			||||||
			for name, f := range t.funcs {
 | 
					 | 
				
			||||||
				// in a correct AST, package-level function names
 | 
					 | 
				
			||||||
				// are all different - no need to check for conflicts
 | 
					 | 
				
			||||||
				r.funcs[name] = f
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
			// 3) move methods
 | 
					 | 
				
			||||||
			for name, m := range t.methods {
 | 
					 | 
				
			||||||
				// don't overwrite functions with the same name - drop them
 | 
					 | 
				
			||||||
				if _, found := r.funcs[name]; !found {
 | 
					 | 
				
			||||||
					r.funcs[name] = m
 | 
					 | 
				
			||||||
				}
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		// remove types w/o declaration or which are not visible
 | 
					 | 
				
			||||||
		if t.decl == nil || !visible {
 | 
					 | 
				
			||||||
			delete(r.types, t.name)
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// ----------------------------------------------------------------------------
 | 
					 | 
				
			||||||
// Sorting
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
type data struct {
 | 
					 | 
				
			||||||
	n    int
 | 
					 | 
				
			||||||
	swap func(i, j int)
 | 
					 | 
				
			||||||
	less func(i, j int) bool
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (d *data) Len() int           { return d.n }
 | 
					 | 
				
			||||||
func (d *data) Swap(i, j int)      { d.swap(i, j) }
 | 
					 | 
				
			||||||
func (d *data) Less(i, j int) bool { return d.less(i, j) }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// sortBy is a helper function for sorting
 | 
					 | 
				
			||||||
func sortBy(less func(i, j int) bool, swap func(i, j int), n int) {
 | 
					 | 
				
			||||||
	sort.Sort(&data{n, swap, less})
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func sortedKeys(m map[string]int) []string {
 | 
					 | 
				
			||||||
	list := make([]string, len(m))
 | 
					 | 
				
			||||||
	i := 0
 | 
					 | 
				
			||||||
	for key := range m {
 | 
					 | 
				
			||||||
		list[i] = key
 | 
					 | 
				
			||||||
		i++
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	sort.Strings(list)
 | 
					 | 
				
			||||||
	return list
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// sortingName returns the name to use when sorting d into place.
 | 
					 | 
				
			||||||
//
 | 
					 | 
				
			||||||
func sortingName(d *ast.GenDecl) string {
 | 
					 | 
				
			||||||
	if len(d.Specs) == 1 {
 | 
					 | 
				
			||||||
		if s, ok := d.Specs[0].(*ast.ValueSpec); ok {
 | 
					 | 
				
			||||||
			return s.Names[0].Name
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return ""
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func sortedValues(m []*Value, tok token.Token) []*Value {
 | 
					 | 
				
			||||||
	list := make([]*Value, len(m)) // big enough in any case
 | 
					 | 
				
			||||||
	i := 0
 | 
					 | 
				
			||||||
	for _, val := range m {
 | 
					 | 
				
			||||||
		if val.Decl.Tok == tok {
 | 
					 | 
				
			||||||
			list[i] = val
 | 
					 | 
				
			||||||
			i++
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	list = list[0:i]
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	sortBy(
 | 
					 | 
				
			||||||
		func(i, j int) bool {
 | 
					 | 
				
			||||||
			if ni, nj := sortingName(list[i].Decl), sortingName(list[j].Decl); ni != nj {
 | 
					 | 
				
			||||||
				return ni < nj
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
			return list[i].order < list[j].order
 | 
					 | 
				
			||||||
		},
 | 
					 | 
				
			||||||
		func(i, j int) { list[i], list[j] = list[j], list[i] },
 | 
					 | 
				
			||||||
		len(list),
 | 
					 | 
				
			||||||
	)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return list
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func sortedTypes(m map[string]*namedType, allMethods bool) []*Type {
 | 
					 | 
				
			||||||
	list := make([]*Type, len(m))
 | 
					 | 
				
			||||||
	i := 0
 | 
					 | 
				
			||||||
	for _, t := range m {
 | 
					 | 
				
			||||||
		list[i] = &Type{
 | 
					 | 
				
			||||||
			Doc:     t.doc,
 | 
					 | 
				
			||||||
			Name:    t.name,
 | 
					 | 
				
			||||||
			Decl:    t.decl,
 | 
					 | 
				
			||||||
			Consts:  sortedValues(t.values, token.CONST),
 | 
					 | 
				
			||||||
			Vars:    sortedValues(t.values, token.VAR),
 | 
					 | 
				
			||||||
			Funcs:   sortedFuncs(t.funcs, true),
 | 
					 | 
				
			||||||
			Methods: sortedFuncs(t.methods, allMethods),
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		i++
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	sortBy(
 | 
					 | 
				
			||||||
		func(i, j int) bool { return list[i].Name < list[j].Name },
 | 
					 | 
				
			||||||
		func(i, j int) { list[i], list[j] = list[j], list[i] },
 | 
					 | 
				
			||||||
		len(list),
 | 
					 | 
				
			||||||
	)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return list
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func removeStar(s string) string {
 | 
					 | 
				
			||||||
	if len(s) > 0 && s[0] == '*' {
 | 
					 | 
				
			||||||
		return s[1:]
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return s
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func sortedFuncs(m methodSet, allMethods bool) []*Func {
 | 
					 | 
				
			||||||
	list := make([]*Func, len(m))
 | 
					 | 
				
			||||||
	i := 0
 | 
					 | 
				
			||||||
	for _, m := range m {
 | 
					 | 
				
			||||||
		// determine which methods to include
 | 
					 | 
				
			||||||
		switch {
 | 
					 | 
				
			||||||
		case m.Decl == nil:
 | 
					 | 
				
			||||||
			// exclude conflict entry
 | 
					 | 
				
			||||||
		case allMethods, m.Level == 0, !ast.IsExported(removeStar(m.Orig)):
 | 
					 | 
				
			||||||
			// forced inclusion, method not embedded, or method
 | 
					 | 
				
			||||||
			// embedded but original receiver type not exported
 | 
					 | 
				
			||||||
			list[i] = m
 | 
					 | 
				
			||||||
			i++
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	list = list[0:i]
 | 
					 | 
				
			||||||
	sortBy(
 | 
					 | 
				
			||||||
		func(i, j int) bool { return list[i].Name < list[j].Name },
 | 
					 | 
				
			||||||
		func(i, j int) { list[i], list[j] = list[j], list[i] },
 | 
					 | 
				
			||||||
		len(list),
 | 
					 | 
				
			||||||
	)
 | 
					 | 
				
			||||||
	return list
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// noteBodies returns a list of note body strings given a list of notes.
 | 
					 | 
				
			||||||
// This is only used to populate the deprecated Package.Bugs field.
 | 
					 | 
				
			||||||
//
 | 
					 | 
				
			||||||
func noteBodies(notes []*Note) []string {
 | 
					 | 
				
			||||||
	var list []string
 | 
					 | 
				
			||||||
	for _, n := range notes {
 | 
					 | 
				
			||||||
		list = append(list, n.Body)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return list
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// ----------------------------------------------------------------------------
 | 
					 | 
				
			||||||
// Predeclared identifiers
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
var predeclaredTypes = map[string]bool{
 | 
					 | 
				
			||||||
	"bool":       true,
 | 
					 | 
				
			||||||
	"byte":       true,
 | 
					 | 
				
			||||||
	"complex64":  true,
 | 
					 | 
				
			||||||
	"complex128": true,
 | 
					 | 
				
			||||||
	"error":      true,
 | 
					 | 
				
			||||||
	"float32":    true,
 | 
					 | 
				
			||||||
	"float64":    true,
 | 
					 | 
				
			||||||
	"int":        true,
 | 
					 | 
				
			||||||
	"int8":       true,
 | 
					 | 
				
			||||||
	"int16":      true,
 | 
					 | 
				
			||||||
	"int32":      true,
 | 
					 | 
				
			||||||
	"int64":      true,
 | 
					 | 
				
			||||||
	"rune":       true,
 | 
					 | 
				
			||||||
	"string":     true,
 | 
					 | 
				
			||||||
	"uint":       true,
 | 
					 | 
				
			||||||
	"uint8":      true,
 | 
					 | 
				
			||||||
	"uint16":     true,
 | 
					 | 
				
			||||||
	"uint32":     true,
 | 
					 | 
				
			||||||
	"uint64":     true,
 | 
					 | 
				
			||||||
	"uintptr":    true,
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
var predeclaredFuncs = map[string]bool{
 | 
					 | 
				
			||||||
	"append":  true,
 | 
					 | 
				
			||||||
	"cap":     true,
 | 
					 | 
				
			||||||
	"close":   true,
 | 
					 | 
				
			||||||
	"complex": true,
 | 
					 | 
				
			||||||
	"copy":    true,
 | 
					 | 
				
			||||||
	"delete":  true,
 | 
					 | 
				
			||||||
	"imag":    true,
 | 
					 | 
				
			||||||
	"len":     true,
 | 
					 | 
				
			||||||
	"make":    true,
 | 
					 | 
				
			||||||
	"new":     true,
 | 
					 | 
				
			||||||
	"panic":   true,
 | 
					 | 
				
			||||||
	"print":   true,
 | 
					 | 
				
			||||||
	"println": true,
 | 
					 | 
				
			||||||
	"real":    true,
 | 
					 | 
				
			||||||
	"recover": true,
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
var predeclaredConstants = map[string]bool{
 | 
					 | 
				
			||||||
	"false": true,
 | 
					 | 
				
			||||||
	"iota":  true,
 | 
					 | 
				
			||||||
	"nil":   true,
 | 
					 | 
				
			||||||
	"true":  true,
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
							
								
								
									
										82
									
								
								third_party/golang/go/doc/synopsis.go
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										82
									
								
								third_party/golang/go/doc/synopsis.go
									
									
									
									
										vendored
									
									
								
							@@ -1,82 +0,0 @@
 | 
				
			|||||||
// Copyright 2012 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 doc
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
import (
 | 
					 | 
				
			||||||
	"strings"
 | 
					 | 
				
			||||||
	"unicode"
 | 
					 | 
				
			||||||
)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// firstSentenceLen returns the length of the first sentence in s.
 | 
					 | 
				
			||||||
// The sentence ends after the first period followed by space and
 | 
					 | 
				
			||||||
// not preceded by exactly one uppercase letter.
 | 
					 | 
				
			||||||
//
 | 
					 | 
				
			||||||
func firstSentenceLen(s string) int {
 | 
					 | 
				
			||||||
	var ppp, pp, p rune
 | 
					 | 
				
			||||||
	for i, q := range s {
 | 
					 | 
				
			||||||
		if q == '\n' || q == '\r' || q == '\t' {
 | 
					 | 
				
			||||||
			q = ' '
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		if q == ' ' && p == '.' && (!unicode.IsUpper(pp) || unicode.IsUpper(ppp)) {
 | 
					 | 
				
			||||||
			return i
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		if p == '。' || p == '.' {
 | 
					 | 
				
			||||||
			return i
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		ppp, pp, p = pp, p, q
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return len(s)
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
const (
 | 
					 | 
				
			||||||
	keepNL = 1 << iota
 | 
					 | 
				
			||||||
)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// clean replaces each sequence of space, \n, \r, or \t characters
 | 
					 | 
				
			||||||
// with a single space and removes any trailing and leading spaces.
 | 
					 | 
				
			||||||
// If the keepNL flag is set, newline characters are passed through
 | 
					 | 
				
			||||||
// instead of being change to spaces.
 | 
					 | 
				
			||||||
func clean(s string, flags int) string {
 | 
					 | 
				
			||||||
	var b []byte
 | 
					 | 
				
			||||||
	p := byte(' ')
 | 
					 | 
				
			||||||
	for i := 0; i < len(s); i++ {
 | 
					 | 
				
			||||||
		q := s[i]
 | 
					 | 
				
			||||||
		if (flags&keepNL) == 0 && q == '\n' || q == '\r' || q == '\t' {
 | 
					 | 
				
			||||||
			q = ' '
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		if q != ' ' || p != ' ' {
 | 
					 | 
				
			||||||
			b = append(b, q)
 | 
					 | 
				
			||||||
			p = q
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	// remove trailing blank, if any
 | 
					 | 
				
			||||||
	if n := len(b); n > 0 && p == ' ' {
 | 
					 | 
				
			||||||
		b = b[0 : n-1]
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return string(b)
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// Synopsis returns a cleaned version of the first sentence in s.
 | 
					 | 
				
			||||||
// That sentence ends after the first period followed by space and
 | 
					 | 
				
			||||||
// not preceded by exactly one uppercase letter. The result string
 | 
					 | 
				
			||||||
// has no \n, \r, or \t characters and uses only single spaces between
 | 
					 | 
				
			||||||
// words. If s starts with any of the IllegalPrefixes, the result
 | 
					 | 
				
			||||||
// is the empty string.
 | 
					 | 
				
			||||||
//
 | 
					 | 
				
			||||||
func Synopsis(s string) string {
 | 
					 | 
				
			||||||
	s = clean(s[0:firstSentenceLen(s)], 0)
 | 
					 | 
				
			||||||
	for _, prefix := range IllegalPrefixes {
 | 
					 | 
				
			||||||
		if strings.HasPrefix(strings.ToLower(s), prefix) {
 | 
					 | 
				
			||||||
			return ""
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return s
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
var IllegalPrefixes = []string{
 | 
					 | 
				
			||||||
	"copyright",
 | 
					 | 
				
			||||||
	"all rights",
 | 
					 | 
				
			||||||
	"author",
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
							
								
								
									
										51
									
								
								third_party/golang/go/doc/synopsis_test.go
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										51
									
								
								third_party/golang/go/doc/synopsis_test.go
									
									
									
									
										vendored
									
									
								
							@@ -1,51 +0,0 @@
 | 
				
			|||||||
// Copyright 2012 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 doc
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
import "testing"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
var tests = []struct {
 | 
					 | 
				
			||||||
	txt string
 | 
					 | 
				
			||||||
	fsl int
 | 
					 | 
				
			||||||
	syn string
 | 
					 | 
				
			||||||
}{
 | 
					 | 
				
			||||||
	{"", 0, ""},
 | 
					 | 
				
			||||||
	{"foo", 3, "foo"},
 | 
					 | 
				
			||||||
	{"foo.", 4, "foo."},
 | 
					 | 
				
			||||||
	{"foo.bar", 7, "foo.bar"},
 | 
					 | 
				
			||||||
	{"  foo.  ", 6, "foo."},
 | 
					 | 
				
			||||||
	{"  foo\t  bar.\n", 12, "foo bar."},
 | 
					 | 
				
			||||||
	{"  foo\t  bar.\n", 12, "foo bar."},
 | 
					 | 
				
			||||||
	{"a  b\n\nc\r\rd\t\t", 12, "a b c d"},
 | 
					 | 
				
			||||||
	{"a  b\n\nc\r\rd\t\t  . BLA", 15, "a b c d ."},
 | 
					 | 
				
			||||||
	{"Package poems by T.S.Eliot. To rhyme...", 27, "Package poems by T.S.Eliot."},
 | 
					 | 
				
			||||||
	{"Package poems by T. S. Eliot. To rhyme...", 29, "Package poems by T. S. Eliot."},
 | 
					 | 
				
			||||||
	{"foo implements the foo ABI. The foo ABI is...", 27, "foo implements the foo ABI."},
 | 
					 | 
				
			||||||
	{"Package\nfoo. ..", 12, "Package foo."},
 | 
					 | 
				
			||||||
	{"P . Q.", 3, "P ."},
 | 
					 | 
				
			||||||
	{"P. Q.   ", 8, "P. Q."},
 | 
					 | 
				
			||||||
	{"Package Καλημέρα κόσμε.", 36, "Package Καλημέρα κόσμε."},
 | 
					 | 
				
			||||||
	{"Package こんにちは 世界\n", 31, "Package こんにちは 世界"},
 | 
					 | 
				
			||||||
	{"Package こんにちは。世界", 26, "Package こんにちは。"},
 | 
					 | 
				
			||||||
	{"Package 안녕.世界", 17, "Package 안녕."},
 | 
					 | 
				
			||||||
	{"Package foo does bar.", 21, "Package foo does bar."},
 | 
					 | 
				
			||||||
	{"Copyright 2012 Google, Inc. Package foo does bar.", 27, ""},
 | 
					 | 
				
			||||||
	{"All Rights reserved. Package foo does bar.", 20, ""},
 | 
					 | 
				
			||||||
	{"All rights reserved. Package foo does bar.", 20, ""},
 | 
					 | 
				
			||||||
	{"Authors: foo@bar.com. Package foo does bar.", 21, ""},
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func TestSynopsis(t *testing.T) {
 | 
					 | 
				
			||||||
	for _, e := range tests {
 | 
					 | 
				
			||||||
		fsl := firstSentenceLen(e.txt)
 | 
					 | 
				
			||||||
		if fsl != e.fsl {
 | 
					 | 
				
			||||||
			t.Errorf("got fsl = %d; want %d for %q\n", fsl, e.fsl, e.txt)
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		syn := Synopsis(e.txt)
 | 
					 | 
				
			||||||
		if syn != e.syn {
 | 
					 | 
				
			||||||
			t.Errorf("got syn = %q; want %q for %q\n", syn, e.syn, e.txt)
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
							
								
								
									
										52
									
								
								third_party/golang/go/doc/testdata/a.0.golden
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										52
									
								
								third_party/golang/go/doc/testdata/a.0.golden
									
									
									
									
										vendored
									
									
								
							@@ -1,52 +0,0 @@
 | 
				
			|||||||
// comment 0  comment 1 
 | 
					 | 
				
			||||||
PACKAGE a
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
IMPORTPATH
 | 
					 | 
				
			||||||
	testdata/a
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
FILENAMES
 | 
					 | 
				
			||||||
	testdata/a0.go
 | 
					 | 
				
			||||||
	testdata/a1.go
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
BUGS .Bugs is now deprecated, please use .Notes instead
 | 
					 | 
				
			||||||
	bug0
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	bug1
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
BUGS
 | 
					 | 
				
			||||||
BUG(uid)	bug0
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
BUG(uid)	bug1
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
NOTES
 | 
					 | 
				
			||||||
NOTE(uid)	
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
NOTE(foo)	1 of 4 - this is the first line of note 1
 | 
					 | 
				
			||||||
	- note 1 continues on this 2nd line
 | 
					 | 
				
			||||||
	- note 1 continues on this 3rd line
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
NOTE(foo)	2 of 4
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
NOTE(bar)	3 of 4
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
NOTE(bar)	4 of 4
 | 
					 | 
				
			||||||
	- this is the last line of note 4
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
NOTE(bam)	This note which contains a (parenthesized) subphrase
 | 
					 | 
				
			||||||
	 must appear in its entirety.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
NOTE(xxx)	The ':' after the marker and uid is optional.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
SECBUGS
 | 
					 | 
				
			||||||
SECBUG(uid)	sec hole 0
 | 
					 | 
				
			||||||
	need to fix asap
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
TODOS
 | 
					 | 
				
			||||||
TODO(uid)	todo0
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
TODO(uid)	todo1
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
							
								
								
									
										52
									
								
								third_party/golang/go/doc/testdata/a.1.golden
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										52
									
								
								third_party/golang/go/doc/testdata/a.1.golden
									
									
									
									
										vendored
									
									
								
							@@ -1,52 +0,0 @@
 | 
				
			|||||||
// comment 0  comment 1 
 | 
					 | 
				
			||||||
PACKAGE a
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
IMPORTPATH
 | 
					 | 
				
			||||||
	testdata/a
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
FILENAMES
 | 
					 | 
				
			||||||
	testdata/a0.go
 | 
					 | 
				
			||||||
	testdata/a1.go
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
BUGS .Bugs is now deprecated, please use .Notes instead
 | 
					 | 
				
			||||||
	bug0
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	bug1
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
BUGS
 | 
					 | 
				
			||||||
BUG(uid)	bug0
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
BUG(uid)	bug1
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
NOTES
 | 
					 | 
				
			||||||
NOTE(uid)	
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
NOTE(foo)	1 of 4 - this is the first line of note 1
 | 
					 | 
				
			||||||
	- note 1 continues on this 2nd line
 | 
					 | 
				
			||||||
	- note 1 continues on this 3rd line
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
NOTE(foo)	2 of 4
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
NOTE(bar)	3 of 4
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
NOTE(bar)	4 of 4
 | 
					 | 
				
			||||||
	- this is the last line of note 4
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
NOTE(bam)	This note which contains a (parenthesized) subphrase
 | 
					 | 
				
			||||||
	 must appear in its entirety.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
NOTE(xxx)	The ':' after the marker and uid is optional.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
SECBUGS
 | 
					 | 
				
			||||||
SECBUG(uid)	sec hole 0
 | 
					 | 
				
			||||||
	need to fix asap
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
TODOS
 | 
					 | 
				
			||||||
TODO(uid)	todo0
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
TODO(uid)	todo1
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
							
								
								
									
										52
									
								
								third_party/golang/go/doc/testdata/a.2.golden
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										52
									
								
								third_party/golang/go/doc/testdata/a.2.golden
									
									
									
									
										vendored
									
									
								
							@@ -1,52 +0,0 @@
 | 
				
			|||||||
// comment 0  comment 1 
 | 
					 | 
				
			||||||
PACKAGE a
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
IMPORTPATH
 | 
					 | 
				
			||||||
	testdata/a
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
FILENAMES
 | 
					 | 
				
			||||||
	testdata/a0.go
 | 
					 | 
				
			||||||
	testdata/a1.go
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
BUGS .Bugs is now deprecated, please use .Notes instead
 | 
					 | 
				
			||||||
	bug0
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	bug1
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
BUGS
 | 
					 | 
				
			||||||
BUG(uid)	bug0
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
BUG(uid)	bug1
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
NOTES
 | 
					 | 
				
			||||||
NOTE(uid)	
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
NOTE(foo)	1 of 4 - this is the first line of note 1
 | 
					 | 
				
			||||||
	- note 1 continues on this 2nd line
 | 
					 | 
				
			||||||
	- note 1 continues on this 3rd line
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
NOTE(foo)	2 of 4
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
NOTE(bar)	3 of 4
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
NOTE(bar)	4 of 4
 | 
					 | 
				
			||||||
	- this is the last line of note 4
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
NOTE(bam)	This note which contains a (parenthesized) subphrase
 | 
					 | 
				
			||||||
	 must appear in its entirety.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
NOTE(xxx)	The ':' after the marker and uid is optional.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
SECBUGS
 | 
					 | 
				
			||||||
SECBUG(uid)	sec hole 0
 | 
					 | 
				
			||||||
	need to fix asap
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
TODOS
 | 
					 | 
				
			||||||
TODO(uid)	todo0
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
TODO(uid)	todo1
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
							
								
								
									
										40
									
								
								third_party/golang/go/doc/testdata/a0.go
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										40
									
								
								third_party/golang/go/doc/testdata/a0.go
									
									
									
									
										vendored
									
									
								
							@@ -1,40 +0,0 @@
 | 
				
			|||||||
// Copyright 2012 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.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// comment 0
 | 
					 | 
				
			||||||
package a
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
//BUG(uid): bug0
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
//TODO(uid): todo0
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// A note with some spaces after it, should be ignored (watch out for
 | 
					 | 
				
			||||||
// emacs modes that remove trailing whitespace).
 | 
					 | 
				
			||||||
//NOTE(uid):
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// SECBUG(uid): sec hole 0
 | 
					 | 
				
			||||||
// need to fix asap
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// Multiple notes may be in the same comment group and should be
 | 
					 | 
				
			||||||
// recognized individually. Notes may start in the middle of a
 | 
					 | 
				
			||||||
// comment group as long as they start at the beginning of an
 | 
					 | 
				
			||||||
// individual comment.
 | 
					 | 
				
			||||||
//
 | 
					 | 
				
			||||||
// NOTE(foo): 1 of 4 - this is the first line of note 1
 | 
					 | 
				
			||||||
// - note 1 continues on this 2nd line
 | 
					 | 
				
			||||||
// - note 1 continues on this 3rd line
 | 
					 | 
				
			||||||
// NOTE(foo): 2 of 4
 | 
					 | 
				
			||||||
// NOTE(bar): 3 of 4
 | 
					 | 
				
			||||||
/* NOTE(bar): 4 of 4 */
 | 
					 | 
				
			||||||
// - this is the last line of note 4
 | 
					 | 
				
			||||||
//
 | 
					 | 
				
			||||||
//
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// NOTE(bam): This note which contains a (parenthesized) subphrase
 | 
					 | 
				
			||||||
//            must appear in its entirety.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// NOTE(xxx) The ':' after the marker and uid is optional.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// NOTE(): NO uid - should not show up.
 | 
					 | 
				
			||||||
// NOTE()  NO uid - should not show up.
 | 
					 | 
				
			||||||
							
								
								
									
										12
									
								
								third_party/golang/go/doc/testdata/a1.go
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										12
									
								
								third_party/golang/go/doc/testdata/a1.go
									
									
									
									
										vendored
									
									
								
							@@ -1,12 +0,0 @@
 | 
				
			|||||||
// Copyright 2012 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.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// comment 1
 | 
					 | 
				
			||||||
package a
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
//BUG(uid): bug1
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
//TODO(uid): todo1
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
//TODO(): ignored
 | 
					 | 
				
			||||||
							
								
								
									
										71
									
								
								third_party/golang/go/doc/testdata/b.0.golden
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										71
									
								
								third_party/golang/go/doc/testdata/b.0.golden
									
									
									
									
										vendored
									
									
								
							@@ -1,71 +0,0 @@
 | 
				
			|||||||
// 
 | 
					 | 
				
			||||||
PACKAGE b
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
IMPORTPATH
 | 
					 | 
				
			||||||
	testdata/b
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
IMPORTS
 | 
					 | 
				
			||||||
	a
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
FILENAMES
 | 
					 | 
				
			||||||
	testdata/b.go
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
CONSTANTS
 | 
					 | 
				
			||||||
	// 
 | 
					 | 
				
			||||||
	const (
 | 
					 | 
				
			||||||
		C1	notExported	= iota
 | 
					 | 
				
			||||||
		C2
 | 
					 | 
				
			||||||
	
 | 
					 | 
				
			||||||
		C4
 | 
					 | 
				
			||||||
		C5
 | 
					 | 
				
			||||||
	)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// 
 | 
					 | 
				
			||||||
	const C notExported = 0
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// 
 | 
					 | 
				
			||||||
	const Pi = 3.14	// Pi
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
VARIABLES
 | 
					 | 
				
			||||||
	// 
 | 
					 | 
				
			||||||
	var (
 | 
					 | 
				
			||||||
		U1, U2, U4, U5	notExported
 | 
					 | 
				
			||||||
	
 | 
					 | 
				
			||||||
		U7	notExported	= 7
 | 
					 | 
				
			||||||
	)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// 
 | 
					 | 
				
			||||||
	var MaxInt int	// MaxInt
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// 
 | 
					 | 
				
			||||||
	var V notExported
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// 
 | 
					 | 
				
			||||||
	var V1, V2, V4, V5 notExported
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
FUNCTIONS
 | 
					 | 
				
			||||||
	// 
 | 
					 | 
				
			||||||
	func F(x int) int
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// 
 | 
					 | 
				
			||||||
	func F1() notExported
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// Always under the package functions list. 
 | 
					 | 
				
			||||||
	func NotAFactory() int
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// Associated with uint type if AllDecls is set. 
 | 
					 | 
				
			||||||
	func UintFactory() uint
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
TYPES
 | 
					 | 
				
			||||||
	// 
 | 
					 | 
				
			||||||
	type T struct{}	// T
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// 
 | 
					 | 
				
			||||||
	var V T	// v
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// 
 | 
					 | 
				
			||||||
	func (x *T) M()
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
							
								
								
									
										83
									
								
								third_party/golang/go/doc/testdata/b.1.golden
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										83
									
								
								third_party/golang/go/doc/testdata/b.1.golden
									
									
									
									
										vendored
									
									
								
							@@ -1,83 +0,0 @@
 | 
				
			|||||||
// 
 | 
					 | 
				
			||||||
PACKAGE b
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
IMPORTPATH
 | 
					 | 
				
			||||||
	testdata/b
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
IMPORTS
 | 
					 | 
				
			||||||
	a
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
FILENAMES
 | 
					 | 
				
			||||||
	testdata/b.go
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
CONSTANTS
 | 
					 | 
				
			||||||
	// 
 | 
					 | 
				
			||||||
	const Pi = 3.14	// Pi
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
VARIABLES
 | 
					 | 
				
			||||||
	// 
 | 
					 | 
				
			||||||
	var MaxInt int	// MaxInt
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
FUNCTIONS
 | 
					 | 
				
			||||||
	// 
 | 
					 | 
				
			||||||
	func F(x int) int
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// Always under the package functions list. 
 | 
					 | 
				
			||||||
	func NotAFactory() int
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
TYPES
 | 
					 | 
				
			||||||
	// 
 | 
					 | 
				
			||||||
	type T struct{}	// T
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// 
 | 
					 | 
				
			||||||
	var V T	// v
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// 
 | 
					 | 
				
			||||||
	func (x *T) M()
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// 
 | 
					 | 
				
			||||||
	type notExported int
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// 
 | 
					 | 
				
			||||||
	const (
 | 
					 | 
				
			||||||
		C1	notExported	= iota
 | 
					 | 
				
			||||||
		C2
 | 
					 | 
				
			||||||
		c3
 | 
					 | 
				
			||||||
		C4
 | 
					 | 
				
			||||||
		C5
 | 
					 | 
				
			||||||
	)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// 
 | 
					 | 
				
			||||||
	const C notExported = 0
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// 
 | 
					 | 
				
			||||||
	var (
 | 
					 | 
				
			||||||
		U1, U2, u3, U4, U5	notExported
 | 
					 | 
				
			||||||
		u6			notExported
 | 
					 | 
				
			||||||
		U7			notExported	= 7
 | 
					 | 
				
			||||||
	)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// 
 | 
					 | 
				
			||||||
	var V notExported
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// 
 | 
					 | 
				
			||||||
	var V1, V2, v3, V4, V5 notExported
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// 
 | 
					 | 
				
			||||||
	func F1() notExported
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// 
 | 
					 | 
				
			||||||
	func f2() notExported
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// Should only appear if AllDecls is set. 
 | 
					 | 
				
			||||||
	type uint struct{}	// overrides a predeclared type uint
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// Associated with uint type if AllDecls is set. 
 | 
					 | 
				
			||||||
	func UintFactory() uint
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// Associated with uint type if AllDecls is set. 
 | 
					 | 
				
			||||||
	func uintFactory() uint
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
							
								
								
									
										71
									
								
								third_party/golang/go/doc/testdata/b.2.golden
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										71
									
								
								third_party/golang/go/doc/testdata/b.2.golden
									
									
									
									
										vendored
									
									
								
							@@ -1,71 +0,0 @@
 | 
				
			|||||||
// 
 | 
					 | 
				
			||||||
PACKAGE b
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
IMPORTPATH
 | 
					 | 
				
			||||||
	testdata/b
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
IMPORTS
 | 
					 | 
				
			||||||
	a
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
FILENAMES
 | 
					 | 
				
			||||||
	testdata/b.go
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
CONSTANTS
 | 
					 | 
				
			||||||
	// 
 | 
					 | 
				
			||||||
	const (
 | 
					 | 
				
			||||||
		C1	notExported	= iota
 | 
					 | 
				
			||||||
		C2
 | 
					 | 
				
			||||||
	
 | 
					 | 
				
			||||||
		C4
 | 
					 | 
				
			||||||
		C5
 | 
					 | 
				
			||||||
	)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// 
 | 
					 | 
				
			||||||
	const C notExported = 0
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// 
 | 
					 | 
				
			||||||
	const Pi = 3.14	// Pi
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
VARIABLES
 | 
					 | 
				
			||||||
	// 
 | 
					 | 
				
			||||||
	var (
 | 
					 | 
				
			||||||
		U1, U2, U4, U5	notExported
 | 
					 | 
				
			||||||
	
 | 
					 | 
				
			||||||
		U7	notExported	= 7
 | 
					 | 
				
			||||||
	)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// 
 | 
					 | 
				
			||||||
	var MaxInt int	// MaxInt
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// 
 | 
					 | 
				
			||||||
	var V notExported
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// 
 | 
					 | 
				
			||||||
	var V1, V2, V4, V5 notExported
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
FUNCTIONS
 | 
					 | 
				
			||||||
	// 
 | 
					 | 
				
			||||||
	func F(x int) int
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// 
 | 
					 | 
				
			||||||
	func F1() notExported
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// Always under the package functions list. 
 | 
					 | 
				
			||||||
	func NotAFactory() int
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// Associated with uint type if AllDecls is set. 
 | 
					 | 
				
			||||||
	func UintFactory() uint
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
TYPES
 | 
					 | 
				
			||||||
	// 
 | 
					 | 
				
			||||||
	type T struct{}	// T
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// 
 | 
					 | 
				
			||||||
	var V T	// v
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// 
 | 
					 | 
				
			||||||
	func (x *T) M()
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
							
								
								
									
										58
									
								
								third_party/golang/go/doc/testdata/b.go
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										58
									
								
								third_party/golang/go/doc/testdata/b.go
									
									
									
									
										vendored
									
									
								
							@@ -1,58 +0,0 @@
 | 
				
			|||||||
// Copyright 2012 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 b
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
import "a"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// ----------------------------------------------------------------------------
 | 
					 | 
				
			||||||
// Basic declarations
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
const Pi = 3.14   // Pi
 | 
					 | 
				
			||||||
var MaxInt int    // MaxInt
 | 
					 | 
				
			||||||
type T struct{}   // T
 | 
					 | 
				
			||||||
var V T           // v
 | 
					 | 
				
			||||||
func F(x int) int {} // F
 | 
					 | 
				
			||||||
func (x *T) M()   {} // M
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// Corner cases: association with (presumed) predeclared types
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// Always under the package functions list.
 | 
					 | 
				
			||||||
func NotAFactory() int {}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// Associated with uint type if AllDecls is set.
 | 
					 | 
				
			||||||
func UintFactory() uint {}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// Associated with uint type if AllDecls is set.
 | 
					 | 
				
			||||||
func uintFactory() uint {}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// Should only appear if AllDecls is set.
 | 
					 | 
				
			||||||
type uint struct{} // overrides a predeclared type uint
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// ----------------------------------------------------------------------------
 | 
					 | 
				
			||||||
// Exported declarations associated with non-exported types must always be shown.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
type notExported int
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
const C notExported = 0
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
const (
 | 
					 | 
				
			||||||
	C1 notExported = iota
 | 
					 | 
				
			||||||
	C2
 | 
					 | 
				
			||||||
	c3
 | 
					 | 
				
			||||||
	C4
 | 
					 | 
				
			||||||
	C5
 | 
					 | 
				
			||||||
)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
var V notExported
 | 
					 | 
				
			||||||
var V1, V2, v3, V4, V5 notExported
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
var (
 | 
					 | 
				
			||||||
	U1, U2, u3, U4, U5 notExported
 | 
					 | 
				
			||||||
	u6                 notExported
 | 
					 | 
				
			||||||
	U7                 notExported = 7
 | 
					 | 
				
			||||||
)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func F1() notExported {}
 | 
					 | 
				
			||||||
func f2() notExported {}
 | 
					 | 
				
			||||||
							
								
								
									
										293
									
								
								third_party/golang/go/doc/testdata/benchmark.go
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										293
									
								
								third_party/golang/go/doc/testdata/benchmark.go
									
									
									
									
										vendored
									
									
								
							@@ -1,293 +0,0 @@
 | 
				
			|||||||
// Copyright 2009 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 testing
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
import (
 | 
					 | 
				
			||||||
	"flag"
 | 
					 | 
				
			||||||
	"fmt"
 | 
					 | 
				
			||||||
	"os"
 | 
					 | 
				
			||||||
	"runtime"
 | 
					 | 
				
			||||||
	"time"
 | 
					 | 
				
			||||||
)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
var matchBenchmarks = flag.String("test.bench", "", "regular expression to select benchmarks to run")
 | 
					 | 
				
			||||||
var benchTime = flag.Duration("test.benchtime", 1*time.Second, "approximate run time for each benchmark")
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// An internal type but exported because it is cross-package; part of the implementation
 | 
					 | 
				
			||||||
// of go test.
 | 
					 | 
				
			||||||
type InternalBenchmark struct {
 | 
					 | 
				
			||||||
	Name string
 | 
					 | 
				
			||||||
	F    func(b *B)
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// B is a type passed to Benchmark functions to manage benchmark
 | 
					 | 
				
			||||||
// timing and to specify the number of iterations to run.
 | 
					 | 
				
			||||||
type B struct {
 | 
					 | 
				
			||||||
	common
 | 
					 | 
				
			||||||
	N         int
 | 
					 | 
				
			||||||
	benchmark InternalBenchmark
 | 
					 | 
				
			||||||
	bytes     int64
 | 
					 | 
				
			||||||
	timerOn   bool
 | 
					 | 
				
			||||||
	result    BenchmarkResult
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// StartTimer starts timing a test.  This function is called automatically
 | 
					 | 
				
			||||||
// before a benchmark starts, but it can also used to resume timing after
 | 
					 | 
				
			||||||
// a call to StopTimer.
 | 
					 | 
				
			||||||
func (b *B) StartTimer() {
 | 
					 | 
				
			||||||
	if !b.timerOn {
 | 
					 | 
				
			||||||
		b.start = time.Now()
 | 
					 | 
				
			||||||
		b.timerOn = true
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// StopTimer stops timing a test.  This can be used to pause the timer
 | 
					 | 
				
			||||||
// while performing complex initialization that you don't
 | 
					 | 
				
			||||||
// want to measure.
 | 
					 | 
				
			||||||
func (b *B) StopTimer() {
 | 
					 | 
				
			||||||
	if b.timerOn {
 | 
					 | 
				
			||||||
		b.duration += time.Now().Sub(b.start)
 | 
					 | 
				
			||||||
		b.timerOn = false
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// ResetTimer sets the elapsed benchmark time to zero.
 | 
					 | 
				
			||||||
// It does not affect whether the timer is running.
 | 
					 | 
				
			||||||
func (b *B) ResetTimer() {
 | 
					 | 
				
			||||||
	if b.timerOn {
 | 
					 | 
				
			||||||
		b.start = time.Now()
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	b.duration = 0
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// SetBytes records the number of bytes processed in a single operation.
 | 
					 | 
				
			||||||
// If this is called, the benchmark will report ns/op and MB/s.
 | 
					 | 
				
			||||||
func (b *B) SetBytes(n int64) { b.bytes = n }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (b *B) nsPerOp() int64 {
 | 
					 | 
				
			||||||
	if b.N <= 0 {
 | 
					 | 
				
			||||||
		return 0
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return b.duration.Nanoseconds() / int64(b.N)
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// runN runs a single benchmark for the specified number of iterations.
 | 
					 | 
				
			||||||
func (b *B) runN(n int) {
 | 
					 | 
				
			||||||
	// Try to get a comparable environment for each run
 | 
					 | 
				
			||||||
	// by clearing garbage from previous runs.
 | 
					 | 
				
			||||||
	runtime.GC()
 | 
					 | 
				
			||||||
	b.N = n
 | 
					 | 
				
			||||||
	b.ResetTimer()
 | 
					 | 
				
			||||||
	b.StartTimer()
 | 
					 | 
				
			||||||
	b.benchmark.F(b)
 | 
					 | 
				
			||||||
	b.StopTimer()
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func min(x, y int) int {
 | 
					 | 
				
			||||||
	if x > y {
 | 
					 | 
				
			||||||
		return y
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return x
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func max(x, y int) int {
 | 
					 | 
				
			||||||
	if x < y {
 | 
					 | 
				
			||||||
		return y
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return x
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// roundDown10 rounds a number down to the nearest power of 10.
 | 
					 | 
				
			||||||
func roundDown10(n int) int {
 | 
					 | 
				
			||||||
	var tens = 0
 | 
					 | 
				
			||||||
	// tens = floor(log_10(n))
 | 
					 | 
				
			||||||
	for n > 10 {
 | 
					 | 
				
			||||||
		n = n / 10
 | 
					 | 
				
			||||||
		tens++
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	// result = 10^tens
 | 
					 | 
				
			||||||
	result := 1
 | 
					 | 
				
			||||||
	for i := 0; i < tens; i++ {
 | 
					 | 
				
			||||||
		result *= 10
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return result
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// roundUp rounds x up to a number of the form [1eX, 2eX, 5eX].
 | 
					 | 
				
			||||||
func roundUp(n int) int {
 | 
					 | 
				
			||||||
	base := roundDown10(n)
 | 
					 | 
				
			||||||
	if n < (2 * base) {
 | 
					 | 
				
			||||||
		return 2 * base
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	if n < (5 * base) {
 | 
					 | 
				
			||||||
		return 5 * base
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return 10 * base
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// run times the benchmark function in a separate goroutine.
 | 
					 | 
				
			||||||
func (b *B) run() BenchmarkResult {
 | 
					 | 
				
			||||||
	go b.launch()
 | 
					 | 
				
			||||||
	<-b.signal
 | 
					 | 
				
			||||||
	return b.result
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// launch launches the benchmark function.  It gradually increases the number
 | 
					 | 
				
			||||||
// of benchmark iterations until the benchmark runs for a second in order
 | 
					 | 
				
			||||||
// to get a reasonable measurement.  It prints timing information in this form
 | 
					 | 
				
			||||||
//		testing.BenchmarkHello	100000		19 ns/op
 | 
					 | 
				
			||||||
// launch is run by the fun function as a separate goroutine.
 | 
					 | 
				
			||||||
func (b *B) launch() {
 | 
					 | 
				
			||||||
	// Run the benchmark for a single iteration in case it's expensive.
 | 
					 | 
				
			||||||
	n := 1
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// Signal that we're done whether we return normally
 | 
					 | 
				
			||||||
	// or by FailNow's runtime.Goexit.
 | 
					 | 
				
			||||||
	defer func() {
 | 
					 | 
				
			||||||
		b.signal <- b
 | 
					 | 
				
			||||||
	}()
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	b.runN(n)
 | 
					 | 
				
			||||||
	// Run the benchmark for at least the specified amount of time.
 | 
					 | 
				
			||||||
	d := *benchTime
 | 
					 | 
				
			||||||
	for !b.failed && b.duration < d && n < 1e9 {
 | 
					 | 
				
			||||||
		last := n
 | 
					 | 
				
			||||||
		// Predict iterations/sec.
 | 
					 | 
				
			||||||
		if b.nsPerOp() == 0 {
 | 
					 | 
				
			||||||
			n = 1e9
 | 
					 | 
				
			||||||
		} else {
 | 
					 | 
				
			||||||
			n = int(d.Nanoseconds() / b.nsPerOp())
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		// Run more iterations than we think we'll need for a second (1.5x).
 | 
					 | 
				
			||||||
		// Don't grow too fast in case we had timing errors previously.
 | 
					 | 
				
			||||||
		// Be sure to run at least one more than last time.
 | 
					 | 
				
			||||||
		n = max(min(n+n/2, 100*last), last+1)
 | 
					 | 
				
			||||||
		// Round up to something easy to read.
 | 
					 | 
				
			||||||
		n = roundUp(n)
 | 
					 | 
				
			||||||
		b.runN(n)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	b.result = BenchmarkResult{b.N, b.duration, b.bytes}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// The results of a benchmark run.
 | 
					 | 
				
			||||||
type BenchmarkResult struct {
 | 
					 | 
				
			||||||
	N     int           // The number of iterations.
 | 
					 | 
				
			||||||
	T     time.Duration // The total time taken.
 | 
					 | 
				
			||||||
	Bytes int64         // Bytes processed in one iteration.
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (r BenchmarkResult) NsPerOp() int64 {
 | 
					 | 
				
			||||||
	if r.N <= 0 {
 | 
					 | 
				
			||||||
		return 0
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return r.T.Nanoseconds() / int64(r.N)
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (r BenchmarkResult) mbPerSec() float64 {
 | 
					 | 
				
			||||||
	if r.Bytes <= 0 || r.T <= 0 || r.N <= 0 {
 | 
					 | 
				
			||||||
		return 0
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return (float64(r.Bytes) * float64(r.N) / 1e6) / r.T.Seconds()
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (r BenchmarkResult) String() string {
 | 
					 | 
				
			||||||
	mbs := r.mbPerSec()
 | 
					 | 
				
			||||||
	mb := ""
 | 
					 | 
				
			||||||
	if mbs != 0 {
 | 
					 | 
				
			||||||
		mb = fmt.Sprintf("\t%7.2f MB/s", mbs)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	nsop := r.NsPerOp()
 | 
					 | 
				
			||||||
	ns := fmt.Sprintf("%10d ns/op", nsop)
 | 
					 | 
				
			||||||
	if r.N > 0 && nsop < 100 {
 | 
					 | 
				
			||||||
		// The format specifiers here make sure that
 | 
					 | 
				
			||||||
		// the ones digits line up for all three possible formats.
 | 
					 | 
				
			||||||
		if nsop < 10 {
 | 
					 | 
				
			||||||
			ns = fmt.Sprintf("%13.2f ns/op", float64(r.T.Nanoseconds())/float64(r.N))
 | 
					 | 
				
			||||||
		} else {
 | 
					 | 
				
			||||||
			ns = fmt.Sprintf("%12.1f ns/op", float64(r.T.Nanoseconds())/float64(r.N))
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return fmt.Sprintf("%8d\t%s%s", r.N, ns, mb)
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// An internal function but exported because it is cross-package; part of the implementation
 | 
					 | 
				
			||||||
// of go test.
 | 
					 | 
				
			||||||
func RunBenchmarks(matchString func(pat, str string) (bool, error), benchmarks []InternalBenchmark) {
 | 
					 | 
				
			||||||
	// If no flag was specified, don't run benchmarks.
 | 
					 | 
				
			||||||
	if len(*matchBenchmarks) == 0 {
 | 
					 | 
				
			||||||
		return
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	for _, Benchmark := range benchmarks {
 | 
					 | 
				
			||||||
		matched, err := matchString(*matchBenchmarks, Benchmark.Name)
 | 
					 | 
				
			||||||
		if err != nil {
 | 
					 | 
				
			||||||
			fmt.Fprintf(os.Stderr, "testing: invalid regexp for -test.bench: %s\n", err)
 | 
					 | 
				
			||||||
			os.Exit(1)
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		if !matched {
 | 
					 | 
				
			||||||
			continue
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		for _, procs := range cpuList {
 | 
					 | 
				
			||||||
			runtime.GOMAXPROCS(procs)
 | 
					 | 
				
			||||||
			b := &B{
 | 
					 | 
				
			||||||
				common: common{
 | 
					 | 
				
			||||||
					signal: make(chan interface{}),
 | 
					 | 
				
			||||||
				},
 | 
					 | 
				
			||||||
				benchmark: Benchmark,
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
			benchName := Benchmark.Name
 | 
					 | 
				
			||||||
			if procs != 1 {
 | 
					 | 
				
			||||||
				benchName = fmt.Sprintf("%s-%d", Benchmark.Name, procs)
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
			fmt.Printf("%s\t", benchName)
 | 
					 | 
				
			||||||
			r := b.run()
 | 
					 | 
				
			||||||
			if b.failed {
 | 
					 | 
				
			||||||
				// The output could be very long here, but probably isn't.
 | 
					 | 
				
			||||||
				// We print it all, regardless, because we don't want to trim the reason
 | 
					 | 
				
			||||||
				// the benchmark failed.
 | 
					 | 
				
			||||||
				fmt.Printf("--- FAIL: %s\n%s", benchName, b.output)
 | 
					 | 
				
			||||||
				continue
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
			fmt.Printf("%v\n", r)
 | 
					 | 
				
			||||||
			// Unlike with tests, we ignore the -chatty flag and always print output for
 | 
					 | 
				
			||||||
			// benchmarks since the output generation time will skew the results.
 | 
					 | 
				
			||||||
			if len(b.output) > 0 {
 | 
					 | 
				
			||||||
				b.trimOutput()
 | 
					 | 
				
			||||||
				fmt.Printf("--- BENCH: %s\n%s", benchName, b.output)
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
			if p := runtime.GOMAXPROCS(-1); p != procs {
 | 
					 | 
				
			||||||
				fmt.Fprintf(os.Stderr, "testing: %s left GOMAXPROCS set to %d\n", benchName, p)
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// trimOutput shortens the output from a benchmark, which can be very long.
 | 
					 | 
				
			||||||
func (b *B) trimOutput() {
 | 
					 | 
				
			||||||
	// The output is likely to appear multiple times because the benchmark
 | 
					 | 
				
			||||||
	// is run multiple times, but at least it will be seen. This is not a big deal
 | 
					 | 
				
			||||||
	// because benchmarks rarely print, but just in case, we trim it if it's too long.
 | 
					 | 
				
			||||||
	const maxNewlines = 10
 | 
					 | 
				
			||||||
	for nlCount, j := 0, 0; j < len(b.output); j++ {
 | 
					 | 
				
			||||||
		if b.output[j] == '\n' {
 | 
					 | 
				
			||||||
			nlCount++
 | 
					 | 
				
			||||||
			if nlCount >= maxNewlines {
 | 
					 | 
				
			||||||
				b.output = append(b.output[:j], "\n\t... [output truncated]\n"...)
 | 
					 | 
				
			||||||
				break
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// Benchmark benchmarks a single function. Useful for creating
 | 
					 | 
				
			||||||
// custom benchmarks that do not use go test.
 | 
					 | 
				
			||||||
func Benchmark(f func(b *B)) BenchmarkResult {
 | 
					 | 
				
			||||||
	b := &B{
 | 
					 | 
				
			||||||
		common: common{
 | 
					 | 
				
			||||||
			signal: make(chan interface{}),
 | 
					 | 
				
			||||||
		},
 | 
					 | 
				
			||||||
		benchmark: InternalBenchmark{"", f},
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return b.run()
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
@@ -1,55 +0,0 @@
 | 
				
			|||||||
// Package blank is a go/doc test for the handling of _. See issue ...
 | 
					 | 
				
			||||||
PACKAGE blank
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
IMPORTPATH
 | 
					 | 
				
			||||||
	testdata/blank
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
IMPORTS
 | 
					 | 
				
			||||||
	os
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
FILENAMES
 | 
					 | 
				
			||||||
	testdata/blank.go
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
CONSTANTS
 | 
					 | 
				
			||||||
	// T constants counting from unexported constants. 
 | 
					 | 
				
			||||||
	const (
 | 
					 | 
				
			||||||
		C1	T
 | 
					 | 
				
			||||||
		C2
 | 
					 | 
				
			||||||
	
 | 
					 | 
				
			||||||
		C3
 | 
					 | 
				
			||||||
	
 | 
					 | 
				
			||||||
		C4	int
 | 
					 | 
				
			||||||
	)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// Constants with an imported type that needs to be propagated. 
 | 
					 | 
				
			||||||
	const (
 | 
					 | 
				
			||||||
		Default		os.FileMode	= 0644
 | 
					 | 
				
			||||||
		Useless				= 0312
 | 
					 | 
				
			||||||
		WideOpen			= 0777
 | 
					 | 
				
			||||||
	)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// Package constants. 
 | 
					 | 
				
			||||||
	const (
 | 
					 | 
				
			||||||
		I1	int
 | 
					 | 
				
			||||||
		I2
 | 
					 | 
				
			||||||
	)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
TYPES
 | 
					 | 
				
			||||||
	// S has a padding field. 
 | 
					 | 
				
			||||||
	type S struct {
 | 
					 | 
				
			||||||
		H	uint32
 | 
					 | 
				
			||||||
	
 | 
					 | 
				
			||||||
		A	uint8
 | 
					 | 
				
			||||||
		// contains filtered or unexported fields
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// 
 | 
					 | 
				
			||||||
	type T int
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// T constants counting from a blank constant. 
 | 
					 | 
				
			||||||
	const (
 | 
					 | 
				
			||||||
		T1	T
 | 
					 | 
				
			||||||
		T2
 | 
					 | 
				
			||||||
	)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
@@ -1,75 +0,0 @@
 | 
				
			|||||||
// Package blank is a go/doc test for the handling of _. See issue ...
 | 
					 | 
				
			||||||
PACKAGE blank
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
IMPORTPATH
 | 
					 | 
				
			||||||
	testdata/blank
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
IMPORTS
 | 
					 | 
				
			||||||
	os
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
FILENAMES
 | 
					 | 
				
			||||||
	testdata/blank.go
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
CONSTANTS
 | 
					 | 
				
			||||||
	// T constants counting from unexported constants. 
 | 
					 | 
				
			||||||
	const (
 | 
					 | 
				
			||||||
		tweedledee	T	= iota
 | 
					 | 
				
			||||||
		tweedledum
 | 
					 | 
				
			||||||
		C1
 | 
					 | 
				
			||||||
		C2
 | 
					 | 
				
			||||||
		alice
 | 
					 | 
				
			||||||
		C3
 | 
					 | 
				
			||||||
		redQueen	int	= iota
 | 
					 | 
				
			||||||
		C4
 | 
					 | 
				
			||||||
	)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// Package constants. 
 | 
					 | 
				
			||||||
	const (
 | 
					 | 
				
			||||||
		_	int	= iota
 | 
					 | 
				
			||||||
		I1
 | 
					 | 
				
			||||||
		I2
 | 
					 | 
				
			||||||
	)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// Constants with an imported type that needs to be propagated. 
 | 
					 | 
				
			||||||
	const (
 | 
					 | 
				
			||||||
		zero		os.FileMode	= 0
 | 
					 | 
				
			||||||
		Default				= 0644
 | 
					 | 
				
			||||||
		Useless				= 0312
 | 
					 | 
				
			||||||
		WideOpen			= 0777
 | 
					 | 
				
			||||||
	)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// Unexported constants counting from blank iota. See issue 9615. 
 | 
					 | 
				
			||||||
	const (
 | 
					 | 
				
			||||||
		_	= iota
 | 
					 | 
				
			||||||
		one	= iota + 1
 | 
					 | 
				
			||||||
	)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
VARIABLES
 | 
					 | 
				
			||||||
	// 
 | 
					 | 
				
			||||||
	var _ = T(55)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
FUNCTIONS
 | 
					 | 
				
			||||||
	// 
 | 
					 | 
				
			||||||
	func _()
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
TYPES
 | 
					 | 
				
			||||||
	// S has a padding field. 
 | 
					 | 
				
			||||||
	type S struct {
 | 
					 | 
				
			||||||
		H	uint32
 | 
					 | 
				
			||||||
		_	uint8
 | 
					 | 
				
			||||||
		A	uint8
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// 
 | 
					 | 
				
			||||||
	type T int
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// T constants counting from a blank constant. 
 | 
					 | 
				
			||||||
	const (
 | 
					 | 
				
			||||||
		_	T	= iota
 | 
					 | 
				
			||||||
		T1
 | 
					 | 
				
			||||||
		T2
 | 
					 | 
				
			||||||
	)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
@@ -1,55 +0,0 @@
 | 
				
			|||||||
// Package blank is a go/doc test for the handling of _. See issue ...
 | 
					 | 
				
			||||||
PACKAGE blank
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
IMPORTPATH
 | 
					 | 
				
			||||||
	testdata/blank
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
IMPORTS
 | 
					 | 
				
			||||||
	os
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
FILENAMES
 | 
					 | 
				
			||||||
	testdata/blank.go
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
CONSTANTS
 | 
					 | 
				
			||||||
	// T constants counting from unexported constants. 
 | 
					 | 
				
			||||||
	const (
 | 
					 | 
				
			||||||
		C1	T
 | 
					 | 
				
			||||||
		C2
 | 
					 | 
				
			||||||
	
 | 
					 | 
				
			||||||
		C3
 | 
					 | 
				
			||||||
	
 | 
					 | 
				
			||||||
		C4	int
 | 
					 | 
				
			||||||
	)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// Constants with an imported type that needs to be propagated. 
 | 
					 | 
				
			||||||
	const (
 | 
					 | 
				
			||||||
		Default		os.FileMode	= 0644
 | 
					 | 
				
			||||||
		Useless				= 0312
 | 
					 | 
				
			||||||
		WideOpen			= 0777
 | 
					 | 
				
			||||||
	)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// Package constants. 
 | 
					 | 
				
			||||||
	const (
 | 
					 | 
				
			||||||
		I1	int
 | 
					 | 
				
			||||||
		I2
 | 
					 | 
				
			||||||
	)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
TYPES
 | 
					 | 
				
			||||||
	// S has a padding field. 
 | 
					 | 
				
			||||||
	type S struct {
 | 
					 | 
				
			||||||
		H	uint32
 | 
					 | 
				
			||||||
	
 | 
					 | 
				
			||||||
		A	uint8
 | 
					 | 
				
			||||||
		// contains filtered or unexported fields
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// 
 | 
					 | 
				
			||||||
	type T int
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// T constants counting from a blank constant. 
 | 
					 | 
				
			||||||
	const (
 | 
					 | 
				
			||||||
		T1	T
 | 
					 | 
				
			||||||
		T2
 | 
					 | 
				
			||||||
	)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
							
								
								
									
										67
									
								
								third_party/golang/go/doc/testdata/blank.go
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										67
									
								
								third_party/golang/go/doc/testdata/blank.go
									
									
									
									
										vendored
									
									
								
							@@ -1,67 +0,0 @@
 | 
				
			|||||||
// Copyright 2014 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 blank is a go/doc test for the handling of _.
 | 
					 | 
				
			||||||
// See issue 5397.
 | 
					 | 
				
			||||||
package blank
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
import "os"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
type T int
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// T constants counting from a blank constant.
 | 
					 | 
				
			||||||
const (
 | 
					 | 
				
			||||||
	_ T = iota
 | 
					 | 
				
			||||||
	T1
 | 
					 | 
				
			||||||
	T2
 | 
					 | 
				
			||||||
)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// T constants counting from unexported constants.
 | 
					 | 
				
			||||||
const (
 | 
					 | 
				
			||||||
	tweedledee T = iota
 | 
					 | 
				
			||||||
	tweedledum
 | 
					 | 
				
			||||||
	C1
 | 
					 | 
				
			||||||
	C2
 | 
					 | 
				
			||||||
	alice
 | 
					 | 
				
			||||||
	C3
 | 
					 | 
				
			||||||
	redQueen int = iota
 | 
					 | 
				
			||||||
	C4
 | 
					 | 
				
			||||||
)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// Constants with an imported type that needs to be propagated.
 | 
					 | 
				
			||||||
const (
 | 
					 | 
				
			||||||
	zero     os.FileMode = 0
 | 
					 | 
				
			||||||
	Default              = 0644
 | 
					 | 
				
			||||||
	Useless              = 0312
 | 
					 | 
				
			||||||
	WideOpen             = 0777
 | 
					 | 
				
			||||||
)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// Package constants.
 | 
					 | 
				
			||||||
const (
 | 
					 | 
				
			||||||
	_ int = iota
 | 
					 | 
				
			||||||
	I1
 | 
					 | 
				
			||||||
	I2
 | 
					 | 
				
			||||||
)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// Unexported constants counting from blank iota.
 | 
					 | 
				
			||||||
// See issue 9615.
 | 
					 | 
				
			||||||
const (
 | 
					 | 
				
			||||||
	_   = iota
 | 
					 | 
				
			||||||
	one = iota + 1
 | 
					 | 
				
			||||||
)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// Blanks not in doc output:
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// S has a padding field.
 | 
					 | 
				
			||||||
type S struct {
 | 
					 | 
				
			||||||
	H uint32
 | 
					 | 
				
			||||||
	_ uint8
 | 
					 | 
				
			||||||
	A uint8
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func _() {}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
type _ T
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
var _ = T(55)
 | 
					 | 
				
			||||||
@@ -1,20 +0,0 @@
 | 
				
			|||||||
// 
 | 
					 | 
				
			||||||
PACKAGE bugpara
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
IMPORTPATH
 | 
					 | 
				
			||||||
	testdata/bugpara
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
FILENAMES
 | 
					 | 
				
			||||||
	testdata/bugpara.go
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
BUGS .Bugs is now deprecated, please use .Notes instead
 | 
					 | 
				
			||||||
	Sometimes bugs have multiple paragraphs.
 | 
					 | 
				
			||||||
	
 | 
					 | 
				
			||||||
	Like this one.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
BUGS
 | 
					 | 
				
			||||||
BUG(rsc)	Sometimes bugs have multiple paragraphs.
 | 
					 | 
				
			||||||
	
 | 
					 | 
				
			||||||
	Like this one.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
@@ -1,20 +0,0 @@
 | 
				
			|||||||
// 
 | 
					 | 
				
			||||||
PACKAGE bugpara
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
IMPORTPATH
 | 
					 | 
				
			||||||
	testdata/bugpara
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
FILENAMES
 | 
					 | 
				
			||||||
	testdata/bugpara.go
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
BUGS .Bugs is now deprecated, please use .Notes instead
 | 
					 | 
				
			||||||
	Sometimes bugs have multiple paragraphs.
 | 
					 | 
				
			||||||
	
 | 
					 | 
				
			||||||
	Like this one.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
BUGS
 | 
					 | 
				
			||||||
BUG(rsc)	Sometimes bugs have multiple paragraphs.
 | 
					 | 
				
			||||||
	
 | 
					 | 
				
			||||||
	Like this one.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
@@ -1,20 +0,0 @@
 | 
				
			|||||||
// 
 | 
					 | 
				
			||||||
PACKAGE bugpara
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
IMPORTPATH
 | 
					 | 
				
			||||||
	testdata/bugpara
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
FILENAMES
 | 
					 | 
				
			||||||
	testdata/bugpara.go
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
BUGS .Bugs is now deprecated, please use .Notes instead
 | 
					 | 
				
			||||||
	Sometimes bugs have multiple paragraphs.
 | 
					 | 
				
			||||||
	
 | 
					 | 
				
			||||||
	Like this one.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
BUGS
 | 
					 | 
				
			||||||
BUG(rsc)	Sometimes bugs have multiple paragraphs.
 | 
					 | 
				
			||||||
	
 | 
					 | 
				
			||||||
	Like this one.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
@@ -1,5 +0,0 @@
 | 
				
			|||||||
package bugpara
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// BUG(rsc): Sometimes bugs have multiple paragraphs.
 | 
					 | 
				
			||||||
//
 | 
					 | 
				
			||||||
// Like this one.
 | 
					 | 
				
			||||||
							
								
								
									
										48
									
								
								third_party/golang/go/doc/testdata/c.0.golden
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										48
									
								
								third_party/golang/go/doc/testdata/c.0.golden
									
									
									
									
										vendored
									
									
								
							@@ -1,48 +0,0 @@
 | 
				
			|||||||
// 
 | 
					 | 
				
			||||||
PACKAGE c
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
IMPORTPATH
 | 
					 | 
				
			||||||
	testdata/c
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
IMPORTS
 | 
					 | 
				
			||||||
	a
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
FILENAMES
 | 
					 | 
				
			||||||
	testdata/c.go
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
TYPES
 | 
					 | 
				
			||||||
	// A (should see this) 
 | 
					 | 
				
			||||||
	type A struct{}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// B (should see this) 
 | 
					 | 
				
			||||||
	type B struct{}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// C (should see this) 
 | 
					 | 
				
			||||||
	type C struct{}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// D (should see this) 
 | 
					 | 
				
			||||||
	type D struct{}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// E1 (should see this) 
 | 
					 | 
				
			||||||
	type E1 struct{}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// E (should see this for E2 and E3) 
 | 
					 | 
				
			||||||
	type E2 struct{}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// E (should see this for E2 and E3) 
 | 
					 | 
				
			||||||
	type E3 struct{}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// E4 (should see this) 
 | 
					 | 
				
			||||||
	type E4 struct{}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// 
 | 
					 | 
				
			||||||
	type T1 struct{}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// 
 | 
					 | 
				
			||||||
	func (t1 *T1) M()
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// T2 must not show methods of local T1 
 | 
					 | 
				
			||||||
	type T2 struct {
 | 
					 | 
				
			||||||
		a.T1	// not the same as locally declared T1
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
							
								
								
									
										48
									
								
								third_party/golang/go/doc/testdata/c.1.golden
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										48
									
								
								third_party/golang/go/doc/testdata/c.1.golden
									
									
									
									
										vendored
									
									
								
							@@ -1,48 +0,0 @@
 | 
				
			|||||||
// 
 | 
					 | 
				
			||||||
PACKAGE c
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
IMPORTPATH
 | 
					 | 
				
			||||||
	testdata/c
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
IMPORTS
 | 
					 | 
				
			||||||
	a
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
FILENAMES
 | 
					 | 
				
			||||||
	testdata/c.go
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
TYPES
 | 
					 | 
				
			||||||
	// A (should see this) 
 | 
					 | 
				
			||||||
	type A struct{}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// B (should see this) 
 | 
					 | 
				
			||||||
	type B struct{}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// C (should see this) 
 | 
					 | 
				
			||||||
	type C struct{}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// D (should see this) 
 | 
					 | 
				
			||||||
	type D struct{}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// E1 (should see this) 
 | 
					 | 
				
			||||||
	type E1 struct{}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// E (should see this for E2 and E3) 
 | 
					 | 
				
			||||||
	type E2 struct{}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// E (should see this for E2 and E3) 
 | 
					 | 
				
			||||||
	type E3 struct{}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// E4 (should see this) 
 | 
					 | 
				
			||||||
	type E4 struct{}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// 
 | 
					 | 
				
			||||||
	type T1 struct{}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// 
 | 
					 | 
				
			||||||
	func (t1 *T1) M()
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// T2 must not show methods of local T1 
 | 
					 | 
				
			||||||
	type T2 struct {
 | 
					 | 
				
			||||||
		a.T1	// not the same as locally declared T1
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
							
								
								
									
										48
									
								
								third_party/golang/go/doc/testdata/c.2.golden
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										48
									
								
								third_party/golang/go/doc/testdata/c.2.golden
									
									
									
									
										vendored
									
									
								
							@@ -1,48 +0,0 @@
 | 
				
			|||||||
// 
 | 
					 | 
				
			||||||
PACKAGE c
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
IMPORTPATH
 | 
					 | 
				
			||||||
	testdata/c
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
IMPORTS
 | 
					 | 
				
			||||||
	a
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
FILENAMES
 | 
					 | 
				
			||||||
	testdata/c.go
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
TYPES
 | 
					 | 
				
			||||||
	// A (should see this) 
 | 
					 | 
				
			||||||
	type A struct{}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// B (should see this) 
 | 
					 | 
				
			||||||
	type B struct{}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// C (should see this) 
 | 
					 | 
				
			||||||
	type C struct{}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// D (should see this) 
 | 
					 | 
				
			||||||
	type D struct{}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// E1 (should see this) 
 | 
					 | 
				
			||||||
	type E1 struct{}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// E (should see this for E2 and E3) 
 | 
					 | 
				
			||||||
	type E2 struct{}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// E (should see this for E2 and E3) 
 | 
					 | 
				
			||||||
	type E3 struct{}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// E4 (should see this) 
 | 
					 | 
				
			||||||
	type E4 struct{}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// 
 | 
					 | 
				
			||||||
	type T1 struct{}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// 
 | 
					 | 
				
			||||||
	func (t1 *T1) M()
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// T2 must not show methods of local T1 
 | 
					 | 
				
			||||||
	type T2 struct {
 | 
					 | 
				
			||||||
		a.T1	// not the same as locally declared T1
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
							
								
								
									
										62
									
								
								third_party/golang/go/doc/testdata/c.go
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										62
									
								
								third_party/golang/go/doc/testdata/c.go
									
									
									
									
										vendored
									
									
								
							@@ -1,62 +0,0 @@
 | 
				
			|||||||
// Copyright 2012 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 c
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
import "a"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// ----------------------------------------------------------------------------
 | 
					 | 
				
			||||||
// Test that empty declarations don't cause problems
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
const ()
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
type ()
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
var ()
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// ----------------------------------------------------------------------------
 | 
					 | 
				
			||||||
// Test that types with documentation on both, the Decl and the Spec node
 | 
					 | 
				
			||||||
// are handled correctly.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// A (should see this)
 | 
					 | 
				
			||||||
type A struct{}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// B (should see this)
 | 
					 | 
				
			||||||
type (
 | 
					 | 
				
			||||||
	B struct{}
 | 
					 | 
				
			||||||
)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
type (
 | 
					 | 
				
			||||||
	// C (should see this)
 | 
					 | 
				
			||||||
	C struct{}
 | 
					 | 
				
			||||||
)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// D (should not see this)
 | 
					 | 
				
			||||||
type (
 | 
					 | 
				
			||||||
	// D (should see this)
 | 
					 | 
				
			||||||
	D struct{}
 | 
					 | 
				
			||||||
)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// E (should see this for E2 and E3)
 | 
					 | 
				
			||||||
type (
 | 
					 | 
				
			||||||
	// E1 (should see this)
 | 
					 | 
				
			||||||
	E1 struct{}
 | 
					 | 
				
			||||||
	E2 struct{}
 | 
					 | 
				
			||||||
	E3 struct{}
 | 
					 | 
				
			||||||
	// E4 (should see this)
 | 
					 | 
				
			||||||
	E4 struct{}
 | 
					 | 
				
			||||||
)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// ----------------------------------------------------------------------------
 | 
					 | 
				
			||||||
// Test that local and imported types are different when
 | 
					 | 
				
			||||||
// handling anonymous fields.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
type T1 struct{}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (t1 *T1) M() {}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// T2 must not show methods of local T1
 | 
					 | 
				
			||||||
type T2 struct {
 | 
					 | 
				
			||||||
	a.T1 // not the same as locally declared T1
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
							
								
								
									
										104
									
								
								third_party/golang/go/doc/testdata/d.0.golden
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										104
									
								
								third_party/golang/go/doc/testdata/d.0.golden
									
									
									
									
										vendored
									
									
								
							@@ -1,104 +0,0 @@
 | 
				
			|||||||
// 
 | 
					 | 
				
			||||||
PACKAGE d
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
IMPORTPATH
 | 
					 | 
				
			||||||
	testdata/d
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
FILENAMES
 | 
					 | 
				
			||||||
	testdata/d1.go
 | 
					 | 
				
			||||||
	testdata/d2.go
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
CONSTANTS
 | 
					 | 
				
			||||||
	// CBx constants should appear before CAx constants. 
 | 
					 | 
				
			||||||
	const (
 | 
					 | 
				
			||||||
		CB2	= iota	// before CB1
 | 
					 | 
				
			||||||
		CB1		// before CB0
 | 
					 | 
				
			||||||
		CB0		// at end
 | 
					 | 
				
			||||||
	)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// CAx constants should appear after CBx constants. 
 | 
					 | 
				
			||||||
	const (
 | 
					 | 
				
			||||||
		CA2	= iota	// before CA1
 | 
					 | 
				
			||||||
		CA1		// before CA0
 | 
					 | 
				
			||||||
		CA0		// at end
 | 
					 | 
				
			||||||
	)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// C0 should be first. 
 | 
					 | 
				
			||||||
	const C0 = 0
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// C1 should be second. 
 | 
					 | 
				
			||||||
	const C1 = 1
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// C2 should be third. 
 | 
					 | 
				
			||||||
	const C2 = 2
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// 
 | 
					 | 
				
			||||||
	const (
 | 
					 | 
				
			||||||
		// Single const declarations inside ()'s are considered ungrouped
 | 
					 | 
				
			||||||
		// and show up in sorted order.
 | 
					 | 
				
			||||||
		Cungrouped = 0
 | 
					 | 
				
			||||||
	)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
VARIABLES
 | 
					 | 
				
			||||||
	// VBx variables should appear before VAx variables. 
 | 
					 | 
				
			||||||
	var (
 | 
					 | 
				
			||||||
		VB2	int	// before VB1
 | 
					 | 
				
			||||||
		VB1	int	// before VB0
 | 
					 | 
				
			||||||
		VB0	int	// at end
 | 
					 | 
				
			||||||
	)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// VAx variables should appear after VBx variables. 
 | 
					 | 
				
			||||||
	var (
 | 
					 | 
				
			||||||
		VA2	int	// before VA1
 | 
					 | 
				
			||||||
		VA1	int	// before VA0
 | 
					 | 
				
			||||||
		VA0	int	// at end
 | 
					 | 
				
			||||||
	)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// V0 should be first. 
 | 
					 | 
				
			||||||
	var V0 uintptr
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// V1 should be second. 
 | 
					 | 
				
			||||||
	var V1 uint
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// V2 should be third. 
 | 
					 | 
				
			||||||
	var V2 int
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// 
 | 
					 | 
				
			||||||
	var (
 | 
					 | 
				
			||||||
		// Single var declarations inside ()'s are considered ungrouped
 | 
					 | 
				
			||||||
		// and show up in sorted order.
 | 
					 | 
				
			||||||
		Vungrouped = 0
 | 
					 | 
				
			||||||
	)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
FUNCTIONS
 | 
					 | 
				
			||||||
	// F0 should be first. 
 | 
					 | 
				
			||||||
	func F0()
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// F1 should be second. 
 | 
					 | 
				
			||||||
	func F1()
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// F2 should be third. 
 | 
					 | 
				
			||||||
	func F2()
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
TYPES
 | 
					 | 
				
			||||||
	// T0 should be first. 
 | 
					 | 
				
			||||||
	type T0 struct{}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// T1 should be second. 
 | 
					 | 
				
			||||||
	type T1 struct{}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// T2 should be third. 
 | 
					 | 
				
			||||||
	type T2 struct{}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// TG0 should be first. 
 | 
					 | 
				
			||||||
	type TG0 struct{}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// TG1 should be second. 
 | 
					 | 
				
			||||||
	type TG1 struct{}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// TG2 should be third. 
 | 
					 | 
				
			||||||
	type TG2 struct{}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
							
								
								
									
										104
									
								
								third_party/golang/go/doc/testdata/d.1.golden
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										104
									
								
								third_party/golang/go/doc/testdata/d.1.golden
									
									
									
									
										vendored
									
									
								
							@@ -1,104 +0,0 @@
 | 
				
			|||||||
// 
 | 
					 | 
				
			||||||
PACKAGE d
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
IMPORTPATH
 | 
					 | 
				
			||||||
	testdata/d
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
FILENAMES
 | 
					 | 
				
			||||||
	testdata/d1.go
 | 
					 | 
				
			||||||
	testdata/d2.go
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
CONSTANTS
 | 
					 | 
				
			||||||
	// CBx constants should appear before CAx constants. 
 | 
					 | 
				
			||||||
	const (
 | 
					 | 
				
			||||||
		CB2	= iota	// before CB1
 | 
					 | 
				
			||||||
		CB1		// before CB0
 | 
					 | 
				
			||||||
		CB0		// at end
 | 
					 | 
				
			||||||
	)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// CAx constants should appear after CBx constants. 
 | 
					 | 
				
			||||||
	const (
 | 
					 | 
				
			||||||
		CA2	= iota	// before CA1
 | 
					 | 
				
			||||||
		CA1		// before CA0
 | 
					 | 
				
			||||||
		CA0		// at end
 | 
					 | 
				
			||||||
	)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// C0 should be first. 
 | 
					 | 
				
			||||||
	const C0 = 0
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// C1 should be second. 
 | 
					 | 
				
			||||||
	const C1 = 1
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// C2 should be third. 
 | 
					 | 
				
			||||||
	const C2 = 2
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// 
 | 
					 | 
				
			||||||
	const (
 | 
					 | 
				
			||||||
		// Single const declarations inside ()'s are considered ungrouped
 | 
					 | 
				
			||||||
		// and show up in sorted order.
 | 
					 | 
				
			||||||
		Cungrouped = 0
 | 
					 | 
				
			||||||
	)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
VARIABLES
 | 
					 | 
				
			||||||
	// VBx variables should appear before VAx variables. 
 | 
					 | 
				
			||||||
	var (
 | 
					 | 
				
			||||||
		VB2	int	// before VB1
 | 
					 | 
				
			||||||
		VB1	int	// before VB0
 | 
					 | 
				
			||||||
		VB0	int	// at end
 | 
					 | 
				
			||||||
	)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// VAx variables should appear after VBx variables. 
 | 
					 | 
				
			||||||
	var (
 | 
					 | 
				
			||||||
		VA2	int	// before VA1
 | 
					 | 
				
			||||||
		VA1	int	// before VA0
 | 
					 | 
				
			||||||
		VA0	int	// at end
 | 
					 | 
				
			||||||
	)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// V0 should be first. 
 | 
					 | 
				
			||||||
	var V0 uintptr
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// V1 should be second. 
 | 
					 | 
				
			||||||
	var V1 uint
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// V2 should be third. 
 | 
					 | 
				
			||||||
	var V2 int
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// 
 | 
					 | 
				
			||||||
	var (
 | 
					 | 
				
			||||||
		// Single var declarations inside ()'s are considered ungrouped
 | 
					 | 
				
			||||||
		// and show up in sorted order.
 | 
					 | 
				
			||||||
		Vungrouped = 0
 | 
					 | 
				
			||||||
	)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
FUNCTIONS
 | 
					 | 
				
			||||||
	// F0 should be first. 
 | 
					 | 
				
			||||||
	func F0()
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// F1 should be second. 
 | 
					 | 
				
			||||||
	func F1()
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// F2 should be third. 
 | 
					 | 
				
			||||||
	func F2()
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
TYPES
 | 
					 | 
				
			||||||
	// T0 should be first. 
 | 
					 | 
				
			||||||
	type T0 struct{}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// T1 should be second. 
 | 
					 | 
				
			||||||
	type T1 struct{}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// T2 should be third. 
 | 
					 | 
				
			||||||
	type T2 struct{}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// TG0 should be first. 
 | 
					 | 
				
			||||||
	type TG0 struct{}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// TG1 should be second. 
 | 
					 | 
				
			||||||
	type TG1 struct{}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// TG2 should be third. 
 | 
					 | 
				
			||||||
	type TG2 struct{}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
							
								
								
									
										104
									
								
								third_party/golang/go/doc/testdata/d.2.golden
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										104
									
								
								third_party/golang/go/doc/testdata/d.2.golden
									
									
									
									
										vendored
									
									
								
							@@ -1,104 +0,0 @@
 | 
				
			|||||||
// 
 | 
					 | 
				
			||||||
PACKAGE d
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
IMPORTPATH
 | 
					 | 
				
			||||||
	testdata/d
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
FILENAMES
 | 
					 | 
				
			||||||
	testdata/d1.go
 | 
					 | 
				
			||||||
	testdata/d2.go
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
CONSTANTS
 | 
					 | 
				
			||||||
	// CBx constants should appear before CAx constants. 
 | 
					 | 
				
			||||||
	const (
 | 
					 | 
				
			||||||
		CB2	= iota	// before CB1
 | 
					 | 
				
			||||||
		CB1		// before CB0
 | 
					 | 
				
			||||||
		CB0		// at end
 | 
					 | 
				
			||||||
	)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// CAx constants should appear after CBx constants. 
 | 
					 | 
				
			||||||
	const (
 | 
					 | 
				
			||||||
		CA2	= iota	// before CA1
 | 
					 | 
				
			||||||
		CA1		// before CA0
 | 
					 | 
				
			||||||
		CA0		// at end
 | 
					 | 
				
			||||||
	)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// C0 should be first. 
 | 
					 | 
				
			||||||
	const C0 = 0
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// C1 should be second. 
 | 
					 | 
				
			||||||
	const C1 = 1
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// C2 should be third. 
 | 
					 | 
				
			||||||
	const C2 = 2
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// 
 | 
					 | 
				
			||||||
	const (
 | 
					 | 
				
			||||||
		// Single const declarations inside ()'s are considered ungrouped
 | 
					 | 
				
			||||||
		// and show up in sorted order.
 | 
					 | 
				
			||||||
		Cungrouped = 0
 | 
					 | 
				
			||||||
	)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
VARIABLES
 | 
					 | 
				
			||||||
	// VBx variables should appear before VAx variables. 
 | 
					 | 
				
			||||||
	var (
 | 
					 | 
				
			||||||
		VB2	int	// before VB1
 | 
					 | 
				
			||||||
		VB1	int	// before VB0
 | 
					 | 
				
			||||||
		VB0	int	// at end
 | 
					 | 
				
			||||||
	)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// VAx variables should appear after VBx variables. 
 | 
					 | 
				
			||||||
	var (
 | 
					 | 
				
			||||||
		VA2	int	// before VA1
 | 
					 | 
				
			||||||
		VA1	int	// before VA0
 | 
					 | 
				
			||||||
		VA0	int	// at end
 | 
					 | 
				
			||||||
	)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// V0 should be first. 
 | 
					 | 
				
			||||||
	var V0 uintptr
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// V1 should be second. 
 | 
					 | 
				
			||||||
	var V1 uint
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// V2 should be third. 
 | 
					 | 
				
			||||||
	var V2 int
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// 
 | 
					 | 
				
			||||||
	var (
 | 
					 | 
				
			||||||
		// Single var declarations inside ()'s are considered ungrouped
 | 
					 | 
				
			||||||
		// and show up in sorted order.
 | 
					 | 
				
			||||||
		Vungrouped = 0
 | 
					 | 
				
			||||||
	)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
FUNCTIONS
 | 
					 | 
				
			||||||
	// F0 should be first. 
 | 
					 | 
				
			||||||
	func F0()
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// F1 should be second. 
 | 
					 | 
				
			||||||
	func F1()
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// F2 should be third. 
 | 
					 | 
				
			||||||
	func F2()
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
TYPES
 | 
					 | 
				
			||||||
	// T0 should be first. 
 | 
					 | 
				
			||||||
	type T0 struct{}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// T1 should be second. 
 | 
					 | 
				
			||||||
	type T1 struct{}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// T2 should be third. 
 | 
					 | 
				
			||||||
	type T2 struct{}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// TG0 should be first. 
 | 
					 | 
				
			||||||
	type TG0 struct{}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// TG1 should be second. 
 | 
					 | 
				
			||||||
	type TG1 struct{}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// TG2 should be third. 
 | 
					 | 
				
			||||||
	type TG2 struct{}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
							
								
								
									
										57
									
								
								third_party/golang/go/doc/testdata/d1.go
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										57
									
								
								third_party/golang/go/doc/testdata/d1.go
									
									
									
									
										vendored
									
									
								
							@@ -1,57 +0,0 @@
 | 
				
			|||||||
// Copyright 2012 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.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// Test cases for sort order of declarations.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
package d
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// C2 should be third.
 | 
					 | 
				
			||||||
const C2 = 2
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// V2 should be third.
 | 
					 | 
				
			||||||
var V2 int
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// CBx constants should appear before CAx constants.
 | 
					 | 
				
			||||||
const (
 | 
					 | 
				
			||||||
	CB2 = iota // before CB1
 | 
					 | 
				
			||||||
	CB1        // before CB0
 | 
					 | 
				
			||||||
	CB0        // at end
 | 
					 | 
				
			||||||
)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// VBx variables should appear before VAx variables.
 | 
					 | 
				
			||||||
var (
 | 
					 | 
				
			||||||
	VB2 int // before VB1
 | 
					 | 
				
			||||||
	VB1 int // before VB0
 | 
					 | 
				
			||||||
	VB0 int // at end
 | 
					 | 
				
			||||||
)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
const (
 | 
					 | 
				
			||||||
	// Single const declarations inside ()'s are considered ungrouped
 | 
					 | 
				
			||||||
	// and show up in sorted order.
 | 
					 | 
				
			||||||
	Cungrouped = 0
 | 
					 | 
				
			||||||
)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
var (
 | 
					 | 
				
			||||||
	// Single var declarations inside ()'s are considered ungrouped
 | 
					 | 
				
			||||||
	// and show up in sorted order.
 | 
					 | 
				
			||||||
	Vungrouped = 0
 | 
					 | 
				
			||||||
)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// T2 should be third.
 | 
					 | 
				
			||||||
type T2 struct{}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// Grouped types are sorted nevertheless.
 | 
					 | 
				
			||||||
type (
 | 
					 | 
				
			||||||
	// TG2 should be third.
 | 
					 | 
				
			||||||
	TG2 struct{}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// TG1 should be second.
 | 
					 | 
				
			||||||
	TG1 struct{}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// TG0 should be first.
 | 
					 | 
				
			||||||
	TG0 struct{}
 | 
					 | 
				
			||||||
)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// F2 should be third.
 | 
					 | 
				
			||||||
func F2() {}
 | 
					 | 
				
			||||||
							
								
								
									
										45
									
								
								third_party/golang/go/doc/testdata/d2.go
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										45
									
								
								third_party/golang/go/doc/testdata/d2.go
									
									
									
									
										vendored
									
									
								
							@@ -1,45 +0,0 @@
 | 
				
			|||||||
// Copyright 2012 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.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// Test cases for sort order of declarations.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
package d
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// C1 should be second.
 | 
					 | 
				
			||||||
const C1 = 1
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// C0 should be first.
 | 
					 | 
				
			||||||
const C0 = 0
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// V1 should be second.
 | 
					 | 
				
			||||||
var V1 uint
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// V0 should be first.
 | 
					 | 
				
			||||||
var V0 uintptr
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// CAx constants should appear after CBx constants.
 | 
					 | 
				
			||||||
const (
 | 
					 | 
				
			||||||
	CA2 = iota // before CA1
 | 
					 | 
				
			||||||
	CA1        // before CA0
 | 
					 | 
				
			||||||
	CA0        // at end
 | 
					 | 
				
			||||||
)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// VAx variables should appear after VBx variables.
 | 
					 | 
				
			||||||
var (
 | 
					 | 
				
			||||||
	VA2 int // before VA1
 | 
					 | 
				
			||||||
	VA1 int // before VA0
 | 
					 | 
				
			||||||
	VA0 int // at end
 | 
					 | 
				
			||||||
)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// T1 should be second.
 | 
					 | 
				
			||||||
type T1 struct{}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// T0 should be first.
 | 
					 | 
				
			||||||
type T0 struct{}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// F1 should be second.
 | 
					 | 
				
			||||||
func F1() {}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// F0 should be first.
 | 
					 | 
				
			||||||
func F0() {}
 | 
					 | 
				
			||||||
							
								
								
									
										109
									
								
								third_party/golang/go/doc/testdata/e.0.golden
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										109
									
								
								third_party/golang/go/doc/testdata/e.0.golden
									
									
									
									
										vendored
									
									
								
							@@ -1,109 +0,0 @@
 | 
				
			|||||||
// The package e is a go/doc test for embedded methods. 
 | 
					 | 
				
			||||||
PACKAGE e
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
IMPORTPATH
 | 
					 | 
				
			||||||
	testdata/e
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
FILENAMES
 | 
					 | 
				
			||||||
	testdata/e.go
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
TYPES
 | 
					 | 
				
			||||||
	// T1 has no embedded (level 1) M method due to conflict. 
 | 
					 | 
				
			||||||
	type T1 struct {
 | 
					 | 
				
			||||||
		// contains filtered or unexported fields
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// T2 has only M as top-level method. 
 | 
					 | 
				
			||||||
	type T2 struct {
 | 
					 | 
				
			||||||
		// contains filtered or unexported fields
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// T2.M should appear as method of T2. 
 | 
					 | 
				
			||||||
	func (T2) M()
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// T3 has only M as top-level method. 
 | 
					 | 
				
			||||||
	type T3 struct {
 | 
					 | 
				
			||||||
		// contains filtered or unexported fields
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// T3.M should appear as method of T3. 
 | 
					 | 
				
			||||||
	func (T3) M()
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// 
 | 
					 | 
				
			||||||
	type T4 struct{}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// T4.M should appear as method of T5 only if AllMethods is set. 
 | 
					 | 
				
			||||||
	func (*T4) M()
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// 
 | 
					 | 
				
			||||||
	type T5 struct {
 | 
					 | 
				
			||||||
		T4
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// 
 | 
					 | 
				
			||||||
	type U1 struct {
 | 
					 | 
				
			||||||
		*U1
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// U1.M should appear as method of U1. 
 | 
					 | 
				
			||||||
	func (*U1) M()
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// 
 | 
					 | 
				
			||||||
	type U2 struct {
 | 
					 | 
				
			||||||
		*U3
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// U2.M should appear as method of U2 and as method of U3 only if ...
 | 
					 | 
				
			||||||
	func (*U2) M()
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// 
 | 
					 | 
				
			||||||
	type U3 struct {
 | 
					 | 
				
			||||||
		*U2
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// U3.N should appear as method of U3 and as method of U2 only if ...
 | 
					 | 
				
			||||||
	func (*U3) N()
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// 
 | 
					 | 
				
			||||||
	type U4 struct {
 | 
					 | 
				
			||||||
		// contains filtered or unexported fields
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// U4.M should appear as method of U4. 
 | 
					 | 
				
			||||||
	func (*U4) M()
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// 
 | 
					 | 
				
			||||||
	type V1 struct {
 | 
					 | 
				
			||||||
		*V2
 | 
					 | 
				
			||||||
		*V5
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// 
 | 
					 | 
				
			||||||
	type V2 struct {
 | 
					 | 
				
			||||||
		*V3
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// 
 | 
					 | 
				
			||||||
	type V3 struct {
 | 
					 | 
				
			||||||
		*V4
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// 
 | 
					 | 
				
			||||||
	type V4 struct {
 | 
					 | 
				
			||||||
		*V5
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// V4.M should appear as method of V2 and V3 if AllMethods is set. 
 | 
					 | 
				
			||||||
	func (*V4) M()
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// 
 | 
					 | 
				
			||||||
	type V5 struct {
 | 
					 | 
				
			||||||
		*V6
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// 
 | 
					 | 
				
			||||||
	type V6 struct{}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// V6.M should appear as method of V1 and V5 if AllMethods is set. 
 | 
					 | 
				
			||||||
	func (*V6) M()
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
							
								
								
									
										144
									
								
								third_party/golang/go/doc/testdata/e.1.golden
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										144
									
								
								third_party/golang/go/doc/testdata/e.1.golden
									
									
									
									
										vendored
									
									
								
							@@ -1,144 +0,0 @@
 | 
				
			|||||||
// The package e is a go/doc test for embedded methods. 
 | 
					 | 
				
			||||||
PACKAGE e
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
IMPORTPATH
 | 
					 | 
				
			||||||
	testdata/e
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
FILENAMES
 | 
					 | 
				
			||||||
	testdata/e.go
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
TYPES
 | 
					 | 
				
			||||||
	// T1 has no embedded (level 1) M method due to conflict. 
 | 
					 | 
				
			||||||
	type T1 struct {
 | 
					 | 
				
			||||||
		t1
 | 
					 | 
				
			||||||
		t2
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// T2 has only M as top-level method. 
 | 
					 | 
				
			||||||
	type T2 struct {
 | 
					 | 
				
			||||||
		t1
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// T2.M should appear as method of T2. 
 | 
					 | 
				
			||||||
	func (T2) M()
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// T3 has only M as top-level method. 
 | 
					 | 
				
			||||||
	type T3 struct {
 | 
					 | 
				
			||||||
		t1e
 | 
					 | 
				
			||||||
		t2e
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// T3.M should appear as method of T3. 
 | 
					 | 
				
			||||||
	func (T3) M()
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// 
 | 
					 | 
				
			||||||
	type T4 struct{}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// T4.M should appear as method of T5 only if AllMethods is set. 
 | 
					 | 
				
			||||||
	func (*T4) M()
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// 
 | 
					 | 
				
			||||||
	type T5 struct {
 | 
					 | 
				
			||||||
		T4
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// 
 | 
					 | 
				
			||||||
	type U1 struct {
 | 
					 | 
				
			||||||
		*U1
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// U1.M should appear as method of U1. 
 | 
					 | 
				
			||||||
	func (*U1) M()
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// 
 | 
					 | 
				
			||||||
	type U2 struct {
 | 
					 | 
				
			||||||
		*U3
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// U2.M should appear as method of U2 and as method of U3 only if ...
 | 
					 | 
				
			||||||
	func (*U2) M()
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// 
 | 
					 | 
				
			||||||
	type U3 struct {
 | 
					 | 
				
			||||||
		*U2
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// U3.N should appear as method of U3 and as method of U2 only if ...
 | 
					 | 
				
			||||||
	func (*U3) N()
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// 
 | 
					 | 
				
			||||||
	type U4 struct {
 | 
					 | 
				
			||||||
		*u5
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// U4.M should appear as method of U4. 
 | 
					 | 
				
			||||||
	func (*U4) M()
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// 
 | 
					 | 
				
			||||||
	type V1 struct {
 | 
					 | 
				
			||||||
		*V2
 | 
					 | 
				
			||||||
		*V5
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// 
 | 
					 | 
				
			||||||
	type V2 struct {
 | 
					 | 
				
			||||||
		*V3
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// 
 | 
					 | 
				
			||||||
	type V3 struct {
 | 
					 | 
				
			||||||
		*V4
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// 
 | 
					 | 
				
			||||||
	type V4 struct {
 | 
					 | 
				
			||||||
		*V5
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// V4.M should appear as method of V2 and V3 if AllMethods is set. 
 | 
					 | 
				
			||||||
	func (*V4) M()
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// 
 | 
					 | 
				
			||||||
	type V5 struct {
 | 
					 | 
				
			||||||
		*V6
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// 
 | 
					 | 
				
			||||||
	type V6 struct{}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// V6.M should appear as method of V1 and V5 if AllMethods is set. 
 | 
					 | 
				
			||||||
	func (*V6) M()
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// 
 | 
					 | 
				
			||||||
	type t1 struct{}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// t1.M should not appear as method in a Tx type. 
 | 
					 | 
				
			||||||
	func (t1) M()
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// 
 | 
					 | 
				
			||||||
	type t1e struct {
 | 
					 | 
				
			||||||
		t1
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// t1.M should not appear as method in a Tx type. 
 | 
					 | 
				
			||||||
	func (t1e) M()
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// 
 | 
					 | 
				
			||||||
	type t2 struct{}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// t2.M should not appear as method in a Tx type. 
 | 
					 | 
				
			||||||
	func (t2) M()
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// 
 | 
					 | 
				
			||||||
	type t2e struct {
 | 
					 | 
				
			||||||
		t2
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// t2.M should not appear as method in a Tx type. 
 | 
					 | 
				
			||||||
	func (t2e) M()
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// 
 | 
					 | 
				
			||||||
	type u5 struct {
 | 
					 | 
				
			||||||
		*U4
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
							
								
								
									
										130
									
								
								third_party/golang/go/doc/testdata/e.2.golden
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										130
									
								
								third_party/golang/go/doc/testdata/e.2.golden
									
									
									
									
										vendored
									
									
								
							@@ -1,130 +0,0 @@
 | 
				
			|||||||
// The package e is a go/doc test for embedded methods. 
 | 
					 | 
				
			||||||
PACKAGE e
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
IMPORTPATH
 | 
					 | 
				
			||||||
	testdata/e
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
FILENAMES
 | 
					 | 
				
			||||||
	testdata/e.go
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
TYPES
 | 
					 | 
				
			||||||
	// T1 has no embedded (level 1) M method due to conflict. 
 | 
					 | 
				
			||||||
	type T1 struct {
 | 
					 | 
				
			||||||
		// contains filtered or unexported fields
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// T2 has only M as top-level method. 
 | 
					 | 
				
			||||||
	type T2 struct {
 | 
					 | 
				
			||||||
		// contains filtered or unexported fields
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// T2.M should appear as method of T2. 
 | 
					 | 
				
			||||||
	func (T2) M()
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// T3 has only M as top-level method. 
 | 
					 | 
				
			||||||
	type T3 struct {
 | 
					 | 
				
			||||||
		// contains filtered or unexported fields
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// T3.M should appear as method of T3. 
 | 
					 | 
				
			||||||
	func (T3) M()
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// 
 | 
					 | 
				
			||||||
	type T4 struct{}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// T4.M should appear as method of T5 only if AllMethods is set. 
 | 
					 | 
				
			||||||
	func (*T4) M()
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// 
 | 
					 | 
				
			||||||
	type T5 struct {
 | 
					 | 
				
			||||||
		T4
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// T4.M should appear as method of T5 only if AllMethods is set. 
 | 
					 | 
				
			||||||
	func (*T5) M()
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// 
 | 
					 | 
				
			||||||
	type U1 struct {
 | 
					 | 
				
			||||||
		*U1
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// U1.M should appear as method of U1. 
 | 
					 | 
				
			||||||
	func (*U1) M()
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// 
 | 
					 | 
				
			||||||
	type U2 struct {
 | 
					 | 
				
			||||||
		*U3
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// U2.M should appear as method of U2 and as method of U3 only if ...
 | 
					 | 
				
			||||||
	func (*U2) M()
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// U3.N should appear as method of U3 and as method of U2 only if ...
 | 
					 | 
				
			||||||
	func (U2) N()
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// 
 | 
					 | 
				
			||||||
	type U3 struct {
 | 
					 | 
				
			||||||
		*U2
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// U2.M should appear as method of U2 and as method of U3 only if ...
 | 
					 | 
				
			||||||
	func (U3) M()
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// U3.N should appear as method of U3 and as method of U2 only if ...
 | 
					 | 
				
			||||||
	func (*U3) N()
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// 
 | 
					 | 
				
			||||||
	type U4 struct {
 | 
					 | 
				
			||||||
		// contains filtered or unexported fields
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// U4.M should appear as method of U4. 
 | 
					 | 
				
			||||||
	func (*U4) M()
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// 
 | 
					 | 
				
			||||||
	type V1 struct {
 | 
					 | 
				
			||||||
		*V2
 | 
					 | 
				
			||||||
		*V5
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// V6.M should appear as method of V1 and V5 if AllMethods is set. 
 | 
					 | 
				
			||||||
	func (V1) M()
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// 
 | 
					 | 
				
			||||||
	type V2 struct {
 | 
					 | 
				
			||||||
		*V3
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// V4.M should appear as method of V2 and V3 if AllMethods is set. 
 | 
					 | 
				
			||||||
	func (V2) M()
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// 
 | 
					 | 
				
			||||||
	type V3 struct {
 | 
					 | 
				
			||||||
		*V4
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// V4.M should appear as method of V2 and V3 if AllMethods is set. 
 | 
					 | 
				
			||||||
	func (V3) M()
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// 
 | 
					 | 
				
			||||||
	type V4 struct {
 | 
					 | 
				
			||||||
		*V5
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// V4.M should appear as method of V2 and V3 if AllMethods is set. 
 | 
					 | 
				
			||||||
	func (*V4) M()
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// 
 | 
					 | 
				
			||||||
	type V5 struct {
 | 
					 | 
				
			||||||
		*V6
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// V6.M should appear as method of V1 and V5 if AllMethods is set. 
 | 
					 | 
				
			||||||
	func (V5) M()
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// 
 | 
					 | 
				
			||||||
	type V6 struct{}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// V6.M should appear as method of V1 and V5 if AllMethods is set. 
 | 
					 | 
				
			||||||
	func (*V6) M()
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
							
								
								
									
										147
									
								
								third_party/golang/go/doc/testdata/e.go
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										147
									
								
								third_party/golang/go/doc/testdata/e.go
									
									
									
									
										vendored
									
									
								
							@@ -1,147 +0,0 @@
 | 
				
			|||||||
// Copyright 2012 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.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// The package e is a go/doc test for embedded methods.
 | 
					 | 
				
			||||||
package e
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// ----------------------------------------------------------------------------
 | 
					 | 
				
			||||||
// Conflicting methods M must not show up.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
type t1 struct{}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// t1.M should not appear as method in a Tx type.
 | 
					 | 
				
			||||||
func (t1) M() {}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
type t2 struct{}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// t2.M should not appear as method in a Tx type.
 | 
					 | 
				
			||||||
func (t2) M() {}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// T1 has no embedded (level 1) M method due to conflict.
 | 
					 | 
				
			||||||
type T1 struct {
 | 
					 | 
				
			||||||
	t1
 | 
					 | 
				
			||||||
	t2
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// ----------------------------------------------------------------------------
 | 
					 | 
				
			||||||
// Higher-level method M wins over lower-level method M.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// T2 has only M as top-level method.
 | 
					 | 
				
			||||||
type T2 struct {
 | 
					 | 
				
			||||||
	t1
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// T2.M should appear as method of T2.
 | 
					 | 
				
			||||||
func (T2) M() {}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// ----------------------------------------------------------------------------
 | 
					 | 
				
			||||||
// Higher-level method M wins over lower-level conflicting methods M.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
type t1e struct {
 | 
					 | 
				
			||||||
	t1
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
type t2e struct {
 | 
					 | 
				
			||||||
	t2
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// T3 has only M as top-level method.
 | 
					 | 
				
			||||||
type T3 struct {
 | 
					 | 
				
			||||||
	t1e
 | 
					 | 
				
			||||||
	t2e
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// T3.M should appear as method of T3.
 | 
					 | 
				
			||||||
func (T3) M() {}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// ----------------------------------------------------------------------------
 | 
					 | 
				
			||||||
// Don't show conflicting methods M embedded via an exported and non-exported
 | 
					 | 
				
			||||||
// type.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// T1 has no embedded (level 1) M method due to conflict.
 | 
					 | 
				
			||||||
type T4 struct {
 | 
					 | 
				
			||||||
	t2
 | 
					 | 
				
			||||||
	T2
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// ----------------------------------------------------------------------------
 | 
					 | 
				
			||||||
// Don't show embedded methods of exported anonymous fields unless AllMethods
 | 
					 | 
				
			||||||
// is set.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
type T4 struct{}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// T4.M should appear as method of T5 only if AllMethods is set.
 | 
					 | 
				
			||||||
func (*T4) M() {}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
type T5 struct {
 | 
					 | 
				
			||||||
	T4
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// ----------------------------------------------------------------------------
 | 
					 | 
				
			||||||
// Recursive type declarations must not lead to endless recursion.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
type U1 struct {
 | 
					 | 
				
			||||||
	*U1
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// U1.M should appear as method of U1.
 | 
					 | 
				
			||||||
func (*U1) M() {}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
type U2 struct {
 | 
					 | 
				
			||||||
	*U3
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// U2.M should appear as method of U2 and as method of U3 only if AllMethods is set.
 | 
					 | 
				
			||||||
func (*U2) M() {}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
type U3 struct {
 | 
					 | 
				
			||||||
	*U2
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// U3.N should appear as method of U3 and as method of U2 only if AllMethods is set.
 | 
					 | 
				
			||||||
func (*U3) N() {}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
type U4 struct {
 | 
					 | 
				
			||||||
	*u5
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// U4.M should appear as method of U4.
 | 
					 | 
				
			||||||
func (*U4) M() {}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
type u5 struct {
 | 
					 | 
				
			||||||
	*U4
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// ----------------------------------------------------------------------------
 | 
					 | 
				
			||||||
// A higher-level embedded type (and its methods) wins over the same type (and
 | 
					 | 
				
			||||||
// its methods) embedded at a lower level.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
type V1 struct {
 | 
					 | 
				
			||||||
	*V2
 | 
					 | 
				
			||||||
	*V5
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
type V2 struct {
 | 
					 | 
				
			||||||
	*V3
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
type V3 struct {
 | 
					 | 
				
			||||||
	*V4
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
type V4 struct {
 | 
					 | 
				
			||||||
	*V5
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
type V5 struct {
 | 
					 | 
				
			||||||
	*V6
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
type V6 struct{}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// V4.M should appear as method of V2 and V3 if AllMethods is set.
 | 
					 | 
				
			||||||
func (*V4) M() {}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// V6.M should appear as method of V1 and V5 if AllMethods is set.
 | 
					 | 
				
			||||||
func (*V6) M() {}
 | 
					 | 
				
			||||||
@@ -1,30 +0,0 @@
 | 
				
			|||||||
// 
 | 
					 | 
				
			||||||
PACKAGE error1
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
IMPORTPATH
 | 
					 | 
				
			||||||
	testdata/error1
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
FILENAMES
 | 
					 | 
				
			||||||
	testdata/error1.go
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
TYPES
 | 
					 | 
				
			||||||
	// 
 | 
					 | 
				
			||||||
	type I0 interface {
 | 
					 | 
				
			||||||
		// When embedded, the predeclared error interface
 | 
					 | 
				
			||||||
		// must remain visible in interface types.
 | 
					 | 
				
			||||||
		error
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// 
 | 
					 | 
				
			||||||
	type S0 struct {
 | 
					 | 
				
			||||||
		// contains filtered or unexported fields
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// 
 | 
					 | 
				
			||||||
	type T0 struct {
 | 
					 | 
				
			||||||
		ExportedField interface {
 | 
					 | 
				
			||||||
			// error should be visible
 | 
					 | 
				
			||||||
			error
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
@@ -1,32 +0,0 @@
 | 
				
			|||||||
// 
 | 
					 | 
				
			||||||
PACKAGE error1
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
IMPORTPATH
 | 
					 | 
				
			||||||
	testdata/error1
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
FILENAMES
 | 
					 | 
				
			||||||
	testdata/error1.go
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
TYPES
 | 
					 | 
				
			||||||
	// 
 | 
					 | 
				
			||||||
	type I0 interface {
 | 
					 | 
				
			||||||
		// When embedded, the predeclared error interface
 | 
					 | 
				
			||||||
		// must remain visible in interface types.
 | 
					 | 
				
			||||||
		error
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// 
 | 
					 | 
				
			||||||
	type S0 struct {
 | 
					 | 
				
			||||||
		// In struct types, an embedded error must only be visible
 | 
					 | 
				
			||||||
		// if AllDecls is set.
 | 
					 | 
				
			||||||
		error
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// 
 | 
					 | 
				
			||||||
	type T0 struct {
 | 
					 | 
				
			||||||
		ExportedField interface {
 | 
					 | 
				
			||||||
			// error should be visible
 | 
					 | 
				
			||||||
			error
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
Some files were not shown because too many files have changed in this diff Show More
		Reference in New Issue
	
	Block a user