|
1 | 1 | package introspection
|
2 | 2 |
|
3 | 3 | import (
|
| 4 | + "encoding/json" |
4 | 5 | "errors"
|
| 6 | + "sort" |
5 | 7 | "strings"
|
6 |
| - "sync" |
7 | 8 |
|
8 | 9 | "github.com/Code-Hex/gqldoc/internal/pool"
|
9 | 10 | )
|
@@ -137,35 +138,50 @@ type Schema struct {
|
137 | 138 | SubscriptionType *OperationType `json:"subscriptionType"`
|
138 | 139 | Types []*Types `json:"types"`
|
139 | 140 | Directives []*Directives `json:"directives"`
|
| 141 | + |
| 142 | + memoizeTypes map[string]*Types |
140 | 143 | }
|
141 | 144 |
|
142 |
| -var ErrNotFoundTypes = errors.New("not found types") |
| 145 | +var _ json.Unmarshaler = (*Schema)(nil) |
143 | 146 |
|
144 |
| -var ( |
145 |
| - memoizeTypes map[string]*Types |
146 |
| - mu sync.Mutex |
147 |
| -) |
| 147 | +var ErrNotFoundTypes = errors.New("not found types") |
148 | 148 |
|
149 | 149 | func (s *Schema) FindTypes(typName string) (*Types, error) {
|
150 |
| - // Make a memo |
151 |
| - mu.Lock() |
152 |
| - if len(memoizeTypes) == 0 && len(s.Types) > 0 { |
153 |
| - memoizeTypes = make(map[string]*Types, len(s.Types)) |
154 |
| - mid := len(s.Types) / 2 |
155 |
| - for i, j := 0, len(s.Types)-1; i < mid; i, j = i+1, j-1 { |
156 |
| - memoizeTypes[s.Types[i].Name] = s.Types[i] |
157 |
| - memoizeTypes[s.Types[j].Name] = s.Types[j] |
158 |
| - } |
159 |
| - } |
160 |
| - mu.Unlock() |
161 |
| - |
162 |
| - memo, ok := memoizeTypes[typName] |
| 150 | + memo, ok := s.memoizeTypes[typName] |
163 | 151 | if ok {
|
164 | 152 | return memo, nil
|
165 | 153 | }
|
166 | 154 | return nil, ErrNotFoundTypes
|
167 | 155 | }
|
168 | 156 |
|
| 157 | +func (s *Schema) UnmarshalJSON(data []byte) error { |
| 158 | + // HACK(codehex): To avoid stackoverflow, I assigned to tmp type. |
| 159 | + type HookSchema Schema |
| 160 | + var schema HookSchema |
| 161 | + if err := json.Unmarshal(data, &schema); err != nil { |
| 162 | + return err |
| 163 | + } |
| 164 | + sort.Slice(schema.Types, func(i, j int) bool { |
| 165 | + return strings.Compare(schema.Types[i].Name, schema.Types[j].Name) < 0 |
| 166 | + }) |
| 167 | + sort.Slice(schema.Directives, func(i, j int) bool { |
| 168 | + return strings.Compare(schema.Directives[i].Name, schema.Directives[j].Name) < 0 |
| 169 | + }) |
| 170 | + *s = (Schema(schema)) |
| 171 | + |
| 172 | + // Make a memo |
| 173 | + memoizeTypes := make(map[string]*Types, len(s.Types)) |
| 174 | + mid := len(s.Types) / 2 |
| 175 | + for i, j := 0, len(schema.Types)-1; i < mid; i, j = i+1, j-1 { |
| 176 | + memoizeTypes[schema.Types[i].Name] = schema.Types[i] |
| 177 | + memoizeTypes[schema.Types[j].Name] = schema.Types[j] |
| 178 | + } |
| 179 | + |
| 180 | + s.memoizeTypes = memoizeTypes |
| 181 | + |
| 182 | + return nil |
| 183 | +} |
| 184 | + |
169 | 185 | func (s *Schema) String() string {
|
170 | 186 | b := pool.GetBuilder()
|
171 | 187 | defer pool.PutBuilder(b)
|
@@ -198,6 +214,37 @@ type Types struct {
|
198 | 214 | PossibleTypes []*Type `json:"possibleTypes"`
|
199 | 215 | }
|
200 | 216 |
|
| 217 | +var _ json.Unmarshaler = (*Types)(nil) |
| 218 | + |
| 219 | +func (t *Types) UnmarshalJSON(data []byte) error { |
| 220 | + // HACK(codehex): To avoid stackoverflow, I assigned to tmp type. |
| 221 | + type HookType Types |
| 222 | + |
| 223 | + var types HookType |
| 224 | + if err := json.Unmarshal(data, &types); err != nil { |
| 225 | + return err |
| 226 | + } |
| 227 | + |
| 228 | + sort.Slice(types.Fields, func(i, j int) bool { |
| 229 | + return strings.Compare(types.Fields[i].Name, types.Fields[j].Name) < 0 |
| 230 | + }) |
| 231 | + sort.Slice(types.InputFields, func(i, j int) bool { |
| 232 | + return strings.Compare(types.InputFields[i].Name, types.InputFields[j].Name) < 0 |
| 233 | + }) |
| 234 | + sort.Slice(types.Interfaces, func(i, j int) bool { |
| 235 | + return strings.Compare(types.Interfaces[i].UnderlyingName(), types.Interfaces[j].UnderlyingName()) < 0 |
| 236 | + }) |
| 237 | + sort.Slice(types.EnumValues, func(i, j int) bool { |
| 238 | + return strings.Compare(types.EnumValues[i].Name, types.EnumValues[j].Name) < 0 |
| 239 | + }) |
| 240 | + sort.Slice(types.PossibleTypes, func(i, j int) bool { |
| 241 | + return strings.Compare(types.PossibleTypes[i].UnderlyingName(), types.PossibleTypes[j].UnderlyingName()) < 0 |
| 242 | + }) |
| 243 | + |
| 244 | + *t = Types(types) |
| 245 | + return nil |
| 246 | +} |
| 247 | + |
201 | 248 | const indent = " "
|
202 | 249 |
|
203 | 250 | func (t *Types) IsOperationType() bool {
|
|
0 commit comments