Skip to content

Commit

Permalink
feat(ogen): pretty print discriminator inference error
Browse files Browse the repository at this point in the history
  • Loading branch information
tdakkota committed Feb 26, 2024
1 parent 6d115d4 commit 8acab2e
Showing 1 changed file with 86 additions and 23 deletions.
109 changes: 86 additions & 23 deletions cmd/ogen/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,24 +3,28 @@ package main

import (
"bytes"
"cmp"

Check failure on line 6 in cmd/ogen/main.go

View workflow job for this annotation

GitHub Actions / test

package cmp is not in GOROOT (/opt/hostedtoolcache/go/1.20.14/x64/src/cmp)

Check failure on line 6 in cmd/ogen/main.go

View workflow job for this annotation

GitHub Actions / Analyze (go)

package cmp is not in GOROOT (/opt/hostedtoolcache/go/1.20.14/x64/src/cmp)

Check failure on line 6 in cmd/ogen/main.go

View workflow job for this annotation

GitHub Actions / test (amd64, ubuntu-latest)

package cmp is not in GOROOT (/opt/hostedtoolcache/go/1.20.14/x64/src/cmp)

Check failure on line 6 in cmd/ogen/main.go

View workflow job for this annotation

GitHub Actions / test (amd64, macos-latest)

package cmp is not in GOROOT (/Users/runner/hostedtoolcache/go/1.20.14/x64/src/cmp)

Check failure on line 6 in cmd/ogen/main.go

View workflow job for this annotation

GitHub Actions / test (amd64, windows-latest)

package cmp is not in GOROOT (C:\hostedtoolcache\windows\go\1.20.14\x64\src\cmp)

Check failure on line 6 in cmd/ogen/main.go

View workflow job for this annotation

GitHub Actions / test (386, ubuntu-latest)

package cmp is not in GOROOT (/opt/hostedtoolcache/go/1.20.14/x64/src/cmp)

Check failure on line 6 in cmd/ogen/main.go

View workflow job for this annotation

GitHub Actions / test (amd64, ubuntu-latest, -race)

package cmp is not in GOROOT (/opt/hostedtoolcache/go/1.20.14/x64/src/cmp)
"flag"
"fmt"
"io"
"os"
"path/filepath"
"runtime"
"runtime/pprof"
"slices"

Check failure on line 14 in cmd/ogen/main.go

View workflow job for this annotation

GitHub Actions / test

package slices is not in GOROOT (/opt/hostedtoolcache/go/1.20.14/x64/src/slices)

Check failure on line 14 in cmd/ogen/main.go

View workflow job for this annotation

GitHub Actions / Analyze (go)

package slices is not in GOROOT (/opt/hostedtoolcache/go/1.20.14/x64/src/slices)

Check failure on line 14 in cmd/ogen/main.go

View workflow job for this annotation

GitHub Actions / test (amd64, ubuntu-latest)

package slices is not in GOROOT (/opt/hostedtoolcache/go/1.20.14/x64/src/slices)

Check failure on line 14 in cmd/ogen/main.go

View workflow job for this annotation

GitHub Actions / test (amd64, macos-latest)

package slices is not in GOROOT (/Users/runner/hostedtoolcache/go/1.20.14/x64/src/slices)

Check failure on line 14 in cmd/ogen/main.go

View workflow job for this annotation

GitHub Actions / test (amd64, windows-latest)

package slices is not in GOROOT (C:\hostedtoolcache\windows\go\1.20.14\x64\src\slices)

Check failure on line 14 in cmd/ogen/main.go

View workflow job for this annotation

GitHub Actions / test (386, ubuntu-latest)

package slices is not in GOROOT (/opt/hostedtoolcache/go/1.20.14/x64/src/slices)

Check failure on line 14 in cmd/ogen/main.go

View workflow job for this annotation

GitHub Actions / test (amd64, ubuntu-latest, -race)

package slices is not in GOROOT (/opt/hostedtoolcache/go/1.20.14/x64/src/slices)
"strings"
"time"

"github.com/go-faster/errors"
"github.com/go-faster/yaml"
"go.uber.org/multierr"
"go.uber.org/zap"
"golang.org/x/exp/maps"

"github.com/ogen-go/ogen"
"github.com/ogen-go/ogen/gen"
"github.com/ogen-go/ogen/gen/genfs"
"github.com/ogen-go/ogen/gen/ir"
"github.com/ogen-go/ogen/internal/ogenversion"
"github.com/ogen-go/ogen/internal/ogenzap"
"github.com/ogen-go/ogen/location"
Expand Down Expand Up @@ -112,60 +116,119 @@ func handleGenerateError(w io.Writer, color bool, err error) (r bool) {
return true
}

if notImplErr, ok := errors.Into[*gen.ErrNotImplemented](err); ok {
if msg, feature, ok := handleNotImplementedError(err); ok {
_, _ = fmt.Fprintf(w, `
Feature %[1]q is not implemented yet.
%s
Try to create ogen.yml with:
generator:
ignore_not_implemented: %[1]q
ignore_not_implemented: [%q]
or
generator:
ignore_not_implemented: ["all"]
to skip unsupported operations.
`, notImplErr.Name)
`, msg, feature)
return true
}

return false
}

func handleNotImplementedError(err error) (msg, feature string, _ bool) {
if notImplErr, ok := errors.Into[*gen.ErrNotImplemented](err); ok {
msg := fmt.Sprintf("Feature %q is not implemented yet.\n", notImplErr.Name)
return msg, notImplErr.Name, true
}

if ctErr, ok := errors.Into[*gen.ErrUnsupportedContentTypes](err); ok {
var msg string
if len(ctErr.ContentTypes) == 1 {
msg = fmt.Sprintf(
`Content type %q is unsupported.`,
"Content type %q is unsupported.\n",
ctErr.ContentTypes[0],
)
} else {
msg = fmt.Sprintf(
`Content types [%s] are unsupported.`,
"Content types [%s] are unsupported.\n",
strings.Join(ctErr.ContentTypes, ", "),
)
}
return msg, "unsupported content types", true
}

_, _ = fmt.Fprintf(w, `
%s
Try to create ogen.yml with:
generator:
ignore_not_implemented: [%q]
if inferErr, ok := errors.Into[*gen.ErrFieldsDiscriminatorInference](err); ok {
printPos := func(sb *strings.Builder, typ *ir.Type) {
if typ == nil || typ.Schema == nil {
return
}
ptr := typ.Schema.Pointer

or
if pos, ok := ptr.Position(); ok {
sb.WriteString(" (defined at ")
at := pos.WithFilename(ptr.File().HumanName())
sb.WriteString(at)
sb.WriteString(")")
}
}
var sb strings.Builder

generator:
ignore_not_implemented: ["all"]
fmt.Fprintf(&sb, "ogen failed to infer fields discriminator for type %q", inferErr.Sum.Name)
printPos(&sb, inferErr.Sum)
sb.WriteString(":\n")

to skip unsupported operations.
Also, you can use "content_type_aliases" field to map content types to supported ones.
`,
msg,
"unsupported content types",
const (
propertyLimit = 5 // 10
usedByLimit = 2
)
return true
for _, bv := range inferErr.Types {
fmt.Fprintf(&sb, "\tvariant %q", bv.Type.Name)
printPos(&sb, bv.Type)
sb.WriteString("\n")

var (
printedProperties int
properties = maps.Keys(bv.Fields)
)
// Sort by number of 'also used' types.
//
// It is likely to be properties to be fixed.
slices.SortFunc(properties, func(a, b string) int {
x, y := bv.Fields[a], bv.Fields[b]
return cmp.Compare(len(x), len(y))
})
for _, field := range properties {
if printedProperties >= propertyLimit {
fmt.Fprintf(&sb, "\t\t...%d more properties...\n", len(properties))
break
}
printedProperties++

fmt.Fprintf(&sb, "\t\tproperty %q also used by\n", field)

var (
printedUsedBy int
alsoUsedBy = bv.Fields[field]
)
for _, typ := range alsoUsedBy {
if printedUsedBy >= usedByLimit {
fmt.Fprintf(&sb, "\t\t\t...%d more variants...\n", len(alsoUsedBy))
break
}
printedUsedBy++

fmt.Fprintf(&sb, "\t\t\tvariant %q", typ.Name)
printPos(&sb, typ)
sb.WriteString("\n")
}
}
}
sb.WriteString("\n")
return sb.String(), "discriminator inference", true
}

return false
return msg, feature, false
}

func loadConfig(cfgPath string, log *zap.Logger) (opts gen.Options, _ error) {
Expand Down

0 comments on commit 8acab2e

Please sign in to comment.