myd/lib.rs
1#![doc = include_str!("../README.md")]
2#![deny(missing_docs)]
3#![deny(clippy::missing_docs_in_private_items)]
4
5use std::collections::{HashMap, HashSet};
6
7pub use cargo_metadata::CargoOpt;
8use ego_tree::NodeId;
9use syn::Item;
10
11mod module;
12pub mod parse;
13pub mod platforms;
14pub use module::Module;
15mod module_information;
16pub use module_information::ModuleInformation;
17mod syn_helpers;
18
19/// A list of [`syn::Item`]s
20pub type Items = Vec<Item>;
21/// A map of depends to their features
22type Features = HashMap<String, HashSet<String>>;
23
24/// A representation of an import
25#[derive(Debug)]
26struct Import {
27 /// The path to the item of which this points
28 pub item: syn::Path,
29 /// The strength of the import
30 pub strength: ImportStrength,
31 /// The alias
32 ///
33 /// For example in the case of `use std::vec::Vec as List` this would be `List`
34 pub az: Option<syn::Ident>,
35}
36
37impl Import {
38 /// Returns the identifier of this Import
39 ///
40 /// This will be the `az` if present, elsewise the last
41 /// identifier in the path.
42 pub fn ident(&self) -> &syn::Ident {
43 match &self.az {
44 Some(az) => az,
45 None => &self.item.segments.last().unwrap().ident,
46 }
47 }
48}
49
50impl Import {
51 /// Creates a new Import
52 pub fn new(item: syn::Path, strength: ImportStrength, az: Option<syn::Ident>) -> Self {
53 Self { item, strength, az }
54 }
55}
56
57/// Represents the 'strength' of an import.
58///
59/// This is used by the program to determine whether an import
60/// is imported via a glob or not; if it is imported via a glob
61/// then it can be safely overriden by another import that is not from a glob.
62///
63/// However, if two imports of the same strength are present then that is an error.
64#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone, Copy)]
65enum ImportStrength {
66 /// Strong - the user explicitely imported this
67 Strong,
68 /// Weak - this was resolved through a glob
69 Weak,
70}
71
72/// A reference to an item on the tree.
73///
74/// Only useful with [`ModuleInformation`]
75#[derive(Debug, PartialEq, Eq, Clone, Copy)]
76pub struct ItemId {
77 /// The Node that this points to
78 node: NodeId,
79 /// The position in the list of the module for the item
80 item_id: usize,
81}
82
83impl ItemId {
84 /// Gets the ID of the module this
85 /// item is under.
86 pub fn module_id(&self) -> NodeId {
87 self.node
88 }
89}
90
91/// A reference either fo a module or an item on the tree
92#[derive(Debug, PartialEq, Eq, Clone, Copy)]
93pub enum ModuleOrItem {
94 /// A module
95 ///
96 /// Can be accessed through the `tree` field on [`ModuleInformation`]
97 Module(NodeId),
98 /// An item, can be accessed by [`ModuleInformation::get`]
99 Item(ItemId),
100}
101
102impl ModuleOrItem {
103 /// Unwraps a module in this
104 ///
105 /// # Panics
106 ///
107 /// Panics if this is not a module
108 pub fn unwrap_module(self) -> NodeId {
109 match self {
110 ModuleOrItem::Module(x) => x,
111 ModuleOrItem::Item(_) => panic!(
112 "Tried to unwrap a Module from a ModuleOrItem::Item: {:?}",
113 self
114 ),
115 }
116 }
117
118 /// Unwraps a item in this
119 ///
120 /// # Panics
121 ///
122 /// Panics if this is not a item
123 pub fn unwrap_item(self) -> ItemId {
124 match self {
125 ModuleOrItem::Item(x) => x,
126 ModuleOrItem::Module(_) => panic!(
127 "Tried to unwrap an Item from a ModuleOrItem::Module: {:?}",
128 self
129 ),
130 }
131 }
132}
133
134impl From<ItemId> for ModuleOrItem {
135 fn from(them: ItemId) -> Self {
136 Self::Item(them)
137 }
138}
139impl From<NodeId> for ModuleOrItem {
140 fn from(them: NodeId) -> Self {
141 Self::Module(them)
142 }
143}
144
145/// An error occuring when resolving a path
146/// with [`ModuleInformation::path`]
147#[derive(thiserror::Error, Debug)]
148pub enum ResolveError {
149 /// The item the path points to does not exist,
150 ///
151 /// ie `std::collections::Bashmap`
152 #[error("path not found")]
153 NotFound,
154 /// AN item is prematurely reached in the path
155 ///
156 /// ie `std::collections::HashMap::mything`
157 // TODO: This should not be an error
158 #[error("premature non module item")]
159 PrematureItem,
160 /// An item is found at the root
161 ///
162 /// ie `::Item` being a struct not a module
163 #[error("items should not exist from the root in rust.")]
164 RootItem,
165 /// Conflicting imports
166 ///
167 /// ie:
168 ///
169 /// ```rust
170 /// use a::*;
171 /// use b::*;
172 ///
173 /// mod a {
174 /// pub struct Foo;
175 /// }
176 ///
177 /// mod b {
178 /// pub struct Foo;
179 /// }
180 ///
181 /// // Could refer to `a::Foo` or `b::Foo`
182 /// Foo
183 /// ```
184 #[error("conflicting imports")]
185 Conflicting,
186 /// When the supers go out of the crate
187 ///
188 /// ie `std::super::super`
189 #[error("too many supers!")]
190 TooManySupers,
191}