mirror of
https://github.com/opentofu/opentofu.git
synced 2025-02-25 18:45:20 -06:00
Avoid copies on calls to parser.Sources() (#1811)
Signed-off-by: Jon Johnson <jon.johnson@chainguard.dev>
This commit is contained in:
parent
8f001311ad
commit
e23aacb440
@ -12,6 +12,7 @@ import (
|
||||
"sort"
|
||||
"strings"
|
||||
|
||||
"github.com/hashicorp/hcl/v2"
|
||||
viewsjson "github.com/opentofu/opentofu/internal/command/views/json"
|
||||
"github.com/opentofu/opentofu/internal/tfdiags"
|
||||
|
||||
@ -31,7 +32,7 @@ var disabledColorize = &colorstring.Colorize{
|
||||
// at all. Although the long-form text parts of the message are wrapped,
|
||||
// not all aspects of the message are guaranteed to fit within the specified
|
||||
// terminal width.
|
||||
func Diagnostic(diag tfdiags.Diagnostic, sources map[string][]byte, color *colorstring.Colorize, width int) string {
|
||||
func Diagnostic(diag tfdiags.Diagnostic, sources map[string]*hcl.File, color *colorstring.Colorize, width int) string {
|
||||
return DiagnosticFromJSON(viewsjson.NewDiagnostic(diag, sources), color, width)
|
||||
}
|
||||
|
||||
@ -127,7 +128,7 @@ func DiagnosticFromJSON(diag *viewsjson.Diagnostic, color *colorstring.Colorize,
|
||||
//
|
||||
// It is intended for use in automation and other contexts in which diagnostic
|
||||
// messages are parsed from the OpenTofu output.
|
||||
func DiagnosticPlain(diag tfdiags.Diagnostic, sources map[string][]byte, width int) string {
|
||||
func DiagnosticPlain(diag tfdiags.Diagnostic, sources map[string]*hcl.File, width int) string {
|
||||
return DiagnosticPlainFromJSON(viewsjson.NewDiagnostic(diag, sources), width)
|
||||
}
|
||||
|
||||
|
@ -269,8 +269,8 @@ func TestDiagnostic(t *testing.T) {
|
||||
},
|
||||
}
|
||||
|
||||
sources := map[string][]byte{
|
||||
"test.tf": []byte(`test source code`),
|
||||
sources := map[string]*hcl.File{
|
||||
"test.tf": {Bytes: []byte(`test source code`)},
|
||||
}
|
||||
|
||||
// This empty Colorize just passes through all of the formatting codes
|
||||
@ -577,8 +577,8 @@ Whatever shall we do?
|
||||
},
|
||||
}
|
||||
|
||||
sources := map[string][]byte{
|
||||
"test.tf": []byte(`test source code`),
|
||||
sources := map[string]*hcl.File{
|
||||
"test.tf": {Bytes: []byte(`test source code`)},
|
||||
}
|
||||
|
||||
for name, test := range tests {
|
||||
@ -676,12 +676,12 @@ func TestDiagnostic_nonOverlappingHighlightContext(t *testing.T) {
|
||||
End: hcl.Pos{Line: 4, Column: 2, Byte: 60},
|
||||
},
|
||||
})
|
||||
sources := map[string][]byte{
|
||||
"source.tf": []byte(`x = somefunc("testing", {
|
||||
sources := map[string]*hcl.File{
|
||||
"source.tf": {Bytes: []byte(`x = somefunc("testing", {
|
||||
alpha = "foo"
|
||||
beta = "bar"
|
||||
})
|
||||
`),
|
||||
`)},
|
||||
}
|
||||
color := &colorstring.Colorize{
|
||||
Colors: colorstring.DefaultColors,
|
||||
@ -725,12 +725,12 @@ func TestDiagnostic_emptyOverlapHighlightContext(t *testing.T) {
|
||||
End: hcl.Pos{Line: 4, Column: 1, Byte: 39},
|
||||
},
|
||||
})
|
||||
sources := map[string][]byte{
|
||||
"source.tf": []byte(`variable "x" {
|
||||
sources := map[string]*hcl.File{
|
||||
"source.tf": {Bytes: []byte(`variable "x" {
|
||||
default = {
|
||||
"foo"
|
||||
}
|
||||
`),
|
||||
`)},
|
||||
}
|
||||
color := &colorstring.Colorize{
|
||||
Colors: colorstring.DefaultColors,
|
||||
@ -773,12 +773,12 @@ func TestDiagnosticPlain_emptyOverlapHighlightContext(t *testing.T) {
|
||||
End: hcl.Pos{Line: 4, Column: 1, Byte: 39},
|
||||
},
|
||||
})
|
||||
sources := map[string][]byte{
|
||||
"source.tf": []byte(`variable "x" {
|
||||
sources := map[string]*hcl.File{
|
||||
"source.tf": {Bytes: []byte(`variable "x" {
|
||||
default = {
|
||||
"foo"
|
||||
}
|
||||
`),
|
||||
`)},
|
||||
}
|
||||
|
||||
expected := `
|
||||
|
@ -380,7 +380,7 @@ func (m *Meta) inputForSchema(given cty.Value, schema *configschema.Block) (cty.
|
||||
//
|
||||
// If a config loader has not yet been instantiated then no files could have
|
||||
// been loaded already, so this method returns a nil map in that case.
|
||||
func (m *Meta) configSources() map[string][]byte {
|
||||
func (m *Meta) configSources() map[string]*hcl.File {
|
||||
if m.configLoader == nil {
|
||||
return nil
|
||||
}
|
||||
|
@ -133,7 +133,7 @@ type DiagnosticFunctionCall struct {
|
||||
|
||||
// NewDiagnostic takes a tfdiags.Diagnostic and a map of configuration sources,
|
||||
// and returns a Diagnostic struct.
|
||||
func NewDiagnostic(diag tfdiags.Diagnostic, sources map[string][]byte) *Diagnostic {
|
||||
func NewDiagnostic(diag tfdiags.Diagnostic, sources map[string]*hcl.File) *Diagnostic { //nolint:funlen,gocognit,gocyclo,cyclop // TODO(1818): Refactor this function.
|
||||
var sev string
|
||||
switch diag.Severity() {
|
||||
case tfdiags.Error:
|
||||
@ -200,7 +200,9 @@ func NewDiagnostic(diag tfdiags.Diagnostic, sources map[string][]byte) *Diagnost
|
||||
|
||||
var src []byte
|
||||
if sources != nil {
|
||||
src = sources[highlightRange.Filename]
|
||||
if f, ok := sources[highlightRange.Filename]; ok {
|
||||
src = f.Bytes
|
||||
}
|
||||
}
|
||||
|
||||
// If we have a source file for the diagnostic, we can emit a code
|
||||
|
@ -26,17 +26,17 @@ func TestNewDiagnostic(t *testing.T) {
|
||||
// Common HCL for diags with source ranges. This does not have any real
|
||||
// semantic errors, but we can synthesize fake HCL errors which will
|
||||
// exercise the diagnostic rendering code using this
|
||||
sources := map[string][]byte{
|
||||
"test.tf": []byte(`resource "test_resource" "test" {
|
||||
sources := map[string]*hcl.File{
|
||||
"test.tf": {Bytes: []byte(`resource "test_resource" "test" {
|
||||
foo = var.boop["hello!"]
|
||||
bar = {
|
||||
baz = maybe
|
||||
}
|
||||
}
|
||||
`),
|
||||
"short.tf": []byte("bad source code"),
|
||||
"odd-comment.tf": []byte("foo\n\n#\n"),
|
||||
"values.tf": []byte(`[
|
||||
`)},
|
||||
"short.tf": {Bytes: []byte("bad source code")},
|
||||
"odd-comment.tf": {Bytes: []byte("foo\n\n#\n")},
|
||||
"values.tf": {Bytes: []byte(`[
|
||||
var.a,
|
||||
var.b,
|
||||
var.c,
|
||||
@ -49,7 +49,7 @@ func TestNewDiagnostic(t *testing.T) {
|
||||
var.j,
|
||||
var.k,
|
||||
]
|
||||
`),
|
||||
`)},
|
||||
}
|
||||
testCases := map[string]struct {
|
||||
diag interface{} // allow various kinds of diags
|
||||
|
@ -6,6 +6,7 @@
|
||||
package views
|
||||
|
||||
import (
|
||||
"github.com/hashicorp/hcl/v2"
|
||||
"github.com/mitchellh/colorstring"
|
||||
"github.com/opentofu/opentofu/internal/command/arguments"
|
||||
"github.com/opentofu/opentofu/internal/command/format"
|
||||
@ -40,7 +41,7 @@ type View struct {
|
||||
// have associated source code in the configuration. This function pointer
|
||||
// will be dereferenced as late as possible when rendering diagnostics in
|
||||
// order to access the config loader cache.
|
||||
configSources func() map[string][]byte
|
||||
configSources func() map[string]*hcl.File
|
||||
}
|
||||
|
||||
// Initialize a View with the given streams, a disabled colorize object, and a
|
||||
@ -53,7 +54,7 @@ func NewView(streams *terminal.Streams) *View {
|
||||
Disable: true,
|
||||
Reset: true,
|
||||
},
|
||||
configSources: func() map[string][]byte { return nil },
|
||||
configSources: func() map[string]*hcl.File { return nil },
|
||||
}
|
||||
}
|
||||
|
||||
@ -82,7 +83,7 @@ func (v *View) Configure(view *arguments.View) {
|
||||
|
||||
// SetConfigSources overrides the default no-op callback with a new function
|
||||
// pointer, and should be called when the config loader is initialized.
|
||||
func (v *View) SetConfigSources(cb func() map[string][]byte) {
|
||||
func (v *View) SetConfigSources(cb func() map[string]*hcl.File) {
|
||||
v.configSources = cb
|
||||
}
|
||||
|
||||
|
@ -9,6 +9,7 @@ import (
|
||||
"fmt"
|
||||
"path/filepath"
|
||||
|
||||
"github.com/hashicorp/hcl/v2"
|
||||
"github.com/hashicorp/terraform-svchost/disco"
|
||||
"github.com/opentofu/opentofu/internal/configs"
|
||||
"github.com/opentofu/opentofu/internal/registry"
|
||||
@ -111,7 +112,7 @@ func (l *Loader) Parser() *configs.Parser {
|
||||
|
||||
// Sources returns the source code cache for the underlying parser of this
|
||||
// loader. This is a shorthand for l.Parser().Sources().
|
||||
func (l *Loader) Sources() map[string][]byte {
|
||||
func (l *Loader) Sources() map[string]*hcl.File {
|
||||
return l.parser.Sources()
|
||||
}
|
||||
|
||||
|
@ -196,7 +196,7 @@ func (l *Loader) addModuleToSnapshot(snap *Snapshot, key string, dir string, sou
|
||||
})
|
||||
continue
|
||||
}
|
||||
snapMod.Files[filepath.Clean(filename)] = src
|
||||
snapMod.Files[filepath.Clean(filename)] = src.Bytes
|
||||
}
|
||||
|
||||
snap.Modules[key] = snapMod
|
||||
|
@ -92,8 +92,8 @@ func (p *Parser) LoadHCLFile(path string) (hcl.Body, hcl.Diagnostics) {
|
||||
// Sources returns a map of the cached source buffers for all files that
|
||||
// have been loaded through this parser, with source filenames (as requested
|
||||
// when each file was opened) as the keys.
|
||||
func (p *Parser) Sources() map[string][]byte {
|
||||
return p.p.Sources()
|
||||
func (p *Parser) Sources() map[string]*hcl.File {
|
||||
return p.p.Files()
|
||||
}
|
||||
|
||||
// ForceFileSource artificially adds source code to the cache of file sources,
|
||||
|
Loading…
Reference in New Issue
Block a user