@@ -360,7 +360,7 @@ static void ScanReferencedAssemblies(
360360 CancellationToken cancellationToken )
361361 {
362362 // Scan all referenced assemblies for activities and orchestrators
363- // Skip system assemblies and assemblies without Durable Task references for performance
363+ // Skip system assemblies and assemblies without Durable symbols for performance
364364 foreach ( MetadataReference reference in compilation . References )
365365 {
366366 cancellationToken . ThrowIfCancellationRequested ( ) ;
@@ -375,7 +375,7 @@ static void ScanReferencedAssemblies(
375375 continue ;
376376 }
377377
378- if ( ! ShouldScanAssembly ( assembly ) )
378+ if ( ! ShouldScanAssembly ( assembly , knownSymbols ) )
379379 {
380380 continue ;
381381 }
@@ -409,18 +409,59 @@ static bool IsSystemAssembly(IAssemblySymbol assembly)
409409 return false ;
410410 }
411411
412- static bool ShouldScanAssembly ( IAssemblySymbol assembly )
412+ static bool ShouldScanAssembly ( IAssemblySymbol assembly , KnownTypeSymbols knownSymbols )
413413 {
414- // Only scan assemblies that reference Durable Task types
415- // This filters out transitive dependencies that don't contain activities/orchestrators
416- foreach ( AssemblyIdentity referencedAssembly in assembly . Modules . SelectMany ( m => m . ReferencedAssemblies ) )
414+ // Check if assembly contains any Durable Task symbols using semantic lookup
415+ // This is more robust than checking assembly references
416+ return ContainsDurableSymbols ( assembly . GlobalNamespace , knownSymbols ) ;
417+ }
418+
419+ static bool ContainsDurableSymbols ( INamespaceSymbol namespaceSymbol , KnownTypeSymbols knownSymbols )
420+ {
421+ // Check types in this namespace for Durable Task symbols
422+ foreach ( INamedTypeSymbol typeSymbol in namespaceSymbol . GetTypeMembers ( ) )
417423 {
418- string refName = referencedAssembly . Name ;
419- // Check for packages that users directly reference when defining activities/orchestrators
420- // Microsoft.DurableTask.Worker: for non-function scenarios (console apps, etc.)
421- // Microsoft.Azure.Functions.Worker.Extensions.DurableTask: for Azure Functions scenarios
422- if ( refName == "Microsoft.DurableTask.Worker" ||
423- refName == "Microsoft.Azure.Functions.Worker.Extensions.DurableTask" )
424+ // Check if type derives from TaskActivity
425+ if ( knownSymbols . TaskActivityBase != null && DerivesFrom ( typeSymbol , knownSymbols . TaskActivityBase ) )
426+ {
427+ return true ;
428+ }
429+
430+ // Check if type implements ITaskOrchestrator
431+ if ( knownSymbols . TaskOrchestratorInterface != null &&
432+ ImplementsInterface ( typeSymbol , knownSymbols . TaskOrchestratorInterface ) )
433+ {
434+ return true ;
435+ }
436+
437+ // Check methods for Durable Task attributes
438+ foreach ( ISymbol member in typeSymbol . GetMembers ( ) )
439+ {
440+ if ( member is not IMethodSymbol methodSymbol )
441+ {
442+ continue ;
443+ }
444+
445+ // Check for ActivityTrigger attribute
446+ if ( knownSymbols . ActivityTriggerAttribute != null &&
447+ methodSymbol . ContainsAttributeInAnyMethodArguments ( knownSymbols . ActivityTriggerAttribute ) )
448+ {
449+ return true ;
450+ }
451+
452+ // Check for OrchestrationTrigger attribute
453+ if ( knownSymbols . FunctionOrchestrationAttribute != null &&
454+ methodSymbol . ContainsAttributeInAnyMethodArguments ( knownSymbols . FunctionOrchestrationAttribute ) )
455+ {
456+ return true ;
457+ }
458+ }
459+ }
460+
461+ // Recursively check nested namespaces
462+ foreach ( INamespaceSymbol nestedNamespace in namespaceSymbol . GetNamespaceMembers ( ) )
463+ {
464+ if ( ContainsDurableSymbols ( nestedNamespace , knownSymbols ) )
424465 {
425466 return true ;
426467 }
@@ -429,6 +470,20 @@ static bool ShouldScanAssembly(IAssemblySymbol assembly)
429470 return false ;
430471 }
431472
473+ static bool DerivesFrom ( INamedTypeSymbol typeSymbol , INamedTypeSymbol baseType )
474+ {
475+ INamedTypeSymbol ? current = typeSymbol . BaseType ;
476+ while ( current != null )
477+ {
478+ if ( SymbolEqualityComparer . Default . Equals ( current . OriginalDefinition , baseType ) )
479+ {
480+ return true ;
481+ }
482+ current = current . BaseType ;
483+ }
484+ return false ;
485+ }
486+
432487 static void ScanNamespaceForFunctions (
433488 INamespaceSymbol namespaceSymbol ,
434489 KnownTypeSymbols knownSymbols ,
0 commit comments