1use anyhow::anyhow;
5use camino::Utf8Path;
6use clap::Parser;
7use nexlint::{NexLintContext, prelude::*};
8use nexlint_lints::{
9 content::*,
10 package::*,
11 project::{
12 BannedDepConfig, BannedDepType, BannedDeps, BannedDepsConfig, DirectDepDups,
13 DirectDepDupsConfig, DirectDuplicateGitDependencies,
14 },
15};
16static EXTERNAL_CRATE_DIR: &str = "external-crates/";
17static CREATE_DAPP_TEMPLATE_DIR: &str = "sdk/create-dapp/templates";
18static LICENSE_HEADER: &str = "Copyright (c) Mysten Labs, Inc.\n\
19 SPDX-License-Identifier: Apache-2.0\n\
20 ";
21#[derive(Debug, Parser)]
22pub struct Args {
23 #[clap(long)]
24 fail_fast: bool,
25}
26
27pub fn run(args: Args) -> crate::Result<()> {
28 let banned_deps_config = BannedDepsConfig(
29 vec![
30 (
31 "lazy_static".to_owned(),
32 BannedDepConfig {
33 message: "use once_cell::sync::Lazy instead".to_owned(),
34 type_: BannedDepType::Direct,
35 },
36 ),
37 (
38 "tracing-test".to_owned(),
39 BannedDepConfig {
40 message: "you should not be testing against log lines".to_owned(),
41 type_: BannedDepType::Always,
42 },
43 ),
44 (
45 "openssl-sys".to_owned(),
46 BannedDepConfig {
47 message: "use rustls for TLS".to_owned(),
48 type_: BannedDepType::Always,
49 },
50 ),
51 (
52 "actix-web".to_owned(),
53 BannedDepConfig {
54 message: "use axum for a webframework instead".to_owned(),
55 type_: BannedDepType::Always,
56 },
57 ),
58 (
59 "warp".to_owned(),
60 BannedDepConfig {
61 message: "use axum for a webframework instead".to_owned(),
62 type_: BannedDepType::Always,
63 },
64 ),
65 (
66 "pq-sys".to_owned(),
67 BannedDepConfig {
68 message: "diesel_async asynchronous database connections instead".to_owned(),
69 type_: BannedDepType::Always,
70 },
71 ),
72 ]
73 .into_iter()
74 .collect(),
75 );
76
77 let direct_dep_dups_config = DirectDepDupsConfig {
78 allow: vec![
79 "serde_yaml".to_owned(),
81 "syn".to_owned(),
82 "prost".to_owned(),
85 "tonic".to_owned(),
86 "http-body".to_owned(),
88 "tower".to_owned(),
90 "axum".to_owned(),
92 "axum-extra".to_owned(),
93 "bincode".to_owned(),
95 "reqwest".to_owned(),
97 ],
98 };
99
100 let project_linters: &[&dyn ProjectLinter] = &[
101 &BannedDeps::new(&banned_deps_config),
102 &DirectDepDups::new(&direct_dep_dups_config),
103 &DirectDuplicateGitDependencies,
104 ];
105
106 let package_linters: &[&dyn PackageLinter] = &[
107 &CrateNamesPaths,
108 &IrrelevantBuildDeps,
109 &PublishedPackagesDontDependOnUnpublishedPackages,
112 &OnlyPublishToCratesIo,
113 &CratesInCratesDirectory,
114 ];
117
118 let file_path_linters: &[&dyn FilePathLinter] = &[
119 ];
121
122 let content_linters: &[&dyn ContentLinter] = &[
125 &LicenseHeader::new(LICENSE_HEADER),
126 &RootToml,
127 ];
130
131 let nexlint_context = NexLintContext::from_current_dir()?;
132 let engine = LintEngineConfig::new(&nexlint_context)
133 .with_project_linters(project_linters)
134 .with_package_linters(package_linters)
135 .with_file_path_linters(file_path_linters)
136 .with_content_linters(content_linters)
137 .fail_fast(args.fail_fast)
138 .build();
139
140 let results = engine.run()?;
141
142 handle_lint_results_exclude_external_crate_checks(results)
143}
144
145pub fn handle_lint_results_exclude_external_crate_checks(
147 results: LintResults,
148) -> crate::Result<()> {
149 let ignore_funcs = [
152 |source: &LintSource, path: &Utf8Path| -> bool {
154 (path.starts_with(EXTERNAL_CRATE_DIR)
155 || path.starts_with(CREATE_DAPP_TEMPLATE_DIR)
156 || path.to_string().contains("/generated/")
157 || path.to_string().contains("/proto/"))
158 && source.name() == "license-header"
159 },
160 |_source: &LintSource, path: &Utf8Path| -> bool {
162 path.starts_with("buck/") || path.starts_with("third-party/")
163 },
164 ];
165
166 let mut errs = false;
168 for (source, message) in &results.messages {
169 if let LintKind::Content(path) = source.kind()
170 && ignore_funcs.iter().any(|func| func(source, path))
171 {
172 continue;
173 }
174 println!(
175 "[{}] [{}] [{}]: {}\n",
176 message.level(),
177 source.name(),
178 source.kind(),
179 message.message()
180 );
181 errs = true;
182 }
183
184 if errs {
185 Err(anyhow!("there were lint errors"))
186 } else {
187 Ok(())
188 }
189}