Skip to content

Commit

Permalink
Go to references
Browse files Browse the repository at this point in the history
  • Loading branch information
radeksimko committed Jul 1, 2021
1 parent 8f1555b commit f0edbbc
Show file tree
Hide file tree
Showing 15 changed files with 224 additions and 6 deletions.
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -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-20210625140347-b5b9a34fd1c6
github.com/hashicorp/hcl-lang v0.0.0-20210701133135-82f993a5569d
github.com/hashicorp/hcl/v2 v2.10.0
github.com/hashicorp/terraform-exec v0.14.0
github.com/hashicorp/terraform-json v0.12.0
Expand Down
4 changes: 2 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -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-20210625140347-b5b9a34fd1c6 h1:vhjdOf16VR3QOrLOR9Il8Vjyswr6RkT6G5UuvZyWDLQ=
github.com/hashicorp/hcl-lang v0.0.0-20210625140347-b5b9a34fd1c6/go.mod h1:rDEzcPJU1AYRanWbpH9AZEik9i+jv1aoKkwqjfs7NyA=
github.com/hashicorp/hcl-lang v0.0.0-20210701133135-82f993a5569d h1:7F3+g9n7Xo7hDjGK0+C3mK9TUM4z4MvP+3kkx5nYBRg=
github.com/hashicorp/hcl-lang v0.0.0-20210701133135-82f993a5569d/go.mod h1:rDEzcPJU1AYRanWbpH9AZEik9i+jv1aoKkwqjfs7NyA=
github.com/hashicorp/hcl/v2 v2.10.0 h1:1S1UnuhDGlv3gRFV4+0EdwB+znNP5HmcGbIqwnSCByg=
github.com/hashicorp/hcl/v2 v2.10.0/go.mod h1:FwWsfWEjyV/CMj8s/gqAuiviY72rJ1/oayI9WftqcKg=
github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO+LraFDTW64=
Expand Down
4 changes: 4 additions & 0 deletions internal/decoder/decoder.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,10 @@ func DecoderForModule(ctx context.Context, mod module.Module) (*decoder.Decoder,
return mod.RefTargets
})

d.SetReferenceOriginReader(func() lang.ReferenceOrigins {
return mod.RefOrigins
})

d.SetUtmSource("terraform-ls")
d.UseUtmContent(true)

