Skip to content

Commit c20527a

Browse files
dbanckradeksimko
andauthored
Expose new kind of origins (#112)
* add new targets field to body schema * expose dependency key attributes as direct origins When the body schema has a valid `Targets` set, we expose all dependecy keys as DirectOrigin for go to definition. * merge Targets as part of the dependent body schema merger Co-authored-by: Radek Simko <[email protected]>
1 parent 89c6067 commit c20527a

File tree

9 files changed

+155
-2
lines changed

9 files changed

+155
-2
lines changed

decoder/decoder.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,8 @@ func mergeBlockBodySchemas(block *hcl.Block, blockSchema *schema.BlockSchema) (*
6969
for _, tBody := range depSchema.TargetableAs {
7070
mergedSchema.TargetableAs = append(mergedSchema.TargetableAs, tBody)
7171
}
72+
73+
mergedSchema.Targets = depSchema.Targets.Copy()
7274
}
7375

7476
return mergedSchema, nil

decoder/reference_origins.go

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,14 @@ func (d *PathDecoder) referenceOriginsInBody(body hcl.Body, bodySchema *schema.B
111111
}
112112
}
113113

114+
if aSchema.IsDepKey && bodySchema.Targets != nil {
115+
origins = append(origins, reference.DirectOrigin{
116+
Range: attr.Expr.Range(),
117+
TargetPath: bodySchema.Targets.Path,
118+
TargetRange: bodySchema.Targets.Range,
119+
})
120+
}
121+
114122
origins = append(origins, d.findOriginsInExpression(attr.Expr, aSchema.Expr)...)
115123
}
116124

decoder/reference_targets.go

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,15 @@ func (d *Decoder) ReferenceTargetsForOriginAtPos(path lang.Path, file string, po
3333
targetCtx := pathCtx
3434
targetPath := path
3535

36+
if directOrigin, ok := origin.(reference.DirectOrigin); ok {
37+
matchingTargets = append(matchingTargets, &ReferenceTarget{
38+
OriginRange: origin.OriginRange(),
39+
Path: directOrigin.TargetPath,
40+
Range: directOrigin.TargetRange,
41+
DefRangePtr: nil,
42+
})
43+
continue
44+
}
3645
if pathOrigin, ok := origin.(reference.PathOrigin); ok {
3746
ctx, err := d.pathReader.PathContext(pathOrigin.TargetPath)
3847
if err != nil {
@@ -42,7 +51,11 @@ func (d *Decoder) ReferenceTargetsForOriginAtPos(path lang.Path, file string, po
4251
targetPath = pathOrigin.TargetPath
4352
}
4453

45-
targets, ok := targetCtx.ReferenceTargets.Match(origin.Address(), origin.OriginConstraints())
54+
matchableOrigin, ok := origin.(reference.MatchableOrigin)
55+
if !ok {
56+
continue
57+
}
58+
targets, ok := targetCtx.ReferenceTargets.Match(matchableOrigin.Address(), matchableOrigin.OriginConstraints())
4659
if !ok {
4760
// target not found
4861
continue

decoder/reference_targets_test.go

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -280,6 +280,49 @@ func TestReferenceTargetForOriginAtPos(t *testing.T) {
280280
},
281281
nil,
282282
},
283+
{
284+
"direct origin target",
285+
map[string]*PathContext{
286+
dirPath: {
287+
ReferenceTargets: reference.Targets{},
288+
ReferenceOrigins: reference.Origins{
289+
reference.DirectOrigin{
290+
Range: hcl.Range{
291+
Filename: "test.tf",
292+
Start: hcl.Pos{Line: 1, Column: 1, Byte: 0},
293+
End: hcl.Pos{Line: 1, Column: 6, Byte: 5},
294+
},
295+
TargetPath: lang.Path{Path: dirPath, LanguageID: "terraform"},
296+
TargetRange: hcl.Range{
297+
Filename: "target.tf",
298+
Start: hcl.Pos{Line: 1, Column: 1, Byte: 0},
299+
End: hcl.Pos{Line: 3, Column: 2, Byte: 15},
300+
},
301+
},
302+
},
303+
},
304+
},
305+
lang.Path{Path: dirPath},
306+
"test.tf",
307+
hcl.InitialPos,
308+
ReferenceTargets{
309+
{
310+
OriginRange: hcl.Range{
311+
Filename: "test.tf",
312+
Start: hcl.Pos{Line: 1, Column: 1, Byte: 0},
313+
End: hcl.Pos{Line: 1, Column: 6, Byte: 5},
314+
},
315+
Path: lang.Path{Path: dirPath, LanguageID: "terraform"},
316+
Range: hcl.Range{
317+
Filename: "target.tf",
318+
Start: hcl.Pos{Line: 1, Column: 1, Byte: 0},
319+
End: hcl.Pos{Line: 3, Column: 2, Byte: 15},
320+
},
321+
DefRangePtr: nil,
322+
},
323+
},
324+
nil,
325+
},
283326
}
284327

285328
for i, tc := range testCases {

reference/origin.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,10 @@ type Origin interface {
1111
isOriginImpl() originSigil
1212
Copy() Origin
1313
OriginRange() hcl.Range
14+
}
15+
16+
type MatchableOrigin interface {
17+
Origin
1418
OriginConstraints() OriginConstraints
1519
Address() lang.Address
1620
}

reference/origin_direct.go

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
package reference
2+
3+
import (
4+
"github.com/hashicorp/hcl-lang/lang"
5+
"github.com/hashicorp/hcl/v2"
6+
)
7+
8+
// DirectOrigin represents an origin which directly targets a file
9+
// and doesn't need a matching target
10+
type DirectOrigin struct {
11+
// Range represents a range of a local traversal, attribute, or an expression
12+
Range hcl.Range
13+
14+
// TargetPath represents what (directory) Path does the origin targets
15+
TargetPath lang.Path
16+
17+
// TargetRange represents which file and line the origin targets
18+
TargetRange hcl.Range
19+
}
20+
21+
func (do DirectOrigin) Copy() Origin {
22+
return DirectOrigin{
23+
Range: do.Range,
24+
TargetPath: do.TargetPath,
25+
TargetRange: do.TargetRange,
26+
}
27+
}
28+
29+
func (DirectOrigin) isOriginImpl() originSigil {
30+
return originSigil{}
31+
}
32+
33+
func (do DirectOrigin) OriginRange() hcl.Range {
34+
return do.Range
35+
}

reference/origins_test.go

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -501,6 +501,33 @@ func TestOrigins_Match(t *testing.T) {
501501
},
502502
},
503503
},
504+
{
505+
"direct origin cannot be matched",
506+
alphaPath,
507+
Origins{
508+
DirectOrigin{
509+
Range: hcl.Range{
510+
Filename: "origin.tf",
511+
Start: hcl.InitialPos,
512+
End: hcl.InitialPos,
513+
},
514+
TargetPath: betaPath,
515+
TargetRange: hcl.Range{
516+
Filename: "target.tf",
517+
Start: hcl.InitialPos,
518+
End: hcl.InitialPos,
519+
},
520+
},
521+
},
522+
alphaPath,
523+
Target{
524+
Addr: lang.Address{
525+
lang.RootStep{Name: "test"},
526+
},
527+
Type: cty.String,
528+
},
529+
Origins{},
530+
},
504531
}
505532
for i, tc := range testCases {
506533
t.Run(fmt.Sprintf("%d-%s", i, tc.name), func(t *testing.T) {

reference/targets_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ func TestTargets_Match(t *testing.T) {
1616
testCases := []struct {
1717
name string
1818
targets Targets
19-
origin Origin
19+
origin MatchableOrigin
2020
expectedTargets Targets
2121
expectedFound bool
2222
}{

schema/body_schema.go

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,13 +31,22 @@ type BodySchema struct {
3131
// TargetableAs represents how else the body may be targeted
3232
// if not by its declarable attributes or blocks.
3333
TargetableAs Targetables
34+
35+
// Targets represents a location targeted by the body, when used as a body
36+
// dependent on an attribute (e.g. Terraform module source)
37+
Targets *Target
3438
}
3539

3640
type DocsLink struct {
3741
URL string
3842
Tooltip string
3943
}
4044

45+
type Target struct {
46+
Path lang.Path
47+
Range hcl.Range
48+
}
49+
4150
func (*BodySchema) isSchemaImpl() schemaImplSigil {
4251
return schemaImplSigil{}
4352
}
@@ -137,6 +146,7 @@ func (bs *BodySchema) Copy() *BodySchema {
137146
AnyAttribute: bs.AnyAttribute.Copy(),
138147
HoverURL: bs.HoverURL,
139148
DocsLink: bs.DocsLink.Copy(),
149+
Targets: bs.Targets.Copy(),
140150
}
141151

142152
if bs.TargetableAs != nil {
@@ -173,3 +183,14 @@ func (dl *DocsLink) Copy() *DocsLink {
173183
Tooltip: dl.Tooltip,
174184
}
175185
}
186+
187+
func (t *Target) Copy() *Target {
188+
if t == nil {
189+
return nil
190+
}
191+
192+
return &Target{
193+
Path: t.Path,
194+
Range: t.Range,
195+
}
196+
}

0 commit comments

Comments
 (0)