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)
| 415 | // It is possible to have both non-nil Ast and Issues values returned from this call: however, |
| 416 | // the mere presence of an Ast does not imply that it is valid for use. |
| 417 | func (e *Env) Check(ast *Ast) (*Ast, *Issues) { |
| 418 | // Surface any error recorded while the Ast was loaded (e.g. an over-deep AST rejected by |
| 419 | // ParsedExprToAst / CheckedExprToAst) before recursing into the type checker on it. |
| 420 | if ast != nil && ast.loadErr != nil { |
| 421 | errs := common.NewErrors(ast.Source()) |
| 422 | errs.ReportErrorString(common.NoLocation, ast.loadErr.Error()) |
| 423 | return nil, NewIssuesWithSourceInfo(errs, ast.NativeRep().SourceInfo()) |
| 424 | } |
| 425 | if nodeLimit := e.configuredExpressionNodeLimit(); nodeLimit > 0 && ast != nil && ast.NativeRep() != nil { |
| 426 | if count := celast.NodeCount(ast.NativeRep()); count > nodeLimit { |
| 427 | errs := common.NewErrors(ast.Source()) |
| 428 | errs.ReportErrorString(common.NoLocation, fmt.Sprintf("expression node count exceeds limit: count %d, limit %d", count, nodeLimit)) |
| 429 | return nil, NewIssuesWithSourceInfo(errs, ast.NativeRep().SourceInfo()) |
| 430 | } |
| 431 | } |
| 432 | // Construct the internal checker env, erroring if there is an issue adding the declarations. |
| 433 | chk, err := e.initChecker() |
| 434 | if err != nil { |
| 435 | errs := common.NewErrors(ast.Source()) |
| 436 | errs.ReportErrorString(common.NoLocation, err.Error()) |
| 437 | return nil, NewIssuesWithSourceInfo(errs, ast.NativeRep().SourceInfo()) |
| 438 | } |
| 439 | |
| 440 | checked, errs := checker.Check(ast.NativeRep(), ast.Source(), chk) |
| 441 | if len(errs.GetErrors()) > 0 { |
| 442 | return nil, NewIssuesWithSourceInfo(errs, ast.NativeRep().SourceInfo()) |
| 443 | } |
| 444 | // Manually create the Ast to ensure that the Ast source information (which may be more |
| 445 | // detailed than the information provided by Check), is returned to the caller. |
| 446 | ast = &Ast{ |
| 447 | source: ast.Source(), |
| 448 | impl: checked} |
| 449 | |
| 450 | // Avoid creating a validator config if it's not needed. |
| 451 | if len(e.validators) == 0 { |
| 452 | return ast, nil |
| 453 | } |
| 454 | |
| 455 | // Generate a validator configuration from the set of configured validators. |
| 456 | vConfig := newValidatorConfig() |
| 457 | for _, v := range e.validators { |
| 458 | if cv, ok := v.(ASTValidatorConfigurer); ok { |
| 459 | cv.Configure(vConfig) |
| 460 | } |
| 461 | } |
| 462 | // Apply additional validators on the type-checked result. |
| 463 | iss := NewIssuesWithSourceInfo(errs, ast.NativeRep().SourceInfo()) |
| 464 | for _, v := range e.validators { |
| 465 | v.Validate(e, vConfig, checked, iss) |
| 466 | } |
| 467 | if iss.Err() != nil { |
| 468 | return nil, iss |
| 469 | } |
| 470 | return ast, nil |
| 471 | } |
| 472 | |
| 473 | // configuredExpressionSizeLimit returns the effective expression size code point limit. |
| 474 | // A zero value means "use the parser default". |