func ctxActionsWarning()

in warn/warn_bazel_api.go [494:577]


func ctxActionsWarning(f *build.File) []*LinterFinding {
	if f.Type != build.TypeBzl {
		return nil
	}

	var findings []*LinterFinding
	build.WalkPointers(f, func(expr *build.Expr, stack []build.Expr) {
		// Find nodes that match the following pattern: ctx.xxxx(...)
		call, ok := (*expr).(*build.CallExpr)
		if !ok {
			return
		}
		dot, ok := (call.X).(*build.DotExpr)
		if !ok {
			return
		}
		base, ok := dot.X.(*build.Ident)
		if !ok || base.Name != "ctx" {
			return
		}

		switch dot.Name {
		case "new_file", "experimental_new_directory", "file_action", "action", "empty_action", "template_action":
			// fix
		default:
			return
		}

		// Fix
		newCall := *call
		newCall.List = append([]build.Expr{}, call.List...)
		newDot := *dot
		newCall.X = &newDot

		switch dot.Name {
		case "new_file":
			if len(call.List) > 2 {
				// Can't fix automatically because the new API doesn't support the 3 arguments signature
				findings = append(findings,
					makeLinterFinding(dot, fmt.Sprintf(`"ctx.new_file" is deprecated in favor of "ctx.actions.declare_file".`)))
				return
			}
			newDot.Name = "actions.declare_file"
			if len(call.List) == 2 {
				// swap arguments:
				// ctx.new_file(sibling, name) -> ctx.actions.declare_file(name, sibling=sibling)
				newCall.List[0], newCall.List[1] = makePositional(call.List[1]), makeKeyword(call.List[0], "sibling")
			}
		case "experimental_new_directory":
			newDot.Name = "actions.declare_directory"
		case "file_action":
			newDot.Name = "actions.write"
			i, ident, param := getParam(newCall.List, "executable")
			if ident != nil {
				newIdent := *ident
				newIdent.Name = "is_executable"
				newParam := *param
				newParam.LHS = &newIdent
				newCall.List[i] = &newParam
			}
		case "action":
			newDot.Name = "actions.run"
			if _, _, command := getParam(call.List, "command"); command != nil {
				newDot.Name = "actions.run_shell"
			}
		case "empty_action":
			newDot.Name = "actions.do_nothing"
		case "template_action":
			newDot.Name = "actions.expand_template"
			if i, ident, param := getParam(call.List, "executable"); ident != nil {
				newIdent := *ident
				newIdent.Name = "is_executable"
				newParam := *param
				newParam.LHS = &newIdent
				newCall.List[i] = &newParam
			}
		}

		findings = append(findings, makeLinterFinding(dot,
			fmt.Sprintf(`"ctx.%s" is deprecated in favor of "ctx.%s".`, dot.Name, newDot.Name),
			LinterReplacement{expr, &newCall}))
	})
	return findings
}