cmd/cue/cmd: track dependencies in definitions

Fixes #237

Change-Id: I338039742184bc7475e447cf5a6e21f11f81920e
Reviewed-on: https://cue-review.googlesource.com/c/cue/+/4440
Reviewed-by: Marcel van Lohuizen <mpvl@golang.org>
diff --git a/cmd/cue/cmd/custom.go b/cmd/cue/cmd/custom.go
index a8d5f82..60a9576 100644
--- a/cmd/cue/cmd/custom.go
+++ b/cmd/cue/cmd/custom.go
@@ -32,6 +32,7 @@
 	"cuelang.org/go/cue"
 	"cuelang.org/go/internal"
 	itask "cuelang.org/go/internal/task"
+	"cuelang.org/go/internal/walk"
 	_ "cuelang.org/go/pkg/tool/cli" // Register tasks
 	_ "cuelang.org/go/pkg/tool/exec"
 	_ "cuelang.org/go/pkg/tool/file"
@@ -292,10 +293,13 @@
 
 	switch op, args := v.Expr(); op {
 	case cue.NoOp:
-		v.Walk(nil, func(w cue.Value) {
-			if v != w {
-				a = appendReferences(a, root, w)
-			}
+		walk.Value(v, &walk.Config{
+			Opts: []cue.Option{cue.All()},
+			After: func(w cue.Value) {
+				if v != w {
+					a = appendReferences(a, root, w)
+				}
+			},
 		})
 	default:
 		for _, arg := range args {
diff --git a/cmd/cue/cmd/testdata/script/cmd_dep.txt b/cmd/cue/cmd/testdata/script/cmd_dep.txt
new file mode 100644
index 0000000..dcd7ec4
--- /dev/null
+++ b/cmd/cue/cmd/testdata/script/cmd_dep.txt
@@ -0,0 +1,32 @@
+cue cmd do
+cmp stdout expect-stdout
+
+-- expect-stdout --
+{"b":"cue\n"}
+-- task_tool.cue --
+package home
+
+import (
+    "encoding/json"
+    "tool/cli"
+    "tool/exec"
+)
+
+foo: {
+  a :: string
+  b: a
+}
+
+command: do: {
+    task: name: exec.Run & {
+        cmd: "echo cue"
+        stdout: string
+    }
+    task: out: cli.Print & {
+        text:  json.Marshal(foo & { a :: task.name.stdout })
+    }
+}
+
+-- task.cue --
+package home
+-- cue.mod --
diff --git a/internal/walk/walk.go b/internal/walk/walk.go
new file mode 100644
index 0000000..8e3c9f9
--- /dev/null
+++ b/internal/walk/walk.go
@@ -0,0 +1,69 @@
+// Copyright 2019 CUE Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// Package walk allows walking over CUE values.
+//
+// This package replicates Value.Walk in the cue package.
+// There are several different internal uses of walk. This
+// package is intended as a single implementation that on
+// which all these implementations should converge. Once a
+// satisfactory API has been established, it can be made public.
+package walk
+
+import "cuelang.org/go/cue"
+
+// TODO:
+// - allow overriding options for descendants.
+//   Perhaps func(f cue.Value) *Config?
+// - Get field information.
+
+// Alternatives:
+// type Visitor struct {}
+// func (v *Visitor) Do(cue.Value)
+// - less typing
+// - two elements are grouped together in UI.
+
+type Config struct {
+	Before func(f cue.Value) bool
+	After  func(f cue.Value)
+	Opts   []cue.Option
+}
+
+func Value(v cue.Value, c *Config) {
+	switch v.Kind() {
+	case cue.StructKind:
+		if c.Before != nil && !c.Before(v) {
+			return
+		}
+		iter, _ := v.Fields(c.Opts...)
+		for iter.Next() {
+			Value(iter.Value(), c)
+		}
+	case cue.ListKind:
+		if c.Before != nil && !c.Before(v) {
+			return
+		}
+		list, _ := v.List()
+		for list.Next() {
+			Value(list.Value(), c)
+		}
+	default:
+		if c.Before != nil {
+			c.Before(v)
+		}
+	}
+	if c.After != nil {
+		c.After(v)
+	}
+}