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

Replace internal watcher with LSP's watching mechanism #953

Merged
merged 2 commits into from
Jun 17, 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
1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ require (
github.com/mitchellh/cli v1.1.4
github.com/mitchellh/go-homedir v1.1.0
github.com/mitchellh/mapstructure v1.5.0
github.com/otiai10/copy v1.7.0 // indirect
github.com/pmezard/go-difflib v1.0.0
github.com/shurcooL/httpfs v0.0.0-20190707220628-8d4bc4ba7749 // indirect
github.com/shurcooL/vfsgen v0.0.0-20200824052919-0d455de96546
Expand Down
6 changes: 6 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -462,6 +462,12 @@ github.com/nsf/termbox-go v0.0.0-20190121233118-02980233997d/go.mod h1:IuKpRQcYE
github.com/nsf/termbox-go v1.1.1/go.mod h1:T0cTdVuOwf7pHQNtfhnEbzHbcNyCEcVU4YPpouCbVxo=
github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec=
github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY=
github.com/otiai10/copy v1.7.0 h1:hVoPiN+t+7d2nzzwMiDHPSOogsWAStewq3TwU05+clE=
github.com/otiai10/copy v1.7.0/go.mod h1:rmRl6QPdJj6EiUqXQ/4Nn2lLXoNQjFCQbbNrxgc/t3U=
github.com/otiai10/curr v0.0.0-20150429015615-9b4961190c95/go.mod h1:9qAhocn7zKJG+0mI8eUu6xqkFDYS2kb2saOteoSB3cE=
github.com/otiai10/curr v1.0.0/go.mod h1:LskTG5wDwr8Rs+nNQ+1LlxRjAtTZZjtJW4rMXl6j4vs=
github.com/otiai10/mint v1.3.0/go.mod h1:F5AjcsTsWUqX+Na9fpHb52P8pcRX2CI6A3ctIT91xUo=
github.com/otiai10/mint v1.3.3/go.mod h1:/yxELlJQ0ufhjUwhshSj+wFjZ78CnZ48/1wtmBH1OTc=
github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc=
github.com/pascaldekloe/goe v0.1.0/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc=
github.com/pelletier/go-toml v1.9.4 h1:tjENF6MfZAg8e4ZmZTeWaWiT2vXtsoO6+iuOjFhECwM=
Expand Down
14 changes: 0 additions & 14 deletions internal/context/context.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ import (
"github.com/hashicorp/terraform-ls/internal/langserver/diagnostics"
lsp "github.com/hashicorp/terraform-ls/internal/protocol"
"github.com/hashicorp/terraform-ls/internal/settings"
"github.com/hashicorp/terraform-ls/internal/terraform/module"
)

type contextKey struct {
Expand All @@ -22,7 +21,6 @@ var (
ctxTfExecPath = &contextKey{"terraform executable path"}
ctxTfExecLogPath = &contextKey{"terraform executor log path"}
ctxTfExecTimeout = &contextKey{"terraform execution timeout"}
ctxWatcher = &contextKey{"watcher"}
ctxRootDir = &contextKey{"root directory"}
ctxCommandPrefix = &contextKey{"command prefix"}
ctxDiagsNotifier = &contextKey{"diagnostics notifier"}
Expand Down Expand Up @@ -53,18 +51,6 @@ func TerraformExecTimeout(ctx context.Context) (time.Duration, bool) {
return path, ok
}

func WithWatcher(ctx context.Context, w module.Watcher) context.Context {
return context.WithValue(ctx, ctxWatcher, w)
}

func Watcher(ctx context.Context) (module.Watcher, error) {
w, ok := ctx.Value(ctxWatcher).(module.Watcher)
if !ok {
return nil, missingContextErr(ctxWatcher)
}
return w, nil
}

func WithTerraformExecPath(ctx context.Context, path string) context.Context {
return context.WithValue(ctx, ctxTfExecPath, path)
}
Expand Down
89 changes: 89 additions & 0 deletions internal/langserver/handlers/did_change_watched_files.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,9 @@ import (
"github.com/hashicorp/terraform-ls/internal/job"
"github.com/hashicorp/terraform-ls/internal/protocol"
lsp "github.com/hashicorp/terraform-ls/internal/protocol"
"github.com/hashicorp/terraform-ls/internal/state"
"github.com/hashicorp/terraform-ls/internal/terraform/ast"
"github.com/hashicorp/terraform-ls/internal/terraform/datadir"
"github.com/hashicorp/terraform-ls/internal/uri"
)

Expand All @@ -21,6 +23,74 @@ func (svc *service) DidChangeWatchedFiles(ctx context.Context, params lsp.DidCha
for _, change := range params.Changes {
rawURI := string(change.URI)

// This is necessary because clients may not send delete notifications
// for individual nested files when the parent directory is deleted.
// VS Code / vscode-languageclient behaves this way.
if modUri, ok := datadir.ModuleUriFromDataDir(rawURI); ok {
modHandle := document.DirHandleFromURI(modUri)
if change.Type == protocol.Deleted {
// This is unlikely to happen unless the user manually removed files
// See https://github.com/hashicorp/terraform/issues/30005
err := svc.modStore.UpdateModManifest(modHandle.Path(), nil, nil)
if err != nil {
svc.logger.Printf("failed to remove module manifest for %q: %s", modHandle, err)
}
}
continue
}

if modUri, ok := datadir.ModuleUriFromPluginLockFile(rawURI); ok {
if change.Type == protocol.Deleted {
// This is unlikely to happen unless the user manually removed files
// See https://github.com/hashicorp/terraform/issues/30005
// Cached provider schema could be removed here but it may be useful
// in other modules, so we trade some memory for better UX here.
continue
}

modHandle := document.DirHandleFromURI(modUri)
err := svc.indexModuleIfNotExists(ctx, modHandle)
if err != nil {
svc.logger.Printf("failed to index module %q: %s", modHandle, err)
continue
}

jobIds, err := svc.indexer.PluginLockChanged(ctx, modHandle)
if err != nil {
svc.logger.Printf("error refreshing plugins for %q: %s", rawURI, err)
continue
}
ids = append(ids, jobIds...)
continue
}

if modUri, ok := datadir.ModuleUriFromModuleLockFile(rawURI); ok {
modHandle := document.DirHandleFromURI(modUri)
if change.Type == protocol.Deleted {
// This is unlikely to happen unless the user manually removed files
// See https://github.com/hashicorp/terraform/issues/30005
err := svc.modStore.UpdateModManifest(modHandle.Path(), nil, nil)
if err != nil {
svc.logger.Printf("failed to remove module manifest for %q: %s", modHandle, err)
}
continue
}

err := svc.indexModuleIfNotExists(ctx, modHandle)
if err != nil {
svc.logger.Printf("failed to index module %q: %s", modHandle, err)
continue
}

jobIds, err := svc.indexer.ModuleManifestChanged(ctx, modHandle)
if err != nil {
svc.logger.Printf("error refreshing plugins for %q: %s", modHandle, err)
continue
}
ids = append(ids, jobIds...)
continue
}

rawPath, err := uri.PathFromURI(rawURI)
if err != nil {
svc.logger.Printf("error parsing %q: %s", rawURI, err)
Expand Down Expand Up @@ -137,6 +207,25 @@ func (svc *service) DidChangeWatchedFiles(ctx context.Context, params lsp.DidCha
return nil
}

func (svc *service) indexModuleIfNotExists(ctx context.Context, modHandle document.DirHandle) error {
_, err := svc.modStore.ModuleByPath(modHandle.Path())
if err != nil {
if state.IsModuleNotFound(err) {
err = svc.stateStore.WalkerPaths.EnqueueDir(modHandle)
if err != nil {
return fmt.Errorf("failed to walk module %q: %w", modHandle, err)
}
err = svc.stateStore.WalkerPaths.WaitForDirs(ctx, []document.DirHandle{modHandle})
if err != nil {
return fmt.Errorf("failed to wait for module walk %q: %w", modHandle, err)
}
} else {
return fmt.Errorf("failed to find module %q: %w", modHandle, err)
}
}
return nil
}

func modHandleFromRawOsPath(ctx context.Context, rawPath string) (*parsedModuleHandle, error) {
fi, err := os.Stat(rawPath)
if err != nil {
Expand Down
Loading