Repository: microsoft/kiota (csharp)

Issue:
Deprecation information generates templates without resolving the types in the templates.
Code writers are not calling the `GetDescription` methods when writing deprecation information. The template is therefore generated withoour resolving the type parameters. 

This causes ambiguous comments as reported in https://github.com/microsoftgraph/msgraph-sdk-dotnet/issues/2336

Pull request description:
Closes https://github.com/microsoft/kiota/issues/4186

Fixes deprecation descriptions missing type information if a template is passed with type parameters. 

Sample generation present at https://github.com/microsoftgraph/msgraph-sdk-dotnet/commit/7208d0626aaf6a9dc323533505f1967d7fd613a0

Patch:
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 40f04bb798..3b434be70c 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -20,6 +20,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
 - Fixed return doc comments for Go/Java/CSharp/TypeScript.
 - Fixed type names in doc comments and deprecation noticed across languages.
 - Added thrown exceptions in doc comments for Go/CSharp/Java/TypeScript. [#3811](https://github.com/microsoft/kiota/issues/3811)
+- Fixed missing type/method names in deprecation comments.[#4186](https://github.com/microsoft/kiota/issues/4186)
 - Fixed `cref` tags not closed in doc comments in CSharp generation.
 - Deduplicates 4XX and 5XX error mappings when they map to the same type to reduce emitted code. [#4025](https://github.com/microsoft/kiota/issues/4025)
 - 📢📢📢 Java generation is now stable! 🚀🚀🚀 special thanks to @andreaTP (Red Hat) for all the help.
diff --git a/src/Kiota.Builder/Writers/CSharp/CSharpConventionService.cs b/src/Kiota.Builder/Writers/CSharp/CSharpConventionService.cs
index dbbb3bdff5..6c71029cf6 100644
--- a/src/Kiota.Builder/Writers/CSharp/CSharpConventionService.cs
+++ b/src/Kiota.Builder/Writers/CSharp/CSharpConventionService.cs
@@ -38,7 +38,9 @@ public static void WriteNullableClosing(LanguageWriter writer)
     }
     private const string ReferenceTypePrefix = "<see cref=\"";
     private const string ReferenceTypeSuffix = "\"/>";
+#pragma warning disable S1006 // Method overrides should not change parameter defaults
     public override void WriteShortDescription(IDocumentedElement element, LanguageWriter writer, string prefix = "<summary>", string suffix = "</summary>")
+#pragma warning restore S1006 // Method overrides should not change parameter defaults
     {
         ArgumentNullException.ThrowIfNull(writer);
         ArgumentNullException.ThrowIfNull(element);
@@ -293,14 +295,14 @@ _ when nameof(String).Equals(parameterType, StringComparison.OrdinalIgnoreCase)
         };
         return $"{GetDeprecationInformation(parameter)}{parameterType} {parameter.Name.ToFirstCharacterLowerCase()}{defaultValue}";
     }
-    private static string GetDeprecationInformation(IDeprecableElement element)
+    private string GetDeprecationInformation(IDeprecableElement element)
     {
         if (element.Deprecation is null || !element.Deprecation.IsDeprecated) return string.Empty;
 
         var versionComment = string.IsNullOrEmpty(element.Deprecation.Version) ? string.Empty : $" as of {element.Deprecation.Version}";
         var dateComment = element.Deprecation.Date is null ? string.Empty : $" on {element.Deprecation.Date.Value.Date.ToString("yyyy-MM-dd", CultureInfo.InvariantCulture)}";
         var removalComment = element.Deprecation.RemovalDate is null ? string.Empty : $" and will be removed {element.Deprecation.RemovalDate.Value.Date.ToString("yyyy-MM-dd", CultureInfo.InvariantCulture)}";
-        return $"[Obsolete(\"{element.Deprecation.DescriptionTemplate}{versionComment}{dateComment}{removalComment}\")]";
+        return $"[Obsolete(\"{element.Deprecation.GetDescription(type => GetTypeString(type, (element as CodeElement)!).Split('.', StringSplitOptions.TrimEntries)[^1])}{versionComment}{dateComment}{removalComment}\")]";
     }
     internal void WriteDeprecationAttribute(IDeprecableElement element, LanguageWriter writer)
     {
diff --git a/src/Kiota.Builder/Writers/Go/GoConventionService.cs b/src/Kiota.Builder/Writers/Go/GoConventionService.cs
index fc4c739d58..df513ad5be 100644
--- a/src/Kiota.Builder/Writers/Go/GoConventionService.cs
+++ b/src/Kiota.Builder/Writers/Go/GoConventionService.cs
@@ -266,6 +266,6 @@ internal void WriteDeprecation(IDeprecableElement element, LanguageWriter writer
         var versionComment = string.IsNullOrEmpty(element.Deprecation.Version) ? string.Empty : $" as of {element.Deprecation.Version}";
         var dateComment = element.Deprecation.Date is null ? string.Empty : $" on {element.Deprecation.Date.Value.Date.ToString("yyyy-MM-dd", CultureInfo.InvariantCulture)}";
         var removalComment = element.Deprecation.RemovalDate is null ? string.Empty : $" and will be removed {element.Deprecation.RemovalDate.Value.Date.ToString("yyyy-MM-dd", CultureInfo.InvariantCulture)}";
-        WriteDescriptionItem($"Deprecated: {element.Deprecation.DescriptionTemplate}{versionComment}{dateComment}{removalComment}", writer);
+        WriteDescriptionItem($"Deprecated: {element.Deprecation.GetDescription(type => GetTypeString(type, (element as CodeElement)!).TrimStart('*'))}{versionComment}{dateComment}{removalComment}", writer);
     }
 }
diff --git a/src/Kiota.Builder/Writers/Java/JavaConventionService.cs b/src/Kiota.Builder/Writers/Java/JavaConventionService.cs
index 314a0404a5..33d6b49fa4 100644
--- a/src/Kiota.Builder/Writers/Java/JavaConventionService.cs
+++ b/src/Kiota.Builder/Writers/Java/JavaConventionService.cs
@@ -181,7 +181,7 @@ private string[] GetDeprecationInformationForDocumentationComment(IDeprecableEle
         var removalComment = element.Deprecation.RemovalDate is null ? string.Empty : $" and will be removed {element.Deprecation.RemovalDate.Value.Date.ToString("yyyy-MM-dd", CultureInfo.InvariantCulture)}";
         return [
             $"@deprecated",
-            $"{element.Deprecation.DescriptionTemplate}{versionComment}{dateComment}{removalComment}"
+            $"{element.Deprecation.GetDescription(type => GetTypeString(type, (element as CodeElement)!))}{versionComment}{dateComment}{removalComment}"
         ];
     }
     internal void WriteDeprecatedAnnotation(CodeElement element, LanguageWriter writer)
diff --git a/src/Kiota.Builder/Writers/Python/PythonConventionService.cs b/src/Kiota.Builder/Writers/Python/PythonConventionService.cs
index 4f1a146415..b4b58b8ad3 100644
--- a/src/Kiota.Builder/Writers/Python/PythonConventionService.cs
+++ b/src/Kiota.Builder/Writers/Python/PythonConventionService.cs
@@ -202,14 +202,14 @@ public void WriteInLineDescription(IDocumentedElement element, LanguageWriter wr
         writer.WriteLine($"{InLineCommentPrefix}{description}");
     }
 
-    private static string GetDeprecationInformation(IDeprecableElement element)
+    private string GetDeprecationInformation(IDeprecableElement element)
     {
         if (element.Deprecation is null || !element.Deprecation.IsDeprecated) return string.Empty;
 
         var versionComment = string.IsNullOrEmpty(element.Deprecation.Version) ? string.Empty : $" as of {element.Deprecation.Version}";
         var dateComment = element.Deprecation.Date is null ? string.Empty : $" on {element.Deprecation.Date.Value.Date.ToString("yyyy-MM-dd", CultureInfo.InvariantCulture)}";
         var removalComment = element.Deprecation.RemovalDate is null ? string.Empty : $" and will be removed {element.Deprecation.RemovalDate.Value.Date.ToString("yyyy-MM-dd", CultureInfo.InvariantCulture)}";
-        return $"{element.Deprecation.DescriptionTemplate}{versionComment}{dateComment}{removalComment}";
+        return $"{element.Deprecation.GetDescription(type => GetTypeString(type, (element as CodeElement)!))}{versionComment}{dateComment}{removalComment}";
     }
     internal void WriteDeprecationWarning(IDeprecableElement element, LanguageWriter writer)
     {
diff --git a/src/Kiota.Builder/Writers/TypeScript/TypeScriptConventionService.cs b/src/Kiota.Builder/Writers/TypeScript/TypeScriptConventionService.cs
index 3b0e16617e..7d7bd6a39b 100644
--- a/src/Kiota.Builder/Writers/TypeScript/TypeScriptConventionService.cs
+++ b/src/Kiota.Builder/Writers/TypeScript/TypeScriptConventionService.cs
@@ -178,6 +178,6 @@ private string GetDeprecationComment(IDeprecableElement element)
         var versionComment = string.IsNullOrEmpty(element.Deprecation.Version) ? string.Empty : $" as of {element.Deprecation.Version}";
         var dateComment = element.Deprecation.Date is null ? string.Empty : $" on {element.Deprecation.Date.Value.Date.ToString("yyyy-MM-dd", CultureInfo.InvariantCulture)}";
         var removalComment = element.Deprecation.RemovalDate is null ? string.Empty : $" and will be removed {element.Deprecation.RemovalDate.Value.Date.ToString("yyyy-MM-dd", CultureInfo.InvariantCulture)}";
-        return $"@deprecated {element.Deprecation.DescriptionTemplate}{versionComment}{dateComment}{removalComment}";
+        return $"@deprecated {element.Deprecation.GetDescription(type => GetTypeString(type, (element as CodeElement)!))}{versionComment}{dateComment}{removalComment}";
     }
 }


Test patch:
diff --git a/tests/Kiota.Builder.Tests/Writers/CSharp/CodeMethodWriterTests.cs b/tests/Kiota.Builder.Tests/Writers/CSharp/CodeMethodWriterTests.cs
index aa2aae7a81..2dc8a949f3 100644
--- a/tests/Kiota.Builder.Tests/Writers/CSharp/CodeMethodWriterTests.cs
+++ b/tests/Kiota.Builder.Tests/Writers/CSharp/CodeMethodWriterTests.cs
@@ -1838,4 +1838,16 @@ public void WritesDeprecationInformation()
         Assert.Contains("v2.0", result);
         Assert.Contains("[Obsolete", result);
     }
+
+    [Fact]
+    public void WritesDeprecationInformationFromBuilder()
+    {
+        setup();
+        var newMethod = method.Clone() as CodeMethod;
+        newMethod.Name = "NewAwesomeMethod";// new method replacement
+        method.Deprecation = new("This method is obsolete. Use {TypeName} instead.", IsDeprecated: true, TypeReferences: new() { { "TypeName", new CodeType { TypeDefinition = newMethod, IsExternal = false } } });
+        writer.Write(method);
+        var result = tw.ToString();
+        Assert.Contains("This method is obsolete. Use NewAwesomeMethod instead.", result);
+    }
 }
diff --git a/tests/Kiota.Builder.Tests/Writers/Go/CodeMethodWriterTests.cs b/tests/Kiota.Builder.Tests/Writers/Go/CodeMethodWriterTests.cs
index bda3bbc109..da4ee17d6b 100644
--- a/tests/Kiota.Builder.Tests/Writers/Go/CodeMethodWriterTests.cs
+++ b/tests/Kiota.Builder.Tests/Writers/Go/CodeMethodWriterTests.cs
@@ -2177,6 +2177,17 @@ public void WritesDeprecationInformation()
         Assert.Contains("// Deprecated:", result);
     }
     [Fact]
+    public void WritesDeprecationInformationFromBuilder()
+    {
+        setup();
+        var newMethod = method.Clone() as CodeMethod;
+        newMethod.Name = "NewAwesomeMethod";// new method replacement
+        method.Deprecation = new("This method is obsolete. Use {TypeName} instead.", IsDeprecated: true, TypeReferences: new() { { "TypeName", new CodeType { TypeDefinition = newMethod, IsExternal = false } } });
+        writer.Write(method);
+        var result = tw.ToString();
+        Assert.Contains("This method is obsolete. Use NewAwesomeMethod instead.", result);
+    }
+    [Fact]
     public void WritesComposedMarker()
     {
         setup();
diff --git a/tests/Kiota.Builder.Tests/Writers/Java/CodeMethodWriterTests.cs b/tests/Kiota.Builder.Tests/Writers/Java/CodeMethodWriterTests.cs
index b1ccaebbc6..1fa32f6de4 100644
--- a/tests/Kiota.Builder.Tests/Writers/Java/CodeMethodWriterTests.cs
+++ b/tests/Kiota.Builder.Tests/Writers/Java/CodeMethodWriterTests.cs
@@ -2070,6 +2070,17 @@ public void WritesDeprecationInformation()
         Assert.Contains("@Deprecated", result);
     }
     [Fact]
+    public void WritesDeprecationInformationFromBuilder()
+    {
+        setup();
+        var newMethod = method.Clone() as CodeMethod;
+        newMethod.Name = "NewAwesomeMethod";// new method replacement
+        method.Deprecation = new("This method is obsolete. Use NewAwesomeMethod instead.", IsDeprecated: true, TypeReferences: new() { { "TypeName", new CodeType { TypeDefinition = newMethod, IsExternal = false } } });
+        writer.Write(method);
+        var result = tw.ToString();
+        Assert.Contains("This method is obsolete. Use NewAwesomeMethod instead.", result);
+    }
+    [Fact]
     public void WritesMessageOverrideOnPrimary()
     {
         // Given
diff --git a/tests/Kiota.Builder.Tests/Writers/Python/CodeMethodWriterTests.cs b/tests/Kiota.Builder.Tests/Writers/Python/CodeMethodWriterTests.cs
index 5e7f62bf0f..6693c4ba59 100644
--- a/tests/Kiota.Builder.Tests/Writers/Python/CodeMethodWriterTests.cs
+++ b/tests/Kiota.Builder.Tests/Writers/Python/CodeMethodWriterTests.cs
@@ -2191,4 +2191,15 @@ public void WritesDeprecationInformation()
         Assert.Contains("v2.0", result);
         Assert.Contains("warn(", result);
     }
+    [Fact]
+    public void WritesDeprecationInformationFromBuilder()
+    {
+        setup();
+        var newMethod = method.Clone() as CodeMethod;
+        newMethod.Name = "NewAwesomeMethod";// new method replacement
+        method.Deprecation = new("This method is obsolete. Use NewAwesomeMethod instead.", IsDeprecated: true, TypeReferences: new() { { "TypeName", new CodeType { TypeDefinition = newMethod, IsExternal = false } } });
+        writer.Write(method);
+        var result = tw.ToString();
+        Assert.Contains("This method is obsolete. Use NewAwesomeMethod instead.", result);
+    }
 }
diff --git a/tests/Kiota.Builder.Tests/Writers/TypeScript/CodeFunctionWriterTests.cs b/tests/Kiota.Builder.Tests/Writers/TypeScript/CodeFunctionWriterTests.cs
index 456da14378..18358913bb 100644
--- a/tests/Kiota.Builder.Tests/Writers/TypeScript/CodeFunctionWriterTests.cs
+++ b/tests/Kiota.Builder.Tests/Writers/TypeScript/CodeFunctionWriterTests.cs
@@ -677,6 +677,25 @@ public void WritesDeprecationInformation()
         Assert.Contains("v2.0", result);
         Assert.Contains("@deprecated", result);
     }
+    [Fact]
+    public void WritesDeprecationInformationFromBuilder()
+    {
+        var parentClass = root.AddClass(new CodeClass
+        {
+            Name = "ODataError",
+            Kind = CodeClassKind.Model,
+        }).First();
+        var method = TestHelper.CreateMethod(parentClass, MethodName, ReturnTypeName);
+        method.Kind = CodeMethodKind.Factory;
+        method.IsStatic = true;
+        method.Name = "NewAwesomeMethod";// new method replacement
+        method.Deprecation = new("This method is obsolete. Use {TypeName} instead.", IsDeprecated: true, TypeReferences: new() { { "TypeName", new CodeType { TypeDefinition = method, IsExternal = false } } });
+        var function = new CodeFunction(method);
+        root.TryAddCodeFile("foo", function);
+        writer.Write(function);
+        var result = tw.ToString();
+        Assert.Contains("This method is obsolete. Use NewAwesomeMethod instead.", result);
+    }
     private const string MethodDescription = "some description";
     private const string ParamDescription = "some parameter description";
     private const string ParamName = "paramName";