mago_docblock/
document.rs

1use bumpalo::collections::Vec;
2use serde::Serialize;
3
4use mago_span::HasSpan;
5use mago_span::Span;
6
7#[derive(Debug, Clone, Eq, PartialEq, Hash, Serialize, PartialOrd, Ord)]
8pub struct Document<'arena> {
9    pub span: Span,
10    pub elements: Vec<'arena, Element<'arena>>,
11}
12
13#[derive(Debug, Clone, Eq, PartialEq, Hash, Serialize, PartialOrd, Ord)]
14pub enum Element<'arena> {
15    Text(Text<'arena>),
16    Code(Code<'arena>),
17    Tag(Tag<'arena>),
18    Line(Span),
19    Annotation(Annotation<'arena>),
20}
21
22#[derive(Debug, Clone, Eq, PartialEq, Hash, Serialize, PartialOrd, Ord)]
23pub struct Text<'arena> {
24    pub span: Span,
25    pub segments: Vec<'arena, TextSegment<'arena>>,
26}
27
28#[derive(Debug, Clone, Eq, PartialEq, Hash, Serialize, PartialOrd, Ord)]
29pub struct Code<'arena> {
30    pub span: Span,
31    pub directives: Vec<'arena, &'arena str>,
32    pub content: &'arena str,
33}
34
35#[derive(Debug, Clone, Eq, PartialEq, Hash, Serialize, PartialOrd, Ord)]
36pub enum TextSegment<'arena> {
37    Paragraph { span: Span, content: &'arena str },
38    InlineCode(Code<'arena>),
39    InlineTag(Tag<'arena>),
40}
41
42#[derive(Debug, Clone, Eq, PartialEq, Hash, Serialize, PartialOrd, Ord)]
43pub struct Annotation<'arena> {
44    pub span: Span,
45    pub name: &'arena str,
46    pub arguments: Option<&'arena str>,
47}
48
49#[derive(Debug, Clone, Eq, PartialEq, Hash, Serialize, PartialOrd, Ord)]
50pub struct Tag<'arena> {
51    pub span: Span,
52    pub name: &'arena str,
53    pub kind: TagKind,
54    pub description: &'arena str,
55    pub description_span: Span,
56}
57
58#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash, Serialize, PartialOrd, Ord)]
59#[non_exhaustive]
60pub enum TagKind {
61    Abstract,
62    Access,
63    Author,
64    Category,
65    Copyright,
66    Deprecated,
67    Example,
68    Final,
69    FileSource,
70    Global,
71    Ignore,
72    Internal,
73    License,
74    Link,
75    Method,
76    Mixin,
77    Name,
78    Package,
79    Param,
80    Property,
81    PropertyRead,
82    PropertyWrite,
83    SealProperties,
84    NoSealProperties,
85    SealMethods,
86    NoSealMethods,
87    ReadOnly,
88    NoNamedArguments,
89    Api,
90    PsalmApi,
91    Inheritors,
92    PsalmInheritors,
93    Return,
94    See,
95    Since,
96    Static,
97    StaticVar,
98    SubPackage,
99    Todo,
100    Tutorial,
101    Uses,
102    Var,
103    Throws,
104    Version,
105    ParamLaterInvokedCallable,
106    ParamImmediatelyInvokedCallable,
107    ParamClosureThis,
108    TemplateExtends,
109    Extends,
110    TemplateImplements,
111    Implements,
112    TemplateUse,
113    Use,
114    NotDeprecated,
115    PhpstanImpure,
116    PhpstanPure,
117    Pure,
118    Immutable,
119    RequireExtends,
120    RequireImplements,
121    InheritDoc,
122    ParamOut,
123    Assert,
124    AssertIfTrue,
125    AssertIfFalse,
126    ConsistentConstructor,
127    PsalmConsistentConstructor,
128    PsalmConsistentTemplates,
129    PsalmParamOut,
130    PsalmVar,
131    PsalmParam,
132    PsalmReturn,
133    PsalmProperty,
134    PsalmPropertyRead,
135    PsalmPropertyWrite,
136    PsalmMethod,
137    PsalmIgnoreVar,
138    PsalmSuppress,
139    PsalmAssert,
140    PsalmAssertIfTrue,
141    PsalmAssertIfFalse,
142    PsalmIfThisIs,
143    PsalmThisOut,
144    IgnoreNullableReturn,
145    IgnoreFalsableReturn,
146    PsalmIgnoreNullableReturn,
147    PsalmIgnoreFalsableReturn,
148    PsalmSealProperties,
149    PsalmNoSealProperties,
150    PsalmSealMethods,
151    PsalmNoSealMethods,
152    PsalmInternal,
153    PsalmReadOnly,
154    PsalmMutationFree,
155    PsalmExternalMutationFree,
156    MutationFree,
157    ExternalMutationFree,
158    PsalmImmutable,
159    PsalmPure,
160    PsalmAllowPrivateMutation,
161    PsalmReadOnlyAllowPrivateMutation,
162    PsalmTrace,
163    PsalmCheckType,
164    PsalmCheckTypeExact,
165    PsalmTaintSource,
166    PsalmTaintSink,
167    PsalmTaintEscape,
168    PsalmTaintUnescape,
169    PsalmTaintSpecialize,
170    PsalmFlow,
171    Type,
172    PsalmType,
173    PhpstanType,
174    ImportType,
175    PsalmImportType,
176    PhpstanImportType,
177    PsalmRequireExtends,
178    PsalmRequireImplements,
179    PsalmIgnoreVariableProperty,
180    PsalmIgnoreVariableMethod,
181    PsalmYield,
182    PhpstanAssert,
183    PhpstanAssertIfTrue,
184    PhpstanAssertIfFalse,
185    PhpstanSelfOut,
186    PhpstanThisOut,
187    PhpstanRequireExtends,
188    PhpstanRequireImplements,
189    PhpstanParam,
190    PhpstanReturn,
191    PhpstanVar,
192    PhpstanReadOnly,
193    PhpstanImmutable,
194    Template,
195    TemplateInvariant,
196    TemplateCovariant,
197    TemplateContravariant,
198    PsalmTemplate,
199    PsalmTemplateInvariant,
200    PsalmTemplateCovariant,
201    PsalmTemplateContravariant,
202    PhpstanTemplate,
203    PhpstanTemplateInvariant,
204    PhpstanTemplateCovariant,
205    PhpstanTemplateContravariant,
206    EnumInterface,
207    MagoUnchecked,
208    Unchecked,
209    ThisOut,
210    SelfOut,
211    Where,
212    MustUse,
213    Other,
214}
215
216#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash, Serialize, PartialOrd, Ord)]
217#[repr(u8)]
218pub enum TagVendor {
219    Mago,
220    Phpstan,
221    Psalm,
222}
223
224impl<'arena> Document<'arena> {
225    pub fn get_tags(&self) -> impl Iterator<Item = &Tag<'arena>> {
226        self.elements.iter().filter_map(|element| if let Element::Tag(tag) = element { Some(tag) } else { None })
227    }
228
229    pub fn get_tags_by_kind(&self, kind: TagKind) -> impl Iterator<Item = &Tag<'arena>> {
230        self.get_tags().filter(move |tag| tag.kind == kind)
231    }
232}
233
234impl HasSpan for Document<'_> {
235    fn span(&self) -> Span {
236        self.span
237    }
238}
239
240impl TagKind {
241    /// Returns the vendor of the tag, if it has one.
242    ///
243    /// If the tag does not have a vendor, `None` is returned.
244    #[must_use]
245    pub fn get_vendor(&self) -> Option<TagVendor> {
246        match self {
247            Self::PsalmConsistentConstructor
248            | Self::PsalmConsistentTemplates
249            | Self::PsalmParamOut
250            | Self::PsalmVar
251            | Self::PsalmParam
252            | Self::PsalmReturn
253            | Self::PsalmProperty
254            | Self::PsalmPropertyRead
255            | Self::PsalmPropertyWrite
256            | Self::PsalmMethod
257            | Self::PsalmIgnoreVar
258            | Self::PsalmSuppress
259            | Self::PsalmAssert
260            | Self::PsalmAssertIfTrue
261            | Self::PsalmAssertIfFalse
262            | Self::PsalmIfThisIs
263            | Self::PsalmThisOut
264            | Self::PsalmIgnoreNullableReturn
265            | Self::PsalmIgnoreFalsableReturn
266            | Self::PsalmSealProperties
267            | Self::PsalmNoSealProperties
268            | Self::PsalmSealMethods
269            | Self::PsalmNoSealMethods
270            | Self::PsalmInternal
271            | Self::PsalmReadOnly
272            | Self::PsalmMutationFree
273            | Self::PsalmExternalMutationFree
274            | Self::PsalmImmutable
275            | Self::PsalmPure
276            | Self::PsalmAllowPrivateMutation
277            | Self::PsalmReadOnlyAllowPrivateMutation
278            | Self::PsalmTrace
279            | Self::PsalmCheckType
280            | Self::PsalmCheckTypeExact
281            | Self::PsalmTaintSource
282            | Self::PsalmTaintSink
283            | Self::PsalmTaintEscape
284            | Self::PsalmTaintUnescape
285            | Self::PsalmTaintSpecialize
286            | Self::PsalmFlow
287            | Self::PsalmType
288            | Self::PsalmRequireExtends
289            | Self::PsalmRequireImplements
290            | Self::PsalmIgnoreVariableProperty
291            | Self::PsalmIgnoreVariableMethod
292            | Self::PsalmYield
293            | Self::PsalmTemplate
294            | Self::PsalmTemplateInvariant
295            | Self::PsalmTemplateCovariant
296            | Self::PsalmTemplateContravariant
297            | Self::PsalmInheritors
298            | Self::PsalmImportType => Some(TagVendor::Psalm),
299            Self::PhpstanAssert
300            | Self::PhpstanAssertIfTrue
301            | Self::PhpstanAssertIfFalse
302            | Self::PhpstanSelfOut
303            | Self::PhpstanThisOut
304            | Self::PhpstanRequireExtends
305            | Self::PhpstanRequireImplements
306            | Self::PhpstanTemplate
307            | Self::PhpstanTemplateInvariant
308            | Self::PhpstanTemplateCovariant
309            | Self::PhpstanTemplateContravariant
310            | Self::PhpstanParam
311            | Self::PhpstanReturn
312            | Self::PhpstanVar
313            | Self::PhpstanReadOnly
314            | Self::PhpstanImmutable => Some(TagVendor::Phpstan),
315            Self::MagoUnchecked => Some(TagVendor::Mago),
316            _ => None,
317        }
318    }
319
320    /// Returns the non-vendored variant of the tag, if it exists.
321    ///
322    /// Note that not all vendored tags have a non-vendored variant.
323    ///
324    /// If the tag is not vendored, or if it does not have a non-vendored variant,
325    ///  `None` is returned.
326    #[must_use]
327    pub fn get_non_vendored_variant(&self) -> Option<TagKind> {
328        match self {
329            Self::PsalmConsistentConstructor => Some(Self::ConsistentConstructor),
330            Self::PsalmParamOut => Some(Self::ParamOut),
331            Self::PsalmVar => Some(Self::Var),
332            Self::PsalmParam => Some(Self::Param),
333            Self::PsalmReturn => Some(Self::Return),
334            Self::PsalmProperty => Some(Self::Property),
335            Self::PsalmPropertyRead => Some(Self::PropertyRead),
336            Self::PsalmPropertyWrite => Some(Self::PropertyWrite),
337            Self::PsalmMethod => Some(Self::Method),
338            Self::PsalmSealProperties => Some(Self::SealProperties),
339            Self::PsalmNoSealProperties => Some(Self::NoSealProperties),
340            Self::PsalmSealMethods => Some(Self::SealMethods),
341            Self::PsalmNoSealMethods => Some(Self::NoSealMethods),
342            Self::PsalmInternal => Some(Self::Internal),
343            Self::PsalmReadOnly => Some(Self::ReadOnly),
344            Self::PsalmImmutable => Some(Self::Immutable),
345            Self::PsalmPure => Some(Self::Pure),
346            Self::PhpstanParam => Some(Self::Param),
347            Self::PhpstanReturn => Some(Self::Return),
348            Self::PhpstanVar => Some(Self::Var),
349            Self::PhpstanReadOnly => Some(Self::ReadOnly),
350            Self::PhpstanImmutable => Some(Self::Immutable),
351            Self::PhpstanAssert | Self::PsalmAssert => Some(Self::Assert),
352            Self::PhpstanAssertIfTrue | Self::PsalmAssertIfTrue => Some(Self::AssertIfTrue),
353            Self::PhpstanAssertIfFalse | Self::PsalmAssertIfFalse => Some(Self::AssertIfFalse),
354            Self::PhpstanTemplate | Self::PsalmTemplate => Some(Self::Template),
355            Self::PhpstanTemplateInvariant | Self::PsalmTemplateInvariant => Some(Self::TemplateInvariant),
356            Self::PhpstanTemplateCovariant | Self::PsalmTemplateCovariant => Some(Self::TemplateCovariant),
357            Self::PhpstanTemplateContravariant | Self::PsalmTemplateContravariant => Some(Self::TemplateContravariant),
358            Self::PsalmMutationFree => Some(Self::MutationFree),
359            Self::PsalmExternalMutationFree => Some(Self::ExternalMutationFree),
360            Self::PsalmIgnoreFalsableReturn => Some(Self::IgnoreFalsableReturn),
361            Self::PsalmIgnoreNullableReturn => Some(Self::IgnoreNullableReturn),
362            Self::PsalmInheritors => Some(Self::Inheritors),
363            Self::MagoUnchecked => Some(Self::Unchecked),
364            Self::PsalmType => Some(Self::Type),
365            Self::PsalmImportType => Some(Self::ImportType),
366            Self::PhpstanRequireExtends | Self::PsalmRequireExtends => Some(Self::RequireExtends),
367            Self::PhpstanRequireImplements | Self::PsalmRequireImplements => Some(Self::RequireImplements),
368            Self::PsalmThisOut | Self::PhpstanThisOut => Some(Self::ThisOut),
369            Self::PhpstanSelfOut => Some(Self::SelfOut),
370            _ => None,
371        }
372    }
373
374    #[must_use]
375    pub fn is_repeatable(&self) -> bool {
376        matches!(
377            self,
378            Self::Author
379                | Self::Deprecated
380                | Self::Example
381                | Self::Ignore
382                | Self::Link
383                | Self::Method
384                | Self::Mixin
385                | Self::Package
386                | Self::Param
387                | Self::Property
388                | Self::PropertyRead
389                | Self::PropertyWrite
390                | Self::Return
391                | Self::See
392                | Self::Since
393                | Self::Throws
394                | Self::Uses
395                | Self::Var
396                | Self::Template
397                | Self::TemplateInvariant
398                | Self::TemplateCovariant
399                | Self::TemplateContravariant
400                | Self::PsalmTemplate
401                | Self::PsalmTemplateInvariant
402                | Self::PsalmTemplateCovariant
403                | Self::PsalmTemplateContravariant
404                | Self::PhpstanTemplate
405                | Self::PhpstanTemplateInvariant
406                | Self::PhpstanTemplateCovariant
407                | Self::PhpstanTemplateContravariant
408                | Self::PhpstanParam
409                | Self::PhpstanVar
410                | Self::PsalmVar
411                | Self::PsalmParam
412                | Self::Extends
413                | Self::TemplateExtends
414                | Self::Implements
415                | Self::TemplateImplements
416                | Self::Use
417                | Self::TemplateUse
418                | Self::PsalmType
419                | Self::Type
420                | Self::PsalmImportType
421                | Self::RequireImplements
422                | Self::PsalmRequireImplements
423                | Self::PhpstanRequireImplements
424                | Self::RequireExtends
425                | Self::PsalmRequireExtends
426                | Self::PhpstanRequireExtends
427                | Self::Where
428        )
429    }
430}
431
432impl<T> From<T> for TagKind
433where
434    T: AsRef<str>,
435{
436    fn from(value: T) -> Self {
437        match value.as_ref().to_ascii_lowercase().as_str() {
438            "abstract" => TagKind::Abstract,
439            "access" => TagKind::Access,
440            "author" => TagKind::Author,
441            "category" => TagKind::Category,
442            "copyright" => TagKind::Copyright,
443            "deprecated" => TagKind::Deprecated,
444            "example" => TagKind::Example,
445            "final" => TagKind::Final,
446            "filesource" => TagKind::FileSource,
447            "global" => TagKind::Global,
448            "ignore" => TagKind::Ignore,
449            "internal" => TagKind::Internal,
450            "license" => TagKind::License,
451            "link" => TagKind::Link,
452            "method" => TagKind::Method,
453            "mixin" => TagKind::Mixin,
454            "name" => TagKind::Name,
455            "package" => TagKind::Package,
456            "param" => TagKind::Param,
457            "property" => TagKind::Property,
458            "property-read" => TagKind::PropertyRead,
459            "propertyread" => TagKind::PropertyRead,
460            "property-write" => TagKind::PropertyWrite,
461            "propertywrite" => TagKind::PropertyWrite,
462            "sealproperties" => TagKind::SealProperties,
463            "seal-properties" => TagKind::SealProperties,
464            "nosealproperties" => TagKind::NoSealProperties,
465            "no-seal-properties" => TagKind::NoSealProperties,
466            "sealmethods" => TagKind::SealMethods,
467            "seal-methods" => TagKind::SealMethods,
468            "nosealmethods" => TagKind::NoSealMethods,
469            "no-seal-methods" => TagKind::NoSealMethods,
470            "readonly" => TagKind::ReadOnly,
471            "nonamedarguments" => TagKind::NoNamedArguments,
472            "no-named-arguments" => TagKind::NoNamedArguments,
473            "api" => TagKind::Api,
474            "psalm-api" => TagKind::PsalmApi,
475            "psalm-inheritors" | "psalminheritors" => TagKind::PsalmInheritors,
476            "inheritors" => TagKind::Inheritors,
477            "return" => TagKind::Return,
478            "see" => TagKind::See,
479            "since" => TagKind::Since,
480            "static" => TagKind::Static,
481            "staticvar" => TagKind::StaticVar,
482            "static-var" => TagKind::StaticVar,
483            "subpackage" => TagKind::SubPackage,
484            "sub-package" => TagKind::SubPackage,
485            "todo" => TagKind::Todo,
486            "tutorial" => TagKind::Tutorial,
487            "uses" => TagKind::Uses,
488            "var" => TagKind::Var,
489            "throws" => TagKind::Throws,
490            "version" => TagKind::Version,
491            "assert" => TagKind::Assert,
492            "assert-if-true" | "assertiftrue" => TagKind::AssertIfTrue,
493            "assert-if-false" | "assertiffalse" => TagKind::AssertIfFalse,
494            "param-later-invoked-callable" => TagKind::ParamLaterInvokedCallable,
495            "paramlaterinvokedcallable" => TagKind::ParamLaterInvokedCallable,
496            "param-immediately-invoked-callable" => TagKind::ParamImmediatelyInvokedCallable,
497            "paramimmediatelyinvokedcallable" => TagKind::ParamImmediatelyInvokedCallable,
498            "param-closure-this" => TagKind::ParamClosureThis,
499            "paramclosurethis" => TagKind::ParamClosureThis,
500            "extends" => TagKind::Extends,
501            "template-extends" | "templateextends" => TagKind::TemplateExtends,
502            "implements" => TagKind::Implements,
503            "template-implements" | "templateimplements" => TagKind::TemplateImplements,
504            "use" => TagKind::Use,
505            "template-use" | "templateuse" => TagKind::TemplateUse,
506            "not-deprecated" | "notdeprecated" => TagKind::NotDeprecated,
507            "phpstan-impure" | "phpstanimpure" => TagKind::PhpstanImpure,
508            "phpstan-pure" | "phpstanpure" => TagKind::PhpstanPure,
509            "pure" => TagKind::Pure,
510            "immutable" => TagKind::Immutable,
511            "inheritdoc" | "inheritdocs" | "inherit-doc" | "inherit-docs" => TagKind::InheritDoc,
512            "param-out" => TagKind::ParamOut,
513            "psalm-param-out" => TagKind::PsalmParamOut,
514            "consistentconstructor" | "consistent-constructor" => TagKind::ConsistentConstructor,
515            "psalmconsistentconstructor" | "psalm-consistent-constructor" => TagKind::PsalmConsistentConstructor,
516            "psalmconsistenttemplates" | "psalm-consistent-templates" => TagKind::PsalmConsistentTemplates,
517            "psalm-var" => TagKind::PsalmVar,
518            "psalm-param" => TagKind::PsalmParam,
519            "psalm-return" => TagKind::PsalmReturn,
520            "psalm-property" => TagKind::PsalmProperty,
521            "psalm-property-read" => TagKind::PsalmPropertyRead,
522            "psalm-propertyread" => TagKind::PsalmPropertyRead,
523            "psalm-property-write" => TagKind::PsalmPropertyWrite,
524            "psalm-propertywrite" => TagKind::PsalmPropertyWrite,
525            "psalm-method" => TagKind::PsalmMethod,
526            "psalm-ignore-var" => TagKind::PsalmIgnoreVar,
527            "psalmignorevar" => TagKind::PsalmIgnoreVar,
528            "psalm-suppress" => TagKind::PsalmSuppress,
529            "psalm-assert" => TagKind::PsalmAssert,
530            "psalm-assert-if-true" | "psalmassertiftrue" => TagKind::PsalmAssertIfTrue,
531            "psalm-assert-if-false" | "psalmassertiffalse" => TagKind::PsalmAssertIfFalse,
532            "psalm-if-this-is" | "psalmifthisis" => TagKind::PsalmIfThisIs,
533            "psalm-this-out" | "psalmthisout" => TagKind::PsalmThisOut,
534            "ignore-nullable-return" | "ignorenullablereturn" => TagKind::IgnoreNullableReturn,
535            "ignore-falsable-return" | "ignorefalsablereturn" => TagKind::IgnoreFalsableReturn,
536            "psalm-ignore-nullable-return" | "psalmignorenullablereturn" => TagKind::PsalmIgnoreNullableReturn,
537            "psalm-ignore-falsable-return" | "psalmignorefalsablereturn" => TagKind::PsalmIgnoreFalsableReturn,
538            "psalm-seal-properties" => TagKind::PsalmSealProperties,
539            "psalmsealproperties" => TagKind::PsalmSealProperties,
540            "psalm-no-seal-properties" => TagKind::PsalmNoSealProperties,
541            "psalmnosealproperties" => TagKind::PsalmNoSealProperties,
542            "psalm-seal-methods" => TagKind::PsalmSealMethods,
543            "psalmsealmethods" => TagKind::PsalmSealMethods,
544            "psalm-no-seal-methods" => TagKind::PsalmNoSealMethods,
545            "psalmnosealmethods" => TagKind::PsalmNoSealMethods,
546            "psalm-internal" => TagKind::PsalmInternal,
547            "psalm-readonly" => TagKind::PsalmReadOnly,
548            "psalm-mutation-free" | "psalmmutationfree" => TagKind::PsalmMutationFree,
549            "psalm-external-mutation-free" | "psalmexternalmutationfree" => TagKind::PsalmExternalMutationFree,
550            "mutation-free" | "mutationfree" => TagKind::MutationFree,
551            "external-mutation-free" | "externalmutationfree" => TagKind::ExternalMutationFree,
552            "psalm-immutable" => TagKind::PsalmImmutable,
553            "psalm-pure" => TagKind::PsalmPure,
554            "psalm-allow-private-mutation" => TagKind::PsalmAllowPrivateMutation,
555            "psalmallowprivatemutation" => TagKind::PsalmAllowPrivateMutation,
556            "psalm-readonly-allow-private-mutation" => TagKind::PsalmReadOnlyAllowPrivateMutation,
557            "psalmreadonlyallowprivatemutation" => TagKind::PsalmReadOnlyAllowPrivateMutation,
558            "psalm-trace" => TagKind::PsalmTrace,
559            "psalm-check-type" => TagKind::PsalmCheckType,
560            "psalmchecktype" => TagKind::PsalmCheckType,
561            "psalm-check-type-exact" => TagKind::PsalmCheckTypeExact,
562            "psalmchecktypeexact" => TagKind::PsalmCheckTypeExact,
563            "psalm-taint-source" => TagKind::PsalmTaintSource,
564            "psalmtaintsource" => TagKind::PsalmTaintSource,
565            "psalm-taint-sink" => TagKind::PsalmTaintSink,
566            "psalmtaintsink" => TagKind::PsalmTaintSink,
567            "psalm-taint-escape" => TagKind::PsalmTaintEscape,
568            "psalmtaintescape" => TagKind::PsalmTaintEscape,
569            "psalm-taint-unescape" => TagKind::PsalmTaintUnescape,
570            "psalmtaintunescape" => TagKind::PsalmTaintUnescape,
571            "psalm-taint-specialize" => TagKind::PsalmTaintSpecialize,
572            "psalmtaintspecialize" => TagKind::PsalmTaintSpecialize,
573            "psalm-flow" => TagKind::PsalmFlow,
574            "psalmflow" => TagKind::PsalmFlow,
575            "psalm-require-extends" => TagKind::PsalmRequireExtends,
576            "psalmrequireextends" => TagKind::PsalmRequireExtends,
577            "psalm-require-implements" => TagKind::PsalmRequireImplements,
578            "psalmrequireimplements" => TagKind::PsalmRequireImplements,
579            "psalm-ignore-variable-property" => TagKind::PsalmIgnoreVariableProperty,
580            "psalmignorevariableproperty" => TagKind::PsalmIgnoreVariableProperty,
581            "psalm-ignore-variable-method" => TagKind::PsalmIgnoreVariableMethod,
582            "psalmignorevariablemethod" => TagKind::PsalmIgnoreVariableMethod,
583            "psalm-yield" => TagKind::PsalmYield,
584            "phpstan-assert" => TagKind::PhpstanAssert,
585            "phpstan-assert-if-true" => TagKind::PhpstanAssertIfTrue,
586            "phpstan-assert-if-false" => TagKind::PhpstanAssertIfFalse,
587            "phpstan-self-out" | "phpstanselfout" => TagKind::PhpstanSelfOut,
588            "phpstan-this-out" | "phpstanthisout" => TagKind::PhpstanThisOut,
589            "phpstan-require-extends" | "phpstanrequireextends" => TagKind::PhpstanRequireExtends,
590            "phpstan-require-implements" | "phpstanrequireimplements" => TagKind::PhpstanRequireImplements,
591            "template" => TagKind::Template,
592            "template-invariant" | "templateinvariant" => TagKind::TemplateInvariant,
593            "template-covariant" | "templatecovariant" => TagKind::TemplateCovariant,
594            "template-contravariant" | "templatecontravariant" => TagKind::TemplateContravariant,
595            "psalm-template" | "psalmtemplate" => TagKind::PsalmTemplate,
596            "psalm-template-invariant" | "psalmtemplateinvariant" => TagKind::PsalmTemplateInvariant,
597            "psalm-template-covariant" | "psalmtemplatecovariant" => TagKind::PsalmTemplateCovariant,
598            "psalm-template-contravariant" | "psalmtemplatecontravariant" => TagKind::PsalmTemplateContravariant,
599            "phpstan-template" | "phpstantemplate" => TagKind::PhpstanTemplate,
600            "phpstan-template-invariant" | "phpstantemplateinvariant" => TagKind::PhpstanTemplateInvariant,
601            "phpstan-template-covariant" | "phpstantemplatecovariant" => TagKind::PhpstanTemplateCovariant,
602            "phpstan-template-contravariant" | "phpstantemplatecontravariant" => TagKind::PhpstanTemplateContravariant,
603            "phpstan-param" => TagKind::PhpstanParam,
604            "phpstan-return" => TagKind::PhpstanReturn,
605            "phpstan-var" => TagKind::PhpstanVar,
606            "phpstan-readonly" => TagKind::PhpstanReadOnly,
607            "phpstan-immutable" => TagKind::PhpstanImmutable,
608            "enuminterface" | "enum-interface" => TagKind::EnumInterface,
609            "mago-unchecked" | "magounchecked" => TagKind::MagoUnchecked,
610            "unchecked" => TagKind::Unchecked,
611            "type" => TagKind::Type,
612            "phpstan-type" | "phpstantype" => TagKind::PhpstanType,
613            "psalm-type" | "psalmtype" => TagKind::PsalmType,
614            "import-type" | "importtype" => TagKind::ImportType,
615            "phpstan-import-type" | "phpstanimporttype" => TagKind::PhpstanImportType,
616            "psalm-import-type" | "psalmimporttype" => TagKind::PsalmImportType,
617            "require-implements" | "requireimplements" => TagKind::RequireImplements,
618            "require-extends" | "requireextends" => TagKind::RequireExtends,
619            "self-out" | "selfout" => TagKind::SelfOut,
620            "this-out" | "thisout" => TagKind::ThisOut,
621            "where" => TagKind::Where,
622            "must-use" | "mustuse" => TagKind::MustUse,
623            _ => TagKind::Other,
624        }
625    }
626}
627
628impl TagVendor {
629    #[must_use]
630    pub fn as_str(&self) -> &'static str {
631        match self {
632            Self::Mago => "mago",
633            Self::Phpstan => "phpstan",
634            Self::Psalm => "psalm",
635        }
636    }
637}