diff --git a/dotnet/src/AutoGen.SourceGenerator/Template/FunctionCallTemplate.cs b/dotnet/src/AutoGen.SourceGenerator/Template/FunctionCallTemplate.cs
index 40adbdcde47..cb3574a8b1e 100644
--- a/dotnet/src/AutoGen.SourceGenerator/Template/FunctionCallTemplate.cs
+++ b/dotnet/src/AutoGen.SourceGenerator/Template/FunctionCallTemplate.cs
@@ -1,31 +1,30 @@
-// ------------------------------------------------------------------------------
+//------------------------------------------------------------------------------
//
// This code was generated by a tool.
-// Runtime Version: 17.0.0.0
-//
+//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
//
-// ------------------------------------------------------------------------------
-namespace AutoGen.SourceGenerator.Template
-{
+//------------------------------------------------------------------------------
+
+namespace AutoGen.SourceGenerator.Template {
using System.Linq;
using System.Collections.Generic;
using Microsoft.CodeAnalysis;
using System;
- ///
- /// Class to produce the template output
- ///
- [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.TextTemplating", "17.0.0.0")]
- internal partial class FunctionCallTemplate : FunctionCallTemplateBase
- {
- ///
- /// Create the template output
- ///
- public virtual string TransformText()
- {
- this.Write("");
+
+ internal partial class FunctionCallTemplate : FunctionCallTemplateBase {
+
+
+public string NameSpace {get; set;}
+public string ClassName {get; set;}
+public IEnumerable FunctionContracts {get; set;}
+public bool IsStatic {get; set;} = false;
+
+
+ public virtual string TransformText() {
+ this.GenerationEnvironment = null;
this.Write(@"//----------------------
//
// This code was generated by a tool.
@@ -42,407 +41,281 @@ public virtual string TransformText()
if (!String.IsNullOrEmpty(NameSpace)) {
this.Write("namespace ");
this.Write(this.ToStringHelper.ToStringWithCulture(NameSpace));
- this.Write("\r\n{\r\n");
+ this.Write("\n{\n");
}
this.Write(" public partial class ");
this.Write(this.ToStringHelper.ToStringWithCulture(ClassName));
- this.Write("\r\n {\r\n");
+ this.Write("\n {\n");
foreach (var functionContract in FunctionContracts) {
- this.Write("\r\n private class ");
+ this.Write("\n private class ");
this.Write(this.ToStringHelper.ToStringWithCulture(functionContract.GetFunctionSchemaClassName()));
- this.Write("\r\n {\r\n");
+ this.Write("\n {\n");
foreach (var parameter in functionContract.Parameters) {
if (parameter.IsOptional) {
this.Write(" [JsonPropertyName(@\"");
this.Write(this.ToStringHelper.ToStringWithCulture(parameter.Name));
- this.Write("\")]\r\n\t\t\tpublic ");
+ this.Write("\")]\n\t\t\tpublic ");
this.Write(this.ToStringHelper.ToStringWithCulture(parameter.Type));
this.Write(" ");
this.Write(this.ToStringHelper.ToStringWithCulture(parameter.Name));
this.Write(" {get; set;} = ");
this.Write(this.ToStringHelper.ToStringWithCulture(parameter.DefaultValue));
- this.Write(";\r\n");
+ this.Write(";\n");
} else {
this.Write(" [JsonPropertyName(@\"");
this.Write(this.ToStringHelper.ToStringWithCulture(parameter.Name));
- this.Write("\")]\r\n\t\t\tpublic ");
+ this.Write("\")]\n\t\t\tpublic ");
this.Write(this.ToStringHelper.ToStringWithCulture(parameter.Type));
this.Write(" ");
this.Write(this.ToStringHelper.ToStringWithCulture(parameter.Name));
- this.Write(" {get; set;}\r\n");
+ this.Write(" {get; set;}\n");
}
}
- this.Write(" }\r\n\r\n public ");
+ this.Write(" }\n\n public ");
this.Write(this.ToStringHelper.ToStringWithCulture(functionContract.ReturnType));
this.Write(" ");
this.Write(this.ToStringHelper.ToStringWithCulture(functionContract.GetFunctionWrapperName()));
- this.Write("(string arguments)\r\n {\r\n var schema = JsonSerializer.Deserializ" +
- "e<");
+ this.Write("(string arguments)\n {\n var schema = JsonSerializer.Deserialize<" +
+ "");
this.Write(this.ToStringHelper.ToStringWithCulture(functionContract.GetFunctionSchemaClassName()));
- this.Write(">(\r\n arguments, \r\n new JsonSerializerOptions\r\n " +
- " {\r\n PropertyNamingPolicy = JsonNamingPolicy.CamelC" +
- "ase,\r\n });\r\n");
+ this.Write(">(\n arguments, \n new JsonSerializerOptions\n " +
+ " {\n PropertyNamingPolicy = JsonNamingPolicy.CamelCase," +
+ "\n });\n");
var argumentLists = string.Join(", ", functionContract.Parameters.Select(p => $"schema.{p.Name}"));
- this.Write("\r\n return ");
+ this.Write("\n return ");
this.Write(this.ToStringHelper.ToStringWithCulture(functionContract.Name));
this.Write("(");
this.Write(this.ToStringHelper.ToStringWithCulture(argumentLists));
- this.Write(");\r\n }\r\n\r\n public FunctionContract ");
+ this.Write(");\n }\n\n public FunctionContract ");
this.Write(this.ToStringHelper.ToStringWithCulture(functionContract.GetFunctionContractName()));
- this.Write("\r\n {\r\n get => new FunctionContract\r\n {\r\n");
+ this.Write("\n {\n get => new FunctionContract\n {\n");
if (functionContract.Namespace != null) {
this.Write(" Namespace = @\"");
this.Write(this.ToStringHelper.ToStringWithCulture(functionContract.Namespace));
- this.Write("\",\r\n");
+ this.Write("\",\n");
}
if (functionContract.ClassName != null) {
this.Write(" ClassName = @\"");
this.Write(this.ToStringHelper.ToStringWithCulture(functionContract.ClassName));
- this.Write("\",\r\n");
+ this.Write("\",\n");
}
if (functionContract.Name != null) {
this.Write(" Name = @\"");
this.Write(this.ToStringHelper.ToStringWithCulture(functionContract.Name));
- this.Write("\",\r\n");
+ this.Write("\",\n");
}
if (functionContract.Description != null) {
this.Write(" Description = @\"");
- this.Write(this.ToStringHelper.ToStringWithCulture(functionContract.Description));
- this.Write("\",\r\n");
+ this.Write(this.ToStringHelper.ToStringWithCulture(functionContract.Description.Replace("\"", "\"\"")));
+ this.Write("\",\n");
}
if (functionContract.ReturnType != null) {
this.Write(" ReturnType = typeof(");
this.Write(this.ToStringHelper.ToStringWithCulture(functionContract.ReturnType));
- this.Write("),\r\n");
+ this.Write("),\n");
}
if (functionContract.ReturnDescription != null) {
this.Write(" ReturnDescription = @\"");
this.Write(this.ToStringHelper.ToStringWithCulture(functionContract.ReturnDescription));
- this.Write("\",\r\n");
+ this.Write("\",\n");
}
if (functionContract.Parameters != null) {
this.Write(" Parameters = new global::AutoGen.Core.FunctionParameterContract[]" +
- "\r\n {\r\n");
+ "\n {\n");
foreach (var parameter in functionContract.Parameters) {
- this.Write(" new FunctionParameterContract\r\n {\r\n");
+ this.Write(" new FunctionParameterContract\n {\n");
if (parameter.Name != null) {
this.Write(" Name = @\"");
this.Write(this.ToStringHelper.ToStringWithCulture(parameter.Name));
- this.Write("\",\r\n");
+ this.Write("\",\n");
}
if (parameter.Description != null) {
this.Write(" Description = @\"");
- this.Write(this.ToStringHelper.ToStringWithCulture(parameter.Description));
- this.Write("\",\r\n");
+ this.Write(this.ToStringHelper.ToStringWithCulture( parameter.Description.Replace("\"", "\"\"") ));
+ this.Write("\",\n");
}
if (parameter.Type != null) {
this.Write(" ParameterType = typeof(");
this.Write(this.ToStringHelper.ToStringWithCulture(parameter.Type));
- this.Write("),\r\n");
+ this.Write("),\n");
}
this.Write(" IsRequired = ");
this.Write(this.ToStringHelper.ToStringWithCulture(parameter.IsOptional ? "false" : "true"));
- this.Write(",\r\n");
+ this.Write(",\n");
if (parameter.DefaultValue != null) {
this.Write(" DefaultValue = ");
this.Write(this.ToStringHelper.ToStringWithCulture(parameter.DefaultValue));
- this.Write(",\r\n");
+ this.Write(",\n");
}
- this.Write(" },\r\n");
+ this.Write(" },\n");
}
- this.Write(" },\r\n");
+ this.Write(" },\n");
}
- this.Write(" };\r\n }\r\n\r\n public global::Azure.AI.OpenAI.FunctionDefin" +
- "ition ");
+ this.Write(" };\n }\n\n public global::Azure.AI.OpenAI.FunctionDefiniti" +
+ "on ");
this.Write(this.ToStringHelper.ToStringWithCulture(functionContract.GetFunctionDefinitionName()));
- this.Write("\r\n {\r\n get => this.");
+ this.Write("\n {\n get => this.");
this.Write(this.ToStringHelper.ToStringWithCulture(functionContract.GetFunctionContractName()));
- this.Write(".ToOpenAIFunctionDefinition();\r\n }\r\n");
+ this.Write(".ToOpenAIFunctionDefinition();\n }\n");
}
- this.Write(" }\r\n");
+ this.Write(" }\n");
if (!String.IsNullOrEmpty(NameSpace)) {
- this.Write("}\r\n");
+ this.Write("}\n");
}
- this.Write("\r\n");
+ this.Write("\n");
return this.GenerationEnvironment.ToString();
}
-
-public string NameSpace {get; set;}
-public string ClassName {get; set;}
-public IEnumerable FunctionContracts {get; set;}
-public bool IsStatic {get; set;} = false;
-
+
+ public virtual void Initialize() {
+ }
}
- #region Base class
- ///
- /// Base class for this transformation
- ///
- [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.TextTemplating", "17.0.0.0")]
- internal class FunctionCallTemplateBase
- {
- #region Fields
- private global::System.Text.StringBuilder generationEnvironmentField;
- private global::System.CodeDom.Compiler.CompilerErrorCollection errorsField;
- private global::System.Collections.Generic.List indentLengthsField;
- private string currentIndentField = "";
- private bool endsWithNewline;
- private global::System.Collections.Generic.IDictionary sessionField;
- #endregion
- #region Properties
- ///
- /// The string builder that generation-time code is using to assemble generated output
- ///
- public System.Text.StringBuilder GenerationEnvironment
- {
- get
- {
- if ((this.generationEnvironmentField == null))
- {
- this.generationEnvironmentField = new global::System.Text.StringBuilder();
- }
- return this.generationEnvironmentField;
+
+ public class FunctionCallTemplateBase {
+
+ private global::System.Text.StringBuilder builder;
+
+ private global::System.Collections.Generic.IDictionary session;
+
+ private global::System.CodeDom.Compiler.CompilerErrorCollection errors;
+
+ private string currentIndent = string.Empty;
+
+ private global::System.Collections.Generic.Stack indents;
+
+ private ToStringInstanceHelper _toStringHelper = new ToStringInstanceHelper();
+
+ public virtual global::System.Collections.Generic.IDictionary Session {
+ get {
+ return this.session;
}
- set
- {
- this.generationEnvironmentField = value;
+ set {
+ this.session = value;
}
}
- ///
- /// The error collection for the generation process
- ///
- public System.CodeDom.Compiler.CompilerErrorCollection Errors
- {
- get
- {
- if ((this.errorsField == null))
- {
- this.errorsField = new global::System.CodeDom.Compiler.CompilerErrorCollection();
+
+ public global::System.Text.StringBuilder GenerationEnvironment {
+ get {
+ if ((this.builder == null)) {
+ this.builder = new global::System.Text.StringBuilder();
}
- return this.errorsField;
+ return this.builder;
+ }
+ set {
+ this.builder = value;
}
}
- ///
- /// A list of the lengths of each indent that was added with PushIndent
- ///
- private System.Collections.Generic.List indentLengths
- {
- get
- {
- if ((this.indentLengthsField == null))
- {
- this.indentLengthsField = new global::System.Collections.Generic.List();
+
+ protected global::System.CodeDom.Compiler.CompilerErrorCollection Errors {
+ get {
+ if ((this.errors == null)) {
+ this.errors = new global::System.CodeDom.Compiler.CompilerErrorCollection();
}
- return this.indentLengthsField;
+ return this.errors;
}
}
- ///
- /// Gets the current indent we use when adding lines to the output
- ///
- public string CurrentIndent
- {
- get
- {
- return this.currentIndentField;
+
+ public string CurrentIndent {
+ get {
+ return this.currentIndent;
}
}
- ///
- /// Current transformation session
- ///
- public virtual global::System.Collections.Generic.IDictionary Session
- {
- get
- {
- return this.sessionField;
- }
- set
- {
- this.sessionField = value;
+
+ private global::System.Collections.Generic.Stack Indents {
+ get {
+ if ((this.indents == null)) {
+ this.indents = new global::System.Collections.Generic.Stack();
+ }
+ return this.indents;
}
}
- #endregion
- #region Transform-time helpers
- ///
- /// Write text directly into the generated output
- ///
- public void Write(string textToAppend)
- {
- if (string.IsNullOrEmpty(textToAppend))
- {
- return;
- }
- // If we're starting off, or if the previous text ended with a newline,
- // we have to append the current indent first.
- if (((this.GenerationEnvironment.Length == 0)
- || this.endsWithNewline))
- {
- this.GenerationEnvironment.Append(this.currentIndentField);
- this.endsWithNewline = false;
- }
- // Check if the current text ends with a newline
- if (textToAppend.EndsWith(global::System.Environment.NewLine, global::System.StringComparison.CurrentCulture))
- {
- this.endsWithNewline = true;
- }
- // This is an optimization. If the current indent is "", then we don't have to do any
- // of the more complex stuff further down.
- if ((this.currentIndentField.Length == 0))
- {
- this.GenerationEnvironment.Append(textToAppend);
- return;
- }
- // Everywhere there is a newline in the text, add an indent after it
- textToAppend = textToAppend.Replace(global::System.Environment.NewLine, (global::System.Environment.NewLine + this.currentIndentField));
- // If the text ends with a newline, then we should strip off the indent added at the very end
- // because the appropriate indent will be added when the next time Write() is called
- if (this.endsWithNewline)
- {
- this.GenerationEnvironment.Append(textToAppend, 0, (textToAppend.Length - this.currentIndentField.Length));
- }
- else
- {
- this.GenerationEnvironment.Append(textToAppend);
+
+ public ToStringInstanceHelper ToStringHelper {
+ get {
+ return this._toStringHelper;
}
}
- ///
- /// Write text directly into the generated output
- ///
- public void WriteLine(string textToAppend)
- {
- this.Write(textToAppend);
- this.GenerationEnvironment.AppendLine();
- this.endsWithNewline = true;
+
+ public void Error(string message) {
+ this.Errors.Add(new global::System.CodeDom.Compiler.CompilerError(null, -1, -1, null, message));
}
- ///
- /// Write formatted text directly into the generated output
- ///
- public void Write(string format, params object[] args)
- {
- this.Write(string.Format(global::System.Globalization.CultureInfo.CurrentCulture, format, args));
+
+ public void Warning(string message) {
+ global::System.CodeDom.Compiler.CompilerError val = new global::System.CodeDom.Compiler.CompilerError(null, -1, -1, null, message);
+ val.IsWarning = true;
+ this.Errors.Add(val);
}
- ///
- /// Write formatted text directly into the generated output
- ///
- public void WriteLine(string format, params object[] args)
- {
- this.WriteLine(string.Format(global::System.Globalization.CultureInfo.CurrentCulture, format, args));
+
+ public string PopIndent() {
+ if ((this.Indents.Count == 0)) {
+ return string.Empty;
+ }
+ int lastPos = (this.currentIndent.Length - this.Indents.Pop());
+ string last = this.currentIndent.Substring(lastPos);
+ this.currentIndent = this.currentIndent.Substring(0, lastPos);
+ return last;
}
- ///
- /// Raise an error
- ///
- public void Error(string message)
- {
- System.CodeDom.Compiler.CompilerError error = new global::System.CodeDom.Compiler.CompilerError();
- error.ErrorText = message;
- this.Errors.Add(error);
+
+ public void PushIndent(string indent) {
+ this.Indents.Push(indent.Length);
+ this.currentIndent = (this.currentIndent + indent);
}
- ///
- /// Raise a warning
- ///
- public void Warning(string message)
- {
- System.CodeDom.Compiler.CompilerError error = new global::System.CodeDom.Compiler.CompilerError();
- error.ErrorText = message;
- error.IsWarning = true;
- this.Errors.Add(error);
+
+ public void ClearIndent() {
+ this.currentIndent = string.Empty;
+ this.Indents.Clear();
}
- ///
- /// Increase the indent
- ///
- public void PushIndent(string indent)
- {
- if ((indent == null))
- {
- throw new global::System.ArgumentNullException("indent");
- }
- this.currentIndentField = (this.currentIndentField + indent);
- this.indentLengths.Add(indent.Length);
+
+ public void Write(string textToAppend) {
+ this.GenerationEnvironment.Append(textToAppend);
}
- ///
- /// Remove the last indent that was added with PushIndent
- ///
- public string PopIndent()
- {
- string returnValue = "";
- if ((this.indentLengths.Count > 0))
- {
- int indentLength = this.indentLengths[(this.indentLengths.Count - 1)];
- this.indentLengths.RemoveAt((this.indentLengths.Count - 1));
- if ((indentLength > 0))
- {
- returnValue = this.currentIndentField.Substring((this.currentIndentField.Length - indentLength));
- this.currentIndentField = this.currentIndentField.Remove((this.currentIndentField.Length - indentLength));
- }
- }
- return returnValue;
+
+ public void Write(string format, params object[] args) {
+ this.GenerationEnvironment.AppendFormat(format, args);
}
- ///
- /// Remove any indentation
- ///
- public void ClearIndent()
- {
- this.indentLengths.Clear();
- this.currentIndentField = "";
+
+ public void WriteLine(string textToAppend) {
+ this.GenerationEnvironment.Append(this.currentIndent);
+ this.GenerationEnvironment.AppendLine(textToAppend);
}
- #endregion
- #region ToString Helpers
- ///
- /// Utility class to produce culture-oriented representation of an object as a string.
- ///
- public class ToStringInstanceHelper
- {
- private System.IFormatProvider formatProviderField = global::System.Globalization.CultureInfo.InvariantCulture;
- ///
- /// Gets or sets format provider to be used by ToStringWithCulture method.
- ///
- public System.IFormatProvider FormatProvider
- {
- get
- {
- return this.formatProviderField ;
+
+ public void WriteLine(string format, params object[] args) {
+ this.GenerationEnvironment.Append(this.currentIndent);
+ this.GenerationEnvironment.AppendFormat(format, args);
+ this.GenerationEnvironment.AppendLine();
+ }
+
+ public class ToStringInstanceHelper {
+
+ private global::System.IFormatProvider formatProvider = global::System.Globalization.CultureInfo.InvariantCulture;
+
+ public global::System.IFormatProvider FormatProvider {
+ get {
+ return this.formatProvider;
}
- set
- {
- if ((value != null))
- {
- this.formatProviderField = value;
+ set {
+ if ((value != null)) {
+ this.formatProvider = value;
}
}
}
- ///
- /// This is called from the compile/run appdomain to convert objects within an expression block to a string
- ///
- public string ToStringWithCulture(object objectToConvert)
- {
- if ((objectToConvert == null))
- {
+
+ public string ToStringWithCulture(object objectToConvert) {
+ if ((objectToConvert == null)) {
throw new global::System.ArgumentNullException("objectToConvert");
}
- System.Type t = objectToConvert.GetType();
- System.Reflection.MethodInfo method = t.GetMethod("ToString", new System.Type[] {
- typeof(System.IFormatProvider)});
- if ((method == null))
- {
- return objectToConvert.ToString();
+ global::System.Type type = objectToConvert.GetType();
+ global::System.Type iConvertibleType = typeof(global::System.IConvertible);
+ if (iConvertibleType.IsAssignableFrom(type)) {
+ return ((global::System.IConvertible)(objectToConvert)).ToString(this.formatProvider);
}
- else
- {
- return ((string)(method.Invoke(objectToConvert, new object[] {
- this.formatProviderField })));
+ global::System.Reflection.MethodInfo methInfo = type.GetMethod("ToString", new global::System.Type[] {
+ iConvertibleType});
+ if ((methInfo != null)) {
+ return ((string)(methInfo.Invoke(objectToConvert, new object[] {
+ this.formatProvider})));
}
+ return objectToConvert.ToString();
}
}
- private ToStringInstanceHelper toStringHelperField = new ToStringInstanceHelper();
- ///
- /// Helper to produce culture-oriented representation of an object as a string
- ///
- public ToStringInstanceHelper ToStringHelper
- {
- get
- {
- return this.toStringHelperField;
- }
- }
- #endregion
}
- #endregion
}
diff --git a/dotnet/src/AutoGen.SourceGenerator/Template/FunctionCallTemplate.tt b/dotnet/src/AutoGen.SourceGenerator/Template/FunctionCallTemplate.tt
index 0d1b221c35c..c7a13ce1fe9 100644
--- a/dotnet/src/AutoGen.SourceGenerator/Template/FunctionCallTemplate.tt
+++ b/dotnet/src/AutoGen.SourceGenerator/Template/FunctionCallTemplate.tt
@@ -63,7 +63,7 @@ namespace <#=NameSpace#>
Name = @"<#=functionContract.Name#>",
<#}#>
<#if (functionContract.Description != null) {#>
- Description = @"<#=functionContract.Description#>",
+ Description = @"<#=functionContract.Description.Replace("\"", "\"\"")#>",
<#}#>
<#if (functionContract.ReturnType != null) {#>
ReturnType = typeof(<#=functionContract.ReturnType#>),
@@ -81,7 +81,7 @@ namespace <#=NameSpace#>
Name = @"<#=parameter.Name#>",
<#}#>
<#if (parameter.Description != null) {#>
- Description = @"<#=parameter.Description#>",
+ Description = @"<#= parameter.Description.Replace("\"", "\"\"") #>",
<#}#>
<#if (parameter.Type != null) {#>
ParameterType = typeof(<#=parameter.Type#>),
diff --git a/dotnet/test/AutoGen.SourceGenerator.Tests/ApprovalTests/FunctionCallTemplateTests.TestFunctionCallTemplate.approved.txt b/dotnet/test/AutoGen.SourceGenerator.Tests/ApprovalTests/FunctionCallTemplateTests.TestFunctionCallTemplate.approved.txt
index 0439febc52c..a5ffa3c8248 100644
--- a/dotnet/test/AutoGen.SourceGenerator.Tests/ApprovalTests/FunctionCallTemplateTests.TestFunctionCallTemplate.approved.txt
+++ b/dotnet/test/AutoGen.SourceGenerator.Tests/ApprovalTests/FunctionCallTemplateTests.TestFunctionCallTemplate.approved.txt
@@ -1,4 +1,4 @@
-//----------------------
+//----------------------
//
// This code was generated by a tool.
//
diff --git a/dotnet/test/AutoGen.SourceGenerator.Tests/FunctionCallTemplateEncodingTests.cs b/dotnet/test/AutoGen.SourceGenerator.Tests/FunctionCallTemplateEncodingTests.cs
new file mode 100644
index 00000000000..8ca6e31a8a4
--- /dev/null
+++ b/dotnet/test/AutoGen.SourceGenerator.Tests/FunctionCallTemplateEncodingTests.cs
@@ -0,0 +1,92 @@
+// Using directives
+using System.Text.Json; // Needed for JsonSerializer
+using Xunit; // Needed for Fact and Assert
+using AutoGen.SourceGenerator.Template; // Needed for FunctionCallTemplate
+
+namespace AutoGen.SourceGenerator.Tests
+{
+ public class FunctionCallTemplateEncodingTests
+ {
+ private readonly JsonSerializerOptions jsonSerializerOptions = new JsonSerializerOptions
+ {
+ WriteIndented = true,
+ };
+
+ [Fact]
+ public void FunctionDescription_Should_Encode_DoubleQuotes()
+ {
+ // Arrange
+ var functionContracts = new List
+ {
+ new SourceGeneratorFunctionContract
+ {
+ Name = "TestFunction",
+ Description = "This is a \"test\" function",
+ Parameters = new SourceGeneratorParameterContract[]
+ {
+ new SourceGeneratorParameterContract
+ {
+ Name = "param1",
+ Description = "This is a \"parameter\" description",
+ Type = "string",
+ IsOptional = false
+ }
+ },
+ ReturnType = "void"
+ }
+ };
+
+ var template = new FunctionCallTemplate
+ {
+ NameSpace = "TestNamespace",
+ ClassName = "TestClass",
+ FunctionContracts = functionContracts
+ };
+
+ // Act
+ var result = template.TransformText();
+
+ // Assert
+ Assert.Contains("Description = @\"This is a \"\"test\"\" function\"", result);
+ Assert.Contains("Description = @\"This is a \"\"parameter\"\" description\"", result);
+ }
+
+ [Fact]
+ public void ParameterDescription_Should_Encode_DoubleQuotes()
+ {
+ // Arrange
+ var functionContracts = new List
+ {
+ new SourceGeneratorFunctionContract
+ {
+ Name = "TestFunction",
+ Description = "This is a test function",
+ Parameters = new SourceGeneratorParameterContract[]
+ {
+ new SourceGeneratorParameterContract
+ {
+ Name = "param1",
+ Description = "This is a \"parameter\" description",
+ Type = "string",
+ IsOptional = false
+ }
+ },
+ ReturnType = "void"
+ }
+ };
+
+ var template = new FunctionCallTemplate
+ {
+ NameSpace = "TestNamespace",
+ ClassName = "TestClass",
+ FunctionContracts = functionContracts
+ };
+
+ // Act
+ var result = template.TransformText();
+
+ // Assert
+ Assert.Contains("Description = @\"This is a \"\"parameter\"\" description\"", result);
+ }
+ }
+}
\ No newline at end of file