mirror of
https://github.com/golang/go.git
synced 2025-12-08 06:10:04 +00:00
various: avoid func compare
R=gri, r, bradfitz CC=golang-dev https://golang.org/cl/5371074
This commit is contained in:
parent
c017a8299f
commit
558e7fc332
9 changed files with 136 additions and 107 deletions
|
|
@ -34,7 +34,7 @@ func addTestCases(t []testCase, fn func(*ast.File) bool) {
|
||||||
|
|
||||||
func fnop(*ast.File) bool { return false }
|
func fnop(*ast.File) bool { return false }
|
||||||
|
|
||||||
func parseFixPrint(t *testing.T, fn func(*ast.File) bool, desc, in string) (out string, fixed, ok bool) {
|
func parseFixPrint(t *testing.T, fn func(*ast.File) bool, desc, in string, mustBeGofmt bool) (out string, fixed, ok bool) {
|
||||||
file, err := parser.ParseFile(fset, desc, in, parserMode)
|
file, err := parser.ParseFile(fset, desc, in, parserMode)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf("%s: parsing: %v", desc, err)
|
t.Errorf("%s: parsing: %v", desc, err)
|
||||||
|
|
@ -46,7 +46,7 @@ func parseFixPrint(t *testing.T, fn func(*ast.File) bool, desc, in string) (out
|
||||||
t.Errorf("%s: printing: %v", desc, err)
|
t.Errorf("%s: printing: %v", desc, err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if s := string(outb); in != s && fn != fnop {
|
if s := string(outb); in != s && mustBeGofmt {
|
||||||
t.Errorf("%s: not gofmt-formatted.\n--- %s\n%s\n--- %s | gofmt\n%s",
|
t.Errorf("%s: not gofmt-formatted.\n--- %s\n%s\n--- %s | gofmt\n%s",
|
||||||
desc, desc, in, desc, s)
|
desc, desc, in, desc, s)
|
||||||
tdiff(t, in, s)
|
tdiff(t, in, s)
|
||||||
|
|
@ -75,13 +75,13 @@ func parseFixPrint(t *testing.T, fn func(*ast.File) bool, desc, in string) (out
|
||||||
func TestRewrite(t *testing.T) {
|
func TestRewrite(t *testing.T) {
|
||||||
for _, tt := range testCases {
|
for _, tt := range testCases {
|
||||||
// Apply fix: should get tt.Out.
|
// Apply fix: should get tt.Out.
|
||||||
out, fixed, ok := parseFixPrint(t, tt.Fn, tt.Name, tt.In)
|
out, fixed, ok := parseFixPrint(t, tt.Fn, tt.Name, tt.In, true)
|
||||||
if !ok {
|
if !ok {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
// reformat to get printing right
|
// reformat to get printing right
|
||||||
out, _, ok = parseFixPrint(t, fnop, tt.Name, out)
|
out, _, ok = parseFixPrint(t, fnop, tt.Name, out, false)
|
||||||
if !ok {
|
if !ok {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
@ -101,7 +101,7 @@ func TestRewrite(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Should not change if run again.
|
// Should not change if run again.
|
||||||
out2, fixed2, ok := parseFixPrint(t, tt.Fn, tt.Name+" output", out)
|
out2, fixed2, ok := parseFixPrint(t, tt.Fn, tt.Name+" output", out, true)
|
||||||
if !ok {
|
if !ok {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -138,6 +138,7 @@ func typecheck(cfg *TypeConfig, f *ast.File) (typeof map[interface{}]string, ass
|
||||||
assign = make(map[string][]interface{})
|
assign = make(map[string][]interface{})
|
||||||
cfg1 := &TypeConfig{}
|
cfg1 := &TypeConfig{}
|
||||||
*cfg1 = *cfg // make copy so we can add locally
|
*cfg1 = *cfg // make copy so we can add locally
|
||||||
|
copied := false
|
||||||
|
|
||||||
// gather function declarations
|
// gather function declarations
|
||||||
for _, decl := range f.Decls {
|
for _, decl := range f.Decls {
|
||||||
|
|
@ -185,7 +186,8 @@ func typecheck(cfg *TypeConfig, f *ast.File) (typeof map[interface{}]string, ass
|
||||||
if cfg1.Type[s.Name.Name] != nil {
|
if cfg1.Type[s.Name.Name] != nil {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
if cfg1.Type == cfg.Type || cfg1.Type == nil {
|
if !copied {
|
||||||
|
copied = true
|
||||||
// Copy map lazily: it's time.
|
// Copy map lazily: it's time.
|
||||||
cfg1.Type = make(map[string]*Type)
|
cfg1.Type = make(map[string]*Type)
|
||||||
for k, v := range cfg.Type {
|
for k, v := range cfg.Type {
|
||||||
|
|
|
||||||
|
|
@ -662,48 +662,49 @@ func TestRunes(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
type TrimTest struct {
|
type TrimTest struct {
|
||||||
f func([]byte, string) []byte
|
f string
|
||||||
in, cutset, out string
|
in, cutset, out string
|
||||||
}
|
}
|
||||||
|
|
||||||
var trimTests = []TrimTest{
|
var trimTests = []TrimTest{
|
||||||
{Trim, "abba", "a", "bb"},
|
{"Trim", "abba", "a", "bb"},
|
||||||
{Trim, "abba", "ab", ""},
|
{"Trim", "abba", "ab", ""},
|
||||||
{TrimLeft, "abba", "ab", ""},
|
{"TrimLeft", "abba", "ab", ""},
|
||||||
{TrimRight, "abba", "ab", ""},
|
{"TrimRight", "abba", "ab", ""},
|
||||||
{TrimLeft, "abba", "a", "bba"},
|
{"TrimLeft", "abba", "a", "bba"},
|
||||||
{TrimRight, "abba", "a", "abb"},
|
{"TrimRight", "abba", "a", "abb"},
|
||||||
{Trim, "<tag>", "<>", "tag"},
|
{"Trim", "<tag>", "<>", "tag"},
|
||||||
{Trim, "* listitem", " *", "listitem"},
|
{"Trim", "* listitem", " *", "listitem"},
|
||||||
{Trim, `"quote"`, `"`, "quote"},
|
{"Trim", `"quote"`, `"`, "quote"},
|
||||||
{Trim, "\u2C6F\u2C6F\u0250\u0250\u2C6F\u2C6F", "\u2C6F", "\u0250\u0250"},
|
{"Trim", "\u2C6F\u2C6F\u0250\u0250\u2C6F\u2C6F", "\u2C6F", "\u0250\u0250"},
|
||||||
//empty string tests
|
//empty string tests
|
||||||
{Trim, "abba", "", "abba"},
|
{"Trim", "abba", "", "abba"},
|
||||||
{Trim, "", "123", ""},
|
{"Trim", "", "123", ""},
|
||||||
{Trim, "", "", ""},
|
{"Trim", "", "", ""},
|
||||||
{TrimLeft, "abba", "", "abba"},
|
{"TrimLeft", "abba", "", "abba"},
|
||||||
{TrimLeft, "", "123", ""},
|
{"TrimLeft", "", "123", ""},
|
||||||
{TrimLeft, "", "", ""},
|
{"TrimLeft", "", "", ""},
|
||||||
{TrimRight, "abba", "", "abba"},
|
{"TrimRight", "abba", "", "abba"},
|
||||||
{TrimRight, "", "123", ""},
|
{"TrimRight", "", "123", ""},
|
||||||
{TrimRight, "", "", ""},
|
{"TrimRight", "", "", ""},
|
||||||
{TrimRight, "☺\xc0", "☺", "☺\xc0"},
|
{"TrimRight", "☺\xc0", "☺", "☺\xc0"},
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestTrim(t *testing.T) {
|
func TestTrim(t *testing.T) {
|
||||||
for _, tc := range trimTests {
|
for _, tc := range trimTests {
|
||||||
actual := string(tc.f([]byte(tc.in), tc.cutset))
|
name := tc.f
|
||||||
var name string
|
var f func([]byte, string) []byte
|
||||||
switch tc.f {
|
switch name {
|
||||||
case Trim:
|
case "Trim":
|
||||||
name = "Trim"
|
f = Trim
|
||||||
case TrimLeft:
|
case "TrimLeft":
|
||||||
name = "TrimLeft"
|
f = TrimLeft
|
||||||
case TrimRight:
|
case "TrimRight":
|
||||||
name = "TrimRight"
|
f = TrimRight
|
||||||
default:
|
default:
|
||||||
t.Error("Undefined trim function")
|
t.Error("Undefined trim function %s", name)
|
||||||
}
|
}
|
||||||
|
actual := string(f([]byte(tc.in), tc.cutset))
|
||||||
if actual != tc.out {
|
if actual != tc.out {
|
||||||
t.Errorf("%s(%q, %q) = %q; want %q", name, tc.in, tc.cutset, actual, tc.out)
|
t.Errorf("%s(%q, %q) = %q; want %q", name, tc.in, tc.cutset, actual, tc.out)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -48,8 +48,9 @@ const (
|
||||||
type encoder struct {
|
type encoder struct {
|
||||||
// w is the writer that compressed bytes are written to.
|
// w is the writer that compressed bytes are written to.
|
||||||
w writer
|
w writer
|
||||||
// write, bits, nBits and width are the state for converting a code stream
|
// order, write, bits, nBits and width are the state for
|
||||||
// into a byte stream.
|
// converting a code stream into a byte stream.
|
||||||
|
order Order
|
||||||
write func(*encoder, uint32) error
|
write func(*encoder, uint32) error
|
||||||
bits uint32
|
bits uint32
|
||||||
nBits uint
|
nBits uint
|
||||||
|
|
@ -213,7 +214,7 @@ func (e *encoder) Close() error {
|
||||||
}
|
}
|
||||||
// Write the final bits.
|
// Write the final bits.
|
||||||
if e.nBits > 0 {
|
if e.nBits > 0 {
|
||||||
if e.write == (*encoder).writeMSB {
|
if e.order == MSB {
|
||||||
e.bits >>= 24
|
e.bits >>= 24
|
||||||
}
|
}
|
||||||
if err := e.w.WriteByte(uint8(e.bits)); err != nil {
|
if err := e.w.WriteByte(uint8(e.bits)); err != nil {
|
||||||
|
|
@ -249,6 +250,7 @@ func NewWriter(w io.Writer, order Order, litWidth int) io.WriteCloser {
|
||||||
lw := uint(litWidth)
|
lw := uint(litWidth)
|
||||||
return &encoder{
|
return &encoder{
|
||||||
w: bw,
|
w: bw,
|
||||||
|
order: order,
|
||||||
write: write,
|
write: write,
|
||||||
width: 1 + lw,
|
width: 1 + lw,
|
||||||
litWidth: lw,
|
litWidth: lw,
|
||||||
|
|
|
||||||
|
|
@ -227,7 +227,7 @@ func (d *decodeState) value(v reflect.Value) {
|
||||||
// d.scan thinks we're still at the beginning of the item.
|
// d.scan thinks we're still at the beginning of the item.
|
||||||
// Feed in an empty string - the shortest, simplest value -
|
// Feed in an empty string - the shortest, simplest value -
|
||||||
// so that it knows we got to the end of the value.
|
// so that it knows we got to the end of the value.
|
||||||
if d.scan.step == stateRedo {
|
if d.scan.redo {
|
||||||
panic("redo")
|
panic("redo")
|
||||||
}
|
}
|
||||||
d.scan.step(&d.scan, '"')
|
d.scan.step(&d.scan, '"')
|
||||||
|
|
|
||||||
|
|
@ -80,6 +80,9 @@ type scanner struct {
|
||||||
// on a 64-bit Mac Mini, and it's nicer to read.
|
// on a 64-bit Mac Mini, and it's nicer to read.
|
||||||
step func(*scanner, int) int
|
step func(*scanner, int) int
|
||||||
|
|
||||||
|
// Reached end of top-level value.
|
||||||
|
endTop bool
|
||||||
|
|
||||||
// Stack of what we're in the middle of - array values, object keys, object values.
|
// Stack of what we're in the middle of - array values, object keys, object values.
|
||||||
parseState []int
|
parseState []int
|
||||||
|
|
||||||
|
|
@ -87,6 +90,7 @@ type scanner struct {
|
||||||
err error
|
err error
|
||||||
|
|
||||||
// 1-byte redo (see undo method)
|
// 1-byte redo (see undo method)
|
||||||
|
redo bool
|
||||||
redoCode int
|
redoCode int
|
||||||
redoState func(*scanner, int) int
|
redoState func(*scanner, int) int
|
||||||
|
|
||||||
|
|
@ -135,6 +139,8 @@ func (s *scanner) reset() {
|
||||||
s.step = stateBeginValue
|
s.step = stateBeginValue
|
||||||
s.parseState = s.parseState[0:0]
|
s.parseState = s.parseState[0:0]
|
||||||
s.err = nil
|
s.err = nil
|
||||||
|
s.redo = false
|
||||||
|
s.endTop = false
|
||||||
}
|
}
|
||||||
|
|
||||||
// eof tells the scanner that the end of input has been reached.
|
// eof tells the scanner that the end of input has been reached.
|
||||||
|
|
@ -143,11 +149,11 @@ func (s *scanner) eof() int {
|
||||||
if s.err != nil {
|
if s.err != nil {
|
||||||
return scanError
|
return scanError
|
||||||
}
|
}
|
||||||
if s.step == stateEndTop {
|
if s.endTop {
|
||||||
return scanEnd
|
return scanEnd
|
||||||
}
|
}
|
||||||
s.step(s, ' ')
|
s.step(s, ' ')
|
||||||
if s.step == stateEndTop {
|
if s.endTop {
|
||||||
return scanEnd
|
return scanEnd
|
||||||
}
|
}
|
||||||
if s.err == nil {
|
if s.err == nil {
|
||||||
|
|
@ -166,8 +172,10 @@ func (s *scanner) pushParseState(p int) {
|
||||||
func (s *scanner) popParseState() {
|
func (s *scanner) popParseState() {
|
||||||
n := len(s.parseState) - 1
|
n := len(s.parseState) - 1
|
||||||
s.parseState = s.parseState[0:n]
|
s.parseState = s.parseState[0:n]
|
||||||
|
s.redo = false
|
||||||
if n == 0 {
|
if n == 0 {
|
||||||
s.step = stateEndTop
|
s.step = stateEndTop
|
||||||
|
s.endTop = true
|
||||||
} else {
|
} else {
|
||||||
s.step = stateEndValue
|
s.step = stateEndValue
|
||||||
}
|
}
|
||||||
|
|
@ -269,6 +277,7 @@ func stateEndValue(s *scanner, c int) int {
|
||||||
if n == 0 {
|
if n == 0 {
|
||||||
// Completed top-level before the current byte.
|
// Completed top-level before the current byte.
|
||||||
s.step = stateEndTop
|
s.step = stateEndTop
|
||||||
|
s.endTop = true
|
||||||
return stateEndTop(s, c)
|
return stateEndTop(s, c)
|
||||||
}
|
}
|
||||||
if c <= ' ' && (c == ' ' || c == '\t' || c == '\r' || c == '\n') {
|
if c <= ' ' && (c == ' ' || c == '\t' || c == '\r' || c == '\n') {
|
||||||
|
|
@ -606,16 +615,18 @@ func quoteChar(c int) string {
|
||||||
// undo causes the scanner to return scanCode from the next state transition.
|
// undo causes the scanner to return scanCode from the next state transition.
|
||||||
// This gives callers a simple 1-byte undo mechanism.
|
// This gives callers a simple 1-byte undo mechanism.
|
||||||
func (s *scanner) undo(scanCode int) {
|
func (s *scanner) undo(scanCode int) {
|
||||||
if s.step == stateRedo {
|
if s.redo {
|
||||||
panic("invalid use of scanner")
|
panic("json: invalid use of scanner")
|
||||||
}
|
}
|
||||||
s.redoCode = scanCode
|
s.redoCode = scanCode
|
||||||
s.redoState = s.step
|
s.redoState = s.step
|
||||||
s.step = stateRedo
|
s.step = stateRedo
|
||||||
|
s.redo = true
|
||||||
}
|
}
|
||||||
|
|
||||||
// stateRedo helps implement the scanner's 1-byte undo.
|
// stateRedo helps implement the scanner's 1-byte undo.
|
||||||
func stateRedo(s *scanner, c int) int {
|
func stateRedo(s *scanner, c int) int {
|
||||||
|
s.redo = false
|
||||||
s.step = s.redoState
|
s.step = s.redoState
|
||||||
return s.redoCode
|
return s.redoCode
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -24,7 +24,7 @@ func exportFilter(name string) bool {
|
||||||
// it returns false otherwise.
|
// it returns false otherwise.
|
||||||
//
|
//
|
||||||
func FileExports(src *File) bool {
|
func FileExports(src *File) bool {
|
||||||
return FilterFile(src, exportFilter)
|
return filterFile(src, exportFilter, true)
|
||||||
}
|
}
|
||||||
|
|
||||||
// PackageExports trims the AST for a Go package in place such that
|
// PackageExports trims the AST for a Go package in place such that
|
||||||
|
|
@ -35,7 +35,7 @@ func FileExports(src *File) bool {
|
||||||
// it returns false otherwise.
|
// it returns false otherwise.
|
||||||
//
|
//
|
||||||
func PackageExports(pkg *Package) bool {
|
func PackageExports(pkg *Package) bool {
|
||||||
return FilterPackage(pkg, exportFilter)
|
return filterPackage(pkg, exportFilter, true)
|
||||||
}
|
}
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
|
|
@ -72,7 +72,7 @@ func fieldName(x Expr) *Ident {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func filterFieldList(fields *FieldList, filter Filter) (removedFields bool) {
|
func filterFieldList(fields *FieldList, filter Filter, export bool) (removedFields bool) {
|
||||||
if fields == nil {
|
if fields == nil {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
@ -93,8 +93,8 @@ func filterFieldList(fields *FieldList, filter Filter) (removedFields bool) {
|
||||||
keepField = len(f.Names) > 0
|
keepField = len(f.Names) > 0
|
||||||
}
|
}
|
||||||
if keepField {
|
if keepField {
|
||||||
if filter == exportFilter {
|
if export {
|
||||||
filterType(f.Type, filter)
|
filterType(f.Type, filter, export)
|
||||||
}
|
}
|
||||||
list[j] = f
|
list[j] = f
|
||||||
j++
|
j++
|
||||||
|
|
@ -107,84 +107,84 @@ func filterFieldList(fields *FieldList, filter Filter) (removedFields bool) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func filterParamList(fields *FieldList, filter Filter) bool {
|
func filterParamList(fields *FieldList, filter Filter, export bool) bool {
|
||||||
if fields == nil {
|
if fields == nil {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
var b bool
|
var b bool
|
||||||
for _, f := range fields.List {
|
for _, f := range fields.List {
|
||||||
if filterType(f.Type, filter) {
|
if filterType(f.Type, filter, export) {
|
||||||
b = true
|
b = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return b
|
return b
|
||||||
}
|
}
|
||||||
|
|
||||||
func filterType(typ Expr, f Filter) bool {
|
func filterType(typ Expr, f Filter, export bool) bool {
|
||||||
switch t := typ.(type) {
|
switch t := typ.(type) {
|
||||||
case *Ident:
|
case *Ident:
|
||||||
return f(t.Name)
|
return f(t.Name)
|
||||||
case *ParenExpr:
|
case *ParenExpr:
|
||||||
return filterType(t.X, f)
|
return filterType(t.X, f, export)
|
||||||
case *ArrayType:
|
case *ArrayType:
|
||||||
return filterType(t.Elt, f)
|
return filterType(t.Elt, f, export)
|
||||||
case *StructType:
|
case *StructType:
|
||||||
if filterFieldList(t.Fields, f) {
|
if filterFieldList(t.Fields, f, export) {
|
||||||
t.Incomplete = true
|
t.Incomplete = true
|
||||||
}
|
}
|
||||||
return len(t.Fields.List) > 0
|
return len(t.Fields.List) > 0
|
||||||
case *FuncType:
|
case *FuncType:
|
||||||
b1 := filterParamList(t.Params, f)
|
b1 := filterParamList(t.Params, f, export)
|
||||||
b2 := filterParamList(t.Results, f)
|
b2 := filterParamList(t.Results, f, export)
|
||||||
return b1 || b2
|
return b1 || b2
|
||||||
case *InterfaceType:
|
case *InterfaceType:
|
||||||
if filterFieldList(t.Methods, f) {
|
if filterFieldList(t.Methods, f, export) {
|
||||||
t.Incomplete = true
|
t.Incomplete = true
|
||||||
}
|
}
|
||||||
return len(t.Methods.List) > 0
|
return len(t.Methods.List) > 0
|
||||||
case *MapType:
|
case *MapType:
|
||||||
b1 := filterType(t.Key, f)
|
b1 := filterType(t.Key, f, export)
|
||||||
b2 := filterType(t.Value, f)
|
b2 := filterType(t.Value, f, export)
|
||||||
return b1 || b2
|
return b1 || b2
|
||||||
case *ChanType:
|
case *ChanType:
|
||||||
return filterType(t.Value, f)
|
return filterType(t.Value, f, export)
|
||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
func filterSpec(spec Spec, f Filter) bool {
|
func filterSpec(spec Spec, f Filter, export bool) bool {
|
||||||
switch s := spec.(type) {
|
switch s := spec.(type) {
|
||||||
case *ValueSpec:
|
case *ValueSpec:
|
||||||
s.Names = filterIdentList(s.Names, f)
|
s.Names = filterIdentList(s.Names, f)
|
||||||
if len(s.Names) > 0 {
|
if len(s.Names) > 0 {
|
||||||
if f == exportFilter {
|
if export {
|
||||||
filterType(s.Type, f)
|
filterType(s.Type, f, export)
|
||||||
}
|
}
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
case *TypeSpec:
|
case *TypeSpec:
|
||||||
if f(s.Name.Name) {
|
if f(s.Name.Name) {
|
||||||
if f == exportFilter {
|
if export {
|
||||||
filterType(s.Type, f)
|
filterType(s.Type, f, export)
|
||||||
}
|
}
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
if f != exportFilter {
|
if !export {
|
||||||
// For general filtering (not just exports),
|
// For general filtering (not just exports),
|
||||||
// filter type even if name is not filtered
|
// filter type even if name is not filtered
|
||||||
// out.
|
// out.
|
||||||
// If the type contains filtered elements,
|
// If the type contains filtered elements,
|
||||||
// keep the declaration.
|
// keep the declaration.
|
||||||
return filterType(s.Type, f)
|
return filterType(s.Type, f, export)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
func filterSpecList(list []Spec, f Filter) []Spec {
|
func filterSpecList(list []Spec, f Filter, export bool) []Spec {
|
||||||
j := 0
|
j := 0
|
||||||
for _, s := range list {
|
for _, s := range list {
|
||||||
if filterSpec(s, f) {
|
if filterSpec(s, f, export) {
|
||||||
list[j] = s
|
list[j] = s
|
||||||
j++
|
j++
|
||||||
}
|
}
|
||||||
|
|
@ -200,9 +200,13 @@ func filterSpecList(list []Spec, f Filter) []Spec {
|
||||||
// filtering; it returns false otherwise.
|
// filtering; it returns false otherwise.
|
||||||
//
|
//
|
||||||
func FilterDecl(decl Decl, f Filter) bool {
|
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) {
|
switch d := decl.(type) {
|
||||||
case *GenDecl:
|
case *GenDecl:
|
||||||
d.Specs = filterSpecList(d.Specs, f)
|
d.Specs = filterSpecList(d.Specs, f, export)
|
||||||
return len(d.Specs) > 0
|
return len(d.Specs) > 0
|
||||||
case *FuncDecl:
|
case *FuncDecl:
|
||||||
return f(d.Name.Name)
|
return f(d.Name.Name)
|
||||||
|
|
@ -221,9 +225,13 @@ func FilterDecl(decl Decl, f Filter) bool {
|
||||||
// left after filtering; it returns false otherwise.
|
// left after filtering; it returns false otherwise.
|
||||||
//
|
//
|
||||||
func FilterFile(src *File, f Filter) bool {
|
func FilterFile(src *File, f Filter) bool {
|
||||||
|
return filterFile(src, f, false)
|
||||||
|
}
|
||||||
|
|
||||||
|
func filterFile(src *File, f Filter, export bool) bool {
|
||||||
j := 0
|
j := 0
|
||||||
for _, d := range src.Decls {
|
for _, d := range src.Decls {
|
||||||
if FilterDecl(d, f) {
|
if filterDecl(d, f, export) {
|
||||||
src.Decls[j] = d
|
src.Decls[j] = d
|
||||||
j++
|
j++
|
||||||
}
|
}
|
||||||
|
|
@ -244,9 +252,13 @@ func FilterFile(src *File, f Filter) bool {
|
||||||
// left after filtering; it returns false otherwise.
|
// left after filtering; it returns false otherwise.
|
||||||
//
|
//
|
||||||
func FilterPackage(pkg *Package, f Filter) bool {
|
func FilterPackage(pkg *Package, f Filter) bool {
|
||||||
|
return filterPackage(pkg, f, false)
|
||||||
|
}
|
||||||
|
|
||||||
|
func filterPackage(pkg *Package, f Filter, export bool) bool {
|
||||||
hasDecls := false
|
hasDecls := false
|
||||||
for _, src := range pkg.Files {
|
for _, src := range pkg.Files {
|
||||||
if FilterFile(src, f) {
|
if filterFile(src, f, export) {
|
||||||
hasDecls = true
|
hasDecls = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,7 @@ package net
|
||||||
var supportsIPv6, supportsIPv4map = probeIPv6Stack()
|
var supportsIPv6, supportsIPv4map = probeIPv6Stack()
|
||||||
|
|
||||||
func firstFavoriteAddr(filter func(IP) IP, addrs []string) (addr IP) {
|
func firstFavoriteAddr(filter func(IP) IP, addrs []string) (addr IP) {
|
||||||
if filter == anyaddr {
|
if filter == nil {
|
||||||
// We'll take any IP address, but since the dialing code
|
// We'll take any IP address, but since the dialing code
|
||||||
// does not yet try multiple addresses, prefer to use
|
// does not yet try multiple addresses, prefer to use
|
||||||
// an IPv4 address if possible. This is especially relevant
|
// an IPv4 address if possible. This is especially relevant
|
||||||
|
|
@ -113,7 +113,7 @@ func hostPortToIP(net, hostport string) (ip IP, iport int, err error) {
|
||||||
// Try as an IP address.
|
// Try as an IP address.
|
||||||
addr = ParseIP(host)
|
addr = ParseIP(host)
|
||||||
if addr == nil {
|
if addr == nil {
|
||||||
filter := anyaddr
|
var filter func(IP) IP
|
||||||
if net != "" && net[len(net)-1] == '4' {
|
if net != "" && net[len(net)-1] == '4' {
|
||||||
filter = ipv4only
|
filter = ipv4only
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -489,46 +489,47 @@ func TestSpecialCase(t *testing.T) {
|
||||||
func TestTrimSpace(t *testing.T) { runStringTests(t, TrimSpace, "TrimSpace", trimSpaceTests) }
|
func TestTrimSpace(t *testing.T) { runStringTests(t, TrimSpace, "TrimSpace", trimSpaceTests) }
|
||||||
|
|
||||||
var trimTests = []struct {
|
var trimTests = []struct {
|
||||||
f func(string, string) string
|
f string
|
||||||
in, cutset, out string
|
in, cutset, out string
|
||||||
}{
|
}{
|
||||||
{Trim, "abba", "a", "bb"},
|
{"Trim", "abba", "a", "bb"},
|
||||||
{Trim, "abba", "ab", ""},
|
{"Trim", "abba", "ab", ""},
|
||||||
{TrimLeft, "abba", "ab", ""},
|
{"TrimLeft", "abba", "ab", ""},
|
||||||
{TrimRight, "abba", "ab", ""},
|
{"TrimRight", "abba", "ab", ""},
|
||||||
{TrimLeft, "abba", "a", "bba"},
|
{"TrimLeft", "abba", "a", "bba"},
|
||||||
{TrimRight, "abba", "a", "abb"},
|
{"TrimRight", "abba", "a", "abb"},
|
||||||
{Trim, "<tag>", "<>", "tag"},
|
{"Trim", "<tag>", "<>", "tag"},
|
||||||
{Trim, "* listitem", " *", "listitem"},
|
{"Trim", "* listitem", " *", "listitem"},
|
||||||
{Trim, `"quote"`, `"`, "quote"},
|
{"Trim", `"quote"`, `"`, "quote"},
|
||||||
{Trim, "\u2C6F\u2C6F\u0250\u0250\u2C6F\u2C6F", "\u2C6F", "\u0250\u0250"},
|
{"Trim", "\u2C6F\u2C6F\u0250\u0250\u2C6F\u2C6F", "\u2C6F", "\u0250\u0250"},
|
||||||
//empty string tests
|
//empty string tests
|
||||||
{Trim, "abba", "", "abba"},
|
{"Trim", "abba", "", "abba"},
|
||||||
{Trim, "", "123", ""},
|
{"Trim", "", "123", ""},
|
||||||
{Trim, "", "", ""},
|
{"Trim", "", "", ""},
|
||||||
{TrimLeft, "abba", "", "abba"},
|
{"TrimLeft", "abba", "", "abba"},
|
||||||
{TrimLeft, "", "123", ""},
|
{"TrimLeft", "", "123", ""},
|
||||||
{TrimLeft, "", "", ""},
|
{"TrimLeft", "", "", ""},
|
||||||
{TrimRight, "abba", "", "abba"},
|
{"TrimRight", "abba", "", "abba"},
|
||||||
{TrimRight, "", "123", ""},
|
{"TrimRight", "", "123", ""},
|
||||||
{TrimRight, "", "", ""},
|
{"TrimRight", "", "", ""},
|
||||||
{TrimRight, "☺\xc0", "☺", "☺\xc0"},
|
{"TrimRight", "☺\xc0", "☺", "☺\xc0"},
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestTrim(t *testing.T) {
|
func TestTrim(t *testing.T) {
|
||||||
for _, tc := range trimTests {
|
for _, tc := range trimTests {
|
||||||
actual := tc.f(tc.in, tc.cutset)
|
name := tc.f
|
||||||
var name string
|
var f func(string, string) string
|
||||||
switch tc.f {
|
switch name {
|
||||||
case Trim:
|
case "Trim":
|
||||||
name = "Trim"
|
f = Trim
|
||||||
case TrimLeft:
|
case "TrimLeft":
|
||||||
name = "TrimLeft"
|
f = TrimLeft
|
||||||
case TrimRight:
|
case "TrimRight":
|
||||||
name = "TrimRight"
|
f = TrimRight
|
||||||
default:
|
default:
|
||||||
t.Error("Undefined trim function")
|
t.Error("Undefined trim function %s", name)
|
||||||
}
|
}
|
||||||
|
actual := f(tc.in, tc.cutset)
|
||||||
if actual != tc.out {
|
if actual != tc.out {
|
||||||
t.Errorf("%s(%q, %q) = %q; want %q", name, tc.in, tc.cutset, actual, tc.out)
|
t.Errorf("%s(%q, %q) = %q; want %q", name, tc.in, tc.cutset, actual, tc.out)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue