Avoid copies on calls to parser.Sources() (#1811)

Signed-off-by: Jon Johnson <jon.johnson@chainguard.dev>
This commit is contained in:
Jon Johnson 2024-07-29 13:15:51 -07:00 committed by GitHub
parent 8f001311ad
commit e23aacb440
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
9 changed files with 37 additions and 32 deletions

View File

@ -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)
}

View File

@ -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 := `

View File

@ -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
}

View File

@ -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

View File

@ -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

View File

@ -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
}

View File

@ -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()
}

View File

@ -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

View File

@ -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,