Skip to content

Commit

Permalink
This change refactors the code for the **Documentarian.DevX** module in
Browse files Browse the repository at this point in the history
preparation for further refactoring and updates.

It:

- Standardizes the structure of classes, adding code regions for static
  properties, static methods, instance properties, instance methods, and
  constructors in that order.
- Standardizes the style for class property declarations using the following
  template:

  ```powershell
  <#
    .SYNOPSIS
    Property synopsis.
  #>
  hidden        # Included only for hidden properties
  static        # Included only for static properties
  [Attribute()] # Any declared attributes, one per line
  [Type]        # Always defined
  $PropertyName # Always defined, PascalCased.
  ```

  If the property has a default value, that value is defined after the property
  name as normal.
- Standardizes the style for class method declarations, using the following
  template:

  ```powershell
  hidden static [ReturnType] MethodName(
    [ParameterOneType]
    $parameterOne,

    [ParameterTwoType]
    $parameterTwo
  ) {
    <#
      .SYNOPSIS
      Method overload synopsis
    #>

    # Method overload body code
  }
  ```

  Methods always define a return type. Methods that don't return any output use
  the `[void]` type. Method parameters are always camel-cased and always define
  a type. If the parameter can be any type, use the `[object]` type. Parameter
  definitions are always multi-line, with a blank line between parameters.
- Standardizes the style for function declarations, using the
  following template:

  ``````powershell
  <#
    .SYNOPSIS
    Function synopsis
  #>

  [CmdletBinding()]    # Always defined, even if empty.
  [OutputType([Type])] # Always defined, one per line.
  param(
    [Parameter()]      # Always defined, even if empty.
    [Attribute()]      # One per line, as needed.
    [ParameterOneType] # Always defined
    $ParameterOne,

    [Parameter()]      # Always defined, even if empty.
    [Attribute()]      # One per line, as needed.
    [ParameterTwoType] # Always defined
    $ParameterTwo
  )

  begin {
    # Code before all processing, including initializing variables and
    # defining helper scriptblocks or functions.
  }

  process {
    # Processing code, main body of the function.
  }

  end {
    # Post-processing code.
  }
  ``````

  Functions always use cmdlet binding and define their output type or types. If
  the function returns no output, the output type is `[void]`. They always
  define the `param` keyword, even if empty, and use the `begin`, `process`,
  and `end` keywords.

  Function parameters are always declared with the `Parameter` attribute, even
  if it's empty. Every parameter must define a type. If the parameter can be of
  any type, specify the type as `[object]`. Parameter names are always
  Pascal-cased and may have default values as normal.
- Adds comment-based help to the beginning of the definition for classes,
  enumerations, functions, and tasks, immediately after the opening of the
  definition script block.

Refactoring the behavior and fully documenting the code will be handled in
future changes. These changes are being made first to avoid conflating
structural changes with the actual refactoring and improvement work.
  • Loading branch information
michaeltlombardi committed May 13, 2024
1 parent 36ae374 commit 627477e
Show file tree
Hide file tree
Showing 36 changed files with 2,021 additions and 504 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -4,25 +4,101 @@
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
)
$this.Tokens = $t
$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
)
Expand All @@ -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
}
Original file line number Diff line number Diff line change
Expand Up @@ -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] } {
Expand Down Expand Up @@ -71,4 +90,12 @@ class DevXAstTypeTransformAttribute : ArgumentTransformationAttribute {

return $outputData
}

#endregion Instance properties

#region Instance methods
#endregion Instance methods

#region Constructors
#endregion Constructors
}
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down Expand Up @@ -38,4 +59,9 @@ class DevXValidatePowerShellScriptPathAttribute : ValidateArgumentsAttribute {
throw [System.ArgumentException]::new("$MessagePrefix; $Message")
}
}

#endregion Instance methods

#region Constructors
#endregion Constructors
}
Original file line number Diff line number Diff line change
Expand Up @@ -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
}
Original file line number Diff line number Diff line change
Expand Up @@ -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
}
Loading

0 comments on commit 627477e

Please sign in to comment.