diff --git a/internal/command/format/diagnostic.go b/internal/command/format/diagnostic.go index a32839ee72..65323a1ab8 100644 --- a/internal/command/format/diagnostic.go +++ b/internal/command/format/diagnostic.go @@ -254,14 +254,8 @@ func (f *snippetFormatter) write() { fmt.Fprintf(buf, " on %s line %d%s:\n", diag.Range.Filename, diag.Range.Start.Line, contextStr) f.writeSnippet(snippet, code) - if diag.DeprecationOriginRange != nil && diag.DeprecationOriginSnippet != nil { - var depContextStr string - if diag.DeprecationOriginSnippet.Context != nil { - depContextStr = fmt.Sprintf(", in %s", *snippet.Context) - } - buf.WriteByte('\n') - fmt.Fprintf(buf, " (origin of deprecation on %s line %d%s):\n", diag.DeprecationOriginRange.Filename, diag.DeprecationOriginRange.Start.Line, depContextStr) - f.writeSnippet(diag.DeprecationOriginSnippet, diag.DeprecationOriginSnippet.Code) + if diag.DeprecationOriginDescription != "" { + fmt.Fprintf(buf, "\n The deprecation originates from %s\n", diag.DeprecationOriginDescription) } } diff --git a/internal/command/format/diagnostic_test.go b/internal/command/format/diagnostic_test.go index b2f15ab531..1c484e53ce 100644 --- a/internal/command/format/diagnostic_test.go +++ b/internal/command/format/diagnostic_test.go @@ -418,11 +418,7 @@ func TestDiagnostic(t *testing.T) { End: hcl.Pos{Line: 1, Column: 12, Byte: 11}, }, Extra: &tfdiags.DeprecationOriginDiagnosticExtra{ - Origin: &tfdiags.SourceRange{ - Filename: "deprecated.tf", - Start: tfdiags.SourcePos{Line: 1, Column: 11, Byte: 10}, - End: tfdiags.SourcePos{Line: 1, Column: 22, Byte: 21}, - }, + OriginDescription: "module.foo.bar", }, }, `[yellow]╷[reset] @@ -431,8 +427,7 @@ func TestDiagnostic(t *testing.T) { [yellow]│[reset] on test.tf line 1: [yellow]│[reset] 1: test [underline]source[reset] code [yellow]│[reset] -[yellow]│[reset] (origin of deprecation on deprecated.tf line 1): -[yellow]│[reset] 1: source of [underline]deprecation[reset] +[yellow]│[reset] The deprecation originates from module.foo.bar [yellow]│[reset] [yellow]│[reset] Countermeasures must be taken. [yellow]╵[reset] @@ -760,11 +755,7 @@ Whatever shall we do? End: hcl.Pos{Line: 1, Column: 12, Byte: 11}, }, Extra: &tfdiags.DeprecationOriginDiagnosticExtra{ - Origin: &tfdiags.SourceRange{ - Filename: "deprecated.tf", - Start: tfdiags.SourcePos{Line: 1, Column: 11, Byte: 10}, - End: tfdiags.SourcePos{Line: 1, Column: 22, Byte: 21}, - }, + OriginDescription: "module.foo.bar", }, }, ` @@ -773,8 +764,7 @@ Warning: Deprecation detected on test.tf line 1: 1: test source code - (origin of deprecation on deprecated.tf line 1): - 1: source of deprecation + The deprecation originates from module.foo.bar Countermeasures must be taken. `, diff --git a/internal/command/views/json/diagnostic.go b/internal/command/views/json/diagnostic.go index 75603f2f99..98c6bed99d 100644 --- a/internal/command/views/json/diagnostic.go +++ b/internal/command/views/json/diagnostic.go @@ -40,8 +40,7 @@ type Diagnostic struct { Range *DiagnosticRange `json:"range,omitempty"` Snippet *DiagnosticSnippet `json:"snippet,omitempty"` - DeprecationOriginRange *DiagnosticRange `json:"deprecation_origin_range,omitempty"` - DeprecationOriginSnippet *DiagnosticSnippet `json:"deprecation_origin_snippet,omitempty"` + DeprecationOriginDescription string `json:"deprecation_origin_description,omitempty"` } // Pos represents a position in the source code. @@ -403,31 +402,8 @@ func NewDiagnostic(diag tfdiags.Diagnostic, sources map[string][]byte) *Diagnost } } - if deprecationOrigin := tfdiags.DiagnosticDeprecationOrigin(diag); deprecationOrigin != nil { - diagnostic.DeprecationOriginRange = &DiagnosticRange{ - Filename: deprecationOrigin.Filename, - Start: Pos{ - Line: deprecationOrigin.Start.Line, - Column: deprecationOrigin.Start.Column, - Byte: deprecationOrigin.Start.Byte, - }, - End: Pos{ - Line: deprecationOrigin.End.Line, - Column: deprecationOrigin.End.Column, - Byte: deprecationOrigin.End.Byte, - }, - } - - var src []byte - if sources != nil { - src = sources[deprecationOrigin.Filename] - } - - if src != nil { - highlightRange := deprecationOrigin.ToHCL() - diagnostic.DeprecationOriginSnippet = snippetFromRange(src, highlightRange, highlightRange) - } - + if deprecationOrigin := tfdiags.DeprecatedOriginDescription(diag); deprecationOrigin != "" { + diagnostic.DeprecationOriginDescription = deprecationOrigin } return diagnostic diff --git a/internal/command/views/json/diagnostic_test.go b/internal/command/views/json/diagnostic_test.go index a375a33f4a..a2b41521f7 100644 --- a/internal/command/views/json/diagnostic_test.go +++ b/internal/command/views/json/diagnostic_test.go @@ -880,11 +880,7 @@ func TestNewDiagnostic(t *testing.T) { End: hcl.Pos{Line: 1, Column: 25, Byte: 24}, }, Extra: &tfdiags.DeprecationOriginDiagnosticExtra{ - Origin: &tfdiags.SourceRange{ - Filename: "deprecation.tf", - Start: tfdiags.SourcePos{Line: 1, Column: 10, Byte: 9}, - End: tfdiags.SourcePos{Line: 1, Column: 25, Byte: 24}, - }, + OriginDescription: "aws_s3_bucket.hello.acl", }, }, &Diagnostic{ @@ -912,19 +908,7 @@ func TestNewDiagnostic(t *testing.T) { HighlightEndOffset: 24, Values: []DiagnosticExpressionValue{}, }, - DeprecationOriginRange: &DiagnosticRange{ - Filename: "deprecation.tf", - Start: Pos{Line: 1, Column: 10, Byte: 9}, - End: Pos{Line: 1, Column: 25, Byte: 24}, - }, - DeprecationOriginSnippet: &DiagnosticSnippet{ - Context: strPtr(`resource "test_resource" "deprecated"`), - Code: `resource "test_resource" "deprecated" {}`, - StartLine: 1, - HighlightStartOffset: 9, - HighlightEndOffset: 24, - Values: []DiagnosticExpressionValue{}, - }, + DeprecationOriginDescription: "aws_s3_bucket.hello.acl", }, }, } diff --git a/internal/command/views/json/testdata/diagnostic/warning-with-deprecation-origin.json b/internal/command/views/json/testdata/diagnostic/warning-with-deprecation-origin.json index 5223cbbf67..b3a077ab0b 100644 --- a/internal/command/views/json/testdata/diagnostic/warning-with-deprecation-origin.json +++ b/internal/command/views/json/testdata/diagnostic/warning-with-deprecation-origin.json @@ -23,25 +23,5 @@ "highlight_end_offset": 24, "values": [] }, - "deprecation_origin_range": { - "filename": "deprecation.tf", - "start": { - "line": 1, - "column": 10, - "byte": 9 - }, - "end": { - "line": 1, - "column": 25, - "byte": 24 - } - }, - "deprecation_origin_snippet": { - "context": "resource \"test_resource\" \"deprecated\"", - "code": "resource \"test_resource\" \"deprecated\" {}", - "start_line": 1, - "highlight_start_offset": 9, - "highlight_end_offset": 24, - "values": [] - } + "deprecation_origin_description": "aws_s3_bucket.hello.acl" } diff --git a/internal/deprecation/deprecation.go b/internal/deprecation/deprecation.go index fbac8ca2cc..4e63617193 100644 --- a/internal/deprecation/deprecation.go +++ b/internal/deprecation/deprecation.go @@ -56,11 +56,9 @@ func (d *Deprecations) Validate(value cty.Value, module addrs.Module, rng *hcl.R Detail: depMark.Message, Subject: rng, } - if depMark.Origin != nil { - origin := *depMark.Origin - sourceRange := tfdiags.SourceRangeFromHCL(origin) + if depMark.OriginDescription != "" { diag.Extra = &tfdiags.DeprecationOriginDiagnosticExtra{ - Origin: &sourceRange, + OriginDescription: depMark.OriginDescription, } } diags = diags.Append(diag) @@ -86,15 +84,14 @@ func (d *Deprecations) ValidateAsConfig(value cty.Value, module addrs.Module) tf depMark.Message, pvm.Path, ) - origin := depMark.Origin - if origin != nil { + if depMark.OriginDescription != "" { diag = tfdiags.Override( diag, tfdiags.Warning, // We just want to override the extra info func() tfdiags.DiagnosticExtraWrapper { - sourceRange := tfdiags.SourceRangeFromHCL(*origin) return &tfdiags.DeprecationOriginDiagnosticExtra{ - Origin: &sourceRange, + // TODO: Remove common prefixes from origin descriptions? + OriginDescription: depMark.OriginDescription, } }) } diff --git a/internal/lang/marks/marks.go b/internal/lang/marks/marks.go index 5b3d3fe0cf..60a578f847 100644 --- a/internal/lang/marks/marks.go +++ b/internal/lang/marks/marks.go @@ -4,7 +4,6 @@ package marks import ( - "github.com/hashicorp/hcl/v2" "github.com/zclconf/go-cty/cty" ) @@ -98,7 +97,8 @@ const TypeType = valueMark("TypeType") // rather than a primitive type so that it can carry a deprecation message. type DeprecationMark struct { Message string - Origin *hcl.Range + + OriginDescription string // a human-readable description of the origin } func (d DeprecationMark) GoString() string { @@ -106,11 +106,11 @@ func (d DeprecationMark) GoString() string { } // Empty deprecation mark for usage in marks.Has / Contains / etc -var Deprecation = NewDeprecation("", nil) +var Deprecation = NewDeprecation("", "") -func NewDeprecation(message string, origin *hcl.Range) DeprecationMark { +func NewDeprecation(message string, originDescription string) DeprecationMark { return DeprecationMark{ - Message: message, - Origin: origin, + Message: message, + OriginDescription: originDescription, } } diff --git a/internal/lang/marks/marks_test.go b/internal/lang/marks/marks_test.go index 8781d1d3ae..fe09a3600d 100644 --- a/internal/lang/marks/marks_test.go +++ b/internal/lang/marks/marks_test.go @@ -10,7 +10,7 @@ import ( ) func TestDeprecationMark(t *testing.T) { - deprecation := cty.StringVal("OldValue").Mark(NewDeprecation("This is outdated", nil)) + deprecation := cty.StringVal("OldValue").Mark(NewDeprecation("This is outdated", "")) composite := cty.ObjectVal(map[string]cty.Value{ "foo": deprecation, diff --git a/internal/lang/marks/paths_test.go b/internal/lang/marks/paths_test.go index 558a48110d..a7850ee9c9 100644 --- a/internal/lang/marks/paths_test.go +++ b/internal/lang/marks/paths_test.go @@ -32,15 +32,15 @@ func TestPathsWithMark(t *testing.T) { }, { Path: cty.GetAttrPath("deprecated"), - Marks: cty.NewValueMarks(NewDeprecation("this is deprecated", nil)), + Marks: cty.NewValueMarks(NewDeprecation("this is deprecated", "")), }, { Path: cty.GetAttrPath("multipleDeprecations"), - Marks: cty.NewValueMarks(NewDeprecation("this is deprecated", nil), NewDeprecation("this is also deprecated", nil)), + Marks: cty.NewValueMarks(NewDeprecation("this is deprecated", ""), NewDeprecation("this is also deprecated", "")), }, { Path: cty.GetAttrPath("multipleDeprecationsAndSensitive"), - Marks: cty.NewValueMarks(NewDeprecation("this is deprecated", nil), NewDeprecation("this is also deprecated", nil), "sensitive"), + Marks: cty.NewValueMarks(NewDeprecation("this is deprecated", ""), NewDeprecation("this is also deprecated", ""), "sensitive"), }, } @@ -71,15 +71,15 @@ func TestPathsWithMark(t *testing.T) { }, { Path: cty.GetAttrPath("deprecated"), - Marks: cty.NewValueMarks(NewDeprecation("this is deprecated", nil)), + Marks: cty.NewValueMarks(NewDeprecation("this is deprecated", "")), }, { Path: cty.GetAttrPath("multipleDeprecations"), - Marks: cty.NewValueMarks(NewDeprecation("this is deprecated", nil), NewDeprecation("this is also deprecated", nil)), + Marks: cty.NewValueMarks(NewDeprecation("this is deprecated", ""), NewDeprecation("this is also deprecated", "")), }, { Path: cty.GetAttrPath("multipleDeprecationsAndSensitive"), - Marks: cty.NewValueMarks(NewDeprecation("this is deprecated", nil), NewDeprecation("this is also deprecated", nil), "sensitive"), + Marks: cty.NewValueMarks(NewDeprecation("this is deprecated", ""), NewDeprecation("this is also deprecated", ""), "sensitive"), }, } @@ -116,7 +116,7 @@ func TestPathsWithMark(t *testing.T) { }, { Path: cty.GetAttrPath("multipleDeprecationsAndSensitive"), - Marks: cty.NewValueMarks(NewDeprecation("this is deprecated", nil), NewDeprecation("this is also deprecated", nil), "sensitive"), + Marks: cty.NewValueMarks(NewDeprecation("this is deprecated", ""), NewDeprecation("this is also deprecated", ""), "sensitive"), }, } @@ -166,15 +166,15 @@ func TestRemoveAll_dataMarks(t *testing.T) { input := []cty.PathValueMarks{ { Path: cty.GetAttrPath("deprecated"), - Marks: cty.NewValueMarks(NewDeprecation("this is deprecated", nil)), + Marks: cty.NewValueMarks(NewDeprecation("this is deprecated", "")), }, { Path: cty.GetAttrPath("multipleDeprecations"), - Marks: cty.NewValueMarks(NewDeprecation("this is deprecated", nil), NewDeprecation("this is also deprecated", nil)), + Marks: cty.NewValueMarks(NewDeprecation("this is deprecated", ""), NewDeprecation("this is also deprecated", "")), }, { Path: cty.GetAttrPath("multipleDeprecationsAndSensitive"), - Marks: cty.NewValueMarks(NewDeprecation("this is deprecated", nil), NewDeprecation("this is also deprecated", nil), "sensitive"), + Marks: cty.NewValueMarks(NewDeprecation("this is deprecated", ""), NewDeprecation("this is also deprecated", ""), "sensitive"), }, } @@ -250,7 +250,7 @@ func TestMarkPaths(t *testing.T) { cty.GetAttrPath("o").GetAttr("b"), cty.GetAttrPath("t").IndexInt(0), } - deprecationMark := NewDeprecation("this is deprecated", nil) + deprecationMark := NewDeprecation("this is deprecated", "") got = MarkPaths(value, deprecationMark, deprecatedPaths) want = cty.ObjectVal(map[string]cty.Value{ "s": cty.StringVal(".s").Mark(deprecationMark), @@ -365,28 +365,28 @@ func TestMarksEqual(t *testing.T) { }, { []cty.PathValueMarks{ - {Path: cty.Path{cty.GetAttrStep{Name: "a"}}, Marks: cty.NewValueMarks(NewDeprecation("same message", nil))}, + {Path: cty.Path{cty.GetAttrStep{Name: "a"}}, Marks: cty.NewValueMarks(NewDeprecation("same message", ""))}, }, []cty.PathValueMarks{ - {Path: cty.Path{cty.GetAttrStep{Name: "a"}}, Marks: cty.NewValueMarks(NewDeprecation("same message", nil))}, + {Path: cty.Path{cty.GetAttrStep{Name: "a"}}, Marks: cty.NewValueMarks(NewDeprecation("same message", ""))}, }, true, }, { []cty.PathValueMarks{ - {Path: cty.Path{cty.GetAttrStep{Name: "a"}}, Marks: cty.NewValueMarks(NewDeprecation("different", nil))}, + {Path: cty.Path{cty.GetAttrStep{Name: "a"}}, Marks: cty.NewValueMarks(NewDeprecation("different", ""))}, }, []cty.PathValueMarks{ - {Path: cty.Path{cty.GetAttrStep{Name: "a"}}, Marks: cty.NewValueMarks(NewDeprecation("message", nil))}, + {Path: cty.Path{cty.GetAttrStep{Name: "a"}}, Marks: cty.NewValueMarks(NewDeprecation("message", ""))}, }, false, }, { []cty.PathValueMarks{ - {Path: cty.Path{cty.GetAttrStep{Name: "a"}}, Marks: cty.NewValueMarks(NewDeprecation("same message", nil))}, + {Path: cty.Path{cty.GetAttrStep{Name: "a"}}, Marks: cty.NewValueMarks(NewDeprecation("same message", ""))}, }, []cty.PathValueMarks{ - {Path: cty.Path{cty.GetAttrStep{Name: "a"}}, Marks: cty.NewValueMarks(NewDeprecation("same message", nil))}, + {Path: cty.Path{cty.GetAttrStep{Name: "a"}}, Marks: cty.NewValueMarks(NewDeprecation("same message", ""))}, }, true, }, diff --git a/internal/terraform/evaluate.go b/internal/terraform/evaluate.go index 691a577dc2..2c0176dd72 100644 --- a/internal/terraform/evaluate.go +++ b/internal/terraform/evaluate.go @@ -421,7 +421,14 @@ func (d *evaluationStateData) GetModule(addr addrs.ModuleCall, rng tfdiags.Sourc atys[name] = cty.DynamicPseudoType // output values are dynamically-typed val := cty.UnknownVal(cty.DynamicPseudoType) if c.DeprecatedSet { - val = val.Mark(marks.NewDeprecation(c.Deprecated, &c.DeclRange)) + accessor := "." + switch { + case callConfig.Count != nil: + accessor = ".[*]." + case callConfig.ForEach != nil: + accessor = ".[*]." + } + val = val.Mark(marks.NewDeprecation(c.Deprecated, fmt.Sprintf("%s%s%s", addr.String(), accessor, name))) } as[name] = val } @@ -482,7 +489,7 @@ func (d *evaluationStateData) GetModule(addr addrs.ModuleCall, rng tfdiags.Sourc } if cfg.DeprecatedSet { - outputVal = outputVal.Mark(marks.NewDeprecation(cfg.Deprecated, &cfg.DeclRange)) + outputVal = outputVal.Mark(marks.NewDeprecation(cfg.Deprecated, fmt.Sprintf("%s.%s", moduleInstAddr.String(), name))) } attrs[name] = outputVal } @@ -791,7 +798,7 @@ func (d *evaluationStateData) GetResource(addr addrs.Resource, rng tfdiags.Sourc // states populated for all resources in the configuration. ret := cty.DynamicVal if schema.Body.Deprecated { - ret = ret.Mark(marks.NewDeprecation(fmt.Sprintf("Resource %q is deprecated", addr.Type), &config.DeclRange)) + ret = ret.Mark(marks.NewDeprecation(fmt.Sprintf("Resource %q is deprecated", addr.Type), addr.String())) } return ret, diags } @@ -869,7 +876,7 @@ func (d *evaluationStateData) GetResource(addr addrs.Resource, rng tfdiags.Sourc } if schema.Body.Deprecated { - ret = ret.Mark(marks.NewDeprecation(fmt.Sprintf("Resource %q is deprecated", addr.Type), &config.DeclRange)) + ret = ret.Mark(marks.NewDeprecation(fmt.Sprintf("Resource %q is deprecated", addr.Type), addr.String())) } return ret, diags @@ -1152,7 +1159,7 @@ func (d *evaluationStateData) GetOutput(addr addrs.OutputValue, rng tfdiags.Sour value = value.Mark(marks.Ephemeral) } if config.DeprecatedSet { - value = value.Mark(marks.NewDeprecation(config.Deprecated, &config.DeclRange)) + value = value.Mark(marks.NewDeprecation(config.Deprecated, addr.Absolute(d.ModulePath).String())) } return value, diags diff --git a/internal/tfdiags/diagnostic_extra.go b/internal/tfdiags/diagnostic_extra.go index df06ed6663..6294503af3 100644 --- a/internal/tfdiags/diagnostic_extra.go +++ b/internal/tfdiags/diagnostic_extra.go @@ -266,21 +266,21 @@ func DiagnosticCausedByTestFailure(diag Diagnostic) bool { // deprecation warning. It provides information about the origin of the // deprecation. type DiagnosticExtraDeprecationOrigin interface { - DeprecationOrigin() *SourceRange + DeprecatedOriginDescription() string } // DiagnosticDeprecationOrigin returns the origin range of a deprecation // warning diagnostic, or nil if the diagnostic does not have such information. -func DiagnosticDeprecationOrigin(diag Diagnostic) *SourceRange { +func DeprecatedOriginDescription(diag Diagnostic) string { maybe := ExtraInfo[DiagnosticExtraDeprecationOrigin](diag) if maybe == nil { - return nil + return "" } - return maybe.DeprecationOrigin() + return maybe.DeprecatedOriginDescription() } type DeprecationOriginDiagnosticExtra struct { - Origin *SourceRange + OriginDescription string wrapped interface{} } @@ -304,6 +304,6 @@ func (c *DeprecationOriginDiagnosticExtra) WrapDiagnosticExtra(inner interface{} c.wrapped = inner } -func (c *DeprecationOriginDiagnosticExtra) DeprecationOrigin() *SourceRange { - return c.Origin +func (c *DeprecationOriginDiagnosticExtra) DeprecatedOriginDescription() string { + return c.OriginDescription }