| // 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/token" | |
| "go/types" | |
| "os" | |
| "path/filepath" | |
| "reflect" | |
| "runtime" | |
| "strings" | |
| "unicode" | |
| ) | |
| func objectKind(obj types.Object) string { | |
| switch obj := obj.(type) { | |
| case *types.PkgName: | |
| return "imported package name" | |
| case *types.TypeName: // defined type | alias | type parameter | |
| return "type" | |
| case *types.Var: | |
| if obj.IsField() { | |
| return "field" | |
| } | |
| case *types.Func: | |
| if obj.Signature().Recv() != nil { | |
| return "method" | |
| } | |
| } | |
| // label, func, var, const | |
| return strings.ToLower(strings.TrimPrefix(reflect.TypeOf(obj).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 | |
| } | |
| // -- 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 is[T any](x any) bool { | |
| _, ok := x.(T) | |
| return ok | |
| } |