tools/trim: fix trimming bug

Closes #277

Change-Id: I1ed0dd75f2c53219c45647b7958d11fdb63ba8f4
Reviewed-on: https://cue-review.googlesource.com/c/cue/+/5001
Reviewed-by: Marcel van Lohuizen <mpvl@golang.org>
diff --git a/cue/instance.go b/cue/instance.go
index 37ca0dc..d2f9c8c 100644
--- a/cue/instance.go
+++ b/cue/instance.go
@@ -70,6 +70,7 @@
 
 // newInstance creates a new instance. Use Insert to populate the instance.
 func (x *index) newInstance(p *build.Instance) *Instance {
+	// TODO: associate root source with structLit.
 	st := &structLit{baseValue: baseValue{nil}}
 	i := &Instance{
 		rootStruct: st,
diff --git a/tools/trim/trim.go b/tools/trim/trim.go
index e78be9b..ccbb197 100644
--- a/tools/trim/trim.go
+++ b/tools/trim/trim.go
@@ -88,6 +88,7 @@
 	defer func() { internal.DropOptional = false }()
 
 	gen := newTrimSet(cfg)
+	gen.files = files
 	for _, f := range files {
 		gen.markNodes(f)
 	}
@@ -103,6 +104,7 @@
 
 type trimSet struct {
 	cfg       Config
+	files     []*ast.File
 	stack     []string
 	exclude   map[ast.Node]bool // don't remove fields marked here
 	alwaysGen map[ast.Node]bool // node is always from a generated source
@@ -337,9 +339,14 @@
 					}
 
 				default:
+					// Currently the ast.Files are not associated with the
+					// nodes. We detect this case here and iterate over all
+					// files.
+					// TODO: fix this. See cue/instance.go.
 					if len(t.stack) == 1 {
-						// TODO: fix this hack to pass down the fields to remove
-						return rm
+						for _, x := range t.files {
+							x.Decls = t.trimDecls(x.Decls, rm, m, canRemove)
+						}
 					}
 				}
 			}
diff --git a/tools/trim/trim_test.go b/tools/trim/trim_test.go
index 558fa72..94bcd4b 100644
--- a/tools/trim/trim_test.go
+++ b/tools/trim/trim_test.go
@@ -94,6 +94,16 @@
 	}
 }
 `,
+	}, {
+		name: "do not remove field",
+		in: `
+		[_]: x: "hello"
+		a: x: "hello"
+		`,
+		out: `[_]: x: "hello"
+a: {
+}
+`,
 		// TODO: This used to work.
 		// 	name: "remove implied interpolations",
 		// 	in: `