Skip to content

Commit

Permalink
feat(parser): pass filename for making pretty-formatted line numbers
Browse files Browse the repository at this point in the history
  • Loading branch information
tdakkota committed Jul 5, 2022
1 parent 236504d commit 1e3fdc1
Show file tree
Hide file tree
Showing 8 changed files with 46 additions and 9 deletions.
3 changes: 3 additions & 0 deletions cmd/ogen/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,7 @@ func run() error {
if flag.NArg() == 0 || specPath == "" {
return errors.New("no spec provided")
}
specPath = filepath.Clean(specPath)

switch files, err := os.ReadDir(*targetDir); {
case os.IsNotExist(err):
Expand All @@ -138,6 +139,7 @@ func run() error {
_ = logger.Sync()
}()

_, fileName := filepath.Split(specPath)
opts := gen.Options{
NoClient: *noClient,
NoServer: *noServer,
Expand All @@ -146,6 +148,7 @@ func run() error {
SkipUnimplemented: *skipUnimplemented,
InferSchemaType: *inferTypes,
AllowRemote: *allowRemote,
Filename: fileName,
Filters: gen.Filters{
PathRegex: filterPath,
Methods: filterMethods,
Expand Down
5 changes: 5 additions & 0 deletions gen/generator.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,10 @@ type Options struct {
AllowRemote bool
// Remote is remote reference resolver options.
Remote RemoteOptions
// Filename is a name of the spec file.
//
// Used for error messages.
Filename string
// Filters contains filters to skip operations.
Filters Filters
// IgnoreNotImplemented contains ErrNotImplemented messages to ignore.
Expand Down Expand Up @@ -98,6 +102,7 @@ func NewGenerator(spec *ogen.Spec, opts Options) (*Generator, error) {
}
api, err := parser.Parse(spec, parser.Settings{
External: external,
Filename: opts.Filename,
InferTypes: opts.InferSchemaType,
})
if err != nil {
Expand Down
5 changes: 4 additions & 1 deletion gen_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -119,11 +119,14 @@ func TestGenerate(t *testing.T) {
func TestNegative(t *testing.T) {
walkTestdata(t, "_testdata/negative", func(t *testing.T, file string, data []byte) {
a := require.New(t)
_, name := path.Split(file)

spec, err := ogen.Parse(data)
a.NoError(err)

_, err = gen.NewGenerator(spec, gen.Options{})
_, err = gen.NewGenerator(spec, gen.Options{
Filename: name,
})
a.Error(err)
t.Logf("%+v", err)
})
Expand Down
2 changes: 1 addition & 1 deletion json/location.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ func (l Location) String() string {
if l.Line == 0 {
return strconv.Quote(l.JSONPointer)
}
return fmt.Sprintf("line %d:%d", l.Line, l.Column)
return fmt.Sprintf("%d:%d", l.Line, l.Column)
}

// Locatable is an interface for JSON value location store.
Expand Down
32 changes: 26 additions & 6 deletions openapi/parser/errors.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,24 +16,43 @@ var _ interface {

// LocationError is a wrapper for an error that has a location.
type LocationError struct {
loc ogenjson.Location
err error
file string
loc ogenjson.Location
err error
}

// Unwrap implements errors.Wrapper.
func (e *LocationError) Unwrap() error {
return e.err
}

func (e *LocationError) fileName() string {
filename := e.file
if filename != "" {
switch {
case e.loc.Line != 0:
// Line is set, so return "${filename}:".
filename += ":"
case e.loc.JSONPointer != "":
// Line is not set, but JSONPointer is set, so return "${filename}#${JSONPointer}".
filename += "#"
default:
// Neither line nor JSONPointer is set, so return empty string.
return ""
}
}
return filename
}

// FormatError implements errors.Formatter.
func (e *LocationError) FormatError(p errors.Printer) (next error) {
p.Printf("at %s", e.loc)
p.Printf("at %s%s", e.fileName(), e.loc)
return e.err
}

// Error implements error.
func (e *LocationError) Error() string {
return fmt.Sprintf("at %s: %s", e.loc, e.err)
return fmt.Sprintf("at %s%s: %s", e.fileName(), e.loc, e.err)
}

func (p *parser) wrapLocation(l ogenjson.Locatable, err error) error {
Expand All @@ -45,7 +64,8 @@ func (p *parser) wrapLocation(l ogenjson.Locatable, err error) error {
return err
}
return &LocationError{
loc: loc,
err: err,
file: p.filename,
loc: loc,
err: err,
}
}
2 changes: 2 additions & 0 deletions openapi/parser/parser.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ type parser struct {
external jsonschema.ExternalResolver
schemas map[string][]byte
depthLimit int
filename string // optional, used for error messages

schemaParser *jsonschema.Parser
}
Expand Down Expand Up @@ -58,6 +59,7 @@ func Parse(spec *ogen.Spec, s Settings) (*openapi.API, error) {
"": spec.Raw,
},
depthLimit: s.DepthLimit,
filename: s.Filename,
schemaParser: jsonschema.NewParser(jsonschema.Settings{
External: s.External,
Resolver: componentsResolver{
Expand Down
1 change: 0 additions & 1 deletion openapi/parser/resolve.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,6 @@ func resolvePointer(root []byte, ptr string, to interface{}) error {
if err != nil {
return err
}

return json.Unmarshal(data, to)
}

Expand Down
5 changes: 5 additions & 0 deletions openapi/parser/settings.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,11 @@ type Settings struct {
// External is external JSON Schema resolver. If nil, NoExternal resolver is used.
External jsonschema.ExternalResolver

// Filename is a name of the file being parsed.
//
// Used for error messages.
Filename string

// DepthLimit limits the number of nested references. Default is 1000.
DepthLimit int

Expand Down

0 comments on commit 1e3fdc1

Please sign in to comment.