From 1d393de437b2933c06f3b6449fc0597ac0d7bc4f Mon Sep 17 00:00:00 2001
From: Tsuyoshi Hombashi <tsuyoshi.hombashi@gmail.com>
Date: Sun, 11 Jul 2021 15:18:18 +0900
Subject: [PATCH 1/2] Fix jsonnet-lint erorr when linting importing files and
 imported files at the same time: #544

---
 imports.go            |  9 +++++++++
 jsonnet_test.go       |  8 ++++----
 linter/linter.go      |  2 +-
 linter/linter_test.go | 17 +++++++++++++++++
 main_test.go          |  2 +-
 vm.go                 |  4 ++--
 6 files changed, 34 insertions(+), 8 deletions(-)

diff --git a/imports.go b/imports.go
index cf0e21edb..6b0f4ea0e 100644
--- a/imports.go
+++ b/imports.go
@@ -117,6 +117,15 @@ func (cache *importCache) importData(importedFrom, importedPath string) (content
 	return
 }
 
+func (cache *importCache) snippetToAST(diagnosticFilename ast.DiagnosticFileName, importedFilename, snippet string) (ast.Node, error) {
+	if cachedNode, isCached := cache.astCache[importedFilename]; isCached {
+		return cachedNode, nil
+	}
+	node, err := program.SnippetToAST(diagnosticFilename, importedFilename, snippet)
+	cache.astCache[importedFilename] = node
+	return node, err
+}
+
 func (cache *importCache) importAST(importedFrom, importedPath string) (ast.Node, string, error) {
 	contents, foundAt, err := cache.importData(importedFrom, importedPath)
 	if err != nil {
diff --git a/jsonnet_test.go b/jsonnet_test.go
index 2287abe5e..6f498eb31 100644
--- a/jsonnet_test.go
+++ b/jsonnet_test.go
@@ -290,11 +290,11 @@ func assertVarOutput(t *testing.T, jsonStr string) {
 }
 
 func TestExtTypes(t *testing.T) {
-	node, err := SnippetToAST("var.jsonnet", `{ node: 'node' }`)
+	vm := MakeVM()
+	node, err := vm.SnippetToAST("var.jsonnet", `{ node: 'node' }`)
 	if err != nil {
 		t.Fatalf("Unexpected error: %v", err)
 	}
-	vm := MakeVM()
 	vm.ExtVar("var", "var")
 	vm.ExtCode("code", `{ code: 'code'}`)
 	vm.ExtNode("node", node)
@@ -310,11 +310,11 @@ func TestExtTypes(t *testing.T) {
 }
 
 func TestTLATypes(t *testing.T) {
-	node, err := SnippetToAST("var.jsonnet", `{ node: 'node' }`)
+	vm := MakeVM()
+	node, err := vm.SnippetToAST("var.jsonnet", `{ node: 'node' }`)
 	if err != nil {
 		t.Fatalf("Unexpected error: %v", err)
 	}
-	vm := MakeVM()
 	vm.TLAVar("var", "var")
 	vm.TLACode("code", `{ code: 'code'}`)
 	vm.TLANode("node", node)
diff --git a/linter/linter.go b/linter/linter.go
index 7092764c3..9ab0f75d7 100644
--- a/linter/linter.go
+++ b/linter/linter.go
@@ -140,7 +140,7 @@ func LintSnippet(vm *jsonnet.VM, output io.Writer, snippets []Snippet) bool {
 
 	var nodes []nodeWithLocation
 	for _, snippet := range snippets {
-		node, err := jsonnet.SnippetToAST(snippet.FileName, snippet.Code)
+		node, err := vm.SnippetToAST(snippet.FileName, snippet.Code)
 
 		if err != nil {
 			errWriter.writeError(vm, err.(errors.StaticError)) // ugly but true
diff --git a/linter/linter_test.go b/linter/linter_test.go
index 8002e5d57..212cb4c96 100644
--- a/linter/linter_test.go
+++ b/linter/linter_test.go
@@ -104,6 +104,23 @@ func runTests(t *testing.T, tests []*linterTest) {
 	if outData != "" && !errorsFound {
 		t.Error(fmt.Errorf("return value indicates no problems, but output is not empty:\n%v", outData))
 	}
+
+	// passing as args for both importing file and imported file.
+	var import_snippets []Snippet
+
+	for _, filepath := range []string{"testdata/import.jsonnet", "testdata/call_integer.jsonnet"} {
+		input := read(filepath)
+		import_snippets = append(import_snippets, Snippet{FileName: filepath, Code: string(input)})
+	}
+
+	errorsFound = LintSnippet(vm, &outBuilder, snippets)
+	outData = outBuilder.String()
+	if outData == "" && errorsFound {
+		t.Error(fmt.Errorf("return value indicates problems present, but no output was produced"))
+	}
+	if outData != "" && !errorsFound {
+		t.Error(fmt.Errorf("return value indicates no problems, but output is not empty:\n%v", outData))
+	}
 }
 
 func TestLinter(t *testing.T) {
diff --git a/main_test.go b/main_test.go
index 9e230a599..d1357c3cf 100644
--- a/main_test.go
+++ b/main_test.go
@@ -146,7 +146,7 @@ func runInternalJsonnet(i jsonnetInput) jsonnetResult {
 	}
 	testChildren(rawAST)
 
-	desugaredAST, err := SnippetToAST(i.name, string(i.input))
+	desugaredAST, err := vm.SnippetToAST(i.name, string(i.input))
 	if err != nil {
 		return jsonnetResult{
 			output:  errFormatter.Format(err) + "\n",
diff --git a/vm.go b/vm.go
index 43b098063..bd3f918b3 100644
--- a/vm.go
+++ b/vm.go
@@ -514,8 +514,8 @@ func (vm *VM) ImportAST(importedFrom, importedPath string) (contents ast.Node, f
 }
 
 // SnippetToAST parses a snippet and returns the resulting AST.
-func SnippetToAST(filename string, snippet string) (ast.Node, error) {
-	return program.SnippetToAST(ast.DiagnosticFileName(filename), filename, snippet)
+func (vm *VM) SnippetToAST(filename string, snippet string) (ast.Node, error) {
+	return vm.importCache.snippetToAST(ast.DiagnosticFileName(filename), filename, snippet)
 }
 
 // Version returns the Jsonnet version number.

From d9173fc67a9cc433eb38541103fab2a22dc9350b Mon Sep 17 00:00:00 2001
From: Tsuyoshi Hombashi <tsuyoshi.hombashi@gmail.com>
Date: Sun, 11 Jul 2021 15:35:25 +0900
Subject: [PATCH 2/2] Fix a test case

---
 linter/linter_test.go | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/linter/linter_test.go b/linter/linter_test.go
index 212cb4c96..62449a7b4 100644
--- a/linter/linter_test.go
+++ b/linter/linter_test.go
@@ -113,7 +113,7 @@ func runTests(t *testing.T, tests []*linterTest) {
 		import_snippets = append(import_snippets, Snippet{FileName: filepath, Code: string(input)})
 	}
 
-	errorsFound = LintSnippet(vm, &outBuilder, snippets)
+	errorsFound = LintSnippet(vm, &outBuilder, import_snippets)
 	outData = outBuilder.String()
 	if outData == "" && errorsFound {
 		t.Error(fmt.Errorf("return value indicates problems present, but no output was produced"))