@ -9,7 +9,7 @@ let
catAttrs
concatLists
concatMap
cou nt
conca tStringsSep
elem
filter
findFirst
@ -47,6 +47,20 @@ let
showOption
unknownModule
;
showDeclPrefix = loc : decl : prefix :
" - o p t i o n ( s ) w i t h p r e f i x ` ${ showOption ( loc ++ [ prefix ] ) } ' i n m o d u l e ` ${ decl . _file } ' " ;
showRawDecls = loc : decls :
concatStringsSep " \n "
( sort ( a : b : a < b )
( concatMap
( decl : map
( showDeclPrefix loc decl )
( attrNames decl . options )
)
decls
) ) ;
in
rec {
@ -474,26 +488,61 @@ rec {
[ { inherit ( module ) file ; inherit value ; } ]
) configs ;
# Convert an option tree decl to a submodule option decl
optionTreeToOption = decl :
if isOption decl . options
then decl
else decl // {
options = mkOption {
type = types . submoduleWith {
modules = [ { options = decl . options ; } ] ;
# `null` is not intended for use by modules. It is an internal
# value that means "whatever the user has declared elsewhere".
# This might become obsolete with https://github.com/NixOS/nixpkgs/issues/162398
shorthandOnlyDefinesConfig = null ;
} ;
} ;
} ;
resultsByName = mapAttrs ( name : decls :
# We're descending into attribute ‘name’.
let
loc = prefix ++ [ name ] ;
defns = defnsByName . ${ name } or [ ] ;
defns' = defnsByName' . ${ name } or [ ] ;
nrOptions = count ( m : isOption m . options ) decls ;
optionDecls = filter ( m : isOption m . options ) decls ;
in
if nrOptions == length decls then
if length optionDecl s == length decls then
let opt = fixupOptionType loc ( mergeOptionDecls loc decls ) ;
in {
matchedOptions = evalOptionValue loc opt defns' ;
unmatchedDefns = [ ] ;
}
else if nrOptions != 0 then
let
firstOption = findFirst ( m : isOption m . options ) " " decls ;
firstNonOption = findFirst ( m : ! isOption m . options ) " " decls ;
in
throw " T h e o p t i o n ` ${ showOption loc } ' i n ` ${ firstOption . _file } ' i s a p r e f i x o f o p t i o n s i n ` ${ firstNonOption . _file } ' . "
else if optionDecls != [ ] then
if all ( x : x . options . type . name == " s u b m o d u l e " ) optionDecls
# Raw options can only be merged into submodules. Merging into
# attrsets might be nice, but ambiguous. Suppose we have
# attrset as a `attrsOf submodule`. User declares option
# attrset.foo.bar, this could mean:
# a. option `bar` is only available in `attrset.foo`
# b. option `foo.bar` is available in all `attrset.*`
# c. reject and require "<name>" as a reminder that it behaves like (b).
# d. magically combine (a) and (c).
# All of the above are merely syntax sugar though.
then
let opt = fixupOptionType loc ( mergeOptionDecls loc ( map optionTreeToOption decls ) ) ;
in {
matchedOptions = evalOptionValue loc opt defns' ;
unmatchedDefns = [ ] ;
}
else
let
firstNonOption = findFirst ( m : ! isOption m . options ) " " decls ;
nonOptions = filter ( m : ! isOption m . options ) decls ;
in
throw " T h e o p t i o n ` ${ showOption loc } ' i n m o d u l e ` ${ ( lib . head optionDecls ) . _file } ' w o u l d b e a p a r e n t o f t h e f o l l o w i n g o p t i o n s , b u t i t s t y p e ` ${ ( lib . head optionDecls ) . options . type . description or " < n o d e s c r i p t i o n > " } ' d o e s n o t s u p p o r t n e s t e d o p t i o n s . \n ${
showRawDecls loc nonOptions
} "
else
mergeModules' loc decls defns ) declsByName ;
@ -753,13 +802,14 @@ rec {
compare = a : b : ( a . priority or 1000 ) < ( b . priority or 1000 ) ;
in sort compare defs' ;
/* H a c k f o r b a c k w a r d c o m p a t i b i l i t y : c o n v e r t o p t i o n s o f t y p e
optionSet to options of type submodule . FIXME : remove
eventually . * /
fixupOptionType = loc : opt :
let
options = opt . options or
( throw " O p t i o n ` ${ showOption loc } ' h a s t y p e o p t i o n S e t b u t h a s n o o p t i o n a t t r i b u t e , i n ${ showFiles opt . declarations } . " ) ;
# Hack for backward compatibility: convert options of type
# optionSet to options of type submodule. FIXME: remove
# eventually.
f = tp :
if tp . name == " o p t i o n s e t " || tp . name == " s u b m o d u l e " then
throw " T h e o p t i o n ${ showOption loc } u s e s s u b m o d u l e s w i t h o u t a w r a p p i n g t y p e , i n ${ showFiles opt . declarations } . "