Skip to content

Commit

Permalink
Add source-level stack traces for build time errors
Browse files Browse the repository at this point in the history
  • Loading branch information
hinshun committed Jun 24, 2020
1 parent 62e9c1f commit f108007
Show file tree
Hide file tree
Showing 23 changed files with 327 additions and 391 deletions.
6 changes: 3 additions & 3 deletions checker/checker_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -395,7 +395,7 @@ func TestChecker_Check(t *testing.T) {
t.Run(tc.name, func(t *testing.T) {
in := strings.NewReader(cleanup(tc.input))

mod, err := parser.Parse(in)
mod, _, err := parser.Parse(in)
require.NoError(t, err)

err = Check(mod)
Expand Down Expand Up @@ -493,14 +493,14 @@ func TestChecker_CheckSelectors(t *testing.T) {
option::image resolveImage() { resolve; }
`

importedModule, err := parser.Parse(strings.NewReader(importedModuleDefinition))
importedModule, _, err := parser.Parse(strings.NewReader(importedModuleDefinition))
require.NoError(t, err)
err = Check(importedModule)
require.NoError(t, err)

in := strings.NewReader(cleanup(tc.input))

module, err := parser.Parse(in)
module, _, err := parser.Parse(in)
require.NoError(t, err)

err = Check(module)
Expand Down
45 changes: 22 additions & 23 deletions codegen/chain.go
Original file line number Diff line number Diff line change
Expand Up @@ -84,15 +84,14 @@ func (cg *CodeGen) EmitFilesystemChainStmt(ctx context.Context, scope *parser.Sc
if obj == nil {
return fc, errors.WithStack(ErrCodeGen{expr.IdentNode(), ErrUndefinedReference})
}
cg.stacktrace = append(cg.stacktrace, Frame{Node: expr})

var v interface{}
var err error
switch n := obj.Node.(type) {
case *parser.FuncDecl:
v, err = cg.EmitFuncDecl(ctx, scope, n, args, ac, chainStart)
v, err = cg.EmitFuncDecl(ctx, scope, expr, n, args, ac, chainStart)
case *parser.AliasDecl:
v, err = cg.EmitAliasDecl(ctx, scope, n, args, chainStart)
v, err = cg.EmitAliasDecl(ctx, scope, expr, n, args, chainStart)
case *parser.ImportDecl:
importScope := obj.Data.(*parser.Scope)
importObj := importScope.Lookup(expr.Selector.Select.Name)
Expand All @@ -102,9 +101,9 @@ func (cg *CodeGen) EmitFilesystemChainStmt(ctx context.Context, scope *parser.Sc

switch m := importObj.Node.(type) {
case *parser.FuncDecl:
v, err = cg.EmitFuncDecl(ctx, scope, m, args, ac, chainStart)
v, err = cg.EmitFuncDecl(ctx, scope, expr, m, args, ac, chainStart)
case *parser.AliasDecl:
v, err = cg.EmitAliasDecl(ctx, scope, m, args, chainStart)
v, err = cg.EmitAliasDecl(ctx, scope, expr, m, args, chainStart)
default:
return fc, errors.WithStack(ErrCodeGen{m, errors.Errorf("unknown obj type")})
}
Expand Down Expand Up @@ -161,24 +160,24 @@ func (cg *CodeGen) EmitShellCommand(ctx context.Context, scope *parser.Scope, ar
}

func (cg *CodeGen) SourceMap(node parser.Node) []llb.ConstraintsOpt {
if cg.ibs == nil {
if cg.fbs == nil {
return nil
}

stacktrace := make([]Frame, len(cg.stacktrace))
stacktrace := make([]Frame, len(cg.stacktrace)+1)
copy(stacktrace, cg.stacktrace)
stacktrace = append(stacktrace, Frame{Node: node})
stacktrace[len(stacktrace)-1] = Frame{Node: node}

var opts []llb.ConstraintsOpt

for i := len(stacktrace) - 1; i >= 0; i-- {
node := stacktrace[i].Node
ibs, ok := cg.ibs[node.Position().Filename]
fb, ok := cg.fbs[node.Position().Filename]
if !ok {
continue
}

opts = append(opts, ibs.SourceMap().Location([]*pb.Range{
opts = append(opts, fb.SourceMap().Location([]*pb.Range{
{
Start: pb.Position{
Line: int32(node.Position().Line),
Expand Down Expand Up @@ -273,7 +272,7 @@ func (cg *CodeGen) EmitFilesystemBuiltinChainStmt(ctx context.Context, scope *pa
return fc, err
}

path, err = ResolvePathForNode(scope.Node, path)
path, err = parser.ResolvePath(scope.Node, path)
if err != nil {
return fc, err
}
Expand Down Expand Up @@ -720,7 +719,7 @@ func (cg *CodeGen) EmitFilesystemBuiltinChainStmt(ctx context.Context, scope *pa
return fc, err
}

localPath, err = ResolvePathForNode(scope.Node, localPath)
localPath, err = parser.ResolvePath(scope.Node, localPath)
if err != nil {
return fc, err
}
Expand All @@ -739,7 +738,7 @@ func (cg *CodeGen) EmitFilesystemBuiltinChainStmt(ctx context.Context, scope *pa
return fc, err
}

localPath, err = ResolvePathForNode(scope.Node, localPath)
localPath, err = parser.ResolvePath(scope.Node, localPath)
if err != nil {
return fc, err
}
Expand All @@ -758,7 +757,7 @@ func (cg *CodeGen) EmitFilesystemBuiltinChainStmt(ctx context.Context, scope *pa
return fc, err
}

localPath, err = ResolvePathForNode(scope.Node, localPath)
localPath, err = parser.ResolvePath(scope.Node, localPath)
if err != nil {
return fc, err
}
Expand All @@ -777,7 +776,7 @@ func (cg *CodeGen) EmitFilesystemBuiltinChainStmt(ctx context.Context, scope *pa
return fc, err
}

localPath, err = ResolvePathForNode(scope.Node, localPath)
localPath, err = parser.ResolvePath(scope.Node, localPath)
if err != nil {
return fc, err
}
Expand Down Expand Up @@ -1088,9 +1087,9 @@ func (cg *CodeGen) EmitStringChainStmt(ctx context.Context, scope *parser.Scope,
var err error
switch n := obj.Node.(type) {
case *parser.FuncDecl:
v, err = cg.EmitFuncDecl(ctx, scope, n, args, noopAliasCallback, chainStart)
v, err = cg.EmitFuncDecl(ctx, scope, expr, n, args, noopAliasCallback, chainStart)
case *parser.AliasDecl:
v, err = cg.EmitAliasDecl(ctx, scope, n, args, chainStart)
v, err = cg.EmitAliasDecl(ctx, scope, expr, n, args, chainStart)
case *parser.ImportDecl:
importScope := obj.Data.(*parser.Scope)
importObj := importScope.Lookup(expr.Selector.Select.Name)
Expand All @@ -1100,9 +1099,9 @@ func (cg *CodeGen) EmitStringChainStmt(ctx context.Context, scope *parser.Scope,

switch m := importObj.Node.(type) {
case *parser.FuncDecl:
v, err = cg.EmitFuncDecl(ctx, scope, m, args, noopAliasCallback, chainStart)
v, err = cg.EmitFuncDecl(ctx, scope, expr, m, args, noopAliasCallback, chainStart)
case *parser.AliasDecl:
v, err = cg.EmitAliasDecl(ctx, scope, m, args, chainStart)
v, err = cg.EmitAliasDecl(ctx, scope, expr, m, args, chainStart)
default:
return nil, errors.WithStack(ErrCodeGen{n, errors.Errorf("unknown obj type")})
}
Expand Down Expand Up @@ -1155,9 +1154,9 @@ func (cg *CodeGen) EmitGroupChainStmt(ctx context.Context, scope *parser.Scope,
var v interface{}
switch n := obj.Node.(type) {
case *parser.FuncDecl:
v, err = cg.EmitFuncDecl(ctx, scope, n, args, ac, chainStart)
v, err = cg.EmitFuncDecl(ctx, scope, expr, n, args, ac, chainStart)
case *parser.AliasDecl:
v, err = cg.EmitAliasDecl(ctx, scope, n, args, chainStart)
v, err = cg.EmitAliasDecl(ctx, scope, expr, n, args, chainStart)
case *parser.ImportDecl:
importScope := obj.Data.(*parser.Scope)
importObj := importScope.Lookup(expr.Selector.Select.Name)
Expand All @@ -1167,9 +1166,9 @@ func (cg *CodeGen) EmitGroupChainStmt(ctx context.Context, scope *parser.Scope,

switch m := importObj.Node.(type) {
case *parser.FuncDecl:
v, err = cg.EmitFuncDecl(ctx, scope, m, args, ac, chainStart)
v, err = cg.EmitFuncDecl(ctx, scope, expr, m, args, ac, chainStart)
case *parser.AliasDecl:
v, err = cg.EmitAliasDecl(ctx, scope, m, args, chainStart)
v, err = cg.EmitAliasDecl(ctx, scope, expr, m, args, chainStart)
default:
return gc, errors.WithStack(ErrCodeGen{m, errors.Errorf("unknown obj type")})
}
Expand Down
36 changes: 10 additions & 26 deletions codegen/codegen.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@ import (

"github.com/docker/buildx/util/progress"
"github.com/docker/cli/cli/command"
homedir "github.com/mitchellh/go-homedir"
"github.com/moby/buildkit/client"
"github.com/moby/buildkit/client/llb"
"github.com/moby/buildkit/client/llb/imagemetaresolver"
Expand All @@ -32,7 +31,6 @@ import (
"github.com/openllb/hlb/checker"
"github.com/openllb/hlb/local"
"github.com/openllb/hlb/parser"
"github.com/openllb/hlb/report"
"github.com/openllb/hlb/sockprovider"
"github.com/openllb/hlb/solver"
"github.com/pkg/errors"
Expand All @@ -47,7 +45,7 @@ type CodeGen struct {
Debug Debugger
cln *client.Client
sessionID string
ibs map[string]*report.IndexedBuffer
fbs map[string]*parser.FileBuffer
stacktrace []Frame

requests []solver.Request
Expand Down Expand Up @@ -85,9 +83,9 @@ func WithClient(cln *client.Client) CodeGenOption {
}
}

func WithIndexedBuffers(ibs map[string]*report.IndexedBuffer) CodeGenOption {
func WithFileBuffers(fbs map[string]*parser.FileBuffer) CodeGenOption {
return func(i *CodeGen) error {
i.ibs = ibs
i.fbs = fbs
return nil
}
}
Expand Down Expand Up @@ -145,7 +143,7 @@ func (cg *CodeGen) Generate(ctx context.Context, mod *parser.Module, targets []T
return nil, checker.ErrInvalidTarget{Node: n, Target: target.Name}
}

v, err = cg.EmitFuncDecl(ctx, mod.Scope, n, nil, noopAliasCallback, nil)
v, err = cg.EmitFuncDecl(ctx, mod.Scope, n.Name, n, nil, noopAliasCallback, nil)
if err != nil {
return nil, err
}
Expand All @@ -155,7 +153,7 @@ func (cg *CodeGen) Generate(ctx context.Context, mod *parser.Module, targets []T
return nil, checker.ErrInvalidTarget{Node: n, Target: target.Name}
}

v, err = cg.EmitAliasDecl(ctx, mod.Scope, n, nil, nil)
v, err = cg.EmitAliasDecl(ctx, mod.Scope, n.Ident, n, nil, nil)
if err != nil {
return nil, err
}
Expand Down Expand Up @@ -210,7 +208,6 @@ func (cg *CodeGen) Generate(ctx context.Context, mod *parser.Module, targets []T
// Reset all the options and session attachables for the next target.
// If we ever need to parallelize compilation we can revisit this.
func (cg *CodeGen) reset() {
cg.stacktrace = []Frame{}
cg.requests = []solver.Request{}
cg.SolveOpts = []solver.SolveOption{}
cg.syncedDirByID = map[string]filesync.SyncedDir{}
Expand Down Expand Up @@ -483,7 +480,7 @@ func (cg *CodeGen) EmitOptionLookup(ctx context.Context, scope *parser.Scope, ex
case parser.DeclKind:
switch n := obj.Node.(type) {
case *parser.FuncDecl:
return cg.EmitOptionFuncDecl(ctx, scope, n, args)
return cg.EmitOptionFuncDecl(ctx, scope, expr, n, args)
case *parser.ImportDecl:
importScope := obj.Data.(*parser.Scope)
importObj := importScope.Lookup(expr.Selector.Select.Name)
Expand All @@ -493,7 +490,7 @@ func (cg *CodeGen) EmitOptionLookup(ctx context.Context, scope *parser.Scope, ex

switch m := importObj.Node.(type) {
case *parser.FuncDecl:
return cg.EmitOptionFuncDecl(ctx, scope, m, args)
return cg.EmitOptionFuncDecl(ctx, scope, expr, m, args)
default:
return opts, errors.WithStack(ErrCodeGen{expr, errors.Errorf("unknown option decl kind")})
}
Expand Down Expand Up @@ -1133,7 +1130,7 @@ func (cg *CodeGen) EmitExecOptions(ctx context.Context, scope *parser.Scope, op
)
switch srcUri.Scheme {
case "unix":
path, err = ResolvePathForNode(scope.Node, srcUri.Path)
path, err = parser.ResolvePath(scope.Node, srcUri.Path)
if err != nil {
return opts, err
}
Expand Down Expand Up @@ -1199,7 +1196,7 @@ func (cg *CodeGen) EmitExecOptions(ctx context.Context, scope *parser.Scope, op
return opts, err
}

localPathArg, err = ResolvePathForNode(scope.Node, localPathArg)
localPathArg, err = parser.ResolvePath(scope.Node, localPathArg)
if err != nil {
return opts, err
}
Expand Down Expand Up @@ -1426,7 +1423,7 @@ func (cg *CodeGen) EmitSSHOptions(ctx context.Context, scope *parser.Scope, op s
return opts, err
}

localPath, err = ResolvePathForNode(scope.Node, localPath)
localPath, err = parser.ResolvePath(scope.Node, localPath)
if err != nil {
return opts, err
}
Expand Down Expand Up @@ -1676,16 +1673,3 @@ func outputFromWriter(w io.WriteCloser) func(map[string]string) (io.WriteCloser,
return w, nil
}
}

func ResolvePathForNode(node parser.Node, path string) (string, error) {
path, err := homedir.Expand(path)
if err != nil {
return path, err
}

if filepath.IsAbs(path) {
return path, nil
}

return filepath.Join(filepath.Dir(node.Position().Filename), path), nil
}
2 changes: 1 addition & 1 deletion codegen/codegen_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -793,7 +793,7 @@ func TestCodeGen(t *testing.T) {
cg, err := New()
require.NoError(t, err)

mod, err := parser.Parse(strings.NewReader(cleanup(tc.input)))
mod, _, err := parser.Parse(strings.NewReader(cleanup(tc.input)))
require.NoError(t, err)

err = checker.Check(mod)
Expand Down
16 changes: 8 additions & 8 deletions codegen/debug.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ type snapshot struct {
value interface{}
}

func NewDebugger(c *client.Client, w io.Writer, r *bufio.Reader, ibs map[string]*report.IndexedBuffer) Debugger {
func NewDebugger(c *client.Client, w io.Writer, r *bufio.Reader, fbs map[string]*parser.FileBuffer) Debugger {
color := aurora.NewAurora(true)

var (
Expand Down Expand Up @@ -100,7 +100,7 @@ func NewDebugger(c *client.Client, w io.Writer, r *bufio.Reader, ibs map[string]
}

if showList && !cont {
err := printList(color, ibs, w, s.node)
err := printList(color, fbs, w, s.node)
if err != nil {
return err
}
Expand Down Expand Up @@ -277,7 +277,7 @@ func NewDebugger(c *client.Client, w io.Writer, r *bufio.Reader, ibs map[string]
fmt.Fprintf(w, "security - print security mode\n")
case "list", "l":
if showList {
err = printList(color, ibs, w, s.node)
err = printList(color, fbs, w, s.node)
if err != nil {
return err
}
Expand Down Expand Up @@ -386,9 +386,9 @@ func NewDebugger(c *client.Client, w io.Writer, r *bufio.Reader, ibs map[string]
}
}

func printList(color aurora.Aurora, ibs map[string]*report.IndexedBuffer, w io.Writer, node parser.Node) error {
func printList(color aurora.Aurora, fbs map[string]*parser.FileBuffer, w io.Writer, node parser.Node) error {
pos := node.Position()
ib := ibs[pos.Filename]
fb := fbs[pos.Filename]

var lines []string

Expand All @@ -398,8 +398,8 @@ func printList(color aurora.Aurora, ibs map[string]*report.IndexedBuffer, w io.W
}

end := start + 10
if end > ib.Len() {
end = ib.Len()
if end > fb.Len() {
end = fb.Len()
}

length := 1
Expand All @@ -419,7 +419,7 @@ func printList(color aurora.Aurora, ibs map[string]*report.IndexedBuffer, w io.W
lines = append(lines, header)

for i := start; i < end; i++ {
line, err := ib.Line(i)
line, err := fb.Line(i)
if err != nil {
return err
}
Expand Down
Loading

0 comments on commit f108007

Please sign in to comment.