Skip to content

Commit

Permalink
decoder: validate required attributes more selectively (hashicorp#1485)
Browse files Browse the repository at this point in the history
* deps: pin hcl-lang to 8254793

* decoder: validate required attributes more selectively

* deps: pin hcl-lang to c89603e93360
  • Loading branch information
radeksimko authored Nov 7, 2023
1 parent b100eaa commit 9ae6980
Show file tree
Hide file tree
Showing 4 changed files with 75 additions and 4 deletions.
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ require (
github.com/hashicorp/go-uuid v1.0.3
github.com/hashicorp/go-version v1.6.0
github.com/hashicorp/hc-install v0.6.1
github.com/hashicorp/hcl-lang v0.0.0-20231103134808-2ce7ad140f7c
github.com/hashicorp/hcl-lang v0.0.0-20231107133629-c89603e93360
github.com/hashicorp/hcl/v2 v2.19.1
github.com/hashicorp/terraform-exec v0.19.0
github.com/hashicorp/terraform-json v0.17.1
Expand Down
4 changes: 2 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -220,8 +220,8 @@ github.com/hashicorp/hc-install v0.6.1 h1:IGxShH7AVhPaSuSJpKtVi/EFORNjO+OYVJJrAt
github.com/hashicorp/hc-install v0.6.1/go.mod h1:0fW3jpg+wraYSnFDJ6Rlie3RvLf1bIqVIkzoon4KoVE=
github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4=
github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=
github.com/hashicorp/hcl-lang v0.0.0-20231103134808-2ce7ad140f7c h1:ppZ7NorEmcV4B7+M9DWd6nQNRSWs55RUebJzYOuAdc0=
github.com/hashicorp/hcl-lang v0.0.0-20231103134808-2ce7ad140f7c/go.mod h1:f8Trmd1qEAs00+y4etS5uTDqYhU3Z/pxJgzsTwWXWM8=
github.com/hashicorp/hcl-lang v0.0.0-20231107133629-c89603e93360 h1:qFawtGK8XOEXuzfNkntGk3+yhk7LusTB9kBw3nCyiWw=
github.com/hashicorp/hcl-lang v0.0.0-20231107133629-c89603e93360/go.mod h1:f8Trmd1qEAs00+y4etS5uTDqYhU3Z/pxJgzsTwWXWM8=
github.com/hashicorp/hcl/v2 v2.19.1 h1://i05Jqznmb2EXqa39Nsvyan2o5XyMowW5fnCKW5RPI=
github.com/hashicorp/hcl/v2 v2.19.1/go.mod h1:ThLC89FV4p9MPW804KVbe/cEXoQ8NZEh+JtMeeGErHE=
github.com/hashicorp/terraform-exec v0.19.0 h1:FpqZ6n50Tk95mItTSS9BjeOVUb4eg81SpgVtZNNtFSM=
Expand Down
70 changes: 70 additions & 0 deletions internal/decoder/validations/missing_required_attribute.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
// Copyright (c) HashiCorp, Inc.
// SPDX-License-Identifier: MPL-2.0

package validations

import (
"context"
"fmt"

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

type MissingRequiredAttribute struct{}

func (mra MissingRequiredAttribute) Visit(ctx context.Context, node hclsyntax.Node, nodeSchema schema.Schema) (context.Context, hcl.Diagnostics) {
var diags hcl.Diagnostics
if HasUnknownRequiredAttributes(ctx) {
return ctx, diags
}

switch nodeType := node.(type) {
case *hclsyntax.Block:
// Providers are excluded from the validation for the time being
// due to complexity around required attributes with dynamic defaults
// See https://github.com/hashicorp/vscode-terraform/issues/1616
nestingLvl, nestingOk := schemacontext.BlockNestingLevel(ctx)
if nodeType.Type == "provider" && (nestingOk && nestingLvl == 0) {
ctx = WithUnknownRequiredAttributes(ctx)
}
case *hclsyntax.Body:
if nodeSchema == nil {
return ctx, diags
}

bodySchema := nodeSchema.(*schema.BodySchema)
if bodySchema.Attributes == nil {
return ctx, diags
}

for name, attr := range bodySchema.Attributes {
if attr.IsRequired {
_, ok := nodeType.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: nodeType.SrcRange.Ptr(),
})
}
}
}
}

return ctx, diags
}

type unknownRequiredAttrsCtxKey struct{}

func HasUnknownRequiredAttributes(ctx context.Context) bool {
_, ok := ctx.Value(unknownRequiredAttrsCtxKey{}).(bool)
return ok
}

func WithUnknownRequiredAttributes(ctx context.Context) context.Context {
return context.WithValue(ctx, unknownRequiredAttrsCtxKey{}, true)
}
3 changes: 2 additions & 1 deletion internal/decoder/validators.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ package decoder

import (
"github.com/hashicorp/hcl-lang/validator"
"github.com/hashicorp/terraform-ls/internal/decoder/validations"
)

var moduleValidators = []validator.Validator{
Expand All @@ -13,7 +14,7 @@ var moduleValidators = []validator.Validator{
validator.DeprecatedBlock{},
validator.MaxBlocks{},
validator.MinBlocks{},
validator.MissingRequiredAttribute{},
validations.MissingRequiredAttribute{},
validator.UnexpectedAttribute{},
validator.UnexpectedBlock{},
}
Expand Down

0 comments on commit 9ae6980

Please sign in to comment.