Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

decoder: Decouple validators & make them pluggable via PathContext #318

Merged
merged 2 commits into from
Sep 19, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 4 additions & 3 deletions decoder/internal/walker/walker.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import (

"github.com/hashicorp/hcl-lang/decoder/internal/schemahelper"
"github.com/hashicorp/hcl-lang/schema"
"github.com/hashicorp/hcl-lang/schemacontext"
"github.com/hashicorp/hcl/v2"
"github.com/hashicorp/hcl/v2/hclsyntax"
)
Expand Down Expand Up @@ -74,8 +75,8 @@ func Walk(ctx context.Context, node hclsyntax.Node, nodeSchema schema.Schema, w
diags = diags.Extend(Walk(ctx, block, blockSchema, w))
}
}
ctx = schemahelper.WithFoundBlocks(ctx, foundBlocks)
ctx = schemahelper.WithDynamicBlocks(ctx, dynamicBlocks)
ctx = schemacontext.WithFoundBlocks(ctx, foundBlocks)
ctx = schemacontext.WithDynamicBlocks(ctx, dynamicBlocks)

diags = diags.Extend(w.Visit(ctx, node, nodeSchema))

Expand All @@ -89,7 +90,7 @@ func Walk(ctx context.Context, node hclsyntax.Node, nodeSchema schema.Schema, w
if ok && bSchema.Body != nil {
mergedSchema, ok := schemahelper.MergeBlockBodySchemas(nodeType.AsHCLBlock(), bSchema)
if !ok {
ctx = schemahelper.WithUnknownSchema(ctx)
ctx = schemacontext.WithUnknownSchema(ctx)
}
blockBodySchema = mergedSchema
}
Expand Down
2 changes: 2 additions & 0 deletions decoder/path_context.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import (

"github.com/hashicorp/hcl-lang/reference"
"github.com/hashicorp/hcl-lang/schema"
"github.com/hashicorp/hcl-lang/validator"
"github.com/hashicorp/hcl/v2"
)

Expand All @@ -20,6 +21,7 @@ type PathContext struct {
ReferenceTargets reference.Targets
Files map[string]*hcl.File
Functions map[string]schema.FunctionSignature
Validators []validator.Validator
}

type pathCtxKey struct{}
Expand Down
25 changes: 11 additions & 14 deletions decoder/validate.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,32 +6,25 @@ package decoder
import (
"context"

"github.com/hashicorp/hcl-lang/decoder/internal/validator"
"github.com/hashicorp/hcl-lang/decoder/internal/walker"
"github.com/hashicorp/hcl-lang/lang"
"github.com/hashicorp/hcl-lang/schema"
"github.com/hashicorp/hcl-lang/validator"
"github.com/hashicorp/hcl/v2"
"github.com/hashicorp/hcl/v2/hclsyntax"
)

var builtinValidators = []validator.Validator{
validator.BlockLabelsLength{},
validator.DeprecatedAttribute{},
validator.DeprecatedBlock{},
validator.MaxBlocks{},
validator.MinBlocks{},
validator.MissingRequiredAttribute{},
validator.UnexpectedAttribute{},
validator.UnexpectedBlock{},
}

// Validate returns a set of Diagnostics for all known files
func (d *PathDecoder) Validate(ctx context.Context) (lang.DiagnosticsMap, error) {
diags := make(lang.DiagnosticsMap)
if d.pathCtx.Schema == nil {
return diags, &NoSchemaError{}
}

if len(d.pathCtx.Validators) == 0 {
return diags, nil
}

// Validate module files per schema
for filename, f := range d.pathCtx.Files {
body, ok := f.Body.(*hclsyntax.Body)
Expand All @@ -41,7 +34,7 @@ func (d *PathDecoder) Validate(ctx context.Context) (lang.DiagnosticsMap, error)
}

diags[filename] = walker.Walk(ctx, body, d.pathCtx.Schema, validationWalker{
validators: builtinValidators,
validators: d.pathCtx.Validators,
})
}

Expand All @@ -54,6 +47,10 @@ func (d *PathDecoder) ValidateFile(ctx context.Context, filename string) (hcl.Di
return hcl.Diagnostics{}, &NoSchemaError{}
}

if len(d.pathCtx.Validators) == 0 {
return hcl.Diagnostics{}, nil
}

f, err := d.fileByName(filename)
if err != nil {
return hcl.Diagnostics{}, err
Expand All @@ -65,7 +62,7 @@ func (d *PathDecoder) ValidateFile(ctx context.Context, filename string) (hcl.Di
}

return walker.Walk(ctx, body, d.pathCtx.Schema, validationWalker{
validators: builtinValidators,
validators: d.pathCtx.Validators,
}), nil
}

Expand Down
14 changes: 14 additions & 0 deletions decoder/validate_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import (
"github.com/google/go-cmp/cmp"
"github.com/hashicorp/hcl-lang/lang"
"github.com/hashicorp/hcl-lang/schema"
"github.com/hashicorp/hcl-lang/validator"
"github.com/hashicorp/hcl/v2"
"github.com/hashicorp/hcl/v2/hclsyntax"
"github.com/zclconf/go-cty/cty"
Expand Down Expand Up @@ -951,6 +952,7 @@ wakka = 2
Files: map[string]*hcl.File{
"test.tf": f,
},
Validators: testValidators,
})

