Skip to content

nixos/modules: Add declarationPositions#249243

Merged
roberth merged 1 commit intoNixOS:masterfrom
lf-:jade/declarationsWithLocations
Sep 17, 2023
Merged

nixos/modules: Add declarationPositions#249243
roberth merged 1 commit intoNixOS:masterfrom
lf-:jade/declarationsWithLocations

Conversation

@lf-
Copy link
Copy Markdown
Member

@lf- lf- commented Aug 15, 2023

Description of changes

What it does: line and column level declaration position information:

$ nix repl .
nix-repl> :p nixosConfigurations.micro.options.environment.systemPackages.declarationsWithLocations
[ { column = 7; file = "/nix/store/24aj3k7fgqv3ly7qkbf98qvphasrw9nb-source/nixos/modules/config/system-path.nix"; line = 63; } ]

Use cases:

  • ctags over NixOS options, as will be presented at NixCon 2023 ;)
  • improving the documentation pages to go to the exact line of the declarations.

Related work:

Benchmarks: conducted by evaluating my own reasonably complex NixOS configuration with the command:
hyperfine -S none -w 1 -- "nix eval .#nixosConfigurations.snowflake.config.system.build.toplevel.outPath"

Benchmark 1: nix eval .#nixosConfigurations.snowflake.config.system.build.toplevel.outPath
  Time (mean ± σ):      8.971 s ±  0.254 s    [User: 5.872 s, System: 1.388 s]
  Range (min … max):    8.574 s …  9.327 s    10 runs

Benchmark 1: nix eval .#nixosConfigurations.snowflake.config.system.build.toplevel.outPath
  Time (mean ± σ):      8.766 s ±  0.160 s    [User: 5.873 s, System: 1.346 s]
  Range (min … max):    8.496 s …  9.033 s    10 runs

Summary of results: it seems to be in the noise, this does not cause any visible regression in times.

Things done

  • Built on platform(s)
    • x86_64-linux
    • aarch64-linux
    • x86_64-darwin
    • aarch64-darwin
  • For non-Linux: Is sandbox = true set in nix.conf? (See Nix manual)
  • Tested, as applicable:
  • Tested compilation of all packages that depend on this change using nix-shell -p nixpkgs-review --run "nixpkgs-review rev HEAD". Note: all changes have to be committed, also see nixpkgs-review usage
  • Tested basic functionality of all binary files (usually in ./result/bin/)
  • 23.11 Release Notes (or backporting 23.05 Release notes)
    • (Package updates) Added a release notes entry if the change is major or breaking
    • (Module updates) Added a release notes entry if the change is significant
    • (Module addition) Added a release notes entry if adding a new NixOS module
  • Fits CONTRIBUTING.md.

@lf- lf- requested review from edolstra and infinisil as code owners August 15, 2023 02:27
@github-actions github-actions bot added 6.topic: module system About "NixOS" module system internals 6.topic: lib The Nixpkgs function library labels Aug 15, 2023
@ofborg ofborg bot added 10.rebuild-darwin: 0 This PR does not cause any packages to rebuild on Darwin. 10.rebuild-linux: 1-10 This PR causes between 1 and 10 packages to rebuild on Linux. labels Aug 15, 2023
@lf-
Copy link
Copy Markdown
Member Author

lf- commented Aug 15, 2023

One somewhat annoying result of this is that it will give quite useless locations for mkRenamedOptionsModule (pointing to the definition of lib.setAttrByPath). However this is really unavoidable, since that is the proximate source of that attrset.

nix-repl> :p nixos.options.boot.binfmtMiscRegistrations.declarationsWithLocations 
[ { column = 16; file = "/home/jade/dev/nixpkgs/lib/attrsets.nix"; line = 88; } ]

I haven't found any other bugs. I would also consider this one a non-bug, since as far as I know, all the users here ignore such options anyway.

@lf-
Copy link
Copy Markdown
Member Author

lf- commented Aug 15, 2023

OK, I found another bug: cleverly defined options such as programs.firefox.nativeMessagingHosts.ff2mpvand services.thanos.query.query.max-concurrent from dynamically generated modules have a null location. This is kind of reasonable; but what should the API actually do here?

I think the most useful thing to do is to just use the old file name as a fallback and either: {file = "blah.nix"; line = 1; column = 1;}, or {file = "blah.nix"; line = null; column = null;}. Thoughts on which one is a better idea?

