-
Notifications
You must be signed in to change notification settings - Fork 26
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
decoder: Decouple each validator into its own type
- Loading branch information
1 parent
01ef96c
commit ec39696
Showing
12 changed files
with
452 additions
and
237 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
package validator | ||
|
||
import ( | ||
"context" | ||
"fmt" | ||
|
||
"github.com/hashicorp/hcl-lang/schema" | ||
"github.com/hashicorp/hcl/v2" | ||
"github.com/hashicorp/hcl/v2/hclsyntax" | ||
) | ||
|
||
type DeprecatedAttribute struct{} | ||
|
||
func (v DeprecatedAttribute) Visit(ctx context.Context, node hclsyntax.Node, nodeSchema schema.Schema) (diags hcl.Diagnostics) { | ||
attr, ok := node.(*hclsyntax.Attribute) | ||
if !ok { | ||
return | ||
} | ||
|
||
if nodeSchema == nil { | ||
return | ||
} | ||
attrSchema := nodeSchema.(*schema.AttributeSchema) | ||
if attrSchema.IsDeprecated { | ||
diags = append(diags, &hcl.Diagnostic{ | ||
Severity: hcl.DiagWarning, | ||
Summary: fmt.Sprintf("%q is deprecated", attr.Name), | ||
Detail: fmt.Sprintf("Reason: %q", attrSchema.Description.Value), | ||
Subject: attr.SrcRange.Ptr(), | ||
}) | ||
} | ||
|
||
return | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
package validator | ||
|
||
import ( | ||
"context" | ||
"fmt" | ||
|
||
"github.com/hashicorp/hcl-lang/schema" | ||
"github.com/hashicorp/hcl/v2" | ||
"github.com/hashicorp/hcl/v2/hclsyntax" | ||
) | ||
|
||
type MissingRequiredAttribute struct{} | ||
|
||
func (v MissingRequiredAttribute) Visit(ctx context.Context, node hclsyntax.Node, nodeSchema schema.Schema) (diags hcl.Diagnostics) { | ||
body, ok := node.(*hclsyntax.Body) | ||
if !ok { | ||
return | ||
} | ||
|
||
if nodeSchema == nil { | ||
return | ||
} | ||
|
||
bodySchema := nodeSchema.(*schema.BodySchema) | ||
if bodySchema.Attributes == nil { | ||
return | ||
} | ||
|
||
for name, attr := range bodySchema.Attributes { | ||
if attr.IsRequired { | ||
_, ok := body.Attributes[name] | ||
if !ok { | ||
diags = append(diags, &hcl.Diagnostic{ | ||
Severity: hcl.DiagError, | ||
Summary: fmt.Sprintf("Required attribute %q not specified", name), | ||
Detail: fmt.Sprintf("An attribute named %q is required here", name), | ||
Subject: body.SrcRange.Ptr(), | ||
}) | ||
} | ||
} | ||
} | ||
|
||
return | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
package validator | ||
|
||
import ( | ||
"context" | ||
"fmt" | ||
|
||
"github.com/hashicorp/hcl-lang/schema" | ||
"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) { | ||
attr, ok := node.(*hclsyntax.Attribute) | ||
if !ok { | ||
return | ||
} | ||
|
||
if nodeSchema == nil { | ||
diags = append(diags, &hcl.Diagnostic{ | ||
Severity: hcl.DiagError, | ||
Summary: "Unexpected attribute", | ||
Detail: fmt.Sprintf("An attribute named %q is not expected here", attr.Name), | ||
Subject: attr.SrcRange.Ptr(), | ||
}) | ||
} | ||
|
||
return | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
package validator | ||
|
||
import ( | ||
"context" | ||
"fmt" | ||
|
||
"github.com/hashicorp/hcl-lang/schema" | ||
"github.com/hashicorp/hcl/v2" | ||
"github.com/hashicorp/hcl/v2/hclsyntax" | ||
) | ||
|
||
type DeprecatedBlock struct{} | ||
|
||
func (v DeprecatedBlock) Visit(ctx context.Context, node hclsyntax.Node, nodeSchema schema.Schema) (diags hcl.Diagnostics) { | ||
block, ok := node.(*hclsyntax.Block) | ||
if !ok { | ||
return | ||
} | ||
|
||
if nodeSchema == nil { | ||
return | ||
} | ||
blockSchema := nodeSchema.(*schema.BlockSchema) | ||
if blockSchema.IsDeprecated { | ||
diags = append(diags, &hcl.Diagnostic{ | ||
Severity: hcl.DiagWarning, | ||
Summary: fmt.Sprintf("%q is deprecated", block.Type), | ||
Detail: fmt.Sprintf("Reason: %q", blockSchema.Description.Value), | ||
Subject: block.TypeRange.Ptr(), | ||
}) | ||
} | ||
|
||
return | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
package validator | ||
|
||
import ( | ||
"context" | ||
"fmt" | ||
|
||
"github.com/hashicorp/hcl-lang/schema" | ||
"github.com/hashicorp/hcl/v2" | ||
"github.com/hashicorp/hcl/v2/hclsyntax" | ||
) | ||
|
||
type BlockLabelsLength struct{} | ||
|
||
func (v BlockLabelsLength) Visit(ctx context.Context, node hclsyntax.Node, nodeSchema schema.Schema) (diags hcl.Diagnostics) { | ||
block, ok := node.(*hclsyntax.Block) | ||
if !ok { | ||
return | ||
} | ||
|
||
if nodeSchema == nil { | ||
return | ||
} | ||
|
||
blockSchema := nodeSchema.(*schema.BlockSchema) | ||
|
||
validLabelNum := len(blockSchema.Labels) | ||
for i := range block.Labels { | ||
if i >= validLabelNum { | ||
diags = append(diags, &hcl.Diagnostic{ | ||
Severity: hcl.DiagError, | ||
Summary: fmt.Sprintf("Too many labels specified for %q", block.Type), | ||
Detail: fmt.Sprintf("Only %d label(s) are expected for %q blocks", validLabelNum, block.Type), | ||
Subject: block.LabelRanges[i].Ptr(), | ||
}) | ||
} | ||
} | ||
|
||
if validLabelNum > len(block.Labels) { | ||
diags = append(diags, &hcl.Diagnostic{ | ||
Severity: hcl.DiagError, | ||
Summary: fmt.Sprintf("Not enough labels specified for %q", block.Type), | ||
Detail: fmt.Sprintf("All %q blocks must have %d label(s)", block.Type, validLabelNum), | ||
Subject: block.TypeRange.Ptr(), | ||
}) | ||
} | ||
|
||
return | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,49 @@ | ||
package validator | ||
|
||
import ( | ||
"context" | ||
"fmt" | ||
|
||
"github.com/hashicorp/hcl-lang/schema" | ||
"github.com/hashicorp/hcl/v2" | ||
"github.com/hashicorp/hcl/v2/hclsyntax" | ||
) | ||
|
||
type MaxBlocks struct{} | ||
|
||
func (v MaxBlocks) Visit(ctx context.Context, node hclsyntax.Node, nodeSchema schema.Schema) (diags hcl.Diagnostics) { | ||
body, ok := node.(*hclsyntax.Body) | ||
if !ok { | ||
return | ||
} | ||
|
||
if nodeSchema == nil { | ||
return | ||
} | ||
|
||
foundBlocks := make(map[string]uint64) | ||
for _, block := range body.Blocks { | ||
if _, ok := foundBlocks[block.Type]; !ok { | ||
foundBlocks[block.Type] = 0 | ||
} | ||
|
||
foundBlocks[block.Type]++ | ||
} | ||
|
||
bodySchema := nodeSchema.(*schema.BodySchema) | ||
for name, blockSchema := range bodySchema.Blocks { | ||
if blockSchema.MaxItems != 0 { | ||
foundBlocks, ok := foundBlocks[name] | ||
if ok && foundBlocks > blockSchema.MaxItems { | ||
diags = append(diags, &hcl.Diagnostic{ | ||
Severity: hcl.DiagError, | ||
Summary: fmt.Sprintf("Too many blocks specified for %q", name), | ||
Detail: fmt.Sprintf("Only %d block(s) are expected for %q", blockSchema.MaxItems, name), | ||
Subject: node.Range().Ptr(), | ||
}) | ||
} | ||
} | ||
} | ||
|
||
return | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,49 @@ | ||
package validator | ||
|
||
import ( | ||
"context" | ||
"fmt" | ||
|
||
"github.com/hashicorp/hcl-lang/schema" | ||
"github.com/hashicorp/hcl/v2" | ||
"github.com/hashicorp/hcl/v2/hclsyntax" | ||
) | ||
|
||
type MinBlocks struct{} | ||
|
||
func (v MinBlocks) Visit(ctx context.Context, node hclsyntax.Node, nodeSchema schema.Schema) (diags hcl.Diagnostics) { | ||
body, ok := node.(*hclsyntax.Body) | ||
if !ok { | ||
return | ||
} | ||
|
||
if nodeSchema == nil { | ||
return | ||
} | ||
|
||
foundBlocks := make(map[string]uint64) | ||
for _, block := range body.Blocks { | ||
if _, ok := foundBlocks[block.Type]; !ok { | ||
foundBlocks[block.Type] = 0 | ||
} | ||
|
||
foundBlocks[block.Type]++ | ||
} | ||
|
||
bodySchema := nodeSchema.(*schema.BodySchema) | ||
for name, blockSchema := range bodySchema.Blocks { | ||
if blockSchema.MinItems != 0 { | ||
foundBlocks, ok := foundBlocks[name] | ||
if !ok || foundBlocks < blockSchema.MinItems { | ||
diags = append(diags, &hcl.Diagnostic{ | ||
Severity: hcl.DiagError, | ||
Summary: fmt.Sprintf("Too few blocks specified for %q", name), | ||
Detail: fmt.Sprintf("At least %d block(s) are expected for %q", blockSchema.MinItems, name), | ||
Subject: node.Range().Ptr(), | ||
}) | ||
} | ||
} | ||
} | ||
|
||
return | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
package validator | ||
|
||
import ( | ||
"context" | ||
"fmt" | ||
|
||
"github.com/hashicorp/hcl-lang/schema" | ||
"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) { | ||
block, ok := node.(*hclsyntax.Block) | ||
if !ok { | ||
return | ||
} | ||
|
||
if nodeSchema == nil { | ||
diags = append(diags, &hcl.Diagnostic{ | ||
Severity: hcl.DiagError, | ||
Summary: "Unexpected block", | ||
Detail: fmt.Sprintf("Blocks of type %q are not expected here", block.Type), | ||
Subject: block.TypeRange.Ptr(), | ||
}) | ||
} | ||
return | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
// Copyright (c) HashiCorp, Inc. | ||
// SPDX-License-Identifier: MPL-2.0 | ||
|
||
package validator | ||
|
||
import ( | ||
"context" | ||
|
||
"github.com/hashicorp/hcl-lang/schema" | ||
"github.com/hashicorp/hcl/v2" | ||
"github.com/hashicorp/hcl/v2/hclsyntax" | ||
) | ||
|
||
type Validator interface { | ||
Visit(ctx context.Context, node hclsyntax.Node, nodeSchema schema.Schema) hcl.Diagnostics | ||
} |
Oops, something went wrong.