Skip to content

Commit

Permalink
New-DscResourceWikiPage: Add support for inherited properties from …
Browse files Browse the repository at this point in the history
…base class (#78)

- Added private functions:
  - `Get-ClassAst` - Returns the AST for a single or all classes.
  - `Get-ClassResourceAst` - Returns the AST for a single or all DSC class
    resources.
  - `Get-ClassResourceProperty` - Returns DSC class resource properties
    from the provided class or classes.
  - `Format-Text` - Format a string according to predefined options.
- `New-DscResourceWikiPage`
  - If a class-based resource have a parent class that contains DSC resource
    properties they will now also be returned as part of the DSC resource
    parameters (issue #62).
  • Loading branch information
johlju authored Jun 8, 2021
1 parent e877879 commit 210424f
Show file tree
Hide file tree
Showing 11 changed files with 1,332 additions and 81 deletions.
17 changes: 17 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,23 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## [Unreleased]

### Added

- Added private functions:
- `Get-ClassAst` - Returns the AST for a single or all classes.
- `Get-ClassResourceAst` - Returns the AST for a single or all DSC class
resources.
- `Get-ClassResourceProperty` - Returns DSC class resource properties
from the provided class or classes.
- `Format-Text` - Format a string according to predefined options.

### Changed

- `New-DscResourceWikiPage`
- If a class-based resource has a parent class that contains DSC resource
properties they will now also be returned as part of the DSC resource
parameters ([issue #62](https://github.com/dsccommunity/DscResource.DocGenerator/issues/62)).

### Fixed

- `Publish_GitHub_Wiki_Content`
Expand Down
83 changes: 83 additions & 0 deletions source/Private/Format-Text.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
<#
.SYNOPSIS
Formats a string using predefined format options.
.PARAMETER Text
The string to format.
.PARAMETER Format
One or more predefined format options. The formatting is done in the
provided order.
.EXAMPLE
Format-Text -Text 'My text description' -Format @('Replace_Multiple_Whitespace_With_One')
Returns a string correctly formatted with one whitespace between each word.
#>
function Format-Text
{
[CmdletBinding()]
[OutputType([System.String])]
param
(
[Parameter(Mandatory = $true)]
[System.String]
$Text,

[Parameter(Mandatory = $true)]
[ValidateSet(
'Replace_Multiple_Whitespace_With_One',
'Remove_Blank_Rows_At_End_Of_String',
'Remove_Indentation_From_Blank_Rows',
'Replace_NewLine_With_One_Whitespace',
'Replace_Vertical_Bar_With_One_Whitespace',
'Remove_Whitespace_From_End_Of_String'
)]
[System.String[]]
$Format
)

$returnString = $Text

switch ($Format)
{
# Replace multiple whitespace with one single white space
'Replace_Multiple_Whitespace_With_One'
{
$returnString = $returnString -replace ' +', ' '
}

# Removes all blank rows at the end
'Remove_Blank_Rows_At_End_Of_String'
{
$returnString = $returnString -replace '[\r?\n]+$'
}

# Remove all indentations from blank rows
'Remove_Indentation_From_Blank_Rows'
{
$returnString = $returnString -replace '[ ]+\r\n', "`r`n"
$returnString = $returnString -replace '[ ]+\n', "`n"
}

# Replace LF or CRLF with one white space
'Replace_NewLine_With_One_Whitespace'
{
$returnString = $returnString -replace '\r?\n', ' '
}

# Replace vertical bar with one white space
'Replace_Vertical_Bar_With_One_Whitespace'
{
$returnString = $returnString -replace '\|', ' '
}

# Remove white space from end of string
'Remove_Whitespace_From_End_Of_String'
{
$returnString = $returnString -replace ' +$'
}
}

return $returnString
}
65 changes: 65 additions & 0 deletions source/Private/Get-ClassAst.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
<#
.SYNOPSIS
Returns the AST for a single or all classes.
.PARAMETER ScriptFile
The path to the source file that contain the class.
.PARAMETER ClassName
The specific class to return the AST for. Optional.
.EXAMPLE
Get-ClassAst -ClassName 'myClass' -ScriptFile '.\output\MyModule\1.0.0\MyModule.psm1'
Returns AST for all the classes in the script file.
.EXAMPLE
Get-ClassAst -ClassName 'myClass' -ScriptFile '.\output\MyModule\1.0.0\MyModule.psm1'
Returns AST for the class 'myClass' from the script file.
#>
function Get-ClassAst
{
[CmdletBinding()]
param
(
[Parameter(Mandatory = $true)]
[System.String]
$ScriptFile,

[Parameter()]
[System.String]
$ClassName
)

$tokens, $parseErrors = $null

$ast = [System.Management.Automation.Language.Parser]::ParseFile($ScriptFile, [ref] $tokens, [ref] $parseErrors)

if ($parseErrors)
{
throw $parseErrors
}

if ($PSBoundParameters.ContainsKey('ClassName') -and $ClassName)
{
# Get only the specific class resource.
$astFilter = {
$args[0] -is [System.Management.Automation.Language.TypeDefinitionAst] `
-and $args[0].IsClass `
-and $args[0].Name -eq $ClassName
}
}
else
{
# Get all class resources.
$astFilter = {
$args[0] -is [System.Management.Automation.Language.TypeDefinitionAst] `
-and $args[0].IsClass
}
}

$classAst = $ast.FindAll($astFilter, $true)

return $classAst
}
62 changes: 62 additions & 0 deletions source/Private/Get-ClassResourceAst.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
<#
.SYNOPSIS
Returns the AST for a single or all DSC class resources.
.PARAMETER ScriptFile
The path to the source file that contain the DSC class resource.
.PARAMETER ClassName
The specific DSC class resource to return the AST for. Optional.
.EXAMPLE
Get-ClassResourceAst -ClassName 'myClass' -ScriptFile '.\output\MyModule\1.0.0\MyModule.psm1'
Returns AST for all DSC class resources in the script file.
.EXAMPLE
Get-ClassResourceAst -ClassName 'myClass' -ScriptFile '.\output\MyModule\1.0.0\MyModule.psm1'
Returns AST for the DSC class resource 'myClass' from the script file.
#>
function Get-ClassResourceAst
{
[CmdletBinding()]
param
(
[Parameter(Mandatory = $true)]
[System.String]
$ScriptFile,

[Parameter()]
[System.String]
$ClassName
)

$dscClassResourceAst = $null

$getClassAstParameters = @{
ScriptFile = $ScriptFile
}

if ($PSBoundParameters.ContainsKey('ClassName'))
{
$getClassAstParameters['ClassName'] = $ClassName
}

$ast = Get-ClassAst @getClassAstParameters

# Only try to filter if there was at least one class returned.
if ($ast)
{
# Get only DSC class resource.
$astFilter = {
$args[0] -is [System.Management.Automation.Language.TypeDefinitionAst] `
-and $args[0].IsClass `
-and $args[0].Attributes.Extent.Text -imatch '\[DscResource\(.*\)\]'
}

$dscClassResourceAst = $ast.FindAll($astFilter, $true)
}

return $dscClassResourceAst
}
127 changes: 127 additions & 0 deletions source/Private/Get-ClassResourceProperty.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
<#
.SYNOPSIS
Returns DSC class resource properties from the provided class or classes.
.PARAMETER SourcePath
The path to the source folder (in which the child folder 'Classes' exist).
.PARAMETER BuiltModuleScriptFilePath
The path to the built module script file that contains the class.
.PARAMETER ClassName
One or more class names to return properties for.
.EXAMPLE
Get-ClassResourceProperty -ClassName @('myParentClass', 'myClass') -BuiltModuleScriptFilePath '.\output\MyModule\1.0.0\MyModule.psm1' -SourcePath '.\source'
Returns all DSC class resource properties.
#>
function Get-ClassResourceProperty
{
[CmdletBinding()]
[OutputType([System.Collections.Hashtable[]])]
param
(
[Parameter(Mandatory = $true)]
[System.String]
$SourcePath,

[Parameter(Mandatory = $true)]
[System.String]
$BuiltModuleScriptFilePath,

[Parameter(Mandatory = $true)]
[System.String[]]
$ClassName
)

$resourceProperty = [System.Collections.Hashtable[]] @()

foreach ($currentClassName in $ClassName)
{
$dscResourceAst = Get-ClassAst -ClassName $currentClassName -ScriptFile $BuiltModuleScriptFilePath

$sourceFilePath = Join-Path -Path $SourcePath -ChildPath ('Classes/*{0}.ps1' -f $currentClassName)

$dscResourceCommentBasedHelp = Get-ClassResourceCommentBasedHelp -Path $sourceFilePath

$astFilter = {
$args[0] -is [System.Management.Automation.Language.PropertyMemberAst] `
-and $args[0].Attributes.TypeName.Name -eq 'DscProperty'
}

$propertyMemberAsts = $dscResourceAst.FindAll($astFilter, $true)

<#
Looping through each resource property to build the resulting
hashtable. Hashtable will be in the format:
@{
Name = <System.String>
State = 'Key' | 'Required' |'Write' | 'Read'
Description = <System.String>
EmbeddedInstance = 'MSFT_Credential' | $null
DataType = 'System.String' | 'System.String[] | etc.
IsArray = $true | $false
ValueMap = @(<System.String> | ...)
}
#>
foreach ($propertyMemberAst in $propertyMemberAsts)
{
Write-Verbose -Message ($script:localizedData.FoundClassResourcePropertyMessage -f $propertyMemberAst.Name, $dscResourceAst.Name)

$propertyAttribute = @{
Name = $propertyMemberAst.Name
DataType = $propertyMemberAst.PropertyType.TypeName.FullName

# Always set to null, correct type name is set in DataType.
EmbeddedInstance = $null

# Always set to $false - correct type name is set in DataType.
IsArray = $false
}

$propertyAttribute['State'] = Get-ClassResourcePropertyState -Ast $propertyMemberAst

$astFilter = {
$args[0] -is [System.Management.Automation.Language.AttributeAst] `
-and $args[0].TypeName.Name -eq 'ValidateSet'
}

$propertyAttributeAsts = $propertyMemberAst.FindAll($astFilter, $true)

if ($propertyAttributeAsts)
{
$propertyAttribute['ValueMap'] = $propertyAttributeAsts.PositionalArguments.Value
}

if ($dscResourceCommentBasedHelp -and $dscResourceCommentBasedHelp.Parameters.Count -gt 0)
{
# The key name must be upper-case for it to match the right item in the list of parameters.
$propertyDescription = $dscResourceCommentBasedHelp.Parameters[$propertyMemberAst.Name.ToUpper()]

if ($propertyDescription)
{
$propertyDescription = Format-Text -Text $propertyDescription -Format @(
'Remove_Blank_Rows_At_End_Of_String',
'Remove_Indentation_From_Blank_Rows',
'Replace_NewLine_With_One_Whitespace',
'Replace_Vertical_Bar_With_One_Whitespace',
'Replace_Multiple_Whitespace_With_One',
'Remove_Whitespace_From_End_Of_String'
)
}
}
else
{
$propertyDescription = ''
}

$propertyAttribute['Description'] = $propertyDescription

$resourceProperty += $propertyAttribute
}
}

return $resourceProperty
}
Loading

0 comments on commit 210424f

Please sign in to comment.