Copy link
Copy Markdown
Member

@infinisil infinisil left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is nice!

One somewhat annoying result of this is that it will give quite useless locations for mkRenamedOptionsModule (pointing to the definition of lib.setAttrByPath)

OK, I found another bug: cleverly defined options such as programs.firefox.nativeMessagingHosts.ff2mpvand services.thanos.query.query.max-concurrent from dynamically generated modules have a null location.

I think it would be great to have a mkOption argument to set the option location manually for such cases. It could later be enforced by the manual build for all options to have a location. But this could be a future PR.

I think the most useful thing to do is to just use the old file name as a fallback and either: {file = "blah.nix"; line = 1; column = 1;}, or {file = "blah.nix"; line = null; column = null;}. Thoughts on which one is a better idea?

The latter definitely, otherwise it's not distinguishable whether the location was determined or not.

In addition, this could benefit from a bit more testing :)

@lf- lf- force-pushed the jade/declarationsWithLocations branch from 997f76f to ed08e82 Compare August 20, 2023 21:38
@lf- lf- requested a review from infinisil August 20, 2023 21:40
@lf-
Copy link
Copy Markdown
Member Author

lf- commented Aug 20, 2023

alright, applied all the suggestions. Thanks for the review!

@roberth
Copy link
Copy Markdown
Member

roberth commented Aug 26, 2023

I think it would be great to have a mkOption argument

+1

Something along the lines of

{ pos ? unsafeGetAttrPos args "description", /*...*/ }: { inherit pos; /* ... */ } could do the job in mkOption I suppose.

It could be set explicitly in mkRe* and mkEnableOption.

I'd expect that to cover almost everything. I don't find enforcement of positions particularly important. Might even be unproductive for module authors, if it's even relevant at all.

@lf- lf- force-pushed the jade/declarationsWithLocations branch from ed08e82 to c745c0b Compare August 28, 2023 23:53
@lf- lf- requested a review from roberth August 28, 2023 23:54
@lf- lf- changed the title nixos/modules: Add declarationsWithLocations nixos/modules: Add declarationPositions Aug 28, 2023
@lf- lf- force-pushed the jade/declarationsWithLocations branch from c745c0b to 26a5174 Compare August 29, 2023 07:22
Copy link
Copy Markdown
Member

@roberth roberth left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A design question and some test suggestions.
Definitely on the right track though!

lib/modules.nix Outdated
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we fall back to the position of the parent, somewhat similar to what we do with _file in imports? (where the imports relation corresponds to the option nesting relation, and the partiality comes from anonymous modules or generated options attrs, resp.)

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not necessarily, since we get garbage for a lot of options anyway, so this wouldn't improve that much I don't think.

dev/nixpkgs2 » rg attrsets.nix ../nixpkgs/opts-tags | wc -l
957
dev/nixpkgs2 » cat ../nixpkgs/opts-tags | wc -l
11201

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Depends on the question in the other comment. We could fall back to the parent's position.

@lf- lf- force-pushed the jade/declarationsWithLocations branch from 26a5174 to c10e207 Compare September 8, 2023 09:48
What it does: line and column level *declaration* position information:

$ nix repl .
nix-repl> :p nixosConfigurations.micro.options.environment.systemPackages.declarationPositions
[ { column = 7; file = "/nix/store/24aj3k7fgqv3ly7qkbf98qvphasrw9nb-source/nixos/modules/config/system-path.nix"; line = 63; } ]

Use cases:
- ctags over NixOS options, as will be presented at NixCon 2023 ;)
- improving the documentation pages to go to the exact line of the
  declarations.

Related work:
- NixOS#65024

  This one does it for all *definitions* rather than declarations, and
  it was not followed through with due to performance worries.
- NixOS#208173

  The basis for this change. This change is just a rebase of that one.
  I split it out to add the capability before adding users of it, in
  order to simplify review. However, the ctags script in there is a
  sample user of this feature.

Benchmarks: conducted by evaluating my own reasonably complex NixOS
configuration with the command:
`hyperfine -S none -w 1 -- "nix eval .#nixosConfigurations.snowflake.config.system.build.toplevel.outPath"`

