Improve imports (#66)

* Improve imports

* Nonexistent file is now a runtime error (used to be ignored)
* Permission denied is a runtime error (used to be an internal error)
* Basic tests added for imports
* Renamed tests from .input to .jsonnet
	* It's standard
	* It's compatible with C++ test suite
	* Editors enable syntax highlighting based on extension
	* Importing .input looks weird
This commit is contained in:
Stanisław Barzowski 2017-09-22 18:03:00 -04:00 committed by Dave Cunningham
parent 8638a21287
commit fe62ec46a8
303 changed files with 36 additions and 14 deletions

View File

@ -68,19 +68,18 @@ func (cache *ImportCache) importData(key importCacheKey) *ImportCacheValue {
return &val return &val
} }
func (cache *ImportCache) ImportString(codeDir, importedPath string) (*valueString, error) { func (cache *ImportCache) ImportString(codeDir, importedPath string, e *evaluator) (*valueString, error) {
data := cache.importData(importCacheKey{codeDir, importedPath}) data := cache.importData(importCacheKey{codeDir, importedPath})
if data.data.err != nil { if data.data.err != nil {
return nil, data.data.err return nil, e.Error(data.data.err.Error())
} }
// TODO(sbarzowski) wrap error in runtime error
return makeValueString(data.data.content), nil return makeValueString(data.data.content), nil
} }
func (cache *ImportCache) ImportCode(codeDir, importedPath string, e *evaluator) (value, error) { func (cache *ImportCache) ImportCode(codeDir, importedPath string, e *evaluator) (value, error) {
cached := cache.importData(importCacheKey{codeDir, importedPath}) cached := cache.importData(importCacheKey{codeDir, importedPath})
if cached.data.err != nil { if cached.data.err != nil {
return nil, cached.data.err return nil, e.Error(cached.data.err.Error())
} }
if cached.asCode == nil { if cached.asCode == nil {
node, err := snippetToAST(cached.data.foundHere, cached.data.content) node, err := snippetToAST(cached.data.foundHere, cached.data.content)
@ -141,6 +140,11 @@ func (importer *FileImporter) Import(dir, importedPath string) *ImportedData {
} }
} }
if !found {
return &ImportedData{
err: fmt.Errorf("Couldn't open import %#v: No match locally or in the Jsonnet library paths.", importedPath),
}
}
return &ImportedData{content: string(content), foundHere: foundHere} return &ImportedData{content: string(content), foundHere: foundHere}
} }

View File

@ -370,14 +370,12 @@ func (i *interpreter) evaluate(a ast.Node, context *TraceContext) (value, error)
return nil, e.Error(fmt.Sprintf("Value non indexable: %v", reflect.TypeOf(targetValue))) return nil, e.Error(fmt.Sprintf("Value non indexable: %v", reflect.TypeOf(targetValue)))
case *ast.Import: case *ast.Import:
// TODO(sbarzowski) put this information in AST instead of getting it out of tracing data... codeDir := path.Dir(ast.Loc().FileName)
codeDir := path.Dir(e.trace.loc.FileName)
return i.importCache.ImportCode(codeDir, ast.File, e) return i.importCache.ImportCode(codeDir, ast.File, e)
case *ast.ImportStr: case *ast.ImportStr:
// TODO(sbarzowski) put this information in AST instead of getting it out of tracing data... codeDir := path.Dir(ast.Loc().FileName)
codeDir := path.Dir(e.trace.loc.FileName) return i.importCache.ImportString(codeDir, ast.File, e)
return i.importCache.ImportString(codeDir, ast.File)
case *ast.LiteralBoolean: case *ast.LiteralBoolean:
return makeValueBoolean(ast.Value), nil return makeValueBoolean(ast.Value), nil

View File

@ -62,15 +62,15 @@ func removeExcessiveWhitespace(s string) string {
func TestMain(t *testing.T) { func TestMain(t *testing.T) {
flag.Parse() flag.Parse()
var mainTests []mainTest var mainTests []mainTest
match, err := filepath.Glob("testdata/*.input") match, err := filepath.Glob("testdata/*.jsonnet")
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
for _, input := range match { for _, input := range match {
golden := input golden := input
name := input name := input
if strings.HasSuffix(input, ".input") { if strings.HasSuffix(input, ".jsonnet") {
name = input[:len(input)-len(".input")] name = input[:len(input)-len(".jsonnet")]
golden = name + ".golden" golden = name + ".golden"
} }
mainTests = append(mainTests, mainTest{name: name, input: input, golden: golden}) mainTests = append(mainTests, mainTest{name: name, input: input, golden: golden})
@ -106,12 +106,12 @@ func TestMain(t *testing.T) {
// TODO(sbarzowski) better reporting of differences in whitespace // TODO(sbarzowski) better reporting of differences in whitespace
// missing newline issues can be very subtle now // missing newline issues can be very subtle now
t.Fail() t.Fail()
t.Errorf("Mismatch when running %s.input. Golden: %s\n", test.name, test.golden) t.Errorf("Mismatch when running %s.jsonnet. Golden: %s\n", test.name, test.golden)
data := diff(output, string(golden)) data := diff(output, string(golden))
if err != nil { if err != nil {
t.Errorf("computing diff: %s", err) t.Errorf("computing diff: %s", err)
} }
t.Errorf("diff %s jsonnet %s.input\n", test.golden, test.name) t.Errorf("diff %s jsonnet %s.jsonnet\n", test.golden, test.name)
t.Errorf(string(data)) t.Errorf(string(data))
} }

1
testdata/false.golden vendored Normal file
View File

@ -0,0 +1 @@
false

1
testdata/false.jsonnet vendored Normal file
View File

@ -0,0 +1 @@
false

Some files were not shown because too many files have changed in this diff Show More