Skip to content

Commit

Permalink
Support any *.tfvars files
Browse files Browse the repository at this point in the history
  • Loading branch information
radeksimko committed Aug 17, 2021
1 parent 0059475 commit e4e1051
Show file tree
Hide file tree
Showing 16 changed files with 353 additions and 187 deletions.
38 changes: 14 additions & 24 deletions internal/decoder/decoder.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,11 @@ package decoder

import (
"context"
"fmt"

"github.com/hashicorp/hcl-lang/decoder"
"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/terraform/ast"
"github.com/hashicorp/terraform-ls/internal/terraform/module"
)

Expand All @@ -30,36 +29,27 @@ func DecoderForModule(ctx context.Context, mod module.Module) (*decoder.Decoder,
d.SetUtmMedium(clientName)
}

err := loadFiles(d, mod.ParsedModuleFiles)
if err != nil {
return nil, err
for name, f := range mod.ParsedModuleFiles {
err := d.LoadFile(name.String(), f)
if err != nil {
// skip unreadable files
continue
}
}

return d, nil
}

func DecoderForVariables(mod module.Module) (*decoder.Decoder, error) {
func DecoderForVariables(varsFiles ast.VarsFiles) (*decoder.Decoder, error) {
d := decoder.NewDecoder()

err := loadFiles(d, mod.ParsedModuleFiles)
if err != nil {
return nil, err
}

err = loadFiles(d, mod.ParsedVarsFiles)
if err != nil {
return nil, err
}

return d, nil
}

func loadFiles(d *decoder.Decoder, files map[string]*hcl.File) error {
for name, f := range files {
err := d.LoadFile(name, f)
for name, f := range varsFiles {
err := d.LoadFile(name.String(), f)
if err != nil {
return fmt.Errorf("failed to load a file: %w", err)
// skip unreadable files
continue
}
}
return nil

return d, nil
}
21 changes: 11 additions & 10 deletions internal/filesystem/filesystem.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package filesystem
import (
"bytes"
"fmt"
"io/fs"
"io/ioutil"
"log"
"os"
Expand Down Expand Up @@ -206,37 +207,37 @@ func (fs *fsystem) ReadFile(name string) ([]byte, error) {
return b, err
}

func (fs *fsystem) ReadDir(name string) ([]os.FileInfo, error) {
memList, err := afero.ReadDir(fs.memFs, name)
func (fsys *fsystem) ReadDir(name string) ([]fs.DirEntry, error) {
memList, err := afero.NewIOFS(fsys.memFs).ReadDir(name)
if err != nil && !os.IsNotExist(err) {
return nil, fmt.Errorf("memory FS: %w", err)
}
osList, err := afero.ReadDir(fs.osFs, name)
osList, err := afero.NewIOFS(fsys.osFs).ReadDir(name)
if err != nil && !os.IsNotExist(err) {
return nil, fmt.Errorf("OS FS: %w", err)
}

list := memList
for _, osFi := range osList {
if fileIsInList(list, osFi) {
for _, osEntry := range osList {
if fileIsInList(list, osEntry) {
continue
}
list = append(list, osFi)
list = append(list, osEntry)
}

return list, nil
}

func fileIsInList(list []os.FileInfo, file os.FileInfo) bool {
for _, fi := range list {
if fi.Name() == file.Name() {
func fileIsInList(list []fs.DirEntry, entry fs.DirEntry) bool {
for _, di := range list {
if di.Name() == entry.Name() {
return true
}
}
return false
}

func (fs *fsystem) Open(name string) (File, error) {
func (fs *fsystem) Open(name string) (fs.File, error) {
f, err := fs.memFs.Open(name)
if err != nil && os.IsNotExist(err) {
return fs.osFs.Open(name)
Expand Down
9 changes: 5 additions & 4 deletions internal/filesystem/filesystem_test.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package filesystem

import (
"io/fs"
"io/ioutil"
"log"
"os"
Expand Down Expand Up @@ -317,10 +318,10 @@ func TestFilesystem_ReadDir_memFsOnly(t *testing.T) {
}
}

func namesFromFileInfos(fis []os.FileInfo) []string {
names := make([]string, len(fis), len(fis))
for i, fi := range fis {
names[i] = fi.Name()
func namesFromFileInfos(entries []fs.DirEntry) []string {
names := make([]string, len(entries), len(entries))
for i, entry := range entries {
names[i] = entry.Name()
}
return names
}
Expand Down
13 changes: 3 additions & 10 deletions internal/filesystem/types.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package filesystem

import (
"io/fs"
"log"
"os"

Expand Down Expand Up @@ -51,15 +52,7 @@ type Filesystem interface {

// direct FS methods
ReadFile(name string) ([]byte, error)
ReadDir(name string) ([]os.FileInfo, error)
Open(name string) (File, error)
ReadDir(name string) ([]fs.DirEntry, error)
Open(name string) (fs.File, error)
Stat(name string) (os.FileInfo, error)
}

// File represents an open file in FS
// See io/fs.File in http://golang.org/s/draft-iofs-design
type File interface {
Stat() (os.FileInfo, error)
Read([]byte) (int, error)
Close() error
}
4 changes: 2 additions & 2 deletions internal/langserver/handlers/command/validate.go
Original file line number Diff line number Diff line change
Expand Up @@ -69,8 +69,8 @@ func TerraformValidateHandler(ctx context.Context, args cmd.CommandArgs) (interf
validateDiags := diagnostics.HCLDiagsFromJSON(jsonDiags)
diags.EmptyRootDiagnostic()
diags.Append("terraform validate", validateDiags)
diags.Append("HCL", mod.ModuleDiagnostics)
diags.Append("HCL", mod.VarsDiagnostics)
diags.Append("HCL", mod.ModuleDiagnostics.AsMap())
diags.Append("HCL", mod.VarsDiagnostics.AutoloadedOnly().AsMap())

notifier.PublishHCLDiags(ctx, mod.Path, diags)

Expand Down
9 changes: 6 additions & 3 deletions internal/langserver/handlers/did_change.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import (
"github.com/hashicorp/terraform-ls/internal/langserver/diagnostics"
ilsp "github.com/hashicorp/terraform-ls/internal/lsp"
lsp "github.com/hashicorp/terraform-ls/internal/protocol"
"github.com/hashicorp/terraform-ls/internal/terraform/ast"
op "github.com/hashicorp/terraform-ls/internal/terraform/module/operation"
)

Expand Down Expand Up @@ -95,9 +96,11 @@ func TextDocumentDidChange(ctx context.Context, params lsp.DidChangeTextDocument

diags := diagnostics.NewDiagnostics()
diags.EmptyRootDiagnostic()
diags.Append("HCL", mod.ModuleDiagnostics)
diags.Append("HCL", mod.VarsDiagnostics)

diags.Append("HCL", mod.ModuleDiagnostics.AsMap())
diags.Append("HCL", mod.VarsDiagnostics.AutoloadedOnly().AsMap())
if vf, ok := ast.NewVarsFilename(f.Filename()); ok && !vf.IsAutoloaded() {
diags.Append("HCL", mod.VarsDiagnostics.ForFile(vf).AsMap())
}
notifier.PublishHCLDiags(ctx, mod.Path, diags)

return nil
Expand Down
24 changes: 23 additions & 1 deletion internal/langserver/handlers/did_close.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,12 @@ package handlers
import (
"context"

"github.com/hashicorp/hcl/v2"
lsctx "github.com/hashicorp/terraform-ls/internal/context"
"github.com/hashicorp/terraform-ls/internal/langserver/diagnostics"
ilsp "github.com/hashicorp/terraform-ls/internal/lsp"
lsp "github.com/hashicorp/terraform-ls/internal/protocol"
"github.com/hashicorp/terraform-ls/internal/terraform/ast"
)

func TextDocumentDidClose(ctx context.Context, params lsp.DidCloseTextDocumentParams) error {
Expand All @@ -15,5 +18,24 @@ func TextDocumentDidClose(ctx context.Context, params lsp.DidCloseTextDocumentPa
}

fh := ilsp.FileHandlerFromDocumentURI(params.TextDocument.URI)
return fs.CloseAndRemoveDocument(fh)
err = fs.CloseAndRemoveDocument(fh)
if err != nil {
return err
}

if vf, ok := ast.NewVarsFilename(fh.Filename()); ok && !vf.IsAutoloaded() {
notifier, err := lsctx.DiagnosticsNotifier(ctx)
if err != nil {
return err
}

diags := diagnostics.NewDiagnostics()
diags.EmptyRootDiagnostic()
diags.Append("HCL", map[string]hcl.Diagnostics{
fh.Filename(): {},
})
notifier.PublishHCLDiags(ctx, fh.Dir(), diags)
}

return nil
}
8 changes: 6 additions & 2 deletions internal/langserver/handlers/did_open.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (
"github.com/hashicorp/terraform-ls/internal/langserver/diagnostics"
ilsp "github.com/hashicorp/terraform-ls/internal/lsp"
lsp "github.com/hashicorp/terraform-ls/internal/protocol"
"github.com/hashicorp/terraform-ls/internal/terraform/ast"
"github.com/hashicorp/terraform-ls/internal/terraform/module"
op "github.com/hashicorp/terraform-ls/internal/terraform/module/operation"
)
Expand Down Expand Up @@ -76,8 +77,11 @@ func (lh *logHandler) TextDocumentDidOpen(ctx context.Context, params lsp.DidOpe

diags := diagnostics.NewDiagnostics()
diags.EmptyRootDiagnostic()
diags.Append("HCL", mod.ModuleDiagnostics)
diags.Append("HCL", mod.VarsDiagnostics)
diags.Append("HCL", mod.ModuleDiagnostics.AsMap())
diags.Append("HCL", mod.VarsDiagnostics.AutoloadedOnly().AsMap())
if vf, ok := ast.NewVarsFilename(f.Filename()); ok && !vf.IsAutoloaded() {
diags.Append("HCL", mod.VarsDiagnostics.ForFile(vf).AsMap())
}

notifier.PublishHCLDiags(ctx, mod.Path, diags)

Expand Down
3 changes: 2 additions & 1 deletion internal/langserver/handlers/service.go
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,7 @@ func (svc *service) Assigner() (jrpc2.Assigner, error) {
if err != nil {
return nil, err
}
ctx = lsctx.WithDiagnosticsNotifier(ctx, notifier)
ctx = lsctx.WithDocumentStorage(ctx, svc.fs)
return handle(ctx, req, TextDocumentDidClose)
},
Expand Down Expand Up @@ -500,7 +501,7 @@ func schemaForDocument(mf module.ModuleFinder, doc filesystem.Document) (*schema

func decoderForDocument(ctx context.Context, mod module.Module, languageID string) (*decoder.Decoder, error) {
if languageID == ilsp.Tfvars.String() {
return idecoder.DecoderForVariables(mod)
return idecoder.DecoderForVariables(mod.ParsedVarsFiles)
}
return idecoder.DecoderForModule(ctx, mod)
}
29 changes: 15 additions & 14 deletions internal/state/module.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import (
tfaddr "github.com/hashicorp/terraform-registry-address"
tfmod "github.com/hashicorp/terraform-schema/module"

"github.com/hashicorp/terraform-ls/internal/terraform/ast"
"github.com/hashicorp/terraform-ls/internal/terraform/datadir"
op "github.com/hashicorp/terraform-ls/internal/terraform/module/operation"
)
Expand Down Expand Up @@ -82,8 +83,8 @@ type Module struct {
RefOriginsErr error
RefOriginsState op.OpState

ParsedModuleFiles map[string]*hcl.File
ParsedVarsFiles map[string]*hcl.File
ParsedModuleFiles ast.ModFiles
ParsedVarsFiles ast.VarsFiles
ModuleParsingErr error
VarsParsingErr error
ModuleParsingState op.OpState
Expand All @@ -93,8 +94,8 @@ type Module struct {
MetaErr error
MetaState op.OpState

ModuleDiagnostics map[string]hcl.Diagnostics
VarsDiagnostics map[string]hcl.Diagnostics
ModuleDiagnostics ast.ModDiags
VarsDiagnostics ast.VarsDiags
}

func (m *Module) Copy() *Module {
Expand Down Expand Up @@ -135,23 +136,23 @@ func (m *Module) Copy() *Module {
}

if m.ParsedModuleFiles != nil {
newMod.ParsedModuleFiles = make(map[string]*hcl.File, len(m.ParsedModuleFiles))
newMod.ParsedModuleFiles = make(ast.ModFiles, len(m.ParsedModuleFiles))
for name, f := range m.ParsedModuleFiles {
// hcl.File is practically immutable once it comes out of parser
newMod.ParsedModuleFiles[name] = f
}
}

if m.ParsedVarsFiles != nil {
newMod.ParsedVarsFiles = make(map[string]*hcl.File, len(m.ParsedVarsFiles))
newMod.ParsedVarsFiles = make(ast.VarsFiles, len(m.ParsedVarsFiles))
for name, f := range m.ParsedVarsFiles {
// hcl.File is practically immutable once it comes out of parser
newMod.ParsedVarsFiles[name] = f
}
}

if m.ModuleDiagnostics != nil {
newMod.ModuleDiagnostics = make(map[string]hcl.Diagnostics, len(m.ModuleDiagnostics))
newMod.ModuleDiagnostics = make(ast.ModDiags, len(m.ModuleDiagnostics))
for name, diags := range m.ModuleDiagnostics {
newMod.ModuleDiagnostics[name] = make(hcl.Diagnostics, len(diags))
for i, diag := range diags {
Expand All @@ -162,7 +163,7 @@ func (m *Module) Copy() *Module {
}

if m.VarsDiagnostics != nil {
newMod.VarsDiagnostics = make(map[string]hcl.Diagnostics, len(m.VarsDiagnostics))
newMod.VarsDiagnostics = make(ast.VarsDiags, len(m.VarsDiagnostics))
for name, diags := range m.VarsDiagnostics {
newMod.VarsDiagnostics[name] = make(hcl.Diagnostics, len(diags))
for i, diag := range diags {
Expand Down Expand Up @@ -503,7 +504,7 @@ func (s *ModuleStore) SetVarsParsingState(path string, state op.OpState) error {
return nil
}

func (s *ModuleStore) UpdateParsedModuleFiles(path string, pFiles map[string]*hcl.File, pErr error) error {
func (s *ModuleStore) UpdateParsedModuleFiles(path string, pFiles ast.ModFiles, pErr error) error {
txn := s.db.Txn(true)
txn.Defer(func() {
s.SetModuleParsingState(path, op.OpStateLoaded)
Expand All @@ -528,7 +529,7 @@ func (s *ModuleStore) UpdateParsedModuleFiles(path string, pFiles map[string]*hc
return nil
}

func (s *ModuleStore) UpdateParsedVarsFiles(path string, pFiles map[string]*hcl.File, pErr error) error {
func (s *ModuleStore) UpdateParsedVarsFiles(path string, vFiles ast.VarsFiles, vErr error) error {
txn := s.db.Txn(true)
txn.Defer(func() {
s.SetVarsParsingState(path, op.OpStateLoaded)
Expand All @@ -540,9 +541,9 @@ func (s *ModuleStore) UpdateParsedVarsFiles(path string, pFiles map[string]*hcl.
return err
}

mod.ParsedVarsFiles = pFiles
mod.ParsedVarsFiles = vFiles

mod.VarsParsingErr = pErr
mod.VarsParsingErr = vErr

err = txn.Insert(s.tableName, mod)
if err != nil {
Expand Down Expand Up @@ -602,7 +603,7 @@ func (s *ModuleStore) UpdateMetadata(path string, meta *tfmod.Meta, mErr error)
return nil
}

func (s *ModuleStore) UpdateModuleDiagnostics(path string, diags map[string]hcl.Diagnostics) error {
func (s *ModuleStore) UpdateModuleDiagnostics(path string, diags ast.ModDiags) error {
txn := s.db.Txn(true)
defer txn.Abort()

Expand All @@ -622,7 +623,7 @@ func (s *ModuleStore) UpdateModuleDiagnostics(path string, diags map[string]hcl.
return nil
}

func (s *ModuleStore) UpdateVarsDiagnostics(path string, diags map[string]hcl.Diagnostics) error {
func (s *ModuleStore) UpdateVarsDiagnostics(path string, diags ast.VarsDiags) error {
txn := s.db.Txn(true)
defer txn.Abort()

Expand Down
Loading

0 comments on commit e4e1051

Please sign in to comment.