diff --git a/internal/features/stacks/ast/deploy.go b/internal/features/stacks/ast/deploy.go deleted file mode 100644 index 2a6efd444..000000000 --- a/internal/features/stacks/ast/deploy.go +++ /dev/null @@ -1,85 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: MPL-2.0 - -package ast - -import ( - "strings" - - "github.com/hashicorp/hcl/v2" - globalAst "github.com/hashicorp/terraform-ls/internal/terraform/ast" -) - -type DeployFilename string -type DeployFiles map[DeployFilename]*hcl.File -type DeployDiags map[DeployFilename]hcl.Diagnostics - -func (df DeployFilename) String() string { - return string(df) -} - -func (df DeployFilename) IsJSON() bool { - return strings.HasSuffix(string(df), ".json") -} - -func (df DeployFilename) IsIgnored() bool { - return globalAst.IsIgnoredFile(string(df)) -} - -func IsDeployFilename(name string) bool { - return strings.HasSuffix(name, ".tfdeploy.hcl") || - strings.HasSuffix(name, ".tfdeploy.json") -} - -func (df DeployFiles) Copy() DeployFiles { - m := make(DeployFiles, len(df)) - for name, file := range df { - m[name] = file - } - return m -} - -func (dd DeployDiags) Copy() DeployDiags { - m := make(DeployDiags, len(dd)) - for name, diags := range dd { - m[name] = diags - } - return m -} - -// AutoloadedOnly returns only diagnostics that are not from ignored files -func (dd DeployDiags) AutoloadedOnly() DeployDiags { - diags := make(DeployDiags) - for name, f := range dd { - if !name.IsIgnored() { - diags[name] = f - } - } - return diags -} - -func (dd DeployDiags) AsMap() map[string]hcl.Diagnostics { - m := make(map[string]hcl.Diagnostics, len(dd)) - for name, diags := range dd { - m[string(name)] = diags - } - return m -} - -func (dd DeployDiags) Count() int { - count := 0 - for _, diags := range dd { - count += len(diags) - } - return count -} - -type SourceDeployDiags map[globalAst.DiagnosticSource]DeployDiags - -func (svd SourceDeployDiags) Count() int { - count := 0 - for _, diags := range svd { - count += diags.Count() - } - return count -} diff --git a/internal/features/stacks/ast/stacks.go b/internal/features/stacks/ast/stacks.go index 72e18ee31..f12ef6e00 100644 --- a/internal/features/stacks/ast/stacks.go +++ b/internal/features/stacks/ast/stacks.go @@ -10,9 +10,14 @@ import ( globalAst "github.com/hashicorp/terraform-ls/internal/terraform/ast" ) +type Filename interface { + String() string + IsJSON() bool + IsIgnored() bool +} + +// StackFilename is a custom type for stack configuration files type StackFilename string -type StackFiles map[StackFilename]*hcl.File -type StackDiags map[StackFilename]hcl.Diagnostics func (mf StackFilename) String() string { return string(mf) @@ -31,16 +36,53 @@ func IsStackFilename(name string) bool { strings.HasSuffix(name, ".tfstack.json") } -func (sf StackFiles) Copy() StackFiles { - m := make(StackFiles, len(sf)) +// DeployFilename is a custom type for deployment files +type DeployFilename string + +func (df DeployFilename) String() string { + return string(df) +} + +func (df DeployFilename) IsJSON() bool { + return strings.HasSuffix(string(df), ".json") +} + +func (df DeployFilename) IsIgnored() bool { + return globalAst.IsIgnoredFile(string(df)) +} + +func IsDeployFilename(name string) bool { + return strings.HasSuffix(name, ".tfdeploy.hcl") || + strings.HasSuffix(name, ".tfdeploy.json") +} + +// FilenameFromName returns either a StackFilename or DeployFilename based +// on the name +func FilenameFromName(name string) Filename { + if IsStackFilename(name) { + return StackFilename(name) + } + if IsDeployFilename(name) { + return DeployFilename(name) + } + + return nil +} + +type Files map[Filename]*hcl.File + +func (sf Files) Copy() Files { + m := make(Files, len(sf)) for name, file := range sf { m[name] = file } return m } -func (sd StackDiags) Copy() StackDiags { - m := make(StackDiags, len(sd)) +type Diagnostics map[Filename]hcl.Diagnostics + +func (sd Diagnostics) Copy() Diagnostics { + m := make(Diagnostics, len(sd)) for name, diags := range sd { m[name] = diags } @@ -48,8 +90,8 @@ func (sd StackDiags) Copy() StackDiags { } // AutoloadedOnly returns only diagnostics that are not from ignored files -func (sd StackDiags) AutoloadedOnly() StackDiags { - diags := make(StackDiags) +func (sd Diagnostics) AutoloadedOnly() Diagnostics { + diags := make(Diagnostics) for name, f := range sd { if !name.IsIgnored() { diags[name] = f @@ -58,15 +100,15 @@ func (sd StackDiags) AutoloadedOnly() StackDiags { return diags } -func (sd StackDiags) AsMap() map[string]hcl.Diagnostics { +func (sd Diagnostics) AsMap() map[string]hcl.Diagnostics { m := make(map[string]hcl.Diagnostics, len(sd)) for name, diags := range sd { - m[string(name)] = diags + m[name.String()] = diags } return m } -func (sd StackDiags) Count() int { +func (sd Diagnostics) Count() int { count := 0 for _, diags := range sd { count += len(diags) @@ -74,9 +116,9 @@ func (sd StackDiags) Count() int { return count } -type SourceStackDiags map[globalAst.DiagnosticSource]StackDiags +type SourceDiagnostics map[globalAst.DiagnosticSource]Diagnostics -func (svd SourceStackDiags) Count() int { +func (svd SourceDiagnostics) Count() int { count := 0 for _, diags := range svd { count += diags.Count() diff --git a/internal/features/stacks/decoder/path_reader.go b/internal/features/stacks/decoder/path_reader.go index 6395f077b..37a8a1736 100644 --- a/internal/features/stacks/decoder/path_reader.go +++ b/internal/features/stacks/decoder/path_reader.go @@ -11,6 +11,7 @@ import ( "github.com/hashicorp/hcl-lang/lang" "github.com/hashicorp/hcl-lang/reference" "github.com/hashicorp/hcl/v2" + "github.com/hashicorp/terraform-ls/internal/features/stacks/ast" "github.com/hashicorp/terraform-ls/internal/features/stacks/state" ilsp "github.com/hashicorp/terraform-ls/internal/lsp" stackschema "github.com/hashicorp/terraform-schema/schema" @@ -59,8 +60,10 @@ func stackPathContext(record *state.StackRecord) (*decoder.PathContext, error) { // TODO: Add reference origins and targets if needed - for name, f := range record.ParsedStackFiles { - pathCtx.Files[name.String()] = f + for name, f := range record.ParsedFiles { + if _, ok := name.(ast.StackFilename); ok { + pathCtx.Files[name.String()] = f + } } return pathCtx, nil @@ -83,8 +86,10 @@ func deployPathContext(record *state.StackRecord) (*decoder.PathContext, error) // TODO: Add reference origins and targets if needed - for name, f := range record.ParsedDeployFiles { - pathCtx.Files[name.String()] = f + for name, f := range record.ParsedFiles { + if _, ok := name.(ast.DeployFilename); ok { + pathCtx.Files[name.String()] = f + } } return pathCtx, nil @@ -99,13 +104,24 @@ func (pr *PathReader) Paths(ctx context.Context) []lang.Path { } for _, record := range stackRecords { - if len(record.ParsedStackFiles) > 0 { + foundStack := false + foundDeploy := false + for name := range record.ParsedFiles { + if _, ok := name.(ast.StackFilename); ok { + foundStack = true + } + if _, ok := name.(ast.DeployFilename); ok { + foundDeploy = true + } + } + + if foundStack { paths = append(paths, lang.Path{ Path: record.Path(), LanguageID: ilsp.Stacks.String(), }) } - if len(record.ParsedDeployFiles) > 0 { + if foundDeploy { paths = append(paths, lang.Path{ Path: record.Path(), LanguageID: ilsp.Deploy.String(), diff --git a/internal/features/stacks/events.go b/internal/features/stacks/events.go index 73d7f0fed..46614fb76 100644 --- a/internal/features/stacks/events.go +++ b/internal/features/stacks/events.go @@ -8,7 +8,6 @@ import ( "os" "path/filepath" - lsctx "github.com/hashicorp/terraform-ls/internal/context" "github.com/hashicorp/terraform-ls/internal/document" "github.com/hashicorp/terraform-ls/internal/features/stacks/ast" "github.com/hashicorp/terraform-ls/internal/features/stacks/jobs" @@ -56,19 +55,7 @@ func (f *StacksFeature) didOpen(ctx context.Context, dir document.DirHandle, lan return ids, err } - sIds, err := f.decodeStacks(ctx, dir, false, true) - if err != nil { - return ids, err - } - ids = append(ids, sIds...) - - dIds, err := f.decodeDeploy(ctx, dir, false, true) - if err != nil { - return ids, err - } - ids = append(ids, dIds...) - - return ids, nil + return f.decodeStack(ctx, dir, false, true) } func (f *StacksFeature) didChange(ctx context.Context, dir document.DirHandle) (job.IDs, error) { @@ -77,15 +64,7 @@ func (f *StacksFeature) didChange(ctx context.Context, dir document.DirHandle) ( return job.IDs{}, nil } - rpcContext := lsctx.DocumentContext(ctx) - switch rpcContext.LanguageID { - case lsp.Stacks.String(): - return f.decodeStacks(ctx, dir, true, true) - case lsp.Deploy.String(): - return f.decodeDeploy(ctx, dir, true, true) - } - - return nil, nil + return f.decodeStack(ctx, dir, true, true) } func (f *StacksFeature) didChangeWatched(ctx context.Context, rawPath string, changeType protocol.FileChangeType, isDir bool) (job.IDs, error) { @@ -138,19 +117,7 @@ func (f *StacksFeature) didChangeWatched(ctx context.Context, rawPath string, ch return ids, nil } - sIds, err := f.decodeStacks(ctx, dir, false, true) - if err != nil { - return ids, err - } - ids = append(ids, sIds...) - - dIds, err := f.decodeDeploy(ctx, dir, false, true) - if err != nil { - return ids, err - } - ids = append(ids, dIds...) - - return ids, nil + return f.decodeStack(ctx, dir, true, true) case protocol.Changed: fallthrough @@ -178,25 +145,13 @@ func (f *StacksFeature) didChangeWatched(ctx context.Context, rawPath string, ch return ids, nil } - sIds, err := f.decodeStacks(ctx, dir, false, true) - if err != nil { - return ids, err - } - ids = append(ids, sIds...) - - dIds, err := f.decodeDeploy(ctx, dir, false, true) - if err != nil { - return ids, err - } - ids = append(ids, dIds...) - - return ids, nil + return f.decodeStack(ctx, dir, true, true) } return nil, nil } -func (f *StacksFeature) decodeStacks(ctx context.Context, dir document.DirHandle, ignoreState bool, isFirstLevel bool) (job.IDs, error) { +func (f *StacksFeature) decodeStack(ctx context.Context, dir document.DirHandle, ignoreState bool, isFirstLevel bool) (job.IDs, error) { ids := make(job.IDs, 0) path := dir.Path() @@ -223,33 +178,6 @@ func (f *StacksFeature) decodeStacks(ctx context.Context, dir document.DirHandle return ids, nil } -func (f *StacksFeature) decodeDeploy(ctx context.Context, dir document.DirHandle, ignoreState bool, isFirstLevel bool) (job.IDs, error) { - ids := make(job.IDs, 0) - path := dir.Path() - - parseId, err := f.stateStore.JobStore.EnqueueJob(ctx, job.Job{ - Dir: dir, - Func: func(ctx context.Context) error { - return jobs.ParseDeployConfiguration(ctx, f.fs, f.store, path) - }, - Type: operation.OpTypeParseDeployConfiguration.String(), - IgnoreState: ignoreState, - }) - if err != nil { - return ids, err - } - ids = append(ids, parseId) - - // TODO: Implement the following functions where appropriate to stacks - // Future: LoadModuleMetadata(ctx, f.Store, path) - // Future: decodeDeclaredModuleCalls(ctx, dir, ignoreState) - // TODO: PreloadEmbeddedSchema(ctx, f.logger, schemas.FS, - // Future: DecodeReferenceTargets(ctx, f.Store, f.rootFeature, path) - // Future: DecodeReferenceOrigins(ctx, f.Store, f.rootFeature, path) - - return ids, nil -} - func (f *StacksFeature) removeIndexedStack(rawPath string) { stackHandle := document.DirHandleFromPath(rawPath) diff --git a/internal/features/stacks/jobs/parse_deploy.go b/internal/features/stacks/jobs/parse_deploy.go deleted file mode 100644 index 43585b666..000000000 --- a/internal/features/stacks/jobs/parse_deploy.go +++ /dev/null @@ -1,96 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: MPL-2.0 - -package jobs - -import ( - "context" - "path/filepath" - - lsctx "github.com/hashicorp/terraform-ls/internal/context" - "github.com/hashicorp/terraform-ls/internal/document" - "github.com/hashicorp/terraform-ls/internal/features/stacks/ast" - "github.com/hashicorp/terraform-ls/internal/features/stacks/parser" - "github.com/hashicorp/terraform-ls/internal/features/stacks/state" - "github.com/hashicorp/terraform-ls/internal/job" - "github.com/hashicorp/terraform-ls/internal/lsp" - globalAst "github.com/hashicorp/terraform-ls/internal/terraform/ast" - "github.com/hashicorp/terraform-ls/internal/terraform/module/operation" - "github.com/hashicorp/terraform-ls/internal/uri" -) - -func ParseDeployConfiguration(ctx context.Context, fs ReadOnlyFS, stackStore *state.StackStore, stackPath string) error { - record, err := stackStore.StackRecordByPath(stackPath) - if err != nil { - return err - } - - // TODO: Avoid parsing if the content matches existing AST - - // Avoid parsing if it is already in progress or already known - if record.DeployDiagnosticsState[globalAst.HCLParsingSource] != operation.OpStateUnknown && !job.IgnoreState(ctx) { - return job.StateNotChangedErr{Dir: document.DirHandleFromPath(stackPath)} - } - - var files ast.DeployFiles - var diags ast.DeployDiags - rpcContext := lsctx.DocumentContext(ctx) - - // Only parse the file that's being changed/opened, unless this is 1st-time parsing - if record.DeployDiagnosticsState[globalAst.HCLParsingSource] == operation.OpStateLoaded && - rpcContext.IsDidChangeRequest() && - rpcContext.LanguageID == lsp.Deploy.String() { - // the file has already been parsed, so only examine this file and not the whole module - err = stackStore.SetDeployDiagnosticsState(stackPath, globalAst.HCLParsingSource, operation.OpStateLoading) - if err != nil { - return err - } - - filePath, err := uri.PathFromURI(rpcContext.URI) - if err != nil { - return err - } - fileName := filepath.Base(filePath) - - deployFile, deployFileDiags, err := parser.ParseDeployFile(fs, filePath) - if err != nil { - return err - } - existingFiles := record.ParsedDeployFiles.Copy() - existingFiles[ast.DeployFilename(fileName)] = deployFile - files = existingFiles - - existingDiags, ok := record.DeployDiagnostics[globalAst.HCLParsingSource] - if !ok { - existingDiags = make(ast.DeployDiags) - } else { - existingDiags = existingDiags.Copy() - } - existingDiags[ast.DeployFilename(fileName)] = deployFileDiags - diags = existingDiags - - } else { - // this is the first time file is opened so parse the whole module - err = stackStore.SetDeployDiagnosticsState(stackPath, globalAst.HCLParsingSource, operation.OpStateLoading) - if err != nil { - return err - } - files, diags, err = parser.ParseDeployFiles(fs, stackPath) - } - - if err != nil { - return err - } - - sErr := stackStore.UpdateParsedDeployFiles(stackPath, files, err) - if sErr != nil { - return sErr - } - - sErr = stackStore.UpdateDeployDiagnostics(stackPath, globalAst.HCLParsingSource, diags) - if sErr != nil { - return sErr - } - - return err -} diff --git a/internal/features/stacks/jobs/parse_stack.go b/internal/features/stacks/jobs/parse_stack.go index 523d22e10..d76ef12dd 100644 --- a/internal/features/stacks/jobs/parse_stack.go +++ b/internal/features/stacks/jobs/parse_stack.go @@ -19,8 +19,8 @@ import ( "github.com/hashicorp/terraform-ls/internal/uri" ) -// ParseModuleConfiguration parses the Stack configuration, -// i.e. turns bytes of `*.tfstack.hcl` files into AST ([*hcl.File]). +// ParseStackConfiguration parses the whole Stack configuration, +// i.e. turns bytes of `*.tfstack.hcl` & `*.tfdeploy.hcl` files into AST ([*hcl.File]). func ParseStackConfiguration(ctx context.Context, fs ReadOnlyFS, stackStore *state.StackStore, stackPath string) error { record, err := stackStore.StackRecordByPath(stackPath) if err != nil { @@ -30,20 +30,22 @@ func ParseStackConfiguration(ctx context.Context, fs ReadOnlyFS, stackStore *sta // TODO: Avoid parsing if the content matches existing AST // Avoid parsing if it is already in progress or already known - if record.StackDiagnosticsState[globalAst.HCLParsingSource] != operation.OpStateUnknown && !job.IgnoreState(ctx) { + if record.DiagnosticsState[globalAst.HCLParsingSource] != operation.OpStateUnknown && !job.IgnoreState(ctx) { return job.StateNotChangedErr{Dir: document.DirHandleFromPath(stackPath)} } - var files ast.StackFiles - var diags ast.StackDiags + var files ast.Files + var diags ast.Diagnostics rpcContext := lsctx.DocumentContext(ctx) + isMatchingLanguageId := (rpcContext.LanguageID == lsp.Stacks.String() || rpcContext.LanguageID == lsp.Deploy.String()) + // Only parse the file that's being changed/opened, unless this is 1st-time parsing - if record.StackDiagnosticsState[globalAst.HCLParsingSource] == operation.OpStateLoaded && + if record.DiagnosticsState[globalAst.HCLParsingSource] == operation.OpStateLoaded && rpcContext.IsDidChangeRequest() && - rpcContext.LanguageID == lsp.Stacks.String() { + isMatchingLanguageId { // the file has already been parsed, so only examine this file and not the whole module - err = stackStore.SetStackDiagnosticsState(stackPath, globalAst.HCLParsingSource, operation.OpStateLoading) + err = stackStore.SetDiagnosticsState(stackPath, globalAst.HCLParsingSource, operation.OpStateLoading) if err != nil { return err } @@ -54,39 +56,39 @@ func ParseStackConfiguration(ctx context.Context, fs ReadOnlyFS, stackStore *sta } fileName := filepath.Base(filePath) - stackFile, stackFileDiags, err := parser.ParseStackFile(fs, filePath) + pFile, fDiags, err := parser.ParseFile(fs, filePath) if err != nil { return err } - existingFiles := record.ParsedStackFiles.Copy() - existingFiles[ast.StackFilename(fileName)] = stackFile + existingFiles := record.ParsedFiles.Copy() + existingFiles[ast.FilenameFromName(fileName)] = pFile files = existingFiles - existingDiags, ok := record.StackDiagnostics[globalAst.HCLParsingSource] + existingDiags, ok := record.Diagnostics[globalAst.HCLParsingSource] if !ok { - existingDiags = make(ast.StackDiags) + existingDiags = make(ast.Diagnostics) } else { existingDiags = existingDiags.Copy() } - existingDiags[ast.StackFilename(fileName)] = stackFileDiags + existingDiags[ast.FilenameFromName(fileName)] = fDiags diags = existingDiags } else { // this is the first time file is opened so parse the whole module - err = stackStore.SetStackDiagnosticsState(stackPath, globalAst.HCLParsingSource, operation.OpStateLoading) + err = stackStore.SetDiagnosticsState(stackPath, globalAst.HCLParsingSource, operation.OpStateLoading) if err != nil { return err } - files, diags, err = parser.ParseStackFiles(fs, stackPath) + files, diags, err = parser.ParseFiles(fs, stackPath) } - sErr := stackStore.UpdateParsedStackFiles(stackPath, files, err) + sErr := stackStore.UpdateParsedFiles(stackPath, files, err) if sErr != nil { return sErr } - sErr = stackStore.UpdateStackDiagnostics(stackPath, globalAst.HCLParsingSource, diags) + sErr = stackStore.UpdateDiagnostics(stackPath, globalAst.HCLParsingSource, diags) if sErr != nil { return sErr } diff --git a/internal/features/stacks/parser/deploy.go b/internal/features/stacks/parser/deploy.go deleted file mode 100644 index 73c8f45bd..000000000 --- a/internal/features/stacks/parser/deploy.go +++ /dev/null @@ -1,71 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: MPL-2.0 - -package parser - -import ( - "path/filepath" - - "github.com/hashicorp/hcl/v2" - "github.com/hashicorp/terraform-ls/internal/features/stacks/ast" - "github.com/hashicorp/terraform-ls/internal/terraform/parser" -) - -func ParseDeployFiles(fs parser.FS, stacksPath string) (ast.DeployFiles, ast.DeployDiags, error) { - files := make(ast.DeployFiles, 0) - diags := make(ast.DeployDiags, 0) - - infos, err := fs.ReadDir(stacksPath) - if err != nil { - return nil, nil, err - } - - for _, info := range infos { - if info.IsDir() { - // We only care about files - continue - } - - name := info.Name() - if !ast.IsDeployFilename(name) { - continue - } - - // TODO: overrides - - fullPath := filepath.Join(stacksPath, name) - - src, err := fs.ReadFile(fullPath) - if err != nil { - // If a file isn't accessible, continue with reading the - // remaining module files - continue - } - - filename := ast.DeployFilename(name) - - f, pDiags := parser.ParseFile(src, filename) - - diags[filename] = pDiags - if f != nil { - files[filename] = f - } - } - - return files, diags, nil -} - -func ParseDeployFile(fs parser.FS, filePath string) (*hcl.File, hcl.Diagnostics, error) { - src, err := fs.ReadFile(filePath) - if err != nil { - // If a file isn't accessible, return - return nil, nil, err - } - - name := filepath.Base(filePath) - filename := ast.DeployFilename(name) - - f, pDiags := parser.ParseFile(src, filename) - - return f, pDiags, nil -} diff --git a/internal/features/stacks/parser/stacks.go b/internal/features/stacks/parser/stacks.go index 72adee761..ba362a0d2 100644 --- a/internal/features/stacks/parser/stacks.go +++ b/internal/features/stacks/parser/stacks.go @@ -11,9 +11,9 @@ import ( "github.com/hashicorp/terraform-ls/internal/terraform/parser" ) -func ParseStackFiles(fs parser.FS, stacksPath string) (ast.StackFiles, ast.StackDiags, error) { - files := make(ast.StackFiles, 0) - diags := make(ast.StackDiags, 0) +func ParseFiles(fs parser.FS, stacksPath string) (ast.Files, ast.Diagnostics, error) { + files := make(ast.Files, 0) + diags := make(ast.Diagnostics, 0) infos, err := fs.ReadDir(stacksPath) if err != nil { @@ -27,12 +27,10 @@ func ParseStackFiles(fs parser.FS, stacksPath string) (ast.StackFiles, ast.Stack } name := info.Name() - if !ast.IsStackFilename(name) { + if !ast.IsStackFilename(name) && !ast.IsDeployFilename(name) { continue } - // TODO: overrides - fullPath := filepath.Join(stacksPath, name) src, err := fs.ReadFile(fullPath) @@ -42,8 +40,7 @@ func ParseStackFiles(fs parser.FS, stacksPath string) (ast.StackFiles, ast.Stack continue } - filename := ast.StackFilename(name) - + filename := ast.FilenameFromName(name) f, pDiags := parser.ParseFile(src, filename) diags[filename] = pDiags @@ -55,7 +52,7 @@ func ParseStackFiles(fs parser.FS, stacksPath string) (ast.StackFiles, ast.Stack return files, diags, nil } -func ParseStackFile(fs parser.FS, filePath string) (*hcl.File, hcl.Diagnostics, error) { +func ParseFile(fs parser.FS, filePath string) (*hcl.File, hcl.Diagnostics, error) { src, err := fs.ReadFile(filePath) if err != nil { // If a file isn't accessible, return @@ -63,8 +60,7 @@ func ParseStackFile(fs parser.FS, filePath string) (*hcl.File, hcl.Diagnostics, } name := filepath.Base(filePath) - filename := ast.StackFilename(name) - + filename := ast.FilenameFromName(name) f, pDiags := parser.ParseFile(src, filename) return f, pDiags, nil diff --git a/internal/features/stacks/stacks_feature.go b/internal/features/stacks/stacks_feature.go index bb458fcb0..835384e0d 100644 --- a/internal/features/stacks/stacks_feature.go +++ b/internal/features/stacks/stacks_feature.go @@ -121,11 +121,7 @@ func (f *StacksFeature) Diagnostics(path string) diagnostics.Diagnostics { return diags } - for source, dm := range mod.StackDiagnostics { - diags.Append(source, dm.AutoloadedOnly().AsMap()) - } - - for source, dm := range mod.DeployDiagnostics { + for source, dm := range mod.Diagnostics { diags.Append(source, dm.AutoloadedOnly().AsMap()) } diff --git a/internal/features/stacks/state/stack_record.go b/internal/features/stacks/state/stack_record.go index 2c30fbb9b..afcd6bc55 100644 --- a/internal/features/stacks/state/stack_record.go +++ b/internal/features/stacks/state/stack_record.go @@ -17,17 +17,12 @@ type StackRecord struct { Meta StackMetadata - // ParsedStackFiles is the parsed tfstack files for the stack - // /some/path/lambda-multi-account-stack/components.tfstack.hcl ParsedStackFiles ast.StackFiles - ParsedStackFiles ast.StackFiles - StackParsingErr error - StackDiagnostics ast.SourceStackDiags - StackDiagnosticsState globalAst.DiagnosticSourceState - - ParsedDeployFiles ast.DeployFiles - DeployParsingErr error - DeployDiagnostics ast.SourceDeployDiags - DeployDiagnosticsState globalAst.DiagnosticSourceState + // ParsedFiles is a map of all the parsed files for the stack, + // including Stack and Deploy files. + ParsedFiles ast.Files + ParsingErr error + Diagnostics ast.SourceDiagnostics + DiagnosticsState globalAst.DiagnosticSourceState } func (m *StackRecord) Path() string { @@ -40,52 +35,29 @@ func (m *StackRecord) Copy() *StackRecord { } newRecord := &StackRecord{ - path: m.path, - Meta: m.Meta.Copy(), - StackParsingErr: m.StackParsingErr, - DeployParsingErr: m.DeployParsingErr, - StackDiagnosticsState: m.StackDiagnosticsState.Copy(), - DeployDiagnosticsState: m.DeployDiagnosticsState.Copy(), + path: m.path, + Meta: m.Meta.Copy(), + ParsingErr: m.ParsingErr, + DiagnosticsState: m.DiagnosticsState.Copy(), } - if m.ParsedStackFiles != nil { - newRecord.ParsedStackFiles = make(ast.StackFiles, len(m.ParsedStackFiles)) - for name, f := range m.ParsedStackFiles { + if m.ParsedFiles != nil { + newRecord.ParsedFiles = make(ast.Files, len(m.ParsedFiles)) + for name, f := range m.ParsedFiles { // hcl.File is practically immutable once it comes out of parser - newRecord.ParsedStackFiles[name] = f + newRecord.ParsedFiles[name] = f } } - if m.StackDiagnostics != nil { - newRecord.StackDiagnostics = make(ast.SourceStackDiags, len(m.StackDiagnostics)) + if m.Diagnostics != nil { + newRecord.Diagnostics = make(ast.SourceDiagnostics, len(m.Diagnostics)) - for source, stacksDiags := range m.StackDiagnostics { - newRecord.StackDiagnostics[source] = make(ast.StackDiags, len(stacksDiags)) + for source, stacksDiags := range m.Diagnostics { + newRecord.Diagnostics[source] = make(ast.Diagnostics, len(stacksDiags)) for name, diags := range stacksDiags { - newRecord.StackDiagnostics[source][name] = make(hcl.Diagnostics, len(diags)) - copy(newRecord.StackDiagnostics[source][name], diags) - } - } - } - - if m.ParsedDeployFiles != nil { - newRecord.ParsedDeployFiles = make(ast.DeployFiles, len(m.ParsedDeployFiles)) - for name, f := range m.ParsedDeployFiles { - // hcl.File is practically immutable once it comes out of parser - newRecord.ParsedDeployFiles[name] = f - } - } - - if m.DeployDiagnostics != nil { - newRecord.DeployDiagnostics = make(ast.SourceDeployDiags, len(m.DeployDiagnostics)) - - for source, deployDiags := range m.DeployDiagnostics { - newRecord.DeployDiagnostics[source] = make(ast.DeployDiags, len(deployDiags)) - - for name, diags := range deployDiags { - newRecord.DeployDiagnostics[source][name] = make(hcl.Diagnostics, len(diags)) - copy(newRecord.DeployDiagnostics[source][name], diags) + newRecord.Diagnostics[source][name] = make(hcl.Diagnostics, len(diags)) + copy(newRecord.Diagnostics[source][name], diags) } } } @@ -96,7 +68,7 @@ func (m *StackRecord) Copy() *StackRecord { func newStack(modPath string) *StackRecord { return &StackRecord{ path: modPath, - StackDiagnosticsState: globalAst.DiagnosticSourceState{ + DiagnosticsState: globalAst.DiagnosticSourceState{ globalAst.HCLParsingSource: operation.OpStateUnknown, globalAst.SchemaValidationSource: operation.OpStateUnknown, globalAst.ReferenceValidationSource: operation.OpStateUnknown, diff --git a/internal/features/stacks/state/stack_store.go b/internal/features/stacks/state/stack_store.go index 7eb853cd0..8f2d485c2 100644 --- a/internal/features/stacks/state/stack_store.go +++ b/internal/features/stacks/state/stack_store.go @@ -129,7 +129,7 @@ func (s *StackStore) AddIfNotExists(path string) error { return err } -func (s *StackStore) SetStackDiagnosticsState(path string, source globalAst.DiagnosticSource, state operation.OpState) error { +func (s *StackStore) SetDiagnosticsState(path string, source globalAst.DiagnosticSource, state operation.OpState) error { txn := s.db.Txn(true) defer txn.Abort() @@ -137,7 +137,7 @@ func (s *StackStore) SetStackDiagnosticsState(path string, source globalAst.Diag if err != nil { return err } - record.StackDiagnosticsState[source] = state + record.DiagnosticsState[source] = state err = txn.Insert(s.tableName, record) if err != nil { @@ -148,7 +148,7 @@ func (s *StackStore) SetStackDiagnosticsState(path string, source globalAst.Diag return nil } -func (s *StackStore) UpdateParsedStackFiles(path string, pFiles ast.StackFiles, pErr error) error { +func (s *StackStore) UpdateParsedFiles(path string, pFiles ast.Files, pErr error) error { txn := s.db.Txn(true) defer txn.Abort() @@ -157,9 +157,9 @@ func (s *StackStore) UpdateParsedStackFiles(path string, pFiles ast.StackFiles, return err } - mod.ParsedStackFiles = pFiles + mod.ParsedFiles = pFiles - mod.StackParsingErr = pErr + mod.ParsingErr = pErr err = txn.Insert(s.tableName, mod) if err != nil { @@ -170,10 +170,10 @@ func (s *StackStore) UpdateParsedStackFiles(path string, pFiles ast.StackFiles, return nil } -func (s *StackStore) UpdateStackDiagnostics(path string, source globalAst.DiagnosticSource, diags ast.StackDiags) error { +func (s *StackStore) UpdateDiagnostics(path string, source globalAst.DiagnosticSource, diags ast.Diagnostics) error { txn := s.db.Txn(true) txn.Defer(func() { - s.SetStackDiagnosticsState(path, source, operation.OpStateLoaded) + s.SetDiagnosticsState(path, source, operation.OpStateLoaded) }) defer txn.Abort() @@ -183,10 +183,10 @@ func (s *StackStore) UpdateStackDiagnostics(path string, source globalAst.Diagno } mod := oldMod.Copy() - if mod.StackDiagnostics == nil { - mod.StackDiagnostics = make(ast.SourceStackDiags) + if mod.Diagnostics == nil { + mod.Diagnostics = make(ast.SourceDiagnostics) } - mod.StackDiagnostics[source] = diags + mod.Diagnostics[source] = diags err = txn.Insert(s.tableName, mod) if err != nil { @@ -202,79 +202,6 @@ func (s *StackStore) UpdateStackDiagnostics(path string, source globalAst.Diagno return nil } -func (s *StackStore) SetDeployDiagnosticsState(path string, source globalAst.DiagnosticSource, state operation.OpState) error { - txn := s.db.Txn(true) - defer txn.Abort() - - record, err := stackCopyByPath(txn, path) - if err != nil { - return err - } - record.DeployDiagnosticsState[source] = state - - err = txn.Insert(s.tableName, record) - if err != nil { - return err - } - - txn.Commit() - return nil -} - -func (s *StackStore) UpdateParsedDeployFiles(path string, pFiles ast.DeployFiles, pErr error) error { - txn := s.db.Txn(true) - defer txn.Abort() - - mod, err := stackCopyByPath(txn, path) - if err != nil { - return err - } - - mod.ParsedDeployFiles = pFiles - - mod.DeployParsingErr = pErr - - err = txn.Insert(s.tableName, mod) - if err != nil { - return err - } - - txn.Commit() - return nil -} - -func (s *StackStore) UpdateDeployDiagnostics(path string, source globalAst.DiagnosticSource, diags ast.DeployDiags) error { - txn := s.db.Txn(true) - txn.Defer(func() { - s.SetStackDiagnosticsState(path, source, operation.OpStateLoaded) - }) - defer txn.Abort() - - oldStack, err := stackByPath(txn, path) - if err != nil { - return err - } - - stack := oldStack.Copy() - if stack.DeployDiagnostics == nil { - stack.DeployDiagnostics = make(ast.SourceDeployDiags) - } - stack.DeployDiagnostics[source] = diags - - err = txn.Insert(s.tableName, stack) - if err != nil { - return err - } - - err = s.queueRecordChange(oldStack, stack) - if err != nil { - return err - } - - txn.Commit() - return nil -} - func (s *StackStore) add(txn *memdb.Txn, stackPath string) error { // TODO: Introduce Exists method to Txn? obj, err := txn.First(s.tableName, "id", stackPath) @@ -328,10 +255,10 @@ func (s *StackStore) queueRecordChange(oldRecord, newRecord *StackRecord) error oldDiags, newDiags := 0, 0 if oldRecord != nil { - oldDiags = oldRecord.StackDiagnostics.Count() + oldRecord.DeployDiagnostics.Count() + oldDiags = oldRecord.Diagnostics.Count() } if newRecord != nil { - newDiags = newRecord.StackDiagnostics.Count() + newRecord.DeployDiagnostics.Count() + newDiags = newRecord.Diagnostics.Count() } // Comparing diagnostics accurately could be expensive // so we just treat any non-empty diags as a change