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

Expose new kind of origins #112

Merged
merged 5 commits into from
Apr 6, 2022
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
2 changes: 2 additions & 0 deletions decoder/decoder.go
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,8 @@ func mergeBlockBodySchemas(block *hcl.Block, blockSchema *schema.BlockSchema) (*
for _, tBody := range depSchema.TargetableAs {
mergedSchema.TargetableAs = append(mergedSchema.TargetableAs, tBody)
}

mergedSchema.Targets = depSchema.Targets.Copy()
}

return mergedSchema, nil
Expand Down
8 changes: 8 additions & 0 deletions decoder/reference_origins.go
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,14 @@ func (d *PathDecoder) referenceOriginsInBody(body hcl.Body, bodySchema *schema.B
}
}

if aSchema.IsDepKey && bodySchema.Targets != nil {
origins = append(origins, reference.DirectOrigin{
Range: attr.Expr.Range(),
TargetPath: bodySchema.Targets.Path,
TargetRange: bodySchema.Targets.Range,
})
}

origins = append(origins, d.findOriginsInExpression(attr.Expr, aSchema.Expr)...)
}

Expand Down
15 changes: 14 additions & 1 deletion decoder/reference_targets.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,15 @@ func (d *Decoder) ReferenceTargetsForOriginAtPos(path lang.Path, file string, po
targetCtx := pathCtx
targetPath := path

if directOrigin, ok := origin.(reference.DirectOrigin); ok {
matchingTargets = append(matchingTargets, &ReferenceTarget{
OriginRange: origin.OriginRange(),
Path: directOrigin.TargetPath,
Range: directOrigin.TargetRange,
DefRangePtr: nil,
})
continue
}
if pathOrigin, ok := origin.(reference.PathOrigin); ok {
ctx, err := d.pathReader.PathContext(pathOrigin.TargetPath)
if err != nil {
Expand All @@ -42,7 +51,11 @@ func (d *Decoder) ReferenceTargetsForOriginAtPos(path lang.Path, file string, po
targetPath = pathOrigin.TargetPath
}

targets, ok := targetCtx.ReferenceTargets.Match(origin.Address(), origin.OriginConstraints())
matchableOrigin, ok := origin.(reference.MatchableOrigin)
if !ok {
continue
}
targets, ok := targetCtx.ReferenceTargets.Match(matchableOrigin.Address(), matchableOrigin.OriginConstraints())
if !ok {
// target not found
continue
Expand Down
43 changes: 43 additions & 0 deletions decoder/reference_targets_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -280,6 +280,49 @@ func TestReferenceTargetForOriginAtPos(t *testing.T) {
},
nil,
},
{
"direct origin target",
map[string]*PathContext{
dirPath: {
ReferenceTargets: reference.Targets{},
ReferenceOrigins: reference.Origins{
reference.DirectOrigin{
Range: hcl.Range{
Filename: "test.tf",
Start: hcl.Pos{Line: 1, Column: 1, Byte: 0},
End: hcl.Pos{Line: 1, Column: 6, Byte: 5},
},
TargetPath: lang.Path{Path: dirPath, LanguageID: "terraform"},
TargetRange: hcl.Range{
Filename: "target.tf",
Start: hcl.Pos{Line: 1, Column: 1, Byte: 0},
End: hcl.Pos{Line: 3, Column: 2, Byte: 15},
},
},
},
},
},
lang.Path{Path: dirPath},
"test.tf",
hcl.InitialPos,
ReferenceTargets{
{
OriginRange: hcl.Range{
Filename: "test.tf",
Start: hcl.Pos{Line: 1, Column: 1, Byte: 0},
End: hcl.Pos{Line: 1, Column: 6, Byte: 5},
},
Path: lang.Path{Path: dirPath, LanguageID: "terraform"},
Range: hcl.Range{
Filename: "target.tf",
Start: hcl.Pos{Line: 1, Column: 1, Byte: 0},
End: hcl.Pos{Line: 3, Column: 2, Byte: 15},
},
DefRangePtr: nil,
},
},
nil,
},
}

for i, tc := range testCases {
Expand Down
4 changes: 4 additions & 0 deletions reference/origin.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,10 @@ type Origin interface {
isOriginImpl() originSigil
Copy() Origin
OriginRange() hcl.Range
}

type MatchableOrigin interface {
Origin
OriginConstraints() OriginConstraints
Address() lang.Address
}
35 changes: 35 additions & 0 deletions reference/origin_direct.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
package reference

import (
"github.com/hashicorp/hcl-lang/lang"
"github.com/hashicorp/hcl/v2"
)

// DirectOrigin represents an origin which directly targets a file
// and doesn't need a matching target
type DirectOrigin struct {
// Range represents a range of a local traversal, attribute, or an expression
Range hcl.Range

// TargetPath represents what (directory) Path does the origin targets
TargetPath lang.Path

// TargetRange represents which file and line the origin targets
TargetRange hcl.Range
}

func (do DirectOrigin) Copy() Origin {
return DirectOrigin{
Range: do.Range,
TargetPath: do.TargetPath,
TargetRange: do.TargetRange,
}
}

func (DirectOrigin) isOriginImpl() originSigil {
return originSigil{}
}

func (do DirectOrigin) OriginRange() hcl.Range {
return do.Range
}
27 changes: 27 additions & 0 deletions reference/origins_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -501,6 +501,33 @@ func TestOrigins_Match(t *testing.T) {
},
},
},
{
"direct origin cannot be matched",
alphaPath,
Origins{
DirectOrigin{
Range: hcl.Range{
Filename: "origin.tf",
Start: hcl.InitialPos,
End: hcl.InitialPos,
},
TargetPath: betaPath,
TargetRange: hcl.Range{
Filename: "target.tf",
Start: hcl.InitialPos,
End: hcl.InitialPos,
},
},
},
alphaPath,
Target{
Addr: lang.Address{
lang.RootStep{Name: "test"},
},
Type: cty.String,
},
Origins{},
},
}
for i, tc := range testCases {
t.Run(fmt.Sprintf("%d-%s", i, tc.name), func(t *testing.T) {
Expand Down
2 changes: 1 addition & 1 deletion reference/targets_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ func TestTargets_Match(t *testing.T) {
testCases := []struct {
name string
targets Targets
origin Origin
origin MatchableOrigin
expectedTargets Targets
expectedFound bool
}{
Expand Down
21 changes: 21 additions & 0 deletions schema/body_schema.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,13 +31,22 @@ type BodySchema struct {
// TargetableAs represents how else the body may be targeted
// if not by its declarable attributes or blocks.
TargetableAs Targetables

// Targets represents a location targeted by the body, when used as a body
// dependent on an attribute (e.g. Terraform module source)
Targets *Target
}

type DocsLink struct {
URL string
Tooltip string
}

type Target struct {
Path lang.Path
Range hcl.Range
}

func (*BodySchema) isSchemaImpl() schemaImplSigil {
return schemaImplSigil{}
}
Expand Down Expand Up @@ -137,6 +146,7 @@ func (bs *BodySchema) Copy() *BodySchema {
AnyAttribute: bs.AnyAttribute.Copy(),
HoverURL: bs.HoverURL,
DocsLink: bs.DocsLink.Copy(),
Targets: bs.Targets.Copy(),
}

if bs.TargetableAs != nil {
Expand Down Expand Up @@ -173,3 +183,14 @@ func (dl *DocsLink) Copy() *DocsLink {
Tooltip: dl.Tooltip,
}
}

func (t *Target) Copy() *Target {
if t == nil {
return nil
}

return &Target{
Path: t.Path,
Range: t.Range,
}
}