Skip to content

Commit 0c18668

Browse files
Support RuntimeConfig API v2 (#96)
1 parent 935e1b4 commit 0c18668

File tree

2 files changed

+64
-27
lines changed

2 files changed

+64
-27
lines changed

pkg/golinters/runtimeconfig.go

Lines changed: 39 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -47,62 +47,74 @@ func run(pass *analysis.Pass) (interface{}, error) {
4747
i.Preorder(nodeFilter, func(n ast.Node) {
4848
call := n.(*ast.CallExpr)
4949
target := typeutil.Callee(pass.TypesInfo, call)
50-
numArgs := 3
50+
numArgs := len(call.Args)
5151
if target == nil {
5252
return
5353
} else if target.Pkg() == nil || !(target.Pkg().Path() == "ghe.anduril.dev/anduril/graphene-go/pkg/graphene" &&
54-
(target.Name() == getFn || target.Name() == subscribeFn)) || len(call.Args) != numArgs {
54+
((target.Name() == getFn && (numArgs == 2 || numArgs == 3)) ||
55+
(target.Name() == subscribeFn) && numArgs != 3)) {
5556
return
5657
}
5758
if selector, ok := call.Fun.(*ast.SelectorExpr); ok {
5859
fnName := selector.Sel.Name
5960
isGetConfig := fnName == getFn
6061
isSubscribeConfig := fnName == subscribeFn
6162
if isGetConfig || isSubscribeConfig {
62-
defaultConfArg := call.Args[1]
63-
defaultConfArgType := pass.TypesInfo.Types[defaultConfArg].Type
64-
defaultConfig := getStructType(defaultConfArgType)
65-
if defaultConfig == nil {
66-
pass.Reportf(
67-
defaultConfArg.Pos(),
68-
"expected 2nd arg to be non nil but got %v",
69-
defaultConfig,
70-
)
71-
return
72-
}
73-
validateFieldSerialization(pass, defaultConfArg.Pos(), defaultConfig, defaultConfArgType.String())
74-
arg3 := call.Args[2]
75-
if isSubscribeConfig {
76-
validateTypeConversion(arg3, defaultConfArgType.String(), pass)
77-
} else if isGetConfig {
78-
checkPointerArg(arg3, "", defaultConfArgType.String(), arg3.Pos(), pass, false)
63+
if numArgs == 3 {
64+
// Using Subscribe or Get from RuntimeConfig
65+
defaultConfArg := call.Args[1]
66+
defaultConfArgType := pass.TypesInfo.Types[defaultConfArg].Type
67+
defaultConfig := getStructType(defaultConfArgType)
68+
if defaultConfig == nil {
69+
pass.Reportf(
70+
defaultConfArg.Pos(),
71+
"expected 2nd arg to be non nil but got %v",
72+
defaultConfig,
73+
)
74+
return
75+
}
76+
validateFieldSerialization(pass, defaultConfArg.Pos(), defaultConfig, defaultConfArgType.String())
77+
arg3 := call.Args[2]
78+
if isSubscribeConfig {
79+
validateTypeConversion(arg3, defaultConfArgType.String(), pass)
80+
} else if isGetConfig {
81+
checkPointerArg(arg3, "", defaultConfArgType.String(), arg3.Pos(), pass, "3rd", false)
82+
}
83+
} else {
84+
// Using Get from RuntimeConfigV2
85+
arg2 := call.Args[1]
86+
checkPointerArg(arg2, "", "", arg2.Pos(), pass, "2nd", false)
7987
}
8088
}
8189
}
8290
})
8391
return nil, nil
8492
}
8593

86-
func checkPointerArg(arg ast.Expr, argName, defType string, pos token.Pos, pass *analysis.Pass, isRef bool) {
94+
func checkPointerArg(arg ast.Expr, argName, defType string, pos token.Pos, pass *analysis.Pass, numArgsString string, isRef bool) {
8795
switch t := arg.(type) {
8896
case *ast.Ident:
8997
if t.Obj == nil {
90-
pass.Reportf(t.Pos(), "expected configuration object as 3rd arg but got nil")
98+
pass.Reportf(t.Pos(), "expected configuration object as %s arg but got nil", numArgsString)
9199
return
92100
}
93101
if varDec, ok := t.Obj.Decl.(*ast.AssignStmt); ok {
94102
if len(varDec.Rhs) == 1 {
95-
checkPointerArg(varDec.Rhs[0], t.Name, defType, pos, pass, isRef)
103+
checkPointerArg(varDec.Rhs[0], t.Name, defType, pos, pass, numArgsString, isRef)
96104
}
97105
}
98106
case *ast.UnaryExpr:
99107
if !t.Op.IsOperator() || t.Op.String() != "&" {
100-
pass.Reportf(pos, "expected ref as 3rd arg to Get")
108+
pass.Reportf(pos, "expected ref as %s arg to Get", numArgsString)
101109
}
102-
checkPointerArg(t.X, argName, defType, pos, pass, true)
110+
checkPointerArg(t.X, argName, defType, pos, pass, numArgsString, true)
103111
case *ast.CompositeLit:
104112
if !isRef {
105-
pass.Reportf(pos, "expected ref as 3rd arg to Get")
113+
pass.Reportf(pos, "expected ref as %s arg to Get", numArgsString)
114+
}
115+
if defType == "" {
116+
// Using RuntimeConfigV2, skip SameType checks
117+
return
106118
}
107119
switch sl := t.Type.(type) {
108120
case *ast.Ident:
@@ -112,10 +124,10 @@ func checkPointerArg(arg ast.Expr, argName, defType string, pos token.Pos, pass
112124
}
113125
case *ast.SelectorExpr:
114126
if !isRef {
115-
pass.Reportf(pos, "expected ref as 3rd arg to Get")
127+
pass.Reportf(pos, "expected ref as %s arg to Get", numArgsString)
116128
}
117129
default:
118-
pass.Reportf(pos, "expected ref as 3rd arg to Get")
130+
pass.Reportf(pos, "expected ref as %s arg to Get", numArgsString)
119131
}
120132
}
121133

test/testdata/runtimeconfig_test.go

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,21 @@ func GetTest() {
6161
6262
// valid usage
6363
rtc.Get("", T1{}, &t1)
64+
65+
rtcv2 := setupv2()
66+
67+
// nil or primitive values are not allowed
68+
rtcv2.Get("", nil) // __ERROR__ "expected configuration object as 2nd arg but got nil"
69+
rtcv2.Get("", false) // __ERROR__ "expected configuration object as 2nd arg but got nil"
70+
rtcv2.Get("", "") // __ERROR__ "expected ref as 2nd arg to Get"
71+
rtcv2.Get("", 456) // __ERROR__ "expected ref as 2nd arg to Get"
72+
73+
// 3rd arg needs to be a ref (update in-place)
74+
t1 = T1{}
75+
rtcv2.Get("", t1) // __ERROR__ "expected ref as 2nd arg to Get"
76+
77+
// valid usage
78+
rtcv2.Get("", T1{}, &t1)
6479
}
6580
6681
func SubscribeTest() {
@@ -120,4 +135,14 @@ func setup() graphene.RuntimeConfigRegistry {
120135
return rtc
121136
}
122137
138+
func setupv2() graphene.RuntimeConfigRegistry2 {
139+
var rtc graphene.RuntimeConfigRegistry2
140+
_, _ = graphene.Create("asdf", 123, 123, nil, func(g *graphene.Graphene) error {
141+
rtc = g.RuntimeConfig2()
142+
return nil
143+
})
144+
return rtc
145+
}
146+
147+
123148
*/

0 commit comments

Comments
 (0)