mago_codex/metadata/ttype.rs
1use serde::Deserialize;
2use serde::Serialize;
3
4use mago_span::Span;
5
6use crate::ttype::union::TUnion;
7
8/// Contains metadata associated with a specific type instance within the type system.
9///
10/// This struct combines the core type information (`TUnion`) with contextual details
11/// about *how* and *where* this type information was determined or declared in the source code
12/// or related documentation.
13#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
14pub struct TypeMetadata {
15 /// The specific location (span) in the source code or documentation
16 /// that this type metadata corresponds to.
17 ///
18 /// This could be:
19 /// - The span of a type annotation (e.g., `: string`).
20 /// - The span of an expression whose type was inferred (e.g., `$x = 10` -> span of `10`).
21 /// - The span of a type mentioned in a documentation block (e.g., `@param int` -> span of `int`).
22 pub span: Span,
23
24 /// The core representation of the type itself.
25 pub type_union: TUnion,
26
27 /// Distinguishes whether this type information originated from analyzing
28 /// executable code constructs (e.g., type declarations, assignments)
29 /// or from documentation blocks.
30 ///
31 /// - `true` if the type information was extracted from a docblock comment.
32 /// - `false` if the type information came from actual code analysis.
33 pub from_docblock: bool,
34
35 /// Indicates whether this type was explicitly declared in the source
36 /// or deduced ("inferred") by the type checker based on context.
37 ///
38 /// - `true` if the type checker inferred this type (e.g., from a variable initialization like `$x = 10;`).
39 /// - `false` if the type was explicitly written by the user (e.g., `int $x;`).
40 pub inferred: bool,
41}
42
43impl TypeMetadata {
44 /// Creates new `TypeMetadata` for an explicitly declared type from code.
45 ///
46 /// This is a convenience constructor assuming the common case where a type
47 /// is directly specified in the code, and wasn't just inferred or from a docblock.
48 ///
49 /// # Arguments
50 ///
51 /// * `type_union`: The core type information (`TUnion`).
52 /// * `span`: The source code location associated with this type.
53 ///
54 /// # Returns
55 ///
56 /// A new `TypeMetadata` instance with `is_nullable`, `from_docblock`, and `inferred` set to `false`.
57 pub fn new(type_union: TUnion, span: Span) -> Self {
58 Self { span, type_union, from_docblock: false, inferred: false }
59 }
60
61 /// Creates a new `TypeMetadata` by applying a function to the inner `TUnion`.
62 ///
63 /// This allows transforming the core type while preserving the surrounding metadata.
64 ///
65 /// # Arguments
66 ///
67 /// * `f`: A function that takes the current `TUnion` and returns a new `TUnion`.
68 ///
69 /// # Returns
70 ///
71 /// A new `TypeMetadata` instance with the transformed `TUnion` and the same metadata flags and span.
72 pub fn map_type_union<F>(self, f: F) -> Self
73 where
74 F: FnOnce(TUnion) -> TUnion,
75 {
76 Self {
77 span: self.span,
78 type_union: f(self.type_union),
79 from_docblock: self.from_docblock,
80 inferred: self.inferred,
81 }
82 }
83}