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