diff --git a/cmd/internal/gen-fixtures/gen-fixtures.go b/cmd/internal/gen-fixtures/gen-fixtures.go index ac44bd4..ae293c5 100644 --- a/cmd/internal/gen-fixtures/gen-fixtures.go +++ b/cmd/internal/gen-fixtures/gen-fixtures.go @@ -40,11 +40,19 @@ func (t testFs) Open(name string) (fs.File, error) { func evaluateCollections(evaluator pkl.Evaluator, fixturesDir string) { for _, expr := range []string{"res1", "res2", "res9"} { - outBytes, err := evaluator.EvaluateExpressionRaw(context.Background(), pkl.FileSource(fixturesDir, "collections.pkl"), expr) + outBytes, err := evaluator.EvaluateExpressionRaw( + context.Background(), + pkl.FileSource(fixturesDir, "collections.pkl"), + expr, + ) if err != nil { panic(err) } - outPath := filepath.Join(fixturesDir, "msgpack", fmt.Sprintf("collections.%s.msgpack", expr)) + outPath := filepath.Join( + fixturesDir, + "msgpack", + fmt.Sprintf("collections.%s.msgpack", expr), + ) if err = os.WriteFile(outPath, outBytes, 0o666); err != nil { panic(err) } @@ -61,7 +69,11 @@ func makeMsgpack(evaluator pkl.Evaluator, fixturesDir string, files []os.DirEntr if file.IsDir() { continue } - outBytes, err := evaluator.EvaluateExpressionRaw(context.Background(), pkl.UriSource("pklgo:/pkl/test_fixtures/"+file.Name()), "") + outBytes, err := evaluator.EvaluateExpressionRaw( + context.Background(), + pkl.UriSource("pklgo:/pkl/test_fixtures/"+file.Name()), + "", + ) if err != nil { panic(err) } @@ -82,7 +94,10 @@ func makeGoCode(evaluator pkl.Evaluator, fixturesDir string, files []os.DirEntry if err := os.RemoveAll(genDir); err != nil { panic(err) } - settings, err := generatorsettings.LoadFromPath(context.Background(), "codegen/snippet-tests/generator-settings.pkl") + settings, err := generatorsettings.LoadFromPath( + context.Background(), + "codegen/snippet-tests/generator-settings.pkl", + ) if err != nil { panic(err) } diff --git a/cmd/internal/gen-snippets/gen-snippets.go b/cmd/internal/gen-snippets/gen-snippets.go index 247604a..2a58fce 100644 --- a/cmd/internal/gen-snippets/gen-snippets.go +++ b/cmd/internal/gen-snippets/gen-snippets.go @@ -55,7 +55,10 @@ func makeGoCode(evaluator pkl.Evaluator, snippetsDir string) { panic(err) } codegenDir := filepath.Join(snippetsDir, "..") - settings, err := generatorsettings.LoadFromPath(context.Background(), "codegen/snippet-tests/generator-settings.pkl") + settings, err := generatorsettings.LoadFromPath( + context.Background(), + "codegen/snippet-tests/generator-settings.pkl", + ) if err != nil { panic(err) } diff --git a/cmd/pkl-gen-go/pkg/generate.go b/cmd/pkl-gen-go/pkg/generate.go index c5045a3..5f595ce 100644 --- a/cmd/pkl-gen-go/pkg/generate.go +++ b/cmd/pkl-gen-go/pkg/generate.go @@ -78,9 +78,19 @@ func doFormat(src string) ([]byte, string, error) { return formatted, cmp.Diff(src, strFormatted), nil } -func generateDryRun(evaluator pkl.Evaluator, tmpFile *os.File, outputPath string, settings *generatorsettings.GeneratorSettings) error { +func generateDryRun( + evaluator pkl.Evaluator, + tmpFile *os.File, + outputPath string, + settings *generatorsettings.GeneratorSettings, +) error { var filenames []string - err := evaluator.EvaluateExpression(context.Background(), pkl.FileSource(tmpFile.Name()), "output.files.toMap().keys.toList()", &filenames) + err := evaluator.EvaluateExpression( + context.Background(), + pkl.FileSource(tmpFile.Name()), + "output.files.toMap().keys.toList()", + &filenames, + ) if err != nil { return err } @@ -143,7 +153,10 @@ func GenerateGo( if settings.DryRun { return generateDryRun(evaluator, tmpFile, outputPath, settings) } - files, err := evaluator.EvaluateOutputFiles(context.Background(), pkl.FileSource(tmpFile.Name())) + files, err := evaluator.EvaluateOutputFiles( + context.Background(), + pkl.FileSource(tmpFile.Name()), + ) if err != nil { return err } @@ -151,7 +164,11 @@ func GenerateGo( for filename, contents := range files { if settings.BasePath != "" { if !strings.HasPrefix(filename, settings.BasePath) { - log("Skipping codegen for file \033[36m%s\033[0m because it does not exist in base path \033[36m%s\033[0m\n", filename, settings.BasePath) + log( + "Skipping codegen for file \033[36m%s\033[0m because it does not exist in base path \033[36m%s\033[0m\n", + filename, + settings.BasePath, + ) continue } filename = strings.TrimPrefix(filename, settings.BasePath) @@ -159,7 +176,11 @@ func GenerateGo( formatted, diff, err := doFormat(contents) if err != nil { - log("[warning] Attempted to format file %s but it produced an unexpected error. Error: %s\n", filename, err.Error()) + log( + "[warning] Attempted to format file %s but it produced an unexpected error. Error: %s\n", + filename, + err.Error(), + ) formatted = []byte(contents) } if diff != "" { diff --git a/cmd/pkl-gen-go/pkl-gen-go.go b/cmd/pkl-gen-go/pkl-gen-go.go index 28dff6a..5a7e72d 100644 --- a/cmd/pkl-gen-go/pkl-gen-go.go +++ b/cmd/pkl-gen-go/pkl-gen-go.go @@ -135,7 +135,8 @@ var Version = "development" func init() { info, ok := debug.ReadBuildInfo() - if !ok || info.Main.Version == "" || info.Main.Version == "(devel)" || Version != "development" { + if !ok || info.Main.Version == "" || info.Main.Version == "(devel)" || + Version != "development" { return } Version = strings.TrimPrefix(info.Main.Version, "v") @@ -161,7 +162,12 @@ func generatorSettingsSource() *pkl.ModuleSource { dirPath := filepath.Dir(filename) return pkl.FileSource(dirPath, "../../codegen/src/GeneratorSettings.pkl") } - return pkl.UriSource(fmt.Sprintf("package://pkg.pkl-lang.org/pkl-go/pkl.golang@%s#/GeneratorSettings.pkl", Version)) + return pkl.UriSource( + fmt.Sprintf( + "package://pkg.pkl-lang.org/pkl-go/pkl.golang@%s#/GeneratorSettings.pkl", + Version, + ), + ) } // mimick logic for finding project dir in the pkl CLI. @@ -189,7 +195,11 @@ func findProjectDir(projectDirFlag string) string { // Loads the settings for controlling codegen. // Uses a Pkl evaluator that is separate from what's used for actually running codegen. -func loadGeneratorSettings(generatorSettingsPath string, projectDirFlag string, cacheDirFlag string) (*generatorsettings.GeneratorSettings, error) { +func loadGeneratorSettings( + generatorSettingsPath string, + projectDirFlag string, + cacheDirFlag string, +) (*generatorsettings.GeneratorSettings, error) { projectDir := findProjectDir(projectDirFlag) var evaluator pkl.Evaluator var err error @@ -199,7 +209,12 @@ func loadGeneratorSettings(generatorSettingsPath string, projectDirFlag string, } } if projectDir != "" { - evaluator, err = pkl.NewProjectEvaluator(context.Background(), projectDir, pkl.PreconfiguredOptions, opts) + evaluator, err = pkl.NewProjectEvaluator( + context.Background(), + projectDir, + pkl.PreconfiguredOptions, + opts, + ) } else { evaluator, err = pkl.NewEvaluator(context.Background(), pkl.PreconfiguredOptions, opts) } @@ -241,17 +256,57 @@ func init() { var dryRun bool var projectDir string var cacheDir string - flags.StringVar(&generatorSettingsPath, "generator-settings", "", "The path to a generator settings file") + flags.StringVar( + &generatorSettingsPath, + "generator-settings", + "", + "The path to a generator settings file", + ) flags.StringVar(&generateScript, "generate-script", "", "The Generate.pkl script to use") - flags.StringToStringVar(&mappings, "mapping", nil, "The mapping of a Pkl module name to a Go package name") + flags.StringToStringVar( + &mappings, + "mapping", + nil, + "The mapping of a Pkl module name to a Go package name", + ) flags.StringVar(&basePath, "base-path", "", "The base path used to determine relative output") - flags.StringVar(&outputPath, "output-path", "", "The output directory to write generated sources into") - flags.BoolVar(&suppressWarnings, "suppress-format-warning", false, "Suppress warnings around formatting issues") - flags.StringSliceVar(&allowedModules, "allowed-modules", nil, "URI patterns that determine which modules can be loaded and evaluated") - flags.StringSliceVar(&allowedResources, "allowed-resources", nil, "URI patterns that determine which resources can be loaded and evaluated") - flags.StringVar(&projectDir, "project-dir", "", "The project directory to load dependency and evaluator settings from") + flags.StringVar( + &outputPath, + "output-path", + "", + "The output directory to write generated sources into", + ) + flags.BoolVar( + &suppressWarnings, + "suppress-format-warning", + false, + "Suppress warnings around formatting issues", + ) + flags.StringSliceVar( + &allowedModules, + "allowed-modules", + nil, + "URI patterns that determine which modules can be loaded and evaluated", + ) + flags.StringSliceVar( + &allowedResources, + "allowed-resources", + nil, + "URI patterns that determine which resources can be loaded and evaluated", + ) + flags.StringVar( + &projectDir, + "project-dir", + "", + "The project directory to load dependency and evaluator settings from", + ) flags.StringVar(&cacheDir, "cache-dir", "", "The cache directory for storing packages") - flags.BoolVar(&dryRun, "dry-run", false, "Print out the names of the files that will be generated, but don't write any files") + flags.BoolVar( + &dryRun, + "dry-run", + false, + "Print out the names of the files that will be generated, but don't write any files", + ) flags.BoolVar(&printVersion, "version", false, "Print the version and exit") var err error if err = flags.Parse(os.Args); err != nil && !errors.Is(err, pflag.ErrHelp) { diff --git a/pkl/decode_slice.go b/pkl/decode_slice.go index a7876a4..be689d1 100644 --- a/pkl/decode_slice.go +++ b/pkl/decode_slice.go @@ -30,7 +30,12 @@ func (d *decoder) decodeSlice(inType reflect.Type) (*reflect.Value, error) { return nil, fmt.Errorf("expected array length 2 but got %d", length) } if code != codeList && code != codeListing { - return nil, fmt.Errorf("invalid code for slices: %d. Expected %d or %d", code, codeList, codeListing) + return nil, fmt.Errorf( + "invalid code for slices: %d. Expected %d or %d", + code, + codeList, + codeListing, + ) } return d.decodeSliceImpl(inType) } diff --git a/pkl/decode_struct.go b/pkl/decode_struct.go index 5a570cc..43297f6 100644 --- a/pkl/decode_struct.go +++ b/pkl/decode_struct.go @@ -260,7 +260,8 @@ func (d *decoder) decodeStructField(fields map[string]structField, out *reflect. } sf, exists := fields[propertyName] if !exists { - log.Default().Printf("warn: Cannot find field on Go struct `%s` matching Pkl property `%s`. Ensure the Go structs are up to date with Pkl classes either through codegen or manually adding `pkl` tags.", out.Type().String(), propertyName) + log.Default(). + Printf("warn: Cannot find field on Go struct `%s` matching Pkl property `%s`. Ensure the Go structs are up to date with Pkl classes either through codegen or manually adding `pkl` tags.", out.Type().String(), propertyName) return d.dec.Skip() } code, err := d.dec.PeekCode() diff --git a/pkl/evaluator.go b/pkl/evaluator.go index fcb4776..2954095 100644 --- a/pkl/evaluator.go +++ b/pkl/evaluator.go @@ -63,13 +63,13 @@ type Evaluator interface { } type evaluator struct { - evaluatorId int64 logger Logger manager *evaluatorManager pendingRequests *sync.Map - closed bool resourceReaders []ResourceReader moduleReaders []ModuleReader + evaluatorId int64 + closed bool } var _ Evaluator = (*evaluator)(nil) @@ -88,13 +88,26 @@ func (e *evaluator) EvaluateOutputValue(ctx context.Context, source *ModuleSourc return e.EvaluateExpression(ctx, source, "output.value", out) } -func (e *evaluator) EvaluateOutputFiles(ctx context.Context, source *ModuleSource) (map[string]string, error) { +func (e *evaluator) EvaluateOutputFiles( + ctx context.Context, + source *ModuleSource, +) (map[string]string, error) { var out map[string]string - err := e.EvaluateExpression(ctx, source, "output.files.toMap().mapValues((_, it) -> it.text)", &out) + err := e.EvaluateExpression( + ctx, + source, + "output.files.toMap().mapValues((_, it) -> it.text)", + &out, + ) return out, err } -func (e *evaluator) EvaluateExpression(ctx context.Context, source *ModuleSource, expr string, out any) error { +func (e *evaluator) EvaluateExpression( + ctx context.Context, + source *ModuleSource, + expr string, + out any, +) error { bytes, err := e.EvaluateExpressionRaw(ctx, source, expr) if err != nil { return err @@ -102,7 +115,11 @@ func (e *evaluator) EvaluateExpression(ctx context.Context, source *ModuleSource return Unmarshal(bytes, out) } -func (e *evaluator) EvaluateExpressionRaw(ctx context.Context, source *ModuleSource, expr string) ([]byte, error) { +func (e *evaluator) EvaluateExpressionRaw( + ctx context.Context, + source *ModuleSource, + expr string, +) ([]byte, error) { if e.Closed() { return nil, fmt.Errorf("evaluator is closed") } @@ -146,7 +163,8 @@ func (e *evaluator) Closed() bool { func (e *evaluator) handleEvaluateResponse(resp *msgapi.EvaluateResponse) { c, exists := e.pendingRequests.Load(resp.RequestId) if !exists { - log.Default().Printf("warn: received a message for an unknown request id: %d", resp.RequestId) + log.Default(). + Printf("warn: received a message for an unknown request id: %d", resp.RequestId) return } ch := c.(chan *msgapi.EvaluateResponse) diff --git a/pkl/evaluator_exec.go b/pkl/evaluator_exec.go index 194ad2c..ec31e99 100644 --- a/pkl/evaluator_exec.go +++ b/pkl/evaluator_exec.go @@ -37,7 +37,11 @@ func NewEvaluator(ctx context.Context, opts ...func(options *EvaluatorOptions)) // // When using project dependencies, they must first be resolved using the `pkl project resolve` // CLI command. -func NewProjectEvaluator(ctx context.Context, projectDir string, opts ...func(options *EvaluatorOptions)) (Evaluator, error) { +func NewProjectEvaluator( + ctx context.Context, + projectDir string, + opts ...func(options *EvaluatorOptions), +) (Evaluator, error) { return NewProjectEvaluatorWithCommand(ctx, projectDir, nil, opts...) } @@ -52,7 +56,12 @@ func NewProjectEvaluator(ctx context.Context, projectDir string, opts ...func(op // // If creating multiple evaluators, prefer using EvaluatorManager.NewProjectEvaluator instead, // because it lessens the overhead of each successive evaluator. -func NewProjectEvaluatorWithCommand(ctx context.Context, projectDir string, pklCmd []string, opts ...func(options *EvaluatorOptions)) (Evaluator, error) { +func NewProjectEvaluatorWithCommand( + ctx context.Context, + projectDir string, + pklCmd []string, + opts ...func(options *EvaluatorOptions), +) (Evaluator, error) { manager := NewEvaluatorManagerWithCommand(pklCmd) projectEvaluator, err := manager.NewEvaluator(ctx, opts...) if err != nil { @@ -87,7 +96,11 @@ func NewProjectEvaluatorWithCommand(ctx context.Context, projectDir string, pklC // // If creating multiple evaluators, prefer using EvaluatorManager.NewEvaluator instead, // because it lessens the overhead of each successive evaluator. -func NewEvaluatorWithCommand(ctx context.Context, pklCmd []string, opts ...func(options *EvaluatorOptions)) (Evaluator, error) { +func NewEvaluatorWithCommand( + ctx context.Context, + pklCmd []string, + opts ...func(options *EvaluatorOptions), +) (Evaluator, error) { manager := NewEvaluatorManagerWithCommand(pklCmd) ev, err := manager.NewEvaluator(ctx, opts...) if err != nil { diff --git a/pkl/evaluator_manager.go b/pkl/evaluator_manager.go index b6b2b5e..670aaa5 100644 --- a/pkl/evaluator_manager.go +++ b/pkl/evaluator_manager.go @@ -55,7 +55,11 @@ type EvaluatorManager interface { // // When using project dependencies, they must first be resolved using the `pkl project resolve` // CLI command. - NewProjectEvaluator(ctx context.Context, projectDir string, opts ...func(options *EvaluatorOptions)) (Evaluator, error) + NewProjectEvaluator( + ctx context.Context, + projectDir string, + opts ...func(options *EvaluatorOptions), + ) (Evaluator, error) } type evaluatorManager struct { @@ -82,7 +86,10 @@ type evaluatorManagerImpl interface { var _ EvaluatorManager = (*evaluatorManager)(nil) -func (m *evaluatorManager) NewEvaluator(ctx context.Context, opts ...func(options *EvaluatorOptions)) (Evaluator, error) { +func (m *evaluatorManager) NewEvaluator( + ctx context.Context, + opts ...func(options *EvaluatorOptions), +) (Evaluator, error) { // Prevent concurrent calls to NewEvaluator because only the first call should call the `init` routine. m.newEvaluatorMutex.Lock() defer m.newEvaluatorMutex.Unlock() @@ -141,12 +148,20 @@ func (m *evaluatorManager) NewEvaluator(ctx context.Context, opts ...func(option } } -func (m *evaluatorManager) NewProjectEvaluator(ctx context.Context, projectDir string, opts ...func(options *EvaluatorOptions)) (Evaluator, error) { +func (m *evaluatorManager) NewProjectEvaluator( + ctx context.Context, + projectDir string, + opts ...func(options *EvaluatorOptions), +) (Evaluator, error) { projectEvaluator, err := NewEvaluator(ctx, opts...) if err != nil { return nil, err } - project, err := LoadProjectFromEvaluator(ctx, projectEvaluator, path.Join(projectDir, "PklProject")) + project, err := LoadProjectFromEvaluator( + ctx, + projectEvaluator, + path.Join(projectDir, "PklProject"), + ) if err != nil { return nil, err } @@ -176,7 +191,8 @@ func (m *evaluatorManager) Close() error { func (m *evaluatorManager) getEvaluator(evaluatorId int64) *evaluator { v, exists := m.evaluators.Load(evaluatorId) if !exists { - log.Default().Printf("warn: received a message for an unknown evaluator id: %d", evaluatorId) + log.Default(). + Printf("warn: received a message for an unknown evaluator id: %d", evaluatorId) return nil } return v.(*evaluator) diff --git a/pkl/evaluator_manager_exec.go b/pkl/evaluator_manager_exec.go index 3b5c540..31b634e 100644 --- a/pkl/evaluator_manager_exec.go +++ b/pkl/evaluator_manager_exec.go @@ -63,15 +63,15 @@ func NewEvaluatorManagerWithCommand(pklCommand []string) EvaluatorManager { } type execEvaluator struct { - cmd *exec.Cmd - in chan msgapi.IncomingMessage - out chan msgapi.OutgoingMessage - closed chan error - // exited is a flag that indicates evaluator was closed explicitly - exited atomicBool + cmd *exec.Cmd + in chan msgapi.IncomingMessage + out chan msgapi.OutgoingMessage + closed chan error version *semver - pklCommand []string processDone chan struct{} + pklCommand []string + // exited is a flag that indicates evaluator was closed explicitly + exited atomicBool } func (e *execEvaluator) inChan() chan msgapi.IncomingMessage { @@ -100,7 +100,11 @@ func (e *execEvaluator) getVersion() (*semver, error) { } matches := pklVersionRegex.FindStringSubmatch(string(versionCmdOut)) if len(matches) < 2 { - return nil, fmt.Errorf("failed to get version information from Pkl. Ran `%s`, and got stdout \"%s\"", strings.Join(command.Args, " "), versionCmdOut) + return nil, fmt.Errorf( + "failed to get version information from Pkl. Ran `%s`, and got stdout \"%s\"", + strings.Join(command.Args, " "), + versionCmdOut, + ) } version, err := parseSemver(matches[1]) if err != nil { diff --git a/pkl/evaluator_options.go b/pkl/evaluator_options.go index 8063ba8..042ea62 100644 --- a/pkl/evaluator_options.go +++ b/pkl/evaluator_options.go @@ -28,20 +28,39 @@ import ( // EvaluatorOptions is the set of options available to control Pkl evaluation. type EvaluatorOptions struct { + + // Logger is the logging interface for messages emitted by the Pkl evaluator. + Logger Logger + // Properties is the set of properties available to the `prop:` resource reader. Properties map[string]string // Env is the set of environment variables available to the `env:` resource reader. Env map[string]string - // ModulePaths is the set of directories, ZIP archives, or JAR archives to search when - // resolving `modulepath`: resources and modules. + // DeclaredProjectDepenedencies is set of dependencies available to modules within ProjectBaseURI. // - // This option must be non-emptyMirror if ModuleReaderModulePath or ResourceModulePath are used. - ModulePaths []string + // When importing dependencies, a PklProject.deps.json file must exist within ProjectBaseURI + // that contains the project's resolved dependencies. + DeclaredProjectDependencies *ProjectDependencies - // Logger is the logging interface for messages emitted by the Pkl evaluator. - Logger Logger + // Settings for controlling how Pkl talks over HTTP(S). + // + // Added in Pkl 0.26. + // If the underlying Pkl does not support HTTP options, NewEvaluator will return with an error. + Http *Http + + // ExternalModuleReaders registers external commands that implement module reader schemes. + // + // Added in Pkl 0.27. + // If the underlying Pkl does not support external readers, evaluation will fail when a registered scheme is used. + ExternalModuleReaders map[string]ExternalReader + + // ExternalResourceReaders registers external commands that implement resource reader schemes. + // + // Added in Pkl 0.27. + // If the underlying Pkl does not support external readers, evaluation will fail when a registered scheme is used. + ExternalResourceReaders map[string]ExternalReader // OutputFormat controls the renderer to be used when rendering the `output.text` // property of a module. @@ -57,24 +76,6 @@ type EvaluatorOptions struct { // - `"yaml"` OutputFormat string - // AllowedModules defines URI patterns that determine which modules are permitted to be loaded and evaluated. - // Patterns are regular expressions in the dialect understood by [java.util.regex.Pattern]. - // - // [java.util.regex.Pattern]: https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/util/regex/Pattern.html - AllowedModules []string - - // AllowedResources defines URI patterns that determine which resources are permitted to be loaded and evaluated. - // Patterns are regular expressions in the dialect understood by [java.util.regex.Pattern]. - // - // [java.util.regex.Pattern]: https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/util/regex/Pattern.html - AllowedResources []string - - // ResourceReaders are the resource readers to be used by the evaluator. - ResourceReaders []ResourceReader - - // ModuleReaders are the set of custom module readers to be used by the evaluator. - ModuleReaders []ModuleReader - // CacheDir is the directory where `package:` modules are cached. // // If empty, no cacheing is performed. @@ -106,34 +107,34 @@ type EvaluatorOptions struct { // or EvaluatorManager.NewProjectEvaluator. ProjectBaseURI string - // DeclaredProjectDepenedencies is set of dependencies available to modules within ProjectBaseURI. + // ModulePaths is the set of directories, ZIP archives, or JAR archives to search when + // resolving `modulepath`: resources and modules. // - // When importing dependencies, a PklProject.deps.json file must exist within ProjectBaseURI - // that contains the project's resolved dependencies. - DeclaredProjectDependencies *ProjectDependencies + // This option must be non-emptyMirror if ModuleReaderModulePath or ResourceModulePath are used. + ModulePaths []string - // Settings for controlling how Pkl talks over HTTP(S). + // AllowedModules defines URI patterns that determine which modules are permitted to be loaded and evaluated. + // Patterns are regular expressions in the dialect understood by [java.util.regex.Pattern]. // - // Added in Pkl 0.26. - // If the underlying Pkl does not support HTTP options, NewEvaluator will return with an error. - Http *Http + // [java.util.regex.Pattern]: https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/util/regex/Pattern.html + AllowedModules []string - // ExternalModuleReaders registers external commands that implement module reader schemes. + // AllowedResources defines URI patterns that determine which resources are permitted to be loaded and evaluated. + // Patterns are regular expressions in the dialect understood by [java.util.regex.Pattern]. // - // Added in Pkl 0.27. - // If the underlying Pkl does not support external readers, evaluation will fail when a registered scheme is used. - ExternalModuleReaders map[string]ExternalReader + // [java.util.regex.Pattern]: https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/util/regex/Pattern.html + AllowedResources []string - // ExternalResourceReaders registers external commands that implement resource reader schemes. - // - // Added in Pkl 0.27. - // If the underlying Pkl does not support external readers, evaluation will fail when a registered scheme is used. - ExternalResourceReaders map[string]ExternalReader + // ResourceReaders are the resource readers to be used by the evaluator. + ResourceReaders []ResourceReader + + // ModuleReaders are the set of custom module readers to be used by the evaluator. + ModuleReaders []ModuleReader } type ProjectRemoteDependency struct { - PackageUri string `pkl:"uri"` Checksums *Checksums `pkl:"checksums"` + PackageUri string `pkl:"uri"` } func (dep *ProjectRemoteDependency) toMessage() *msgapi.ProjectOrDependency { @@ -156,11 +157,10 @@ func (checksums *Checksums) toMessage() *msgapi.Checksums { } type ProjectLocalDependency struct { - PackageUri string + Dependencies *ProjectDependencies + PackageUri string ProjectFileUri string - - Dependencies *ProjectDependencies } func (dep *ProjectLocalDependency) toMessage() *msgapi.ProjectOrDependency { @@ -182,7 +182,10 @@ func (p *ProjectDependencies) toMessage() map[string]*msgapi.ProjectOrDependency if p == nil { return nil } - ret := make(map[string]*msgapi.ProjectOrDependency, len(p.LocalDependencies)+len(p.RemoteDependencies)) + ret := make( + map[string]*msgapi.ProjectOrDependency, + len(p.LocalDependencies)+len(p.RemoteDependencies), + ) for name, dep := range p.LocalDependencies { ret[name] = dep.toMessage() } @@ -193,15 +196,15 @@ func (p *ProjectDependencies) toMessage() map[string]*msgapi.ProjectOrDependency } type Http struct { - // PEM format certificates to trust when making HTTP requests. - // - // If empty, Pkl will trust its own built-in certificates. - CaCertificates []byte // Configuration of the HTTP proxy to use. // // If nil, uses the operating system's proxy configuration. Proxy *Proxy + // PEM format certificates to trust when making HTTP requests. + // + // If empty, Pkl will trust its own built-in certificates. + CaCertificates []byte } func (http *Http) toMessage() *msgapi.Http { @@ -319,7 +322,10 @@ var WithOsEnv = func(opts *EvaluatorOptions) { } } -func buildEvaluatorOptions(version *semver, fns ...func(*EvaluatorOptions)) (*EvaluatorOptions, error) { +func buildEvaluatorOptions( + version *semver, + fns ...func(*EvaluatorOptions), +) (*EvaluatorOptions, error) { o := &EvaluatorOptions{} for _, f := range fns { f(o) @@ -329,20 +335,43 @@ func buildEvaluatorOptions(version *semver, fns ...func(*EvaluatorOptions)) (*Ev if o.Http != nil && pklVersion0_26.isGreaterThan(version) { return nil, fmt.Errorf("http options are not supported on Pkl versions lower than 0.26") } - if (len(o.ExternalModuleReaders) > 0 || len(o.ExternalResourceReaders) > 0) && pklVersion0_27.isGreaterThan(version) { - return nil, fmt.Errorf("external reader options are not supported on Pkl versions lower than 0.27") + if (len(o.ExternalModuleReaders) > 0 || len(o.ExternalResourceReaders) > 0) && + pklVersion0_27.isGreaterThan(version) { + return nil, fmt.Errorf( + "external reader options are not supported on Pkl versions lower than 0.27", + ) } return o, nil } // WithDefaultAllowedResources enables reading http, https, file, env, prop, modulepath, and package resources. var WithDefaultAllowedResources = func(opts *EvaluatorOptions) { - opts.AllowedResources = append(opts.AllowedResources, "http:", "https:", "file:", "env:", "prop:", "modulepath:", "package:", "projectpackage:") + opts.AllowedResources = append( + opts.AllowedResources, + "http:", + "https:", + "file:", + "env:", + "prop:", + "modulepath:", + "package:", + "projectpackage:", + ) } // WithDefaultAllowedModules enables reading stdlib, repl, file, http, https, modulepath, and package modules. var WithDefaultAllowedModules = func(opts *EvaluatorOptions) { - opts.AllowedModules = append(opts.AllowedModules, "pkl:", "repl:", "file:", "http:", "https:", "modulepath:", "package:", "projectpackage:") + opts.AllowedModules = append( + opts.AllowedModules, + "pkl:", + "repl:", + "file:", + "http:", + "https:", + "modulepath:", + "package:", + "projectpackage:", + ) } // WithDefaultCacheDir sets the cache directory to Pkl's default location. @@ -431,7 +460,10 @@ var WithProjectEvaluatorSettings = func(project *Project) func(opts *EvaluatorOp } } if evaluatorSettings.ExternalModuleReaders != nil { - opts.ExternalModuleReaders = make(map[string]ExternalReader, len(evaluatorSettings.ExternalModuleReaders)) + opts.ExternalModuleReaders = make( + map[string]ExternalReader, + len(evaluatorSettings.ExternalModuleReaders), + ) for scheme, reader := range evaluatorSettings.ExternalModuleReaders { opts.ExternalModuleReaders[scheme] = ExternalReader(reader) if evaluatorSettings.AllowedModules == nil { // if no explicit allowed modules are set in the project, allow declared external module readers @@ -440,7 +472,10 @@ var WithProjectEvaluatorSettings = func(project *Project) func(opts *EvaluatorOp } } if evaluatorSettings.ExternalResourceReaders != nil { - opts.ExternalResourceReaders = make(map[string]ExternalReader, len(evaluatorSettings.ExternalResourceReaders)) + opts.ExternalResourceReaders = make( + map[string]ExternalReader, + len(evaluatorSettings.ExternalResourceReaders), + ) for scheme, reader := range evaluatorSettings.ExternalResourceReaders { opts.ExternalResourceReaders[scheme] = ExternalReader(reader) if evaluatorSettings.AllowedResources == nil { // if no explicit allowed resources are set in the project, allow declared external resource readers diff --git a/pkl/evaluator_test.go b/pkl/evaluator_test.go index dc86741..fdf0ba5 100644 --- a/pkl/evaluator_test.go +++ b/pkl/evaluator_test.go @@ -105,9 +105,13 @@ func TestEvaluator(t *testing.T) { }) t.Run("EvaluateOutputText - output format", func(t *testing.T) { - ev, err := manager.NewEvaluator(context.Background(), PreconfiguredOptions, func(options *EvaluatorOptions) { - options.OutputFormat = "yaml" - }) + ev, err := manager.NewEvaluator( + context.Background(), + PreconfiguredOptions, + func(options *EvaluatorOptions) { + options.OutputFormat = "yaml" + }, + ) if assert.NoError(t, err) { out, err := ev.EvaluateOutputText(context.Background(), TextSource("foo { bar = 1 }")) assert.NoError(t, err) @@ -152,11 +156,18 @@ bar: Int = 5 t.Run("custom logger", func(t *testing.T) { s := &stubLogger{} - ev, err := manager.NewEvaluator(context.Background(), PreconfiguredOptions, func(options *EvaluatorOptions) { - options.Logger = s - }) + ev, err := manager.NewEvaluator( + context.Background(), + PreconfiguredOptions, + func(options *EvaluatorOptions) { + options.Logger = s + }, + ) if assert.NoError(t, err) { - out, err := ev.EvaluateOutputText(context.Background(), TextSource("foo { bar = trace(\"bar\") }")) + out, err := ev.EvaluateOutputText( + context.Background(), + TextSource("foo { bar = trace(\"bar\") }"), + ) assert.NoError(t, err) assert.Equal(t, "foo {\n bar = \"bar\"\n}\n", out) if assert.Len(t, s.traces, 1) { @@ -173,9 +184,16 @@ bar: Int = 5 return []byte("Fred Flintstone"), nil }, } - ev, err := manager.NewEvaluator(context.Background(), PreconfiguredOptions, WithResourceReader(reader)) + ev, err := manager.NewEvaluator( + context.Background(), + PreconfiguredOptions, + WithResourceReader(reader), + ) if assert.NoError(t, err) { - out, err := ev.EvaluateOutputText(context.Background(), TextSource(`foo = read("flintstone:fred").text`)) + out, err := ev.EvaluateOutputText( + context.Background(), + TextSource(`foo = read("flintstone:fred").text`), + ) assert.NoError(t, err) assert.Equal(t, "foo = \"Fred Flintstone\"\n", out) assert.NoError(t, ev.Close()) @@ -189,9 +207,16 @@ bar: Int = 5 return nil, fmt.Errorf("cannot find resource %s", &url) }, } - ev, err := manager.NewEvaluator(context.Background(), PreconfiguredOptions, WithResourceReader(reader)) + ev, err := manager.NewEvaluator( + context.Background(), + PreconfiguredOptions, + WithResourceReader(reader), + ) if assert.NoError(t, err) { - out, err := ev.EvaluateOutputText(context.Background(), TextSource(`foo = read("flintstone:fred").text`)) + out, err := ev.EvaluateOutputText( + context.Background(), + TextSource(`foo = read("flintstone:fred").text`), + ) assert.Empty(t, out) assert.Error(t, err) assert.IsType(t, &EvalError{}, err) @@ -221,9 +246,16 @@ bar: Int = 5 }, isGlobbable: true, } - ev, err := manager.NewEvaluator(context.Background(), PreconfiguredOptions, WithResourceReader(reader)) + ev, err := manager.NewEvaluator( + context.Background(), + PreconfiguredOptions, + WithResourceReader(reader), + ) if assert.NoError(t, err) { - out, err := ev.EvaluateOutputText(context.Background(), TextSource(`flintstones = read*("flintstone:*")`)) + out, err := ev.EvaluateOutputText( + context.Background(), + TextSource(`flintstones = read*("flintstone:*")`), + ) assert.Nil(t, err) assert.Equal(t, `flintstones { ["flintstone:barney"] { @@ -258,9 +290,16 @@ bar: Int = 5 }, isGlobbable: true, } - ev, err := manager.NewEvaluator(context.Background(), PreconfiguredOptions, WithResourceReader(reader)) + ev, err := manager.NewEvaluator( + context.Background(), + PreconfiguredOptions, + WithResourceReader(reader), + ) if assert.NoError(t, err) { - out, err := ev.EvaluateOutputText(context.Background(), TextSource(`flintstones = read*("flintstone:*")`)) + out, err := ev.EvaluateOutputText( + context.Background(), + TextSource(`flintstones = read*("flintstone:*")`), + ) assert.Empty(t, out) assert.Error(t, err, "IOException: something went wrong") assert.Zero(t, out) @@ -275,9 +314,16 @@ bar: Int = 5 return `foo = 1`, nil }, } - ev, err := manager.NewEvaluator(context.Background(), PreconfiguredOptions, WithModuleReader(reader)) + ev, err := manager.NewEvaluator( + context.Background(), + PreconfiguredOptions, + WithModuleReader(reader), + ) if assert.NoError(t, err) { - out, err := ev.EvaluateOutputText(context.Background(), TextSource(`result = import("flintstone:fred").foo`)) + out, err := ev.EvaluateOutputText( + context.Background(), + TextSource(`result = import("flintstone:fred").foo`), + ) assert.NoError(t, err) assert.Equal(t, "result = 1\n", out) assert.NoError(t, ev.Close()) @@ -291,9 +337,16 @@ bar: Int = 5 return "", fmt.Errorf("no idea where %s is", &u) }, } - ev, err := manager.NewEvaluator(context.Background(), PreconfiguredOptions, WithModuleReader(reader)) + ev, err := manager.NewEvaluator( + context.Background(), + PreconfiguredOptions, + WithModuleReader(reader), + ) if assert.NoError(t, err) { - out, err := ev.EvaluateOutputText(context.Background(), TextSource(`result = import("flintstone:fred").foo`)) + out, err := ev.EvaluateOutputText( + context.Background(), + TextSource(`result = import("flintstone:fred").foo`), + ) assert.Empty(t, out) assert.Error(t, err) assert.Contains(t, err.Error(), "no idea where flintstone:fred is") @@ -321,9 +374,16 @@ bar: Int = 5 return "", nil }, } - ev, err := manager.NewEvaluator(context.Background(), PreconfiguredOptions, WithModuleReader(reader)) + ev, err := manager.NewEvaluator( + context.Background(), + PreconfiguredOptions, + WithModuleReader(reader), + ) if assert.NoError(t, err) { - out, err := ev.EvaluateOutputText(context.Background(), UriSource("flintstone:/foo/bar/baz.pkl")) + out, err := ev.EvaluateOutputText( + context.Background(), + UriSource("flintstone:/foo/bar/baz.pkl"), + ) assert.NoError(t, err) assert.Equal(t, `res { bar = 1 @@ -356,9 +416,16 @@ bar: Int = 5 }, nil }, } - ev, err := manager.NewEvaluator(context.Background(), PreconfiguredOptions, WithModuleReader(reader)) + ev, err := manager.NewEvaluator( + context.Background(), + PreconfiguredOptions, + WithModuleReader(reader), + ) if assert.NoError(t, err) { - out, err := ev.EvaluateOutputText(context.Background(), TextSource(`res = import*("flintstone:/**.pkl")`)) + out, err := ev.EvaluateOutputText( + context.Background(), + TextSource(`res = import*("flintstone:/**.pkl")`), + ) assert.NoError(t, err) assert.Equal(t, `res { ["flintstone:/bar.pkl"] { @@ -385,28 +452,48 @@ bar: Int = 5 return nil, fmt.Errorf("i failed") }, } - ev, err := manager.NewEvaluator(context.Background(), PreconfiguredOptions, WithModuleReader(reader)) + ev, err := manager.NewEvaluator( + context.Background(), + PreconfiguredOptions, + WithModuleReader(reader), + ) if assert.NoError(t, err) { - out, err := ev.EvaluateOutputText(context.Background(), TextSource(`res = import*("flintstone:/**.pkl")`)) + out, err := ev.EvaluateOutputText( + context.Background(), + TextSource(`res = import*("flintstone:/**.pkl")`), + ) assert.Error(t, err) assert.Zero(t, out) } }) t.Run("custom fs", func(t *testing.T) { - ev, err := manager.NewEvaluator(context.Background(), PreconfiguredOptions, WithFs(testFs, "testfs")) + ev, err := manager.NewEvaluator( + context.Background(), + PreconfiguredOptions, + WithFs(testFs, "testfs"), + ) if assert.NoError(t, err) { - out, err := ev.EvaluateOutputText(context.Background(), UriSource("testfs:/test_fixtures/testfs/person.pkl")) + out, err := ev.EvaluateOutputText( + context.Background(), + UriSource("testfs:/test_fixtures/testfs/person.pkl"), + ) assert.NoError(t, err) assert.Equal(t, `name = "Barney" age = 43 `, out) - out, err = ev.EvaluateOutputText(context.Background(), UriSource("testfs:/test_fixtures/testfs/subdir/person.pkl")) + out, err = ev.EvaluateOutputText( + context.Background(), + UriSource("testfs:/test_fixtures/testfs/subdir/person.pkl"), + ) assert.NoError(t, err) assert.Equal(t, `name = "Fred" age = 43 `, out) - out, err = ev.EvaluateOutputText(context.Background(), TextSource(`result = import*("testfs:/**.pkl")`)) + out, err = ev.EvaluateOutputText( + context.Background(), + TextSource(`result = import*("testfs:/**.pkl")`), + ) assert.NoError(t, err) assert.Equal(t, `result { ["testfs:/test_fixtures/testfs/person.pkl"] { @@ -425,9 +512,16 @@ age = 43 t.Run("EvaluatorManager.NewProjectEvaluator", func(t *testing.T) { // TODO(oss): re-enable this test after repos are public t.SkipNow() - ev, err := manager.NewProjectEvaluator(context.Background(), projectDir, PreconfiguredOptions) + ev, err := manager.NewProjectEvaluator( + context.Background(), + projectDir, + PreconfiguredOptions, + ) if assert.NoError(t, err) { - out, err := ev.EvaluateOutputText(context.Background(), FileSource(projectDir, "main.pkl")) + out, err := ev.EvaluateOutputText( + context.Background(), + FileSource(projectDir, "main.pkl"), + ) assert.NoError(t, err) assert.Equal(t, "uri = \"https://www.example.com\"\n", out) } @@ -451,7 +545,10 @@ age = 43 ch := make(chan string) for i := 0; i < 5; i++ { go func(j int) { - res, _ := ev.EvaluateOutputText(context.Background(), TextSource(fmt.Sprintf("foo = %d", j))) + res, _ := ev.EvaluateOutputText( + context.Background(), + TextSource(fmt.Sprintf("foo = %d", j)), + ) ch <- res }(i) } @@ -504,13 +601,17 @@ age = 43 if pklVersion0_26.isGreaterThan(version) { t.SkipNow() } - ev, err := manager.NewEvaluator(context.Background(), PreconfiguredOptions, func(options *EvaluatorOptions) { - options.Http = &Http{ - Proxy: &Proxy{ - Address: fmt.Sprintf("http://localhost:%d", getOpenPort()), - }, - } - }) + ev, err := manager.NewEvaluator( + context.Background(), + PreconfiguredOptions, + func(options *EvaluatorOptions) { + options.Http = &Http{ + Proxy: &Proxy{ + Address: fmt.Sprintf("http://localhost:%d", getOpenPort()), + }, + } + }, + ) if err != nil { t.Fatal(err) } @@ -526,14 +627,22 @@ age = 43 if version.isGreaterThan(pklVersion0_25) { t.SkipNow() } - _, err = manager.NewEvaluator(context.Background(), PreconfiguredOptions, func(options *EvaluatorOptions) { - options.Http = &Http{ - Proxy: &Proxy{ - Address: fmt.Sprintf("http://localhost:%d", getOpenPort()), - }, - } - }) - assert.ErrorContains(t, err, "http options are not supported on Pkl versions lower than 0.26") + _, err = manager.NewEvaluator( + context.Background(), + PreconfiguredOptions, + func(options *EvaluatorOptions) { + options.Http = &Http{ + Proxy: &Proxy{ + Address: fmt.Sprintf("http://localhost:%d", getOpenPort()), + }, + } + }, + ) + assert.ErrorContains( + t, + err, + "http options are not supported on Pkl versions lower than 0.26", + ) }) t.Cleanup(func() { diff --git a/pkl/external_reader.go b/pkl/external_reader.go index 6054228..721446c 100644 --- a/pkl/external_reader.go +++ b/pkl/external_reader.go @@ -74,7 +74,9 @@ var WithExternalClientStreams = func(requestReader io.Reader, responseWriter io. } // NewExternalReaderClient creates a new ExternalReaderClient. -func NewExternalReaderClient(opts ...func(options *ExternalReaderClientOptions)) (ExternalReaderClient, error) { +func NewExternalReaderClient( + opts ...func(options *ExternalReaderClientOptions), +) (ExternalReaderClient, error) { o := ExternalReaderClientOptions{} for _, f := range opts { f(&o) @@ -96,10 +98,10 @@ func NewExternalReaderClient(opts ...func(options *ExternalReaderClientOptions)) } type externalReaderClient struct { - ExternalReaderClientOptions in chan msgapi.IncomingMessage out chan msgapi.OutgoingMessage closed chan error + ExternalReaderClientOptions exited atomicBool } @@ -111,7 +113,11 @@ func (r *externalReaderClient) Run() error { internal.Debug("Registered module reader of type %T for scheme %q", reader, reader.Scheme()) } for _, reader := range r.ResourceReaders { - internal.Debug("Registered resource reader of type %T for scheme %q", reader, reader.Scheme()) + internal.Debug( + "Registered resource reader of type %T for scheme %q", + reader, + reader.Scheme(), + ) } go r.readIncomingMessages() @@ -205,7 +211,9 @@ func (r *externalReaderClient) handleInitializeModuleReader(msg *msgapi.Initiali } } -func (r *externalReaderClient) handleInitializeResourceReader(msg *msgapi.InitializeResourceReader) { +func (r *externalReaderClient) handleInitializeResourceReader( + msg *msgapi.InitializeResourceReader, +) { for _, reader := range r.ResourceReaders { if reader.Scheme() == msg.Scheme { r.out <- &msgapi.InitializeResourceReaderResponse{ @@ -280,7 +288,10 @@ func (r *externalReaderClient) handleReadModule(msg *msgapi.ReadModule) { } func (r *externalReaderClient) handleListResources(msg *msgapi.ListResources) { - response := &msgapi.ListResourcesResponse{EvaluatorId: msg.EvaluatorId, RequestId: msg.RequestId} + response := &msgapi.ListResourcesResponse{ + EvaluatorId: msg.EvaluatorId, + RequestId: msg.RequestId, + } u, err := url.Parse(msg.Uri) if err != nil { response.Error = fmt.Errorf("internal error: failed to parse resource url: %w", err).Error() diff --git a/pkl/external_reader_test.go b/pkl/external_reader_test.go index d01701d..1f6621c 100644 --- a/pkl/external_reader_test.go +++ b/pkl/external_reader_test.go @@ -55,7 +55,10 @@ func TestExternalReaderE2E(t *testing.T) { if !ok { panic("can't find caller") } - projectRoot := filepath.Join(filepath.Dir(filename), "../cmd/internal/test-external-reader/test-external-reader.go") + projectRoot := filepath.Join( + filepath.Dir(filename), + "../cmd/internal/test-external-reader/test-external-reader.go", + ) evaluator, err := manager.NewEvaluator( context.Background(), @@ -69,7 +72,10 @@ func TestExternalReaderE2E(t *testing.T) { return } - output, err := evaluator.EvaluateOutputText(context.Background(), FileSource(tempDir+"/test.pkl")) + output, err := evaluator.EvaluateOutputText( + context.Background(), + FileSource(tempDir+"/test.pkl"), + ) assert.NoError(t, err) assert.Equal(t, output, `fib5 = 5 fib10 = 55 diff --git a/pkl/internal/msgapi/incoming.go b/pkl/internal/msgapi/incoming.go index f885ec5..593a590 100644 --- a/pkl/internal/msgapi/incoming.go +++ b/pkl/internal/msgapi/incoming.go @@ -44,73 +44,82 @@ var ( type CreateEvaluatorResponse struct { incomingMessageImpl - RequestId int64 `msgpack:"requestId"` - EvaluatorId int64 `msgpack:"evaluatorId"` - Error string `msgpack:"error"` + Error string `msgpack:"error"` + + RequestId int64 `msgpack:"requestId"` + EvaluatorId int64 `msgpack:"evaluatorId"` } type EvaluateResponse struct { incomingMessageImpl - RequestId int64 `msgpack:"requestId"` - EvaluatorId int64 `msgpack:"evaluatorId"` - Result []byte `msgpack:"result"` - Error string `msgpack:"error"` + Error string `msgpack:"error"` + Result []byte `msgpack:"result"` + + RequestId int64 `msgpack:"requestId"` + EvaluatorId int64 `msgpack:"evaluatorId"` } type ReadResource struct { incomingMessageImpl - RequestId int64 `msgpack:"requestId"` - EvaluatorId int64 `msgpack:"evaluatorId"` - Uri string `msgpack:"uri"` + Uri string `msgpack:"uri"` + + RequestId int64 `msgpack:"requestId"` + EvaluatorId int64 `msgpack:"evaluatorId"` } type ReadModule struct { incomingMessageImpl - RequestId int64 `msgpack:"requestId"` - EvaluatorId int64 `msgpack:"evaluatorId"` - Uri string `msgpack:"uri"` + Uri string `msgpack:"uri"` + + RequestId int64 `msgpack:"requestId"` + EvaluatorId int64 `msgpack:"evaluatorId"` } type Log struct { incomingMessageImpl - EvaluatorId int64 `msgpack:"evaluatorId"` - Level int `msgpack:"level"` - Message string `msgpack:"message"` - FrameUri string `msgpack:"frameUri"` + Message string `msgpack:"message"` + FrameUri string `msgpack:"frameUri"` + + EvaluatorId int64 `msgpack:"evaluatorId"` + Level int `msgpack:"level"` } type ListResources struct { incomingMessageImpl - RequestId int64 `msgpack:"requestId"` - EvaluatorId int64 `msgpack:"evaluatorId"` - Uri string `msgpack:"uri"` + Uri string `msgpack:"uri"` + + RequestId int64 `msgpack:"requestId"` + EvaluatorId int64 `msgpack:"evaluatorId"` } type ListModules struct { incomingMessageImpl - RequestId int64 `msgpack:"requestId"` - EvaluatorId int64 `msgpack:"evaluatorId"` - Uri string `msgpack:"uri"` + Uri string `msgpack:"uri"` + + RequestId int64 `msgpack:"requestId"` + EvaluatorId int64 `msgpack:"evaluatorId"` } type InitializeModuleReader struct { incomingMessageImpl - RequestId int64 `msgpack:"requestId"` - Scheme string `msgpack:"scheme"` + Scheme string `msgpack:"scheme"` + + RequestId int64 `msgpack:"requestId"` } type InitializeResourceReader struct { incomingMessageImpl - RequestId int64 `msgpack:"requestId"` - Scheme string `msgpack:"scheme"` + Scheme string `msgpack:"scheme"` + + RequestId int64 `msgpack:"requestId"` } type CloseExternalProcess struct { diff --git a/pkl/internal/msgapi/outgoing.go b/pkl/internal/msgapi/outgoing.go index a037b98..f75d375 100644 --- a/pkl/internal/msgapi/outgoing.go +++ b/pkl/internal/msgapi/outgoing.go @@ -66,37 +66,37 @@ type ModuleReader struct { } type CreateEvaluator struct { - RequestId int64 `msgpack:"requestId"` - ResourceReaders []*ResourceReader `msgpack:"clientResourceReaders,omitempty"` - ModuleReaders []*ModuleReader `msgpack:"clientModuleReaders,omitempty"` - ExternalReaderCommands [][]string `msgpack:"externalReaderCommands,omitempty"` - ModulePaths []string `msgpack:"modulePaths,omitempty"` - Env map[string]string `msgpack:"env,omitempty"` - Properties map[string]string `msgpack:"properties,omitempty"` - OutputFormat string `msgpack:"outputFormat,omitempty"` - AllowedModules []string `msgpack:"allowedModules,omitempty"` - AllowedResources []string `msgpack:"allowedResources,omitempty"` - RootDir string `msgpack:"rootDir,omitempty"` - CacheDir string `msgpack:"cacheDir,omitempty"` - Project *ProjectOrDependency `msgpack:"project,omitempty"` - Http *Http `msgpack:"http,omitempty"` - // Intentionally not used right now. Go has `context.WithTimeout` which is a more canonical way to handle timeouts. - TimeoutSeconds int64 `msgpack:"timeoutSeconds,omitempty"` + Env map[string]string `msgpack:"env,omitempty"` + Properties map[string]string `msgpack:"properties,omitempty"` + Project *ProjectOrDependency `msgpack:"project,omitempty"` + Http *Http `msgpack:"http,omitempty"` ExternalModuleReaders map[string]*ExternalReader `msgpack:"externalModuleReaders,omitempty"` ExternalResourceReaders map[string]*ExternalReader `msgpack:"externalResourceReaders,omitempty"` + OutputFormat string `msgpack:"outputFormat,omitempty"` + RootDir string `msgpack:"rootDir,omitempty"` + CacheDir string `msgpack:"cacheDir,omitempty"` + ResourceReaders []*ResourceReader `msgpack:"clientResourceReaders,omitempty"` + ModuleReaders []*ModuleReader `msgpack:"clientModuleReaders,omitempty"` + ExternalReaderCommands [][]string `msgpack:"externalReaderCommands,omitempty"` + ModulePaths []string `msgpack:"modulePaths,omitempty"` + AllowedModules []string `msgpack:"allowedModules,omitempty"` + AllowedResources []string `msgpack:"allowedResources,omitempty"` + RequestId int64 `msgpack:"requestId"` + // Intentionally not used right now. Go has `context.WithTimeout` which is a more canonical way to handle timeouts. + TimeoutSeconds int64 `msgpack:"timeoutSeconds,omitempty"` } type ProjectOrDependency struct { + Checksums *Checksums `msgpack:"checksums,omitempty"` + Dependencies map[string]*ProjectOrDependency `msgpack:"dependencies"` PackageUri string `msgpack:"packageUri,omitempty"` Type string `msgpack:"type"` ProjectFileUri string `msgpack:"projectFileUri,omitempty"` - Checksums *Checksums `msgpack:"checksums,omitempty"` - Dependencies map[string]*ProjectOrDependency `msgpack:"dependencies"` } type Http struct { - CaCertificates []byte `msgpack:"caCertificates,omitempty"` Proxy *Proxy `msgpack:"proxy,omitempty"` + CaCertificates []byte `msgpack:"caCertificates,omitempty"` } type Proxy struct { @@ -126,11 +126,11 @@ func (msg *CloseEvaluator) ToMsgPack() ([]byte, error) { } type Evaluate struct { - RequestId int64 `msgpack:"requestId"` - EvaluatorId int64 `msgpack:"evaluatorId"` ModuleUri string `msgpack:"moduleUri"` ModuleText string `msgpack:"moduleText,omitempty"` Expr string `msgpack:"expr,omitempty"` + RequestId int64 `msgpack:"requestId"` + EvaluatorId int64 `msgpack:"evaluatorId"` } func (msg *Evaluate) ToMsgPack() ([]byte, error) { @@ -138,10 +138,10 @@ func (msg *Evaluate) ToMsgPack() ([]byte, error) { } type ReadResourceResponse struct { + Error string `msgpack:"error,omitempty"` + Contents []byte `msgpack:"contents,omitempty"` RequestId int64 `msgpack:"requestId"` EvaluatorId int64 `msgpack:"evaluatorId"` - Contents []byte `msgpack:"contents,omitempty"` - Error string `msgpack:"error,omitempty"` } func (msg *ReadResourceResponse) ToMsgPack() ([]byte, error) { @@ -149,10 +149,10 @@ func (msg *ReadResourceResponse) ToMsgPack() ([]byte, error) { } type ReadModuleResponse struct { - RequestId int64 `msgpack:"requestId"` - EvaluatorId int64 `msgpack:"evaluatorId"` Contents string `msgpack:"contents,omitempty"` Error string `msgpack:"error,omitempty"` + RequestId int64 `msgpack:"requestId"` + EvaluatorId int64 `msgpack:"evaluatorId"` } func (msg *ReadModuleResponse) ToMsgPack() ([]byte, error) { @@ -160,10 +160,10 @@ func (msg *ReadModuleResponse) ToMsgPack() ([]byte, error) { } type ListResourcesResponse struct { + Error string `msgpack:"error,omitempty"` + PathElements []*PathElement `msgpack:"pathElements,omitempty"` RequestId int64 `msgpack:"requestId"` EvaluatorId int64 `msgpack:"evaluatorId"` - PathElements []*PathElement `msgpack:"pathElements,omitempty"` - Error string `msgpack:"error,omitempty"` } func (msg ListResourcesResponse) ToMsgPack() ([]byte, error) { @@ -171,10 +171,10 @@ func (msg ListResourcesResponse) ToMsgPack() ([]byte, error) { } type ListModulesResponse struct { + Error string `msgpack:"error,omitempty"` + PathElements []*PathElement `msgpack:"pathElements,omitempty"` RequestId int64 `msgpack:"requestId"` EvaluatorId int64 `msgpack:"evaluatorId"` - PathElements []*PathElement `msgpack:"pathElements,omitempty"` - Error string `msgpack:"error,omitempty"` } func (msg ListModulesResponse) ToMsgPack() ([]byte, error) { @@ -187,8 +187,8 @@ type PathElement struct { } type InitializeModuleReaderResponse struct { - RequestId int64 `msgpack:"requestId"` Spec *ModuleReader `msgpack:"spec,omitempty"` + RequestId int64 `msgpack:"requestId"` } func (msg InitializeModuleReaderResponse) ToMsgPack() ([]byte, error) { @@ -196,8 +196,8 @@ func (msg InitializeModuleReaderResponse) ToMsgPack() ([]byte, error) { } type InitializeResourceReaderResponse struct { - RequestId int64 `msgpack:"requestId"` Spec *ResourceReader `msgpack:"spec,omitempty"` + RequestId int64 `msgpack:"requestId"` } func (msg InitializeResourceReaderResponse) ToMsgPack() ([]byte, error) { diff --git a/pkl/project.go b/pkl/project.go index 3e1c794..1f364da 100644 --- a/pkl/project.go +++ b/pkl/project.go @@ -30,17 +30,17 @@ func init() { // Project is the go representation of pkl.Project. type Project struct { - ProjectFileUri string `pkl:"projectFileUri"` Package *ProjectPackage `pkl:"package"` EvaluatorSettings *ProjectEvaluatorSettings `pkl:"evaluatorSettings"` - Tests []string `pkl:"tests"` - Annotations []Object `pkl:"annotations"` // internal field; use Project.Dependencies instead. // values are either *Project or *ProjectRemoteDependency RawDependencies map[string]any `pkl:"dependencies"` - dependencies *ProjectDependencies `pkl:"-"` + dependencies *ProjectDependencies `pkl:"-"` + ProjectFileUri string `pkl:"projectFileUri"` + Tests []string `pkl:"tests"` + Annotations []Object `pkl:"annotations"` } // ProjectPackage is the go representation of pkl.Project#Package. @@ -50,7 +50,6 @@ type ProjectPackage struct { Version string `pkl:"version"` PackageZipUrl string `pkl:"packageZipUrl"` Description string `pkl:"description"` - Authors []string `pkl:"authors"` Website string `pkl:"website"` Documentation string `pkl:"documentation"` SourceCode string `pkl:"sourceCode"` @@ -58,9 +57,10 @@ type ProjectPackage struct { License string `pkl:"license"` LicenseText string `pkl:"licenseText"` IssueTracker string `pkl:"issueTracker"` + Uri string `pkl:"uri"` + Authors []string `pkl:"authors"` ApiTests []string `pkl:"apiTests"` Exclude []string `pkl:"exclude"` - Uri string `pkl:"uri"` } // ProjectEvaluatorSettings is the Go representation of pkl.EvaluatorSettings @@ -70,14 +70,14 @@ type ProjectEvaluatorSettings struct { AllowedModules *[]string `pkl:"allowedModules"` AllowedResources *[]string `pkl:"allowedResources"` NoCache *bool `pkl:"noCache"` - ModulePath []string `pkl:"modulePath"` - Timeout Duration `pkl:"timeout"` - ModuleCacheDir string `pkl:"moduleCacheDir"` - RootDir string `pkl:"rootDir"` Http *ProjectEvaluatorSettingsHttp `pkl:"http"` - Color string `pkl:"color"` ExternalModuleReaders map[string]ProjectEvaluatorSettingExternalReader `pkl:"externalModuleReaders"` ExternalResourceReaders map[string]ProjectEvaluatorSettingExternalReader `pkl:"externalResourceReaders"` + ModuleCacheDir string `pkl:"moduleCacheDir"` + RootDir string `pkl:"rootDir"` + Color string `pkl:"color"` + ModulePath []string `pkl:"modulePath"` + Timeout Duration `pkl:"timeout"` } // ProjectEvaluatorSettingsHttp is the Go representation of pkl.EvaluatorSettings.Http @@ -135,7 +135,11 @@ func LoadProject(context context.Context, path string) (*Project, error) { return LoadProjectFromEvaluator(context, ev, path) } -func LoadProjectFromEvaluator(context context.Context, ev Evaluator, path string) (*Project, error) { +func LoadProjectFromEvaluator( + context context.Context, + ev Evaluator, + path string, +) (*Project, error) { var proj Project if err := ev.EvaluateOutputValue(context, FileSource(path), &proj); err != nil { return nil, err diff --git a/pkl/project_test.go b/pkl/project_test.go index 3fad79f..3ee0702 100644 --- a/pkl/project_test.go +++ b/pkl/project_test.go @@ -178,7 +178,11 @@ func TestLoadProject(t *testing.T) { project, err := LoadProject(context.Background(), tempDir+"/hawks/PklProject") if assert.NoError(t, err) { t.Run("projectFileUri", func(t *testing.T) { - assert.Equal(t, fmt.Sprintf("file://%s/hawks/PklProject", tempDir), project.ProjectFileUri) + assert.Equal( + t, + fmt.Sprintf("file://%s/hawks/PklProject", tempDir), + project.ProjectFileUri, + ) }) t.Run("annotations", func(t *testing.T) { diff --git a/pkl/unmarshal_test.go b/pkl/unmarshal_test.go index fd8cf24..4437cab 100644 --- a/pkl/unmarshal_test.go +++ b/pkl/unmarshal_test.go @@ -439,5 +439,9 @@ func TestUnmarshal_UnknownType(t *testing.T) { var res unknowntype.UnknownType err := pkl.Unmarshal(unknownType, &res) assert.Error(t, err) - assert.Equal(t, "cannot decode Pkl value of type `PcfRenderer` into Go type `interface {}`. Define a custom mapping for this using `pkl.RegisterMapping`", err.Error()) + assert.Equal( + t, + "cannot decode Pkl value of type `PcfRenderer` into Go type `interface {}`. Define a custom mapping for this using `pkl.RegisterMapping`", + err.Error(), + ) } diff --git a/pkl/version.go b/pkl/version.go index 3c309f9..3e9efb3 100644 --- a/pkl/version.go +++ b/pkl/version.go @@ -23,7 +23,9 @@ import ( "strings" ) -var semverPattern = regexp.MustCompile(`(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-((?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\+([0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?`) +var semverPattern = regexp.MustCompile( + `(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-((?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\+([0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?`, +) var numericIdentifer = regexp.MustCompile(`^(0|[1-9]\d*)$`) @@ -37,17 +39,17 @@ var pklVersion0_26 = mustParseSemver("0.26.0") var pklVersion0_27 = mustParseSemver("0.27.0") type semver struct { - major int - minor int - patch int prerelease string build string prereleaseIdentifiers []prereleaseIdentifier + major int + minor int + patch int } type prereleaseIdentifier struct { - numericId int alphaNumericId string + numericId int } func (i prereleaseIdentifier) compareTo(other prereleaseIdentifier) int {