github.com/zebozhuang/go@v0.0.0-20200207033046-f8a98f6f5c5d/src/go/types/ordering.go (about) 1 // Copyright 2014 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 // This file implements resolveOrder. 6 7 package types 8 9 import ( 10 "go/ast" 11 "sort" 12 ) 13 14 // resolveOrder computes the order in which package-level objects 15 // must be type-checked. 16 // 17 // Interface types appear first in the list, sorted topologically 18 // by dependencies on embedded interfaces that are also declared 19 // in this package, followed by all other objects sorted in source 20 // order. 21 // 22 // TODO(gri) Consider sorting all types by dependencies here, and 23 // in the process check _and_ report type cycles. This may simplify 24 // the full type-checking phase. 25 // 26 func (check *Checker) resolveOrder() []Object { 27 var ifaces, others []Object 28 29 // collect interface types with their dependencies, and all other objects 30 for obj := range check.objMap { 31 if ityp := check.interfaceFor(obj); ityp != nil { 32 ifaces = append(ifaces, obj) 33 // determine dependencies on embedded interfaces 34 for _, f := range ityp.Methods.List { 35 if len(f.Names) == 0 { 36 // Embedded interface: The type must be a (possibly 37 // qualified) identifier denoting another interface. 38 // Imported interfaces are already fully resolved, 39 // so we can ignore qualified identifiers. 40 if ident, _ := f.Type.(*ast.Ident); ident != nil { 41 embedded := check.pkg.scope.Lookup(ident.Name) 42 if check.interfaceFor(embedded) != nil { 43 check.objMap[obj].addDep(embedded) 44 } 45 } 46 } 47 } 48 } else { 49 others = append(others, obj) 50 } 51 } 52 53 // final object order 54 var order []Object 55 56 // sort interface types topologically by dependencies, 57 // and in source order if there are no dependencies 58 sort.Sort(inSourceOrder(ifaces)) 59 visited := make(objSet) 60 for _, obj := range ifaces { 61 check.appendInPostOrder(&order, obj, visited) 62 } 63 64 // sort everything else in source order 65 sort.Sort(inSourceOrder(others)) 66 67 return append(order, others...) 68 } 69 70 // interfaceFor returns the AST interface denoted by obj, or nil. 71 func (check *Checker) interfaceFor(obj Object) *ast.InterfaceType { 72 tname, _ := obj.(*TypeName) 73 if tname == nil { 74 return nil // not a type 75 } 76 d := check.objMap[obj] 77 if d == nil { 78 check.dump("%s: %s should have been declared", obj.Pos(), obj.Name()) 79 unreachable() 80 } 81 if d.typ == nil { 82 return nil // invalid AST - ignore (will be handled later) 83 } 84 ityp, _ := d.typ.(*ast.InterfaceType) 85 return ityp 86 } 87 88 func (check *Checker) appendInPostOrder(order *[]Object, obj Object, visited objSet) { 89 if visited[obj] { 90 // We've already seen this object; either because it's 91 // already added to order, or because we have a cycle. 92 // In both cases we stop. Cycle errors are reported 93 // when type-checking types. 94 return 95 } 96 visited[obj] = true 97 98 d := check.objMap[obj] 99 for _, obj := range orderedSetObjects(d.deps) { 100 check.appendInPostOrder(order, obj, visited) 101 } 102 103 *order = append(*order, obj) 104 } 105 106 func orderedSetObjects(set objSet) []Object { 107 list := make([]Object, len(set)) 108 i := 0 109 for obj := range set { 110 // we don't care about the map element value 111 list[i] = obj 112 i++ 113 } 114 sort.Sort(inSourceOrder(list)) 115 return list 116 } 117 118 // inSourceOrder implements the sort.Sort interface. 119 type inSourceOrder []Object 120 121 func (a inSourceOrder) Len() int { return len(a) } 122 func (a inSourceOrder) Less(i, j int) bool { return a[i].order() < a[j].order() } 123 func (a inSourceOrder) Swap(i, j int) { a[i], a[j] = a[j], a[i] }