-
-
Notifications
You must be signed in to change notification settings - Fork 21
/
Show-Coverage.ps1
165 lines (139 loc) · 3.54 KB
/
Show-Coverage.ps1
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
<#
.Synopsis
Converts to HTML and shows script coverage data.
Author: Roman Kuzmin
.Description
This script converts script coverage data produced by Trace-Debugger.ps1 to
a HTML file and opens it by an associated application, normally the default
internet browser.
Coverage information is not always accurate because a tracing tool may not
step through all pieces of code and this script does not perform detailed
analysis of sources.
.Parameter Data
A hashtable with coverage data, e.g. produced by Trace-Debugger.ps1.
.Parameter Html
Specifies the output HTML file.
Default: $env:TEMP\Coverage.htm
.Parameter Show
Specifies the script block which opens the converted HTML file. The
default script { Invoke-Item -LiteralPath $args[0] } opens it by the
associated application, normally the default browser.
.Inputs
None
.Outputs
None
.Example
>
How to collect and show script coverage data
# enable tracing with result data table
Trace-Debugger Test.ps1 -Table Coverage
# invoke with tracing
Test.ps1
# stop tracing
Restore-Debugger
# show coverage data
Show-Coverage $Coverage
.Link
https://github.com/nightroman/PowerShelf
.Link
Trace-Debugger.ps1
#>
param(
[Parameter(Mandatory=1)]
[hashtable]$Data,
[string]$Html = "$env:TEMP\Coverage.htm",
[scriptblock]$Show = {Invoke-Item -LiteralPath $args[0]}
)
$ErrorActionPreference = 'Stop'
Set-StrictMode -Version Latest
# HtmlEncode
Add-Type -AssemblyName System.Web
function encode($Text) {
[System.Web.HttpUtility]::HtmlEncode($text)
}
function convert($Path, $Data) {
$lines = Get-Content -LiteralPath $Path
[ref]$bugs = $null
$tokens = [System.Management.Automation.PSParser]::Tokenize($lines, $bugs)
if ($bugs.Value.Count) {
$can = $null
}
else {
$can = @{}
foreach($token in $tokens) {
switch($token.Type) {
Attribute {$yes = 0; break}
Command {$yes = 1; break}
CommandArgument {$yes = 0; break}
CommandParameter {$yes = 0; break}
Comment {$yes = 0; break}
GroupEnd {$yes = 0; break}
GroupStart {$yes = 0; break}
Keyword {$yes = 0; break}
LineContinuation {$yes = 0; break}
LoopLabel {$yes = 0; break}
Member {$yes = 1; break}
NewLine {$yes = 0; break}
Number {$yes = 1; break}
Operator {$yes = 0; break}
Position {$yes = 1; break}
StatementSeparator {$yes = 0; break}
String {$yes = 1; break}
Type {$yes = 1; break}
Variable {$yes = 1; break}
default {$yes = 1; break}
}
if ($yes) {
++$can[$token.StartLine]
}
}
}
'<pre>'
$n = 0
foreach($line in $lines) {
++$n
$line = $line.TrimEnd()
if (!$line) {
'{0,5} : ' -f $n
continue
}
if (!($pass = $Data[$n])) {
if (!$can -or $can[$n]) {
$pass = '---->'
}
else {
$pass = ' '
}
}
'{0,5} {1,5} : {2}' -f $n, $pass, (encode $line)
}
'</pre>'
}
### generate
.{
'<html><title>Coverage</title>'
'<body>'
$paths = $Data.Keys | Sort-Object
### index
'<h3>Covered Scripts</h3>'
'<ul>'
$n = 0
foreach($path in $paths) { if (Test-Path -LiteralPath $path) {
++$n
"<li><a href='#file$n'>$(encode $path)</a></li>"
}}
'</ul>'
### content
$n = 0
foreach($path in $paths) { if (Test-Path -LiteralPath $path) {
++$n
"<hr/><h3><a id='file$n'>$(encode $path)</a></h3>"
convert $path $Data[$path]
}}
'</body>'
'</html>'
} | Set-Content -LiteralPath $Html -Encoding UTF8
### show
if ($Show) {
& $Show $Html
}