Check performs type-checking on the input Ast and yields a checked Ast and/or set of Issues. If any `ASTValidators` are configured on the environment, they will be applied after a valid type-check result. If any issues are detected, the validators will provide them on the output Issues object. Eith
(ast *Ast)
| 399 | // It is possible to have both non-nil Ast and Issues values returned from this call: however, |
| 400 | // the mere presence of an Ast does not imply that it is valid for use. |
| 401 | func (e *Env) Check(ast *Ast) (*Ast, *Issues) { |
| 402 | // Surface any error recorded while the Ast was loaded (e.g. an over-deep AST rejected by |
| 403 | // ParsedExprToAst / CheckedExprToAst) before recursing into the type checker on it. |
| 404 | if ast != nil && ast.loadErr != nil { |
| 405 | errs := common.NewErrors(ast.Source()) |
| 406 | errs.ReportErrorString(common.NoLocation, ast.loadErr.Error()) |
| 407 | return nil, NewIssuesWithSourceInfo(errs, ast.NativeRep().SourceInfo()) |
| 408 | } |
| 409 | if nodeLimit := e.configuredExpressionNodeLimit(); nodeLimit > 0 && ast != nil && ast.NativeRep() != nil { |
| 410 | if count := celast.NodeCount(ast.NativeRep()); count > nodeLimit { |
| 411 | errs := common.NewErrors(ast.Source()) |
| 412 | errs.ReportErrorString(common.NoLocation, fmt.Sprintf("expression node count exceeds limit: count %d, limit %d", count, nodeLimit)) |
| 413 | return nil, NewIssuesWithSourceInfo(errs, ast.NativeRep().SourceInfo()) |
| 414 | } |
| 415 | } |
| 416 | // Construct the internal checker env, erroring if there is an issue adding the declarations. |
| 417 | chk, err := e.initChecker() |
| 418 | if err != nil { |
| 419 | errs := common.NewErrors(ast.Source()) |
| 420 | errs.ReportErrorString(common.NoLocation, err.Error()) |
| 421 | return nil, NewIssuesWithSourceInfo(errs, ast.NativeRep().SourceInfo()) |
| 422 | } |
| 423 | |
| 424 | checked, errs := checker.Check(ast.NativeRep(), ast.Source(), chk) |
| 425 | if len(errs.GetErrors()) > 0 { |
| 426 | return nil, NewIssuesWithSourceInfo(errs, ast.NativeRep().SourceInfo()) |
| 427 | } |
| 428 | // Manually create the Ast to ensure that the Ast source information (which may be more |
| 429 | // detailed than the information provided by Check), is returned to the caller. |
| 430 | ast = &Ast{ |
| 431 | source: ast.Source(), |
| 432 | impl: checked} |
| 433 | |
| 434 | // Avoid creating a validator config if it's not needed. |
| 435 | if len(e.validators) == 0 { |
| 436 | return ast, nil |
| 437 | } |
| 438 | |
| 439 | // Generate a validator configuration from the set of configured validators. |
| 440 | vConfig := newValidatorConfig() |
| 441 | for _, v := range e.validators { |
| 442 | if cv, ok := v.(ASTValidatorConfigurer); ok { |
| 443 | cv.Configure(vConfig) |
| 444 | } |
| 445 | } |
| 446 | // Apply additional validators on the type-checked result. |
| 447 | iss := NewIssuesWithSourceInfo(errs, ast.NativeRep().SourceInfo()) |
| 448 | for _, v := range e.validators { |
| 449 | v.Validate(e, vConfig, checked, iss) |
| 450 | } |
| 451 | if iss.Err() != nil { |
| 452 | return nil, iss |
| 453 | } |
| 454 | return ast, nil |
| 455 | } |
| 456 | |
| 457 | // configuredExpressionSizeLimit returns the effective expression size code point limit. |
| 458 | // A zero value means "use the parser default". |