Skip to content

Commit 1506641

Browse files
committed
Revamp the spec package and document for stability
Revisit and make significant changes to the spec package toward public stability, usability, and greater comprehension. Make the names of things more consistent, the APIs more legible and user-friendly, and the documentation thorough, with examples for each significant type. Details: * Add examples for all the various types. * Make type names more consistent and appropriately descriptive: * Always use `Func` as a prefix rather than sometimes `Function` * Rename `FilterQuery` to `NodesQuery` to complement `SingularQuery` * Remove the `Func` prefix from the stringification of `FuncType`s * Always use `Nodes` as a suffix in methods, constructors, and value names (`FuncNodes`) than sometimes `NodeList` (but retain the latter for types) * `ValueType`, and `NodesType` stringification now returns Go-formatted values rather than the strings "ValueType" and "NodesType" * Use variadic parameters in object constructors to decrease verbosity and improve legibility. * Ensure consistent stringification and implementation of `fmt.Stringer`. * Document the use cases for each type, and list interface implementations for improved cross-referencing. * Consistently use doc links when referring to other types, fix invalid type names in doc comments, and copiously cross-reference related types. * Add constructors for most types that lacked them, and use them consistently in the parser and registry packages. * Add links to the relevant parts of [RFC 9535] for most types. * Replace `FuncType.ConvertsTo()` method and its dependent data type, `PathType`, with separate methods for each type that function validators care about: `ConvertsToValue()`, `ConvertsToLogical()`, and `ConvertsToNode()`. * Make fields of most structs private where they weren't already. The exception is `LocatedNode`, which is a simple wrapper around a value and its location. * Remove the "Package Stability" statement from the README. Also: Add support for `json.Number` values to complement the existing support for all Go numeric types. This should allow for transparent handling of values marshaled with [json.Decoder.UseNumber] enabled. [RFC 9535]: https://www.rfc-editor.org/rfc/rfc9535.html [json.Decoder.UseNumber]: https://pkg.go.dev/encoding/json#Decoder.UseNumber
1 parent 4ba89c7 commit 1506641

30 files changed

+2260
-1482
lines changed

.golangci.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ linters:
3636
- stdlib
3737
- generic
3838
- spec\.JSONPathValue
39-
- spec\.FunctionExprArg
39+
- spec\.FuncExprArg
4040
- spec\.Selector
4141
- spec\.BasicExpr
4242
- spec\.CompVal

CHANGELOG.md

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,26 @@ All notable changes to this project will be documented in this file. It uses the
77
[Semantic Versioning]: https://semver.org/spec/v2.0.0.html
88
"Semantic Versioning 2.0.0"
99

10+
## [v0.10.0] — Unreleased
11+
12+
### ⚡ Improvements
13+
14+
* Made significant changes to the `spec` package toward public stability,
15+
usability, and greater comprehension. The names of things are more
16+
consistent, the APIs more legible and user-friendly, and the documentation
17+
thorough, with examples for each significant type. See [PR #14] for
18+
details.
19+
* Removed the "Package Stability" statement from the README, as all packages
20+
are considered stable.
21+
* Added support for [json.Number] values to complement the existing support
22+
for Go core numeric types. This should allow for transparent handling of
23+
values marshaled with [json.Decoder.UseNumber] enabled.
24+
25+
[v0.4.1]: https://github.com/theory/jsonpath/compare/v0.4.1...v0.10.0
26+
[json.Number]: https://pkg.go.dev/encoding/json#Number
27+
[json.Decoder.UseNumber]: https://pkg.go.dev/encoding/json#Decoder.UseNumber
28+
[PR #14]: https://github.com/theory/jsonpath/pull/14
29+
1030
## [v0.4.1] — 2025-05-02
1131

1232
### 🪲 Bug Fixes

README.md

Lines changed: 0 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -33,21 +33,6 @@ A brief overview of [RFC 9535 JSONPath] syntax:
3333
| `?<logical-expr>` | filter selector: selects particular children using a logical expression |
3434
| `length(@.foo)` | function extension: invokes a function in a filter expression |
3535

36-
## Package Stability
37-
38-
The root `jsonpath` package is stable and ready for use. These are the main
39-
interfaces to the package.
40-
41-
The `registry` package is also stable, but exposes data types from the `spec`
42-
package that are still in flux. Argument data types may still change.
43-
44-
The `parser` package interface is also stable, but in general should not be
45-
used directly.
46-
47-
The `spec` package remains under active development, mainly refactoring,
48-
reorganizing, renaming, and documenting. Its interface therefore is not stable
49-
and should not be used for production purposes.
50-
5136
## Copyright
5237

5338
Copyright © 2024-2025 David E. Wheeler

parser/parse.go

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,7 @@ func (p *parser) parseQuery(root bool) (*spec.PathQuery, error) {
105105
fallthrough
106106
default:
107107
// Done parsing.
108-
return spec.Query(root, segs), nil
108+
return spec.Query(root, segs...), nil
109109
}
110110
}
111111
}
@@ -288,7 +288,7 @@ func (p *parser) parseFilter() (*spec.FilterSelector, error) {
288288
if err != nil {
289289
return nil, err
290290
}
291-
return spec.Filter(lor), nil
291+
return spec.Filter(lor...), nil
292292
}
293293

