Skip to main content

x_lint/
project.rs

1// Copyright (c) The Diem Core Contributors
2// SPDX-License-Identifier: Apache-2.0
3
4use crate::{prelude::*, LintContext};
5use guppy::graph::PackageGraph;
6use hakari::Hakari;
7use std::path::{Path, PathBuf};
8use x_core::{WorkspaceSubset, XCoreContext};
9
10/// Represents a linter that checks some property for the overall project.
11///
12/// Linters that implement `ProjectLinter` will run once for the whole project.
13pub trait ProjectLinter: Linter {
14    // Since ProjectContext is only 1 word long, clippy complains about passing it by reference. Do
15    // it that way for consistency reasons.
16    #[allow(clippy::trivially_copy_pass_by_ref)]
17    /// Executes the lint against the given project context.
18    fn run<'l>(
19        &self,
20        ctx: &ProjectContext<'l>,
21        out: &mut LintFormatter<'l, '_>,
22    ) -> Result<RunStatus<'l>>;
23}
24
25/// Overall linter context for a project.
26#[derive(Debug)]
27pub struct ProjectContext<'l> {
28    core: &'l XCoreContext,
29}
30
31impl<'l> ProjectContext<'l> {
32    pub fn new(core: &'l XCoreContext) -> Self {
33        Self { core }
34    }
35
36    /// Returns the core context.
37    pub fn core(&self) -> &'l XCoreContext {
38        self.core
39    }
40
41    /// Returns the project root.
42    pub fn project_root(&self) -> &'l Path {
43        self.core.project_root()
44    }
45
46    /// Returns the package graph, computing it for the first time if necessary.
47    pub fn package_graph(&self) -> Result<&'l PackageGraph> {
48        Ok(self.core.package_graph()?)
49    }
50
51    /// Returns the absolute path from the project root.
52    pub fn full_path(&self, path: impl AsRef<Path>) -> PathBuf {
53        self.core.project_root().join(path.as_ref())
54    }
55
56    /// Returns information about the default workspace members.
57    ///
58    /// This includes all packages included by default in the default workspace members, but not
59    /// those that Cargo would ignore.
60    pub fn default_members(&self) -> Result<&WorkspaceSubset> {
61        Ok(self.core.subsets()?.default_members())
62    }
63
64    /// Returns Hakari information.
65    pub fn hakari(&self) -> Result<Hakari<'l, 'static>> {
66        Ok(self.core.hakari_builder()?.compute())
67    }
68}
69
70impl<'l> LintContext<'l> for ProjectContext<'l> {
71    fn kind(&self) -> LintKind<'l> {
72        LintKind::Project
73    }
74}