Skip to content

Add unified deprecation system and @deprecated attribute#15770

Merged
cptpiepmatz merged 28 commits intonushell:mainfrom
132ikl:deprecated-attribute
Jun 1, 2025
Merged

Add unified deprecation system and @deprecated attribute#15770
cptpiepmatz merged 28 commits intonushell:mainfrom
132ikl:deprecated-attribute

Conversation

@132ikl
Copy link
Copy Markdown
Member

@132ikl 132ikl commented May 16, 2025

Description

This PR adds the ability for users to mark commands as deprecated with a @deprecated attribute. The attribute can be invoked with or without an extra explanation message.

Without a message:
image

With a message:
image

I also changed the deprecated warnings a bit to make them look a bit nicer in my opinion:

  • Added an error code (looks nicer with Warning: text)
  • Removed command name from error description (it's already in the label)
  • Removed suggestion from label and made it optional (it's already in the help text)
  • Removed backticks surrounding command names (errors seem to be split on whether they use backticks or not, but we have no special formatting for them which I think leads to unnecessary noise)
  • Removed the hardcoded "for more info see" in the help text, so users of the deprecation warning can set the help text however they would like

Here's what a previous deprecation warning looked like, for reference

image

User-Facing Changes

  • Adds the @deprecated attribute, which can be used to mark a custom command as deprecated. You can optionally supply a message to suggest a new command.

Tests + Formatting

Changed the attributes completions test to not be hard-coded (so if we add any more attributes they don't need to be manually added) and added a test for @deprecated.

  • 🟢 toolkit fmt
  • 🟢 toolkit clippy
  • 🟢 toolkit test
  • 🟢 toolkit test stdlib

After Submitting

N/A

@132ikl 132ikl requested a review from Bahex May 16, 2025 22:42
@github-actions github-actions bot added the A:parser Issues related to parsing label May 16, 2025
@132ikl 132ikl added the deprecated:pr-commands (deprecated: too vague) This PR changes our commands in some way label May 16, 2025
@Bahex
Copy link
Copy Markdown
Member

Bahex commented May 17, 2025

This only shows the warnings when deprecated commands' definitions are parsed and not on calls to the deprecated commands right?

I like the idea of @deprecated and the refactors you made, but I think we first need a way to properly handle deprecation warnings. If we decide to deprecate a command in std and use @deprecated as it is now, rather than users getting warned when they use deprecated commands, they will be warned when they import modules that contain deprecated commands.

I looked around a bit to see what's usually done when built-in commands are deprecated and they just throw a warning each time they are called and then run as usual.
I think we need a different approach where deprecated commands (let's say they are just marked by changing their category to deprecated) throw a warning when they are first called. And by called I don't mean when they run, I mean when they appear in parsed code.

# aaa.nu
@deprecated
export def foo [] { ... }
# bbb.nu
use aaa.nu
export def bar [] {
    foo
}
# repl

 use aaa.nu
# no warning

 use bbb.nu
# warning is thrown since

@132ikl
Copy link
Copy Markdown
Member Author

132ikl commented May 18, 2025

they will be warned when they import modules that contain deprecated commands

whoops, not sure how that slipped my mind. this definitely needs to happen when parsing a call, not when parsing the definition

throw a warning when they are first called

this is definitely needed, we discussed this before in the context of table->render and also lints, although i don't think we need that for an initial implementation necessary

let's say they are just marked by changing their category to deprecated

i think we need something more complex than this so we can have a message still. maybe @deprecated can just be a normal attribute, and then we check for the @deprecated attribute when we parse a call?

@Bahex
Copy link
Copy Markdown
Member

Bahex commented May 19, 2025

Yeah, a normal attribute makes more sense than a category for this since it can also store a message.

We can add a Command::is_deprecated() that for BlockCommand's is based on their attributes and can be manually implemented for built-ins.

@132ikl
Copy link
Copy Markdown
Member Author

132ikl commented May 19, 2025

just updated the PR with your suggest @Bahex. also added a "report log" (thread-global, rather than in EngineState) which lets us make sure we only report deprecation warnings (and later, lints if we decide to add those) once. It needs to be in the reporting code since we might generate the warning without reporting it (for example, while typing the command in the REPL). I'm not sure about storing the DeclId in the error itself, but it seems to be the only place which really makes sense

@132ikl 132ikl changed the title Add @deprecated attribute Add unified deprecation system and @deprecated attribute May 19, 2025
Copy link
Copy Markdown
Member

@Bahex Bahex left a comment

Choose a reason for hiding this comment

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

Wow I didn't expect this to be done so soon 🚀

Everything looks goods, and it works just as expected:

  • reporting just once in shell
  • reporting each occurrence in lsp

image

@cptpiepmatz cptpiepmatz self-requested a review May 19, 2025 19:09
@132ikl
Copy link
Copy Markdown
Member Author

132ikl commented May 21, 2025

this is almost ready, just need to move the ReportLog to EngineState and also investigate how difficult it would be to expose the deprecation stuff to plugins

@132ikl
Copy link
Copy Markdown
Member Author

132ikl commented May 28, 2025

this is ready now, I moved the report log into EngineState. I investigated if it would be possible to make this available to plugins, and I think it should be possible by implementing deprecation_info for PluginDeclaration? I think we would have to store deprecation status as part of the plugin registry in order for that to work unfortunately (since we don't want to load the plugin just for deprecation status during parse-time), and that's a bit more than I can do at the moment, but I might try to revisit this later (or if anyone else wants to implement it that would also be great)

@132ikl
Copy link
Copy Markdown
Member Author

132ikl commented May 28, 2025

should be good to (re-)review @cptpiepmatz and @Bahex if you'd like to take a look

@Bahex Bahex self-requested a review May 29, 2025 02:41
Copy link
Copy Markdown
Member

@Bahex Bahex left a comment

Choose a reason for hiding this comment

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

The design and its implementation look good to me 👍

also

@deprecated --flag sensitive --since 0.104.2 --remove 0.104.4 'cell-paths are now case-sensitive by default
to make a cell-path case-insensitive add `!` after the relevant path member'
def get [ --sensitive ] { }

image

AMAZING 💯

@cptpiepmatz cptpiepmatz self-requested a review May 29, 2025 15:02
Copy link
Copy Markdown
Member

@cptpiepmatz cptpiepmatz left a comment

Choose a reason for hiding this comment

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

Great work, thank you ♥️

@cptpiepmatz cptpiepmatz merged commit cfbe835 into nushell:main Jun 1, 2025
17 checks passed
@github-actions github-actions bot added this to the v0.105.0 milestone Jun 1, 2025
Bahex added a commit that referenced this pull request Jun 1, 2025
# Description
- Use #15770 to
  - improve `get --sensitive` deprecation warning
  - add deprecation warning for `filter`
- refactor `filter` to use `where` as its implementation
- replace usages of `filter` with `where` in `std`

# User-Facing Changes
- `get --sensitive` will raise a warning only once, during parsing
whereas before it was raised during runtime for each usage.
- using `filter` will raise a deprecation warning, once

# Tests + Formatting
No existing test broke or required tweaking. Additional tests covering
this case was added.
- 🟢 toolkit fmt
- 🟢 toolkit clippy
- 🟢 toolkit test
- 🟢 toolkit test stdlib

# After Submitting
N/A

---------

Co-authored-by: Bahex <17417311+Bahex@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

A:parser Issues related to parsing deprecated:pr-commands (deprecated: too vague) This PR changes our commands in some way

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants