From 8adc4a0222f4913c8d1747104ff2ecbfa7cd5e80 Mon Sep 17 00:00:00 2001 From: Radek Simko Date: Tue, 27 Jul 2021 16:36:05 +0100 Subject: [PATCH] fix: recognize references in lists and other complex types (#594) --- go.mod | 2 +- go.sum | 4 +- internal/langserver/handlers/code_lens.go | 42 +++++++++++++++---- .../langserver/handlers/go_to_ref_target.go | 1 + internal/langserver/handlers/references.go | 17 +++++--- 5 files changed, 48 insertions(+), 18 deletions(-) diff --git a/go.mod b/go.mod index 3f1cbc0b..0180ec17 100644 --- a/go.mod +++ b/go.mod @@ -12,7 +12,7 @@ require ( github.com/hashicorp/go-memdb v1.3.2 github.com/hashicorp/go-multierror v1.1.1 github.com/hashicorp/go-version v1.3.0 - github.com/hashicorp/hcl-lang v0.0.0-20210720185741-4775fe675507 + github.com/hashicorp/hcl-lang v0.0.0-20210727133229-454bfd2596ce github.com/hashicorp/hcl/v2 v2.10.1 github.com/hashicorp/terraform-exec v0.14.0 github.com/hashicorp/terraform-json v0.12.0 diff --git a/go.sum b/go.sum index 25bbd062..f0df40df 100644 --- a/go.sum +++ b/go.sum @@ -191,8 +191,8 @@ github.com/hashicorp/golang-lru v0.5.4/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uG 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-20210616121206-bd34ebcc883b/go.mod h1:uMsq6wV8ZXEH8qndov4tncXlHDYnZ8aHsGmS4T74e2o= -github.com/hashicorp/hcl-lang v0.0.0-20210720185741-4775fe675507 h1:oJvWrjpJ631eWE/WLeNfVX7JXgEEIbavD17B70JA5bU= -github.com/hashicorp/hcl-lang v0.0.0-20210720185741-4775fe675507/go.mod h1:A1Pj/o2k+ADlN0onToNuOJWNuWywxV7towLQmzU8dfU= +github.com/hashicorp/hcl-lang v0.0.0-20210727133229-454bfd2596ce h1:XekCZzsJL95UGIMEWHBdPjGSPpi8uxU91zRghDbRgTc= +github.com/hashicorp/hcl-lang v0.0.0-20210727133229-454bfd2596ce/go.mod h1:xzXU6Fn+TWVaZUFxV8CyAsObi2oMgSEFAmLvCx2ArzM= github.com/hashicorp/hcl/v2 v2.10.0/go.mod h1:FwWsfWEjyV/CMj8s/gqAuiviY72rJ1/oayI9WftqcKg= github.com/hashicorp/hcl/v2 v2.10.1 h1:h4Xx4fsrRE26ohAk/1iGF/JBqRQbyUqu5Lvj60U54ys= github.com/hashicorp/hcl/v2 v2.10.1/go.mod h1:FwWsfWEjyV/CMj8s/gqAuiviY72rJ1/oayI9WftqcKg= diff --git a/internal/langserver/handlers/code_lens.go b/internal/langserver/handlers/code_lens.go index 54ca55f7..025dea17 100644 --- a/internal/langserver/handlers/code_lens.go +++ b/internal/langserver/handlers/code_lens.go @@ -5,6 +5,7 @@ import ( "encoding/json" "fmt" + "github.com/hashicorp/hcl-lang/lang" "github.com/hashicorp/hcl/v2" lsctx "github.com/hashicorp/terraform-ls/internal/context" "github.com/hashicorp/terraform-ls/internal/filesystem" @@ -76,20 +77,43 @@ func referenceCountCodeLens(ctx context.Context, doc filesystem.Document) []lsp. return list } + // There can be two targets pointing to the same range + // e.g. when a block is targettable as type-less reference + // and as an object, which is important in most contexts + // but not here, where we present it to the user. + dedupedTargets := make(map[hcl.Range]lang.ReferenceTargets, 0) for _, refTarget := range refTargets { - origins, err := d.ReferenceOriginsTargeting(refTarget) - if err != nil { - continue + rng := *refTarget.RangePtr + if _, ok := dedupedTargets[rng]; !ok { + dedupedTargets[rng] = make(lang.ReferenceTargets, 0) + } + dedupedTargets[rng] = append(dedupedTargets[rng], refTarget) + } + + for rng, refTargets := range dedupedTargets { + originCount := 0 + var defRange *hcl.Range + for _, refTarget := range refTargets { + if refTarget.DefRangePtr != nil { + defRange = refTarget.DefRangePtr + } + + origins, err := d.ReferenceOriginsTargeting(refTarget) + if err != nil { + continue + } + originCount += len(origins) } - if len(origins) == 0 { + + if originCount == 0 { continue } var pos hcl.Pos - if refTarget.DefRangePtr != nil { - pos = posMiddleOfRange(refTarget.DefRangePtr) + if defRange != nil { + pos = posMiddleOfRange(defRange) } else { - pos = posMiddleOfRange(refTarget.RangePtr) + pos = posMiddleOfRange(&rng) } posBytes, err := json.Marshal(ilsp.HCLPosToLSP(pos)) @@ -98,9 +122,9 @@ func referenceCountCodeLens(ctx context.Context, doc filesystem.Document) []lsp. } list = append(list, lsp.CodeLens{ - Range: ilsp.HCLRangeToLSP(*refTarget.RangePtr), + Range: ilsp.HCLRangeToLSP(rng), Command: lsp.Command{ - Title: getTitle("reference", "references", len(origins)), + Title: getTitle("reference", "references", originCount), Command: showReferencesCmd, Arguments: []json.RawMessage{ json.RawMessage(posBytes), diff --git a/internal/langserver/handlers/go_to_ref_target.go b/internal/langserver/handlers/go_to_ref_target.go index dba63430..6bd1ed0d 100644 --- a/internal/langserver/handlers/go_to_ref_target.go +++ b/internal/langserver/handlers/go_to_ref_target.go @@ -58,6 +58,7 @@ func (h *logHandler) GoToReferenceTarget(ctx context.Context, params lsp.TextDoc if origin == nil { return nil, nil } + h.logger.Printf("found origin: %#v", origin) target, err := d.ReferenceTargetForOrigin(*origin) if err != nil { diff --git a/internal/langserver/handlers/references.go b/internal/langserver/handlers/references.go index fde65ab2..08ce4052 100644 --- a/internal/langserver/handlers/references.go +++ b/internal/langserver/handlers/references.go @@ -3,6 +3,7 @@ package handlers import ( "context" + "github.com/hashicorp/hcl-lang/lang" lsctx "github.com/hashicorp/terraform-ls/internal/context" ilsp "github.com/hashicorp/terraform-ls/internal/lsp" lsp "github.com/hashicorp/terraform-ls/internal/protocol" @@ -47,21 +48,25 @@ func (h *logHandler) References(ctx context.Context, params lsp.ReferenceParams) return list, err } - refTarget, err := d.InnermostReferenceTargetAtPos(fPos.Filename(), fPos.Position()) + refTargets, err := d.InnermostReferenceTargetsAtPos(fPos.Filename(), fPos.Position()) if err != nil { return list, err } - if refTarget == nil { + if len(refTargets) == 0 { // this position is not addressable h.logger.Printf("position is not addressable: %s - %#v", fPos.Filename(), fPos.Position()) return list, nil } - h.logger.Printf("finding origins for inner-most target: %#v", refTarget) + h.logger.Printf("finding origins for inner-most targets: %#v", refTargets) - origins, err := d.ReferenceOriginsTargeting(*refTarget) - if err != nil { - return list, err + origins := make(lang.ReferenceOrigins, 0) + for _, refTarget := range refTargets { + refOrigins, err := d.ReferenceOriginsTargeting(refTarget) + if err != nil { + return list, err + } + origins = append(origins, refOrigins...) } return ilsp.RefOriginsToLocations(mod.Path, origins), nil