@@ -321,7 +321,7 @@ private static void GenerateTestMetadata(CodeWriter writer, TestMethodMetadata t
321321
322322 if ( hasTypedDataSource || hasGenerateGenericTest || testMethod . IsGenericMethod || hasClassArguments || hasTypedDataSourceForGenericType || hasMethodArgumentsForGenericType || hasMethodDataSourceForGenericType || hasClassDataSources )
323323 {
324- GenerateGenericTestWithConcreteTypes ( writer , testMethod , className , uniqueClassName ) ;
324+ GenerateGenericTestWithConcreteTypes ( writer , testMethod , className ) ;
325325 }
326326 else
327327 {
@@ -350,138 +350,6 @@ private static void GenerateTestMetadata(CodeWriter writer, TestMethodMetadata t
350350 GenerateModuleInitializer ( writer , testMethod , uniqueClassName ) ;
351351 }
352352
353- private static void GenerateSpecificGenericInstantiation (
354- CodeWriter writer ,
355- TestMethodMetadata testMethod ,
356- string className ,
357- string combinationGuid ,
358- ImmutableArray < ITypeSymbol > typeArguments )
359- {
360- var methodName = testMethod . MethodSymbol . Name ;
361- var typeArgsString = string . Join ( ", " , typeArguments . Select ( t => t . GloballyQualified ( ) ) ) ;
362- var instantiatedMethodName = $ "{ methodName } <{ typeArgsString } >";
363-
364- var concreteTestMethod = new TestMethodMetadata
365- {
366- MethodSymbol = testMethod . MethodSymbol ,
367- TypeSymbol = testMethod . TypeSymbol ,
368- FilePath = testMethod . FilePath ,
369- LineNumber = testMethod . LineNumber ,
370- TestAttribute = testMethod . TestAttribute ,
371- Context = testMethod . Context ,
372- MethodSyntax = testMethod . MethodSyntax ,
373- IsGenericType = testMethod . IsGenericType ,
374- IsGenericMethod = false , // We're creating a concrete instantiation
375- MethodAttributes = testMethod . MethodAttributes
376- } ;
377-
378- writer . AppendLine ( $ "// Generated instantiation for { instantiatedMethodName } ") ;
379- writer . AppendLine ( "{" ) ;
380- writer . Indent ( ) ;
381-
382- writer . AppendLine ( $ "var metadata = new global::TUnit.Core.TestMetadata<{ className } >") ;
383- writer . AppendLine ( "{" ) ;
384- writer . Indent ( ) ;
385-
386- writer . AppendLine ( $ "TestName = \" { instantiatedMethodName } \" ,") ;
387- writer . AppendLine ( $ "TestClassType = { GenerateTypeReference ( testMethod . TypeSymbol , testMethod . IsGenericType ) } ,") ;
388- writer . AppendLine ( $ "TestMethodName = \" { methodName } \" ,") ;
389- writer . AppendLine ( $ "GenericMethodTypeArguments = new global::System.Type[] {{ { string . Join ( ", " , typeArguments . Select ( t => $ "typeof({ t . GloballyQualified ( ) } )") ) } }},") ;
390-
391- GenerateMetadata ( writer , concreteTestMethod ) ;
392-
393- if ( testMethod . IsGenericType )
394- {
395- GenerateGenericTypeInfo ( writer , testMethod . TypeSymbol ) ;
396- }
397-
398- GenerateAotFriendlyInvokers ( writer , testMethod , className , typeArguments ) ;
399-
400- writer . AppendLine ( $ "FilePath = @\" { ( testMethod . FilePath ?? "" ) . Replace ( "\\ " , "\\ \\ " ) } \" ,") ;
401- writer . AppendLine ( $ "LineNumber = { testMethod . LineNumber } ,") ;
402-
403- writer . Unindent ( ) ;
404- writer . AppendLine ( "};" ) ;
405-
406- writer . AppendLine ( "metadata.TestSessionId = testSessionId;" ) ;
407- writer . AppendLine ( "yield return metadata;" ) ;
408-
409- writer . Unindent ( ) ;
410- writer . AppendLine ( "}" ) ;
411- writer . AppendLine ( ) ;
412- }
413-
414- private static void GenerateAotFriendlyInvokers (
415- CodeWriter writer ,
416- TestMethodMetadata testMethod ,
417- string className ,
418- ImmutableArray < ITypeSymbol > typeArguments )
419- {
420- var methodName = testMethod . MethodSymbol . Name ;
421- var typeArgsString = string . Join ( ", " , typeArguments . Select ( t => t . GloballyQualified ( ) ) ) ;
422- var hasCancellationToken = testMethod . MethodSymbol . Parameters . Any ( p =>
423- p . Type . Name == "CancellationToken" &&
424- p . Type . ContainingNamespace ? . ToString ( ) == "System.Threading" ) ;
425-
426- writer . AppendLine ( "InstanceFactory = static (typeArgs, args) =>" ) ;
427- writer . AppendLine ( "{" ) ;
428- writer . Indent ( ) ;
429-
430- writer . AppendLine ( $ "return new { className } ();") ;
431-
432- writer . Unindent ( ) ;
433- writer . AppendLine ( "}," ) ;
434-
435- writer . AppendLine ( "InvokeTypedTest = static (instance, args, cancellationToken) =>" ) ;
436- writer . AppendLine ( "{" ) ;
437- writer . Indent ( ) ;
438-
439- // Wrap entire lambda body in try-catch to handle synchronous exceptions
440- writer . AppendLine ( "try" ) ;
441- writer . AppendLine ( "{" ) ;
442- writer . Indent ( ) ;
443-
444- // Generate direct method call with specific types (no MakeGenericMethod)
445- writer . AppendLine ( $ "var typedInstance = ({ className } )instance;") ;
446-
447- writer . AppendLine ( "var methodArgs = new object?[args.Length" + ( hasCancellationToken ? " + 1" : "" ) + "];" ) ;
448- writer . AppendLine ( "global::System.Array.Copy(args, methodArgs, args.Length);" ) ;
449-
450- if ( hasCancellationToken )
451- {
452- writer . AppendLine ( "methodArgs[args.Length] = cancellationToken;" ) ;
453- }
454-
455- var parameterCasts = new List < string > ( ) ;
456- for ( var i = 0 ; i < testMethod . MethodSymbol . Parameters . Length ; i ++ )
457- {
458- var param = testMethod . MethodSymbol . Parameters [ i ] ;
459- if ( param . Type . Name == "CancellationToken" )
460- {
461- parameterCasts . Add ( "cancellationToken" ) ;
462- }
463- else
464- {
465- var paramType = ReplaceTypeParametersWithConcreteTypes ( param . Type , testMethod . MethodSymbol . TypeParameters , typeArguments ) ;
466- parameterCasts . Add ( $ "({ paramType . GloballyQualified ( ) } )methodArgs[{ i } ]!") ;
467- }
468- }
469-
470- writer . AppendLine ( $ "return global::TUnit.Core.AsyncConvert.Convert(() => typedInstance.{ methodName } <{ typeArgsString } >({ string . Join ( ", " , parameterCasts ) } ));") ;
471-
472- writer . Unindent ( ) ;
473- writer . AppendLine ( "}" ) ;
474- writer . AppendLine ( "catch (global::System.Exception ex)" ) ;
475- writer . AppendLine ( "{" ) ;
476- writer . Indent ( ) ;
477- writer . AppendLine ( "return new global::System.Threading.Tasks.ValueTask(global::System.Threading.Tasks.Task.FromException(ex));" ) ;
478- writer . Unindent ( ) ;
479- writer . AppendLine ( "}" ) ;
480-
481- writer . Unindent ( ) ;
482- writer . AppendLine ( "}," ) ;
483- }
484-
485353 private static ITypeSymbol ReplaceTypeParametersWithConcreteTypes (
486354 ITypeSymbol type ,
487355 ImmutableArray < ITypeParameterSymbol > typeParameters ,
@@ -2062,7 +1930,6 @@ private static void GenerateConcreteTestInvoker(CodeWriter writer, TestMethodMet
20621930 writer . AppendLine ( "}," ) ;
20631931 }
20641932
2065-
20661933 private static void GenerateEnumerateTestDescriptors ( CodeWriter writer , TestMethodMetadata testMethod , string className )
20671934 {
20681935 var methodName = testMethod . MethodSymbol . Name ;
@@ -2387,23 +2254,6 @@ private static void GenerateModuleInitializer(CodeWriter writer, TestMethodMetad
23872254 writer . AppendLine ( "}" ) ;
23882255 }
23892256
2390- private static bool IsAsyncMethod ( IMethodSymbol method )
2391- {
2392- var returnType = method . ReturnType ;
2393-
2394- var returnTypeName = returnType . ToDisplayString ( ) ;
2395- return returnTypeName . StartsWith ( "System.Threading.Tasks.Task" ) ||
2396- returnTypeName . StartsWith ( "System.Threading.Tasks.ValueTask" ) ||
2397- returnTypeName . StartsWith ( "Task<" ) ||
2398- returnTypeName . StartsWith ( "ValueTask<" ) ;
2399- }
2400-
2401- private static bool ReturnsValueTask ( IMethodSymbol method )
2402- {
2403- var returnTypeName = method . ReturnType . ToDisplayString ( ) ;
2404- return returnTypeName . StartsWith ( "System.Threading.Tasks.ValueTask" ) ;
2405- }
2406-
24072257 private enum TestReturnPattern
24082258 {
24092259 Void , // void methods
@@ -2669,70 +2519,6 @@ private static bool GetProceedOnFailureValue(AttributeData attributeData)
26692519 return false ;
26702520 }
26712521
2672- private static string GetDefaultValueString ( IParameterSymbol parameter )
2673- {
2674- if ( ! parameter . HasExplicitDefaultValue )
2675- {
2676- return $ "default({ parameter . Type . GloballyQualified ( ) } )";
2677- }
2678-
2679- var defaultValue = parameter . ExplicitDefaultValue ;
2680- if ( defaultValue == null )
2681- {
2682- return "null" ;
2683- }
2684-
2685- var type = parameter . Type ;
2686-
2687- // Handle string
2688- if ( type . SpecialType == SpecialType . System_String )
2689- {
2690- return $ "\" { defaultValue . ToString ( ) . Replace ( "\\ " , "\\ \\ " ) . Replace ( "\" " , "\\ \" " ) } \" ";
2691- }
2692-
2693- // Handle char
2694- if ( type . SpecialType == SpecialType . System_Char )
2695- {
2696- return $ "'{ defaultValue } '";
2697- }
2698-
2699- // Handle bool
2700- if ( type . SpecialType == SpecialType . System_Boolean )
2701- {
2702- return defaultValue . ToString ( ) . ToLowerInvariant ( ) ;
2703- }
2704-
2705- // Handle numeric types with proper suffixes
2706- if ( type . SpecialType == SpecialType . System_Single )
2707- {
2708- return $ "{ defaultValue } f";
2709- }
2710- if ( type . SpecialType == SpecialType . System_Double )
2711- {
2712- return $ "{ defaultValue } d";
2713- }
2714- if ( type . SpecialType == SpecialType . System_Decimal )
2715- {
2716- return $ "{ defaultValue } m";
2717- }
2718- if ( type . SpecialType == SpecialType . System_Int64 )
2719- {
2720- return $ "{ defaultValue } L";
2721- }
2722- if ( type . SpecialType == SpecialType . System_UInt32 )
2723- {
2724- return $ "{ defaultValue } u";
2725- }
2726- if ( type . SpecialType == SpecialType . System_UInt64 )
2727- {
2728- return $ "{ defaultValue } ul";
2729- }
2730-
2731- // Default for other types
2732- return defaultValue . ToString ( ) ;
2733- }
2734-
2735-
27362522 private static bool IsMethodHiding ( IMethodSymbol derivedMethod , IMethodSymbol baseMethod )
27372523 {
27382524 // Must have same name
@@ -3147,11 +2933,6 @@ private static void GenerateGenericParameterConstraints(CodeWriter writer, IType
31472933 writer . AppendLine ( "}," ) ;
31482934 }
31492935
3150- private static bool IsGenericTypeParameter ( ITypeSymbol type )
3151- {
3152- return type . TypeKind == TypeKind . TypeParameter ;
3153- }
3154-
31552936 private static bool ContainsGenericTypeParameter ( ITypeSymbol type )
31562937 {
31572938 if ( type . TypeKind == TypeKind . TypeParameter )
@@ -3175,8 +2956,7 @@ private static bool ContainsGenericTypeParameter(ITypeSymbol type)
31752956 private static void GenerateGenericTestWithConcreteTypes (
31762957 CodeWriter writer ,
31772958 TestMethodMetadata testMethod ,
3178- string className ,
3179- string combinationGuid )
2959+ string className )
31802960 {
31812961 var compilation = testMethod . Context ! . Value . SemanticModel . Compilation ;
31822962 var methodName = testMethod . MethodSymbol . Name ;
@@ -3775,76 +3555,6 @@ private static void GenerateGenericTestWithConcreteTypes(
37753555 writer . AppendLine ( "yield return genericMetadata;" ) ;
37763556 }
37773557
3778- private static void ProcessGenerateGenericTestAttribute (
3779- AttributeData genAttr ,
3780- TestMethodMetadata testMethod ,
3781- string className ,
3782- CodeWriter writer ,
3783- HashSet < string > processedTypeCombinations ,
3784- bool isClassLevel )
3785- {
3786- // Extract type arguments from the attribute
3787- if ( genAttr . ConstructorArguments . Length == 0 )
3788- {
3789- return ;
3790- }
3791-
3792- var typeArgs = new List < ITypeSymbol > ( ) ;
3793- foreach ( var arg in genAttr . ConstructorArguments )
3794- {
3795- if ( arg is { Kind : TypedConstantKind . Type , Value : ITypeSymbol typeSymbol } )
3796- {
3797- typeArgs . Add ( typeSymbol ) ;
3798- }
3799- else if ( arg . Kind == TypedConstantKind . Array )
3800- {
3801- foreach ( var arrayElement in arg . Values )
3802- {
3803- if ( arrayElement is { Kind : TypedConstantKind . Type , Value : ITypeSymbol arrayTypeSymbol } )
3804- {
3805- typeArgs . Add ( arrayTypeSymbol ) ;
3806- }
3807- }
3808- }
3809- }
3810-
3811- if ( typeArgs . Count == 0 )
3812- {
3813- return ;
3814- }
3815-
3816- var inferredTypes = typeArgs . ToArray ( ) ;
3817- var typeKey = BuildTypeKey ( inferredTypes ) ;
3818-
3819- // Skip if we've already processed this type combination
3820- if ( ! processedTypeCombinations . Add ( typeKey ) )
3821- {
3822- return ;
3823- }
3824-
3825- // Validate constraints based on whether this is a class-level or method-level attribute
3826- bool constraintsValid ;
3827- if ( isClassLevel )
3828- {
3829- // For class-level [GenerateGenericTest], validate against class type constraints
3830- constraintsValid = ValidateClassTypeConstraints ( testMethod . TypeSymbol , inferredTypes ) ;
3831- }
3832- else
3833- {
3834- // For method-level [GenerateGenericTest], validate against method type constraints
3835- constraintsValid = ValidateTypeConstraints ( testMethod . MethodSymbol , inferredTypes ) ;
3836- }
3837-
3838- if ( constraintsValid )
3839- {
3840- // Generate a concrete instantiation for this type combination
3841- // Use the same key format as runtime: FullName ?? Name
3842- writer . AppendLine ( $ "[{ string . Join ( " + \" ,\" + " , inferredTypes . Select ( FormatTypeForRuntimeName ) ) } ] = ") ;
3843- GenerateConcreteTestMetadata ( writer , testMethod , className , inferredTypes ) ;
3844- writer . AppendLine ( "," ) ;
3845- }
3846- }
3847-
38483558 private static List < ITypeSymbol [ ] > ExtractTypeArgumentSets ( List < AttributeData > attributes )
38493559 {
38503560 var result = new List < ITypeSymbol [ ] > ( ) ;
@@ -4676,23 +4386,6 @@ private static void ProcessTypeForGenerics(ITypeSymbol paramType, ITypeSymbol ac
46764386 }
46774387 }
46784388
4679- private static bool ValidateTypeConstraints ( INamedTypeSymbol classType , ITypeSymbol [ ] typeArguments )
4680- {
4681- // Validate constraints for a generic class
4682- if ( ! classType . IsGenericType )
4683- {
4684- return true ;
4685- }
4686-
4687- var typeParams = classType . TypeParameters ;
4688- if ( typeParams . Length != typeArguments . Length )
4689- {
4690- return false ;
4691- }
4692-
4693- return ValidateTypeParameterConstraints ( typeParams , typeArguments ) ;
4694- }
4695-
46964389 private static bool ValidateTypeConstraints ( IMethodSymbol method , ITypeSymbol [ ] typeArguments )
46974390 {
46984391 // Only validate method type parameters here - class type parameters are validated separately
0 commit comments