Skip to content

Commit

Permalink
multierr: Move dinosql.ParserErr to a new package (sqlc-dev#496)
Browse files Browse the repository at this point in the history
  • Loading branch information
kyleconroy authored May 15, 2020
1 parent 5d28068 commit 4b7238e
Show file tree
Hide file tree
Showing 6 changed files with 101 additions and 79 deletions.
15 changes: 8 additions & 7 deletions internal/cmd/generate.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import (
"github.com/kyleconroy/sqlc/internal/config"
"github.com/kyleconroy/sqlc/internal/dinosql"
"github.com/kyleconroy/sqlc/internal/dinosql/kotlin"
"github.com/kyleconroy/sqlc/internal/multierr"
"github.com/kyleconroy/sqlc/internal/mysql"
)

Expand All @@ -32,7 +33,7 @@ The only supported version is "1".

const errMessageNoPackages = `No packages are configured`

func printFileErr(stderr io.Writer, dir string, fileErr dinosql.FileErr) {
func printFileErr(stderr io.Writer, dir string, fileErr *multierr.FileError) {
filename := strings.TrimPrefix(fileErr.Filename, dir+"/")
fmt.Fprintf(stderr, "%s:%d:%d: %s\n", filename, fileErr.Line, fileErr.Column, fileErr.Err)
}
Expand Down Expand Up @@ -179,8 +180,8 @@ func parse(name, dir string, sql config.SQL, combo config.CombinedSettings, pars
q, err := mysql.GeneratePkg(name, sql.Schema, sql.Queries, combo)
if err != nil {
fmt.Fprintf(stderr, "# package %s\n", name)
if parserErr, ok := err.(*dinosql.ParserErr); ok {
for _, fileErr := range parserErr.Errs {
if parserErr, ok := err.(*multierr.Error); ok {
for _, fileErr := range parserErr.Errs() {
printFileErr(stderr, dir, fileErr)
}
} else {
Expand All @@ -194,8 +195,8 @@ func parse(name, dir string, sql config.SQL, combo config.CombinedSettings, pars
c, err := dinosql.ParseCatalog(sql.Schema)
if err != nil {
fmt.Fprintf(stderr, "# package %s\n", name)
if parserErr, ok := err.(*dinosql.ParserErr); ok {
for _, fileErr := range parserErr.Errs {
if parserErr, ok := err.(*multierr.Error); ok {
for _, fileErr := range parserErr.Errs() {
printFileErr(stderr, dir, fileErr)
}
} else {
Expand All @@ -207,8 +208,8 @@ func parse(name, dir string, sql config.SQL, combo config.CombinedSettings, pars
q, err := dinosql.ParseQueries(c, sql.Queries, parserOpts)
if err != nil {
fmt.Fprintf(stderr, "# package %s\n", name)
if parserErr, ok := err.(*dinosql.ParserErr); ok {
for _, fileErr := range parserErr.Errs {
if parserErr, ok := err.(*multierr.Error); ok {
for _, fileErr := range parserErr.Errs() {
printFileErr(stderr, dir, fileErr)
}
} else {
Expand Down
72 changes: 5 additions & 67 deletions internal/dinosql/parser.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import (

"github.com/kyleconroy/sqlc/internal/catalog"
"github.com/kyleconroy/sqlc/internal/migrations"
"github.com/kyleconroy/sqlc/internal/multierr"
core "github.com/kyleconroy/sqlc/internal/pg"
"github.com/kyleconroy/sqlc/internal/postgres"
"github.com/kyleconroy/sqlc/internal/postgresql/ast"
Expand All @@ -27,46 +28,13 @@ func keepSpew() {
spew.Dump("hello world")
}

type FileErr struct {
Filename string
Line int
Column int
Err error
}

type ParserErr struct {
Errs []FileErr
}

func (e *ParserErr) Add(filename, source string, loc int, err error) {
line := 1
column := 1
if lerr, ok := err.(core.Error); ok {
if lerr.Location != 0 {
loc = lerr.Location
}
}
if source != "" && loc != 0 {
line, column = lineno(source, loc)
}
e.Errs = append(e.Errs, FileErr{filename, line, column, err})
}

func NewParserErr() *ParserErr {
return &ParserErr{}
}

func (e *ParserErr) Error() string {
return fmt.Sprintf("multiple errors: %d errors", len(e.Errs))
}

func ParseCatalog(schemas []string) (core.Catalog, error) {
files, err := sqlpath.Glob(schemas)
if err != nil {
return core.Catalog{}, err
}

merr := NewParserErr()
merr := multierr.New()
c := core.NewCatalog()
for _, filename := range files {
blob, err := ioutil.ReadFile(filename)
Expand Down Expand Up @@ -96,7 +64,7 @@ func ParseCatalog(schemas []string) (core.Catalog, error) {
// catalog so that other queries can not read from it.
delete(c.Schemas, "pg_temp")

if len(merr.Errs) > 0 {
if len(merr.Errs()) > 0 {
return c, merr
}
return c, nil
Expand Down Expand Up @@ -163,7 +131,7 @@ type ParserOpts struct {
}

func ParseQueries(c core.Catalog, queriesPaths []string, opts ParserOpts) (*Result, error) {
merr := NewParserErr()
merr := multierr.New()
var q []*Query

set := map[string]struct{}{}
Expand Down Expand Up @@ -205,7 +173,7 @@ func ParseQueries(c core.Catalog, queriesPaths []string, opts ParserOpts) (*Resu
}
}
}
if len(merr.Errs) > 0 {
if len(merr.Errs()) > 0 {
return nil, merr
}
if len(q) == 0 {
Expand All @@ -227,36 +195,6 @@ func location(node nodes.Node) int {
return 0
}

func lineno(source string, head int) (int, int) {
// Calculate the true line and column number for a query, ignoring spaces
var comment bool
var loc, line, col int
for i, char := range source {
loc += 1
col += 1
// TODO: Check bounds
if char == '-' && source[i+1] == '-' {
comment = true
}
if char == '\n' {
comment = false
line += 1
col = 0
}
if loc <= head {
continue
}
if unicode.IsSpace(char) {
continue
}
if comment {
continue
}
break
}
return line + 1, col
}

func pluckQuery(source string, n nodes.RawStmt) (string, error) {
head := n.StmtLocation
tail := n.StmtLocation + n.StmtLen
Expand Down
3 changes: 2 additions & 1 deletion internal/dinosql/parser_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (
"path"
"testing"

"github.com/kyleconroy/sqlc/internal/source"
"github.com/kyleconroy/sqlc/internal/sql/sqlpath"

"github.com/google/go-cmp/cmp"
Expand Down Expand Up @@ -81,7 +82,7 @@ func TestLineColumn(t *testing.T) {
{tree.Statements[5], 10, 12},
} {
raw := test.node.(nodes.RawStmt)
line, column := lineno(lineColumn, raw.StmtLocation)
line, column := source.LineNumber(lineColumn, raw.StmtLocation)
if line != test.line {
t.Errorf("expected stmt %d to be on line %d, not %d", i, test.line, line)
}
Expand Down
49 changes: 49 additions & 0 deletions internal/multierr/error.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
package multierr

import (
"fmt"

"github.com/kyleconroy/sqlc/internal/pg"
"github.com/kyleconroy/sqlc/internal/source"
)

type FileError struct {
Filename string
Line int
Column int
Err error
}

func (e *FileError) Unwrap() error {
return e.Err
}

type Error struct {
errs []*FileError
}

func (e *Error) Add(filename, in string, loc int, err error) {
line := 1
column := 1
if lerr, ok := err.(pg.Error); ok {
if lerr.Location != 0 {
loc = lerr.Location
}
}
if in != "" && loc != 0 {
line, column = source.LineNumber(in, loc)
}
e.errs = append(e.errs, &FileError{filename, line, column, err})
}

func (e *Error) Errs() []*FileError {
return e.errs
}

func (e *Error) Error() string {
return fmt.Sprintf("multiple errors: %d errors", len(e.errs))
}

func New() *Error {
return &Error{}
}
8 changes: 4 additions & 4 deletions internal/mysql/parse.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import (
"github.com/kyleconroy/sqlc/internal/config"
"github.com/kyleconroy/sqlc/internal/dinosql"
"github.com/kyleconroy/sqlc/internal/migrations"
"github.com/kyleconroy/sqlc/internal/multierr"
"github.com/kyleconroy/sqlc/internal/sql/sqlpath"
)

Expand All @@ -38,8 +39,7 @@ func parsePath(sqlPath []string, generator PackageGenerator) (*Result, error) {
return nil, err
}

parseErrors := dinosql.ParserErr{}

parseErrors := multierr.New()
parsedQueries := []*Query{}
for _, filename := range files {
blob, err := ioutil.ReadFile(filename)
Expand Down Expand Up @@ -86,8 +86,8 @@ func parsePath(sqlPath []string, generator PackageGenerator) (*Result, error) {
}
}

if len(parseErrors.Errs) > 0 {
return nil, &parseErrors
if len(parseErrors.Errs()) > 0 {
return nil, parseErrors
}

return &Result{
Expand Down
33 changes: 33 additions & 0 deletions internal/source/code.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package source

import "unicode"

func LineNumber(source string, head int) (int, int) {
// Calculate the true line and column number for a query, ignoring spaces
var comment bool
var loc, line, col int
for i, char := range source {
loc += 1
col += 1
// TODO: Check bounds
if char == '-' && source[i+1] == '-' {
comment = true
}
if char == '\n' {
comment = false
line += 1
col = 0
}
if loc <= head {
continue
}
if unicode.IsSpace(char) {
continue
}
if comment {
continue
}
break
}
return line + 1, col
}

0 comments on commit 4b7238e

Please sign in to comment.