From 4c22789c0710a9b104d8c36e698c1e9e776b5345 Mon Sep 17 00:00:00 2001 From: Delyan Angelov Date: Wed, 12 Nov 2025 02:42:07 +0200 Subject: [PATCH] parser: warn on `@[deprecated_after]` used without a corresponding `@[deprecated]` attribute (#25712) --- vlib/v/parser/attribute.v | 24 +++++++++++++++++ .../deprecated_after_without_deprecated.out | 26 +++++++++++++++++++ .../deprecated_after_without_deprecated.vv | 14 ++++++++++ vlib/v/util/diff/diff.v | 12 +++++---- vlib/x/crypto/chacha20/chacha.v | 1 + 5 files changed, 72 insertions(+), 5 deletions(-) create mode 100644 vlib/v/parser/tests/deprecated_after_without_deprecated.out create mode 100644 vlib/v/parser/tests/deprecated_after_without_deprecated.vv diff --git a/vlib/v/parser/attribute.v b/vlib/v/parser/attribute.v index 63431c010..cc97c4db6 100644 --- a/vlib/v/parser/attribute.v +++ b/vlib/v/parser/attribute.v @@ -158,6 +158,8 @@ fn (mut p Parser) attributes() { if p.attrs.len == 0 { p.error_with_pos('attributes cannot be empty', start_pos.extend(p.tok.pos())) return + } else { + p.check_deprecated_attributes() } // TODO: remove when old attr syntax is removed if p.inside_struct_attr_decl && p.tok.kind == .lsbr { @@ -170,3 +172,25 @@ fn (mut p Parser) attributes() { return } } + +fn (mut p Parser) check_deprecated_attributes() { + mut deprecated := false + mut deprecated_after := false + mut deprecated_after_pos := token.Pos{} + for attr in p.attrs { + match attr.name { + 'deprecated' { + deprecated = true + } + 'deprecated_after' { + deprecated_after = true + deprecated_after_pos = attr.pos + } + else {} + } + } + if deprecated_after && !deprecated { + p.warn_with_pos('@[deprecated_after] is only valid, in the presence of a `@[deprecated]` attribute', + deprecated_after_pos) + } +} diff --git a/vlib/v/parser/tests/deprecated_after_without_deprecated.out b/vlib/v/parser/tests/deprecated_after_without_deprecated.out new file mode 100644 index 000000000..2c1c178b8 --- /dev/null +++ b/vlib/v/parser/tests/deprecated_after_without_deprecated.out @@ -0,0 +1,26 @@ +vlib/v/parser/tests/deprecated_after_without_deprecated.vv:1:1: warning: @[deprecated_after] is only valid, in the presence of a `@[deprecated]` attribute + 1 | @[deprecated_after: '2025-10-10'] + | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + 2 | fn my_fn() { + 3 | } +vlib/v/parser/tests/deprecated_after_without_deprecated.vv:5:1: warning: @[deprecated_after] is only valid, in the presence of a `@[deprecated]` attribute + 3 | } + 4 | + 5 | @[deprecated_after: '2025-10-10'] + | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + 6 | const my_const = 123 + 7 | +vlib/v/parser/tests/deprecated_after_without_deprecated.vv:8:1: warning: @[deprecated_after] is only valid, in the presence of a `@[deprecated]` attribute + 6 | const my_const = 123 + 7 | + 8 | @[deprecated_after: '2025-10-10'] + | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + 9 | type MyType = u8 + 10 | +vlib/v/parser/tests/deprecated_after_without_deprecated.vv:11:1: warning: @[deprecated_after] is only valid, in the presence of a `@[deprecated]` attribute + 9 | type MyType = u8 + 10 | + 11 | @[deprecated_after: '2025-10-10'] + | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + 12 | interface MyInterface { + 13 | x int diff --git a/vlib/v/parser/tests/deprecated_after_without_deprecated.vv b/vlib/v/parser/tests/deprecated_after_without_deprecated.vv new file mode 100644 index 000000000..883b32e9b --- /dev/null +++ b/vlib/v/parser/tests/deprecated_after_without_deprecated.vv @@ -0,0 +1,14 @@ +@[deprecated_after: '2025-10-10'] +fn my_fn() { +} + +@[deprecated_after: '2025-10-10'] +const my_const = 123 + +@[deprecated_after: '2025-10-10'] +type MyType = u8 + +@[deprecated_after: '2025-10-10'] +interface MyInterface { + x int +} diff --git a/vlib/v/util/diff/diff.v b/vlib/v/util/diff/diff.v index 633bfab7a..7af32c5d1 100644 --- a/vlib/v/util/diff/diff.v +++ b/vlib/v/util/diff/diff.v @@ -43,30 +43,32 @@ pub enum DiffTool { @[params] pub struct CompareOptions { pub: - tool DiffTool @[deprecated_after: '2025-12-31'] + tool DiffTool @[deprecated: 'use compare_files or compare_text'; deprecated_after: '2025-12-31'] // Custom args used with the diff command. - args string @[deprecated_after: '2025-12-31'] + args string @[deprecated: 'use compare_files or compare_text'; deprecated_after: '2025-12-31'] // Sets the environment variable whose value can overwrite a diff command passed to a compare function. // It also enables the use of commands that are not in the list of known diff tools. // Set it to `none` to disable it. - env_overwrite_var ?string = 'VDIFF_CMD' @[deprecated_after: '2025-12-31'] + env_overwrite_var ?string = 'VDIFF_CMD' @[deprecated: 'use compare_files or compare_text'; deprecated_after: '2025-12-31'] } @[params] pub struct CompareTextOptions { CompareOptions pub: - base_name string = 'base' @[deprecated_after: '2025-12-31'] - target_name string = 'target' @[deprecated_after: '2025-12-31'] + base_name string = 'base' @[deprecated: 'use compare_files or compare_text'; deprecated_after: '2025-12-31'] + target_name string = 'target' @[deprecated: 'use compare_files or compare_text'; deprecated_after: '2025-12-31'] } // Allows public checking for the available tools and prevents repeated searches // when using compare functions with automatic diff tool detection. +@[deprecated: 'use compare_files or compare_text'] @[deprecated_after: '2025-12-31'] pub fn available_tools() []DiffTool { return [] } +@[deprecated: 'use compare_files or compare_text'] @[deprecated_after: '2025-12-31'] pub fn find_working_diff_command() !string { return error('deprecated') diff --git a/vlib/x/crypto/chacha20/chacha.v b/vlib/x/crypto/chacha20/chacha.v index f19723dbc..b86a0d0d3 100644 --- a/vlib/x/crypto/chacha20/chacha.v +++ b/vlib/x/crypto/chacha20/chacha.v @@ -189,6 +189,7 @@ pub fn (mut c Cipher) free() { // reset quickly sets all Cipher's fields to default value. // This method will be deprecated. +@[deprecated: 'do not use .reset() at all, create a new Cipher instead'] @[deprecated_after: '2025-11-30'] @[unsafe] pub fn (mut c Cipher) reset() { -- 2.39.5