```
Benchmark 1: nix eval .#nixosConfigurations.snowflake.config.system.build.toplevel.outPath
  Time (mean ± σ):      8.971 s ±  0.254 s    [User: 5.872 s, System: 1.388 s]
  Range (min … max):    8.574 s …  9.327 s    10 runs

Benchmark 1: nix eval .#nixosConfigurations.snowflake.config.system.build.toplevel.outPath
  Time (mean ± σ):      8.766 s ±  0.160 s    [User: 5.873 s, System: 1.346 s]
  Range (min … max):    8.496 s …  9.033 s    10 runs
```

Summary of results: it seems to be in the noise, this does not cause any
visible regression in times.
@lf- lf- force-pushed the jade/declarationsWithLocations branch from c10e207 to a1d3882 Compare September 8, 2023 09:48
@lf-
Copy link
Copy Markdown
Member Author

lf- commented Sep 15, 2023

@roberth sorry I missed you at NixCon, I was running around with my hair metaphorically on fire on the hackday. I think this may be mergeable, or at least, I am not sure how to improve it further.

@delroth delroth added the 12.approvals: 1 This PR was reviewed and approved by one person. label Sep 17, 2023
@roberth
Copy link
Copy Markdown
Member

roberth commented Sep 17, 2023

hair metaphorically on fire

Kinda same. No need to apologize!

@roberth roberth merged commit 00e5487 into NixOS:master Sep 17, 2023
lf- added a commit to lf-/nixpkgs that referenced this pull request Jan 7, 2024
This is rather a strawman of a PR to try to figure out the best spot to
put this code and the documentation of how to use it. I don't really
know.

Sample content:
```
!_TAG_FILE_SORTED	1	1
!_TAG_FILE_ENCODING	utf-8	1
_module.args	/home/jade/dev/nixpkgs/lib/modules.nix	122
_module.check	/home/jade/dev/nixpkgs/lib/modules.nix	186
_module.freeformType	/home/jade/dev/nixpkgs/lib/modules.nix	193
_module.specialArgs	/home/jade/dev/nixpkgs/lib/modules.nix	209
appstream.enable	/home/jade/dev/nixpkgs/nixos/modules/config/appstream.nix	6
assertions	/home/jade/dev/nixpkgs/nixos/modules/misc/assertions.nix	9
boot.binfmt.emulatedSystems	/home/jade/dev/nixpkgs/nixos/modules/system/boot/binfmt.nix	272
```

Sample usage (can be used in parallel with `nix-doc tags`):
```
nix build -f nixos/release.nix optionsCtags -o opts-tags
(in vim): :set tags+=opts-tags
          :tj boot.binfmt.emulatedSystems
```

This PR depends on and contains NixOS#249243. Marked as draft till that's
worked out. This PR pair replaces NixOS#208173.
philiptaron pushed a commit to philiptaron/nixpkgs that referenced this pull request Mar 4, 2024
This is rather a strawman of a PR to try to figure out the best spot to
put this code and the documentation of how to use it. I don't really
know.

Sample content:
```
!_TAG_FILE_SORTED	1	1
!_TAG_FILE_ENCODING	utf-8	1
_module.args	/home/jade/dev/nixpkgs/lib/modules.nix	122
_module.check	/home/jade/dev/nixpkgs/lib/modules.nix	186
_module.freeformType	/home/jade/dev/nixpkgs/lib/modules.nix	193
_module.specialArgs	/home/jade/dev/nixpkgs/lib/modules.nix	209
appstream.enable	/home/jade/dev/nixpkgs/nixos/modules/config/appstream.nix	6
assertions	/home/jade/dev/nixpkgs/nixos/modules/misc/assertions.nix	9
boot.binfmt.emulatedSystems	/home/jade/dev/nixpkgs/nixos/modules/system/boot/binfmt.nix	272
```

Sample usage (can be used in parallel with `nix-doc tags`):
```
nix build -f nixos/release.nix optionsCtags -o opts-tags
(in vim): :set tags+=opts-tags
          :tj boot.binfmt.emulatedSystems
```

This PR depends on and contains NixOS#249243. Marked as draft till that's
worked out. This PR pair replaces NixOS#208173.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

6.topic: lib The Nixpkgs function library 6.topic: module system About "NixOS" module system internals 10.rebuild-darwin: 0 This PR does not cause any packages to rebuild on Darwin. 10.rebuild-linux: 1-10 This PR causes between 1 and 10 packages to rebuild on Linux. 12.approvals: 1 This PR was reviewed and approved by one person.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants