chore(clippy): enable and fix many stricter lints (#3783)

* chore(clippy): enable and fix many stricter lints

These ensure that the codebase uses more idiomatic, performant, and
concise language constructions.

* chore: make non-Clippy compiler warnings also deny by default
This commit is contained in:
Alejandro González
2025-06-14 02:10:12 +02:00
committed by GitHub
parent 301967d204
commit f84f8c1c2b
106 changed files with 542 additions and 760 deletions

View File

@@ -12,7 +12,7 @@ use labrinth::models::teams::ProjectPermissions;
use labrinth::queue::payouts;
use rust_decimal::{Decimal, prelude::ToPrimitive};
mod common;
pub mod common;
#[actix_rt::test]
pub async fn analytics_revenue() {
@@ -50,7 +50,7 @@ pub async fn analytics_revenue() {
];
let project_id = parse_base62(&alpha_project_id).unwrap() as i64;
for (money, time) in money_time_pairs.iter() {
for (money, time) in &money_time_pairs {
insert_user_ids.push(USER_USER_ID_PARSED);
insert_project_ids.push(project_id);
insert_payouts.push(Decimal::from_f64_retain(*money).unwrap());
@@ -87,7 +87,7 @@ pub async fn analytics_revenue() {
)
.await;
assert_eq!(analytics.len(), 1); // 1 project
let project_analytics = analytics.get(&alpha_project_id).unwrap();
let project_analytics = &analytics[&alpha_project_id];
assert_eq!(project_analytics.len(), 8); // 1 days cut off, and 2 points take place on the same day. note that the day exactly 14 days ago is included
// sorted_by_key, values in the order of smallest to largest key
let (sorted_keys, sorted_by_key): (Vec<i64>, Vec<Decimal>) =
@@ -117,7 +117,7 @@ pub async fn analytics_revenue() {
USER_USER_PAT,
)
.await;
let project_analytics = analytics.get(&alpha_project_id).unwrap();
let project_analytics = &analytics[&alpha_project_id];
assert_eq!(project_analytics.len(), 9); // and 2 points take place on the same day
let (sorted_keys, sorted_by_key): (Vec<i64>, Vec<Decimal>) =
project_analytics

View File

@@ -31,13 +31,12 @@ use serde::Deserialize;
// as the environment generator for both uses common fields.
#[derive(Deserialize)]
#[allow(dead_code)]
pub struct CommonProject {
// For example, for CommonProject, we do not include:
// - game_versions (v2 only)
// - loader_fields (v3 only)
// - etc.
// For any tests that require those fields, we make a separate test with separate API functions tht do not use Common models.
// For any tests that require those fields, we make a separate test with separate API functions that do not use Common models.
pub id: ProjectId,
pub slug: Option<String>,
pub organization: Option<OrganizationId>,
@@ -62,7 +61,6 @@ pub struct CommonProject {
pub monetization_status: MonetizationStatus,
}
#[derive(Deserialize, Clone)]
#[allow(dead_code)]
pub struct CommonVersion {
pub id: VersionId,
pub loaders: Vec<String>,
@@ -82,7 +80,6 @@ pub struct CommonVersion {
}
#[derive(Deserialize)]
#[allow(dead_code)]
pub struct CommonLoaderData {
pub icon: String,
pub name: String,
@@ -90,7 +87,6 @@ pub struct CommonLoaderData {
}
#[derive(Deserialize)]
#[allow(dead_code)]
pub struct CommonCategoryData {
pub icon: String,
pub name: String,
@@ -100,7 +96,6 @@ pub struct CommonCategoryData {
/// A member of a team
#[derive(Deserialize)]
#[allow(dead_code)]
pub struct CommonTeamMember {
pub team_id: TeamId,
pub user: User,
@@ -114,7 +109,6 @@ pub struct CommonTeamMember {
}
#[derive(Deserialize)]
#[allow(dead_code)]
pub struct CommonNotification {
pub id: NotificationId,
pub user_id: UserId,
@@ -127,7 +121,6 @@ pub struct CommonNotification {
}
#[derive(Deserialize)]
#[allow(dead_code)]
pub struct CommonNotificationAction {
pub action_route: (String, String),
}
@@ -153,7 +146,6 @@ impl CommonItemType {
}
#[derive(Deserialize)]
#[allow(dead_code)]
pub struct CommonReport {
pub id: ReportId,
pub report_type: String,
@@ -175,7 +167,6 @@ pub enum LegacyItemType {
}
#[derive(Deserialize)]
#[allow(dead_code)]
pub struct CommonThread {
pub id: ThreadId,
#[serde(rename = "type")]
@@ -187,7 +178,6 @@ pub struct CommonThread {
}
#[derive(Deserialize)]
#[allow(dead_code)]
pub struct CommonThreadMessage {
pub id: ThreadMessageId,
pub author_id: Option<UserId>,
@@ -196,7 +186,6 @@ pub struct CommonThreadMessage {
}
#[derive(Deserialize)]
#[allow(dead_code)]
pub enum CommonMessageBody {
Text {
body: String,
@@ -216,7 +205,6 @@ pub enum CommonMessageBody {
}
#[derive(Deserialize)]
#[allow(dead_code)]
pub enum CommonThreadType {
Report,
Project,
@@ -224,7 +212,6 @@ pub enum CommonThreadType {
}
#[derive(Deserialize)]
#[allow(dead_code)]
pub struct CommonUser {
pub id: UserId,
pub username: String,

View File

@@ -5,21 +5,18 @@ use labrinth::util::actix::MultipartSegment;
use crate::common::dummy_data::TestFile;
#[allow(dead_code)]
pub struct ProjectCreationRequestData {
pub slug: String,
pub jar: Option<TestFile>,
pub segment_data: Vec<MultipartSegment>,
}
#[allow(dead_code)]
pub struct VersionCreationRequestData {
pub version: String,
pub jar: Option<TestFile>,
pub segment_data: Vec<MultipartSegment>,
}
#[allow(dead_code)]
pub struct ImageData {
pub filename: String,
pub extension: String,

View File

@@ -1,5 +1,3 @@
#![allow(dead_code)]
use super::{
api_common::{Api, ApiBuildable},
environment::LocalService,

View File

@@ -1,4 +1,4 @@
use std::collections::HashMap;
use std::{collections::HashMap, fmt::Write};
use crate::{
assert_status,
@@ -490,13 +490,13 @@ impl ApiProject for ApiV2 {
featured = featured
);
if let Some(title) = title {
url.push_str(&format!("&title={title}"));
write!(&mut url, "&title={title}").unwrap();
}
if let Some(description) = description {
url.push_str(&format!("&description={description}"));
write!(&mut url, "&description={description}").unwrap();
}
if let Some(ordering) = ordering {
url.push_str(&format!("&ordering={ordering}"));
write!(&mut url, "&ordering={ordering}").unwrap();
}
let req = test::TestRequest::post()
@@ -521,11 +521,12 @@ impl ApiProject for ApiV2 {
);
for (key, value) in patch {
url.push_str(&format!(
write!(
&mut url,
"&{key}={value}",
key = key,
value = urlencoding::encode(&value)
));
)
.unwrap();
}
let req = test::TestRequest::patch()

View File

@@ -1,4 +1,3 @@
#![allow(dead_code)]
use serde_json::json;
use crate::common::{
@@ -90,7 +89,7 @@ pub fn get_public_project_creation_data_json(
{
"title": format!("Test Project {slug}"),
"slug": slug,
"project_type": version_jar.as_ref().map(|f| f.project_type()).unwrap_or("mod".to_string()),
"project_type": version_jar.as_ref().map_or("mod".to_string(), |f| f.project_type()),
"description": "A dummy project for testing with.",
"body": "This project is approved, and versions are listed.",
"client_side": "required",

View File

@@ -1,4 +1,5 @@
use std::collections::HashMap;
use std::fmt::Write;
use super::{
ApiV2,
@@ -383,32 +384,36 @@ impl ApiVersion for ApiV2 {
) -> ServiceResponse {
let mut query_string = String::new();
if let Some(game_versions) = game_versions {
query_string.push_str(&format!(
write!(
&mut query_string,
"&game_versions={}",
urlencoding::encode(
&serde_json::to_string(&game_versions).unwrap()
)
));
)
.unwrap();
}
if let Some(loaders) = loaders {
query_string.push_str(&format!(
write!(
&mut query_string,
"&loaders={}",
urlencoding::encode(&serde_json::to_string(&loaders).unwrap())
));
)
.unwrap();
}
if let Some(featured) = featured {
query_string.push_str(&format!("&featured={featured}"));
write!(&mut query_string, "&featured={featured}").unwrap();
}
if let Some(version_type) = version_type {
query_string.push_str(&format!("&version_type={version_type}"));
write!(&mut query_string, "&version_type={version_type}").unwrap();
}
if let Some(limit) = limit {
let limit = limit.to_string();
query_string.push_str(&format!("&limit={limit}"));
write!(&mut query_string, "&limit={limit}").unwrap();
}
if let Some(offset) = offset {
let offset = offset.to_string();
query_string.push_str(&format!("&offset={offset}"));
write!(&mut query_string, "&offset={offset}").unwrap();
}
let req = test::TestRequest::get()

View File

@@ -1,5 +1,3 @@
#![allow(dead_code)]
use super::{
api_common::{Api, ApiBuildable},
environment::LocalService,

View File

@@ -1,4 +1,4 @@
use std::collections::HashMap;
use std::{collections::HashMap, fmt::Write};
use actix_http::StatusCode;
use actix_web::{
@@ -363,13 +363,13 @@ impl ApiProject for ApiV3 {
featured = featured
);
if let Some(title) = title {
url.push_str(&format!("&title={title}"));
write!(&mut url, "&title={title}").unwrap();
}
if let Some(description) = description {
url.push_str(&format!("&description={description}"));
write!(&mut url, "&description={description}").unwrap();
}
if let Some(ordering) = ordering {
url.push_str(&format!("&ordering={ordering}"));
write!(&mut url, "&ordering={ordering}").unwrap();
}
let req = test::TestRequest::post()
@@ -394,11 +394,12 @@ impl ApiProject for ApiV3 {
);
for (key, value) in patch {
url.push_str(&format!(
write!(
&mut url,
"&{key}={value}",
key = key,
value = urlencoding::encode(&value)
));
)
.unwrap();
}
let req = test::TestRequest::patch()
@@ -593,17 +594,17 @@ impl ApiV3 {
let start_date = start_date.to_rfc3339();
// let start_date = serde_json::to_string(&start_date).unwrap();
let start_date = urlencoding::encode(&start_date);
extra_args.push_str(&format!("&start_date={start_date}"));
write!(&mut extra_args, "&start_date={start_date}").unwrap();
}
if let Some(end_date) = end_date {
let end_date = end_date.to_rfc3339();
// let end_date = serde_json::to_string(&end_date).unwrap();
let end_date = urlencoding::encode(&end_date);
extra_args.push_str(&format!("&end_date={end_date}"));
write!(&mut extra_args, "&end_date={end_date}").unwrap();
}
if let Some(resolution_minutes) = resolution_minutes {
extra_args
.push_str(&format!("&resolution_minutes={resolution_minutes}"));
write!(&mut extra_args, "&resolution_minutes={resolution_minutes}")
.unwrap();
}
let req = test::TestRequest::get()

View File

@@ -1,4 +1,3 @@
#![allow(dead_code)]
use serde_json::json;
use crate::common::{

View File

@@ -1,4 +1,5 @@
use std::collections::HashMap;
use std::fmt::Write;
use super::{
ApiV3,
@@ -416,32 +417,36 @@ impl ApiVersion for ApiV3 {
) -> ServiceResponse {
let mut query_string = String::new();
if let Some(game_versions) = game_versions {
query_string.push_str(&format!(
write!(
&mut query_string,
"&game_versions={}",
urlencoding::encode(
&serde_json::to_string(&game_versions).unwrap()
)
));
)
.unwrap();
}
if let Some(loaders) = loaders {
query_string.push_str(&format!(
write!(
&mut query_string,
"&loaders={}",
urlencoding::encode(&serde_json::to_string(&loaders).unwrap())
));
)
.unwrap();
}
if let Some(featured) = featured {
query_string.push_str(&format!("&featured={featured}"));
write!(&mut query_string, "&featured={featured}").unwrap();
}
if let Some(version_type) = version_type {
query_string.push_str(&format!("&version_type={version_type}"));
write!(&mut query_string, "&version_type={version_type}").unwrap();
}
if let Some(limit) = limit {
let limit = limit.to_string();
query_string.push_str(&format!("&limit={limit}"));
write!(&mut query_string, "&limit={limit}").unwrap();
}
if let Some(offset) = offset {
let offset = offset.to_string();
query_string.push_str(&format!("&offset={offset}"));
write!(&mut query_string, "&offset={offset}").unwrap();
}
let req = test::TestRequest::get()

View File

@@ -1,5 +1,3 @@
#![allow(dead_code)]
use crate::common::get_json_val_str;
use itertools::Itertools;
use labrinth::models::v3::projects::Version;

View File

@@ -1,5 +1,3 @@
#![allow(dead_code)]
use labrinth::{database::redis::RedisPool, search};
use sqlx::{PgPool, postgres::PgPoolOptions};
use std::time::Duration;

View File

@@ -1,4 +1,3 @@
#![allow(dead_code)]
use std::io::{Cursor, Write};
use crate::{
@@ -28,7 +27,6 @@ use super::{database::USER_USER_ID, get_json_val_str};
pub const DUMMY_DATA_UPDATE: i64 = 7;
#[allow(dead_code)]
pub const DUMMY_CATEGORIES: &[&str] = &[
"combat",
"decoration",
@@ -41,7 +39,6 @@ pub const DUMMY_CATEGORIES: &[&str] = &[
pub const DUMMY_OAUTH_CLIENT_ALPHA_SECRET: &str = "abcdefghijklmnopqrstuvwxyz";
#[allow(dead_code)]
#[derive(Clone)]
pub enum TestFile {
DummyProjectAlpha,
@@ -173,7 +170,6 @@ impl TestFile {
}
#[derive(Clone)]
#[allow(dead_code)]
pub enum DummyImage {
SmallIcon, // 200x200
}

View File

@@ -1,5 +1,3 @@
#![allow(dead_code)]
use super::{
api_common::{Api, ApiBuildable, generic::GenericApi},
api_v2::ApiV2,

View File

@@ -1,5 +1,3 @@
#![allow(dead_code)]
use chrono::Utc;
use labrinth::{
database::{self, models::generate_pat_id},

View File

@@ -1,4 +1,3 @@
#![allow(dead_code)]
use actix_http::StatusCode;
use actix_web::{dev::ServiceResponse, test};
use futures::Future;

View File

@@ -1,4 +1,3 @@
#![allow(dead_code)]
use actix_web::{dev::ServiceResponse, test};
use futures::Future;
use labrinth::models::pats::Scopes;

View File

@@ -1,5 +1,3 @@
#![allow(dead_code)]
use std::{collections::HashMap, sync::Arc};
use actix_http::StatusCode;

View File

@@ -7,7 +7,7 @@ use common::api_v3::ApiV3;
use common::database::USER_USER_PAT;
use common::environment::{TestEnvironment, with_test_environment};
mod common;
pub mod common;
#[actix_rt::test]
pub async fn error_404_body() {

View File

@@ -5,7 +5,7 @@ use common::{
environment::{TestEnvironment, with_test_environment},
};
mod common;
pub mod common;
#[actix_rt::test]
async fn get_games() {

View File

@@ -17,8 +17,7 @@ use crate::common::dummy_data::{
DummyProjectAlpha, DummyProjectBeta, TestFile,
};
// importing common module.
mod common;
pub mod common;
#[actix_rt::test]
@@ -242,7 +241,7 @@ async fn creating_loader_fields() {
USER_USER_PAT,
)
.await;
assert_eq!(v.fields.get("test_fabric_optional").unwrap(), &json!(555));
assert_eq!(&v.fields["test_fabric_optional"], &json!(555));
// - Patch
let resp = api
.edit_version(
@@ -257,7 +256,7 @@ async fn creating_loader_fields() {
let v = api
.get_version_deserialized(alpha_version_id, USER_USER_PAT)
.await;
assert_eq!(v.fields.get("test_fabric_optional").unwrap(), &json!(555));
assert_eq!(&v.fields["test_fabric_optional"], &json!(555));
// Simply setting them as expected works
// - Create
@@ -286,12 +285,9 @@ async fn creating_loader_fields() {
USER_USER_PAT,
)
.await;
assert_eq!(
v.fields.get("game_versions").unwrap(),
&json!(["1.20.1", "1.20.2"])
);
assert_eq!(v.fields.get("singleplayer").unwrap(), &json!(false));
assert_eq!(v.fields.get("server_only").unwrap(), &json!(true));
assert_eq!(&v.fields["game_versions"], &json!(["1.20.1", "1.20.2"]));
assert_eq!(&v.fields["singleplayer"], &json!(false));
assert_eq!(&v.fields["server_only"], &json!(true));
// - Patch
let resp = api
.edit_version(
@@ -308,10 +304,7 @@ async fn creating_loader_fields() {
let v = api
.get_version_deserialized(alpha_version_id, USER_USER_PAT)
.await;
assert_eq!(
v.fields.get("game_versions").unwrap(),
&json!(["1.20.1", "1.20.2"])
);
assert_eq!(&v.fields["game_versions"], &json!(["1.20.1", "1.20.2"]));
// Now that we've created a version, we need to make sure that the Project's loader fields are updated (aggregate)
// First, add a new version
@@ -361,23 +354,11 @@ async fn creating_loader_fields() {
)
.await;
assert_eq!(
project.fields.get("game_versions").unwrap(),
&project.fields["game_versions"],
&[json!("1.20.1"), json!("1.20.2"), json!("1.20.5")]
);
assert!(
project
.fields
.get("singleplayer")
.unwrap()
.contains(&json!(false))
);
assert!(
project
.fields
.get("singleplayer")
.unwrap()
.contains(&json!(true))
);
assert!(project.fields["singleplayer"].contains(&json!(false)));
assert!(project.fields["singleplayer"].contains(&json!(true)));
})
.await
}
@@ -533,7 +514,7 @@ async fn test_multi_get_redis_cache() {
assert_eq!(projects.len(), 10);
// Ensure all 5 modpacks have 'mrpack_loaders', and all 5 mods do not
for project in projects.iter() {
for project in &projects {
if modpacks.contains(project.slug.as_ref().unwrap()) {
assert!(project.fields.contains_key("mrpack_loaders"));
} else if mods.contains(project.slug.as_ref().unwrap()) {
@@ -566,7 +547,7 @@ async fn test_multi_get_redis_cache() {
assert_eq!(versions.len(), 10);
// Ensure all 5 versions from modpacks have 'mrpack_loaders', and all 5 versions from mods do not
for version in versions.iter() {
for version in &versions {
if version_ids_modpacks.contains(&version.id) {
assert!(version.fields.contains_key("mrpack_loaders"));
} else if version_ids_mods.contains(&version.id) {

View File

@@ -5,7 +5,7 @@ use common::{
use crate::common::api_common::ApiTeams;
mod common;
pub mod common;
#[actix_rt::test]
pub async fn get_user_notifications_after_team_invitation_returns_notification()

View File

@@ -16,7 +16,7 @@ use common::{
};
use labrinth::auth::oauth::TokenResponse;
mod common;
pub mod common;
#[actix_rt::test]
async fn oauth_flow_happy_path() {

View File

@@ -17,7 +17,7 @@ use labrinth::{
use common::database::USER_USER_ID_PARSED;
mod common;
pub mod common;
#[actix_rt::test]
async fn can_create_edit_get_oauth_client() {

View File

@@ -22,7 +22,7 @@ use common::{
use labrinth::models::teams::{OrganizationPermissions, ProjectPermissions};
use serde_json::json;
mod common;
pub mod common;
#[actix_rt::test]
async fn create_organization() {
@@ -583,9 +583,7 @@ async fn add_remove_organization_project_ownership_to_user() {
.await;
assert_eq!(members.len(), 1);
assert_eq!(members[0].user.id.to_string(), FRIEND_USER_ID);
let user_member =
members.iter().filter(|m| m.is_owner).collect::<Vec<_>>();
assert_eq!(user_member.len(), 0);
assert_eq!(members.iter().filter(|m| m.is_owner).count(), 0);
// Beta project should have:
// - No members
@@ -836,9 +834,7 @@ async fn delete_organization_means_all_projects_to_org_owner() {
.api
.get_team_members_deserialized(alpha_team_id, USER_USER_PAT)
.await;
let user_member =
members.iter().filter(|m| m.is_owner).collect::<Vec<_>>();
assert_eq!(user_member.len(), 0);
assert_eq!(members.iter().filter(|m| m.is_owner).count(), 0);
// Transfer ownership of zeta organization to FRIEND
let resp = test_env
@@ -856,9 +852,7 @@ async fn delete_organization_means_all_projects_to_org_owner() {
.api
.get_team_members_deserialized(alpha_team_id, USER_USER_PAT)
.await;
let user_member =
members.iter().filter(|m| m.is_owner).collect::<Vec<_>>();
assert_eq!(user_member.len(), 0);
assert_eq!(members.iter().filter(|m| m.is_owner).count(), 0);
// Delete organization
let resp = test_env

View File

@@ -8,7 +8,7 @@ use serde_json::json;
use crate::common::api_common::AppendsOptionalPat;
mod common;
pub mod common;
// Full pat test:
// - create a PAT and ensure it can be used for the scope

View File

@@ -27,7 +27,7 @@ use labrinth::util::actix::{MultipartSegment, MultipartSegmentData};
use serde_json::json;
use sha1::Digest;
mod common;
pub mod common;
#[actix_rt::test]
async fn test_get_project() {

View File

@@ -29,7 +29,7 @@ use serde_json::json;
// - test the function with the PAT with the given scopes
// - test the function with the PAT with all other scopes
mod common;
pub mod common;
// Test for users, emails, and payout scopes (not user auth scope or notifs)
#[actix_rt::test]

View File

@@ -14,7 +14,7 @@ use serde_json::json;
use crate::common::api_common::Api;
use crate::common::api_common::ApiProject;
mod common;
pub mod common;
// TODO: Revisit this wit h the new modify_json in the version maker
// That change here should be able to simplify it vastly

View File

@@ -9,7 +9,7 @@ use common::{
use crate::common::api_common::ApiTags;
mod common;
pub mod common;
#[actix_rt::test]
async fn get_tags() {

View File

@@ -10,7 +10,7 @@ use labrinth::models::teams::{OrganizationPermissions, ProjectPermissions};
use rust_decimal::Decimal;
use serde_json::json;
mod common;
pub mod common;
#[actix_rt::test]
async fn test_get_team() {

View File

@@ -5,7 +5,7 @@ use common::{
environment::with_test_environment_all,
};
mod common;
pub mod common;
// user GET (permissions, different users)
// users GET

View File

@@ -219,7 +219,7 @@ async fn version_updates() {
// Add 3 new versions, 1 before, and 2 after, with differing game_version/version_types/loaders
let mut update_ids = vec![];
for (version_number, patch_value) in [
for (version_number, patch_value) in &[
(
"0.9.9",
json!({
@@ -241,9 +241,7 @@ async fn version_updates() {
"version_type": "beta"
}),
),
]
.iter()
{
] {
let version = api
.add_public_version_deserialized_common(
*alpha_project_id_parsed,

View File

@@ -1,5 +1,4 @@
// importing common module.
mod common;
pub mod common;
// Not all tests expect exactly the same functionality in v2 and v3.
// For example, though we expect the /GET version to return the corresponding project,

View File

@@ -22,8 +22,7 @@ use labrinth::models::projects::{
use labrinth::routes::v3::version_file::FileUpdateData;
use serde_json::json;
// importing common module.
mod common;
pub mod common;
#[actix_rt::test]
async fn test_get_version() {
@@ -164,7 +163,7 @@ async fn version_updates() {
// Add 3 new versions, 1 before, and 2 after, with differing game_version/version_types/loaders
let mut update_ids = vec![];
for (version_number, patch_value) in [
for (version_number, patch_value) in &[
(
"0.9.9",
json!({
@@ -186,9 +185,7 @@ async fn version_updates() {
"version_type": "beta"
}),
),
]
.iter()
{
] {
let version = api
.add_public_version_deserialized(
*alpha_project_id_parsed,