1use anyhow::anyhow;
5use camino::Utf8Path;
6use clap::Parser;
7use nexlint::{prelude::*, NexLintContext};
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 ],
96 };
97
98 let project_linters: &[&dyn ProjectLinter] = &[
99 &BannedDeps::new(&banned_deps_config),
100 &DirectDepDups::new(&direct_dep_dups_config),
101 &DirectDuplicateGitDependencies,
102 ];
103
104 let package_linters: &[&dyn PackageLinter] = &[
105 &CrateNamesPaths,
106 &IrrelevantBuildDeps,
107 &PublishedPackagesDontDependOnUnpublishedPackages,
110 &OnlyPublishToCratesIo,
111 &CratesInCratesDirectory,
112 ];
115
116 let file_path_linters: &[&dyn FilePathLinter] = &[
117 ];
119
120 let content_linters: &[&dyn ContentLinter] = &[
123 &LicenseHeader::new(LICENSE_HEADER),
124 &RootToml,
125 ];
128
129 let nexlint_context = NexLintContext::from_current_dir()?;
130 let engine = LintEngineConfig::new(&nexlint_context)
131 .with_project_linters(project_linters)
132 .with_package_linters(package_linters)
133 .with_file_path_linters(file_path_linters)
134 .with_content_linters(content_linters)
135 .fail_fast(args.fail_fast)
136 .build();
137
138 let results = engine.run()?;
139
140 handle_lint_results_exclude_external_crate_checks(results)
141}
142
143pub fn handle_lint_results_exclude_external_crate_checks(
145 results: LintResults,
146) -> crate::Result<()> {
147 let ignore_funcs = [
150 |source: &LintSource, path: &Utf8Path| -> bool {
152 (path.starts_with(EXTERNAL_CRATE_DIR)
153 || path.starts_with(CREATE_DAPP_TEMPLATE_DIR)
154 || path.to_string().contains("/generated/")
155 || path.to_string().contains("/proto/"))
156 && source.name() == "license-header"
157 },
158 |_source: &LintSource, path: &Utf8Path| -> bool {
160 path.starts_with("buck/") || path.starts_with("third-party/")
161 },
162 ];
163
164 let mut errs = false;
166 for (source, message) in &results.messages {
167 if let LintKind::Content(path) = source.kind() {
168 if ignore_funcs.iter().any(|func| func(source, path)) {
169 continue;
170 }
171 }
172 println!(
173 "[{}] [{}] [{}]: {}\n",
174 message.level(),
175 source.name(),
176 source.kind(),
177 message.message()
178 );
179 errs = true;
180 }
181
182 if errs {
183 Err(anyhow!("there were lint errors"))
184 } else {
185 Ok(())
186 }
187}