// 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 rename import ( "go/ast" "go/token" "go/types" "os" "path/filepath" "reflect" "runtime" "strings" "unicode" "golang.org/x/tools/go/ast/astutil" ) func objectKind(obj types.Object) string { switch obj := obj.(type) { case *types.PkgName: return "imported package name" case *types.TypeName: return "type" case *types.Var: if obj.IsField() { return "field" } case *types.Func: if obj.Type().(*types.Signature).Recv() != nil { return "method" } } // label, func, var, const return strings.ToLower(strings.TrimPrefix(reflect.TypeOf(obj).String(), "*types.")) } func typeKind(T types.Type) string { return strings.ToLower(strings.TrimPrefix(reflect.TypeOf(T.Underlying()).String(), "*types.")) } // NB: for renamings, blank is not considered valid. func isValidIdentifier(id string) bool { if id == "" || id == "_" { return false } for i, r := range id { if !isLetter(r) && (i == 0 || !isDigit(r)) { return false } } return token.Lookup(id) == token.IDENT } // isLocal reports whether obj is local to some function. // Precondition: not a struct field or interface method. func isLocal(obj types.Object) bool { // [... 5=stmt 4=func 3=file 2=pkg 1=universe] var depth int for scope := obj.Parent(); scope != nil; scope = scope.Parent() { depth++ } return depth >= 4 } func isPackageLevel(obj types.Object) bool { return obj.Pkg().Scope().Lookup(obj.Name()) == obj } // -- Plundered from go/scanner: --------------------------------------- func isLetter(ch rune) bool { return 'a' <= ch && ch <= 'z' || 'A' <= ch && ch <= 'Z' || ch == '_' || ch >= 0x80 && unicode.IsLetter(ch) } func isDigit(ch rune) bool { return '0' <= ch && ch <= '9' || ch >= 0x80 && unicode.IsDigit(ch) } // -- Plundered from golang.org/x/tools/cmd/guru ----------------- // sameFile returns true if x and y have the same basename and denote // the same file. // func sameFile(x, y string) bool { if runtime.GOOS == "windows" { x = filepath.ToSlash(x) y = filepath.ToSlash(y) } if x == y { return true } if filepath.Base(x) == filepath.Base(y) { // (optimisation) if xi, err := os.Stat(x); err == nil { if yi, err := os.Stat(y); err == nil { return os.SameFile(xi, yi) } } } return false } func unparen(e ast.Expr) ast.Expr { return astutil.Unparen(e) }