diff --git a/linter/linter.go b/linter/linter.go index 1437ba1f..c7838848 100644 --- a/linter/linter.go +++ b/linter/linter.go @@ -2,12 +2,13 @@ package linter import ( - "io" - jsonnet "github.com/google/go-jsonnet" "github.com/google/go-jsonnet/ast" "github.com/google/go-jsonnet/internal/errors" "github.com/google/go-jsonnet/internal/parser" + "io" + "path/filepath" + "strings" "github.com/google/go-jsonnet/linter/internal/common" "github.com/google/go-jsonnet/linter/internal/traversal" @@ -45,14 +46,6 @@ type nodeWithLocation struct { // Lint analyses a node and reports any issues it encounters to an error writer. func lint(vm *jsonnet.VM, nodes []nodeWithLocation, errWriter *ErrorWriter) { - roots := make(map[string]ast.Node) - for _, node := range nodes { - roots[node.path] = node.node - } - for _, node := range nodes { - getImports(vm, node, roots, errWriter) - } - variablesInFile := make(map[string]common.VariableInfo) std := common.Variable{ @@ -65,16 +58,20 @@ func lint(vm *jsonnet.VM, nodes []nodeWithLocation, errWriter *ErrorWriter) { return variables.FindVariables(node.node, variables.Environment{"std": &std, "$std": &std}) } - for importedPath, rootNode := range roots { - variablesInFile[importedPath] = *findVariables(nodeWithLocation{rootNode, importedPath}) - } + for _, node := range nodes { + roots := make(map[string]ast.Node) + roots[node.path] = node.node + getImports(vm, node, roots, errWriter) - vars := make(map[string]map[ast.Node]*common.Variable) - for importedPath, info := range variablesInFile { - vars[importedPath] = info.VarAt - } + for importedPath, rootNode := range roots { + variablesInFile[importedPath] = *findVariables(nodeWithLocation{rootNode, importedPath}) + } + + vars := make(map[string]map[ast.Node]*common.Variable) + for importedPath, info := range variablesInFile { + vars[importedPath] = info.VarAt + } - for _, node := range nodes { variableInfo := findVariables(node) for _, v := range variableInfo.Variables { @@ -85,6 +82,20 @@ func lint(vm *jsonnet.VM, nodes []nodeWithLocation, errWriter *ErrorWriter) { ec := common.ErrCollector{} types.Check(node.node, roots, vars, func(currentPath, importedPath string) ast.Node { + // try to resolve the imported node from the already calculated list of roots + // if this fails, reimport the node + idx := strings.LastIndex(currentPath, "/") + var currentDir = "" + if idx != -1 { + currentDir = currentPath[:idx] + } + + relativePath := filepath.Join(currentDir, importedPath) + node := roots[relativePath] + if node != nil { + return node + } + node, _, err := vm.ImportAST(currentPath, importedPath) if err != nil { return nil