Repository: openllb/hlb
Pull request #188 (2020-09-23 21:01:33)

Fix relative path resolution for imports
- Relpaths for imports importing modules from its directory does not properly construct path from hlb process's cwd

## build.hlb
```hlb
import module from "./root/module.hlb"

fs default() {
	module.foo
}
```

## ./root/module.hlb
```hlb
import transient from "./transient.hlb"

export foo
fs foo() {
	transient.bar
}
```

## ./root/transient.hlb
```hlb
export bar

fs bar() {
	image "alpine"
}
```


Patch:
diff --git a/cmd/hlb/command/lint.go b/cmd/hlb/command/lint.go
index bbda889..56c634f 100644
--- a/cmd/hlb/command/lint.go
+++ b/cmd/hlb/command/lint.go
@@ -4,6 +4,7 @@ import (
 	"io/ioutil"
 	"os"
 
+	"github.com/moby/buildkit/util/appcontext"
 	"github.com/openllb/hlb"
 	"github.com/openllb/hlb/checker"
 	"github.com/openllb/hlb/linter"
@@ -37,7 +38,8 @@ var lintCommand = &cli.Command{
 			return err
 		}
 
-		err = linter.Lint(mod, linter.WithRecursive())
+		ctx := appcontext.Context()
+		err = linter.Lint(ctx, mod, linter.WithRecursive())
 		if err != nil {
 			if lintErr, ok := err.(linter.ErrLint); ok {
 				if !c.Bool("fix") {
diff --git a/hlb.go b/hlb.go
index f8fe619..622894e 100644
--- a/hlb.go
+++ b/hlb.go
@@ -42,7 +42,7 @@ func Compile(ctx context.Context, cln *client.Client, targets []codegen.Target,
 		return nil, err
 	}
 
-	err = linter.Lint(mod, linter.WithRecursive())
+	err = linter.Lint(ctx, mod, linter.WithRecursive())
 	if err != nil {
 		fmt.Println(err)
 	}
diff --git a/langserver/server.go b/langserver/server.go
index 785983a..13c7585 100644
--- a/langserver/server.go
+++ b/langserver/server.go
@@ -134,7 +134,7 @@ func (ls *LangServer) textDocumentDidOpenHandler(ctx context.Context, params lsp
 	uri := params.TextDocument.URI
 	log.Printf("did open %q", uri)
 
-	td := NewTextDocument(uri, params.TextDocument.Text)
+	td := NewTextDocument(ctx, uri, params.TextDocument.Text)
 
 	ls.tmu.Lock()
 	ls.tds[uri] = td
@@ -408,7 +408,7 @@ func (ls *LangServer) textDocumentDidChangeHandler(ctx context.Context, params l
 		}
 
 		for _, change := range params.ContentChanges {
-			td := NewTextDocument(uri, change.Text)
+			td := NewTextDocument(ctx, uri, change.Text)
 			if _, ok := ls.capset[SemanticHighlightingCapability]; ok {
 				go func() {
 					err := ls.publishSemanticHighlighting(ctx, td)
@@ -585,7 +585,7 @@ func (ls *LangServer) textDocumentDefinitionHandler(ctx context.Context, params
 					return
 				}
 
-				importTD = NewTextDocument(importUri, string(data))
+				importTD = NewTextDocument(ctx, importUri, string(data))
 				ls.tds[importUri] = importTD
 			}
 			ls.tmu.Unlock()
@@ -746,7 +746,7 @@ type TextDocument struct {
 	Err        error
 }
 
-func NewTextDocument(uri lsp.DocumentURI, text string) TextDocument {
+func NewTextDocument(ctx context.Context, uri lsp.DocumentURI, text string) TextDocument {
 	td := TextDocument{
 		Identifier: lsp.VersionedTextDocumentIdentifier{
 			TextDocumentIdentifier: lsp.TextDocumentIdentifier{
@@ -769,7 +769,7 @@ func NewTextDocument(uri lsp.DocumentURI, text string) TextDocument {
 		return td
 	}
 
-	linter.Lint(td.Module)
+	linter.Lint(ctx, td.Module)
 
 	td.Err = checker.Check(td.Module)
 	if td.Err != nil {
diff --git a/linter/linter.go b/linter/linter.go
index 0d3818b..c744899 100644
--- a/linter/linter.go
+++ b/linter/linter.go
@@ -22,12 +22,12 @@ func WithRecursive() LintOption {
 	}
 }
 
-func Lint(mod *parser.Module, opts ...LintOption) error {
+func Lint(ctx context.Context, mod *parser.Module, opts ...LintOption) error {
 	linter := Linter{}
 	for _, opt := range opts {
 		opt(&linter)
 	}
-	err := linter.Lint(mod)
+	err := linter.Lint(ctx, mod)
 	if err != nil {
 		return err
 	}
@@ -37,7 +37,7 @@ func Lint(mod *parser.Module, opts ...LintOption) error {
 	return nil
 }
 
-func (l *Linter) Lint(mod *parser.Module) error {
+func (l *Linter) Lint(ctx context.Context, mod *parser.Module) error {
 	var (
 		modErr error
 		errs   []error
@@ -59,7 +59,7 @@ func (l *Linter) Lint(mod *parser.Module) error {
 				return
 			}
 
-			err := l.LintRecursive(mod, id.Expr)
+			err := l.LintRecursive(ctx, mod, id.Expr)
 			if err != nil {
 				if lintErr, ok := err.(ErrLint); ok {
 					l.errs = append(l.errs, lintErr.Errs...)
@@ -78,14 +78,16 @@ func (l *Linter) Lint(mod *parser.Module) error {
 	return nil
 }
 
-func (l *Linter) LintRecursive(mod *parser.Module, expr *parser.Expr) error {
+func (l *Linter) LintRecursive(ctx context.Context, mod *parser.Module, expr *parser.Expr) error {
+	ctx = codegen.WithProgramCounter(ctx, mod)
+
 	cg, err := codegen.New(nil)
 	if err != nil {
 		return err
 	}
 
 	ret := codegen.NewRegister()
-	err = cg.EmitExpr(context.Background(), mod.Scope, expr, nil, nil, nil, ret)
+	err = cg.EmitExpr(ctx, mod.Scope, expr, nil, nil, nil, ret)
 	if err != nil {
 		return err
 	}
@@ -94,12 +96,17 @@ func (l *Linter) LintRecursive(mod *parser.Module, expr *parser.Expr) error {
 		return nil
 	}
 
-	path, err := ret.String()
+	relPath, err := ret.String()
+	if err != nil {
+		return err
+	}
+
+	filename, err := parser.ResolvePath(codegen.ModuleDir(ctx), relPath)
 	if err != nil {
 		return err
 	}
 
-	f, err := os.Open(path)
+	f, err := os.Open(filename)
 	if err != nil {
 		return err
 	}
@@ -115,5 +122,5 @@ func (l *Linter) LintRecursive(mod *parser.Module, expr *parser.Expr) error {
 		return err
 	}
 
-	return l.Lint(imod)
+	return l.Lint(ctx, imod)
 }
diff --git a/module/resolve.go b/module/resolve.go
index 43bf72f..bd09d5b 100644
--- a/module/resolve.go
+++ b/module/resolve.go
@@ -382,7 +382,10 @@ func resolveGraph(ctx context.Context, info *resolveGraphInfo, res Resolved, mod
 	parser.Match(mod, parser.MatchOpts{},
 		func(id *parser.ImportDecl) {
 			g.Go(func() error {
-				ret := codegen.NewRegister()
+				var (
+					ctx = codegen.WithProgramCounter(ctx, id.Expr)
+					ret = codegen.NewRegister()
+				)
 				err := cg.EmitExpr(ctx, mod.Scope, id.Expr, nil, nil, nil, ret)
 				if err != nil {
 					return err
@@ -407,7 +410,12 @@ func resolveGraph(ctx context.Context, info *resolveGraphInfo, res Resolved, mod
 					defer ires.Close()
 				case parser.String:
 					ires = res
-					filename, err = ret.String()
+					relPath, err := ret.String()
+					if err != nil {
+						return err
+					}
+
+					filename, err = parser.ResolvePath(codegen.ModuleDir(ctx), relPath)
 					if err != nil {
 						return err
 					}
@@ -433,7 +441,7 @@ func resolveGraph(ctx context.Context, info *resolveGraphInfo, res Resolved, mod
 				}
 
 				// Drop errors from linting.
-				linter.Lint(imod)
+				linter.Lint(ctx, imod)
 
 				err = checker.Check(imod)
 				if err != nil {


Test patch:
diff --git a/codegen/codegen_test.go b/codegen/codegen_test.go
index 34755c4..5032738 100644
--- a/codegen/codegen_test.go
+++ b/codegen/codegen_test.go
@@ -797,6 +797,7 @@ func TestCodeGen(t *testing.T) {
 	}} {
 		tc := tc
 		t.Run(tc.name, func(t *testing.T) {
+			ctx := codegen.WithSessionID(context.Background(), identity.NewID())
 			cg, err := codegen.New(nil)
 			require.NoError(t, err, tc.name)
 
@@ -806,7 +807,7 @@ func TestCodeGen(t *testing.T) {
 			err = checker.SemanticPass(mod)
 			require.NoError(t, err, tc.name)
 
-			linter.Lint(mod)
+			linter.Lint(ctx, mod)
 
 			err = checker.Check(mod)
 			require.NoError(t, err, tc.name)
@@ -823,7 +824,7 @@ func TestCodeGen(t *testing.T) {
 				err = checker.SemanticPass(imod)
 				require.NoError(t, err, tc.name)
 
-				linter.Lint(imod)
+				linter.Lint(ctx, imod)
 
 				err = checker.Check(imod)
 				require.NoError(t, err, tc.name)
@@ -839,7 +840,6 @@ func TestCodeGen(t *testing.T) {
 				targets = append(targets, codegen.Target{Name: target})
 			}
 
-			ctx := codegen.WithSessionID(context.Background(), identity.NewID())
 			request, err := cg.Generate(ctx, mod, targets)
 			require.NoError(t, err, tc.name)