Skip to content

Commit 282db55

Browse files
authored
Merge pull request #110 from dengsh12/NLB5265
Provide three more custom option for command-line generator
2 parents 5f14056 + 82990a0 commit 282db55

16 files changed

+230
-70
lines changed

README.md

+3-4
Original file line numberDiff line numberDiff line change
@@ -75,8 +75,8 @@ func main() {
7575

7676
# Generate support for third-party modules
7777
This is a simple example that takes the path of a third-party module source code to generate support for it. For detailed usage of the tool, please run
78-
`go run ./cmd/generate/ --help`
79-
Assuming the source code path of that module is `./src`, you can call `go run ./cmd/generate/ --src-path=./src`. The output will be similar to:
78+
`go run ./cmd/generate/ --help`.
79+
Assuming the source code path of that module is `./src`, you can call `go run ./cmd/generate/ --src-path=./src -directive-map-name=directives -match-func-name=Match -match-func-comment=comment`. The output will be similar to:
8080

8181
```go
8282
/**
@@ -109,8 +109,7 @@ var directives = map[string][]uint{
109109
},
110110
}
111111

112-
// Match is a matchFunc for parsing an NGINX config that contains the
113-
// preceding directives.
112+
// comment
114113
func Match(directive string) ([]uint, bool) {
115114
m, ok := directives[directive]
116115
return m, ok

cmd/generate/main.go

+28-2
Original file line numberDiff line numberDiff line change
@@ -19,12 +19,18 @@ func main() {
1919
var (
2020
sourceCodePath = flag.String("src-path", "",
2121
"The path of source code your want to generate support from, it can be either a file or a directory. (required)")
22+
directiveMapName = flag.String("directive-map-name", "", "Name of the generated map variable."+
23+
" Normally it should start with lowercase to avoid export. (required)")
24+
matchFuncName = flag.String("match-func-name", "", "Name of the generated matchFunc."+
25+
" Normally it should start with uppercase to export. (required)")
26+
matchFnComment = flag.String("match-func-comment", "", "The code comment for generated matchFunc."+
27+
" You can add some explanations like which modules included in it. Normally it should start with match-func-name (optional)")
2228
filterflags filterFlag
2329
directiveOverride override
2430
)
2531
flag.Var(&filterflags, "filter",
2632
"A list of strings specifying the directives to exclude from the output. "+
27-
"An example is: -filter directive1 -filter directive2...(optional)")
33+
"An example is: -filter directive1 -filter directive2... (optional)")
2834
flag.Var(&directiveOverride, "override",
2935
"A list of strings, used to override the output. "+
3036
"It should follow the format:{directive:bitmask00|bitmask01...,bitmask10|bitmask11...}"+"\n"+
@@ -33,7 +39,27 @@ func main() {
3339

3440
flag.Parse()
3541

36-
err := generator.Generate(*sourceCodePath, os.Stdout, filterflags.filter, directiveOverride)
42+
if *sourceCodePath == "" {
43+
log.Fatal("src-path can't be empty")
44+
}
45+
46+
if *directiveMapName == "" {
47+
log.Fatal("directive-map can't be empty")
48+
}
49+
50+
if *matchFuncName == "" {
51+
log.Fatal("match-func can't be empty")
52+
}
53+
54+
config := generator.GenerateConfig{
55+
Filter: filterflags.filter,
56+
Override: directiveOverride,
57+
DirectiveMapName: *directiveMapName,
58+
MatchFuncName: *matchFuncName,
59+
MatchFuncComment: *matchFnComment,
60+
}
61+
62+
err := generator.Generate(*sourceCodePath, os.Stdout, config)
3763
if err != nil {
3864
log.Fatal(err)
3965
}

internal/generator/generator.go

+36-6
Original file line numberDiff line numberDiff line change
@@ -11,10 +11,40 @@ import (
1111
"io"
1212
)
1313

14-
// Generate receives a string sourcePath and an io.Writer writer. It will
15-
// extract all the directives definitions from the .c and .cpp files in
16-
// sourcePath and its subdirectories, then output the corresponding directive
17-
// masks map named "directives" and matchFunc named "Match" via writer.
18-
func Generate(sourcePath string, writer io.Writer, filter map[string]struct{}, override map[string][]Mask) error {
19-
return genFromSrcCode(sourcePath, "directives", "Match", writer, filter, override)
14+
type GenerateConfig struct {
15+
// Filter is a map used to exclude directives from generator.
16+
// The key of it is the directive names.
17+
Filter map[string]struct{}
18+
19+
// Override is a map used to override the masks from source code of directives.
20+
// The key of it is the directive name. The value is the masks we want.
21+
// If a directive exists in Override, generator won't consider its definition
22+
// in source code.
23+
Override map[string][]Mask
24+
25+
// DirectiveMapName is the name assigned to the variable containing the directives
26+
// discovered by generator. The variable name generally starts with a
27+
// lowercase to avoid export. Users will use the generated function named by
28+
// MatchFuncName to validate the module directives in nginx configurations.
29+
DirectiveMapName string
30+
31+
// MatchFuncName is the name assigned to the matchFunc generated by the generator.
32+
// It should generally start with a uppercase to export.
33+
// Users will use the generated function named by MatchFuncName
34+
// to validate the module directives in nginx configurations.
35+
MatchFuncName string
36+
37+
// MatchFuncComment is the comment appears above the generated MatchFunc.
38+
// It may contain some information like what modules are included
39+
// in the generated MatchFunc. Generally it should start with MatchFuncName.
40+
// If it is empty, no comments will appear above the generated MatchFunc.
41+
MatchFuncComment string
42+
}
43+
44+
// Generate receives a string sourcePath, an io.Writer writer, and a
45+
// GenerateConfig config. It will extract all the directives definitions
46+
// from the .c and .cpp files in sourcePath and its subdirectories,
47+
// then output the corresponding directive masks map and matchFunc via writer.
48+
func Generate(sourcePath string, writer io.Writer, config GenerateConfig) error {
49+
return genFromSrcCode(sourcePath, writer, config)
2050
}

internal/generator/generator_util.go

+7-4
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ type supportFileTmplStruct struct {
3030
Directive2Masks map[string][]Mask
3131
MapVariableName string
3232
MatchFnName string
33+
MatchFnComment string
3334
}
3435

3536
var (
@@ -184,13 +185,13 @@ func getMasksFromPath(path string) (directive2Masks map[string][]Mask, err error
184185
return directive2Masks, nil
185186
}
186187

187-
func genFromSrcCode(codePath string, mapVariableName string, matchFnName string, writer io.Writer,
188-
filter map[string]struct{}, override map[string][]Mask) error {
188+
func genFromSrcCode(codePath string, writer io.Writer, config GenerateConfig) error {
189189
directive2Masks, err := getMasksFromPath(codePath)
190190
if err != nil {
191191
return err
192192
}
193193

194+
filter := config.Filter
194195
if len(filter) > 0 {
195196
for d := range directive2Masks {
196197
if _, found := filter[d]; found {
@@ -199,6 +200,7 @@ func genFromSrcCode(codePath string, mapVariableName string, matchFnName string,
199200
}
200201
}
201202

203+
override := config.Override
202204
if override != nil {
203205
for d := range directive2Masks {
204206
if newMasks, found := override[d]; found {
@@ -209,8 +211,9 @@ func genFromSrcCode(codePath string, mapVariableName string, matchFnName string,
209211

210212
err = supportFileTmpl.Execute(writer, supportFileTmplStruct{
211213
Directive2Masks: directive2Masks,
212-
MapVariableName: mapVariableName,
213-
MatchFnName: matchFnName,
214+
MapVariableName: config.DirectiveMapName,
215+
MatchFnName: config.MatchFuncName,
216+
MatchFnComment: config.MatchFuncComment,
214217
})
215218
if err != nil {
216219
return err

internal/generator/generator_util_test.go

+87-33
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ import (
2626
var (
2727
update = flag.Bool("update", false,
2828
`update the expected output of these tests,
29-
only use when the expected output is outdated and you are sure your output is correct`)
29+
only use when the expected output is outdated and you are sure your output is correct`)
3030
)
3131

