Repository: attic-labs/noms (go)

Issue:
nomdl.Parse(): Incorrect result
`nomdl.Parse("[map {}]")` should return `types.NewList(vs, types.NewMap(vs)))`, but it actually returns an empty list.


Pull request description:
Do not ignore empty collections in ListEditor
We used to ignore empty collections inside a ListEditor which meant that
a list editor could not be used to create lists that contain empty
lists, maps or sets.

Fixes #3868

Patch:
diff --git a/go/types/collection.go b/go/types/collection.go
index 0ef86530..c8cdbb3e 100644
--- a/go/types/collection.go
+++ b/go/types/collection.go
@@ -6,7 +6,7 @@ package types
 
 type Collection interface {
 	Value
-	Emptyable
+	Empty() bool
 	Len() uint64
 	asSequence() sequence
 }
diff --git a/go/types/list_editor.go b/go/types/list_editor.go
index ef3f20e3..fe636ed0 100644
--- a/go/types/list_editor.go
+++ b/go/types/list_editor.go
@@ -101,10 +101,6 @@ func (le *ListEditor) List() List {
 		}
 
 		for _, v := range sp.inserted {
-			if emp, ok := v.(Emptyable); ok && emp.Empty() {
-				continue
-			}
-
 			ch.Append(v)
 		}
 	}
diff --git a/go/types/map_editor.go b/go/types/map_editor.go
index 785a27e2..f5571649 100644
--- a/go/types/map_editor.go
+++ b/go/types/map_editor.go
@@ -78,12 +78,6 @@ func (me *MapEditor) Map() Map {
 
 			go func() {
 				sv := edit.value.Value()
-				if e, ok := sv.(Emptyable); ok {
-					if e.Empty() {
-						sv = nil
-					}
-				}
-
 				kvc <- mapEntry{edit.key, sv}
 			}()
 		}
diff --git a/go/types/value.go b/go/types/value.go
index 9a72cf19..bc22a278 100644
--- a/go/types/value.go
+++ b/go/types/value.go
@@ -21,11 +21,6 @@ type Valuable interface {
 	Value() Value
 }
 
-// Emptyable is an interface for Values which may or may not be empty
-type Emptyable interface {
-	Empty() bool
-}
-
 // Value is the interface all Noms values implement.
 type Value interface {
 	Valuable


Test patch:
diff --git a/go/nomdl/parser_test.go b/go/nomdl/parser_test.go
index 31dd8a75..09a05ee4 100644
--- a/go/nomdl/parser_test.go
+++ b/go/nomdl/parser_test.go
@@ -282,11 +282,27 @@ func TestValueList(t *testing.T) {
 	assertParseError(t, "[,]", "Unexpected token \",\", example:1:3")
 
 	assertParse(t, vs, `[42,
-                Bool,
-        ]`, types.NewList(vs, types.Number(42), types.BoolType))
+	            Bool,
+	    ]`, types.NewList(vs, types.Number(42), types.BoolType))
 	assertParse(t, vs, `[42,
-                Bool
-        ]`, types.NewList(vs, types.Number(42), types.BoolType))
+	            Bool
+		]`, types.NewList(vs, types.Number(42), types.BoolType))
+}
+
+func TestEmptyValuesInEditors(t *testing.T) {
+	vs := newTestValueStore()
+
+	assertParse(t, vs, "[[]]", types.NewList(vs, types.NewList(vs)))
+	assertParse(t, vs, "[set {}]", types.NewList(vs, types.NewSet(vs)))
+	assertParse(t, vs, "[map {}]", types.NewList(vs, types.NewMap(vs)))
+
+	assertParse(t, vs, "set {[]}", types.NewSet(vs, types.NewList(vs)))
+	assertParse(t, vs, "set {set {}}", types.NewSet(vs, types.NewSet(vs)))
+	assertParse(t, vs, "set {map {}}", types.NewSet(vs, types.NewMap(vs)))
+
+	assertParse(t, vs, "map {map {}: map {}}", types.NewMap(vs, types.NewMap(vs), types.NewMap(vs)))
+	assertParse(t, vs, "map {[]: []}", types.NewMap(vs, types.NewList(vs), types.NewList(vs)))
+	assertParse(t, vs, "map {set {}: set {}}", types.NewMap(vs, types.NewSet(vs), types.NewSet(vs)))
 }
 
 func TestValueSet(t *testing.T) {
diff --git a/go/types/map_test.go b/go/types/map_test.go
index 6dd05345..05f90d4d 100644
--- a/go/types/map_test.go
+++ b/go/types/map_test.go
@@ -1666,5 +1666,9 @@ func TestNestedEditing(t *testing.T) {
 	se2b.Remove(String("bb"))
 
 	mOut = me0.Map()
-	assert.True(t, mOut.Equals(NewMap(vrw))) // remove empty
+	fmt.Println(EncodedValue(mOut))
+	assert.True(t, mOut.Equals(NewMap(vrw,
+		String("a"), NewMap(vrw, String("a"), NewSet(vrw)),
+		String("b"), NewMap(vrw, String("b"), NewSet(vrw)),
+	))) // do not remove empty
 }