From ed1f34d8a3bf079580f06654935d40330a5f450b Mon Sep 17 00:00:00 2001 From: Daniil Polyakov Date: Mon, 4 Nov 2024 18:30:13 +0300 Subject: [PATCH] Prefer expect instead of allow & fix some lints --- Cargo.toml | 4 +- crypto/Cargo.toml | 2 +- crypto/src/lib.rs | 6 +- password_storage/src/grpc.rs | 10 +-- password_storage/src/lib.rs | 2 +- password_storage/src/main.rs | 6 +- password_storage/src/service.rs | 4 +- password_storage/src/service/cache.rs | 4 +- password_storage/src/service/cache/rated.rs | 2 +- telegram_gate/build.rs | 2 +- telegram_gate/src/button.rs | 19 +++--- telegram_gate/src/command.rs | 4 +- telegram_gate/src/context.rs | 5 ++ telegram_gate/src/grpc.rs | 14 ++-- telegram_gate/src/main.rs | 3 +- telegram_gate/src/message.rs | 18 ++--- telegram_gate/src/state.rs | 11 +--- .../src/state/delete_confirmation.rs | 7 +- telegram_gate/src/state/main_menu.rs | 4 +- telegram_gate/src/state/resource_actions.rs | 4 +- telegram_gate/src/state/resources_list.rs | 2 +- telegram_gate/src/test_utils.rs | 2 +- telegram_gate/src/test_utils/mock_bot.rs | 3 - web_app/src/components/common.rs | 65 +++++++++++++++---- web_app/src/components/show.rs | 28 +++++--- web_app/src/components/submit.rs | 7 +- web_app/src/main.rs | 5 +- web_app/src/tg_api.rs | 6 -- 28 files changed, 146 insertions(+), 103 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 28c405d..8689026 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -33,6 +33,9 @@ mockall = { version = "0.13.0", features = ["nightly"] } mockall_double = "0.3.1" base64 = "0.22.1" +[workspace.lints.rust] +warnings = "deny" + [workspace.lints] clippy.all = { level = "deny", priority = -1 } clippy.pedantic = { level = "deny", priority = -1 } @@ -45,7 +48,6 @@ clippy.perf = { level = "deny", priority = -1 } clippy.suspicious = { level = "deny", priority = -1 } clippy.style = { level = "deny", priority = -1 } -clippy.allow_attributes = "allow" clippy.cfg_not_test = "allow" clippy.blanket-clippy-restriction-lints = "allow" clippy.implicit-return = "allow" diff --git a/crypto/Cargo.toml b/crypto/Cargo.toml index 23b1f71..af6c9b8 100644 --- a/crypto/Cargo.toml +++ b/crypto/Cargo.toml @@ -23,5 +23,5 @@ workspace = true aes-gcm = { version = "0.10.3", optional = true } pbkdf2 = { version = "0.12.2", features = ["std", "parallel", "hmac"], optional = true } sha2 = { version = "0.10.8", optional = true } -serde.workspace = true +serde = { workspace = true, features = ["derive"] } thiserror.workspace = true diff --git a/crypto/src/lib.rs b/crypto/src/lib.rs index f07ea9d..6a5ca66 100644 --- a/crypto/src/lib.rs +++ b/crypto/src/lib.rs @@ -1,7 +1,5 @@ //! Crate for passwords encryption and decryption used in Telepass. -#![allow(clippy::assertions_on_constants, reason = "health checks")] - use std::string::FromUtf8Error; #[cfg(feature = "impls")] @@ -126,7 +124,7 @@ fn derive_key(password: &str) -> Key { #[cfg(test)] #[cfg(feature = "impls")] mod tests { - #![allow(clippy::expect_used, reason = "it's ok in tests")] + #![expect(clippy::expect_used, reason = "it's ok in tests")] use super::*; @@ -183,7 +181,7 @@ mod tests { } #[test] - #[allow(clippy::indexing_slicing, reason = "it's ok in tests")] + #[expect(clippy::indexing_slicing, reason = "it's ok in tests")] fn decrypt_with_wrong_payload_fails() { let payload = "payload"; let password = "password"; diff --git a/password_storage/src/grpc.rs b/password_storage/src/grpc.rs index fe111ee..4e6ed8f 100644 --- a/password_storage/src/grpc.rs +++ b/password_storage/src/grpc.rs @@ -1,20 +1,22 @@ //! Module with generated `gRPC` code. -#![allow( +#![expect( clippy::empty_structs_with_brackets, clippy::similar_names, clippy::default_trait_access, clippy::too_many_lines, clippy::clone_on_ref_ptr, - clippy::shadow_unrelated, - clippy::unwrap_used, clippy::missing_const_for_fn, - clippy::missing_docs_in_private_items, clippy::allow_attributes_without_reason, clippy::as_conversions, clippy::derive_partial_eq_without_eq, + clippy::allow_attributes, reason = "generated code" )] +#![allow( + clippy::missing_docs_in_private_items, + reason = "allow because it's false positive unfulfilled-lint-expectations if in expect" +)] tonic::include_proto!("password_storage"); diff --git a/password_storage/src/lib.rs b/password_storage/src/lib.rs index af83345..90d118a 100644 --- a/password_storage/src/lib.rs +++ b/password_storage/src/lib.rs @@ -3,6 +3,6 @@ pub mod grpc; pub mod models; /// Module with database schema generated by `diesel` -#[allow(clippy::single_char_lifetime_names, reason = "generated code")] +#[expect(clippy::single_char_lifetime_names, reason = "generated code")] pub mod schema; pub mod service; diff --git a/password_storage/src/main.rs b/password_storage/src/main.rs index fba7950..c26f6f4 100644 --- a/password_storage/src/main.rs +++ b/password_storage/src/main.rs @@ -37,7 +37,7 @@ async fn main() -> Result<()> { let password_storage = PasswordStorageServer::new(service::PasswordStorage::new(&database_url, cache_size)?); - #[allow(unused_mut, reason = "used in conditional compilation")] + #[expect(unused_mut, reason = "used in conditional compilation")] let mut server = Server::builder(); let (mut health_reporter, health_service) = tonic_health::server::health_reporter(); @@ -76,7 +76,7 @@ async fn main() -> Result<()> { /// /// Returns a [`Receiver`](tokio::sync::oneshot::Receiver) that will /// receive a shutdown message when program receive some kind of termination signal from OS. -#[allow( +#[expect( clippy::panic, clippy::expect_used, clippy::panic_in_result_fn, @@ -103,7 +103,7 @@ fn init_signal_handler() -> Result> { /// Receive shutdown signal from `rx`. /// /// Implemented as a function, because async closures are not yet supported. -#[allow(clippy::expect_used, reason = "should never happen")] +#[expect(clippy::expect_used, reason = "should never happen")] async fn recv_shutdown(rx: tokio::sync::oneshot::Receiver<()>) { rx.await.expect("Shutdown signal sender dropped"); } diff --git a/password_storage/src/service.rs b/password_storage/src/service.rs index 88bbd4e..af2256c 100644 --- a/password_storage/src/service.rs +++ b/password_storage/src/service.rs @@ -73,7 +73,7 @@ impl WithContextExt for diesel::result::Error { } } -#[allow( +#[expect( clippy::wildcard_enum_match_arm, reason = "only exact variants are needed" )] @@ -187,7 +187,7 @@ impl grpc::password_storage_server::PasswordStorage for PasswordStorage { } #[instrument(skip(self))] - #[allow(clippy::panic, reason = "should never happen")] + #[expect(clippy::panic, reason = "should never happen")] async fn delete( &self, request: Request, diff --git a/password_storage/src/service/cache.rs b/password_storage/src/service/cache.rs index ba60d82..ae19e99 100644 --- a/password_storage/src/service/cache.rs +++ b/password_storage/src/service/cache.rs @@ -88,7 +88,7 @@ impl Cache { /// Creates new [`Cache`] instance with max size `size` and pre-loaded `records`. /// /// All records after `size - 1` index will be ignored. - #[allow(clippy::expect_used, reason = "u32 to usize conversion is safe")] + #[expect(clippy::expect_used, reason = "u32 to usize conversion is safe")] pub fn load(size: u32, records: impl IntoIterator) -> Self { let size = size .try_into() @@ -164,7 +164,7 @@ impl Cache { } #[cfg(test)] -#[allow(clippy::unwrap_used, clippy::panic, reason = "it's ok in tests")] +#[expect(clippy::unwrap_used, clippy::panic, reason = "it's ok in tests")] mod tests { use std::convert::Infallible; diff --git a/password_storage/src/service/cache/rated.rs b/password_storage/src/service/cache/rated.rs index a3d5117..426f547 100644 --- a/password_storage/src/service/cache/rated.rs +++ b/password_storage/src/service/cache/rated.rs @@ -1,7 +1,7 @@ //! Module with [`Set`] that stores only specified number of records, replacing the least popular //! one on insertion. -#![allow( +#![expect( clippy::expect_used, clippy::unwrap_in_result, reason = "used to indicate programmer errors" diff --git a/telegram_gate/build.rs b/telegram_gate/build.rs index 282addc..146c377 100644 --- a/telegram_gate/build.rs +++ b/telegram_gate/build.rs @@ -8,7 +8,7 @@ fn main() -> Result<()> { .build_client(true) .client_mod_attribute( "password_storage", - "#[allow(clippy::missing_docs_in_private_items)]", + "#[expect(clippy::missing_docs_in_private_items)]", ) .compile_protos(&["../proto/password_storage.proto"], &["../proto"]) .map_err(Into::into) diff --git a/telegram_gate/src/button.rs b/telegram_gate/src/button.rs index 2edbe58..b53a7b3 100644 --- a/telegram_gate/src/button.rs +++ b/telegram_gate/src/button.rs @@ -2,8 +2,6 @@ //! //! Button means inline button attached to a message. -#![allow(clippy::non_ascii_literal, reason = "emojis are allowed")] - use derive_more::From; use parse_display::{Display, FromStr}; @@ -24,7 +22,7 @@ impl ButtonBox { /// # Errors /// /// Fails if `data` does not correspond to any valid button [`kind`]. - #[allow(clippy::map_err_ignore, reason = "not interested in exact parse error")] + #[expect(clippy::map_err_ignore, reason = "not interested in exact parse error")] pub fn new( message: TelegramMessage, data: &str, @@ -39,9 +37,13 @@ impl ButtonBox { } #[cfg(test)] -#[allow( - clippy::multiple_inherent_impl, - reason = "better looking conditional compilation" +#[cfg_attr(test, allow(clippy::allow_attributes, reason = "false positive"))] +#[cfg_attr( + test, + allow( + clippy::multiple_inherent_impl, + reason = "better looking conditional compilation" + ) )] impl ButtonBox { #[must_use] @@ -128,11 +130,12 @@ pub mod kind { #[cfg(test)] mod tests { - #![allow(clippy::unwrap_used, reason = "it's ok in tests")] + #![expect(clippy::unwrap_used, reason = "it's ok in tests")] + #![expect(clippy::non_ascii_literal, reason = "emojis are allowed")] use super::*; - #[allow( + #[expect( dead_code, unreachable_code, unused_variables, diff --git a/telegram_gate/src/command.rs b/telegram_gate/src/command.rs index 052aa67..43f1b9a 100644 --- a/telegram_gate/src/command.rs +++ b/telegram_gate/src/command.rs @@ -70,11 +70,11 @@ blank_from_str!(Help, Start, Cancel); #[cfg(test)] mod tests { - #![allow(clippy::unwrap_used, reason = "it's ok in tests")] + #![expect(clippy::unwrap_used, reason = "it's ok in tests")] use super::*; - #[allow( + #[expect( dead_code, unreachable_code, unused_variables, diff --git a/telegram_gate/src/context.rs b/telegram_gate/src/context.rs index b857de8..e88af15 100644 --- a/telegram_gate/src/context.rs +++ b/telegram_gate/src/context.rs @@ -1,5 +1,10 @@ //! Module with [`Context`] structure to pass values and dependencies between different states. +#![allow( + clippy::allow_attributes, + reason = "mockall is really bad at placing expects in the right place" +)] + #[cfg(test)] use mockall::automock; use url::Url; diff --git a/telegram_gate/src/grpc.rs b/telegram_gate/src/grpc.rs index ddcf454..a4e18c9 100644 --- a/telegram_gate/src/grpc.rs +++ b/telegram_gate/src/grpc.rs @@ -1,20 +1,18 @@ //! Module with `gRPC` client for `password_storage` service -#![allow( +#![expect( clippy::empty_structs_with_brackets, - clippy::similar_names, - clippy::default_trait_access, - clippy::too_many_lines, - clippy::clone_on_ref_ptr, - clippy::shadow_unrelated, - clippy::unwrap_used, clippy::missing_errors_doc, clippy::future_not_send, clippy::allow_attributes_without_reason, - clippy::mixed_attributes_style, clippy::derive_partial_eq_without_eq, reason = "generated code" )] +#![allow( + clippy::missing_docs_in_private_items, + unfulfilled_lint_expectations, + reason = "allow because it's false positive unfulfilled-lint-expectations if in expect" +)] tonic::include_proto!("password_storage"); diff --git a/telegram_gate/src/main.rs b/telegram_gate/src/main.rs index 6c4b97a..867056b 100644 --- a/telegram_gate/src/main.rs +++ b/telegram_gate/src/main.rs @@ -1,7 +1,6 @@ //! Telegram Gate controls the bot using Telegram API. #![cfg(feature = "executable")] -#![allow(clippy::panic, reason = "indicates programmer error")] use std::{str::FromStr as _, sync::Arc}; @@ -130,7 +129,7 @@ async fn message_handler( } #[instrument(skip(bot, state_storage, storage_client))] -#[allow(clippy::significant_drop_tightening, reason = "false positive")] +#[expect(clippy::significant_drop_tightening, reason = "false positive")] async fn button_callback_handler( bot: Bot, query: CallbackQuery, diff --git a/telegram_gate/src/message.rs b/telegram_gate/src/message.rs index 49afe93..d4a03e4 100644 --- a/telegram_gate/src/message.rs +++ b/telegram_gate/src/message.rs @@ -1,7 +1,5 @@ //! This module contains strongly-typed messages user can send. -#![allow(clippy::non_ascii_literal, reason = "emojis are allowed")] - use std::str::FromStr; use derive_more::From; @@ -29,7 +27,7 @@ impl MessageBox { /// /// Returns [`None`] if message is of unsupported kind. #[must_use] - #[allow( + #[expect( clippy::wildcard_enum_match_arm, reason = "only exact variants are needed" )] @@ -61,9 +59,13 @@ impl MessageBox { } #[cfg(test)] -#[allow( - clippy::multiple_inherent_impl, - reason = "better looking conditional compilation" +#[cfg_attr(test, allow(clippy::allow_attributes, reason = "false positive"))] +#[cfg_attr( + test, + allow( + clippy::multiple_inherent_impl, + reason = "better looking conditional compilation" + ) )] impl MessageBox { #[must_use] @@ -141,11 +143,11 @@ pub mod kind { #[cfg(test)] mod tests { - #![allow(clippy::unwrap_used, reason = "it's ok in tests")] + #![expect(clippy::non_ascii_literal, reason = "emojis are allowed")] use super::*; - #[allow( + #[expect( dead_code, unreachable_code, unused_variables, diff --git a/telegram_gate/src/state.rs b/telegram_gate/src/state.rs index 3691cdb..8765042 100644 --- a/telegram_gate/src/state.rs +++ b/telegram_gate/src/state.rs @@ -1,6 +1,6 @@ //! Contains strongly-typed states of the [`Dialogue`](super::Dialogue). -#![allow(clippy::non_ascii_literal, reason = "messages may contain emojis")] +#![expect(clippy::non_ascii_literal, reason = "messages may contain emojis")] #[cfg(test)] use std::sync::Arc; @@ -379,16 +379,11 @@ impl + Send> TryFromTransition for T { #[cfg(test)] mod tests { - #![allow( - clippy::unwrap_used, - clippy::expect_used, - clippy::panic, - reason = "it's ok in tests" - )] + #![expect(clippy::panic, reason = "it's ok in tests")] use super::*; - #[allow( + #[expect( dead_code, unreachable_code, unused_variables, diff --git a/telegram_gate/src/state/delete_confirmation.rs b/telegram_gate/src/state/delete_confirmation.rs index e369c73..11e6ff0 100644 --- a/telegram_gate/src/state/delete_confirmation.rs +++ b/telegram_gate/src/state/delete_confirmation.rs @@ -155,12 +155,7 @@ impl TryFromTransition> for Delete #[cfg(test)] pub mod tests { - #![allow( - clippy::panic, - clippy::unwrap_used, - clippy::expect_used, - reason = "it's ok in tests" - )] + #![expect(clippy::panic, clippy::unwrap_used, reason = "it's ok in tests")] pub mod command { use tokio::test; diff --git a/telegram_gate/src/state/main_menu.rs b/telegram_gate/src/state/main_menu.rs index be2e6cf..6cf06eb 100644 --- a/telegram_gate/src/state/main_menu.rs +++ b/telegram_gate/src/state/main_menu.rs @@ -56,7 +56,7 @@ impl MainMenu { } /// [`setup()`](Self::setup) and [`setup_destroying()`](Self::setup_destroying) implementation. - #[allow(clippy::expect_used, reason = "indicates programmer error")] + #[expect(clippy::expect_used, reason = "indicates programmer error")] async fn setup_impl(context: &Context) -> Result { let buttons = [ [KeyboardButton::new(message::kind::List.to_string())], @@ -196,7 +196,7 @@ impl TryFromTransition> for MainMe #[cfg(test)] pub mod tests { - #![allow(clippy::unwrap_used, clippy::expect_used, reason = "it's ok in tests")] + #![expect(clippy::unwrap_used, clippy::expect_used, reason = "it's ok in tests")] pub mod command { use teloxide::types::{KeyboardButton, KeyboardMarkup}; diff --git a/telegram_gate/src/state/resource_actions.rs b/telegram_gate/src/state/resource_actions.rs index 66e9d68..f20ca6d 100644 --- a/telegram_gate/src/state/resource_actions.rs +++ b/telegram_gate/src/state/resource_actions.rs @@ -154,7 +154,7 @@ impl ResourceActions { } /// Construct keyboard with possible actions for a resource. - #[allow(clippy::expect_used, reason = "indicates programmer error")] + #[expect(clippy::expect_used, reason = "indicates programmer error")] fn construct_actions_keyboard( record: &grpc::Record, context: &Context, @@ -245,7 +245,7 @@ impl TryFromTransition> for Resourc #[cfg(test)] pub mod tests { - #![allow(clippy::panic, clippy::unwrap_used, reason = "it's ok in tests")] + #![expect(clippy::panic, clippy::unwrap_used, reason = "it's ok in tests")] pub mod command { use tokio::test; diff --git a/telegram_gate/src/state/resources_list.rs b/telegram_gate/src/state/resources_list.rs index 5fe7581..19d6ed4 100644 --- a/telegram_gate/src/state/resources_list.rs +++ b/telegram_gate/src/state/resources_list.rs @@ -227,7 +227,7 @@ impl TryFromTransition for ResourcesList { #[cfg(test)] pub mod tests { - #![allow(clippy::unwrap_used, reason = "it's ok in tests")] + #![expect(clippy::unwrap_used, reason = "it's ok in tests")] pub mod command { use std::{future::ready, sync::Arc}; diff --git a/telegram_gate/src/test_utils.rs b/telegram_gate/src/test_utils.rs index 1e8c439..e658725 100644 --- a/telegram_gate/src/test_utils.rs +++ b/telegram_gate/src/test_utils.rs @@ -1,7 +1,7 @@ //! Test utilities. #![cfg(test)] -#![allow(clippy::unwrap_used, reason = "it's ok in tests")] +#![expect(clippy::unwrap_used, reason = "it's ok in tests")] use mock_bot::{MockBotBuilder, CHAT_ID}; use teloxide::utils::command::BotCommands as _; diff --git a/telegram_gate/src/test_utils/mock_bot.rs b/telegram_gate/src/test_utils/mock_bot.rs index b8e16b0..613144a 100644 --- a/telegram_gate/src/test_utils/mock_bot.rs +++ b/telegram_gate/src/test_utils/mock_bot.rs @@ -1,6 +1,5 @@ //! Module with mock structures to test [`Bot`](teloxide::Bot) usage. -#![allow(clippy::unimplemented, reason = "it's ok in tests")] use std::future::{ready, Future, IntoFuture, Ready}; pub use builder::*; @@ -547,8 +546,6 @@ mod builder { } mod tests { - #![allow(clippy::unwrap_used, reason = "it's ok in tests")] - use tokio::test; use super::*; diff --git a/web_app/src/components/common.rs b/web_app/src/components/common.rs index ecfa41b..2b112f4 100644 --- a/web_app/src/components/common.rs +++ b/web_app/src/components/common.rs @@ -8,10 +8,18 @@ use leptos::{ use serde::{Deserialize, Serialize}; use web_sys::SubmitEvent; -const PASSWORD_TY: &str = "password"; -const TEXT_TY: &str = "text"; -const EYE_CLASS: &str = "fas fa-eye"; -const SLASHED_EYE_CLASS: &str = "fas fa-eye-slash"; +mod css { + //! Module with css classes + + /// Type of password field protected with stars. + pub const PASSWORD_TY: &str = "password"; + /// Type of password field for unprotected text view. + pub const TEXT_TY: &str = "text"; + /// Class of an open eye behind password field. + pub const EYE_CLASS: &str = "fas fa-eye"; + /// Class of a slashed eye behind password field. + pub const SLASHED_EYE_CLASS: &str = "fas fa-eye-slash"; +} /// Payload with user data to be encrypted and sent to the bot backend. #[derive(Serialize, Deserialize)] @@ -75,13 +83,21 @@ pub fn create_record_form_parameter( /// Main component with the record form. #[component] pub fn RecordForm( + /// Name of the resource. resource_name: RecordFormParamRead, + /// Login. login: RecordFormParamRead, + /// Password. password: RecordFormParamRead, + /// Comments. comments: RecordFormParamRead