@@ -16,7 +16,6 @@ namespace Microsoft.PowerShell.EditorServices.Symbols
16
16
/// </summary>
17
17
public class PesterDocumentSymbolProvider : FeatureProviderBase , IDocumentSymbolProvider
18
18
{
19
- private static char [ ] DefinitionTrimChars = new char [ ] { ' ' , '{' } ;
20
19
21
20
IEnumerable < SymbolReference > IDocumentSymbolProvider . ProvideDocumentSymbols (
22
21
ScriptFile scriptFile )
@@ -30,33 +29,135 @@ IEnumerable<SymbolReference> IDocumentSymbolProvider.ProvideDocumentSymbols(
30
29
31
30
var commandAsts = scriptFile . ScriptAst . FindAll ( ast =>
32
31
{
33
- switch ( ( ast as CommandAst ) ? . GetCommandName ( ) ? . ToLower ( ) )
34
- {
35
- case "describe" :
36
- case "context" :
37
- case "it" :
38
- return true ;
39
-
40
- default :
41
- return false ;
42
- }
32
+ CommandAst commandAst = ast as CommandAst ;
33
+
34
+ return
35
+ commandAst != null &&
36
+ PesterSymbolReference . GetCommandType ( commandAst . GetCommandName ( ) ) . HasValue &&
37
+ commandAst . CommandElements . Count >= 2 ;
43
38
} ,
44
39
true ) ;
45
40
46
41
return commandAsts . Select (
47
- ast => {
48
- var testDefinitionLine =
42
+ ast =>
43
+ {
44
+ // By this point we know the Ast is a CommandAst with 2 or more CommandElements
45
+ int testNameParamIndex = 1 ;
46
+ CommandAst testAst = ( CommandAst ) ast ;
47
+
48
+ // The -Name parameter
49
+ for ( int i = 1 ; i < testAst . CommandElements . Count ; i ++ )
50
+ {
51
+ CommandParameterAst paramAst = testAst . CommandElements [ i ] as CommandParameterAst ;
52
+ if ( paramAst != null &&
53
+ paramAst . ParameterName . Equals ( "Name" , StringComparison . OrdinalIgnoreCase ) )
54
+ {
55
+ testNameParamIndex = i + 1 ;
56
+ break ;
57
+ }
58
+ }
59
+
60
+ if ( testNameParamIndex > testAst . CommandElements . Count - 1 )
61
+ {
62
+ return null ;
63
+ }
64
+
65
+ StringConstantExpressionAst stringAst =
66
+ testAst . CommandElements [ testNameParamIndex ] as StringConstantExpressionAst ;
67
+
68
+ if ( stringAst == null )
69
+ {
70
+ return null ;
71
+ }
72
+
73
+ string testDefinitionLine =
49
74
scriptFile . GetLine (
50
75
ast . Extent . StartLineNumber ) ;
51
76
52
77
return
53
- new SymbolReference (
54
- SymbolType . Function ,
55
- testDefinitionLine . TrimEnd ( DefinitionTrimChars ) ,
56
- ast . Extent ,
57
- scriptFile . FilePath ,
58
- testDefinitionLine ) ;
59
- } ) ;
78
+ new PesterSymbolReference (
79
+ scriptFile ,
80
+ testAst . GetCommandName ( ) ,
81
+ testDefinitionLine ,
82
+ stringAst . Value ,
83
+ ast . Extent ) ;
84
+
85
+ } ) . Where ( s => s != null ) ;
86
+ }
87
+ }
88
+
89
+ /// <summary>
90
+ /// Defines command types for Pester test blocks.
91
+ /// </summary>
92
+ public enum PesterCommandType
93
+ {
94
+ /// <summary>
95
+ /// Identifies a Describe block.
96
+ /// </summary>
97
+ Describe ,
98
+
99
+ /// <summary>
100
+ /// Identifies a Context block.
101
+ /// </summary>
102
+ Context ,
103
+
104
+ /// <summary>
105
+ /// Identifies an It block.
106
+ /// </summary>
107
+ It
108
+ }
109
+
110
+ /// <summary>
111
+ /// Provides a specialization of SymbolReference containing
112
+ /// extra information about Pester test symbols.
113
+ /// </summary>
114
+ public class PesterSymbolReference : SymbolReference
115
+ {
116
+ private static char [ ] DefinitionTrimChars = new char [ ] { ' ' , '{' } ;
117
+
118
+ /// <summary>
119
+ /// Gets the name of the test
120
+ /// </summary>
121
+ public string TestName { get ; private set ; }
122
+
123
+ /// <summary>
124
+ /// Gets the test's command type.
125
+ /// </summary>
126
+ public PesterCommandType Command { get ; private set ; }
127
+
128
+ internal PesterSymbolReference (
129
+ ScriptFile scriptFile ,
130
+ string commandName ,
131
+ string testLine ,
132
+ string testName ,
133
+ IScriptExtent scriptExtent )
134
+ : base (
135
+ SymbolType . Function ,
136
+ testLine . TrimEnd ( DefinitionTrimChars ) ,
137
+ scriptExtent ,
138
+ scriptFile . FilePath ,
139
+ testLine )
140
+ {
141
+ this . Command = GetCommandType ( commandName ) . Value ;
142
+ this . TestName = testName ;
143
+ }
144
+
145
+ internal static PesterCommandType ? GetCommandType ( string commandName )
146
+ {
147
+ switch ( commandName . ToLower ( ) )
148
+ {
149
+ case "describe" :
150
+ return PesterCommandType . Describe ;
151
+
152
+ case "context" :
153
+ return PesterCommandType . Context ;
154
+
155
+ case "it" :
156
+ return PesterCommandType . It ;
157
+
158
+ default :
159
+ return null ;
160
+ }
60
161
}
61
162
}
62
163
}
0 commit comments