diff --git a/docs/DocDeprecation.md b/docs/DocDeprecation.md
new file mode 100644
index 0000000..d9cfcd4
--- /dev/null
+++ b/docs/DocDeprecation.md
@@ -0,0 +1,22 @@
+# Summary.DocDeprecation
+```cs
+public record DocDeprecation
+```
+
+Contains deprecation information (e.g. the warning message).
+
+## Properties
+### Message
+```cs
+public string? Message { get; init; }
+```
+
+The deprecation warning message.
+
+### Error
+```cs
+public bool Error { get; init; }
+```
+
+Whether the usage should be treated as an error instead of a warning.
+
diff --git a/docs/DocMember.md b/docs/DocMember.md
index ed00a29..26fe741 100644
--- a/docs/DocMember.md
+++ b/docs/DocMember.md
@@ -49,6 +49,21 @@ public required DocType? DeclaringType { get; init; }
The type that this member is declared in (works for nested types as well).
+### Deprecated
+```cs
+[MemberNotNullWhen(true, nameof(Deprecation))]
+public bool Deprecated { get; }
+```
+
+Whether the member is deprecated (e.g. marked with `[Obsolete]`).
+
+### Deprecation
+```cs
+public DocDeprecation? Deprecation { get; init; }
+```
+
+The member deprecation information.
+
## Methods
### MatchesCref(string)
```cs
diff --git a/docs/Sample{T0,T1}.Child.md b/docs/Sample{T0,T1}.Child.md
index 3bdf914..a0965bc 100644
--- a/docs/Sample{T0,T1}.Child.md
+++ b/docs/Sample{T0,T1}.Child.md
@@ -1,5 +1,9 @@
-# Summary.Samples.Sample.Child
+# ~~Summary.Samples.Sample.Child~~
+> [!WARNING]
+> The type is deprecated.
+
```cs
+[Obsolete(error: true, message: "The type is deprecated.")]
public class Child
```
diff --git a/docs/Sample{T0,T1}.md b/docs/Sample{T0,T1}.md
index e7ba9c7..40f253c 100644
--- a/docs/Sample{T0,T1}.md
+++ b/docs/Sample{T0,T1}.md
@@ -52,8 +52,12 @@ public int Field
A field of the child class.
-### Field1
+### ~~Field1~~
+> [!WARNING]
+> The field is deprecated.
+
```cs
+[Obsolete("The field is deprecated.")]
public int Field1
```
diff --git a/src/Core/DocDeprecation.cs b/src/Core/DocDeprecation.cs
new file mode 100644
index 0000000..ec2465d
--- /dev/null
+++ b/src/Core/DocDeprecation.cs
@@ -0,0 +1,17 @@
+namespace Summary;
+
+///
+/// Contains deprecation information (e.g. the warning message).
+///
+public record DocDeprecation
+{
+ ///
+ /// The deprecation warning message.
+ ///
+ public string? Message { get; init; }
+
+ ///
+ /// Whether the usage should be treated as an error instead of a warning.
+ ///
+ public bool Error { get; init; }
+}
\ No newline at end of file
diff --git a/src/Core/DocMember.cs b/src/Core/DocMember.cs
index 03d3948..4780d01 100644
--- a/src/Core/DocMember.cs
+++ b/src/Core/DocMember.cs
@@ -1,4 +1,6 @@
-namespace Summary;
+using System.Diagnostics.CodeAnalysis;
+
+namespace Summary;
///
/// A member of the generated document (e.g. type, field, property, method, etc.).
@@ -36,6 +38,17 @@ public abstract record DocMember
///
public required DocType? DeclaringType { get; init; }
+ ///
+ /// Whether the member is deprecated (e.g. marked with [Obsolete]).
+ ///
+ [MemberNotNullWhen(true, nameof(Deprecation))]
+ public bool Deprecated => Deprecation is not null;
+
+ ///
+ /// The member deprecation information.
+ ///
+ public DocDeprecation? Deprecation { get; init; }
+
///
/// Whether this member matches the specified `cref` reference.
///
diff --git a/src/Core/Extensions/StringExtensions.cs b/src/Core/Extensions/StringExtensions.cs
index ef3c7ba..e183244 100644
--- a/src/Core/Extensions/StringExtensions.cs
+++ b/src/Core/Extensions/StringExtensions.cs
@@ -16,6 +16,13 @@ public static string Space(this string self) =>
public static string Surround(this string self, string left, string right) =>
self.Map(x => $"{left}{x}{right}");
+ ///
+ /// Surrounds the specified string with the given prefix and suffix strings
+ /// if the specified condition is satisfied. If the string is empty, returns the string as is.
+ ///
+ public static string Surround(this string self, string left, string right, bool when) =>
+ when ? self.Surround(left, right) : self;
+
private static string Map(this string self, Func map) =>
self is "" ? self : map(self);
diff --git a/src/Core/Samples/Sample.cs b/src/Core/Samples/Sample.cs
index b56440b..829ad98 100644
--- a/src/Core/Samples/Sample.cs
+++ b/src/Core/Samples/Sample.cs
@@ -29,6 +29,7 @@ public class Sample
///
/// A child of the class.
///
+ [Obsolete(error: true, message: "The type is deprecated.")]
public class Child
{
///
@@ -45,6 +46,7 @@ public class Child
///
/// A sample field.
///
+ [Obsolete("The field is deprecated.")]
public int Field1;
///
diff --git a/src/Plugins/Markdown/MdRenderer.cs b/src/Plugins/Markdown/MdRenderer.cs
index fde92fb..c6da41c 100644
--- a/src/Plugins/Markdown/MdRenderer.cs
+++ b/src/Plugins/Markdown/MdRenderer.cs
@@ -28,15 +28,15 @@ public void Dispose() =>
_renderer._level -= 2;
}
- private readonly StringBuilder _sb = new();
+ private readonly StringBuilder _builder = new();
private int _level = 1;
///
- /// Converts the rendered text into a string.
+ /// Converts the rendered Markdown into a string.
///
public string Text() =>
- _sb.ToString();
+ _builder.ToString();
///
/// Renders the specified documentation member into Markdown format.
@@ -45,146 +45,177 @@ public string Text() =>
private MdRenderer Member(DocTypeDeclaration? parent, DocMember member) => member switch
{
- DocTypeDeclaration type =>
- MemberHeader(type).TypeDeclaration(type),
- DocMethod method =>
- MemberHeader(method).Method(method),
- DocProperty { Generated: true } generated =>
- GeneratedProperty(parent!, generated),
- DocIndexer indexer =>
- MemberHeader(indexer).Indexer(indexer),
- _ =>
- MemberHeader(member),
+ DocTypeDeclaration type => TypeDeclaration(type),
+ DocMethod method => Method(method),
+ DocProperty property => Property(parent!, property),
+ _ => Header(member),
};
- private MdRenderer TypeDeclaration(DocTypeDeclaration type) => TypeParamsSection(type)
- .MembersSection("Delegates", type, x => x.Delegate)
- .MembersSection("Events", type, x => x.Event)
- .MembersSection("Fields", type)
- .MembersSection("Properties", type, x => !x.Event && x is not DocIndexer)
- .MembersSection("Indexers", type)
- .MembersSection("Methods", type, x => !x.Delegate);
+ private MdRenderer TypeDeclaration(DocTypeDeclaration type) => this
+ .Header(type)
+ .TypeParams(type)
+ .Members("Delegates", type, x => x.Delegate)
+ .Members("Events", type, x => x.Event)
+ .Members("Fields", type)
+ .Members("Properties", type, x => !x.Event && x is not DocIndexer)
+ .Members("Indexers", type)
+ .Members("Methods", type, x => !x.Delegate);
+
+ private MdRenderer Method(DocMethod method) => this
+ .Header(method)
+ .TypeParams(method)
+ .Params(method)
+ .Returns(method.Comment);
+
+ private MdRenderer Property(DocTypeDeclaration parent, DocProperty property)
+ {
+ if (property.Generated)
+ return this
+ .Name(property)
+ .Declaration(property)
+ .Element(parent.Comment.Param(property.Name));
- private MdRenderer Method(DocMethod method) => TypeParamsSection(method)
- .ParamsSection(method)
- .ReturnsSection(method.Comment);
+ if (property is DocIndexer indexer)
+ return Indexer(indexer);
- private MdRenderer Indexer(DocIndexer indexer) => ParamsSection(indexer)
- .ReturnsSection(indexer.Comment);
+ return Header(property);
+ }
- private MdRenderer MemberHeader(DocMember member) => Name(member)
+ private MdRenderer Header(DocMember member) => this
+ .Name(member)
+ .Deprecation(member.Deprecation)
.Declaration(member)
.Element(member.Comment.Element("summary"))
.Element(member.Comment.Element("remarks"), x => $"_{x}_")
- .ElementSection("Example", member.Comment.Element("example"));
+ .Elements("Example", member.Comment.Element("example"));
- private MdRenderer GeneratedProperty(DocTypeDeclaration parent, DocMember prop) => Name(prop)
- .Declaration(prop)
- .Element(parent.Comment.Param(prop.Name));
+ private MdRenderer Indexer(DocIndexer indexer) => this
+ .Header(indexer)
+ .Params(indexer)
+ .Returns(indexer.Comment);
// TODO: We can omit rendering `Name` and render `Declaration` only but it'd be nice to make this customizable via plugins.
private MdRenderer Name(DocMember member) => member switch
{
- DocMethod x =>
+ DocMethod method =>
Line($"{new string(c: '#', _level)} " +
- $"{x.Name}" +
- $"{x.TypeParams.Select(x => x.Name).Separated(", ").Surround("<", ">")}" +
- $"({x.Params.Select(x => x.Type?.FullName).NonNulls().Separated(", ")})"),
- DocIndexer x =>
- Line($"{new string(c: '#', _level)} this[{x.Params.Select(x => x.Type?.Name).NonNulls().Separated(", ")}]"),
- DocTypeDeclaration x when _level is 1 =>
- Line($"{new string(c: '#', _level)} {member.FullyQualifiedName}{x.TypeParams.Select(x => x.Name).Separated(with: ", ").Surround("<", ">")}"),
+ $"{method.Name.Surround("~~", "~~", when: method.Deprecated)}" +
+ $"{method.TypeParams.Select(x => x.Name).Separated(", ").Surround("<", ">")}" +
+ $"({method.Params.Select(x => x.Type?.FullName).NonNulls().Separated(", ")})"),
+ DocIndexer indexer =>
+ Line($"{new string(c: '#', _level)} this[{indexer.Params.Select(x => x.Type?.Name).NonNulls().Separated(", ")}]"),
+ DocTypeDeclaration type when _level is 1 =>
+ Line($"{new string(c: '#', _level)} {type.FullyQualifiedName.Surround("~~", "~~", when: type.Deprecated)}{type.TypeParams.Select(x => x.Name).Separated(with: ", ").Surround("<", ">")}"),
_ =>
- Line($"{new string(c: '#', _level)} {member.Name}"),
+ Line($"{new string(c: '#', _level)} {member.Name.Surround("~~", "~~", when: member.Deprecated)}"),
};
- private MdRenderer ElementSection(string name, DocCommentElement? element, Func? map = null) =>
- element is null ? this : Line($"{new string(c: '#', _level + 1)} {name}").Element(element, map);
+ private MdRenderer Deprecation(DocDeprecation? deprecation)
+ {
+ if (!string.IsNullOrWhiteSpace(deprecation?.Message))
+ {
+ // We currently render the deprecation message as an alert: https://github.com/orgs/community/discussions/16925.
+ // > Alerts are an extension of Markdown used to emphasize critical information. On GitHub, they
+ // > are displayed with distinctive colors and icons to indicate the importance of the content.
+ return this
+ .Line($"> [!WARNING]")
+ .Line($"> {deprecation.Message}")
+ .Line();
+ }
+
+ return this;
+ }
- private MdRenderer Declaration(DocMember member) => Line("```cs")
+ private MdRenderer Declaration(DocMember member) => this
+ .Line("```cs")
.Line(member.Declaration)
.Line("```")
.Line();
- private MdRenderer TypeParamsSection(DocMethod method) =>
- ParamsSection("Type Parameters", method.TypeParams.Select(x => (x.Name, x.Comment(method))));
+ private MdRenderer TypeParams(DocMethod method) =>
+ Params("Type Parameters", method.TypeParams.Select(x => (x.Name, x.Comment(method))));
- private MdRenderer TypeParamsSection(DocTypeDeclaration type) =>
- ParamsSection("Type Parameters", type.TypeParams.Select(x => (x.Name, x.Comment(type))));
+ private MdRenderer TypeParams(DocTypeDeclaration type) =>
+ Params("Type Parameters", type.TypeParams.Select(x => (x.Name, x.Comment(type))));
- private MdRenderer ParamsSection(DocMethod method) =>
- ParamsSection("Parameters", method.Params.Select(x => (x.Name, x.Comment(method))));
+ private MdRenderer Params(DocMethod method) =>
+ Params("Parameters", method.Params.Select(x => (x.Name, x.Comment(method))));
- private MdRenderer ParamsSection(DocIndexer method) =>
- ParamsSection("Parameters", method.Params.Select(x => (x.Name, x.Comment(method))));
+ private MdRenderer Params(DocIndexer method) =>
+ Params("Parameters", method.Params.Select(x => (x.Name, x.Comment(method))));
- private MdRenderer ParamsSection(string section, IEnumerable<(string Name, DocCommentElement? Comment)> parameters)
- {
- if (parameters.All(x => x.Comment is null))
- return this;
+ private MdRenderer Params(string section, IEnumerable<(string Name, DocCommentElement? Comment)> parameters) =>
+ Params(section, parameters.Where(x => x.Comment is not null).ToList()!);
- Section(section);
+ private MdRenderer Params(string section, ICollection<(string Name, DocCommentElement Comment)> parameters) =>
+ Section(section, parameters, x => Line($"- `{x.Name}`: {x.Comment.Render()}")).Line(when: parameters.Any());
- foreach (var param in parameters)
- Line($"- `{param.Name}`: {param.Comment.Render()}");
+ private MdRenderer Members(string section, DocTypeDeclaration type) where T : DocMember =>
+ Members(section, type, _ => true);
- return Line();
- }
+ private MdRenderer Members(string section, DocTypeDeclaration type, Func p) where T : DocMember =>
+ Members(section, type, type.Members.OfType().Where(p));
- private MdRenderer ReturnsSection(DocComment comment) =>
- ElementSection("Returns", comment.Element("returns"));
+ private MdRenderer Members(string section, DocTypeDeclaration type, IEnumerable members) where T : DocMember =>
+ Section(section, members, x => Member(type, x));
- private MdRenderer MembersSection(string section, DocTypeDeclaration type) where T : DocMember =>
- MembersSection(section, type, _ => true);
+ private MdRenderer Returns(DocComment comment) =>
+ Elements("Returns", comment.Element("returns"));
- private MdRenderer MembersSection(string section, DocTypeDeclaration type, Func p) where T : DocMember =>
- MembersSection(section, type, type.Members.OfType().Where(p));
+ private MdRenderer Elements(string section, DocCommentElement? element, Func? map = null) =>
+ element is null ? this : Section(section).Element(element, map);
- private MdRenderer MembersSection(string section, DocTypeDeclaration type, IEnumerable members) where T : DocMember =>
- MembersSection(section, type, members, Member);
-
- private MdRenderer MembersSection(
- string section,
- DocTypeDeclaration type,
- IEnumerable members,
- Func render) where T : DocMember
+ private MdRenderer Element(DocCommentElement? element, Func? map = null)
{
- if (members.Any())
- {
- Section(section);
+ if (element is null)
+ return this;
- using var _ = new Scope(this);
+ var lines = element
+ .Render()
+ .Split(NewLine)
+ .Select(x => x is "" ? x : map?.Invoke(x) ?? x);
- foreach (var x in members)
- render(type, x);
- }
+ foreach (var line in lines)
+ Line(line);
+
+ return Line();
+ }
+ private MdRenderer Section(string name)
+ {
+ _builder.Append('#', _level + 1).Append(' ').AppendLine(name);
return this;
}
- private MdRenderer Element(DocCommentElement? element, Func? map = null)
+ private MdRenderer Section(string name, IEnumerable items, Action render)
{
- if (element is null)
- return this;
+ var scope = null as IDisposable;
- var lines =
- element
- .Render()
- .Split(NewLine)
- .Select(x => x is "" ? x : map?.Invoke(x) ?? x);
+ try
+ {
+ foreach (var item in items)
+ {
+ scope ??= Section(name).Scoped();
- foreach (var line in lines)
- Line(line);
+ render(item);
+ }
+ }
+ finally
+ {
+ scope?.Dispose();
+ }
- return Line();
+ return this;
}
- private MdRenderer Section(string name) =>
- Line($"{new string(c: '#', _level + 1)} {name}");
+ private MdRenderer Line(string text = "", bool when = true)
+ {
+ if (when)
+ _builder.AppendLine(text);
- private MdRenderer Line(string s = "", bool when = true) =>
- With(when ? _sb.AppendLine(s) : _sb);
+ return this;
+ }
- private MdRenderer With(T _) =>
- this;
+ private Scope Scoped() =>
+ new(this);
}
\ No newline at end of file
diff --git a/src/Plugins/Markdown/RenderMarkdownPipe.cs b/src/Plugins/Markdown/RenderMarkdownPipe.cs
index d22c84d..a480447 100644
--- a/src/Plugins/Markdown/RenderMarkdownPipe.cs
+++ b/src/Plugins/Markdown/RenderMarkdownPipe.cs
@@ -10,12 +10,12 @@ public class RenderMarkdownPipe : IPipe
{
public Task Run(Doc doc) =>
Task.FromResult(doc
- .Members
- .Concat(doc
.Members
- .OfType()
- .SelectMany(x => x.AllMembers.OfType()))
- .Select(Render).ToArray());
+ .Concat(doc
+ .Members
+ .OfType()
+ .SelectMany(x => x.AllMembers.OfType()))
+ .Select(Render).ToArray());
private static Md Render(DocMember member)
{
@@ -25,7 +25,7 @@ private static Md Render(DocMember member)
string Name(DocMember x) => x switch
{
- DocTypeDeclaration { DeclaringType: null } type => $"{x.Name}{TypeParams(type)}",
+ DocTypeDeclaration { DeclaringType: null } type => $"{x.Name}{TypeParams(type)}",
DocTypeDeclaration { DeclaringType: not null } type => $"{type.DeclaringType!.FullName.AsCref()}.{x.Name}{TypeParams(type)}",
_ => x.Name,
diff --git a/src/Plugins/Roslyn/CSharp/Extensions/FieldSyntaxExtensions.cs b/src/Plugins/Roslyn/CSharp/Extensions/FieldSyntaxExtensions.cs
index 0743ad3..b64530d 100644
--- a/src/Plugins/Roslyn/CSharp/Extensions/FieldSyntaxExtensions.cs
+++ b/src/Plugins/Roslyn/CSharp/Extensions/FieldSyntaxExtensions.cs
@@ -32,5 +32,6 @@ private static DocField Field(this VariableDeclaratorSyntax self, FieldDeclarati
Access = field.Access(),
Comment = field.Comment(),
DeclaringType = self.DeclaringType(),
+ Deprecation = field.AttributeLists.Deprecation(),
};
}
\ No newline at end of file
diff --git a/src/Plugins/Roslyn/CSharp/Extensions/MethodSyntaxExtensions.cs b/src/Plugins/Roslyn/CSharp/Extensions/MethodSyntaxExtensions.cs
index 13beee8..30a200e 100644
--- a/src/Plugins/Roslyn/CSharp/Extensions/MethodSyntaxExtensions.cs
+++ b/src/Plugins/Roslyn/CSharp/Extensions/MethodSyntaxExtensions.cs
@@ -20,6 +20,7 @@ public static DocMethod Method(this MethodDeclarationSyntax self) =>
Access = self.Access(),
Comment = self.Comment(),
DeclaringType = self.DeclaringType(),
+ Deprecation = self.AttributeLists.Deprecation(),
Params = self.ParameterList.Params(),
TypeParams = self.TypeParameterList.TypeParams(),
Delegate = false,
@@ -39,6 +40,7 @@ public static DocMethod Method(this MethodDeclarationSyntax self) =>
Params = self.ParameterList.Params(),
TypeParams = self.TypeParameterList.TypeParams(),
DeclaringType = self.DeclaringType(),
+ Deprecation = self.AttributeLists.Deprecation(),
Delegate = true,
};
}
\ No newline at end of file
diff --git a/src/Plugins/Roslyn/CSharp/Extensions/PropertySyntaxExtensions.cs b/src/Plugins/Roslyn/CSharp/Extensions/PropertySyntaxExtensions.cs
index 57fef30..588a94e 100644
--- a/src/Plugins/Roslyn/CSharp/Extensions/PropertySyntaxExtensions.cs
+++ b/src/Plugins/Roslyn/CSharp/Extensions/PropertySyntaxExtensions.cs
@@ -27,6 +27,7 @@ public static DocProperty Property(this PropertyDeclarationSyntax self) =>
Access = self.Access(),
Comment = self.Comment(),
DeclaringType = self.DeclaringType(),
+ Deprecation = self.AttributeLists.Deprecation(),
Generated = false,
Event = false,
};
@@ -47,6 +48,7 @@ public static DocProperty Property(this ParameterSyntax self) =>
Access = AccessModifier.Public,
Comment = DocComment.Empty,
DeclaringType = self.DeclaringType(),
+ Deprecation = self.AttributeLists.Deprecation(),
Generated = true,
Event = false,
};
@@ -64,6 +66,7 @@ public static DocProperty Property(this EventDeclarationSyntax self) =>
Access = self.Access(),
Comment = self.Comment(),
DeclaringType = self.DeclaringType(),
+ Deprecation = self.AttributeLists.Deprecation(),
Generated = false,
Event = true,
};
@@ -90,6 +93,7 @@ public static DocIndexer Indexer(this IndexerDeclarationSyntax self) =>
Access = self.Access(),
Comment = self.Comment(),
DeclaringType = self.DeclaringType(),
+ Deprecation = self.AttributeLists.Deprecation(),
Generated = false,
Event = false,
Params = self.ParameterList.Params(),
@@ -105,6 +109,7 @@ private static DocProperty Property(this VariableDeclaratorSyntax self, EventFie
Access = field.Access(),
Comment = field.Comment(),
DeclaringType = self.DeclaringType(),
+ Deprecation = field.AttributeLists.Deprecation(),
Generated = false,
Event = true,
};
diff --git a/src/Plugins/Roslyn/CSharp/Extensions/SyntaxExtensions.cs b/src/Plugins/Roslyn/CSharp/Extensions/SyntaxExtensions.cs
index 6152a1f..f2bbae0 100644
--- a/src/Plugins/Roslyn/CSharp/Extensions/SyntaxExtensions.cs
+++ b/src/Plugins/Roslyn/CSharp/Extensions/SyntaxExtensions.cs
@@ -81,6 +81,59 @@ public static AccessModifier Access(this MemberDeclarationSyntax self)
public static DocType? DeclaringType(this SyntaxNode self) =>
self.Ancestors().OfType().FirstOrDefault()?.Type();
+ ///
+ /// A that contains the member deprecation information.
+ ///
+ public static DocDeprecation? Deprecation(this SyntaxList self)
+ {
+ var attribute = self
+ .SelectMany(x => x.Attributes)
+ .FirstOrDefault(x => x.Name.ToString() is
+ "Obsolete" or "System.Obsolete" or "global::System.Obsolete" or
+ "ObsoleteAttribute" or "System.ObsoleteAttribute" or "global::System.ObsoleteAttribute");
+
+ if (attribute is null)
+ return null;
+
+ return new DocDeprecation
+ {
+ Message = Message(attribute),
+ Error = Error(attribute),
+ };
+
+ static string? Message(AttributeSyntax attribute)
+ {
+ var message = Argument(attribute, position: 0, name: "message")?.Expression.ToString();
+ if (message is not null && message.StartsWith("\"") && message.EndsWith("\""))
+ return message[1..^1];
+
+ return message;
+ }
+
+ static bool Error(AttributeSyntax attribute)
+ {
+ var error = Argument(attribute, position: 1, name: "error")?.Expression.ToString();
+
+ return bool.TryParse(error, out var parsed) && parsed;
+ }
+
+ static AttributeArgumentSyntax? Argument(AttributeSyntax attribute, int position, string name)
+ {
+ if (attribute.ArgumentList is null)
+ return null;
+
+ if (attribute.ArgumentList.Arguments.Count > position)
+ {
+ var argument = attribute.ArgumentList.Arguments[position];
+ if (argument is { NameColon: null, NameEquals: null })
+ return argument;
+ }
+
+ return attribute.ArgumentList.Arguments.FirstOrDefault(
+ x => x.NameColon?.Name.Identifier.ValueText == name);
+ }
+ }
+
///
/// A list of attributes of the specified member formatted as a string.
///
diff --git a/src/Plugins/Roslyn/CSharp/Extensions/TypeDeclarationSyntaxExtensions.cs b/src/Plugins/Roslyn/CSharp/Extensions/TypeDeclarationSyntaxExtensions.cs
index 83af0f9..f79804e 100644
--- a/src/Plugins/Roslyn/CSharp/Extensions/TypeDeclarationSyntaxExtensions.cs
+++ b/src/Plugins/Roslyn/CSharp/Extensions/TypeDeclarationSyntaxExtensions.cs
@@ -21,6 +21,7 @@ public static DocTypeDeclaration TypeDeclaration(this TypeDeclarationSyntax self
Access = self.Access(),
Comment = self.Comment(),
DeclaringType = self.DeclaringType(),
+ Deprecation = self.AttributeLists.Deprecation(),
Members = self.Members(),
TypeParams = self.TypeParams(),
Base = self.BaseList?.Types.Select(x => x.Type.Type()).ToArray() ?? Array.Empty(),