Expand Down
5 changes: 5 additions & 0 deletions internal/langserver/handlers/did_change.go
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ func TextDocumentDidChange(ctx context.Context, params lsp.DidChangeTextDocument
if err != nil {
return err
}
// TODO: parallelise the operations below in a workgroup
err = modMgr.EnqueueModuleOpWait(mod.Path, op.OpTypeLoadModuleMetadata)
if err != nil {
return err
Expand All @@ -75,6 +76,10 @@ func TextDocumentDidChange(ctx context.Context, params lsp.DidChangeTextDocument
if err != nil {
return err
}
err = modMgr.EnqueueModuleOpWait(mod.Path, op.OpTypeDecodeReferenceOrigins)
if err != nil {
return err
}

diags, err := lsctx.Diagnostics(ctx)
if err != nil {
Expand Down
1 change: 1 addition & 0 deletions internal/langserver/handlers/did_open.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ func (lh *logHandler) TextDocumentDidOpen(ctx context.Context, params lsp.DidOpe
modMgr.EnqueueModuleOpWait(mod.Path, op.OpTypeParseVariables)
modMgr.EnqueueModuleOpWait(mod.Path, op.OpTypeLoadModuleMetadata)
modMgr.EnqueueModuleOpWait(mod.Path, op.OpTypeDecodeReferenceTargets)
modMgr.EnqueueModuleOpWait(mod.Path, op.OpTypeDecodeReferenceOrigins)

if mod.TerraformVersionState == op.OpStateUnknown {
modMgr.EnqueueModuleOp(mod.Path, op.OpTypeGetTerraformVersion)
Expand Down
1 change: 1 addition & 0 deletions internal/langserver/handlers/handlers_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ func initializeResponse(t *testing.T, commandPrefix string) string {
},
"hoverProvider": true,
"signatureHelpProvider": {},
"referencesProvider": true,
"documentSymbolProvider": true,
"codeLensProvider": {},
"documentLinkProvider": {},
Expand Down
1 change: 1 addition & 0 deletions internal/langserver/handlers/initialize.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ func (lh *logHandler) Initialize(ctx context.Context, params lsp.InitializeParam
TriggerCharacters: []string{".", "["},
},
CodeLensProvider: lsp.CodeLensOptions{},
ReferencesProvider: true,
HoverProvider: true,
DocumentFormattingProvider: true,
DocumentSymbolProvider: true,
Expand Down
68 changes: 68 additions & 0 deletions internal/langserver/handlers/references.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
package handlers

import (
"context"

lsctx "github.com/hashicorp/terraform-ls/internal/context"
ilsp "github.com/hashicorp/terraform-ls/internal/lsp"
lsp "github.com/hashicorp/terraform-ls/internal/protocol"
)

func (h *logHandler) References(ctx context.Context, params lsp.ReferenceParams) ([]lsp.Location, error) {
list := make([]lsp.Location, 0)

fs, err := lsctx.DocumentStorage(ctx)
if err != nil {
return list, err
}

mf, err := lsctx.ModuleFinder(ctx)
if err != nil {
return list, err
}

file, err := fs.GetDocument(ilsp.FileHandlerFromDocumentURI(params.TextDocument.URI))
if err != nil {
return list, err
}

mod, err := mf.ModuleByPath(file.Dir())
if err != nil {
return list, err
}

schema, err := schemaForDocument(mf, file)
if err != nil {
return list, err
}

d, err := decoderForDocument(ctx, mod, file.LanguageID())
if err != nil {
return list, err
}
d.SetSchema(schema)

fPos, err := ilsp.FilePositionFromDocumentPosition(params.TextDocumentPositionParams, file)
if err != nil {
return list, err
}

refTarget, err := d.OutermostReferenceTargetAtPos(fPos.Filename(), fPos.Position())
if err != nil {
return list, err
}
if refTarget == nil {
// 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 target: %#v", refTarget)

origins, err := d.ReferenceOriginsTargeting(*refTarget)
if err != nil {
return list, err
}

return ilsp.RefOriginsToLocations(mod.Path, origins), nil
}
11 changes: 11 additions & 0 deletions internal/langserver/handlers/service.go
Original file line number Diff line number Diff line change
Expand Up @@ -301,6 +301,17 @@ func (svc *service) Assigner() (jrpc2.Assigner, error) {

return handle(ctx, req, lh.TextDocumentDidSave)
},
"textDocument/references": func(ctx context.Context, req *jrpc2.Request) (interface{}, error) {
err := session.CheckInitializationIsConfirmed()
if err != nil {
return nil, err
}

ctx = lsctx.WithDocumentStorage(ctx, svc.fs)
ctx = lsctx.WithModuleFinder(ctx, svc.modMgr)

return handle(ctx, req, lh.References)
},
"workspace/executeCommand": func(ctx context.Context, req *jrpc2.Request) (interface{}, error) {
err := session.CheckInitializationIsConfirmed()
if err != nil {
Expand Down
23 changes: 23 additions & 0 deletions internal/lsp/locations.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package lsp

import (
"path/filepath"

"github.com/hashicorp/hcl-lang/lang"
lsp "github.com/hashicorp/terraform-ls/internal/protocol"
"github.com/hashicorp/terraform-ls/internal/uri"
)

func RefOriginsToLocations(originModPath string, origins lang.ReferenceOrigins) []lsp.Location {
locations := make([]lsp.Location, len(origins))

for i, origin := range origins {
originUri := uri.FromPath(filepath.Join(originModPath, origin.Range.Filename))
locations[i] = lsp.Location{
URI: lsp.DocumentURI(originUri),
Range: HCLRangeToLSP(origin.Range),
}
}

return locations
}
51 changes: 51 additions & 0 deletions internal/state/module.go
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,10 @@ type Module struct {
RefTargetsErr error
RefTargetsState op.OpState

RefOrigins lang.ReferenceOrigins
RefOriginsErr error
RefOriginsState op.OpState

ParsedModuleFiles map[string]*hcl.File
ParsedVarsFiles map[string]*hcl.File
ModuleParsingErr error
Expand Down Expand Up @@ -106,6 +110,10 @@ func (m *Module) Copy() *Module {
RefTargetsErr: m.RefTargetsErr,
RefTargetsState: m.RefTargetsState,

RefOrigins: m.RefOrigins.Copy(),
RefOriginsErr: m.RefOriginsErr,
RefOriginsState: m.RefOriginsState,

ModuleParsingErr: m.ModuleParsingErr,
VarsParsingErr: m.VarsParsingErr,
ModuleParsingState: m.ModuleParsingState,
Expand Down Expand Up @@ -617,3 +625,46 @@ func (s *ModuleStore) UpdateReferenceTargets(path string, refs lang.ReferenceTar
txn.Commit()
return nil
}

func (s *ModuleStore) SetReferenceOriginsState(path string, state op.OpState) error {
txn := s.db.Txn(true)
defer txn.Abort()

mod, err := moduleByPath(txn, path)
if err != nil {
return err
}

mod.RefOriginsState = state
err = txn.Insert(s.tableName, mod)
if err != nil {
return err
}

txn.Commit()
return nil
}

func (s *ModuleStore) UpdateReferenceOrigins(path string, origins lang.ReferenceOrigins, roErr error) error {
txn := s.db.Txn(true)
txn.Defer(func() {
s.SetReferenceOriginsState(path, op.OpStateLoaded)
})
defer txn.Abort()

mod, err := moduleByPath(txn, path)
if err != nil {
return err
}

mod.RefOrigins = origins
mod.RefOriginsErr = roErr

err = txn.Insert(s.tableName, mod)
if err != nil {
return err
}

txn.Commit()
return nil
}
14 changes: 13 additions & 1 deletion internal/terraform/module/module_loader.go
Original file line number Diff line number Diff line change
Expand Up @@ -190,7 +190,13 @@ func (ml *moduleLoader) executeModuleOp(ctx context.Context, modOp ModuleOperati
case op.OpTypeDecodeReferenceTargets:
err := DecodeReferenceTargets(ml.modStore, ml.schemaStore, modOp.ModulePath)
if err != nil {
ml.logger.Printf("failed to decode references: %s", err)
ml.logger.Printf("failed to decode reference targets: %s", err)
}
return
case op.OpTypeDecodeReferenceOrigins:
err := DecodeReferenceOrigins(ml.modStore, ml.schemaStore, modOp.ModulePath)
if err != nil {
ml.logger.Printf("failed to decode reference origins: %s", err)
}
return
}
Expand Down Expand Up @@ -250,6 +256,12 @@ func (ml *moduleLoader) EnqueueModuleOp(modOp ModuleOperation) error {
return nil
}
ml.modStore.SetReferenceTargetsState(modOp.ModulePath, op.OpStateQueued)
case op.OpTypeDecodeReferenceOrigins:
if mod.MetaState == op.OpStateQueued {
// avoid enqueuing duplicate operation
return nil
}
ml.modStore.SetReferenceOriginsState(modOp.ModulePath, op.OpStateQueued)
}

ml.queue.PushOp(modOp)
Expand Down
39 changes: 39 additions & 0 deletions internal/terraform/module/module_ops.go
Original file line number Diff line number Diff line change
Expand Up @@ -380,3 +380,42 @@ func DecodeReferenceTargets(modStore *state.ModuleStore, schemaReader state.Sche

return rErr
}

func DecodeReferenceOrigins(modStore *state.ModuleStore, schemaReader state.SchemaReader, modPath string) error {
err := modStore.SetReferenceOriginsState(modPath, op.OpStateLoading)
if err != nil {
return err
}

mod, err := modStore.ModuleByPath(modPath)
if err != nil {
return err
}

d := decoder.NewDecoder()
for name, f := range mod.ParsedModuleFiles {
err := d.LoadFile(name, f)
if err != nil {
return fmt.Errorf("failed to load a file: %w", err)
}
}

fullSchema, schemaErr := schemaForModule(mod, schemaReader)
if schemaErr != nil {
sErr := modStore.UpdateReferenceOrigins(modPath, lang.ReferenceOrigins{}, schemaErr)
if sErr != nil {
return sErr
}
return schemaErr
}
d.SetSchema(fullSchema)

origins, rErr := d.CollectReferenceOrigins()

sErr := modStore.UpdateReferenceOrigins(modPath, origins, rErr)
if sErr != nil {
return sErr
}

return rErr
}
5 changes: 3 additions & 2 deletions internal/terraform/module/operation/op_type_string.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions internal/terraform/module/operation/operation.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,4 +22,5 @@ const (
OpTypeParseModuleManifest
OpTypeLoadModuleMetadata
OpTypeDecodeReferenceTargets
OpTypeDecodeReferenceOrigins
)

0 comments on commit f0edbbc

Please sign in to comment.