mago_docblock/
document.rs

1use serde::Deserialize;
2use serde::Serialize;
3
4use mago_interner::StringIdentifier;
5use mago_span::Span;
6
7#[derive(Debug, Clone, Eq, PartialEq, Hash, Serialize, Deserialize, PartialOrd, Ord)]
8pub struct Document {
9    pub elements: Vec<Element>,
10}
11
12#[derive(Debug, Clone, Eq, PartialEq, Hash, Serialize, Deserialize, PartialOrd, Ord)]
13pub enum Element {
14    Text(Text),
15    Code(Code),
16    Tag(Tag),
17    Line(Span),
18    Annotation(Annotation),
19}
20
21#[derive(Debug, Clone, Eq, PartialEq, Hash, Serialize, Deserialize, PartialOrd, Ord)]
22pub struct Text {
23    pub span: Span,
24    pub segments: Vec<TextSegment>,
25}
26
27#[derive(Debug, Clone, Eq, PartialEq, Hash, Serialize, Deserialize, PartialOrd, Ord)]
28pub struct Code {
29    pub span: Span,
30    pub directives: Vec<StringIdentifier>,
31    pub content: StringIdentifier,
32}
33
34#[derive(Debug, Clone, Eq, PartialEq, Hash, Serialize, Deserialize, PartialOrd, Ord)]
35pub enum TextSegment {
36    Paragraph { span: Span, content: StringIdentifier },
37    InlineCode(Code),
38    InlineTag(Tag),
39}
40
41#[derive(Debug, Clone, Eq, PartialEq, Hash, Serialize, Deserialize, PartialOrd, Ord)]
42pub struct Annotation {
43    pub span: Span,
44    pub name: StringIdentifier,
45    pub arguments: Option<StringIdentifier>,
46}
47
48#[derive(Debug, Clone, Eq, PartialEq, Hash, Serialize, Deserialize, PartialOrd, Ord)]
49pub struct Tag {
50    pub span: Span,
51    pub name: StringIdentifier,
52    pub kind: TagKind,
53    pub description: StringIdentifier,
54}
55
56#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash, Serialize, Deserialize, PartialOrd, Ord)]
57#[non_exhaustive]
58pub enum TagKind {
59    Abstract,
60    Access,
61    Author,
62    Category,
63    Copyright,
64    Deprecated,
65    Example,
66    Final,
67    FileSource,
68    Global,
69    Ignore,
70    Internal,
71    License,
72    Link,
73    Method,
74    Mixin,
75    Name,
76    Package,
77    Param,
78    Property,
79    PropertyRead,
80    PropertyWrite,
81    SealProperties,
82    NoSealProperties,
83    SealMethods,
84    NoSealMethods,
85    ReadOnly,
86    NoNamedArguments,
87    Template,
88    PsalmTemplate,
89    Api,
90    PsalmApi,
91    PsalmInheritors,
92    Return,
93    See,
94    Since,
95    Static,
96    StaticVar,
97    SubPackage,
98    Todo,
99    Tutorial,
100    Uses,
101    Var,
102    Throws,
103    Version,
104    ParamLaterInvokedCallable,
105    ParamImmediatelyInvokedCallable,
106    ParamClosureThis,
107    TemplateCovariant,
108    TemplateContravariant,
109    Extends,
110    Implements,
111    Use,
112    NotDeprecated,
113    PhpstanImpure,
114    PhpstanPure,
115    Pure,
116    Immutable,
117    InheritDoc,
118    ParamOut,
119    PsalmConsistentConstructor,
120    PsalmConsistentTemplates,
121    PsalmParamOut,
122    PsalmVar,
123    PsalmParam,
124    PsalmReturn,
125    PsalmProperty,
126    PsalmPropertyRead,
127    PsalmPropertyWrite,
128    PsalmMethod,
129    PsalmIgnoreVar,
130    PsalmSuppress,
131    PsalmAssert,
132    PsalmAssertIfTrue,
133    PsalmAssertIfFalse,
134    PsalmIfThisIs,
135    PsalmThisOut,
136    PsalmIgnoreNullableReturn,
137    PsalmIgnoreFalsableReturn,
138    PsalmSealProperties,
139    PsalmNoSealProperties,
140    PsalmSealMethods,
141    PsalmNoSealMethods,
142    PsalmInternal,
143    PsalmReadOnly,
144    PsalmMutationFree,
145    PsalmExternalMutationFree,
146    PsalmImmutable,
147    PsalmPure,
148    PsalmAllowPrivateMutation,
149    PsalmReadOnlyAllowPrivateMutation,
150    PsalmTrace,
151    PsalmCheckType,
152    PsalmCheckTypeExact,
153    PsalmTaintSource,
154    PsalmTaintSink,
155    PsalmTaintEscape,
156    PsalmTaintUnescape,
157    PsalmTaintSpecialize,
158    PsalmFlow,
159    PsalmType,
160    PsalmImportType,
161    PsalmRequireExtends,
162    PsalmRequireImplements,
163    PsalmIgnoreVariableProperty,
164    PsalmIgnoreVariableMethod,
165    PsalmYield,
166    PhpstanAssert,
167    PhpstanAssertIfTrue,
168    PhpstanAssertIfFalse,
169    PhpstanSelfOut,
170    PhpstanThisOut,
171    PhpstanRequireExtends,
172    PhpstanRequireImplements,
173    PhpstanTemplate,
174    PhpstanTemplateCovariant,
175    PhpstanTemplateContravariant,
176    PhpstanParam,
177    PhpstanReturn,
178    PhpstanVar,
179    PhpstanReadOnly,
180    PhpstanImmutable,
181    Other,
182}
183
184#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash, Serialize, Deserialize, PartialOrd, Ord)]
185pub enum TagVendor {
186    Phpstan,
187    Psalm,
188}
189
190impl TagKind {
191    /// Returns the vendor of the tag, if it has one.
192    ///
193    /// If the tag does not have a vendor, `None` is returned.
194    pub fn get_vendor(&self) -> Option<TagVendor> {
195        match self {
196            Self::PsalmConsistentConstructor
197            | Self::PsalmConsistentTemplates
198            | Self::PsalmParamOut
199            | Self::PsalmVar
200            | Self::PsalmParam
201            | Self::PsalmReturn
202            | Self::PsalmProperty
203            | Self::PsalmPropertyRead
204            | Self::PsalmPropertyWrite
205            | Self::PsalmMethod
206            | Self::PsalmIgnoreVar
207            | Self::PsalmSuppress
208            | Self::PsalmAssert
209            | Self::PsalmAssertIfTrue
210            | Self::PsalmAssertIfFalse
211            | Self::PsalmIfThisIs
212            | Self::PsalmThisOut
213            | Self::PsalmIgnoreNullableReturn
214            | Self::PsalmIgnoreFalsableReturn
215            | Self::PsalmSealProperties
216            | Self::PsalmNoSealProperties
217            | Self::PsalmSealMethods
218            | Self::PsalmNoSealMethods
219            | Self::PsalmInternal
220            | Self::PsalmReadOnly
221            | Self::PsalmMutationFree
222            | Self::PsalmExternalMutationFree
223            | Self::PsalmImmutable
224            | Self::PsalmPure
225            | Self::PsalmAllowPrivateMutation
226            | Self::PsalmReadOnlyAllowPrivateMutation
227            | Self::PsalmTrace
228            | Self::PsalmCheckType
229            | Self::PsalmCheckTypeExact
230            | Self::PsalmTaintSource
231            | Self::PsalmTaintSink
232            | Self::PsalmTaintEscape
233            | Self::PsalmTaintUnescape
234            | Self::PsalmTaintSpecialize
235            | Self::PsalmFlow
236            | Self::PsalmType
237            | Self::PsalmImportType
238            | Self::PsalmRequireExtends
239            | Self::PsalmRequireImplements
240            | Self::PsalmIgnoreVariableProperty
241            | Self::PsalmIgnoreVariableMethod
242            | Self::PsalmYield => Some(TagVendor::Psalm),
243            Self::PhpstanAssert
244            | Self::PhpstanAssertIfTrue
245            | Self::PhpstanAssertIfFalse
246            | Self::PhpstanSelfOut
247            | Self::PhpstanThisOut
248            | Self::PhpstanRequireExtends
249            | Self::PhpstanRequireImplements
250            | Self::PhpstanTemplate
251            | Self::PhpstanTemplateCovariant
252            | Self::PhpstanTemplateContravariant
253            | Self::PhpstanParam
254            | Self::PhpstanReturn
255            | Self::PhpstanVar
256            | Self::PhpstanReadOnly
257            | Self::PhpstanImmutable => Some(TagVendor::Phpstan),
258            _ => None,
259        }
260    }
261
262    /// Returns the non-vendored variant of the tag, if it exists.
263    ///
264    /// Note that not all vendored tags have a non-vendored variant.
265    ///
266    /// If the tag is not vendored, or if it does not have a non-vendored variant,
267    ///  `None` is returned.
268    pub fn get_non_vendored_variant(&self) -> Option<TagKind> {
269        match self {
270            Self::PsalmParamOut => Some(Self::ParamOut),
271            Self::PsalmVar => Some(Self::Var),
272            Self::PsalmParam => Some(Self::Param),
273            Self::PsalmReturn => Some(Self::Return),
274            Self::PsalmProperty => Some(Self::Property),
275            Self::PsalmPropertyRead => Some(Self::PropertyRead),
276            Self::PsalmPropertyWrite => Some(Self::PropertyWrite),
277            Self::PsalmMethod => Some(Self::Method),
278            Self::PsalmSealProperties => Some(Self::SealProperties),
279            Self::PsalmNoSealProperties => Some(Self::NoSealProperties),
280            Self::PsalmSealMethods => Some(Self::SealMethods),
281            Self::PsalmNoSealMethods => Some(Self::NoSealMethods),
282            Self::PsalmInternal => Some(Self::Internal),
283            Self::PsalmReadOnly => Some(Self::ReadOnly),
284            Self::PsalmImmutable => Some(Self::Immutable),
285            Self::PsalmPure => Some(Self::Pure),
286            Self::PhpstanTemplate => Some(Self::Template),
287            Self::PhpstanTemplateCovariant => Some(Self::TemplateCovariant),
288            Self::PhpstanTemplateContravariant => Some(Self::TemplateContravariant),
289            Self::PhpstanParam => Some(Self::Param),
290            Self::PhpstanReturn => Some(Self::Return),
291            Self::PhpstanVar => Some(Self::Var),
292            Self::PhpstanReadOnly => Some(Self::ReadOnly),
293            Self::PhpstanImmutable => Some(Self::Immutable),
294            _ => None,
295        }
296    }
297
298    pub fn is_repeatable(&self) -> bool {
299        matches!(
300            self,
301            Self::Author
302                | Self::Deprecated
303                | Self::Example
304                | Self::Ignore
305                | Self::Link
306                | Self::Method
307                | Self::Mixin
308                | Self::Package
309                | Self::Param
310                | Self::Property
311                | Self::PropertyRead
312                | Self::PropertyWrite
313                | Self::Return
314                | Self::See
315                | Self::Since
316                | Self::Throws
317                | Self::Uses
318                | Self::Var
319        )
320    }
321}
322
323impl<T> From<T> for TagKind
324where
325    T: AsRef<str>,
326{
327    fn from(value: T) -> Self {
328        match value.as_ref().to_ascii_lowercase().as_str() {
329            "abstract" => TagKind::Abstract,
330            "access" => TagKind::Access,
331            "author" => TagKind::Author,
332            "category" => TagKind::Category,
333            "copyright" => TagKind::Copyright,
334            "deprecated" => TagKind::Deprecated,
335            "example" => TagKind::Example,
336            "final" => TagKind::Final,
337            "filesource" => TagKind::FileSource,
338            "global" => TagKind::Global,
339            "ignore" => TagKind::Ignore,
340            "internal" => TagKind::Internal,
341            "license" => TagKind::License,
342            "link" => TagKind::Link,
343            "method" => TagKind::Method,
344            "mixin" => TagKind::Mixin,
345            "name" => TagKind::Name,
346            "package" => TagKind::Package,
347            "param" => TagKind::Param,
348            "property" => TagKind::Property,
349            "property-read" => TagKind::PropertyRead,
350            "propertyread" => TagKind::PropertyRead,
351            "property-write" => TagKind::PropertyWrite,
352            "propertywrite" => TagKind::PropertyWrite,
353            "sealproperties" => TagKind::SealProperties,
354            "seal-properties" => TagKind::SealProperties,
355            "nosealproperties" => TagKind::NoSealProperties,
356            "no-seal-properties" => TagKind::NoSealProperties,
357            "sealmethods" => TagKind::SealMethods,
358            "seal-methods" => TagKind::SealMethods,
359            "nosealmethods" => TagKind::NoSealMethods,
360            "no-seal-methods" => TagKind::NoSealMethods,
361            "readonly" => TagKind::ReadOnly,
362            "nonamedarguments" => TagKind::NoNamedArguments,
363            "no-named-arguments" => TagKind::NoNamedArguments,
364            "template" => TagKind::Template,
365            "psalm-template" => TagKind::PsalmTemplate,
366            "api" => TagKind::Api,
367            "psalm-api" => TagKind::PsalmApi,
368            "psalm-inheritors" => TagKind::PsalmInheritors,
369            "return" => TagKind::Return,
370            "see" => TagKind::See,
371            "since" => TagKind::Since,
372            "static" => TagKind::Static,
373            "staticvar" => TagKind::StaticVar,
374            "static-var" => TagKind::StaticVar,
375            "subpackage" => TagKind::SubPackage,
376            "sub-package" => TagKind::SubPackage,
377            "todo" => TagKind::Todo,
378            "tutorial" => TagKind::Tutorial,
379            "uses" => TagKind::Uses,
380            "var" => TagKind::Var,
381            "throws" => TagKind::Throws,
382            "version" => TagKind::Version,
383            "param-later-invoked-callable" => TagKind::ParamLaterInvokedCallable,
384            "paramlaterinvokedcallable" => TagKind::ParamLaterInvokedCallable,
385            "param-immediately-invoked-callable" => TagKind::ParamImmediatelyInvokedCallable,
386            "paramimmediatelyinvokedcallable" => TagKind::ParamImmediatelyInvokedCallable,
387            "param-closure-this" => TagKind::ParamClosureThis,
388            "paramclosurethis" => TagKind::ParamClosureThis,
389            "template-covariant" => TagKind::TemplateCovariant,
390            "templatecovariant" => TagKind::TemplateCovariant,
391            "template-contravariant" => TagKind::TemplateContravariant,
392            "templatecontravariant" => TagKind::TemplateContravariant,
393            "extends" => TagKind::Extends,
394            "implements" => TagKind::Implements,
395            "use" => TagKind::Use,
396            "not-deprecated" => TagKind::NotDeprecated,
397            "notdeprecated" => TagKind::NotDeprecated,
398            "phpstan-impure" => TagKind::PhpstanImpure,
399            "phpstan-pure" => TagKind::PhpstanPure,
400            "pure" => TagKind::Pure,
401            "immutable" => TagKind::Immutable,
402            "inheritdoc" => TagKind::InheritDoc,
403            "inherit-doc" => TagKind::InheritDoc,
404            "param-out" => TagKind::ParamOut,
405            "psalm-param-out" => TagKind::PsalmParamOut,
406            "psalmconsistentconstructor" => TagKind::PsalmConsistentConstructor,
407            "psalm-consistent-constructor" => TagKind::PsalmConsistentConstructor,
408            "psalmconsistenttemplates" => TagKind::PsalmConsistentTemplates,
409            "psalm-consistent-templates" => TagKind::PsalmConsistentTemplates,
410            "psalm-var" => TagKind::PsalmVar,
411            "psalm-param" => TagKind::PsalmParam,
412            "psalm-return" => TagKind::PsalmReturn,
413            "psalm-property" => TagKind::PsalmProperty,
414            "psalm-property-read" => TagKind::PsalmPropertyRead,
415            "psalm-propertyread" => TagKind::PsalmPropertyRead,
416            "psalm-property-write" => TagKind::PsalmPropertyWrite,
417            "psalm-propertywrite" => TagKind::PsalmPropertyWrite,
418            "psalm-method" => TagKind::PsalmMethod,
419            "psalm-ignore-var" => TagKind::PsalmIgnoreVar,
420            "psalmignorevar" => TagKind::PsalmIgnoreVar,
421            "psalm-suppress" => TagKind::PsalmSuppress,
422            "psalm-assert" => TagKind::PsalmAssert,
423            "psalm-assert-if-true" => TagKind::PsalmAssertIfTrue,
424            "psalm-assertiftrue" => TagKind::PsalmAssertIfTrue,
425            "psalm-assert-if-false" => TagKind::PsalmAssertIfFalse,
426            "psalm-assertiffalse" => TagKind::PsalmAssertIfFalse,
427            "psalm-if-this-is" => TagKind::PsalmIfThisIs,
428            "psalmifthisis" => TagKind::PsalmIfThisIs,
429            "psalm-this-out" => TagKind::PsalmThisOut,
430            "psalmthisout" => TagKind::PsalmThisOut,
431            "psalm-ignore-nullable-return" => TagKind::PsalmIgnoreNullableReturn,
432            "psalmignorenullablereturn" => TagKind::PsalmIgnoreNullableReturn,
433            "psalm-ignore-falsable-return" => TagKind::PsalmIgnoreFalsableReturn,
434            "psalmignorefalsablereturn" => TagKind::PsalmIgnoreFalsableReturn,
435            "psalm-seal-properties" => TagKind::PsalmSealProperties,
436            "psalmsealproperties" => TagKind::PsalmSealProperties,
437            "psalm-no-seal-properties" => TagKind::PsalmNoSealProperties,
438            "psalmnosealproperties" => TagKind::PsalmNoSealProperties,
439            "psalm-seal-methods" => TagKind::PsalmSealMethods,
440            "psalmsealmethods" => TagKind::PsalmSealMethods,
441            "psalm-no-seal-methods" => TagKind::PsalmNoSealMethods,
442            "psalmnosealmethods" => TagKind::PsalmNoSealMethods,
443            "psalm-internal" => TagKind::PsalmInternal,
444            "psalm-readonly" => TagKind::PsalmReadOnly,
445            "psalm-mutation-free" => TagKind::PsalmMutationFree,
446            "psalmmutationfree" => TagKind::PsalmMutationFree,
447            "psalm-external-mutation-free" => TagKind::PsalmExternalMutationFree,
448            "psalmexternalmutationfree" => TagKind::PsalmExternalMutationFree,
449            "psalm-immutable" => TagKind::PsalmImmutable,
450            "psalm-pure" => TagKind::PsalmPure,
451            "psalm-allow-private-mutation" => TagKind::PsalmAllowPrivateMutation,
452            "psalmallowprivatemutation" => TagKind::PsalmAllowPrivateMutation,
453            "psalm-readonly-allow-private-mutation" => TagKind::PsalmReadOnlyAllowPrivateMutation,
454            "psalmreadonlyallowprivatemutation" => TagKind::PsalmReadOnlyAllowPrivateMutation,
455            "psalm-trace" => TagKind::PsalmTrace,
456            "psalm-check-type" => TagKind::PsalmCheckType,
457            "psalmchecktype" => TagKind::PsalmCheckType,
458            "psalm-check-type-exact" => TagKind::PsalmCheckTypeExact,
459            "psalmchecktypeexact" => TagKind::PsalmCheckTypeExact,
460            "psalm-taint-source" => TagKind::PsalmTaintSource,
461            "psalmtaintsource" => TagKind::PsalmTaintSource,
462            "psalm-taint-sink" => TagKind::PsalmTaintSink,
463            "psalmtaintsink" => TagKind::PsalmTaintSink,
464            "psalm-taint-escape" => TagKind::PsalmTaintEscape,
465            "psalmtaintescape" => TagKind::PsalmTaintEscape,
466            "psalm-taint-unescape" => TagKind::PsalmTaintUnescape,
467            "psalmtaintunescape" => TagKind::PsalmTaintUnescape,
468            "psalm-taint-specialize" => TagKind::PsalmTaintSpecialize,
469            "psalmtaintspecialize" => TagKind::PsalmTaintSpecialize,
470            "psalm-flow" => TagKind::PsalmFlow,
471            "psalmflow" => TagKind::PsalmFlow,
472            "psalm-type" => TagKind::PsalmType,
473            "psalm-import-type" => TagKind::PsalmImportType,
474            "psalm-require-extends" => TagKind::PsalmRequireExtends,
475            "psalmrequireextends" => TagKind::PsalmRequireExtends,
476            "psalm-require-implements" => TagKind::PsalmRequireImplements,
477            "psalmrequireimplements" => TagKind::PsalmRequireImplements,
478            "psalm-ignore-variable-property" => TagKind::PsalmIgnoreVariableProperty,
479            "psalmignorevariableproperty" => TagKind::PsalmIgnoreVariableProperty,
480            "psalm-ignore-variable-method" => TagKind::PsalmIgnoreVariableMethod,
481            "psalmignorevariablemethod" => TagKind::PsalmIgnoreVariableMethod,
482            "psalm-yield" => TagKind::PsalmYield,
483            "phpstan-assert" => TagKind::PhpstanAssert,
484            "phpstan-assert-if-true" => TagKind::PhpstanAssertIfTrue,
485            "phpstan-assert-if-false" => TagKind::PhpstanAssertIfFalse,
486            "phpstan-self-out" => TagKind::PhpstanSelfOut,
487            "phpstan-this-out" => TagKind::PhpstanThisOut,
488            "phpstan-require-extends" => TagKind::PhpstanRequireExtends,
489            "phpstan-require-implements" => TagKind::PhpstanRequireImplements,
490            "phpstan-template" => TagKind::PhpstanTemplate,
491            "phpstan-template-covariant" => TagKind::PhpstanTemplateCovariant,
492            "phpstan-template-contravariant" => TagKind::PhpstanTemplateContravariant,
493            "phpstan-param" => TagKind::PhpstanParam,
494            "phpstan-return" => TagKind::PhpstanReturn,
495            "phpstan-var" => TagKind::PhpstanVar,
496            "phpstan-readonly" => TagKind::PhpstanReadOnly,
497            "phpstan-immutable" => TagKind::PhpstanImmutable,
498            _ => TagKind::Other,
499        }
500    }
501}