github.com/q45/go@v0.0.0-20151101211701-a4fb8c13db3f/src/go/types/api.go (about) 1 // Copyright 2012 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 // Package types declares the data types and implements 6 // the algorithms for type-checking of Go packages. Use 7 // Config.Check to invoke the type checker for a package. 8 // Alternatively, create a new type checked with NewChecker 9 // and invoke it incrementally by calling Checker.Files. 10 // 11 // Type-checking consists of several interdependent phases: 12 // 13 // Name resolution maps each identifier (ast.Ident) in the program to the 14 // language object (Object) it denotes. 15 // Use Info.{Defs,Uses,Implicits} for the results of name resolution. 16 // 17 // Constant folding computes the exact constant value (constant.Value) 18 // for every expression (ast.Expr) that is a compile-time constant. 19 // Use Info.Types[expr].Value for the results of constant folding. 20 // 21 // Type inference computes the type (Type) of every expression (ast.Expr) 22 // and checks for compliance with the language specification. 23 // Use Info.Types[expr].Type for the results of type inference. 24 // 25 package types // import "go/types" 26 27 import ( 28 "bytes" 29 "fmt" 30 "go/ast" 31 "go/constant" 32 "go/token" 33 ) 34 35 // An Error describes a type-checking error; it implements the error interface. 36 // A "soft" error is an error that still permits a valid interpretation of a 37 // package (such as "unused variable"); "hard" errors may lead to unpredictable 38 // behavior if ignored. 39 type Error struct { 40 Fset *token.FileSet // file set for interpretation of Pos 41 Pos token.Pos // error position 42 Msg string // error message 43 Soft bool // if set, error is "soft" 44 } 45 46 // Error returns an error string formatted as follows: 47 // filename:line:column: message 48 func (err Error) Error() string { 49 return fmt.Sprintf("%s: %s", err.Fset.Position(err.Pos), err.Msg) 50 } 51 52 // An importer resolves import paths to Packages. 53 // See go/importer for existing implementations. 54 type Importer interface { 55 // Import returns the imported package for the given import 56 // path, or an error if the package couldn't be imported. 57 // Import is responsible for returning the same package for 58 // matching import paths. 59 Import(path string) (*Package, error) 60 } 61 62 // A Config specifies the configuration for type checking. 63 // The zero value for Config is a ready-to-use default configuration. 64 type Config struct { 65 // If IgnoreFuncBodies is set, function bodies are not 66 // type-checked. 67 IgnoreFuncBodies bool 68 69 // If FakeImportC is set, `import "C"` (for packages requiring Cgo) 70 // declares an empty "C" package and errors are omitted for qualified 71 // identifiers referring to package C (which won't find an object). 72 // This feature is intended for the standard library cmd/api tool. 73 // 74 // Caution: Effects may be unpredictable due to follow-up errors. 75 // Do not use casually! 76 FakeImportC bool 77 78 // If Error != nil, it is called with each error found 79 // during type checking; err has dynamic type Error. 80 // Secondary errors (for instance, to enumerate all types 81 // involved in an invalid recursive type declaration) have 82 // error strings that start with a '\t' character. 83 // If Error == nil, type-checking stops with the first 84 // error found. 85 Error func(err error) 86 87 // Importer is called for each import declaration except when 88 // importing package "unsafe". An error is reported if an 89 // importer is needed but none was installed. 90 Importer Importer 91 92 // If Sizes != nil, it provides the sizing functions for package unsafe. 93 // Otherwise &StdSizes{WordSize: 8, MaxAlign: 8} is used instead. 94 Sizes Sizes 95 96 // If DisableUnusedImportCheck is set, packages are not checked 97 // for unused imports. 98 DisableUnusedImportCheck bool 99 } 100 101 // Info holds result type information for a type-checked package. 102 // Only the information for which a map is provided is collected. 103 // If the package has type errors, the collected information may 104 // be incomplete. 105 type Info struct { 106 // Types maps expressions to their types, and for constant 107 // expressions, their values. Invalid expressions are omitted. 108 // 109 // For (possibly parenthesized) identifiers denoting built-in 110 // functions, the recorded signatures are call-site specific: 111 // if the call result is not a constant, the recorded type is 112 // an argument-specific signature. Otherwise, the recorded type 113 // is invalid. 114 // 115 // Identifiers on the lhs of declarations (i.e., the identifiers 116 // which are being declared) are collected in the Defs map. 117 // Identifiers denoting packages are collected in the Uses maps. 118 Types map[ast.Expr]TypeAndValue 119 120 // Defs maps identifiers to the objects they define (including 121 // package names, dots "." of dot-imports, and blank "_" identifiers). 122 // For identifiers that do not denote objects (e.g., the package name 123 // in package clauses, or symbolic variables t in t := x.(type) of 124 // type switch headers), the corresponding objects are nil. 125 // 126 // For an anonymous field, Defs returns the field *Var it defines. 127 // 128 // Invariant: Defs[id] == nil || Defs[id].Pos() == id.Pos() 129 Defs map[*ast.Ident]Object 130 131 // Uses maps identifiers to the objects they denote. 132 // 133 // For an anonymous field, Uses returns the *TypeName it denotes. 134 // 135 // Invariant: Uses[id].Pos() != id.Pos() 136 Uses map[*ast.Ident]Object 137 138 // Implicits maps nodes to their implicitly declared objects, if any. 139 // The following node and object types may appear: 140 // 141 // node declared object 142 // 143 // *ast.ImportSpec *PkgName for dot-imports and imports without renames 144 // *ast.CaseClause type-specific *Var for each type switch case clause (incl. default) 145 // *ast.Field anonymous parameter *Var 146 // 147 Implicits map[ast.Node]Object 148 149 // Selections maps selector expressions (excluding qualified identifiers) 150 // to their corresponding selections. 151 Selections map[*ast.SelectorExpr]*Selection 152 153 // Scopes maps ast.Nodes to the scopes they define. Package scopes are not 154 // associated with a specific node but with all files belonging to a package. 155 // Thus, the package scope can be found in the type-checked Package object. 156 // Scopes nest, with the Universe scope being the outermost scope, enclosing 157 // the package scope, which contains (one or more) files scopes, which enclose 158 // function scopes which in turn enclose statement and function literal scopes. 159 // Note that even though package-level functions are declared in the package 160 // scope, the function scopes are embedded in the file scope of the file 161 // containing the function declaration. 162 // 163 // The following node types may appear in Scopes: 164 // 165 // *ast.File 166 // *ast.FuncType 167 // *ast.BlockStmt 168 // *ast.IfStmt 169 // *ast.SwitchStmt 170 // *ast.TypeSwitchStmt 171 // *ast.CaseClause 172 // *ast.CommClause 173 // *ast.ForStmt 174 // *ast.RangeStmt 175 // 176 Scopes map[ast.Node]*Scope 177 178 // InitOrder is the list of package-level initializers in the order in which 179 // they must be executed. Initializers referring to variables related by an 180 // initialization dependency appear in topological order, the others appear 181 // in source order. Variables without an initialization expression do not 182 // appear in this list. 183 InitOrder []*Initializer 184 } 185 186 // TypeOf returns the type of expression e, or nil if not found. 187 // Precondition: the Types, Uses and Defs maps are populated. 188 // 189 func (info *Info) TypeOf(e ast.Expr) Type { 190 if t, ok := info.Types[e]; ok { 191 return t.Type 192 } 193 if id, _ := e.(*ast.Ident); id != nil { 194 if obj := info.ObjectOf(id); obj != nil { 195 return obj.Type() 196 } 197 } 198 return nil 199 } 200 201 // ObjectOf returns the object denoted by the specified id, 202 // or nil if not found. 203 // 204 // If id is an anonymous struct field, ObjectOf returns the field (*Var) 205 // it uses, not the type (*TypeName) it defines. 206 // 207 // Precondition: the Uses and Defs maps are populated. 208 // 209 func (info *Info) ObjectOf(id *ast.Ident) Object { 210 if obj, _ := info.Defs[id]; obj != nil { 211 return obj 212 } 213 return info.Uses[id] 214 } 215 216 // TypeAndValue reports the type and value (for constants) 217 // of the corresponding expression. 218 type TypeAndValue struct { 219 mode operandMode 220 Type Type 221 Value constant.Value 222 } 223 224 // TODO(gri) Consider eliminating the IsVoid predicate. Instead, report 225 // "void" values as regular values but with the empty tuple type. 226 227 // IsVoid reports whether the corresponding expression 228 // is a function call without results. 229 func (tv TypeAndValue) IsVoid() bool { 230 return tv.mode == novalue 231 } 232 233 // IsType reports whether the corresponding expression specifies a type. 234 func (tv TypeAndValue) IsType() bool { 235 return tv.mode == typexpr 236 } 237 238 // IsBuiltin reports whether the corresponding expression denotes 239 // a (possibly parenthesized) built-in function. 240 func (tv TypeAndValue) IsBuiltin() bool { 241 return tv.mode == builtin 242 } 243 244 // IsValue reports whether the corresponding expression is a value. 245 // Builtins are not considered values. Constant values have a non- 246 // nil Value. 247 func (tv TypeAndValue) IsValue() bool { 248 switch tv.mode { 249 case constant_, variable, mapindex, value, commaok: 250 return true 251 } 252 return false 253 } 254 255 // IsNil reports whether the corresponding expression denotes the 256 // predeclared value nil. 257 func (tv TypeAndValue) IsNil() bool { 258 return tv.mode == value && tv.Type == Typ[UntypedNil] 259 } 260 261 // Addressable reports whether the corresponding expression 262 // is addressable (https://golang.org/ref/spec#Address_operators). 263 func (tv TypeAndValue) Addressable() bool { 264 return tv.mode == variable 265 } 266 267 // Assignable reports whether the corresponding expression 268 // is assignable to (provided a value of the right type). 269 func (tv TypeAndValue) Assignable() bool { 270 return tv.mode == variable || tv.mode == mapindex 271 } 272 273 // HasOk reports whether the corresponding expression may be 274 // used on the lhs of a comma-ok assignment. 275 func (tv TypeAndValue) HasOk() bool { 276 return tv.mode == commaok || tv.mode == mapindex 277 } 278 279 // An Initializer describes a package-level variable, or a list of variables in case 280 // of a multi-valued initialization expression, and the corresponding initialization 281 // expression. 282 type Initializer struct { 283 Lhs []*Var // var Lhs = Rhs 284 Rhs ast.Expr 285 } 286 287 func (init *Initializer) String() string { 288 var buf bytes.Buffer 289 for i, lhs := range init.Lhs { 290 if i > 0 { 291 buf.WriteString(", ") 292 } 293 buf.WriteString(lhs.Name()) 294 } 295 buf.WriteString(" = ") 296 WriteExpr(&buf, init.Rhs) 297 return buf.String() 298 } 299 300 // Check type-checks a package and returns the resulting package object and 301 // the first error if any. Additionally, if info != nil, Check populates each 302 // of the non-nil maps in the Info struct. 303 // 304 // The package is marked as complete if no errors occurred, otherwise it is 305 // incomplete. See Config.Error for controlling behavior in the presence of 306 // errors. 307 // 308 // The package is specified by a list of *ast.Files and corresponding 309 // file set, and the package path the package is identified with. 310 // The clean path must not be empty or dot ("."). 311 func (conf *Config) Check(path string, fset *token.FileSet, files []*ast.File, info *Info) (*Package, error) { 312 pkg := NewPackage(path, "") 313 return pkg, NewChecker(conf, fset, pkg, info).Files(files) 314 } 315 316 // AssertableTo reports whether a value of type V can be asserted to have type T. 317 func AssertableTo(V *Interface, T Type) bool { 318 m, _ := assertableTo(V, T) 319 return m == nil 320 } 321 322 // AssignableTo reports whether a value of type V is assignable to a variable of type T. 323 func AssignableTo(V, T Type) bool { 324 x := operand{mode: value, typ: V} 325 return x.assignableTo(nil, T, nil) // config not needed for non-constant x 326 } 327 328 // ConvertibleTo reports whether a value of type V is convertible to a value of type T. 329 func ConvertibleTo(V, T Type) bool { 330 x := operand{mode: value, typ: V} 331 return x.convertibleTo(nil, T) // config not needed for non-constant x 332 } 333 334 // Implements reports whether type V implements interface T. 335 func Implements(V Type, T *Interface) bool { 336 f, _ := MissingMethod(V, T, true) 337 return f == nil 338 }