diff --git a/Projects/Modules/Documentarian.DevX/Source/Private/Classes/DevXAstInfo.psm1 b/Projects/Modules/Documentarian.DevX/Source/Private/Classes/DevXAstInfo.psm1 index b8ece4f..b9fb259 100644 --- a/Projects/Modules/Documentarian.DevX/Source/Private/Classes/DevXAstInfo.psm1 +++ b/Projects/Modules/Documentarian.DevX/Source/Private/Classes/DevXAstInfo.psm1 @@ -4,14 +4,78 @@ using namespace System.Management.Automation.Language class DevXAstInfo { - [ScriptBlockAst]$Ast - [Token[]]$Tokens - [ParseError[]]$Errors + <# + .SYNOPSIS + Class synopsis + #> - DevXAstInfo([ScriptBlock]$ScriptBlock) { + #region Static properties + #endregion Static properties + + #region Static methods + #endregion Static methods + + #region Instance properties + + <# + .Synopsis + The abstract syntax tree (AST) of the script block. + + .Description + This property contains the abstract syntax tree (AST) of the script block. The AST represents + the structure of the script block, including the statements, expressions, and other elements + that make up the script block. The AST is generated by the PowerShell parser when the script + block is parsed. + + #> + [ScriptBlockAst] + $Ast + + <# + .Synopsis + The tokens found when parsing the script block. + + .Description + This property contains the tokens found when parsing the script block. The tokens include the + comments from the script block, which aren't available in the AST. + #> + [Token[]] + $Tokens + + <# + .Synopsis + The parse errors found when parsing the script block. + + .Description + This property contains the parse errors found when parsing the script block. This property is + only populated if there are errors in the script block that prevent it from being parsed. The + presence of these errors indicates that the script block is not valid PowerShell code and + needs attention. + #> + [ParseError[]] + $Errors + + #endregion Instance properties + + #region Instance methods + #endregion Instance methods + + #region Constructors + + DevXAstInfo([ScriptBlock]$scriptBlock) { + <# + .SYNOPSIS + Initializes a new instance of DevXAstInfo from a script block. + + .DESCRIPTION + This constructor creates a new instance of DevXAstInfo from a script block. It parses the + script block into an AST and stores the AST, tokens, and errors in the new instance. + + .PARAMETER scriptBlock + #> $t, $e = $null $this.Ast = [Parser]::ParseInput( - $ScriptBlock.ToString(), + $scriptBlock.ToString(), [ref]$t, [ref]$e ) @@ -19,10 +83,22 @@ class DevXAstInfo { $this.Errors = $e } - DevXAstInfo([string]$Path) { + DevXAstInfo([string]$path) { + <# + .SYNOPSIS + Initializes a new instance of DevXAstInfo from a file path. + + .DESCRIPTION + This constructor creates a new instance of DevXAstInfo from a file path. It parses the file + into an AST and stores the AST, tokens, and errors in the new instance. + + .PARAMETER path + The path to a PowerShell code file to parse into an AST. + #> + $t, $e = $null $this.Ast = [Parser]::ParseFile( - $Path, + $path, [ref]$t, [ref]$e ) @@ -31,12 +107,45 @@ class DevXAstInfo { } DevXAstInfo([ScriptBlockAst]$ast) { + <# + .SYNOPSIS + Initializes a new instance of DevXAstInfo from a script block AST. + + .DESCRIPTION + This constructor creates a new instance of DevXAstInfo from a script block AST. It stores the + AST in the new instance. This contructor can't define the tokens or errors as it doesn't + parse the code itself. + + .PARAMETER ast + The script block AST to store in the new instance. + #> + $this.Ast = $ast } DevXAstInfo([ScriptBlockAst]$ast, [Token[]]$tokens, [ParseError[]]$errors) { - $this.Ast = $ast + <# + .SYNOPSIS + Initializes a new instance of DevXAstInfo from an AST, tokens, and errors. + + .DESCRIPTION + This constructor creates a new instance of DevXAstInfo from an AST, tokens, and errors. It + stores the AST, tokens, and errors in the new instance. + + .PARAMETER ast + The script block AST to store in the new instance. + + .PARAMETER tokens + The tokens to store in the new instance. + + .PARAMETER errors + The parse errors to store in the new instance. + #> + + $this.Ast = $ast $this.Tokens = $tokens $this.Errors = $errors } + + #endregion Constructors } diff --git a/Projects/Modules/Documentarian.DevX/Source/Private/Classes/DevXAstTypeTransformAttribute.psm1 b/Projects/Modules/Documentarian.DevX/Source/Private/Classes/DevXAstTypeTransformAttribute.psm1 index 36a0b93..a38d541 100644 --- a/Projects/Modules/Documentarian.DevX/Source/Private/Classes/DevXAstTypeTransformAttribute.psm1 +++ b/Projects/Modules/Documentarian.DevX/Source/Private/Classes/DevXAstTypeTransformAttribute.psm1 @@ -20,6 +20,25 @@ foreach ($RequiredFunction in $RequiredFunctions) { #endregion RequiredFunctions class DevXAstTypeTransformAttribute : ArgumentTransformationAttribute { + <# + .SYNOPSIS + Transforms input into a valid AST type. + + .DESCRIPTION + This attribute transforms input into a valid AST type. The input can be a type object or a + string representing the type name. The type must be in the + `System.Management.Automation.Language` namespace and must end in `Ast`. If the input is not a + valid AST type, an exception is thrown. + #> + + #region Static properties + #endregion Static properties + + #region Static methods + #endregion Static methods + + #region Instance properties + [object] Transform([EngineIntrinsics]$engineIntrinsics, [System.Object]$inputData) { $outputData = switch ($inputData) { { $_ -is [System.Type] } { @@ -71,4 +90,12 @@ class DevXAstTypeTransformAttribute : ArgumentTransformationAttribute { return $outputData } + + #endregion Instance properties + + #region Instance methods + #endregion Instance methods + + #region Constructors + #endregion Constructors } diff --git a/Projects/Modules/Documentarian.DevX/Source/Private/Classes/DevXValidatePowerShellScriptPathAttribute.psm1 b/Projects/Modules/Documentarian.DevX/Source/Private/Classes/DevXValidatePowerShellScriptPathAttribute.psm1 index c3f849d..4b2f94a 100644 --- a/Projects/Modules/Documentarian.DevX/Source/Private/Classes/DevXValidatePowerShellScriptPathAttribute.psm1 +++ b/Projects/Modules/Documentarian.DevX/Source/Private/Classes/DevXValidatePowerShellScriptPathAttribute.psm1 @@ -4,6 +4,27 @@ using namespace System.Management.Automation class DevXValidatePowerShellScriptPathAttribute : ValidateArgumentsAttribute { + <# + .SYNOPSIS + Validates that the specified path is for a valid PowerShell script file. + + .DESCRIPTION + This attribute validates that the specified path is for a valid PowerShell script file. The + path must be a file path to a PowerShell file with one of the following extensions: `.ps1`, + `.psm1`, or `.psd1`. The file must exist and be accessible. + #> + + #region Static properties + #endregion Static properties + + #region Static methods + #endregion Static methods + + #region Instance properties + #endregion Instance properties + + #region Instance methods + [void] Validate([object]$arguments, [EngineIntrinsics]$engineIntrinsics) { $Path = $arguments @@ -38,4 +59,9 @@ class DevXValidatePowerShellScriptPathAttribute : ValidateArgumentsAttribute { throw [System.ArgumentException]::new("$MessagePrefix; $Message") } } + + #endregion Instance methods + + #region Constructors + #endregion Constructors } diff --git a/Projects/Modules/Documentarian.DevX/Source/Private/Enums/ClassLogLevels.psm1 b/Projects/Modules/Documentarian.DevX/Source/Private/Enums/ClassLogLevels.psm1 index 7f8f3c2..50946ae 100644 --- a/Projects/Modules/Documentarian.DevX/Source/Private/Enums/ClassLogLevels.psm1 +++ b/Projects/Modules/Documentarian.DevX/Source/Private/Enums/ClassLogLevels.psm1 @@ -2,12 +2,25 @@ # Licensed under the MIT License. enum ClassLogLevels { - # The class shouldn't write any log messages. - None = 0 - # The class should write basic log messages. - # Equivalent to verbose logging. - Basic = 1 - # The class should write detailed log messages. - # Equivalent to debug logging. + <# + .SYNOPSIS + Defines the logging levels for classes. + + .DESCRIPTION + Defines the logging levels for classes. The logging level determines the amount of log + messages that a class should write when it performs operations. + + .LABEL None + The class shouldn't write any log messages. + + .LABEL Basic + The class should write basic log messages. Equivalent to verbose logging. + + .LABEL Detailed + The class should write detailed log messages. Equivalent to debug logging. + #> + + None = 0 + Basic = 1 Detailed = 2 } diff --git a/Projects/Modules/Documentarian.DevX/Source/Private/Enums/UncommonLineEndingAction.psm1 b/Projects/Modules/Documentarian.DevX/Source/Private/Enums/UncommonLineEndingAction.psm1 index 0c90b2b..d651e35 100644 --- a/Projects/Modules/Documentarian.DevX/Source/Private/Enums/UncommonLineEndingAction.psm1 +++ b/Projects/Modules/Documentarian.DevX/Source/Private/Enums/UncommonLineEndingAction.psm1 @@ -2,7 +2,25 @@ # Licensed under the MIT License. enum UncommonLineEndingAction { - SilentlyContinue - WarnAndContinue - ErrorAndStop + <# + .SYNOPSIS + Defines the action to take when an uncommon line ending is encountered. + + .DESCRIPTION + Defines the action to take when an uncommon line ending is encountered. An uncommon line ending + is a line ending that is not the standard line ending for the current platform. + + .LABEL SilentlyContinue + Ignore the uncommon line ending and continue processing. + + .LABEL WarnAndContinue + Emit a warning about the uncommon line ending and continue processing. + + .LABEL ErrorAndStop + Emit an error about the uncommon line ending and stop processing. + #> + + SilentlyContinue = 0 + WarnAndContinue = 1 + ErrorAndStop = 2 } diff --git a/Projects/Modules/Documentarian.DevX/Source/Private/Functions/Find-Ast.ps1 b/Projects/Modules/Documentarian.DevX/Source/Private/Functions/Find-Ast.ps1 index 6716fbb..d36e67a 100644 --- a/Projects/Modules/Documentarian.DevX/Source/Private/Functions/Find-Ast.ps1 +++ b/Projects/Modules/Documentarian.DevX/Source/Private/Functions/Find-Ast.ps1 @@ -21,37 +21,91 @@ foreach ($RequiredFunction in $RequiredFunctions) { #endregion RequiredFunctions Function Find-Ast { + <# + .SYNOPSIS + Search an AST for nodes that match a predicate. + + .DESCRIPTION + This function searches an AST for nodes that match a predicate. The predicate can be a script + block or a type. If a type is specified, the predicate is created from the type, returning any + matching AST objects. You can specify the AST to search by providing an `AstInfo` object, a + file path, or a script block. + + The function can search a single AST node or recurse through all child nodes. The function + returns all matching nodes. + + .PARAMETER DevXAstInfo + The `AstInfo` object to search. This parameter is mandatory if the **Path** or **ScriptBlock** + parameters are not specified. + + .PARAMETER Path + The file path to the script file containing the AST to search. This parameter is mandatory if + the **DevXAstInfo** or **ScriptBlock** parameters are not specified. + + .PARAMETER ScriptBlock + The script block containing the AST to search. This parameter is mandatory if the + **DevXAstInfo** or **Path** parameters are not specified. + + .PARAMETER Predicate + The predicates to use when searching the AST. This parameter is mandatory if the **Type** + parameter is not specified. Each predicate must be a script block that returns `$true` if the + AST node should be returned and otherwise `$false`. + + .PARAMETER Type + The AST types to search for. This parameter is mandatory if the **Predicate** parameter is not + specified. Each type must be a type object or a string representing the type name. The type + must be in the `System.Management.Automation.Language` namespace and must end in `Ast`. + + .PARAMETER Recurse + Indicates that the function should search all child nodes of the AST. By default, the function + only searches the top-level nodes. + + .OUTPUTS System.Management.Automation.Language.Ast + The function returns every AST node that matches the predicates or is in the type list. + #> + [CmdletBinding(DefaultParameterSetName = 'FromtAstInfo')] [OutputType([System.Management.Automation.Language.Ast])] Param( [Parameter(Mandatory, ParameterSetName = 'FromAstInfoWithPredicate')] [Parameter(Mandatory, ParameterSetName = 'FromAstInfoWithType')] - [DevXAstInfo]$DevXAstInfo, + [DevXAstInfo] + $DevXAstInfo, [Parameter(Mandatory, ParameterSetName = 'FromPathWithPredicate')] [Parameter(Mandatory, ParameterSetName = 'FromPathWithType')] - [string]$Path, + [string] + $Path, [Parameter(Mandatory, ParameterSetName = 'FromScriptBlockWithPredicate')] [Parameter(Mandatory, ParameterSetName = 'FromScriptBlockWithType')] - [scriptblock]$ScriptBlock, + [scriptblock] + $ScriptBlock, [Parameter(Mandatory, ParameterSetName = 'FromAstInfoWithPredicate')] [Parameter(Mandatory, ParameterSetName = 'FromPathWithPredicate')] [Parameter(Mandatory, ParameterSetName = 'FromScriptBlockWithPredicate')] - [ScriptBlock[]]$Predicate, + [ScriptBlock[]] + $Predicate, [Parameter(Mandatory, ParameterSetName = 'FromAstInfoWithType')] [Parameter(Mandatory, ParameterSetName = 'FromPathWithType')] [Parameter(Mandatory, ParameterSetName = 'FromScriptBlockWithType')] [DevXAstTypeTransformAttribute()] - [System.Type[]]$Type, + [System.Type[]] + $Type, - [switch]$Recurse + [Parameter()] + [switch] + $Recurse ) + begin { + + } + process { - if (![string]::isNullOrEmpty($Path)) { + if (-not [string]::IsNullOrEmpty($Path)) { $DevXAstInfo = Get-Ast -Path $Path } elseif ($null -ne $ScriptBlock) { $DevXAstInfo = Get-Ast -ScriptBlock $ScriptBlock @@ -65,4 +119,8 @@ Function Find-Ast { $DevXAstInfo.Ast.FindAll($_, $Recurse) } } + + end { + + } } diff --git a/Projects/Modules/Documentarian.DevX/Source/Private/Functions/Get-Ast.ps1 b/Projects/Modules/Documentarian.DevX/Source/Private/Functions/Get-Ast.ps1 index fcac198..ee826c2 100644 --- a/Projects/Modules/Documentarian.DevX/Source/Private/Functions/Get-Ast.ps1 +++ b/Projects/Modules/Documentarian.DevX/Source/Private/Functions/Get-Ast.ps1 @@ -5,22 +5,57 @@ using module ../Classes/DevXAstInfo.psm1 using module ../Classes/DevXValidatePowerShellScriptPathAttribute.psm1 Function Get-Ast { + <# + .SYNOPSIS + Gets the abstract syntax tree (AST) of a PowerShell script. + + .DESCRIPTION + This function gets the abstract syntax tree (AST) of a PowerShell script. The AST represents + the structure of the script, including the statements, expressions, and other elements that + make up the script. The AST is generated by the PowerShell parser when the script is parsed. + + You can specify the script to parse by providing a file path, a script block, or a string + containing the script text. + + .PARAMETER Path + The file path to the script file to parse. The file must be a valid PowerShell code file that + exists and is accessible. This parameter is mandatory if the **ScriptBlock** or **Text** + parameters aren't specified. + + .PARAMETER ScriptBlock + The script block to parse. This parameter is mandatory if the **Path** or **Text** parameters + aren't specified. + + .PARAMETER Text + The text of the script to parse. This parameter is mandatory if the **Path** or **ScriptBlock** + parameters aren't specified. + + .OUTPUTs + Returns an instance of the `DevXAstInfo` class that contains the AST, tokens, and errors found + when parsing the script. + #> + [CmdletBinding()] [OutputType([DevXAstInfo])] param( [Parameter(Mandatory, ParameterSetName = 'ByPath')] [DevXValidatePowerShellScriptPathAttribute()] - [string]$Path, + [string] + $Path, [Parameter(Mandatory, ParameterSetName = 'ByScriptBlock')] - [scriptblock]$ScriptBlock, + [scriptblock] + $ScriptBlock, [Parameter(Mandatory, ParameterSetName = 'ByInputText')] [ValidateNotNullOrEmpty()] - [string]$Text + [string] + $Text ) - begin {} + begin { + + } process { switch ($PSCmdlet.ParameterSetName) { @@ -37,5 +72,7 @@ Function Get-Ast { } } - end {} + end { + + } } diff --git a/Projects/Modules/Documentarian.DevX/Source/Private/Functions/Get-AstType.ps1 b/Projects/Modules/Documentarian.DevX/Source/Private/Functions/Get-AstType.ps1 index 39e0d9b..560c8ca 100644 --- a/Projects/Modules/Documentarian.DevX/Source/Private/Functions/Get-AstType.ps1 +++ b/Projects/Modules/Documentarian.DevX/Source/Private/Functions/Get-AstType.ps1 @@ -17,6 +17,11 @@ foreach ($RequiredFunction in $RequiredFunctions) { #endregion RequiredFunctions Function Get-AstType { + <# + .SYNOPSIS + Function synopsis. + #> + [CmdletBinding(DefaultParameterSetName = 'ByPattern')] [OutputType([Type])] Param( @@ -25,14 +30,16 @@ Function Get-AstType { ParameterSetName = 'ByPattern', HelpMessage = 'Specify a valid regex pattern to match in the list of AST types' )] - [string]$Pattern, + [string] + $Pattern, [Parameter( Mandatory, ParameterSetName = 'ByName', HelpMessage = 'Specify a name to look for in the list of AST types; the "Ast" suffix is optional' )] - [string[]]$Name + [string[]] + $Name ) begin { @@ -45,7 +52,7 @@ Function Get-AstType { } process { - if (![string]::IsNullOrEmpty($Pattern)) { + if (-not [string]::IsNullOrEmpty($Pattern)) { $Types | Where-Object -FilterScript { $_.Name -match $Pattern } @@ -60,5 +67,7 @@ Function Get-AstType { } } - end {} + end { + + } } diff --git a/Projects/Modules/Documentarian.DevX/Source/Private/Functions/Get-EnumRegex.ps1 b/Projects/Modules/Documentarian.DevX/Source/Private/Functions/Get-EnumRegex.ps1 index ae5a546..10bf7d4 100644 --- a/Projects/Modules/Documentarian.DevX/Source/Private/Functions/Get-EnumRegex.ps1 +++ b/Projects/Modules/Documentarian.DevX/Source/Private/Functions/Get-EnumRegex.ps1 @@ -2,13 +2,29 @@ # Licensed under the MIT License. function Get-EnumRegex { + <# + .SYNOPSIS + Function synopsis. + #> + [CmdletBinding()] [OutputType([String])] param( [Parameter(Mandatory)] [ValidateScript({ $_.IsEnum })] - [Type]$EnumType + [Type] + $EnumType ) - "(?<$($EnumType.Name)>($($EnumType.GetEnumNames() -join '|')))" + begin { + + } + + process { + "(?<$($EnumType.Name)>($($EnumType.GetEnumNames() -join '|')))" + } + + end { + + } } diff --git a/Projects/Modules/Documentarian.DevX/Source/Private/Functions/New-AstPredicate.ps1 b/Projects/Modules/Documentarian.DevX/Source/Private/Functions/New-AstPredicate.ps1 index 426afa2..56f657e 100644 --- a/Projects/Modules/Documentarian.DevX/Source/Private/Functions/New-AstPredicate.ps1 +++ b/Projects/Modules/Documentarian.DevX/Source/Private/Functions/New-AstPredicate.ps1 @@ -4,17 +4,34 @@ using module ../Classes/DevXAstTypeTransformAttribute.psm1 Function New-AstPredicate { + <# + .SYNOPSIS + Function synopsis. + #> + [CmdletBinding()] [OutputType([ScriptBlock])] Param ( + [Parameter()] [DevXAstTypeTransformAttribute()] - [System.Type[]]$Type + [System.Type[]] + $Type ) - foreach ($Item in $Type) { - { - param([System.Management.Automation.Language.Ast]$AstObject) - return ($AstObject -is $Item) - }.GetNewClosure() + begin { + + } + + process { + foreach ($Item in $Type) { + { + param([System.Management.Automation.Language.Ast]$AstObject) + return ($AstObject -is $Item) + }.GetNewClosure() + } + } + + end { + } } diff --git a/Projects/Modules/Documentarian.DevX/Source/Private/Functions/New-SourceFile.ps1 b/Projects/Modules/Documentarian.DevX/Source/Private/Functions/New-SourceFile.ps1 index 3e79c0f..f3b9c60 100644 --- a/Projects/Modules/Documentarian.DevX/Source/Private/Functions/New-SourceFile.ps1 +++ b/Projects/Modules/Documentarian.DevX/Source/Private/Functions/New-SourceFile.ps1 @@ -4,14 +4,32 @@ using module ../../Public/Classes/SourceFile.psm1 function New-SourceFile { + <# + .SYNOPSIS + Function synopsis. + #> + [CmdletBinding()] [OutputType([SourceFile])] param( - [string]$NameSpace, - [string]$Path + [Parameter()] + [string] + $NameSpace, + + [Parameter()] + [string] + $Path ) + begin { + + } + process { [SourceFile]::new($NameSpace, $Path) } + + end { + + } } diff --git a/Projects/Modules/Documentarian.DevX/Source/Private/Functions/New-SourceFolder.ps1 b/Projects/Modules/Documentarian.DevX/Source/Private/Functions/New-SourceFolder.ps1 index 2827755..9266390 100644 --- a/Projects/Modules/Documentarian.DevX/Source/Private/Functions/New-SourceFolder.ps1 +++ b/Projects/Modules/Documentarian.DevX/Source/Private/Functions/New-SourceFolder.ps1 @@ -4,15 +4,27 @@ using module ../../Public/Classes/SourceFolder.psm1 function New-SourceFolder { + <# + .SYNOPSIS + Function synopsis. + #> + [CmdletBinding()] [OutputType([SourceFolder])] param( - [string]$NameSpace, + [Parameter()] + [string] + $NameSpace, [Parameter(Mandatory)] - [string]$Path + [string] + $Path ) + begin { + + } + process { if ($NameSpace) { [SourceFolder]::new($NameSpace, $Path) @@ -20,4 +32,8 @@ function New-SourceFolder { [SourceFolder]::new($Path) } } + + end { + + } } diff --git a/Projects/Modules/Documentarian.DevX/Source/Private/Functions/New-SourceReference.ps1 b/Projects/Modules/Documentarian.DevX/Source/Private/Functions/New-SourceReference.ps1 index 0de09c9..a2854ac 100644 --- a/Projects/Modules/Documentarian.DevX/Source/Private/Functions/New-SourceReference.ps1 +++ b/Projects/Modules/Documentarian.DevX/Source/Private/Functions/New-SourceReference.ps1 @@ -5,13 +5,27 @@ using module ../../Public/Classes/SourceFile.psm1 using module ../../Public/Classes/SourceReference.psm1 function New-SourceReference { + <# + .SYNOPSIS + Function synopsis. + #> + [CmdletBinding()] [OutputType([SourceReference])] param( - [SourceFile]$SourceFile, - [SourceFile[]]$Reference + [Parameter()] + [SourceFile] + $SourceFile, + + [Parameter()] + [SourceFile[]] + $Reference ) + begin { + + } + process { if ($Reference) { [SourceReference]::new($SourceFile, $Reference) @@ -19,4 +33,8 @@ function New-SourceReference { [SourceReference]::new($SourceFile) } } + + end { + + } } diff --git a/Projects/Modules/Documentarian.DevX/Source/Private/Functions/Resolve-NameSpace.ps1 b/Projects/Modules/Documentarian.DevX/Source/Private/Functions/Resolve-NameSpace.ps1 index 8972304..feda0a7 100644 --- a/Projects/Modules/Documentarian.DevX/Source/Private/Functions/Resolve-NameSpace.ps1 +++ b/Projects/Modules/Documentarian.DevX/Source/Private/Functions/Resolve-NameSpace.ps1 @@ -20,20 +20,29 @@ foreach ($RequiredFunction in $RequiredFunctions) { #endregion RequiredFunctions function Resolve-NameSpace { + <# + .SYNOPSIS + Function synopsis + #> + [CmdletBinding()] [OutputType([String])] param( [Parameter(Mandatory, ParameterSetName = 'ByTaxonomy')] - [SourceCategory]$Category, + [SourceCategory] + $Category, [Parameter(Mandatory, ParameterSetName = 'ByTaxonomy')] - [SourceScope]$Scope, + [SourceScope] + $Scope, [Parameter(ParameterSetName = 'ByPath')] - [string]$ParentNameSpace, + [string] + $ParentNameSpace, [Parameter(Mandatory, ParameterSetName = 'ByPath')] - [string]$Path + [string] + $Path ) begin { @@ -48,7 +57,7 @@ function Resolve-NameSpace { process { $ParentNameSpace = '' - $ChildNameSpace = '' + $ChildNameSpace = '' # If a path is specified, we need to figure out child namespacing if ($Path) { @@ -108,4 +117,8 @@ function Resolve-NameSpace { return $ParentNameSpace } } + + end { + + } } diff --git a/Projects/Modules/Documentarian.DevX/Source/Private/Functions/Test-DevXIsAstType.ps1 b/Projects/Modules/Documentarian.DevX/Source/Private/Functions/Test-DevXIsAstType.ps1 index bf383d7..197bfd4 100644 --- a/Projects/Modules/Documentarian.DevX/Source/Private/Functions/Test-DevXIsAstType.ps1 +++ b/Projects/Modules/Documentarian.DevX/Source/Private/Functions/Test-DevXIsAstType.ps1 @@ -2,14 +2,31 @@ # Licensed under the MIT License. Function Test-DevXIsAstType { + <# + .SYNOPSIS + Determines if a type is an AST type. + #> + [CmdletBinding()] [OutputType([bool])] Param( - [System.Type]$Type + [Parameter()] + [System.Type] + $Type ) - $InNamespace = $Type.NameSpace -eq 'System.Management.Automation.Language' - $EndsInAst = $Type.Name -match 'Ast$' + begin { + + } + + process { + $InNamespace = $Type.NameSpace -eq 'System.Management.Automation.Language' + $EndsInAst = $Type.Name -match 'Ast$' + + return ($InNamespace -and $EndsInAst) + } + + end { - return ($InNamespace -and $EndsInAst) + } } diff --git a/Projects/Modules/Documentarian.DevX/Source/Public/Classes/ModuleComposer.psm1 b/Projects/Modules/Documentarian.DevX/Source/Public/Classes/ModuleComposer.psm1 index b5f85ca..fe5bd2f 100644 --- a/Projects/Modules/Documentarian.DevX/Source/Public/Classes/ModuleComposer.psm1 +++ b/Projects/Modules/Documentarian.DevX/Source/Public/Classes/ModuleComposer.psm1 @@ -25,6 +25,13 @@ foreach ($RequiredFunction in $RequiredFunctions) { #endregion RequiredFunctions class ModuleComposer { + <# + .SYNOPSIS + Composes a PowerShell module from source files and configuration settings. + #> + + #region Instance properties + #region Configurable Settings [string] $ProjectRootFolderPath @@ -80,15 +87,31 @@ class ModuleComposer { #endregion Composed Module Content Properties #region Logging - hidden [ClassLogLevels] $LogLevel = [ClassLogLevels]::None + + <# + .SYNOPSIS + #> + hidden + [ClassLogLevels] + $LogLevel = [ClassLogLevels]::None + hidden [System.Management.Automation.ActionPreference] VerbosePreference() { + <# + .SYNOPSIS + #> + if ($this.LogLevel -gt [ClassLogLevels]::None) { return [System.Management.Automation.ActionPreference]::Continue } else { return [System.Management.Automation.ActionPreference]::SilentlyContinue } } + hidden [System.Management.Automation.ActionPreference] DebugPreference() { + <# + .SYNOPSIS + #> + if ($this.LogLevel -eq [ClassLogLevels]::Detailed) { return [System.Management.Automation.ActionPreference]::Continue } else { @@ -97,7 +120,15 @@ class ModuleComposer { } #endregion Logging + #endregion Instance properties + + #region Instance methods + [string] GetUsingPrivateModuleStatement() { + <# + .SYNOPSIS + #> + $VerbosePreference = $this.VerbosePreference() $DebugPreference = $this.DebugPreference() $statement = if ([string]::IsNullOrEmpty($this.OutputPrivateModulePath)) { @@ -109,63 +140,16 @@ class ModuleComposer { return $statement } - #region Constructors - ModuleComposer () { - $this.Initialize() - } - - hidden ModuleComposer([ClassLogLevels]$LogLevel) { - $this.LogLevel = $LogLevel - $VerbosePreference = $this.VerbosePreference() - $DebugPreference = $this.DebugPreference() - Write-Verbose 'Constructing ModuleComposer...' - $this.Initialize() - } - - ModuleComposer ([string]$ProjectRootFolderPath) { - $this.ProjectRootFolderPath = $ProjectRootFolderPath - $this.Initialize() - } - - hidden ModuleComposer ([string]$ProjectRootFolderPath, [ClassLogLevels]$LogLevel) { - $this.LogLevel = $LogLevel - $VerbosePreference = $this.VerbosePreference() - $DebugPreference = $this.DebugPreference() - Write-Verbose 'Constructing ModuleComposer...' - $this.ProjectRootFolderPath = $ProjectRootFolderPath - Write-Debug "Set project root path to $ProjectRootFolderPath" - $this.Initialize() - } - - ModuleComposer( - [string]$ProjectRootFolderPath, - [hashtable]$ConfigurationSettings - ) { - $this.ProjectRootFolderPath = $ProjectRootFolderPath - $this.ProcessConfigurationSettings($ConfigurationSettings) - $this.Initialize() - } - - hidden ModuleComposer( - [string]$ProjectRootFolderPath, - [hashtable]$ConfigurationSettings, - [ClassLogLevels]$LogLevel + [void] ProcessConfigurationSettings( + [hashtable] + $ConfigurationSettings ) { - $this.LogLevel = $LogLevel - $VerbosePreference = $this.VerbosePreference() - $DebugPreference = $this.DebugPreference() - Write-Verbose 'Constructing ModuleComposer...' - $this.ProjectRootFolderPath = $ProjectRootFolderPath - Write-Debug "Set project root path to $ProjectRootFolderPath" - $this.ProcessConfigurationSettings($ConfigurationSettings) - $this.Initialize() - Write-Verbose 'Constructed ModuleComposer.' - } - #endregion Constructors + <# + .SYNOPSIS + #> - [void] ProcessConfigurationSettings([hashtable]$ConfigurationSettings) { $VerbosePreference = $this.VerbosePreference() - $DebugPreference = $this.DebugPreference() + $DebugPreference = $this.DebugPreference() Write-Verbose 'Processing configuration settings...' foreach ($SettingKey in $ConfigurationSettings.Keys) { @@ -225,10 +209,15 @@ class ModuleComposer { # $MungedHash.$SettingKey = $Value $this.$SettingKey = $Value } + Write-Verbose 'Processed configuration settings.' } [void] Initialize() { + <# + .SYNOPSIS + #> + $VerbosePreference = $this.VerbosePreference() $DebugPreference = $this.DebugPreference() Write-Verbose 'Initializing...' @@ -387,6 +376,10 @@ class ModuleComposer { } [void] InitializeModuleLineEnding() { + <# + .SYNOPSIS + #> + $VerbosePreference = $this.VerbosePreference() $DebugPreference = $this.DebugPreference() if ([string]::IsNullOrEmpty($this.ModuleLineEnding)) { @@ -405,6 +398,10 @@ class ModuleComposer { } [void] InitializeSourceFolders() { + <# + .SYNOPSIS + #> + $VerbosePreference = $this.VerbosePreference() $DebugPreference = $this.DebugPreference() Write-Verbose 'Initializing source folders...' @@ -442,6 +439,10 @@ class ModuleComposer { } [void] InitializePublicFunctions() { + <# + .SYNOPSIS + #> + $VerbosePreference = $this.VerbosePreference() $DebugPreference = $this.DebugPreference() if ($null -eq $this.SourceFolders) { @@ -457,6 +458,10 @@ class ModuleComposer { } [void] InitializeTaskList() { + <# + .SYNOPSIS + #> + $VerbosePreference = $this.VerbosePreference() $DebugPreference = $this.DebugPreference() Write-Verbose 'Initializing task list...' @@ -486,6 +491,10 @@ class ModuleComposer { } [void] CleanOutputFolder() { + <# + .SYNOPSIS + #> + $VerbosePreference = $this.VerbosePreference() $DebugPreference = $this.DebugPreference() @@ -500,6 +509,10 @@ class ModuleComposer { } [void] CreateOutputFolder() { + <# + .SYNOPSIS + #> + $VerbosePreference = $this.VerbosePreference() $DebugPreference = $this.DebugPreference() $this.CleanOutputFolder() @@ -510,6 +523,10 @@ class ModuleComposer { } [void] ComposePrivateModuleContent() { + <# + .SYNOPSIS + #> + $VerbosePreference = $this.VerbosePreference() $DebugPreference = $this.DebugPreference() if (!([string]::IsNullOrEmpty($this.OutputPrivateModulePath))) { @@ -536,6 +553,10 @@ class ModuleComposer { } [void] ComposeRootModuleContent() { + <# + .SYNOPSIS + #> + $VerbosePreference = $this.VerbosePreference() $DebugPreference = $this.DebugPreference() Write-Verbose 'Composing root module content...' @@ -729,25 +750,56 @@ class ModuleComposer { Write-Verbose 'Composed root module content.' } - [SourceFolder[]] GetSourceFolder([SourceScope]$Scope) { + [SourceFolder[]] GetSourceFolder( + [SourceScope] + $Scope + ) { + <# + .SYNOPSIS + #> + return $this.SourceFolders | Where-Object -FilterScript { $_.Scope -eq $Scope } } - [string] GetDefinedTypeName([SourceFile]$sourceFile) { + [string] GetDefinedTypeName( + [SourceFile] + $sourceFile + ) { + <# + .SYNOPSIS + #> + # Replace with AST Lookup later $TypeName = $sourceFile.FileInfo.BaseName return "[$TypeName]" } - [SourceFolder[]] GetSourceFolder([SourceCategory[]]$Category) { + [SourceFolder[]] GetSourceFolder( + [SourceCategory[]] + $Category + ) { + <# + .SYNOPSIS + #> + return $this.SourceFolders | Where-Object -FilterScript { $_.Category -in $Category } } - [SourceFolder[]] GetSourceFolder([SourceScope]$Scope, [SourceCategory[]]$Category) { + [SourceFolder[]] GetSourceFolder( + [SourceScope] + $Scope, + + [SourceCategory[]] + $Category + ) { + <# + .SYNOPSIS + #> + return $this.SourceFolders | Where-Object -FilterScript { ($_.Scope -eq $Scope) -and ($_.Category -in $Category) } @@ -774,7 +826,14 @@ class ModuleComposer { ).SourceFiles } - hidden [string] TrimNotices([string]$Content) { + hidden [string] TrimNotices( + [string] + $Content + ) { + <# + .SYNOPSIS + #> + foreach ($Notice in @($this.ModuleCopyrightNotice, $this.ModuleLicenseNotice)) { if (![string]::IsNullOrEmpty($Notice)) { $NoticeRegex = [regex]::escape($Notice) @@ -784,7 +843,14 @@ class ModuleComposer { return $Content.trim() } - hidden [string] MungeComposedContent([string]$Content) { + hidden [string] MungeComposedContent( + [string] + $Content + ) { + <# + .SYNOPSIS + #> + # Remove the module notices from the file. These global notices only need to # be listed once at the top of the file. $MungedContent = $this.TrimNotices($content) @@ -812,8 +878,12 @@ class ModuleComposer { } [void] ComposeInitScriptContent() { + <# + .SYNOPSIS + #> + $VerbosePreference = $this.VerbosePreference() - $DebugPreference = $this.DebugPreference() + $DebugPreference = $this.DebugPreference() Write-Verbose 'Composing init script content...' $ContentBuilder = New-Object -TypeName System.Text.StringBuilder @@ -884,6 +954,10 @@ class ModuleComposer { } [void] ComposeTypeFileContent() { + <# + .SYNOPSIS + #> + $VerbosePreference = $this.VerbosePreference() $DebugPreference = $this.DebugPreference() if (!([string]::IsNullOrEmpty($this.OutputTypesFilePath))) { @@ -919,6 +993,10 @@ class ModuleComposer { } [void] ComposeFormatFileContent() { + <# + .SYNOPSIS + #> + $VerbosePreference = $this.VerbosePreference() $DebugPreference = $this.DebugPreference() @@ -957,6 +1035,10 @@ class ModuleComposer { } [void] ComposeDocumentation() { + <# + .SYNOPSIS + #> + $VerbosePreference = $this.VerbosePreference() $DebugPreference = $this.DebugPreference() Write-Verbose 'Composing documentation...' @@ -977,6 +1059,10 @@ class ModuleComposer { } [void] ExportComposedModule() { + <# + .SYNOPSIS + #> + $VerbosePreference = $this.VerbosePreference() $DebugPreference = $this.DebugPreference() @@ -1040,4 +1126,111 @@ class ModuleComposer { New-ModuleManifest @ManifestParameters Write-Verbose 'Exported composed module.' } + + #endregion Instance methods + + #region Constructors + + ModuleComposer () { + <# + .SYNOPSIS + #> + + + $this.Initialize() + } + + ModuleComposer( + [ClassLogLevels] + $LogLevel + ) { + <# + .SYNOPSIS + #> + + + $this.LogLevel = $LogLevel + $VerbosePreference = $this.VerbosePreference() + $DebugPreference = $this.DebugPreference() + Write-Verbose 'Constructing ModuleComposer...' + $this.Initialize() + } + + ModuleComposer ( + [string] + $ProjectRootFolderPath + ) { + <# + .SYNOPSIS + #> + + + $this.ProjectRootFolderPath = $ProjectRootFolderPath + $this.Initialize() + } + + ModuleComposer ( + [string] + $ProjectRootFolderPath, + + [ClassLogLevels] + $LogLevel + ) { + <# + .SYNOPSIS + #> + + + $this.LogLevel = $LogLevel + $VerbosePreference = $this.VerbosePreference() + $DebugPreference = $this.DebugPreference() + Write-Verbose 'Constructing ModuleComposer...' + $this.ProjectRootFolderPath = $ProjectRootFolderPath + Write-Debug "Set project root path to $ProjectRootFolderPath" + $this.Initialize() + } + + ModuleComposer( + [string] + $ProjectRootFolderPath, + + [hashtable] + $ConfigurationSettings + ) { + <# + .SYNOPSIS + #> + + + $this.ProjectRootFolderPath = $ProjectRootFolderPath + $this.ProcessConfigurationSettings($ConfigurationSettings) + $this.Initialize() + } + + ModuleComposer( + [string] + $ProjectRootFolderPath, + + [hashtable] + $ConfigurationSettings, + + [ClassLogLevels] + $LogLevel + ) { + <# + .SYNOPSIS + #> + + $this.LogLevel = $LogLevel + $VerbosePreference = $this.VerbosePreference() + $DebugPreference = $this.DebugPreference() + Write-Verbose 'Constructing ModuleComposer...' + $this.ProjectRootFolderPath = $ProjectRootFolderPath + Write-Debug "Set project root path to $ProjectRootFolderPath" + $this.ProcessConfigurationSettings($ConfigurationSettings) + $this.Initialize() + Write-Verbose 'Constructed ModuleComposer.' + } + + #endregion Constructors } diff --git a/Projects/Modules/Documentarian.DevX/Source/Public/Classes/SourceFile.psm1 b/Projects/Modules/Documentarian.DevX/Source/Public/Classes/SourceFile.psm1 index ebe3880..99bc29d 100644 --- a/Projects/Modules/Documentarian.DevX/Source/Public/Classes/SourceFile.psm1 +++ b/Projects/Modules/Documentarian.DevX/Source/Public/Classes/SourceFile.psm1 @@ -21,26 +21,47 @@ foreach ($RequiredFunction in $RequiredFunctions) { #endregion RequiredFunctions class SourceFile { - [SourceCategory]$Category - [SourceScope]$Scope - [string]$NameSpace - [System.IO.FileInfo]$FileInfo - [string]$LineEnding - [string[]]$CopyrightNotices - [string[]]$LicenseNotices - [string]$RawContent - [string]$MungedContent - - hidden [string[]]$NonLocalUsingStatements - hidden [bool]$CheckedForLocalUsingStatements - - static [string]$CopyrightNoticePattern = '^# Copyright (.+)$' - static [string]$CopyrightNoticePatternXml = 'Copyright .+' - - static [string]$LicenseNoticePattern = '^# Licensed under (.+)$' - static [string]$LicenseNoticePatternXml = 'Licensed under .+' - - static [string]$MungingPrefixPattern = @( + <# + .SYNOPSIS + Defines a source file for module composition and development. + #> + + #region Static properties + + <# + .SYNOPSIS + #> + static + [string] + $CopyrightNoticePattern = '^# Copyright (.+)$' + + <# + .SYNOPSIS + #> + static + [string] + $CopyrightNoticePatternXml = 'Copyright .+' + + <# + .SYNOPSIS + #> + static + [string] + $LicenseNoticePattern = '^# Licensed under (.+)$' + + <# + .SYNOPSIS + #> + static + [string] + $LicenseNoticePatternXml = 'Licensed under .+' + + <# + .SYNOPSIS + #> + static + [string] + $MungingPrefixPattern = @( # This segment is to do multiline regex and capture only named groups '(?m)(?n)' # This segment captures everything until the first definition @@ -49,63 +70,40 @@ class SourceFile { '(?(.|\s)+)' ) -join '' - static [string]$MungingNoticesPattern = @( + <# + .SYNOPSIS + #> + static + [string] + $MungingNoticesPattern = @( # This segment is to do multiline regex and capture only named groups '(?m)(?n)' # Capture the notices so they can be stripped out. '(?' - '(' - '(' # We don't know the definite ordering for notices, so accept either - [SourceFile]::CopyrightNoticePattern - '|' - [SourceFile]::LicenseNoticePattern - ')\r?\n?' - ')+' # Can have 1 or more notices + '(' + '(' # We don't know the definite ordering for notices, so accept either + [SourceFile]::CopyrightNoticePattern + '|' + [SourceFile]::LicenseNoticePattern + ')\r?\n?' + ')+' # Can have 1 or more notices ')?' # Some projects might not have notices # This segment captures the rest of the file as the definition. '(?(.|\s)+)' ) -join '' - SourceFile([string]$ParentNameSpace, [string]$Path) { - $this.NameSpace = Resolve-NameSpace -Path $Path -ParentNameSpace $ParentNameSpace - $this.ResolveCategoryAndScopeFromNameSpace() - $this.FileInfo = $Path - $this.SetRawContent() - $this.MungeContent() - $this.DefineCopyrightNotice() - $this.DefineLicenseNotice() - $this.DefineLineEnding() - } - - SourceFile( - [string]$Path - ) { - $this.NameSpace = Resolve-NameSpace -Path $Path - $this.ResolveCategoryAndScopeFromNameSpace() - $this.FileInfo = $Path - $this.SetRawContent() - $this.MungeContent() - $this.DefineCopyrightNotice() - $this.DefineLicenseNotice() - $this.DefineLineEnding() - } - - [void] SetRawContent() { - $this.RawContent = Get-Content -Path $this.FileInfo.FullName -Raw - } + #endregion Static properties - [string[]] GetNonLocalUsingStatements() { - if (!$this.CheckedForLocalUsingStatements) { - $this.NonLocalUsingStatements = $this.RawContent -split '(\r\n|\n|\r)' - | Where-Object -FilterScript { $_ -match '^(using \w+ .+|#requires -\w+ .+)' } - | Where-Object -FilterScript { $_ -notmatch '(\\|\/)' } + #region Static methods - $this.CheckedForLocalUsingStatements = $true - } - return $this.NonLocalUsingStatements - } + static [string] MungeContent( + [string] + $Content + ) { + <# + .SYNOPSIS + #> - static [string] MungeContent([string]$Content) { $SplitContent = $Content -split '(\r\n|\n|\r)' if ( ($SplitContent -match '^(using|#requires|#region)') -and @@ -119,11 +117,14 @@ class SourceFile { } } - [void] MungeContent() { - $this.MungedContent = [SourceFile]::MungeContent($this.RawContent) - } + static [string] GetLineEnding( + [string] + $Content + ) { + <# + .SYNOPSIS + #> - static [string] GetLineEnding([string]$Content) { if ($content -match '\r\n') { return "`r`n" } else { @@ -131,51 +132,241 @@ class SourceFile { } } - [void] DefineLineEnding() { - $this.LineEnding = [SourceFile]::GetLineEnding($this.RawContent) - } + static [string[]] SplitContent( + [string] + $content + ) { + <# + .SYNOPSIS + #> - static [string[]] SplitContent([string]$content) { return $Content -split '(\r\n|\n|\r)' } - static [string] FindCopyrightNotice([string]$content) { + static [string] FindCopyrightNotice( + [string] + $content + ) { + <# + .SYNOPSIS + #> + return [SourceFile]::SplitContent($content) -match [SourceFile]::CopyrightNoticePattern } - static [string] FindCopyrightNoticeXml([string]$content) { + static [string] FindCopyrightNoticeXml( + [string] + $content + ) { + <# + .SYNOPSIS + #> + return [SourceFile]::SplitContent($content) -match [SourceFile]::CopyrightNoticePatternXml } - static [string] FindCopyrightNotice([string]$content, [string]$pattern) { + static [string] FindCopyrightNotice( + [string] + $content, + + [string] + $pattern + ) { + <# + .SYNOPSIS + #> + return [SourceFile]::SplitContent($content) -match $pattern } - [void] DefineCopyrightNotice() { - if ($this.FileInfo.Extension -eq '.ps1xml') { - $this.CopyrightNotices = [SourceFile]::FindCopyrightNoticeXml($this.RawContent) - } else { - $this.CopyrightNotices = [SourceFile]::FindCopyrightNotice($this.RawContent) + static [string] FindLicenseNotice( + [string] + $content + ) { + <# + .SYNOPSIS + #> + + return [SourceFile]::SplitContent($content) -match [SourceFile]::LicenseNoticePattern + } + + static [string] FindLicenseNoticeXml( + [string] + $content + ) { + <# + .SYNOPSIS + #> + + return [SourceFile]::SplitContent($content) -match [SourceFile]::LicenseNoticePatternXml + } + + static [string] FindLicenseNotice( + [string] + $content, + + [string] + $pattern + ) { + <# + .SYNOPSIS + #> + + return [SourceFile]::SplitContent($content) -match $pattern + } + + #endregion Static methods + + #region Instance properties + + <# + .SYNOPSIS + The category of the source file. + #> + [SourceCategory] + $Category + + <# + .SYNOPSIS + The scope of the source file. + #> + [SourceScope] + $Scope + + <# + .SYNOPSIS + The namespace of the source file. + #> + [string] + $NameSpace + + <# + .SYNOPSIS + The file information for the source file. + #> + [System.IO.FileInfo] + $FileInfo + + <# + .SYNOPSIS + The line ending for the source file. + #> + [string] + $LineEnding + + <# + .SYNOPSIS + The list of copyright notices for the source file. + #> + [string[]] + $CopyrightNotices + + <# + .SYNOPSIS + The list of license notices for the source file. + #> + [string[]] + $LicenseNotices + + <# + .SYNOPSIS + The content of the source file as it exists on disk before any processing. + #> + [string] + $RawContent + + <# + .SYNOPSIS + The content of the source file after processing. + #> + [string] + $MungedContent + + <# + .SYNOPSIS + #> + hidden + [string[]] + $NonLocalUsingStatements + + <# + .SYNOPSIS + #> + hidden + [bool] + $CheckedForLocalUsingStatements + + #endregion Instance properties + + #region Instance methods + + [void] SetRawContent() { + <# + .SYNOPSIS + #> + + $this.RawContent = Get-Content -Path $this.FileInfo.FullName -Raw + } + + [string[]] GetNonLocalUsingStatements() { + <# + .SYNOPSIS + #> + + if (!$this.CheckedForLocalUsingStatements) { + $this.NonLocalUsingStatements = $this.RawContent -split '(\r\n|\n|\r)' + | Where-Object -FilterScript { $_ -match '^(using \w+ .+|#requires -\w+ .+)' } + | Where-Object -FilterScript { $_ -notmatch '(\\|\/)' } + + $this.CheckedForLocalUsingStatements = $true } + return $this.NonLocalUsingStatements } - [void] DefineCopyrightNotice([string]$pattern = [SourceFile]::CopyrightNoticePattern) { - $this.CopyrightNotices = [SourceFile]::FindCopyrightNotice($this.RawContent, $pattern) + [void] MungeContent() { + <# + .SYNOPSIS + #> + + $this.MungedContent = [SourceFile]::MungeContent($this.RawContent) } - static [string] FindLicenseNotice([string]$content) { - return [SourceFile]::SplitContent($content) -match [SourceFile]::LicenseNoticePattern + [void] DefineLineEnding() { + <# + .SYNOPSIS + #> + + $this.LineEnding = [SourceFile]::GetLineEnding($this.RawContent) } - static [string] FindLicenseNoticeXml([string]$content) { - return [SourceFile]::SplitContent($content) -match [SourceFile]::LicenseNoticePatternXml + [void] DefineCopyrightNotice() { + <# + .SYNOPSIS + #> + + if ($this.FileInfo.Extension -eq '.ps1xml') { + $this.CopyrightNotices = [SourceFile]::FindCopyrightNoticeXml($this.RawContent) + } else { + $this.CopyrightNotices = [SourceFile]::FindCopyrightNotice($this.RawContent) + } } - static [string] FindLicenseNotice([string]$content, [string]$pattern) { - return [SourceFile]::SplitContent($content) -match $pattern + [void] DefineCopyrightNotice( + [string] + $pattern = [SourceFile]::CopyrightNoticePattern + ) { + <# + .SYNOPSIS + #> + + $this.CopyrightNotices = [SourceFile]::FindCopyrightNotice($this.RawContent, $pattern) } [void] DefineLicenseNotice() { + <# + .SYNOPSIS + #> + if ($this.FileInfo.Extension -eq '.ps1xml') { $this.LicenseNotices = [SourceFile]::FindLicenseNoticeXml($this.RawContent) } else { @@ -183,11 +374,22 @@ class SourceFile { } } - [void] DefineLicenseNotice([string]$pattern) { + [void] DefineLicenseNotice( + [string] + $pattern + ) { + <# + .SYNOPSIS + #> + $this.LicenseNotices = [SourceFile]::FindLicenseNotice($this.RawContent, $pattern) } [void] ResolveCategoryAndScopeFromNameSpace() { + <# + .SYNOPSIS + #> + $this.NameSpace -split '\.' | Select-Object -First 2 | ForEach-Object -Process { @@ -198,4 +400,49 @@ class SourceFile { } } } + + #endregion Instance methods + + #region Constructors + + SourceFile( + [string] + $ParentNameSpace, + + [string] + $Path + ) { + <# + .SYNOPSIS + #> + + $this.NameSpace = Resolve-NameSpace -Path $Path -ParentNameSpace $ParentNameSpace + $this.ResolveCategoryAndScopeFromNameSpace() + $this.FileInfo = $Path + $this.SetRawContent() + $this.MungeContent() + $this.DefineCopyrightNotice() + $this.DefineLicenseNotice() + $this.DefineLineEnding() + } + + SourceFile( + [string] + $Path + ) { + <# + .SYNOPSIS + #> + + $this.NameSpace = Resolve-NameSpace -Path $Path + $this.ResolveCategoryAndScopeFromNameSpace() + $this.FileInfo = $Path + $this.SetRawContent() + $this.MungeContent() + $this.DefineCopyrightNotice() + $this.DefineLicenseNotice() + $this.DefineLineEnding() + } + + #endregion Constructors } diff --git a/Projects/Modules/Documentarian.DevX/Source/Public/Classes/SourceFolder.psm1 b/Projects/Modules/Documentarian.DevX/Source/Public/Classes/SourceFolder.psm1 index 2a78f79..23f2f1e 100644 --- a/Projects/Modules/Documentarian.DevX/Source/Public/Classes/SourceFolder.psm1 +++ b/Projects/Modules/Documentarian.DevX/Source/Public/Classes/SourceFolder.psm1 @@ -23,39 +23,158 @@ foreach ($RequiredFunction in $RequiredFunctions) { #endregion RequiredFunctions class SourceFolder { - [SourceCategory]$Category - [SourceScope]$Scope - [string]$NameSpace - [System.IO.DirectoryInfo]$DirectoryInfo - [SourceFile[]]$SourceFiles + <# + .SYNOPSIS + Defines a source folder for module composition and development. + #> - SourceFolder([string]$NameSpace, [string]$Path) { - $this.NameSpace = $NameSpace - $this.ResolveCategoryAndScopeFromNameSpace() - $this.DirectoryInfo = $Path - $this.FindSourceFiles() + #region Static properties + #endregion Static properties + + #region Static methods + + static hidden [string[]] ValidLineEndings() { + <# + .SYNOPSIS + #> + + return @("`r`n", "`r", "`n") } - SourceFolder([SourceCategory]$Category, [SourceScope]$Scope, [string]$Path) { - $this.Category = $Category - $this.Scope = $Scope - $this.NameSpace = Resolve-NameSpace -Category $Category -Scope $Scope - $this.DirectoryInfo = $Path - $this.FindSourceFiles() + static hidden [bool] IsValidLineEnding( + [string] + $LineEnding + ) { + <# + .SYNOPSIS + #> + + return [SourceFolder]::ValidLineEndings() -contains $LineEnding } - SourceFolder([string]$Path) { - $this.DirectoryInfo = Resolve-Path -Path $Path -ErrorAction Stop | Select-Object -ExpandProperty Path - $this.NameSpace = Resolve-NameSpace -Path $this.DirectoryInfo.FullName - $this.ResolveCategoryAndScopeFromNameSpace() - $this.FindSourceFiles() + static hidden [string] InvalidLineEndingMessage( + [string] + $LineEnding + ) { + <# + .SYNOPSIS + #> + + $ValidLineEndings = [SourceFolder]::ValidLineEndings() + | ForEach-Object -Process { "'$([regex]::Escape($_))'" } + + $ValidLineEndings = @( + Join-String -InputObject $ValidLineEndings[0..($ValidLineEndings.Count - 2)] -Separator ', ' + $ValidLineEndings[-1] + ) -join ', or ' + + $Message = @( + "Line ending '$([regex]::Escape($LineEnding))' is not one of the expected line endings" + "($ValidLineEndings)." + ) -join ' ' + + return $Message } + static hidden [void] CheckLineEnding( + [string] + $LineEnding, + + [UncommonLineEndingAction] + $UncommonLineEndingAction + ) { + <# + .SYNOPSIS + #> + + if (![SourceFolder]::IsValidLineEnding($LineEnding)) { + $Message = [SourceFolder]::InvalidLineEndingMessage($LineEnding) + + switch ($UncommonLineEndingAction) { + SilentlyContinue {} + WarnAndContinue { + Write-Warning -Message $Message + } + ErrorAndStop { + throw [System.ArgumentException]::new($Message) + } + default { + throw 'This is not handled! If you see this message, the devs goofed.' + } + } + } + } + + static hidden [void] CheckLineEnding( + [string] + $LineEnding + ) { + <# + .SYNOPSIS + #> + + if (![SourceFolder]::IsValidLineEnding($LineEnding)) { + $Message = @( + "$([SourceFolder]::InvalidLineEndingMessage($LineEnding));" + 'Use a common line ending, ComposeSourceFiles() without parameters,' + 'or ComposeSourceFiles($LineEnding, $UncommonLineEndingAction) instead.' + ) -join ' ' + + throw [System.ArgumentException]::new($Message) + } + } + + #endregion Static methods + + #region Instance properties + + <# + .SYNOPSIS + #> + [SourceCategory] + $Category + + <# + .SYNOPSIS + #> + [SourceScope] + $Scope + + <# + .SYNOPSIS + #> + [string] + $NameSpace + + <# + .SYNOPSIS + #> + [System.IO.DirectoryInfo] + $DirectoryInfo + + <# + .SYNOPSIS + #> + [SourceFile[]] + $SourceFiles + + #endregion Instance properties + + #region Instance methods + [bool] HasOrderedFiles() { + <# + .SYNOPSIS + #> + return $this.Category -eq [SourceCategory]::Enum -or $this.Category -eq [SourceCategory]::Class } [void] ResolveCategoryAndScopeFromNameSpace() { + <# + .SYNOPSIS + #> + $this.NameSpace -split '\.' | Select-Object -First 2 | ForEach-Object -Process { @@ -68,6 +187,10 @@ class SourceFolder { } [void] FindSourceFiles() { + <# + .SYNOPSIS + #> + $BasePath = $this.DirectoryInfo.FullName $this.SourceFiles = switch ($this.HasOrderedFiles()) { $true { @@ -108,6 +231,10 @@ class SourceFolder { } [string] ComposeSourceFiles() { + <# + .SYNOPSIS + #> + if ($this.SourceFiles.Count -eq 0) { return '' } @@ -123,7 +250,14 @@ class SourceFolder { return $Output.ToString() } - [string] ComposeSourceFiles([string]$LineEnding) { + [string] ComposeSourceFiles( + [string] + $LineEnding + ) { + <# + .SYNOPSIS + #> + [SourceFolder]::CheckLineEnding($LineEnding) if ($this.SourceFiles.Count -eq 0) { @@ -141,9 +275,16 @@ class SourceFolder { } [string] ComposeSourceFiles( - [string]$LineEnding, - [UncommonLineEndingAction]$UncommonLineEndingAction + [string] + $LineEnding, + + [UncommonLineEndingAction] + $UncommonLineEndingAction ) { + <# + .SYNOPSIS + #> + [SourceFolder]::CheckLineEnding($LineEnding, $UncommonLineEndingAction) if ($this.SourceFiles.Count -eq 0) { @@ -160,62 +301,61 @@ class SourceFolder { return $Output.ToString() -replace [regex]::Escape([System.Environment]::NewLine), $LineEnding } - static hidden [string[]] ValidLineEndings() { - return @("`r`n", "`r", "`n") - } - - static hidden [bool] IsValidLineEnding([string]$LineEnding) { - return [SourceFolder]::ValidLineEndings() -contains $LineEnding - } + #endregion Instance methods - static hidden [string] InvalidLineEndingMessage([string]$LineEnding) { - $ValidLineEndings = [SourceFolder]::ValidLineEndings() - | ForEach-Object -Process { "'$([regex]::Escape($_))'" } + #region Constructors - $ValidLineEndings = @( - Join-String -InputObject $ValidLineEndings[0..($ValidLineEndings.Count - 2)] -Separator ', ' - $ValidLineEndings[-1] - ) -join ', or ' + SourceFolder( + [string] + $NameSpace, - $Message = @( - "Line ending '$([regex]::Escape($LineEnding))' is not one of the expected line endings" - "($ValidLineEndings)." - ) -join ' ' + [string] + $Path + ) { + <# + .SYNOPSIS + #> - return $Message + $this.NameSpace = $NameSpace + $this.ResolveCategoryAndScopeFromNameSpace() + $this.DirectoryInfo = $Path + $this.FindSourceFiles() } - static hidden [void] CheckLineEnding( - [string]$LineEnding, - [UncommonLineEndingAction]$UncommonLineEndingAction + SourceFolder( + [SourceCategory] + $Category, + + [SourceScope] + $Scope, + + [string] + $Path ) { - if (![SourceFolder]::IsValidLineEnding($LineEnding)) { - $Message = [SourceFolder]::InvalidLineEndingMessage($LineEnding) + <# + .SYNOPSIS + #> - switch ($UncommonLineEndingAction) { - SilentlyContinue {} - WarnAndContinue { - Write-Warning -Message $Message - } - ErrorAndStop { - throw [System.ArgumentException]::new($Message) - } - default { - throw 'This is not handled! If you see this message, the devs goofed.' - } - } - } + $this.Category = $Category + $this.Scope = $Scope + $this.NameSpace = Resolve-NameSpace -Category $Category -Scope $Scope + $this.DirectoryInfo = $Path + $this.FindSourceFiles() } - static hidden [void] CheckLineEnding([string]$LineEnding) { - if (![SourceFolder]::IsValidLineEnding($LineEnding)) { - $Message = @( - "$([SourceFolder]::InvalidLineEndingMessage($LineEnding));" - 'Use a common line ending, ComposeSourceFiles() without parameters,' - 'or ComposeSourceFiles($LineEnding, $UncommonLineEndingAction) instead.' - ) -join ' ' + SourceFolder( + [string] + $Path + ) { + <# + .SYNOPSIS + #> - throw [System.ArgumentException]::new($Message) - } + $this.DirectoryInfo = Resolve-Path -Path $Path -ErrorAction Stop | Select-Object -ExpandProperty Path + $this.NameSpace = Resolve-NameSpace -Path $this.DirectoryInfo.FullName + $this.ResolveCategoryAndScopeFromNameSpace() + $this.FindSourceFiles() } + + #endregion Constructors } diff --git a/Projects/Modules/Documentarian.DevX/Source/Public/Classes/SourceReference.psm1 b/Projects/Modules/Documentarian.DevX/Source/Public/Classes/SourceReference.psm1 index 9eceb23..f452d9e 100644 --- a/Projects/Modules/Documentarian.DevX/Source/Public/Classes/SourceReference.psm1 +++ b/Projects/Modules/Documentarian.DevX/Source/Public/Classes/SourceReference.psm1 @@ -4,106 +4,117 @@ using module ./SourceFile.psm1 class SourceReference { - [SourceFile]$SourceFile - [SourceFile[]]$LocalReferences - [string[]]$NonLocalReferences - [string[]]$ReferencePreamble + <# + .SYNOPSIS + Represents a source file reference with local and non-local references. + #> - SourceReference([SourceFile]$SourceFile) { - $this.SourceFile = $SourceFile - $this.DiscoverNonLocalReferences() - $this.ReferencePreamble = $this.ResolveReferencePreamble() - } + #region Static properties + #endregion Static properties - SourceReference([SourceFile]$SourceFile, [SourceFile[]]$LocalReferences) { - $this.SourceFile = $SourceFile - $this.DiscoverNonLocalReferences() - $this.LocalReferences = $LocalReferences | Sort-Object -Unique -Property NameSpace, FileInfo - $this.ReferencePreamble = $this.ResolveReferencePreamble() - } + #region Static methods + #endregion Static methods - [void] DiscoverNonLocalReferences() { - if (!$this.NonLocalReferences) { - $this.NonLocalReferences = $this.SourceFile.GetNonLocalUsingStatements() - } - } + #region Instance properties - hidden [void] WriteMungedContentWithReferencePreamble() { - $LineEnding = $this.SourceFile.LineEnding + <# + .SYNOPSIS + The source file that is analyzed for references. - if ([string]::IsNullOrEmpty($LineEnding)) { - $LineEnding = [System.Environment]::NewLine - } + .DESCRIPTION + The source file that is analyzed for references. The source file is analyzed for using + statements and other references to determine the preamble that should be included in the + munged content when updating source references. + #> + [SourceFile] + $SourceFile - $Sections = New-Object -TypeName System.Collections.Generic.List[String] + <# + .SYNOPSIS + The local references that are discovered in the source file. - foreach ($notice in $this.SourceFile.CopyrightNotices) { - $Sections.Add($notice) - } + .DESCRIPTION + The local references that are discovered in the source file. Local references include enums, + classes, and functions that are defined in the same module as the source file. Local references + are used to determine the preamble that should be included in the munged content when updating + source references. + #> + [SourceFile[]] + $LocalReferences - foreach ($notice in $this.SourceFile.LicenseNotices) { - $Sections.Add($notice) - } + <# + .SYNOPSIS + The non-local references that are discovered in the source file. - if ($this.ReferencePreamble.Count) { - if ($sections.Count) { - $Sections.Add('') - } - foreach ($preamble in $this.ReferencePreamble) { - $Sections.Add($preamble) - } - $Sections.Add('') - $Sections.Add($this.SourceFile.MungedContent) - $Sections.Add('') + .DESCRIPTION + The non-local references that are discovered in the source file. Non-local references include + using statements that reference modules outside of the current module, as well as any classes, + enums, and functions that aren't defined in the current module. Non-local references are used + to determine the preamble that should be included in the munged content when updating source + references. + #> + [string[]] + $NonLocalReferences - $Sections - | Join-String -Separator $LineEnding - | Set-Content -Path $this.SourceFile.FileInfo.FullName -NoNewline - } - } + <# + .SYNOPSIS + The preamble that should be included in the munged content when updating source references. - hidden [void] WriteMungedContentWithReferencePreamble([string]$LineEnding) { - $Sections = New-Object -TypeName System.Collections.Generic.List[String] + .DESCRIPTION + The preamble that should be included in the munged content when updating source references. The + preamble includes using statements for non-local references and dot-sourcing for functions that + are required by the source file. + #> + [string[]] + $ReferencePreamble - foreach ($notice in $this.SourceFile.CopyrightNotices) { - $Sections.Add($notice) - } + #endregion Instance properties - foreach ($notice in $this.SourceFile.LicenseNotices) { - $Sections.Add($notice) - } + #region Instance methods - if ($this.ReferencePreamble.Count) { - if ($sections.Count) { - $Sections.Add('') - } - foreach ($preamble in $this.ReferencePreamble) { - $Sections.Add($preamble) - } - $Sections.Add('') - $Sections.Add($this.SourceFile.MungedContent) - $Sections.Add('') + [void] DiscoverNonLocalReferences() { + <# + .SYNOPSIS + #> - $Sections - | Join-String -Separator $LineEnding - | Set-Content -Path $this.SourceFile.FileInfo.FullName -NoNewline + if (!$this.NonLocalReferences) { + $this.NonLocalReferences = $this.SourceFile.GetNonLocalUsingStatements() } } [void] ResolveAndSetReferencePreamble() { + <# + .SYNOPSIS + #> + $this.ReferencePreamble = $this.ResolveReferencePreamble() $this.WriteMungedContentWithReferencePreamble() } [void] SetReferencePreamble() { + <# + .SYNOPSIS + #> + $this.WriteMungedContentWithReferencePreamble() } - [void] SetReferencePreamble([string]$LineEnding) { + [void] SetReferencePreamble( + [string] + $LineEnding + ) { + <# + .SYNOPSIS + #> + $this.WriteMungedContentWithReferencePreamble($LineEnding) } [string[]] ResolveReferencePreamble() { + <# + .SYNOPSIS + #> + $Lines = [string[]]@() $this.DiscoverNonLocalReferences() @@ -178,4 +189,138 @@ class SourceReference { return $Lines } + + hidden [void] WriteMungedContentWithReferencePreamble() { + <# + .SYNOPSIS + #> + + $LineEnding = $this.SourceFile.LineEnding + + if ([string]::IsNullOrEmpty($LineEnding)) { + $LineEnding = [System.Environment]::NewLine + } + + $Sections = New-Object -TypeName System.Collections.Generic.List[String] + + foreach ($notice in $this.SourceFile.CopyrightNotices) { + $Sections.Add($notice) + } + + foreach ($notice in $this.SourceFile.LicenseNotices) { + $Sections.Add($notice) + } + + if ($this.ReferencePreamble.Count) { + if ($sections.Count) { + $Sections.Add('') + } + foreach ($preamble in $this.ReferencePreamble) { + $Sections.Add($preamble) + } + $Sections.Add('') + $Sections.Add($this.SourceFile.MungedContent) + $Sections.Add('') + + $Sections + | Join-String -Separator $LineEnding + | Set-Content -Path $this.SourceFile.FileInfo.FullName -NoNewline + } + } + + hidden [void] WriteMungedContentWithReferencePreamble( + [string] + $LineEnding + ) { + <# + .SYNOPSIS + #> + + $Sections = New-Object -TypeName System.Collections.Generic.List[String] + + foreach ($notice in $this.SourceFile.CopyrightNotices) { + $Sections.Add($notice) + } + + foreach ($notice in $this.SourceFile.LicenseNotices) { + $Sections.Add($notice) + } + + if ($this.ReferencePreamble.Count) { + if ($sections.Count) { + $Sections.Add('') + } + foreach ($preamble in $this.ReferencePreamble) { + $Sections.Add($preamble) + } + $Sections.Add('') + $Sections.Add($this.SourceFile.MungedContent) + $Sections.Add('') + + $Sections + | Join-String -Separator $LineEnding + | Set-Content -Path $this.SourceFile.FileInfo.FullName -NoNewline + } + } + + #endregion Instance methods + + #region Constructors + + SourceReference( + [SourceFile] + $SourceFile + ) { + <# + .SYNOPSIS + Initialize a new instance of the SourceReference class from a **SourceFile**. + + .DESCRIPTION + Initialize a new instance of the SourceReference class from a **SourceFile**. It analyzes the + source file for non-local references and resolves the preamble that should be included in the + munged content when updating source references. This ensures that, even without looking up + references from other source files, the preamble includes using statements for non-local + references. + + .PARAMETER SourceFile + The source file to analyze for references. + #> + $this.SourceFile = $SourceFile + $this.DiscoverNonLocalReferences() + $this.ReferencePreamble = $this.ResolveReferencePreamble() + } + + SourceReference( + [SourceFile] + $SourceFile, + + [SourceFile[]] + $LocalReferences + ) { + <# + .SYNOPSIS + Initialize a new instance of the SourceReference class from a **SourceFile** and local + references. + + .DESCRIPTION + Initialize a new instance of the SourceReference class from a **SourceFile** and local + references. It analyzes the source file for non-local references and resolves the preamble + that should be included in the munged content when updating source references. This ensures + that, even without looking up references from other source files, the preamble includes using + statements for non-local references. + + .PARAMETER SourceFile + The source file to analyze for references. + + .PARAMETER LocalReferences + The local references that are discovered in the source file. + #> + $this.SourceFile = $SourceFile + $this.DiscoverNonLocalReferences() + $this.LocalReferences = $LocalReferences + | Sort-Object -Unique -Property NameSpace, FileInfo + $this.ReferencePreamble = $this.ResolveReferencePreamble() + } + + #endregion Constructors } diff --git a/Projects/Modules/Documentarian.DevX/Source/Public/Classes/TaskDefinition.psm1 b/Projects/Modules/Documentarian.DevX/Source/Public/Classes/TaskDefinition.psm1 index d253676..a56953a 100644 --- a/Projects/Modules/Documentarian.DevX/Source/Public/Classes/TaskDefinition.psm1 +++ b/Projects/Modules/Documentarian.DevX/Source/Public/Classes/TaskDefinition.psm1 @@ -4,14 +4,77 @@ using module ./SourceFile.psm1 class TaskDefinition { - [string]$Name - [SourceFile[]]$SourceFiles + <# + .SYNOPSIS + Defines an Invoke-Build task by name and source files. + #> - [string] GetTaskName([string]$Prefix) { + #region Static properties + #endregion Static properties + + #region Static methods + #endregion Static methods + + #region Instance properties + + <# + .SYNOPSIS + The name of the task. + #> + [string] + $Name + + <# + .SYNOPSIS + The source files to include in the task. + + .DESCRIPTION + The source files to include in the task. The content of the source files is munged and + concatenated to form the content of the task file. + #> + [SourceFile[]] + $SourceFiles + + #endregion Instance properties + + #region Instance methods + + [string] GetTaskName( + [string] + $Prefix + ) { + <# + .SYNOPSIS + Return the name of the task with the specified prefix. + + .DESCRIPTION + Return the name of the task with the specified prefix. The returned string includes the + prefix and the task name, using a period (`.`) as a separator. + + .PARAMETER Prefix + The prefix to use when composing the task name. + #> return "$Prefix.$($this.Name)" } - [string] GetTaskPath([string]$Prefix) { + [string] GetTaskPath( + [string] + $Prefix + ) { + <# + .SYNOPSIS + Return the path to the task file with the specified prefix. + + .DESCRIPTION + Return the path to the task file with the specified prefix. The returned string includes + the prefix, the task name, and the file extension, using a forward slash (`/`) as a + separator. Tasks are always composed in the `Tasks` directory of the output module, so the + task path is always relative to the module root and found in the `Tasks` directory. + + .PARAMETER Prefix + The prefix to use when composing the task name. + #> + return @( '$PSScriptRoot' 'Tasks' @@ -20,6 +83,16 @@ class TaskDefinition { } [string] ComposeContent() { + <# + .SYNOPSIS + Compose the content of the task file. + + .DESCRIPTION + Compose the content of the task file. The content is composed by concatenating the munged + content of each source file in the task. The content of each source file is munged by + stripping out the notices and prefixing the content with the namespace of the source file. + #> + if ($this.SourceFiles.Count -eq 0) { return '' } @@ -32,4 +105,9 @@ class TaskDefinition { return $Output.ToString() } + + #endregion Instance methods + + #region Constructors + #endregion Constructors } diff --git a/Projects/Modules/Documentarian.DevX/Source/Public/Enums/SourceCategory.psm1 b/Projects/Modules/Documentarian.DevX/Source/Public/Enums/SourceCategory.psm1 index 94d963f..36ed5bc 100644 --- a/Projects/Modules/Documentarian.DevX/Source/Public/Enums/SourceCategory.psm1 +++ b/Projects/Modules/Documentarian.DevX/Source/Public/Enums/SourceCategory.psm1 @@ -2,6 +2,38 @@ # Licensed under the MIT License. enum SourceCategory { + <# + .SYNOPSIS + Defines the category of the a source file. + + .DESCRIPTION + Defines the category of the a source file. A source file's category determines how the source + file should be processed for module composition and reference lookup. + + .LABEL ArgumentCompleter + Indicates that the source file defines a PowerShell argument completer. + + .LABEL Class + Indicates that the source file defines a PowerShell class. + + .LABEL Enum + Indicates that the source file defines a PowerShell enumeration. + + .LABEL Function + Indicates that the source file defines a PowerShell function. + + .LABEL Format + Indicates that the source file defines a PowerShell object format definition, a snippet for the + module's `format.ps1xml` file. + + .LABEL Task + Indicates that the source file defines an Invoke-Build task. + + .LABEL Type + Indicates that the source file defines a PowerShell extended type definition, a snippet for the + module's `types.ps1xml` file. + #> + ArgumentCompleter Class Enum diff --git a/Projects/Modules/Documentarian.DevX/Source/Public/Enums/SourceScope.psm1 b/Projects/Modules/Documentarian.DevX/Source/Public/Enums/SourceScope.psm1 index f4701be..1e48a0e 100644 --- a/Projects/Modules/Documentarian.DevX/Source/Public/Enums/SourceScope.psm1 +++ b/Projects/Modules/Documentarian.DevX/Source/Public/Enums/SourceScope.psm1 @@ -2,6 +2,30 @@ # Licensed under the MIT License. enum SourceScope { + <# + .SYNOPSIS + Defines the scope of a source file. + + .DESCRIPTION + Defines the scope of a source file. The scope determines how the source file should be + processed for module composition. Public source files are included in the module's public + root module manifest, while private source files are placed in the `.Private.psm1` + module manifest. + + Module composition defines type accelerators for public classes and enumerations, making them + available to users when they call `Import-Module`, without needing to also call `using module`. + It also ensures that all public functions are included in the generated module manifest as + exported functions. + + .LABEL Private + Indicates that the source file is private and should not be included in the module's public + interface. + + .LABEL Public + Indicates that the source file is public and should be included in the module's public + interface. + #> + Private Public } diff --git a/Projects/Modules/Documentarian.DevX/Source/Public/Functions/General/Build-ComposedModule.ps1 b/Projects/Modules/Documentarian.DevX/Source/Public/Functions/General/Build-ComposedModule.ps1 index b5ae88a..7ed25cb 100644 --- a/Projects/Modules/Documentarian.DevX/Source/Public/Functions/General/Build-ComposedModule.ps1 +++ b/Projects/Modules/Documentarian.DevX/Source/Public/Functions/General/Build-ComposedModule.ps1 @@ -5,62 +5,89 @@ using module ../../../Private/Enums/ClassLogLevels.psm1 using module ../../Classes/ModuleComposer.psm1 function Build-ComposedModule { + <# + .SYNOPSIS + #> + [CmdletBinding(DefaultParameterSetName = 'WithConfigurationFile')] param( - [string] $ProjectRootFolderPath, + [Parameter()] + [string] + $ProjectRootFolderPath, [Parameter(ParameterSetName = 'WithConfigurationFile')] - [string] $ConfigurationFilePath, + [string] + $ConfigurationFilePath, [Parameter(ParameterSetName = 'WithOptionValues')] - [hashtable] $ManifestData, + [hashtable] + $ManifestData, [Parameter(ParameterSetName = 'WithOptionValues')] - [string] $ModuleCopyrightNotice, + [string] + $ModuleCopyrightNotice, [Parameter(ParameterSetName = 'WithOptionValues')] - [string] $ModuleLicenseNotice, + [string] + $ModuleLicenseNotice, [Parameter(ParameterSetName = 'WithOptionValues')] - [string] $ModuleName, + [string] + $ModuleName, [Parameter(ParameterSetName = 'WithOptionValues')] - [version] $ModuleVersion, + [version] + $ModuleVersion, [Parameter(ParameterSetName = 'WithOptionValues')] - [string] $OutputFolderPath, + [string] + $OutputFolderPath, [Parameter(ParameterSetName = 'WithOptionValues')] - [string] $OutputInitScriptPath, + [string] + $OutputInitScriptPath, [Parameter(ParameterSetName = 'WithOptionValues')] - [string] $OutputManifestPath, + [string] + $OutputManifestPath, [Parameter(ParameterSetName = 'WithOptionValues')] - [string] $OutputPrivateModulePath, + [string] + $OutputPrivateModulePath, [Parameter(ParameterSetName = 'WithOptionValues')] - [string] $OutputRootModulePath, + [string] + $OutputRootModulePath, [Parameter(ParameterSetName = 'WithOptionValues')] - [string] $SourceFolderPath, + [string] + $SourceFolderPath, [Parameter(ParameterSetName = 'WithOptionValues')] - [string] $SourceInitScriptPath, + [string] + $SourceInitScriptPath, [Parameter(ParameterSetName = 'WithOptionValues')] - [string] $SourceManifestPath, + [string] + $SourceManifestPath, [Parameter(ParameterSetName = 'WithOptionValues')] - [string] $SourcePrivateFolderPath, + [string] + $SourcePrivateFolderPath, [Parameter(ParameterSetName = 'WithOptionValues')] - [string] $SourcePublicFolderPath, + [string] + $SourcePublicFolderPath, [Parameter(ParameterSetName = 'WithOptionValues')] - [string] $UsingModuleList + [string] + $UsingModuleList ) + begin { + + } + process { if ([string]::IsNullOrEmpty($ProjectRootFolderPath)) { [string]$ProjectRootFolderPath = Get-Location @@ -112,4 +139,8 @@ function Build-ComposedModule { $Composer.ExportComposedModule() } + + end { + + } } diff --git a/Projects/Modules/Documentarian.DevX/Source/Public/Functions/General/Copy-Template.ps1 b/Projects/Modules/Documentarian.DevX/Source/Public/Functions/General/Copy-Template.ps1 index d0b6fc7..c89da90 100644 --- a/Projects/Modules/Documentarian.DevX/Source/Public/Functions/General/Copy-Template.ps1 +++ b/Projects/Modules/Documentarian.DevX/Source/Public/Functions/General/Copy-Template.ps1 @@ -17,12 +17,27 @@ foreach ($RequiredFunction in $RequiredFunctions) { #endregion RequiredFunctions function Copy-Template { + <# + .SYNOPSIS + #> + [CmdletBinding()] param( - [string] $TemplatePath, - [string] $DestinationPath, - [hashtable] $TemplateData, - [switch] $PassThru + [Parameter()] + [string] + $TemplatePath, + + [Parameter()] + [string] + $DestinationPath, + + [Parameter()] + [hashtable] + $TemplateData, + + [Parameter()] + [switch] + $PassThru ) begin { @@ -63,4 +78,8 @@ function Copy-Template { Get-Item -Path $CopiedFiles } } + + end { + + } } diff --git a/Projects/Modules/Documentarian.DevX/Source/Public/Functions/General/Get-ModuleRelativePath.ps1 b/Projects/Modules/Documentarian.DevX/Source/Public/Functions/General/Get-ModuleRelativePath.ps1 index 77cc56c..fbe0d6b 100644 --- a/Projects/Modules/Documentarian.DevX/Source/Public/Functions/General/Get-ModuleRelativePath.ps1 +++ b/Projects/Modules/Documentarian.DevX/Source/Public/Functions/General/Get-ModuleRelativePath.ps1 @@ -17,11 +17,23 @@ foreach ($RequiredFunction in $RequiredFunctions) { #endregion RequiredFunctions function Get-ModuleRelativePath { + <# + .SYNOPSIS + #> + [CmdletBinding()] param( - [string]$Path, - [string]$SourcePath = $MyInvocation.MyCommand.Module.ModuleBase, - [switch]$Resolve + [Parameter()] + [string] + $Path, + + [Parameter()] + [string] + $SourcePath = $MyInvocation.MyCommand.Module.ModuleBase, + + [Parameter()] + [switch] + $Resolve ) process { @@ -50,4 +62,8 @@ function Get-ModuleRelativePath { Pop-Location } } + + end { + + } } diff --git a/Projects/Modules/Documentarian.DevX/Source/Public/Functions/General/Get-SourceFolder.ps1 b/Projects/Modules/Documentarian.DevX/Source/Public/Functions/General/Get-SourceFolder.ps1 index 543517e..fb485d9 100644 --- a/Projects/Modules/Documentarian.DevX/Source/Public/Functions/General/Get-SourceFolder.ps1 +++ b/Projects/Modules/Documentarian.DevX/Source/Public/Functions/General/Get-SourceFolder.ps1 @@ -19,40 +19,62 @@ foreach ($RequiredFunction in $RequiredFunctions) { #endregion RequiredFunctions function Get-SourceFolder { + <# + .SYNOPSIS + #> + [CmdletBinding(DefaultParameterSetName = 'ByPreset')] [OutputType([SourceFolder])] param( [Parameter(Mandatory, ParameterSetName = 'ByOption')] [Parameter(ParameterSetName = 'WithSpecificFolders')] - [ValidateSet('ArgumentCompleters', 'Classes', 'Enums', 'Formats', 'Functions', 'Tasks', 'Types')] - [string[]]$Category, + [ValidateSet( + 'ArgumentCompleters', + 'Classes', + 'Enums', + 'Formats', + 'Functions', + 'Tasks', + 'Types' + )] + [string[]] + $Category, [Parameter(Mandatory, ParameterSetName = 'ByOption')] [Parameter(ParameterSetName = 'WithSpecificFolders')] [ValidateSet('Public', 'Private')] - [string[]]$Scope, + [string[]] + $Scope, [Parameter(ParameterSetName = 'ByPreset')] [Parameter(ParameterSetName = 'WithSpecificFolders')] [ValidateSet('Ordered', 'Functions', 'PS1Xmls', 'PSD1s', 'Tasks', 'All')] - [string]$Preset = 'All', + [string] + $Preset = 'All', [Parameter(ParameterSetName = 'ByPreset')] [Parameter(Mandatory, ParameterSetName = 'ByOption')] [Parameter(ParameterSetName = 'WithSpecificFolders')] - [string]$PublicFolder, + [string] + $PublicFolder, [Parameter(ParameterSetName = 'ByPreset')] [Parameter(Mandatory, ParameterSetName = 'ByOption')] [Parameter(ParameterSetName = 'WithSpecificFolders')] - [string]$PrivateFolder, + [string] + $PrivateFolder, [Parameter(ParameterSetName = 'ByPreset')] [Parameter(Mandatory, ParameterSetName = 'ByOption')] [Parameter(ParameterSetName = 'WithSourceFolder')] - [string]$SourceFolder + [string] + $SourceFolder ) + begin { + + } + process { $Category ??= @('ArgumentCompleters', 'Classes', 'Enums', 'Formats', 'Functions', 'Tasks', 'Types') $CategoryPattern = "\b$($Category -join '|')\b" @@ -146,4 +168,8 @@ function Get-SourceFolder { } } } + + end { + + } } diff --git a/Projects/Modules/Documentarian.DevX/Source/Public/Functions/General/New-ArgumentCompleterDefinition.ps1 b/Projects/Modules/Documentarian.DevX/Source/Public/Functions/General/New-ArgumentCompleterDefinition.ps1 index b54e0cd..0516b2f 100644 --- a/Projects/Modules/Documentarian.DevX/Source/Public/Functions/General/New-ArgumentCompleterDefinition.ps1 +++ b/Projects/Modules/Documentarian.DevX/Source/Public/Functions/General/New-ArgumentCompleterDefinition.ps1 @@ -2,111 +2,142 @@ # Licensed under the MIT License. function New-ArgumentCompleterDefinition { - [CmdletBinding()] - param( - [string[]]$Path = './ArgumentCompleter.psd1', - [string]$CopyrightNotice, - [string]$LicenseNotice, - [string[]]$CommandName, - [string]$ParameterName, - [scriptblock]$ScriptBlock, - [switch]$Native, - [switch]$Force + <# + .SYNOPSIS + #> + + [CmdletBinding()] + param( + [Parameter()] + [string[]] + $Path = './ArgumentCompleter.psd1', + + [Parameter()] + [string] + $CopyrightNotice, + + [Parameter()] + [string] + $LicenseNotice, + + [Parameter()] + [string[]] + $CommandName, + + [Parameter()] + [string] + $ParameterName, + + [Parameter()] + [scriptblock] + $ScriptBlock, + + [Parameter()] + [switch] + $Native, + + [Parameter()] + [switch] + $Force + ) + + begin { + $Content = @() + # Handle adding notices to the top of the file, if needed. + $HasCopyrightNotice = -not [string]::IsNullOrEmpty($CopyrightNotice) + $HasLicenseNotice = -not [string]::IsNullOrEmpty($LicenseNotice) + if ($HasCopyrightNotice) { $Content += "# $CopyrightNotice" } + if ($HasLicenseNotice) { $Content += "# $LicenseNotice" } + if ($HasCopyrightNotice -or $HasLicenseNotice) { $Content += '' } + + # Add contextual help for future editors of the file. + $Content += @( + '# The key-value pairs are parameters for the Register-ArgumentCompleter cmdlet.' + '# For more information, run `Get-Help Register-ArgumentCompleter` or see:' + '# https://learn.microsoft.com/powershell/module/microsoft.powershell.core/register-argumentcompleter' ) - begin { - $Content = @() - # Handle adding notices to the top of the file, if needed. - $HasCopyrightNotice = -not [string]::IsNullOrEmpty($CopyrightNotice) - $HasLicenseNotice = -not [string]::IsNullOrEmpty($LicenseNotice) - if ($HasCopyrightNotice) { $Content += "# $CopyrightNotice" } - if ($HasLicenseNotice) { $Content += "# $LicenseNotice" } - if ($HasCopyrightNotice -or $HasLicenseNotice) { $Content += '' } - - # Add contextual help for future editors of the file. - $Content += @( - '# The key-value pairs are parameters for the Register-ArgumentCompleter cmdlet.' - '# For more information, run `Get-Help Register-ArgumentCompleter` or see:' - '# https://learn.microsoft.com/powershell/module/microsoft.powershell.core/register-argumentcompleter' - ) + $PowerShellCommandParamBlock = @( + ' param(' + ' $commandName,' + ' $parameterName,' + ' $wordToComplete,' + ' $commandAst,' + ' $fakeBoundParameters' + ' )' + ) -join "`n" + $NativeCommandParamBlock = @( + ' param(' + ' $wordToComplete,' + ' $commandAst,' + ' $cursorPosition' + ' )' + ) -join "`n" + + $Content += @( + '@{' + " CommandName = '$($CommandName -join "', '")'" + " ParameterName = '$ParameterName'" + ' ScriptBlock = {' + ($Native ? $NativeCommandParamBlock : $PowerShellCommandParamBlock) + '' + ' # Script block body here.' + '' + ' }' + '}' + ) - $PowerShellCommandParamBlock = @( - ' param(' - ' $commandName,' - ' $parameterName,' - ' $wordToComplete,' - ' $commandAst,' - ' $fakeBoundParameters' - ' )' - ) -join "`n" - $NativeCommandParamBlock = @( - ' param(' - ' $wordToComplete,' - ' $commandAst,' - ' $cursorPosition' - ' )' - ) -join "`n" - - $Content += @( - '@{' - " CommandName = '$($CommandName -join "', '")'" - " ParameterName = '$ParameterName'" - ' ScriptBlock = {' + $Content = $Content -join "`n" + } + + process { + if ($null -ne $ScriptBlock) { + # Parse the script block to get the parameter names, make sure they're correct. + $ParameterNames = $ScriptBlock.Ast.ParamBlock.Parameters.Name + $ParameterCount = $ParameterNames.Count + $ExpectedParameterCount = $Native ? 3 : 5 + if ($ParameterCount -ne $ExpectedParameterCount) { + $ErrorMessage = @( + "The scriptblock must have $ExpectedParameterCount parameters," + "but only had $ParameterCount ($($ParameterNames -join ', '))." + 'Use the following parameter block for the scriptblock.' + "`n" ($Native ? $NativeCommandParamBlock : $PowerShellCommandParamBlock) - '' - ' # Script block body here.' - '' - ' }' - '}' + "`n" + 'For more information, see the Register-ArgumentCompleter cmdlet.' + ) -join ' ' + } + $PSCmdlet.ThrowTerminatingError( + [System.Management.Automation.ErrorRecord]::new( + [System.ArgumentException]::new($ErrorMessage), + 'InvalidArgumentCompleterScriptBlock', + 'InvalidArgumentCompleter', + $null ) - - $Content = $Content -join "`n" + ) } - process { - if ($null -ne $ScriptBlock) { - # Parse the script block to get the parameter names, make sure they're correct. - $ParameterNames = $ScriptBlock.Ast.ParamBlock.Parameters.Name - $ParameterCount = $ParameterNames.Count - $ExpectedParameterCount = $Native ? 3 : 5 - if ($ParameterCount -ne $ExpectedParameterCount) { - $ErrorMessage = @( - "The scriptblock must have $ExpectedParameterCount parameters," - "but only had $ParameterCount ($($ParameterNames -join ', '))." - 'Use the following parameter block for the scriptblock.' - "`n" - ($Native ? $NativeCommandParamBlock : $PowerShellCommandParamBlock) - "`n" - 'For more information, see the Register-ArgumentCompleter cmdlet.' - ) -join ' ' - } - $PSCmdlet.ThrowTerminatingError( - [System.Management.Automation.ErrorRecord]::new( - [System.ArgumentException]::new($ErrorMessage), - 'InvalidArgumentCompleterScriptBlock', - 'InvalidArgumentCompleter', - $null - ) - ) - } - - if ((Test-Path -Path $Path) -and -not $Force) { - $Message = @( - "The file '$((Get-Item $Path).FullName)' already exists." - 'Use the -Force switch to overwrite the file.' - ) -join ' ' - $PSCmdlet.ThrowTerminatingError( - [System.Management.Automation.ErrorRecord]::new( - [System.IO.IOException]::new($Message), - 'FileAlreadyExists', - 'ResourceExists', - $null - ) - ) - } - - $File = New-Item -Path $Path -ItemType File -Force - $Content | Out-File -FilePath $File -Encoding utf8NoBOM -Force - $File + if ((Test-Path -Path $Path) -and -not $Force) { + $Message = @( + "The file '$((Get-Item $Path).FullName)' already exists." + 'Use the -Force switch to overwrite the file.' + ) -join ' ' + $PSCmdlet.ThrowTerminatingError( + [System.Management.Automation.ErrorRecord]::new( + [System.IO.IOException]::new($Message), + 'FileAlreadyExists', + 'ResourceExists', + $null + ) + ) } + + $File = New-Item -Path $Path -ItemType File -Force + $Content | Out-File -FilePath $File -Encoding utf8NoBOM -Force + $File + } + + end { + + } } diff --git a/Projects/Modules/Documentarian.DevX/Source/Public/Functions/General/New-ComposableModule.ps1 b/Projects/Modules/Documentarian.DevX/Source/Public/Functions/General/New-ComposableModule.ps1 index 3b09782..4b856fb 100644 --- a/Projects/Modules/Documentarian.DevX/Source/Public/Functions/General/New-ComposableModule.ps1 +++ b/Projects/Modules/Documentarian.DevX/Source/Public/Functions/General/New-ComposableModule.ps1 @@ -19,10 +19,19 @@ foreach ($RequiredFunction in $RequiredFunctions) { #endregion RequiredFunctions function New-ComposableModule { + <# + .SYNOPSIS + #> + [CmdletBinding()] param( - [string]$Name, - [string]$Path + [Parameter()] + [string] + $Name, + + [Parameter()] + [string] + $Path ) begin { @@ -71,7 +80,7 @@ function New-ComposableModule { New-ConfigurationJson -FolderPath $ModuleFolder -Name $Name } - End { + end { Pop-Location } } diff --git a/Projects/Modules/Documentarian.DevX/Source/Public/Functions/General/New-ConfigurationJson.ps1 b/Projects/Modules/Documentarian.DevX/Source/Public/Functions/General/New-ConfigurationJson.ps1 index 681821a..03374fb 100644 --- a/Projects/Modules/Documentarian.DevX/Source/Public/Functions/General/New-ConfigurationJson.ps1 +++ b/Projects/Modules/Documentarian.DevX/Source/Public/Functions/General/New-ConfigurationJson.ps1 @@ -2,15 +2,39 @@ # Licensed under the MIT License. function New-ConfigurationJson { + <# + .SYNOPSIS + #> + [CmdletBinding()] param( - [string] $FolderPath = (Get-Location), - [string] $Name, - [guid] $Guid = (New-Guid), - [string] $CopyrightNotice, - [string] $LicenseNotice, - [string] $ProjectUri, - [string] $LicenseUri + [Parameter()] + [string] + $FolderPath = (Get-Location), + + [Parameter()] + [string] + $Name, + + [Parameter()] + [guid] + $Guid = (New-Guid), + + [Parameter()] + [string] + $CopyrightNotice, + + [Parameter()] + [string] + $LicenseNotice, + + [Parameter()] + [string] + $ProjectUri, + + [Parameter()] + [string] + $LicenseUri ) begin { @@ -76,4 +100,8 @@ function New-ConfigurationJson { $File } + + end { + + } } diff --git a/Projects/Modules/Documentarian.DevX/Source/Public/Functions/General/New-LoadOrderJson.ps1 b/Projects/Modules/Documentarian.DevX/Source/Public/Functions/General/New-LoadOrderJson.ps1 index 6d6d518..4b5b4bd 100644 --- a/Projects/Modules/Documentarian.DevX/Source/Public/Functions/General/New-LoadOrderJson.ps1 +++ b/Projects/Modules/Documentarian.DevX/Source/Public/Functions/General/New-LoadOrderJson.ps1 @@ -2,11 +2,23 @@ # Licensed under the MIT License. function New-LoadOrderJson { + <# + .SYNOPSIS + #> + [CmdletBinding()] param( - [string[]]$FolderPath, - [string]$CopyrightNotice, - [string]$LicenseNotice + [Parameter()] + [string[]] + $FolderPath, + + [Parameter()] + [string] + $CopyrightNotice, + + [Parameter()] + [string] + $LicenseNotice ) begin { @@ -44,4 +56,8 @@ function New-LoadOrderJson { $File } } + + end { + + } } diff --git a/Projects/Modules/Documentarian.DevX/Source/Public/Functions/General/Resolve-SourceDependency.ps1 b/Projects/Modules/Documentarian.DevX/Source/Public/Functions/General/Resolve-SourceDependency.ps1 index bcff599..e824550 100644 --- a/Projects/Modules/Documentarian.DevX/Source/Public/Functions/General/Resolve-SourceDependency.ps1 +++ b/Projects/Modules/Documentarian.DevX/Source/Public/Functions/General/Resolve-SourceDependency.ps1 @@ -24,15 +24,26 @@ foreach ($RequiredFunction in $RequiredFunctions) { #endregion RequiredFunctions function Resolve-SourceDependency { + <# + .SYNOPSIS + #> + [CmdletBinding(DefaultParameterSetName = 'ByPath')] [OutputType([SourceReference])] param( - [SourceFile[]]$SourceFile, + [Parameter()] + [SourceFile[]] + $SourceFile, + [Parameter()] [parameter(Mandatory, ParameterSetName = 'ByName')] - [string[]]$Name, + [string[]] + $Name, + + [Parameter()] [parameter(Mandatory, ParameterSetName = 'ByPath')] - [string[]]$Path + [string[]] + $Path ) begin { @@ -48,6 +59,7 @@ function Resolve-SourceDependency { 'CommandAst' ) } + process { if ($Path) { $Path = Resolve-Path $Path -ErrorAction Stop @@ -138,4 +150,8 @@ function Resolve-SourceDependency { New-SourceReference -SourceFile $Source -Reference $References } } + + end { + + } } diff --git a/Projects/Modules/Documentarian.DevX/Source/Public/Functions/General/Resolve-SourceFolderPath.ps1 b/Projects/Modules/Documentarian.DevX/Source/Public/Functions/General/Resolve-SourceFolderPath.ps1 index 7398b79..1f2612f 100644 --- a/Projects/Modules/Documentarian.DevX/Source/Public/Functions/General/Resolve-SourceFolderPath.ps1 +++ b/Projects/Modules/Documentarian.DevX/Source/Public/Functions/General/Resolve-SourceFolderPath.ps1 @@ -4,13 +4,26 @@ using module ../../Classes/SourceFile.psm1 function Resolve-SourceFolderPath { + <# + .SYNOPSIS + #> + [CmdletBinding()] [OutputType([String])] param( - [SourceFile[]]$SourceFile, - [string[]]$Path + [Parameter()] + [SourceFile[]] + $SourceFile, + + [Parameter()] + [string[]] + $Path ) + begin { + + } + process { if ($SourceFile) { $Path = $SourceFile.FileInfo.FullName @@ -26,4 +39,8 @@ function Resolve-SourceFolderPath { $SourceFolderPath } } + + end { + + } } diff --git a/Projects/Modules/Documentarian.DevX/Source/Public/Functions/General/Update-SourceDependency.ps1 b/Projects/Modules/Documentarian.DevX/Source/Public/Functions/General/Update-SourceDependency.ps1 index 55bd854..7d2e73f 100644 --- a/Projects/Modules/Documentarian.DevX/Source/Public/Functions/General/Update-SourceDependency.ps1 +++ b/Projects/Modules/Documentarian.DevX/Source/Public/Functions/General/Update-SourceDependency.ps1 @@ -20,17 +20,30 @@ foreach ($RequiredFunction in $RequiredFunctions) { #endregion RequiredFunctions function Update-SourceDependency { + <# + .SYNOPSIS + #> + [CmdletBinding(DefaultParameterSetName = 'ByPath')] [OutputType([SourceReference])] param( - [SourceFile[]]$SourceFile, + [Parameter()] + [SourceFile[]] + $SourceFile, [parameter(Mandatory, ParameterSetName = 'ByName')] - [string[]]$Name, + [string[]] + $Name, + [parameter(Mandatory, ParameterSetName = 'ByPath')] - [string[]]$Path + [string[]] + $Path ) + begin { + + } + process { $ResolvedDependencies = Resolve-SourceDependency @PSBoundParameters $ResolvedDependencies | ForEach-Object -Process { @@ -43,4 +56,8 @@ function Update-SourceDependency { $_.SetReferencePreamble() } } + + end { + + } } diff --git a/Projects/Modules/Documentarian.DevX/Source/Public/Tasks/ComposeModule.ps1 b/Projects/Modules/Documentarian.DevX/Source/Public/Tasks/ComposeModule.ps1 index aa24a5c..7aa83f5 100644 --- a/Projects/Modules/Documentarian.DevX/Source/Public/Tasks/ComposeModule.ps1 +++ b/Projects/Modules/Documentarian.DevX/Source/Public/Tasks/ComposeModule.ps1 @@ -3,5 +3,9 @@ # Synopsis: Compose the module from source files task ComposeModule InitializeDevXConfiguration, { + <# + .SYNOPSIS + #> + Build-ComposedModule -ProjectRootFolderPath $BuildRoot } diff --git a/Projects/Modules/Documentarian.DevX/Source/Public/Tasks/Configuration.ps1 b/Projects/Modules/Documentarian.DevX/Source/Public/Tasks/Configuration.ps1 index 97d0618..c8329f5 100644 --- a/Projects/Modules/Documentarian.DevX/Source/Public/Tasks/Configuration.ps1 +++ b/Projects/Modules/Documentarian.DevX/Source/Public/Tasks/Configuration.ps1 @@ -3,6 +3,10 @@ # Synopsis: Load the DevX configuration file to use in other tasks task InitializeDevXConfiguration { + <# + .SYNOPSIS + #> + $DevXConfigurationFile = Join-Path -Path $BuildRoot -ChildPath '.DevX.jsonc' if (Test-Path $DevXConfigurationFile) { $Script:DevX = Get-Content -Path $DevXConfigurationFile -Raw diff --git a/Projects/Modules/Documentarian.DevX/Source/Public/Tasks/Testing.ps1 b/Projects/Modules/Documentarian.DevX/Source/Public/Tasks/Testing.ps1 index f7be637..bafb129 100644 --- a/Projects/Modules/Documentarian.DevX/Source/Public/Tasks/Testing.ps1 +++ b/Projects/Modules/Documentarian.DevX/Source/Public/Tasks/Testing.ps1 @@ -3,12 +3,20 @@ # Synopsis: Define shared Pester configuration for test tasks task ConfigurePester -Data $PSBoundParameters InitializeDevXConfiguration, { + <# + .SYNOPSIS + #> + $Script:PesterConfiguration = New-PesterConfiguration $Script:PesterConfiguration.Output.Verbosity = 'Detailed' } # Synopsis: Run unit tests for internal functionality task Unit -If (!$SkipUnitTests) ConfigurePester, { + <# + .SYNOPSIS + #> + $UnitTestPath = Join-Path -Path $BuildRoot -ChildPath Source if (Get-ChildItem -Path $UnitTestPath -Recurse -Include '*.Tests.ps1') { $Configuration = $Script:PesterConfiguration @@ -25,6 +33,10 @@ task Unit -If (!$SkipUnitTests) ConfigurePester, { # Synopsis: Run acceptance tests on composed module task Acceptance -If (!$SkipAcceptanceTests) ConfigurePester, { + <# + .SYNOPSIS + #> + $AcceptanceTestPath = Join-Path -Path $BuildRoot -ChildPath Spec if ( (Test-Path -Path $AcceptanceTestPath) -and