/
parser.go
96 lines (79 loc) · 2.21 KB
/
parser.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
package extractor
import (
"go/ast"
"go/parser"
"go/token"
"github.com/rotisserie/eris"
)
func parseEnumsFromFile(
filePath string,
targetObjectTypeNames []constantObjectTypeName,
includeNonExported bool,
) (enums, error) {
fileNode, err := parser.ParseFile(token.NewFileSet(), filePath, nil, parser.ParseComments)
if err != nil {
return nil, eris.Wrapf(err, "parsing file %s", filePath)
}
var objects = make(enums)
for i := range fileNode.Decls {
declaration, ok := fileNode.Decls[i].(*ast.GenDecl)
if !ok {
continue
}
if declaration.Tok != token.CONST {
continue
}
for key, value := range extractEnumsFromDeclaration(declaration, includeNonExported) {
if insideTargetObjectTypeNames(key, targetObjectTypeNames) {
objects[key] = value
}
}
}
return objects, nil
}
func extractEnumsFromDeclaration(declaration *ast.GenDecl, includeNonExported bool) enums {
var objects = make(enums)
for i := range declaration.Specs {
constantDeclarationSpecification, constantDeclarationSpecificationOk := declaration.Specs[i].(*ast.ValueSpec)
if !constantDeclarationSpecificationOk {
continue
}
objectTypeName, e := extractEnumFromSpecification(
constantDeclarationSpecification,
objects.constantObjectTypeNameIfConsistsOfIota,
includeNonExported,
)
if objectTypeName == "" {
continue
} else if len(e.Name) == 0 {
continue
}
objects[objectTypeName] = append(objects[objectTypeName], e)
}
return objects
}
func extractEnumFromSpecification(
constantDeclarationSpecification *ast.ValueSpec,
objectTypeNameOnIotaFunction func() constantObjectTypeName,
includeNonExported bool,
) (constantObjectTypeName, enum) {
name, objectTypeName, value := extractConstantsBlock(constantDeclarationSpecification, includeNonExported)
if objectTypeName == "" {
objectTypeName = objectTypeNameOnIotaFunction()
}
return objectTypeName, enum{Name: name, Value: value}
}
func insideTargetObjectTypeNames(
objectTypeName constantObjectTypeName,
targetObjectTypeNames []constantObjectTypeName,
) bool {
if len(targetObjectTypeNames) == 0 {
return true
}
for i := range targetObjectTypeNames {
if targetObjectTypeNames[i] == objectTypeName {
return true
}
}
return false
}