Skip to content

Commit cdf5c1c

Browse files
committed
More LineNumber Converters
1 parent 97349a1 commit cdf5c1c

File tree

3 files changed

+122
-3
lines changed

3 files changed

+122
-3
lines changed

Source/Public/Convert-Breakpoint.ps1

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
function Convert-Breakpoint {
2+
<#
3+
.SYNOPSIS
4+
Convert any breakpoints on source files to module files and vice-versa
5+
#>
6+
[CmdletBinding(DefaultParameterSetName="All")]
7+
param(
8+
[Parameter(ParameterSetName="Module")]
9+
[switch]$ModuleOnly,
10+
[Parameter(ParameterSetName="Source")]
11+
[switch]$SourceOnly
12+
)
13+
14+
if (!$SourceOnly) {
15+
foreach ($ModuleBreakPoint in Get-PSBreakpoint | ConvertFrom-SourceLineNumber) {
16+
Set-PSBreakpoint -Script $ModuleBreakPoint.Script -Line $ModuleBreakPoint.Line
17+
if ($ModuleOnly) {
18+
# TODO: | Remove-PSBreakpoint
19+
}
20+
}
21+
}
22+
23+
if (!$ModuleOnly) {
24+
foreach ($SourceBreakPoint in Get-PSBreakpoint | ConvertTo-SourceLineNumber) {
25+
if (!(Test-Path $SourceBreakPoint.SourceFile)) {
26+
Write-Warning "Can't find source path: $($SourceBreakPoint.SourceFile)"
27+
} else {
28+
Set-PSBreakpoint -Script $SourceBreakPoint.SourceFile -Line $SourceBreakPoint.SourceLineNumber
29+
}
30+
if ($SourceOnly) {
31+
# TODO: | Remove-PSBreakpoint
32+
}
33+
}
34+
}
35+
}
Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
function ConvertFrom-SourceLineNumber {
2+
<#
3+
.SYNOPSIS
4+
Convert the line number in a built module to a file and line number in source
5+
.EXAMPLE
6+
ConvertFrom-SourceLineNumber -Module ~\2.0.0\ModuleBuilder.psm1 -SourceFile ~\Source\Public\Build-Module.ps1 -Line 27
7+
#>
8+
[CmdletBinding(DefaultParameterSetName="FromString")]
9+
param(
10+
# The SourceFile is the source script file that was built into the module
11+
[Parameter(Mandatory, ValueFromPipelineByPropertyName, Position=0)]
12+
[Alias("PSCommandPath", "File", "ScriptName", "Script")]
13+
[string]$SourceFile,
14+
15+
# The SourceLineNumber (from an InvocationInfo) is the line number in the source file
16+
[Parameter(Mandatory, ValueFromPipelineByPropertyName, Position=1)]
17+
[Alias("LineNumber", "Line", "ScriptLineNumber")]
18+
[int]$SourceLineNumber,
19+
20+
# The name of the module in memory, or the full path to the module psm1
21+
[Parameter()]
22+
[string]$Module
23+
)
24+
begin {
25+
$filemap = @{}
26+
}
27+
process {
28+
if (!$Module) {
29+
$Command = [IO.Path]::GetFileNameWithoutExtension($SourceFile)
30+
$Module = (Get-Command $Command -ErrorAction SilentlyContinue).Source
31+
if (!$Module) {
32+
Write-Warning "Please specify -Module for breakpoint ${SourceFile}: $SourceLineNumber"
33+
return
34+
}
35+
}
36+
if ($Module -and -not (Test-Path $Module)) {
37+
$Module = (Get-Module $Module -ErrorAction Stop).Path
38+
}
39+
# Push-Location (Split-Path $SourceFile)
40+
try {
41+
if (!$filemap.ContainsKey($Module)) {
42+
# Note: the new pattern is #Region but the old one was # BEGIN
43+
$regions = Select-String '^(?:#Region|# BEGIN) (?<SourceFile>.*) (?<LineNumber>\d+)?$' -Path $Module
44+
$filemap[$Module] = @($regions.ForEach{
45+
[PSCustomObject]@{
46+
PSTypeName = "BuildSourceMapping"
47+
SourceFile = $_.Matches[0].Groups["SourceFile"].Value.Trim("'")
48+
StartLineNumber = $_.LineNumber
49+
}
50+
})
51+
}
52+
53+
$hit = $filemap[$Module]
54+
55+
if ($Source = $hit.Where{ $SourceFile.EndsWith($_.SourceFile.TrimStart(".\")) }) {
56+
[PSCustomObject]@{
57+
PSTypeName = "OutputLocation"
58+
Script = $Module
59+
Line = $Source.StartLineNumber + $SourceLineNumber
60+
}
61+
} elseif($Source -eq $Module) {
62+
[PSCustomObject]@{
63+
PSTypeName = "OutputLocation"
64+
Script = $Module
65+
Line = $SourceLineNumber
66+
}
67+
} else {
68+
Write-Warning "'$SourceFile' not found in $Module"
69+
}
70+
} finally {
71+
Pop-Location
72+
}
73+
}
74+
}

Source/Public/Convert-LineNumber.ps1 renamed to Source/Public/ConvertTo-SourceLineNumber.ps1

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
function Convert-LineNumber {
1+
function ConvertTo-SourceLineNumber {
22
<#
33
.SYNOPSIS
44
Convert the line number in a built module to a file and line number in source
@@ -7,43 +7,53 @@ function Convert-LineNumber {
77
.EXAMPLE
88
Convert-LineNumber -PositionMessage "At C:\Users\Joel\OneDrive\Documents\PowerShell\Modules\ErrorMaker\ErrorMaker.psm1:27 char:4"
99
#>
10+
[Alias("Convert-LineNumber")]
1011
[CmdletBinding(DefaultParameterSetName="FromString")]
1112
param(
1213
# A position message as found in PowerShell's error messages, ScriptStackTrace, or InvocationInfo
1314
[Parameter(Mandatory, ValueFromPipeline, ValueFromPipelineByPropertyName, ParameterSetName="FromString")]
1415
[string]$PositionMessage,
1516

17+
# The SourceFile (from an InvocationInfo) is the module psm1 path
1618
[Parameter(Mandatory, ValueFromPipelineByPropertyName, Position=0, ParameterSetName="FromInvocationInfo")]
1719
[Alias("PSCommandPath", "File", "ScriptName", "Script")]
1820
[string]$SourceFile,
1921

22+
# The SourceLineNumber (from an InvocationInfo) is the module line number
2023
[Parameter(Mandatory, ValueFromPipelineByPropertyName, Position=1, ParameterSetName="FromInvocationInfo")]
2124
[Alias("LineNumber", "Line", "ScriptLineNumber")]
2225
[int]$SourceLineNumber,
2326

27+
# The actual InvocationInfo
2428
[Parameter(ValueFromPipeline, DontShow, ParameterSetName="FromInvocationInfo")]
2529
[psobject]$InputObject,
2630

31+
# If set, passes through the InputObject, overwriting the SourceFile and SourceLineNumber.
32+
# Otherwise, creates a new SourceLocation object with just those properties.
2733
[Parameter(ParameterSetName="FromInvocationInfo")]
2834
[switch]$Passthru
2935
)
3036
begin {
3137
$filemap = @{}
3238
}
3339
process {
34-
if($PSCmdlet.ParameterSetName -eq "FromString") {
40+
if ($PSCmdlet.ParameterSetName -eq "FromString") {
3541
$Invocation = ParseLineNumber $PositionMessage
3642
$SourceFile = $Invocation.SourceFile
3743
$SourceLineNumber = $Invocation.SourceLineNumber
3844
}
39-
if(!(Test-Path $SourceFile)) {
45+
if (!(Test-Path $SourceFile)) {
4046
throw "'$SourceFile' does not exist"
4147
}
4248
Push-Location (Split-Path $SourceFile)
4349
try {
4450
if (!$filemap.ContainsKey($SourceFile)) {
4551
# Note: the new pattern is #Region but the old one was # BEGIN
4652
$regions = Select-String '^(?:#Region|# BEGIN) (?<SourceFile>.*) (?<LineNumber>\d+)?$' -Path $SourceFile
53+
if ($regions.Count -eq 0) {
54+
Write-Warning "No SourceMap for $SourceFile"
55+
return
56+
}
4757
$filemap[$SourceFile] = @($regions.ForEach{
4858
[PSCustomObject]@{
4959
PSTypeName = "BuildSourceMapping"

0 commit comments

Comments
 (0)