Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -286,7 +286,7 @@ private static bool TryBuildMethodArgumentsForOverload(
}
else
{
arguments.Add(previousParameter);
arguments.Add(parameter.PositionalReference(previousParameter));
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -193,7 +193,54 @@ public async Task BackCompatibility_NewModelPropertyAdded()
Assert.IsNotNull(body);
var result = body!.ToDisplayString();
Assert.AreEqual(
"return PublicModel1(stringProp, modelProp, listProp, dictProp: default);\n",
"return PublicModel1(stringProp: stringProp, modelProp: modelProp, listProp: listProp, dictProp: default);\n",
result);
}

// This test validates that when a new property is added AND the previous contract had a different
// parameter ordering, the backward-compat overload uses named arguments to correctly call the current method.
[Test]
public async Task BackCompatibility_NewPropertyAddedWithDifferentParamOrder()
{
_instance = (await MockHelpers.LoadMockGeneratorAsync(
inputNamespaceName: "Sample.Namespace",
inputModelTypes: ModelList,
lastContractCompilation: async () => await Helpers.GetCompilationFromDirectoryAsync())).Object;

var modelFactory = _instance!.OutputLibrary.ModelFactory.Value;
Assert.AreEqual("SampleNamespaceModelFactory", modelFactory.Name);

modelFactory.ProcessTypeForBackCompatibility();

var methods = modelFactory.Methods;
// There should be an additional method for backward compatibility
Assert.AreEqual(ModelList.Length - ModelList.Where(m => m.Access == "internal").Count() + 1, methods.Count);

var currentOverloadMethod = methods
.FirstOrDefault(m => m.Signature.Name == "PublicModel1" && m.Signature.Parameters.Any(p => p.Name == "dictProp"));
var backwardCompatibilityMethod = methods
.FirstOrDefault(m => m.Signature.Name == "PublicModel1" && m.Signature.Parameters.All(p => p.Name != "dictProp"));
Assert.IsNotNull(currentOverloadMethod);
Assert.IsNotNull(backwardCompatibilityMethod);

// validate the signature of the backward compatibility method preserves the previous parameter order
var parameters = backwardCompatibilityMethod!.Signature.Parameters;
Assert.AreEqual(3, parameters.Count);
Assert.AreEqual("modelProp", parameters[0].Name);
Assert.AreEqual("stringProp", parameters[1].Name);
Assert.AreEqual("listProp", parameters[2].Name);
foreach (var param in parameters)
{
Assert.IsNull(param.DefaultValue);
}

// validate the previous method body uses named arguments to ensure correct mapping
// even though the parameter order differs between the previous and current methods
var body = backwardCompatibilityMethod!.BodyStatements;
Assert.IsNotNull(body);
var result = body!.ToDisplayString();
Assert.AreEqual(
"return PublicModel1(stringProp: stringProp, modelProp: modelProp, listProp: listProp, dictProp: default);\n",
result);
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
using SampleTypeSpec;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using Sample.Models;

namespace Sample.Namespace
{
public static partial class SampleNamespaceModelFactory
{
public static PublicModel1 PublicModel1(
Thing modelProp = default,
string stringProp = default,
IEnumerable<string> listProp = default)
{ }
}
}

namespace Sample.Models
{
public partial class PublicModel1
{ }

public partial class Thing
{ }
}
Loading