func (c *funcContext) varPtrName(o *types.Var) string { if isPkgLevel(o) && o.Exported() { return c.pkgVar(o.Pkg()) + "." + o.Name() + "$ptr" } name, ok := c.p.varPtrNames[o] if !ok { name = c.newVariableWithLevel(o.Name()+"$ptr", isPkgLevel(o)) c.p.varPtrNames[o] = name } return name }
func (p *exporter) field(f *types.Var) { // anonymous fields have "" name name := "" if !f.Anonymous() { name = f.Name() } // qualifiedName will always emit the field package for // anonymous fields because "" is not an exported name. p.qualifiedName(f.Pkg(), name) p.typ(f.Type()) }
func (tr *Transformer) matchWildcard(xobj *types.Var, y ast.Expr) bool { name := xobj.Name() if tr.verbose { fmt.Fprintf(os.Stderr, "%s: wildcard %s -> %s?: ", tr.fset.Position(y.Pos()), name, astString(tr.fset, y)) } // Check that y is assignable to the declared type of the param. yt := tr.info.TypeOf(y) if yt == nil { // y has no type. // Perhaps it is an *ast.Ellipsis in [...]T{}, or // an *ast.KeyValueExpr in T{k: v}. // Clearly these pseudo-expressions cannot match a // wildcard, but it would nice if we had a way to ignore // the difference between T{v} and T{k:v} for structs. return false } if !types.AssignableTo(yt, xobj.Type()) { if tr.verbose { fmt.Fprintf(os.Stderr, "%s not assignable to %s\n", yt, xobj.Type()) } return false } // A wildcard matches any expression. // If it appears multiple times in the pattern, it must match // the same expression each time. if old, ok := tr.env[name]; ok { // found existing binding tr.allowWildcards = false r := tr.matchExpr(old, y) if tr.verbose { fmt.Fprintf(os.Stderr, "%t secondary match, primary was %s\n", r, astString(tr.fset, old)) } tr.allowWildcards = true return r } if tr.verbose { fmt.Fprintf(os.Stderr, "primary match\n") } tr.env[name] = y // record binding return true }
func (tr *Transformer) matchWildcard(xobj *types.Var, y ast.Expr) bool { name := xobj.Name() if tr.verbose { fmt.Fprintf(os.Stderr, "%s: wildcard %s -> %s?: ", tr.fset.Position(y.Pos()), name, astString(tr.fset, y)) } // Check that y is assignable to the declared type of the param. if yt := tr.info.TypeOf(y); !types.AssignableTo(yt, xobj.Type()) { if tr.verbose { fmt.Fprintf(os.Stderr, "%s not assignable to %s\n", yt, xobj.Type()) } return false } // A wildcard matches any expression. // If it appears multiple times in the pattern, it must match // the same expression each time. if old, ok := tr.env[name]; ok { // found existing binding tr.allowWildcards = false r := tr.matchExpr(old, y) if tr.verbose { fmt.Fprintf(os.Stderr, "%t secondary match, primary was %s\n", r, astString(tr.fset, old)) } tr.allowWildcards = true return r } if tr.verbose { fmt.Fprintf(os.Stderr, "primary match\n") } tr.env[name] = y // record binding return true }
// checkStructField checks that the field renaming will not cause // conflicts at its declaration, or ambiguity or changes to any selection. func (r *Unexporter) checkStructField(objsToUpdate map[types.Object]string, from *types.Var, to string) { // Check that the struct declaration is free of field conflicts, // and field/method conflicts. // go/types offers no easy way to get from a field (or interface // method) to its declaring struct (or interface), so we must // ascend the AST. info, path, _ := r.iprog.PathEnclosingInterval(from.Pos(), from.Pos()) // path matches this pattern: // [Ident SelectorExpr? StarExpr? Field FieldList StructType ParenExpr* ... File] // Ascend to FieldList. var i int for { if _, ok := path[i].(*ast.FieldList); ok { break } i++ } i++ tStruct := path[i].(*ast.StructType) i++ // Ascend past parens (unlikely). for { _, ok := path[i].(*ast.ParenExpr) if !ok { break } i++ } if spec, ok := path[i].(*ast.TypeSpec); ok { // This struct is also a named type. // We must check for direct (non-promoted) field/field // and method/field conflicts. named := info.Defs[spec.Name].Type() prev, indices, _ := types.LookupFieldOrMethod(named, true, info.Pkg, to) if len(indices) == 1 { r.warn(from, r.errorf(from.Pos(), "renaming this field %q to %q", from.Name(), to), r.errorf(prev.Pos(), "\twould conflict with this %s", objectKind(prev))) return // skip checkSelections to avoid redundant errors } } else { // This struct is not a named type. // We need only check for direct (non-promoted) field/field conflicts. t := info.Types[tStruct].Type.Underlying().(*types.Struct) for i := 0; i < t.NumFields(); i++ { if prev := t.Field(i); prev.Name() == to { r.warn(from, r.errorf(from.Pos(), "renaming this field %q to %q", from.Name(), to), r.errorf(prev.Pos(), "\twould conflict with this field")) return // skip checkSelections to avoid redundant errors } } } // Renaming an anonymous field requires renaming the type too. e.g. // print(s.T) // if we rename T to U, // type T int // this and // var s struct {T} // this must change too. if from.Anonymous() { if named, ok := from.Type().(*types.Named); ok { r.check(objsToUpdate, named.Obj(), to) } else if named, ok := deref(from.Type()).(*types.Named); ok { r.check(objsToUpdate, named.Obj(), to) } } // Check integrity of existing (field and method) selections. r.checkSelections(objsToUpdate, from, to) }
func newVarFrom(p *Package, v *types.Var) *Var { return newVar(p, v.Type(), v.Name(), v.Name(), p.getDoc("", v)) }
func (p *exporter) param(v *types.Var) { p.string(v.Name()) p.typ(v.Type()) }