-
-
Notifications
You must be signed in to change notification settings - Fork 109
feat: Fix MatrixMethod attribute ignored for enum parameter type #4146
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
Pull Request Review: Fix MatrixMethod attribute ignored for enum parameter typeSummaryThis PR fixes a bug where MatrixMethodAttribute was being ignored for enum parameter types in the source-generated mode. The fix introduces a new marker interface IDataSourceMemberAttribute to distinguish parameter-level data source attributes from test-level ones, ensuring they get properly cached by the source generator for AOT compatibility. Strengths
Concerns and RecommendationsCRITICAL: Verify Dual-Mode Compatibility Per Rule 1 in CLAUDE.md: ALL changes must work identically in both execution modes. Verification Needed: Confirm that MatrixAttribute implements or inherits from IDataSourceAttribute so the filtering logic in CombinedDataSourcesAttribute.cs:129-131 works correctly. The cached attributes are now Attribute[] but then filtered with .OfType IDataSourceAttribute. This will only work if MatrixAttribute and MatrixMethodAttribute implement IDataSourceAttribute. Action: Please verify that the reflection mode also works correctly by running tests with reflection-based discovery enabled. Code Quality Assessment
RecommendationStatus: Approve with verification requested Required Verification:
Suggested Improvements:
This is a well-crafted fix addressing the root cause. Great work! |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Copilot reviewed 11 out of 11 changed files in this pull request and generated no comments.
Comments suppressed due to low confidence (1)
TUnit.Core.SourceGenerator/CodeGenerationHelpers.cs:76
- The method
GenerateParameterMetadataArrayincludes logic to generateCachedDataSourceAttributesfor bothIDataSourceAttributeandIDataSourceMemberAttributeimplementations (lines 51-71). However, this method appears to be unused in the codebase - there are no call sites for it.
The actual parameter metadata generation uses MetadataGenerationHelper.WriteParameterMetadata, which does NOT include any logic to populate CachedDataSourceAttributes. This means that the AOT-compatible caching mechanism described in the comments is not actually being utilized.
Either:
WriteParameterMetadatashould be updated to include the sameCachedDataSourceAttributesgeneration logic, or- The code should be refactored to use
GenerateParameterMetadataArrayinstead ofWriteParameterMetadata, or - If
GenerateParameterMetadataArrayis truly unused/dead code, it should be removed to avoid confusion.
Without the caching working properly, the framework will fall back to reflection at runtime, which defeats the purpose of the AOT compatibility improvements.
public static string GenerateParameterMetadataArray(IMethodSymbol method)
{
if (method.Parameters.Length == 0)
{
return "System.Array.Empty<global::TUnit.Core.ParameterMetadata>()";
}
using var writer = new CodeWriter("", includeHeader: false);
writer.SetIndentLevel(2);
using (writer.BeginArrayInitializer("new global::TUnit.Core.ParameterMetadata[]"))
{
foreach (var param in method.Parameters)
{
var parameterIndex = method.Parameters.IndexOf(param);
var containsTypeParam = ContainsTypeParameter(param.Type);
var typeForConstructor = containsTypeParam ? "object" : param.Type.GloballyQualified();
using (writer.BeginObjectInitializer($"new global::TUnit.Core.ParameterMetadata(typeof({typeForConstructor}))", ","))
{
writer.AppendLine($"Name = \"{param.Name}\",");
writer.AppendLine($"TypeInfo = {GenerateTypeInfo(param.Type)},");
writer.AppendLine($"IsNullable = {param.Type.IsNullable().ToString().ToLowerInvariant()},");
var paramTypesArray = GenerateParameterTypesArray(method);
if (paramTypesArray == "null")
{
writer.AppendLine($"ReflectionInfo = typeof({method.ContainingType.GloballyQualified()}).GetMethods(global::System.Reflection.BindingFlags.Public | global::System.Reflection.BindingFlags.NonPublic | global::System.Reflection.BindingFlags.Instance | global::System.Reflection.BindingFlags.Static).FirstOrDefault(m => m.Name == \"{method.Name}\" && m.GetParameters().Length == {method.Parameters.Length})?.GetParameters()[{parameterIndex}],");
}
else
{
writer.AppendLine($"ReflectionInfo = typeof({method.ContainingType.GloballyQualified()}).GetMethod(\"{method.Name}\", global::System.Reflection.BindingFlags.Public | global::System.Reflection.BindingFlags.NonPublic | global::System.Reflection.BindingFlags.Instance | global::System.Reflection.BindingFlags.Static, null, {paramTypesArray}, null)!.GetParameters()[{parameterIndex}],");
}
// Generate cached data source attributes for AOT compatibility
// Include both IDataSourceAttribute and IDataSourceMemberAttribute implementations
var dataSourceAttributes = param.GetAttributes()
.Where(attr => attr.AttributeClass != null &&
attr.AttributeClass.AllInterfaces.Any(i =>
i.Name == "IDataSourceAttribute" || i.Name == "IDataSourceMemberAttribute"))
.ToArray();
if (dataSourceAttributes.Length > 0)
{
writer.AppendLine($"CachedDataSourceAttributes = new global::System.Attribute[]");
writer.AppendLine("{");
writer.SetIndentLevel(3);
foreach (var attr in dataSourceAttributes)
{
var attrCode = GenerateAttributeInstantiation(attr, method.Parameters);
writer.AppendLine($"{attrCode},");
}
writer.SetIndentLevel(2);
writer.Append("}");
}
}
}
}
return writer.ToString().TrimEnd(); // Trim trailing newline for inline use
}
|
This PR fixes a bug where MatrixMethodAttribute was being ignored during source generation for enum parameters. The fix introduces a new marker interface IDataSourceMemberAttribute to ensure these attributes are properly cached by the source generator for AOT-compatible runtime access. Key Changes:
Compliance with CLAUDE.md: Test Math: New test generates 4 combinations (2 bool × 2 enum values), matching the increase from 133→137 (net framework) and 271→275 (other platforms). LGTM ✅ - Clean, well-implemented fix that follows TUnit architectural patterns and maintains backward compatibility. Ready to merge. |
No description provided.