MCPcopy
hub / github.com/uber-go/nilaway / NodeTriggersOkRead

Function NodeTriggersOkRead

assertion/function/assertiontree/rich_check_effect.go:290–422  ·  view source on GitHub ↗

NodeTriggersOkRead is a case of a node creating a rich bool effect for map reads, channel receives, and user-defined functions in the "ok" form. Specifically, it matches on `AssignStmt`s of the form - `v, ok := mp[k]` - `v, ok := <-ch` - `r0, r1, r2, ..., ok := f()`

(rootNode *RootAssertionNode, nonceGenerator *guard.NonceGenerator, node ast.Node)

Source from the content-addressed store, hash-verified

288// - `v, ok := <-ch`
289// - `r0, r1, r2, ..., ok := f()`
290func NodeTriggersOkRead(rootNode *RootAssertionNode, nonceGenerator *guard.NonceGenerator, node ast.Node) ([]RichCheckEffect, bool) {
291 lhs, rhs := asthelper.ExtractLHSRHS(node)
292 if len(lhs) < 2 || len(rhs) != 1 {
293 return nil, false
294 }
295
296 okExpr := lhs[len(lhs)-1]
297 lhsOkParsed := parseExpr(rootNode, okExpr)
298 if lhsOkParsed == nil {
299 // here, the lhs `ok` operand is not trackable so there are no rich effects
300 return nil, false
301 }
302
303 var effects []RichCheckEffect
304
305 switch rhs := rhs[0].(type) {
306 case *ast.IndexExpr:
307 // this is the case of `v, ok := mp[k]`. Early return if the lhs is not a map read of the expected format
308 if len(lhs) != 2 {
309 return nil, false
310 }
311
312 rhsXType := rootNode.Pass().TypesInfo.Types[rhs.X].Type
313 if typeshelper.IsDeeplyType[*types.Map](rhsXType) {
314 // Create a rich check effect for `v` part of the map read in `v, ok := mp[k]`
315 if lhsValueParsed := parseExpr(rootNode, lhs[0]); lhsValueParsed != nil {
316 // Here, the lhs `value` operand is trackable
317 effects = append(effects, &MapOkRead{
318 okRead{
319 root: rootNode,
320 value: lhsValueParsed,
321 ok: lhsOkParsed,
322 guard: nonceGenerator.Next(lhs[0]),
323 }})
324 }
325
326 // Create a rich check effect for the map read `mp[k]` part of `v, ok := mp[k]`. This is important
327 // to support cases when consequent map reads are used instead of creating a local variable `v`. For example,
328 // ```
329 // if _, ok := mp[k]; ok {
330 // return *mp[k]
331 // }
332 // ```
333 if rhsParsed := parseExpr(rootNode, rhs); rhsParsed != nil {
334 // Here, the rhs `map read` itself is trackable
335 effects = append(effects, &MapOkRead{
336 okRead{
337 root: rootNode,
338 value: rhsParsed,
339 ok: lhsOkParsed,
340 guard: nonceGenerator.Next(rhs),
341 }})
342 }
343
344 // Create a rich check effect for the map itself, `mp`, in `v, ok := mp[k]`
345 if rhsMapParsed := parseExpr(rootNode, rhs.X); rhsMapParsed != nil {
346 // Here, the rhs `map` operand is trackable
347 effects = append(effects, &MapOkReadRefl{

Callers 1

RichCheckFromNodeFunction · 0.85

Calls 7

ExtractLHSRHSFunction · 0.92
FuncIdentFromCallExprFunction · 0.92
FuncIsOkReturningFunction · 0.92
parseExprFunction · 0.85
PassMethod · 0.80
NextMethod · 0.80
ObjectOfMethod · 0.80

Tested by

no test coverage detected