diff --git a/core/core-configuration-layer.el b/core/core-configuration-layer.el index 450975e2f..688e0ba3f 100644 --- a/core/core-configuration-layer.el +++ b/core/core-configuration-layer.el @@ -116,15 +116,18 @@ ROOT is returned." :initform 'unspecified :type (satisfies (lambda (x) (or (listp x) (eq 'unspecified x)))) :documentation - "A list of layers where this layer is enabled. (Takes precedence over `:disabled-for'.)") + (concat "A list of layers where this layer is enabled. " + "(Takes precedence over `:disabled-for'.)")) + ;; Note: + ;; 'can-shadow' is a commutative relation: + ;; if Y 'can-shadow' X then X 'can-shadow' Y + ;; but the 'shadow' operation is not commutative, the order of the operands + ;; is determined by the order of the layers in the dotfile + ;; (variable: dotspacemacs-configuration-layers) (can-shadow :initarg :can-shadow - :initform t - :type boolean - :documentation "If non-nil this layer can shadow other layers.") - (shadowed-by :initarg :shadowed-by - :initform nil - :type list - :documentation "A list of layers that can shadow this layer.")) + :initform 'unspecified + :type (satisfies (lambda (x) (or (listp x) (eq 'unspecified x)))) + :documentation "A list of layers this layer can shadow.")) "A configuration layer.") (defmethod cfgl-layer-owned-packages ((layer cfgl-layer) &optional props) @@ -142,25 +145,30 @@ LAYER has to be installed for this method to work properly." "Accept nil as argument and return nil." nil) -(defmethod cfgl-layer-shadowed-p ((layer cfgl-layer)) - "Return the list of layers that shadow LAYER." +(defmethod cfgl-layer-get-shadowing-layers ((layer cfgl-layer)) + "Return the list of used layers that shadow LAYER." (let ((rank (cl-position (oref layer :name) configuration-layer--used-layers)) + (shadow-candidates (oref layer :can-shadow)) shadowing-layers) - (when (numberp rank) + (when (and (numberp rank) + (not (eq 'unspecified shadow-candidates)) + (listp shadow-candidates)) (mapcar (lambda (other) (let ((orank (cl-position other configuration-layer--used-layers))) - ;; LAYER is shadowed by OTHER if and only if its rank is lower than - ;; OTHER's rank. + ;; OTHER shadows LAYER if and only if OTHER's rank is bigger than + ;; LAYER's rank. (when (and (numberp orank) (< rank orank)) (add-to-list 'shadowing-layers other)))) - (oref layer :shadowed-by))) + ;; since the 'can-shadow' relation is commutative it is safe to use this + ;; list, i.e. if LAYER can shadow layers X and Y then X and Y can shadow + ;; LAYER. + shadow-candidates)) shadowing-layers)) (defmethod cfgl-layer-get-packages ((layer cfgl-layer) &optional props) "Return the list of packages for LAYER. -If PROPS is non-nil then return packages as lists along with their properties. -Returns nil if the layer is shadowed by a layer." +If PROPS is non-nil then return packages as lists along with their properties." (let ((all (eq 'all (oref layer :selected-packages)))) (delq nil (mapcar (lambda (x) @@ -626,10 +634,10 @@ If USEDP or `configuration-layer--load-packages-files' is non-nil then the 'unspecified)) (variables (when (listp layer-specs) (spacemacs/mplist-get layer-specs :variables))) - (can-shadow + (shadow (if (and (listp layer-specs) (memq :can-shadow layer-specs)) - (nth 0 (spacemacs/mplist-get layer-specs :can-shadow)) + (spacemacs/mplist-get layer-specs :can-shadow) 'unspecified)) (packages-file (concat dir "packages.el")) (packages @@ -649,8 +657,8 @@ If USEDP or `configuration-layer--load-packages-files' is non-nil then the (oset obj :disabled-for disabled) (oset obj :enabled-for enabled) (oset obj :variables variables) - (unless (eq 'unspecified can-shadow) - (oset obj :can-shadow can-shadow))) + (unless (eq 'unspecified shadow) + (oset obj :can-shadow shadow))) (when packages (oset obj :packages packages) (oset obj :selected-packages selected-packages)) @@ -1048,7 +1056,7 @@ If SKIP-LAYER-DISCOVERY is non-nil then do not check for new layers." USEDP if non-nil indicates that made packages are used packages." (dolist (layer-name layer-names) (let* ((layer (configuration-layer/get-layer layer-name)) - (shadowed-by (cfgl-layer-shadowed-p layer))) + (shadowed-by (cfgl-layer-get-shadowing-layers layer))) (if shadowed-by (spacemacs-buffer/message "Ignoring layer '%s' because it is shadowed by layer(s) '%s'." @@ -1350,32 +1358,56 @@ wether the declared layer is an used one or not." (configuration-layer/declare-layer distribution))) (configuration-layer/declare-layer 'spacemacs-bootstrap))) -(defun configuration-layer/shadow-layers (layer-name shadowed-layers) - "Declare LAYER-NAME to shadow SHADOWED-LAYERS. -LAYER-NAME is a the name symbol of an existing layer. -SHADOWED-LAYERS is a list of layer name symbols." - (mapc (lambda (x) - (configuration-layer/shadow-layer layer-name x)) - shadowed-layers)) +(defun configuration-layer/declare-shadow-relation (layer-name &rest onames) + "Declare 'can-shadow' relationship between LAYER_NAME and OTHER-NAMES layers. +LAYER-NAME is the name symbol of an existing layer. +ONAMES is a list of other layer name symbols." + (dolist (o onames) + (configuration-layer//declare-shadow-relation layer-name o))) -(defun configuration-layer/shadow-layer (layer-name shadowed-layer-name) - "Declare LAYER-NAME to shadow SHADOWED-LAYER. -LAYER-NAME is a the name symbol of an existing layer. -SHADOWED-LAYER-NAME is the name symbol of an existing layer." - (let* ((layer (configuration-layer/get-layer layer-name)) - (shadowed-layer (configuration-layer/get-layer shadowed-layer-name))) - (if (and layer shadowed-layer) - (progn - ;; note: shadowing is commutative - (cl-pushnew layer-name (oref shadowed-layer :shadowed-by)) - (cl-pushnew shadowed-layer-name (oref layer :shadowed-by))) - ;; cannot find one or both layers - (if (null layer) - (configuration-layer//warning "Unknown layer %s to shadow %s." - layer-name shadowed-layer-name)) - (if (null shadowed-layer) - (configuration-layer//warning "Unknown shadowed layer %s by %s." - shadowed-layer-name layer-name))))) +(defun configuration-layer//declare-shadow-relation (lname rname) + "Declare 'can-shadow' relationship between LAYER_NAME and OTHER-NAMES layers. +LNAME is the name symbol of an existing layer. +RNAME is the name symbol of another existing layer." + (let ((llayer (configuration-layer/get-layer lname)) + (rlayer (configuration-layer/get-layer rname))) + (if (and llayer rlayer) + (let ((lshadow (oref llayer :can-shadow)) + (rshadow (oref rlayer :can-shadow))) + ;; lhs of the relation + (cond + ((eq 'unspecified lshadow) + (when rshadow + (oset llayer :can-shadow `(,rname)))) + ((and lshadow (listp lshadow)) + (when rshadow + (cl-pushnew rname (oref llayer :can-shadow)))) + ((null lshadow) + (spacemacs-buffer/message + (concat "Ignore shadow relation between layers %s and %s because " + ":can-shadow of layer %s has been set to nil by the user.") + lname rname lname))) + ;; rhs of the relation + (cond + ((eq 'unspecified rshadow) + (when lshadow + (oset rlayer :can-shadow `(,lname)))) + ((and rshadow (listp rshadow)) + (when lshadow + (cl-pushnew lname (oref rlayer :can-shadow)))) + ((null rshadow) + (spacemacs-buffer/message + (concat "Ignore shadow relation between layers %s and %s because " + ":can-shadow of layer %s has been set to nil by the user.") + rname lname rname)))) + (when (null llayer) + (configuration-layer//warning + "Unknown layer %s to declare lshadow relationship." + lname)) + (when (null rlayer) + (configuration-layer//warning + "Unknown layer %s to declare lshadow relationship." + rname))))) (defun configuration-layer//set-layers-variables (layers) "Set the configuration variables for the passed LAYERS." @@ -1403,7 +1435,7 @@ SHADOWED-LAYER-NAME is the name symbol of an existing layer." "Return non-nil if LAYER-NAME is the name of a used and non-shadowed layer." (or (eq 'dotfile layer-name) (let ((obj (configuration-layer/get-layer layer-name))) - (when obj (and (not (cfgl-layer-shadowed-p obj)) + (when obj (and (not (cfgl-layer-get-shadowing-layers obj)) (memq layer-name configuration-layer--used-layers)))))) (defalias 'configuration-layer/layer-usedp 'configuration-layer/layer-used-p) diff --git a/layers/+completion/helm/layers.el b/layers/+completion/helm/layers.el index c9adc5b10..77ff52888 100644 --- a/layers/+completion/helm/layers.el +++ b/layers/+completion/helm/layers.el @@ -9,4 +9,4 @@ ;; ;;; License: GPLv3 -(configuration-layer/shadow-layer 'helm 'ivy) +(configuration-layer/declare-shadow-relation 'helm 'ivy) diff --git a/layers/+completion/ivy/layers.el b/layers/+completion/ivy/layers.el index 32975f089..0f0473cc5 100644 --- a/layers/+completion/ivy/layers.el +++ b/layers/+completion/ivy/layers.el @@ -9,7 +9,7 @@ ;; ;;; License: GPLv3 -(configuration-layer/shadow-layer 'ivy 'helm) +(configuration-layer/declare-shadow-relation 'ivy 'helm) ;; smex is handled by the `ivy' layer and we don't want ;; to use the ownership mechanism of layers because it is dependent diff --git a/tests/core/core-configuration-layer-utest.el b/tests/core/core-configuration-layer-utest.el index 5d62c84a2..c89b9d1a7 100644 --- a/tests/core/core-configuration-layer-utest.el +++ b/tests/core/core-configuration-layer-utest.el @@ -170,29 +170,48 @@ :selected-packages '(pkg-unknown)))) (should (null (cfgl-layer-get-packages layer))))) -;; method: cfgl-layer-shadowed-p +;; method: cfgl-layer-get-shadowing-layers -(ert-deftest test-cfgl-layer-shadowed-p--layer2-shadows-layer1 () +(ert-deftest test-cfgl-layer-get-shadowing-layers--l2-declared-after-l1-shadows-l1 () (let ((layer1 (cfgl-layer "layer1" :name 'layer1)) (layer2 (cfgl-layer "layer2" :name 'layer2)) (configuration-layer--used-layers nil) (configuration-layer--indexed-layers (make-hash-table :size 1024))) (helper--add-layers `(,layer1 ,layer2) 'used) - (configuration-layer/shadow-layer 'layer2 'layer1) - (should (and (equal '(layer2) (cfgl-layer-shadowed-p layer1)) - (not (cfgl-layer-shadowed-p layer2)))))) + (configuration-layer/declare-shadow-relation 'layer1 'layer2) + (should (and (equal '(layer2) (cfgl-layer-get-shadowing-layers layer1)) + (equal '() (cfgl-layer-get-shadowing-layers layer2)))))) -(ert-deftest test-cfgl-layer-shadowed-p--layer1-shadows-layer2 () +(ert-deftest test-cfgl-layer-get-shadowing-layers--l1-declared-after-l2-shadows-l2 () (let ((layer1 (cfgl-layer "layer1" :name 'layer1)) (layer2 (cfgl-layer "layer2" :name 'layer2)) (configuration-layer--used-layers nil) (configuration-layer--indexed-layers (make-hash-table :size 1024))) - ;; we just switched the order of used layers - ;; remember, shadowing is commutative - (helper--add-layers `(,layer2 ,layer1) 'used) - (configuration-layer/shadow-layer 'layer2 'layer1) - (should (and (equal '(layer1) (cfgl-layer-shadowed-p layer2)) - (not (cfgl-layer-shadowed-p layer1)))))) + (helper--add-layers `(,layer1 ,layer2) 'used) + (configuration-layer/declare-shadow-relation 'layer1 'layer2) + (should (and (equal '(layer2) (cfgl-layer-get-shadowing-layers layer1)) + (equal '() (cfgl-layer-get-shadowing-layers layer2)))))) + +(ert-deftest test-cfgl-layer-get-shadowing-layers--prevent-l2-from-shadowing-l1 () + (let ((layer1 (cfgl-layer "layer1" :name 'layer1)) + (layer2 (cfgl-layer "layer2" :name 'layer2 :can-shadow nil)) + (configuration-layer--used-layers nil) + (configuration-layer--indexed-layers (make-hash-table :size 1024))) + (helper--add-layers `(,layer1 ,layer2) 'used) + (configuration-layer/declare-shadow-relation 'layer2 'layer1) + (should (null (cfgl-layer-get-shadowing-layers layer1))))) + +(ert-deftest test-cfgl-layer-get-shadowing-layers--prevent-l2-from-shadowing-l1-alternative () + ;; using the commutative property of the can-shadow relation + ;; setting :can-shadow to nil on layer1 produces the same effect as the more + ;; intuitive test-cfgl-layer-get-shadowing-layers--prevent-l2-from-shadowing-l1 + (let ((layer1 (cfgl-layer "layer1" :name 'layer1 :can-shadow nil)) + (layer2 (cfgl-layer "layer2" :name 'layer2)) + (configuration-layer--used-layers nil) + (configuration-layer--indexed-layers (make-hash-table :size 1024))) + (helper--add-layers `(,layer1 ,layer2) 'used) + (configuration-layer/declare-shadow-relation 'layer2 'layer1) + (should (null (cfgl-layer-get-shadowing-layers layer1))))) ;; --------------------------------------------------------------------------- ;; configuration-layer/layer-used-p @@ -218,7 +237,7 @@ configuration-layer--used-layers (configuration-layer--indexed-layers (make-hash-table :size 1024))) (helper--add-layers `(,usedlayer1 ,usedlayer2) 'used) - (configuration-layer/shadow-layer 'usedlayer2 'usedlayer1) + (configuration-layer/declare-shadow-relation 'usedlayer2 'usedlayer1) (should (not (configuration-layer/layer-used-p 'usedlayer1))))) (ert-deftest test-layer-used-p--dotfile-layer-is-always-used () @@ -949,7 +968,7 @@ :name 'layer :dir spacemacs-start-directory)) (layer-specs '(layer :disabled-for pkg8 pkg9 - :can-shadow nil + :can-shadow layer2 layer3 :variables foo bar toto 1)) (layer-packages '(pkg1 pkg2 pkg3)) (mocker-mock-default-record-cls 'mocker-stub-record)) @@ -959,7 +978,7 @@ (should (equal (cfgl-layer "layer" :name 'layer :disabled-for '(pkg8 pkg9) - :can-shadow nil + :can-shadow '(layer2 layer3) :variables '(foo bar toto 1) :packages '(pkg1 pkg2 pkg3) :selected-packages 'all @@ -971,13 +990,13 @@ :name 'layer :dir spacemacs-start-directory)) (layer-specs '(layer :disabled-for pkg8 pkg9 - :can-shadow nil + :can-shadow layer2 :variables foo bar toto 1)) (layer-packages '(pkg1 pkg2 pkg3))) (should (equal (cfgl-layer "layer" :name 'layer :disabled-for nil - :can-shadow t + :can-shadow 'unspecified :variables nil :packages nil :selected-packages 'all @@ -988,11 +1007,11 @@ (let ((layer (cfgl-layer "layer" :name 'layer :disabled-for '(pkg10) - :can-shadow nil + :can-shadow '() :variables '(titi tata tutu 1) :dir spacemacs-start-directory)) (layer-specs '(layer :disabled-for pkg8 pkg9 - :can-shadow t + :can-shadow layer2 :variables foo bar toto 1)) (layer-packages '(pkg1 pkg2 pkg3)) (mocker-mock-default-record-cls 'mocker-stub-record)) @@ -1002,7 +1021,7 @@ (should (equal (cfgl-layer "layer" :name 'layer :disabled-for '(pkg8 pkg9) - :can-shadow t + :can-shadow '(layer2) :variables '(foo bar toto 1) :packages '(pkg1 pkg2 pkg3) :selected-packages 'all @@ -1013,115 +1032,86 @@ (let ((layer (cfgl-layer "layer" :name 'layer :disabled-for '(pkg10) - :can-shadow nil + :can-shadow '() :variables '(titi tata tutu 1) :packages '(pkg1 pkg2 pkg3) :selected-packages 'all :dir spacemacs-start-directory)) (layer-specs '(layer :disabled-for pkg8 pkg9 - :can-shadow t + :can-shadow '(layer2) :variables foo bar toto 1)) (mocker-mock-default-record-cls 'mocker-stub-record)) (should (equal (cfgl-layer "layer" :name 'layer :disabled-for '(pkg10) - :can-shadow nil + :can-shadow '() :variables '(titi tata tutu 1) :packages '(pkg1 pkg2 pkg3) :selected-packages 'all :dir spacemacs-start-directory) (configuration-layer/make-layer layer-specs layer))))) -;; shadow layers - -(ert-deftest test-make-layer--by-default-layer-can-shadow-other-layers () - (let ((layer-specs 'layer) - (mocker-mock-default-record-cls 'mocker-stub-record)) - (should - (equal (cfgl-layer "layer" - :name 'layer - :dir spacemacs-start-directory - :can-shadow t) - (configuration-layer/make-layer layer-specs nil nil - spacemacs-start-directory))))) - -(ert-deftest test-make-layer--force-used-layer-to-not-shadow-other-layers () - (let ((layer-specs '(layer :can-shadow nil)) - (mocker-mock-default-record-cls 'mocker-stub-record)) - (should - (equal (cfgl-layer "layer" - :name 'layer - :dir spacemacs-start-directory - :can-shadow nil) - (configuration-layer/make-layer layer-specs nil 'used - spacemacs-start-directory))))) -(ert-deftest test-make-layer--unused-layer-can-always-shadow-other-layers () - (let ((layer-specs '(layer :can-shadow nil)) - (mocker-mock-default-record-cls 'mocker-stub-record)) - (should - (equal (cfgl-layer "layer" - :name 'layer - :dir spacemacs-start-directory - :can-shadow t) - (configuration-layer/make-layer layer-specs nil nil - spacemacs-start-directory))))) - ;; --------------------------------------------------------------------------- -;; configuration-layer//shadow-layer +;; configuration-layer//declare-shadow-relation ;; --------------------------------------------------------------------------- -(ert-deftest test-shadow-layer--layer-1-shadows-layer2 () +(ert-deftest test-declare-shadow-relation--is-commutative () (let ((configuration-layer--indexed-layers (make-hash-table :size 1024))) (helper--add-layers `(,(cfgl-layer "layer-shadow-1" :name 'layer-shadow-1) ,(cfgl-layer "layer-shadow-2" :name 'layer-shadow-2))) - (configuration-layer/shadow-layer 'layer-shadow-1 'layer-shadow-2) - (should (equal '(layer-shadow-1) - (oref (configuration-layer/get-layer 'layer-shadow-2) - :shadowed-by))))) + (configuration-layer/declare-shadow-relation + 'layer-shadow-1 + 'layer-shadow-2) + (should (and + (equal '(layer-shadow-1) (oref (configuration-layer/get-layer + 'layer-shadow-2) + :can-shadow)) + (equal '(layer-shadow-2) (oref (configuration-layer/get-layer + 'layer-shadow-1) + :can-shadow)))))) -(ert-deftest test-shadow-layer--layer-2-shadows-layer1-as-well--commutativity () +(ert-deftest test-declare-shadow-relation--is-idempotent () (let ((configuration-layer--indexed-layers (make-hash-table :size 1024))) (helper--add-layers `(,(cfgl-layer "layer-shadow-1" :name 'layer-shadow-1) ,(cfgl-layer "layer-shadow-2" :name 'layer-shadow-2))) - (configuration-layer/shadow-layer 'layer-shadow-1 'layer-shadow-2) - (should (equal '(layer-shadow-2) - (oref (configuration-layer/get-layer 'layer-shadow-1) - :shadowed-by))))) - -(ert-deftest test-shadow-layer--idempotency-and-commutatitivity () - (let ((configuration-layer--indexed-layers (make-hash-table :size 1024))) - (helper--add-layers - `(,(cfgl-layer "layer-shadow-1" :name 'layer-shadow-1) - ,(cfgl-layer "layer-shadow-2" :name 'layer-shadow-2))) - (dotimes (i 2) - (configuration-layer/shadow-layer 'layer-shadow-1 'layer-shadow-2)) - (dotimes (i 2) - (configuration-layer/shadow-layer 'layer-shadow-2 'layer-shadow-1)) - (should (and (equal '(layer-shadow-2) - (oref (configuration-layer/get-layer 'layer-shadow-1) - :shadowed-by)) - (equal '(layer-shadow-1) + (dotimes (i 3) + (configuration-layer/declare-shadow-relation + 'layer-shadow-1 + 'layer-shadow-2)) + (dotimes (i 3) + (configuration-layer/declare-shadow-relation + 'layer-shadow-2 + 'layer-shadow-1)) + (should (and (equal '(layer-shadow-1) (oref (configuration-layer/get-layer 'layer-shadow-2) - :shadowed-by)))))) + :can-shadow)) + (equal '(layer-shadow-2) + (oref (configuration-layer/get-layer 'layer-shadow-1) + :can-shadow)))))) -(ert-deftest test-shadow-layer--layer-1-shadows-multiple-layers () +(ert-deftest test-declare-shadow-relation--layer-1-shadows-multiple-layers () (let ((configuration-layer--indexed-layers (make-hash-table :size 1024))) (helper--add-layers `(,(cfgl-layer "layer-shadow-1" :name 'layer-shadow-1) ,(cfgl-layer "layer-shadow-2" :name 'layer-shadow-2) ,(cfgl-layer "layer-shadow-3" :name 'layer-shadow-3))) - (configuration-layer/shadow-layer 'layer-shadow-1 'layer-shadow-2) - (configuration-layer/shadow-layer 'layer-shadow-1 'layer-shadow-3) - (should (and (equal '(layer-shadow-1) - (oref (configuration-layer/get-layer 'layer-shadow-2) - :shadowed-by)) - (equal '(layer-shadow-1) - (oref (configuration-layer/get-layer 'layer-shadow-3) - :shadowed-by)))))) + (configuration-layer/declare-shadow-relation + 'layer-shadow-1 + 'layer-shadow-2 + 'layer-shadow-3) + (should (equal '(layer-shadow-1) + (oref (configuration-layer/get-layer 'layer-shadow-2) + :can-shadow))) + (should (equal '(layer-shadow-1) + (oref (configuration-layer/get-layer 'layer-shadow-3) + :can-shadow))) + (should (equal '(layer-shadow-3 layer-shadow-2) + (oref (configuration-layer/get-layer 'layer-shadow-1) + :can-shadow))))) -(ert-deftest test-shadow-layer--unknown-layer-shadows-existing-layer () +(ert-deftest test-declare-shadow-relation--unknown-layer-shadows-known-layer () (let ((configuration-layer--indexed-layers (make-hash-table :size 1024))) (helper--add-layers `(,(cfgl-layer "layer-shadow-2" :name 'layer-shadow-2))) @@ -1129,11 +1119,14 @@ ((configuration-layer//warning (msg &rest args) ((:record-cls 'mocker-stub-record :output nil :occur 1)))) - (configuration-layer/shadow-layer 'layer-shadow-1 'layer-shadow-2) - (should (null (oref (configuration-layer/get-layer 'layer-shadow-2) - :shadowed-by)))))) + (configuration-layer/declare-shadow-relation + 'layer-shadow-1 + 'layer-shadow-2) + (should (eq 'unspecified + (oref (configuration-layer/get-layer 'layer-shadow-2) + :can-shadow)))))) -(ert-deftest test-shadow-layer--existing-layer-shadows-non-existing-layer () +(ert-deftest test-declare-shadow-relation--known-layer-shadows-unknown-layer () (let ((configuration-layer--indexed-layers (make-hash-table :size 1024))) (helper--add-layers `(,(cfgl-layer "layer-shadow-1" :name 'layer-shadow-1))) @@ -1141,15 +1134,15 @@ ((configuration-layer//warning (msg &rest args) ((:record-cls 'mocker-stub-record :output nil :occur 1)))) - (configuration-layer/shadow-layer 'layer-shadow-1 'layer-shadow-2)))) + (configuration-layer/declare-shadow-relation 'layer-shadow-1 'layer-shadow-2)))) -(ert-deftest test-shadow-layer--unknown-layer-shadows-unknown-layer () +(ert-deftest test-declare-shadow-relation--unknown-layer-shadows-unknown-layer () (let ((configuration-layer--indexed-layers (make-hash-table :size 1024))) (mocker-let ((configuration-layer//warning (msg &rest args) ((:record-cls 'mocker-stub-record :output nil :occur 2)))) - (configuration-layer/shadow-layer 'layer-shadow-1 'layer-shadow-2)))) + (configuration-layer/declare-shadow-relation 'layer-shadow-1 'layer-shadow-2)))) ;; --------------------------------------------------------------------------- ;; configuration-layer//set-layers-variables