github.com/99designs/gqlgen@v0.17.45/docs/content/reference/name-collision.md (about) 1 --- 2 title: Handling type naming collisions 3 description: Examples of logic used to avoid type name collision 4 linkTitle: Name Collision 5 menu: { main: { parent: 'reference', weight: 10 }} 6 --- 7 8 While most generated Golang types must have unique names by virtue of being based on their GraphQL `type` counterpart, 9 which themselves must be unique, there are a few edge scenarios where conflicts can occur. This document describes 10 how those collisions are handled. 11 12 ## Enum Constants 13 14 Enum type generation is a prime example of where naming collisions can occur, as we build the const names per value 15 as a composite of the Enum name and each individual value. 16 17 ### Example Problem 18 19 Currently, enum types are transposed as such: 20 21 ```graphql 22 # graphql 23 24 enum MyEnum { 25 value1 26 value2 27 value3 28 value4 29 } 30 ``` 31 32 Which will result in the following Golang: 33 34 ```go 35 // golang 36 37 type MyEnum string 38 39 const ( 40 MyEnumValue1 MyEnum = "value1" 41 MyEnumValue2 MyEnum = "value2" 42 MyEnumValue3 MyEnum = "value3" 43 MyEnumValue4 MyEnum = "value4" 44 ) 45 ``` 46 47 However, those above enum values are just strings. What if you encounter a scenario where the following is 48 necessary: 49 50 ```graphql 51 # graphql 52 53 enum MyEnum { 54 value1 55 value2 56 value3 57 value4 58 Value4 59 Value_4 60 } 61 ``` 62 63 The `Value4` and `Value_4` enum values cannot be directly transposed into the same "pretty" naming convention as their 64 resulting constant names would conflict with the name for `value4`, as so: 65 66 ```go 67 // golang 68 69 type MyEnum string 70 71 const ( 72 MyEnumValue1 MyEnum = "value1" 73 MyEnumValue2 MyEnum = "value2" 74 MyEnumValue3 MyEnum = "value3" 75 MyEnumValue4 MyEnum = "value4" 76 MyEnumValue4 MyEnum = "Value4" 77 MyEnumValue4 MyEnum = "Value_4" 78 ) 79 ``` 80 81 Which immediately leads to compilation errors as we now have three constants with the same name, but different values. 82 83 ### Resolution 84 85 1. Store each name generated as part of a run for later comparison 86 2. Try to coerce name into `CapitalCase`. Use if no conflicts. 87 - This process attempts to break apart identifiers into "words", identified by separating on capital letters, 88 underscores, hyphens, and spaces. 89 - Each "word" is capitalized and appended to previous word. 90 3. If non-composite name, append integer to end of name, starting at 0 and going to `math.MaxInt` 91 4. If composite name, in reverse order, the pieces of the name have a less opinionated converter applied 92 5. If all else fails, append integer to end of name, starting at 0 and going to `math.MaxInt` 93 94 The first step to produce a name that does not conflict with an existing name succeeds. 95 96 ## Examples 97 98 ### Example A 99 GraphQL: 100 ```graphql 101 # graphql 102 103 enum MyEnum { 104 Value 105 value 106 TitleValue 107 title_value 108 } 109 ``` 110 Go: 111 ```go 112 // golang 113 114 type MyEnum string 115 116 const ( 117 MyEnumValue MyEnum = "Value" 118 MyEnumvalue MyEnum = "value" 119 MyEnumTitleValue MyEnum = "TitleValue" 120 MyEnumtitle_value MyEnum = "title_value" 121 ) 122 ``` 123 124 ### Example B 125 GraphQL: 126 ```graphql 127 # graphql 128 129 enum MyEnum { 130 TitleValue 131 title_value 132 title_Value 133 Title_Value 134 } 135 ``` 136 Go: 137 ```go 138 // golang 139 140 type MyEnum string 141 142 const ( 143 MyEnumTitleValue MyEnum = "TitleValue" 144 MyEnumtitle_value MyEnum = "title_value" 145 MyEnumtitle_Value MyEnum = "title_Value" 146 MyEnumTitle_Value MyEnum = "Title_Value" 147 ) 148 ``` 149 150 ### Example C 151 GraphQL: 152 ```graphql 153 # graphql 154 155 enum MyEnum { 156 value 157 Value 158 } 159 ``` 160 Go: 161 ```go 162 // golang 163 164 type MyEnum string 165 166 const ( 167 MyEnumValue = "value" 168 MyEnumValue0 = "Value" 169 ) 170 ``` 171 172 ## Warning 173 174 Name collision resolution is handled per-name, as they come in. If you change the order of an enum, you could very 175 well end up with the same constant resolving to a different value. 176 177 Lets mutate [Example C](#example-c): 178 179 ### Example C - State A 180 GraphQL: 181 ```graphql 182 # graphql 183 184 enum MyEnum { 185 value 186 Value 187 } 188 ``` 189 Go: 190 ```go 191 // golang 192 193 type MyEnum string 194 195 const ( 196 MyEnumValue = "value" 197 MyEnumValue0 = "Value" 198 ) 199 ``` 200 201 ### Example C - State B 202 GraphQL: 203 ```graphql 204 # graphql 205 206 enum MyEnum { 207 Value 208 value 209 } 210 ``` 211 Go: 212 ```go 213 // golang 214 215 type MyEnum string 216 217 const ( 218 MyEnumValue = "Value" 219 MyEnumValue0 = "value" 220 ) 221 ``` 222 223 Notice how the constant names are the same, but the value that each applies to has changed.