sphinx_rustdocgen/utils.rs
1// sphinxcontrib_rust - Sphinx extension for the Rust programming language
2// Copyright (C) 2024 Munir Contractor
3//
4// This program is free software: you can redistribute it and/or modify
5// it under the terms of the GNU General Public License as published by
6// the Free Software Foundation, either version 3 of the License, or
7// (at your option) any later version.
8//
9// This program is distributed in the hope that it will be useful,
10// but WITHOUT ANY WARRANTY; without even the implied warranty of
11// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12// GNU General Public License for more details.
13//
14// You should have received a copy of the GNU General Public License
15// along with this program. If not, see <https://www.gnu.org/licenses/>.
16
17//! Module for various utility classes and structs.
18
19use std::fs::read_to_string;
20use std::path::{Path, PathBuf};
21
22use cargo_toml::{Manifest, Product};
23
24/// Check the provided paths for the Cargo.toml file.
25///
26/// Returns:
27/// A Some value of the path that contained the Cargo manifest and the
28/// associated manifest for the first path contains a ``Cargo.toml`` file.
29pub(crate) fn check_for_manifest(paths: Vec<&Path>) -> Option<(PathBuf, CargoManifest)> {
30 for path in paths {
31 let manifest_path = path.join("Cargo.toml");
32 if manifest_path.is_file() {
33 return Some((
34 path.into(),
35 CargoManifest(Manifest::from_path(manifest_path).unwrap()),
36 ));
37 }
38 }
39 None
40}
41
42/// Struct for the source code files encountered when scanning the crate.
43#[derive(Clone, Debug)]
44pub(crate) struct SourceCodeFile {
45 /// The path to the file.
46 pub(crate) path: PathBuf,
47 /// The name of the item in the file.
48 pub(crate) item: String,
49}
50
51impl SourceCodeFile {
52 /// Generate and return the AST for the file.
53 pub(crate) fn ast(&self) -> syn::File {
54 syn::parse_file(&read_to_string(&self.path).unwrap()).unwrap()
55 }
56
57 /// Get the parent directory of the file for the item.
58 ///
59 /// The item of the returned struct is the same as this struct's item.
60 /// This is mainly used for ``mod.rs`` and ``lib.rs`` files, where the
61 /// directory name determines the item's name.
62 pub(crate) fn to_parent_directory(&self) -> Self {
63 SourceCodeFile {
64 path: self.path.parent().as_ref().unwrap().into(),
65 item: self.item.clone(),
66 }
67 }
68
69 /// Create an instance for the product in the crate.
70 ///
71 /// Args:
72 /// :prd: The product for which the file should be created.
73 /// :crate_dir: The path for the crate's directory, used to
74 /// generate the absolute path for the file.
75 fn from_product(prd: &Product, crate_dir: &Path) -> Self {
76 SourceCodeFile {
77 path: crate_dir.join(prd.path.as_ref().unwrap()),
78 item: prd.name.as_ref().unwrap().clone(),
79 }
80 }
81
82 /// Returns the name of the crate from the item name.
83 pub(crate) fn crate_name(&self) -> &str {
84 &self.item[0..self.item.find("::").unwrap_or(self.item.len())]
85 }
86}
87
88/// Newtype struct for the Cargo manifest from cargo_toml.
89pub(crate) struct CargoManifest(Manifest);
90
91impl CargoManifest {
92 /// Get the library file for the crate, if any.
93 pub(crate) fn lib_file(&self, crate_dir: &Path) -> Option<SourceCodeFile> {
94 self.0
95 .lib
96 .as_ref()
97 .map(|lib| SourceCodeFile::from_product(lib, crate_dir))
98 }
99
100 /// Get all the executable files in the crate.
101 pub(crate) fn executable_files(&self, crate_dir: &Path) -> Vec<SourceCodeFile> {
102 self.0
103 .bin
104 .iter()
105 .map(|prd| SourceCodeFile::from_product(prd, crate_dir))
106 .collect()
107 }
108}