aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/libexpr/parser.y26
-rw-r--r--tests/lang/parse-fail-mixed-nested-attrs1.nix4
-rw-r--r--tests/lang/parse-fail-mixed-nested-attrs2.nix4
-rw-r--r--tests/lang/parse-okay-dup-attrs-6.nix (renamed from tests/lang/parse-fail-dup-attrs-6.nix)0
-rw-r--r--tests/lang/parse-okay-mixed-nested-attrs-1.nix4
-rw-r--r--tests/lang/parse-okay-mixed-nested-attrs-2.nix4
-rw-r--r--tests/lang/parse-okay-mixed-nested-attrs-3.nix7
7 files changed, 46 insertions, 3 deletions
diff --git a/src/libexpr/parser.y b/src/libexpr/parser.y
index 787039307..97e1a6584 100644
--- a/src/libexpr/parser.y
+++ b/src/libexpr/parser.y
@@ -81,7 +81,9 @@ static void addAttr(ExprAttrs * attrs, AttrPath & attrPath,
AttrPath::iterator i;
// All attrpaths have at least one attr
assert(!attrPath.empty());
- for (i = attrPath.begin(); i + 1 < attrPath.end(); i++) {
+ // Checking attrPath validity.
+ // ===========================
+ for (i = attrPath.begin(); i + 1 < attrPath.end(); i++) {
if (i->symbol.set()) {
ExprAttrs::AttrDefs::iterator j = attrs->attrs.find(i->symbol);
if (j != attrs->attrs.end()) {
@@ -102,11 +104,29 @@ static void addAttr(ExprAttrs * attrs, AttrPath & attrPath,
attrs = nested;
}
}
- if (i->symbol.set()) {
+ // Expr insertion.
+ // ==========================
+ if (i->symbol.set()) {
ExprAttrs::AttrDefs::iterator j = attrs->attrs.find(i->symbol);
if (j != attrs->attrs.end()) {
- dupAttr(attrPath, pos, j->second.pos);
+ // This attr path is already defined. However, if both
+ // e and the expr pointed by the attr path are two attribute sets,
+ // we want to merge them.
+ // Otherwise, throw an error.
+ ExprAttrs* ae = dynamic_cast<ExprAttrs *>(e);
+ ExprAttrs* jAttrs = dynamic_cast<ExprAttrs *>(j->second.e);
+ if (jAttrs && ae) {
+ for (auto ad: ae->attrs) {
+ ExprAttrs::AttrDefs::iterator j2 = jAttrs->attrs.find(ad.first);
+ if (j2 != jAttrs->attrs.end()) // Attr already defined in iAttrs, error.
+ dupAttr(ad.first, j2->second.pos, ad.second.pos);
+ jAttrs->attrs[ad.first] = ad.second;
+ }
+ } else {
+ dupAttr(attrPath, pos, j->second.pos);
+ }
} else {
+ // This attr path is not defined. Let's create it.
attrs->attrs[i->symbol] = ExprAttrs::AttrDef(e, pos);
e->setName(i->symbol);
}
diff --git a/tests/lang/parse-fail-mixed-nested-attrs1.nix b/tests/lang/parse-fail-mixed-nested-attrs1.nix
new file mode 100644
index 000000000..11e40e66f
--- /dev/null
+++ b/tests/lang/parse-fail-mixed-nested-attrs1.nix
@@ -0,0 +1,4 @@
+{
+ x.z = 3;
+ x = { y = 3; z = 3; };
+}
diff --git a/tests/lang/parse-fail-mixed-nested-attrs2.nix b/tests/lang/parse-fail-mixed-nested-attrs2.nix
new file mode 100644
index 000000000..17da82e5f
--- /dev/null
+++ b/tests/lang/parse-fail-mixed-nested-attrs2.nix
@@ -0,0 +1,4 @@
+{
+ x.y.y = 3;
+ x = { y.y= 3; z = 3; };
+}
diff --git a/tests/lang/parse-fail-dup-attrs-6.nix b/tests/lang/parse-okay-dup-attrs-6.nix
index ae6d7a769..ae6d7a769 100644
--- a/tests/lang/parse-fail-dup-attrs-6.nix
+++ b/tests/lang/parse-okay-dup-attrs-6.nix
diff --git a/tests/lang/parse-okay-mixed-nested-attrs-1.nix b/tests/lang/parse-okay-mixed-nested-attrs-1.nix
new file mode 100644
index 000000000..fd1001c8c
--- /dev/null
+++ b/tests/lang/parse-okay-mixed-nested-attrs-1.nix
@@ -0,0 +1,4 @@
+{
+ x = { y = 3; z = 3; };
+ x.q = 3;
+}
diff --git a/tests/lang/parse-okay-mixed-nested-attrs-2.nix b/tests/lang/parse-okay-mixed-nested-attrs-2.nix
new file mode 100644
index 000000000..ad066b680
--- /dev/null
+++ b/tests/lang/parse-okay-mixed-nested-attrs-2.nix
@@ -0,0 +1,4 @@
+{
+ x.q = 3;
+ x = { y = 3; z = 3; };
+}
diff --git a/tests/lang/parse-okay-mixed-nested-attrs-3.nix b/tests/lang/parse-okay-mixed-nested-attrs-3.nix
new file mode 100644
index 000000000..45a33e480
--- /dev/null
+++ b/tests/lang/parse-okay-mixed-nested-attrs-3.nix
@@ -0,0 +1,7 @@
+{
+ services.ssh.enable = true;
+ services.ssh = { port = 123; };
+ services = {
+ httpd.enable = true;
+ };
+}