@@ -332,23 +332,23 @@ public bool VerifyContainsValidNamespacePowerFxFunctions(TestSettingExtensions s
332332 t . Interfaces . Any ( i => i . InterfaceType . FullName == typeof ( Users . IUserManager ) . FullName ) ||
333333 t . Interfaces . Any ( i => i . InterfaceType . FullName == typeof ( Config . IUserCertificateProvider ) . FullName )
334334 ) ;
335-
336- // Check if PauseModule exists and inspect its IsPreviewNamespaceEnabled property
337- var pauseModule = module . Types . FirstOrDefault ( t => t . Name == "PauseModule" ) ; // Local flag indicating PauseModule declares IsPreviewNamespaceEnabled
338- if ( pauseModule != null )
339- {
340- // Check if the PauseModule has IsPreviewNamespaceEnabled property
341- var previewProperty = pauseModule . Properties . FirstOrDefault ( p => p . Name == "IsPreviewNamespaceEnabled" ) ;
342- if ( previewProperty != null )
343- {
344- // Do not modify the global settings here. Instead record that PauseModule exposes the preview toggle.
345- // The property's value will be determined at runtime based on YAML settings; use the flag to
346- // selectively allow the Preview namespace for providers only.
347- Logger ? . LogInformation ( "Detected PauseModule.IsPreviewNamespaceEnabled; preview semantics will be applied per-type." ) ;
348- }
349- }
350-
351- // Get the source code of the assembly as will be used to check Power FX Namespaces
335+
336+ // Check if PauseModule exists and inspect its IsPreviewNamespaceEnabled property
337+ var pauseModule = module . Types . FirstOrDefault ( t => t . Name == "PauseModule" ) ;
338+ if ( pauseModule != null )
339+ {
340+ // Check if the PauseModule has IsPreviewNamespaceEnabled property
341+ var previewProperty = pauseModule . Properties . FirstOrDefault ( p => p . Name == "IsPreviewNamespaceEnabled" ) ;
342+ if ( previewProperty != null )
343+ {
344+ // Do not modify the global settings here. Instead record that PauseModule exposes the preview toggle.
345+ // The property's value will be determined at runtime based on YAML settings; use the flag to
346+ // selectively allow the Preview namespace for providers only.
347+ Logger ? . LogInformation ( "Detected PauseModule.IsPreviewNamespaceEnabled; preview semantics will be applied per-type." ) ;
348+ }
349+ }
350+
351+ // Get the source code of the assembly as will be used to check Power FX Namespaces
352352 var code = DecompileModuleToCSharp ( assembly ) ;
353353
354354 foreach ( TypeDefinition type in module . GetAllTypes ( ) )
@@ -371,38 +371,38 @@ public bool VerifyContainsValidNamespacePowerFxFunctions(TestSettingExtensions s
371371 allowedForProvider . Add ( NAMESPACE_PREVIEW ) ;
372372 }
373373
374- foreach ( var name in values )
375- {
376- // Check against deny list using regular expressions
377- if ( settings . DenyPowerFxNamespaces . Any ( pattern => Regex . IsMatch ( name , WildcardToRegex ( pattern ) ) ) )
378- {
379- Logger . LogInformation ( $ "Deny Power FX Namespace { name } for { type . Name } ") ;
380- return false ;
381- }
382-
383- // Check against deny wildcard and allow list using regular expressions
384- if ( settings . DenyPowerFxNamespaces . Any ( pattern => pattern == "*" ) &&
374+ foreach ( var name in values )
375+ {
376+ // Check against deny list using regular expressions
377+ if ( settings . DenyPowerFxNamespaces . Any ( pattern => Regex . IsMatch ( name , WildcardToRegex ( pattern ) ) ) )
378+ {
379+ Logger . LogInformation ( $ "Deny Power FX Namespace { name } for { type . Name } ") ;
380+ return false ;
381+ }
382+
383+ // Check against deny wildcard and allow list using regular expressions
384+ if ( settings . DenyPowerFxNamespaces . Any ( pattern => pattern == "*" ) &&
385385 ( ! allowedForProvider . Any ( pattern => Regex . IsMatch ( name , WildcardToRegex ( pattern ) ) ) &&
386386 name != NAMESPACE_TEST_ENGINE ) )
387- {
388- Logger . LogInformation ( $ "Deny Power FX Namespace { name } for { type . Name } ") ;
389- return false ;
390- }
387+ {
388+ Logger . LogInformation ( $ "Deny Power FX Namespace { name } for { type . Name } ") ;
389+ return false ;
390+ }
391391
392- // Check against allow list using regular expressions
392+ // Check against allow list using regular expressions
393393 if ( ! allowedForProvider . Any ( pattern => Regex . IsMatch ( name , WildcardToRegex ( pattern ) ) ) &&
394394 name != NAMESPACE_TEST_ENGINE )
395- {
396- Logger . LogInformation ( $ "Not allow Power FX Namespace { name } for { type . Name } ") ;
397- return false ;
398- }
399- }
400- }
401- }
402-
403- // Extension Module Check are based on constructor
404- if ( type . BaseType != null && type . BaseType . Name == "ReflectionFunction" )
405- {
395+ {
396+ Logger . LogInformation ( $ "Not allow Power FX Namespace { name } for { type . Name } ") ;
397+ return false ;
398+ }
399+ }
400+ }
401+ }
402+
403+ // Extension Module Check are based on constructor
404+ if ( type . BaseType != null && type . BaseType . Name == "ReflectionFunction" )
405+ {
406406 // Special handling for PauseFunction - allow root namespace when PauseModule is present
407407 if ( type . Name == "PauseFunction" && pauseModule != null )
408408 {
@@ -498,98 +498,98 @@ public bool VerifyContainsValidNamespacePowerFxFunctions(TestSettingExtensions s
498498 // Not in allow list or the Reserved TestEngine namespace
499499 return false ;
500500 }
501- }
502-
503- // Special validation for ReflectionAction types. Actions must not declare the Preview namespace
504- if ( type . BaseType != null && type . BaseType . Name == "ReflectionAction" )
505- {
506- // If PauseModule is present, allow certain actions to be declared in the root namespace (skip namespace validation)
507- if ( pauseModule != null )
508- {
509- // Check configured allow-list of action class names/wildcards
510- var allowActions = settings . AllowActionsInRoot ?? new HashSet < string > ( ) ;
511- var isAllowedAction = allowActions . Any ( pattern => Regex . IsMatch ( type . Name , WildcardToRegex ( pattern ) ) ) ;
512- if ( isAllowedAction )
513- {
514- Logger ? . LogInformation ( $ "Allowing action { type . Name } in root namespace due to PauseModule presence and AllowActionsInRoot setting.") ;
515- continue ; // Skip namespace validation for this action
516- }
517- }
518-
519- var constructors = type . GetConstructors ( ) ;
520-
521- if ( constructors . Count ( ) == 0 )
522- {
523- Logger . LogInformation ( $ "No constructor defined for { type . Name } . Found { constructors . Count ( ) } expected 1 or more") ;
524- return false ;
525- }
526-
527- var constructor = constructors . Where ( c => c . HasBody ) . FirstOrDefault ( ) ;
528-
529- if ( constructor == null || ! constructor . HasBody )
530- {
531- Logger . LogInformation ( $ "No constructor body defined for { type . Name } ") ;
532- return false ;
533- }
534-
535- var baseCall = constructor . Body . Instructions ? . FirstOrDefault ( i => i . OpCode == OpCodes . Call && i . Operand is MethodReference && ( ( MethodReference ) i . Operand ) . Name == ".ctor" ) ;
536- if ( baseCall == null )
537- {
538- Logger . LogInformation ( $ "No base constructor defined for { type . Name } ") ;
539- return false ;
540- }
541-
542- MethodReference baseConstructor = ( MethodReference ) baseCall . Operand ;
543- if ( baseConstructor . Parameters ? . Count ( ) < 2 )
544- {
545- Logger . LogInformation ( $ "No not enough parameters for { type . Name } ") ;
546- return false ;
547- }
548-
549- if ( baseConstructor . Parameters [ 0 ] . ParameterType . FullName != "Microsoft.PowerFx.Core.Utils.DPath" )
550- {
551- Logger . LogInformation ( $ "No Power FX Namespace for { type . Name } ") ;
552- return false ;
553- }
554-
555- // Extract namespace from decompiled source
556- var actionName = GetPowerFxNamespace ( type . Name , code ) ;
557- if ( string . IsNullOrEmpty ( actionName ) )
558- {
559- Logger . LogInformation ( $ "No Power FX Namespace found for { type . Name } ") ;
560- return false ;
561- }
562-
563- // Actions must not use the Preview namespace
564- if ( string . Equals ( actionName , NAMESPACE_PREVIEW , StringComparison . OrdinalIgnoreCase ) )
565- {
566- Logger . LogInformation ( $ "Deny Preview Power FX Namespace { actionName } for action { type . Name } ") ;
567- return false ;
568- }
569-
570- // Continue with the same allow/deny validation as functions
571- if ( settings . DenyPowerFxNamespaces . Contains ( actionName ) )
572- {
573- Logger . LogInformation ( $ "Deny Power FX Namespace { actionName } for { type . Name } ") ;
574- return false ;
575- }
576-
577- if ( ( settings . DenyPowerFxNamespaces . Contains ( "*" ) && (
578- ! settings . AllowPowerFxNamespaces . Contains ( actionName ) ||
579- ( ! settings . AllowPowerFxNamespaces . Contains ( actionName ) && actionName != NAMESPACE_TEST_ENGINE )
580- )
581- ) )
582- {
583- Logger . LogInformation ( $ "Deny Power FX Namespace { actionName } for { type . Name } ") ;
584- return false ;
585- }
586-
587- if ( ! settings . AllowPowerFxNamespaces . Contains ( actionName ) && actionName != NAMESPACE_TEST_ENGINE )
588- {
589- Logger . LogInformation ( $ "Do not allow Power FX Namespace { actionName } for { type . Name } ") ;
590- return false ;
591- }
592- }
501+ }
502+
503+ // Special validation for ReflectionAction types. Actions must not declare the Preview namespace
504+ if ( type . BaseType != null && type . BaseType . Name == "ReflectionAction" )
505+ {
506+ // If PauseModule is present, allow certain actions to be declared in the root namespace (skip namespace validation)
507+ if ( pauseModule != null )
508+ {
509+ // Check configured allow-list of action class names/wildcards
510+ var allowActions = settings . AllowActionsInRoot ?? new HashSet < string > ( ) ;
511+ var isAllowedAction = allowActions . Any ( pattern => Regex . IsMatch ( type . Name , WildcardToRegex ( pattern ) ) ) ;
512+ if ( isAllowedAction )
513+ {
514+ Logger ? . LogInformation ( $ "Allowing action { type . Name } in root namespace due to PauseModule presence and AllowActionsInRoot setting.") ;
515+ continue ; // Skip namespace validation for this action
516+ }
517+ }
518+
519+ var constructors = type . GetConstructors ( ) ;
520+
521+ if ( constructors . Count ( ) == 0 )
522+ {
523+ Logger . LogInformation ( $ "No constructor defined for { type . Name } . Found { constructors . Count ( ) } expected 1 or more") ;
524+ return false ;
525+ }
526+
527+ var constructor = constructors . Where ( c => c . HasBody ) . FirstOrDefault ( ) ;
528+
529+ if ( constructor == null || ! constructor . HasBody )
530+ {
531+ Logger . LogInformation ( $ "No constructor body defined for { type . Name } ") ;
532+ return false ;
533+ }
534+
535+ var baseCall = constructor . Body . Instructions ? . FirstOrDefault ( i => i . OpCode == OpCodes . Call && i . Operand is MethodReference && ( ( MethodReference ) i . Operand ) . Name == ".ctor" ) ;
536+ if ( baseCall == null )
537+ {
538+ Logger . LogInformation ( $ "No base constructor defined for { type . Name } ") ;
539+ return false ;
540+ }
541+
542+ MethodReference baseConstructor = ( MethodReference ) baseCall . Operand ;
543+ if ( baseConstructor . Parameters ? . Count ( ) < 2 )
544+ {
545+ Logger . LogInformation ( $ "No not enough parameters for { type . Name } ") ;
546+ return false ;
547+ }
548+
549+ if ( baseConstructor . Parameters [ 0 ] . ParameterType . FullName != "Microsoft.PowerFx.Core.Utils.DPath" )
550+ {
551+ Logger . LogInformation ( $ "No Power FX Namespace for { type . Name } ") ;
552+ return false ;
553+ }
554+
555+ // Extract namespace from decompiled source
556+ var actionName = GetPowerFxNamespace ( type . Name , code ) ;
557+ if ( string . IsNullOrEmpty ( actionName ) )
558+ {
559+ Logger . LogInformation ( $ "No Power FX Namespace found for { type . Name } ") ;
560+ return false ;
561+ }
562+
563+ // Actions must not use the Preview namespace
564+ if ( string . Equals ( actionName , NAMESPACE_PREVIEW , StringComparison . OrdinalIgnoreCase ) )
565+ {
566+ Logger . LogInformation ( $ "Deny Preview Power FX Namespace { actionName } for action { type . Name } ") ;
567+ return false ;
568+ }
569+
570+ // Continue with the same allow/deny validation as functions
571+ if ( settings . DenyPowerFxNamespaces . Contains ( actionName ) )
572+ {
573+ Logger . LogInformation ( $ "Deny Power FX Namespace { actionName } for { type . Name } ") ;
574+ return false ;
575+ }
576+
577+ if ( ( settings . DenyPowerFxNamespaces . Contains ( "*" ) && (
578+ ! settings . AllowPowerFxNamespaces . Contains ( actionName ) ||
579+ ( ! settings . AllowPowerFxNamespaces . Contains ( actionName ) && actionName != NAMESPACE_TEST_ENGINE )
580+ )
581+ ) )
582+ {
583+ Logger . LogInformation ( $ "Deny Power FX Namespace { actionName } for { type . Name } ") ;
584+ return false ;
585+ }
586+
587+ if ( ! settings . AllowPowerFxNamespaces . Contains ( actionName ) && actionName != NAMESPACE_TEST_ENGINE )
588+ {
589+ Logger . LogInformation ( $ "Do not allow Power FX Namespace { actionName } for { type . Name } ") ;
590+ return false ;
591+ }
592+ }
593593 }
594594 }
595595 return isValid ;
0 commit comments