ctx := context.Background()
Expand Down Expand Up @@ -1026,6 +1028,7 @@ func TestValidate_schema_SingleFile(t *testing.T) {
Files: map[string]*hcl.File{
tc.filename: f,
},
Validators: testValidators,
})

ctx := context.Background()
Expand All @@ -1049,3 +1052,14 @@ func sortDiagnostics(diags hcl.Diagnostics) {
diags[i].Summary < diags[j].Summary
})
}

var testValidators = []validator.Validator{
validator.BlockLabelsLength{},
validator.DeprecatedAttribute{},
validator.DeprecatedBlock{},
validator.MaxBlocks{},
validator.MinBlocks{},
validator.MissingRequiredAttribute{},
validator.UnexpectedAttribute{},
validator.UnexpectedBlock{},
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// Copyright (c) HashiCorp, Inc.
// SPDX-License-Identifier: MPL-2.0

package schemahelper
package schemacontext

import "context"

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,16 +7,16 @@ import (
"context"
"fmt"

"github.com/hashicorp/hcl-lang/decoder/internal/schemahelper"
"github.com/hashicorp/hcl-lang/schema"
"github.com/hashicorp/hcl-lang/schemacontext"
"github.com/hashicorp/hcl/v2"
"github.com/hashicorp/hcl/v2/hclsyntax"
)

type UnexpectedAttribute struct{}

func (v UnexpectedAttribute) Visit(ctx context.Context, node hclsyntax.Node, nodeSchema schema.Schema) (diags hcl.Diagnostics) {
if schemahelper.HasUnknownSchema(ctx) {
if schemacontext.HasUnknownSchema(ctx) {
// Avoid checking for unexpected attributes
// if we cannot tell which ones are expected.
return
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@ import (
"context"
"fmt"

"github.com/hashicorp/hcl-lang/decoder/internal/schemahelper"
"github.com/hashicorp/hcl-lang/schema"
"github.com/hashicorp/hcl-lang/schemacontext"
"github.com/hashicorp/hcl/v2"
"github.com/hashicorp/hcl/v2/hclsyntax"
)
Expand All @@ -25,7 +25,7 @@ func (v MaxBlocks) Visit(ctx context.Context, node hclsyntax.Node, nodeSchema sc
return
}

foundBlocks := schemahelper.FoundBlocks(ctx)
foundBlocks := schemacontext.FoundBlocks(ctx)

bodySchema := nodeSchema.(*schema.BodySchema)
for name, blockSchema := range bodySchema.Blocks {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@ import (
"context"
"fmt"

"github.com/hashicorp/hcl-lang/decoder/internal/schemahelper"
"github.com/hashicorp/hcl-lang/schema"
"github.com/hashicorp/hcl-lang/schemacontext"
"github.com/hashicorp/hcl/v2"
"github.com/hashicorp/hcl/v2/hclsyntax"
)
Expand All @@ -25,8 +25,8 @@ func (v MinBlocks) Visit(ctx context.Context, node hclsyntax.Node, nodeSchema sc
return
}

foundBlocks := schemahelper.FoundBlocks(ctx)
dynamicBlocks := schemahelper.DynamicBlocks(ctx)
foundBlocks := schemacontext.FoundBlocks(ctx)
dynamicBlocks := schemacontext.DynamicBlocks(ctx)

bodySchema := nodeSchema.(*schema.BodySchema)
for name, blockSchema := range bodySchema.Blocks {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,16 +7,16 @@ import (
"context"
"fmt"

"github.com/hashicorp/hcl-lang/decoder/internal/schemahelper"
"github.com/hashicorp/hcl-lang/schema"
"github.com/hashicorp/hcl-lang/schemacontext"
"github.com/hashicorp/hcl/v2"
"github.com/hashicorp/hcl/v2/hclsyntax"
)

type UnexpectedBlock struct{}

func (v UnexpectedBlock) Visit(ctx context.Context, node hclsyntax.Node, nodeSchema schema.Schema) (diags hcl.Diagnostics) {
if schemahelper.HasUnknownSchema(ctx) {
if schemacontext.HasUnknownSchema(ctx) {
// Avoid checking for unexpected blocks
// if we cannot tell which ones are expected.
return
Expand Down
File renamed without changes.