@@ -16,7 +16,6 @@ namespace Microsoft.PowerShell.EditorServices.Symbols
1616 /// </summary>
1717 public class PesterDocumentSymbolProvider : FeatureProviderBase , IDocumentSymbolProvider
1818 {
19- private static char [ ] DefinitionTrimChars = new char [ ] { ' ' , '{' } ;
2019
2120 IEnumerable < SymbolReference > IDocumentSymbolProvider . ProvideDocumentSymbols (
2221 ScriptFile scriptFile )
@@ -30,33 +29,135 @@ IEnumerable<SymbolReference> IDocumentSymbolProvider.ProvideDocumentSymbols(
3029
3130 var commandAsts = scriptFile . ScriptAst . FindAll ( ast =>
3231 {
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 ;
4338 } ,
4439 true ) ;
4540
4641 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 =
4974 scriptFile . GetLine (
5075 ast . Extent . StartLineNumber ) ;
5176
5277 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+ }
60161 }
61162 }
62163}
0 commit comments