github.com/Johnny2210/revive@v1.0.8-0.20210625134200-febf37ccd0f5/lint/utils.go (about) 1 package lint 2 3 import ( 4 "strings" 5 "unicode" 6 ) 7 8 // Name returns a different name if it should be different. 9 func Name(name string, whitelist, blacklist []string) (should string) { 10 // Fast path for simple cases: "_" and all lowercase. 11 if name == "_" { 12 return name 13 } 14 allLower := true 15 for _, r := range name { 16 if !unicode.IsLower(r) { 17 allLower = false 18 break 19 } 20 } 21 if allLower { 22 return name 23 } 24 25 // Split camelCase at any lower->upper transition, and split on underscores. 26 // Check each word for common initialisms. 27 runes := []rune(name) 28 w, i := 0, 0 // index of start of word, scan 29 for i+1 <= len(runes) { 30 eow := false // whether we hit the end of a word 31 if i+1 == len(runes) { 32 eow = true 33 } else if runes[i+1] == '_' { 34 // underscore; shift the remainder forward over any run of underscores 35 eow = true 36 n := 1 37 for i+n+1 < len(runes) && runes[i+n+1] == '_' { 38 n++ 39 } 40 41 // Leave at most one underscore if the underscore is between two digits 42 if i+n+1 < len(runes) && unicode.IsDigit(runes[i]) && unicode.IsDigit(runes[i+n+1]) { 43 n-- 44 } 45 46 copy(runes[i+1:], runes[i+n+1:]) 47 runes = runes[:len(runes)-n] 48 } else if unicode.IsLower(runes[i]) && !unicode.IsLower(runes[i+1]) { 49 // lower->non-lower 50 eow = true 51 } 52 i++ 53 if !eow { 54 continue 55 } 56 57 // [w,i) is a word. 58 word := string(runes[w:i]) 59 ignoreInitWarnings := map[string]bool{} 60 for _, i := range whitelist { 61 ignoreInitWarnings[i] = true 62 } 63 64 extraInits := map[string]bool{} 65 for _, i := range blacklist { 66 extraInits[i] = true 67 } 68 69 if u := strings.ToUpper(word); (commonInitialisms[u] || extraInits[u]) && !ignoreInitWarnings[u] { 70 // Keep consistent case, which is lowercase only at the start. 71 if w == 0 && unicode.IsLower(runes[w]) { 72 u = strings.ToLower(u) 73 } 74 // All the common initialisms are ASCII, 75 // so we can replace the bytes exactly. 76 copy(runes[w:], []rune(u)) 77 } else if w > 0 && strings.ToLower(word) == word { 78 // already all lowercase, and not the first word, so uppercase the first character. 79 runes[w] = unicode.ToUpper(runes[w]) 80 } 81 w = i 82 } 83 return string(runes) 84 } 85 86 // commonInitialisms is a set of common initialisms. 87 // Only add entries that are highly unlikely to be non-initialisms. 88 // For instance, "ID" is fine (Freudian code is rare), but "AND" is not. 89 var commonInitialisms = map[string]bool{ 90 "ACL": true, 91 "API": true, 92 "ASCII": true, 93 "CPU": true, 94 "CSS": true, 95 "DNS": true, 96 "EOF": true, 97 "GUID": true, 98 "HTML": true, 99 "HTTP": true, 100 "HTTPS": true, 101 "ID": true, 102 "IP": true, 103 "JSON": true, 104 "LHS": true, 105 "QPS": true, 106 "RAM": true, 107 "RHS": true, 108 "RPC": true, 109 "SLA": true, 110 "SMTP": true, 111 "SQL": true, 112 "SSH": true, 113 "TCP": true, 114 "TLS": true, 115 "TTL": true, 116 "UDP": true, 117 "UI": true, 118 "UID": true, 119 "UUID": true, 120 "URI": true, 121 "URL": true, 122 "UTF8": true, 123 "VM": true, 124 "XML": true, 125 "XMPP": true, 126 "XSRF": true, 127 "XSS": true, 128 }