3232
func TestMain(m *testing.M) {
@@ -70,79 +70,133 @@ func getExpectedFilePath(relativePath string) (string, error) {
7070
}
7171

7272
//nolint:funlen,gocognit
73-
func TestGenSupFromSrcCode(t *testing.T) {
73+
func TestGenFromSrcCode(t *testing.T) {
7474
t.Parallel()
7575
tests := map[string]struct {
7676
relativePath string
7777
wantErr bool
78-
filter map[string]struct{}
79-
override map[string][]Mask
78+
config GenerateConfig
8079
}{
8180
"normalDirectiveDefinition_pass": {
8281
relativePath: "normalDefinition",
83-
wantErr: false,
82+
config: GenerateConfig{
83+
DirectiveMapName: "myDirectives",
84+
MatchFuncName: "MyMatchFn",
85+
},
86+
wantErr: false,
8487
},
8588
"unknownBitmask_fail": {
8689
relativePath: "unknownBitmask",
87-
wantErr: true,
90+
config: GenerateConfig{
91+
DirectiveMapName: "directives",
92+
MatchFuncName: "Match",
93+
},
94+
wantErr: true,
8895
},
8996
"noDirectivesDefinition_fail": {
9097
relativePath: "noDirectives",
91-
wantErr: true,
98+
config: GenerateConfig{
99+
DirectiveMapName: "directives",
100+
MatchFuncName: "Match",
101+
},
102+
wantErr: true,
92103
},
93104
// If one directive was defined in several files, we should keep all
94105
// of the bitmask definitions
95106
"directiveRepeatDefine_pass": {
96107
relativePath: "repeatDefine",
108+
config: GenerateConfig{
109+
DirectiveMapName: "directives",
110+
MatchFuncName: "Match",
111+
},
112+
wantErr: false,
97113
},
98114
// If there are comments in directive definition, we should ignore them
99115
"commentsInDefinition_pass": {
100116
relativePath: "commentsInDefinition",
117+
config: GenerateConfig{
118+
DirectiveMapName: "directives",
119+
MatchFuncName: "Match",
120+
},
121+
wantErr: false,
101122
},
102123
"genFromSingleFile_pass": {
103124
relativePath: "single_file.c",
125+
config: GenerateConfig{
126+
DirectiveMapName: "directives",
127+
MatchFuncName: "Match",
128+
},
129+
wantErr: false,
104130
},
105131
"fullNgxBitmaskCover_pass": {
106132
relativePath: "fullNgxBitmaskCover",
133+
config: GenerateConfig{
134+
DirectiveMapName: "directives",
135+
MatchFuncName: "Match",
136+
},
137+
wantErr: false,
107138
},
108139
"testFilter_pass": {
109140
relativePath: "filter",
110-
filter: map[string]struct{}{"my_directive_2": {}, "my_directive_3": {}},
141+
config: GenerateConfig{
142+
DirectiveMapName: "directives",
143+
MatchFuncName: "Match",
144+
Filter: map[string]struct{}{"my_directive_2": {}, "my_directive_3": {}},
145+
},
111146
},
112147
"testOverride_pass": {
113148
relativePath: "override",
114-
override: map[string][]Mask{
115-
"my_directive_1": {
116-
Mask{"ngxHTTPMainConf", "ngxConfTake1"},
117-
Mask{"ngxHTTPMainConf", "ngxConfTake2"},
118-
},
119-
"my_directive_3": {
120-
Mask{"ngxHTTPMainConf", "ngxConfTake2"},
121-
Mask{"ngxHTTPMainConf", "ngxConfTake3"},
149+
config: GenerateConfig{
150+
DirectiveMapName: "directives",
151+
MatchFuncName: "Match",
152+
Override: map[string][]Mask{
153+
"my_directive_1": {
154+
Mask{"ngxHTTPMainConf", "ngxConfTake1"},
155+
Mask{"ngxHTTPMainConf", "ngxConfTake2"},
156+
},
157+
"my_directive_3": {
158+
Mask{"ngxHTTPMainConf", "ngxConfTake2"},
159+
Mask{"ngxHTTPMainConf", "ngxConfTake3"},
160+
},
122161
},
123162
},
163+
wantErr: false,
124164
},
125165
"testFilterAndOverride_pass": {
126166
relativePath: "filterAndOverride",
127-
filter: map[string]struct{}{
128-
"my_directive_1": {},
129-
"my_directive_2": {},
130-
"my_directive_3": {},
131-
},
132-
override: map[string][]Mask{
133-
"my_directive_1": {
134-
Mask{"ngxHTTPMainConf", "ngxConfTake1"},
135-
Mask{"ngxHTTPMainConf", "ngxConfTake2"},
167+
config: GenerateConfig{
168+
Filter: map[string]struct{}{
169+
"my_directive_1": {},
170+
"my_directive_2": {},
171+
"my_directive_3": {},
136172
},
137-
"my_directive_3": {
138-
Mask{"ngxHTTPMainConf", "ngxConfTake2"},
139-
Mask{"ngxHTTPMainConf", "ngxConfTake3"},
140-
},
141-
"my_directive_4": {
142-
Mask{"ngxHTTPMainConf", "ngxConfTake2"},
143-
Mask{"ngxHTTPMainConf", "ngxConfTake3"},
173+
Override: map[string][]Mask{
174+
"my_directive_1": {
175+
Mask{"ngxHTTPMainConf", "ngxConfTake1"},
176+
Mask{"ngxHTTPMainConf", "ngxConfTake2"},
177+
},
178+
"my_directive_3": {
179+
Mask{"ngxHTTPMainConf", "ngxConfTake2"},
180+
Mask{"ngxHTTPMainConf", "ngxConfTake3"},
181+
},
182+
"my_directive_4": {
183+
Mask{"ngxHTTPMainConf", "ngxConfTake2"},
184+
Mask{"ngxHTTPMainConf", "ngxConfTake3"},
185+
},
144186
},
187+
DirectiveMapName: "directives",
188+
MatchFuncName: "Match",
189+
},
190+
wantErr: false,
191+
},
192+
"withMatchFuncComment_pass": {
193+
relativePath: "withMatchFuncComment",
194+
config: GenerateConfig{
195+
DirectiveMapName: "myDirectives",
196+
MatchFuncName: "MyMatchFn",
197+
MatchFuncComment: "This is a matchFunc",
145198
},
199+
wantErr: false,
146200
},
147201
}
148202
for name, tc := range tests {
@@ -157,7 +211,7 @@ func TestGenSupFromSrcCode(t *testing.T) {
157211

158212
var buf bytes.Buffer
159213

160-
err = genFromSrcCode(codePath, "directives", "Match", &buf, tc.filter, tc.override)
214+
err = genFromSrcCode(codePath, &buf, tc.config)
161215

162216
if tc.wantErr {
163217
require.Error(t, err)

internal/generator/testdata/expected/commentsInDefinition

+1-2
Original file line numberDiff line numberDiff line change
@@ -27,8 +27,7 @@ var directives = map[string][]uint{
2727
},
2828
}
2929

30-
// Match is a matchFunc for parsing an NGINX config that contains the
31-
// preceding directives.
30+
3231
func Match(directive string) ([]uint, bool) {
3332
m, ok := directives[directive]
3433
return m, ok

internal/generator/testdata/expected/filter

+1-2
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,7 @@ var directives = map[string][]uint{
2424
},
2525
}
2626

27-
// Match is a matchFunc for parsing an NGINX config that contains the
28-
// preceding directives.
27+
2928
func Match(directive string) ([]uint, bool) {
3029
m, ok := directives[directive]
3130
return m, ok

internal/generator/testdata/expected/filterAndOverride

+1-2
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,7 @@ var directives = map[string][]uint{
2222
},
2323
}
2424

25-
// Match is a matchFunc for parsing an NGINX config that contains the
26-
// preceding directives.
25+
2726
func Match(directive string) ([]uint, bool) {
2827
m, ok := directives[directive]
2928
return m, ok

internal/generator/testdata/expected/fullNgxBitmaskCover

+1-2
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,7 @@ var directives = map[string][]uint{
2121
},
2222
}
2323

24-
// Match is a matchFunc for parsing an NGINX config that contains the
25-
// preceding directives.
24+
2625
func Match(directive string) ([]uint, bool) {
2726
m, ok := directives[directive]
2827
return m, ok

0 commit comments

Comments
 (0)