294294
// parseLogicalOrExpr parses a [LogicalOrExpr] from lex. A [LogicalOrExpr] is
@@ -410,7 +410,7 @@ func (p *parser) parseBasicExpr() (spec.BasicExpr, error) {
410410

411411
// parseFunctionFilterExpr parses a [BasicExpr] (basic-expr) that starts with
412412
// ident, which must be an identifier token that's expected to be the name of
413-
// a function. The return value will be either a [FunctionExpr]
413+
// a function. The return value will be either a [spec.FuncExpr]
414414
// (function-expr), if the function return value is a logical (boolean) value.
415415
// Otherwise it will be a [ComparisonExpr] (comparison-expr), as long as the
416416
// function call is compared to another expression. Any other configuration
@@ -481,7 +481,7 @@ func (p *parser) parseParenExpr() (*spec.ParenExpr, error) {
481481
if err != nil {
482482
return nil, err
483483
}
484-
return spec.Paren(expr), nil
484+
return spec.Paren(expr...), nil
485485
}
486486

487487
// parseParenExpr parses a [*spec.NotParenExpr] expression (logical-not-op
@@ -493,14 +493,14 @@ func (p *parser) parseNotParenExpr() (*spec.NotParenExpr, error) {
493493
if err != nil {
494494
return nil, err
495495
}
496-
return spec.NotParen(expr), nil
496+
return spec.NotParen(expr...), nil
497497
}
498498

499499
// parseFunction parses a function named tok.val from lex. tok should be the
500500
// token just before the next call to lex.scan, and must be an identifier
501501
// token naming the function. Returns an error if the function is not found in
502502
// the registry or if arguments are invalid for the function.
503-
func (p *parser) parseFunction(tok token) (*spec.FunctionExpr, error) {
503+
func (p *parser) parseFunction(tok token) (*spec.FuncExpr, error) {
504504
function := p.reg.Get(tok.val)
505505
if function == nil {
506506
return nil, makeError(tok, fmt.Sprintf("unknown function %v()", tok.val))
@@ -516,14 +516,14 @@ func (p *parser) parseFunction(tok token) (*spec.FunctionExpr, error) {
516516
return nil, makeError(paren, fmt.Sprintf("function %v() %v", tok.val, err.Error()))
517517
}
518518

519-
return spec.Function(function, args), nil
519+
return spec.Function(function, args...), nil
520520
}
521521

522522
// parseFunctionArgs parses the comma-delimited arguments to a function from
523523
// lex. Arguments may be one of literal, filter-query (including
524524
// singular-query), logical-expr, or function-expr.
525-
func (p *parser) parseFunctionArgs() ([]spec.FunctionExprArg, error) {
526-
res := []spec.FunctionExprArg{}
525+
func (p *parser) parseFunctionArgs() ([]spec.FuncExprArg, error) {
526+
res := []spec.FuncExprArg{}
527527
lex := p.lex
528528
for {
529529
switch tok := p.lex.scan(); tok.tok {
@@ -730,7 +730,7 @@ func parseSingularQuery(startToken token, lex *lexer) (*spec.SingularQueryExpr,
730730
selectors = append(selectors, spec.Name(tok.val))
731731
default:
732732
// Done parsing.
733-
return spec.SingularQuery(startToken.tok == '$', selectors), nil
733+
return spec.SingularQuery(startToken.tok == '$', selectors...), nil
734734
}
735735
}
736736
}

0 commit comments

Comments
 (0)