@@ -229,6 +229,141 @@ public bool IsDscResourceModule(string filePath)
229229 return false ;
230230 }
231231
232+ /// <summary>
233+ /// Get the list of exported function by analyzing the ast
234+ /// </summary>
235+ /// <param name="ast"></param>
236+ /// <returns></returns>
237+ public HashSet < string > GetExportedFunction ( Ast ast )
238+ {
239+ HashSet < string > exportedFunctions = new HashSet < string > ( StringComparer . OrdinalIgnoreCase ) ;
240+ List < string > exportFunctionsCmdlet = Helper . Instance . CmdletNameAndAliases ( "export-modulemember" ) ;
241+
242+ // find functions exported
243+ IEnumerable < Ast > cmdAsts = ast . FindAll ( item => item is CommandAst
244+ && exportFunctionsCmdlet . Contains ( ( item as CommandAst ) . GetCommandName ( ) , StringComparer . OrdinalIgnoreCase ) , true ) ;
245+
246+ CommandInfo exportMM = Helper . Instance . GetCommandInfo ( "export-modulemember" , CommandTypes . Cmdlet ) ;
247+
248+ // switch parameters
249+ IEnumerable < ParameterMetadata > switchParams = ( exportMM != null ) ? exportMM . Parameters . Values . Where < ParameterMetadata > ( pm => pm . SwitchParameter ) : Enumerable . Empty < ParameterMetadata > ( ) ;
250+
251+ if ( exportMM == null )
252+ {
253+ return exportedFunctions ;
254+ }
255+
256+ foreach ( CommandAst cmdAst in cmdAsts )
257+ {
258+ if ( cmdAst . CommandElements == null || cmdAst . CommandElements . Count < 2 )
259+ {
260+ continue ;
261+ }
262+
263+ int i = 1 ;
264+
265+ while ( i < cmdAst . CommandElements . Count )
266+ {
267+ CommandElementAst ceAst = cmdAst . CommandElements [ i ] ;
268+ ExpressionAst exprAst = null ;
269+
270+ if ( ceAst is CommandParameterAst )
271+ {
272+ var paramAst = ceAst as CommandParameterAst ;
273+ var param = exportMM . ResolveParameter ( paramAst . ParameterName ) ;
274+
275+ if ( param == null )
276+ {
277+ i += 1 ;
278+ continue ;
279+ }
280+
281+ if ( string . Equals ( param . Name , "function" , StringComparison . OrdinalIgnoreCase ) )
282+ {
283+ // checks for the case of -Function:"verb-nouns"
284+ if ( paramAst . Argument != null )
285+ {
286+ exprAst = paramAst . Argument ;
287+ }
288+ // checks for the case of -Function "verb-nouns"
289+ else if ( i < cmdAst . CommandElements . Count - 1 )
290+ {
291+ i += 1 ;
292+ exprAst = cmdAst . CommandElements [ i ] as ExpressionAst ;
293+ }
294+ }
295+ // some other parameter. we just checks whether the one after this is positional
296+ else if ( i < cmdAst . CommandElements . Count - 1 )
297+ {
298+ // the next element is a parameter like -module so just move to that one
299+ if ( cmdAst . CommandElements [ i + 1 ] is CommandParameterAst )
300+ {
301+ i += 1 ;
302+ continue ;
303+ }
304+
305+ // not a switch parameter so the next element is definitely the argument to this parameter
306+ if ( paramAst . Argument == null && ! switchParams . Contains ( param ) )
307+ {
308+ // skips the next element
309+ i += 1 ;
310+ }
311+
312+ i += 1 ;
313+ continue ;
314+ }
315+ }
316+ else if ( ceAst is ExpressionAst )
317+ {
318+ exprAst = ceAst as ExpressionAst ;
319+ }
320+
321+ if ( exprAst != null )
322+ {
323+ // One string so just add this to the list
324+ if ( exprAst is StringConstantExpressionAst )
325+ {
326+ exportedFunctions . Add ( ( exprAst as StringConstantExpressionAst ) . Value ) ;
327+ }
328+ // Array of the form "v-n", "v-n1"
329+ else if ( exprAst is ArrayLiteralAst )
330+ {
331+ exportedFunctions . UnionWith ( Helper . Instance . GetStringsFromArrayLiteral ( exprAst as ArrayLiteralAst ) ) ;
332+ }
333+ // Array of the form @("v-n", "v-n1")
334+ else if ( exprAst is ArrayExpressionAst )
335+ {
336+ ArrayExpressionAst arrExAst = exprAst as ArrayExpressionAst ;
337+ if ( arrExAst . SubExpression != null && arrExAst . SubExpression . Statements != null )
338+ {
339+ foreach ( StatementAst stAst in arrExAst . SubExpression . Statements )
340+ {
341+ if ( stAst is PipelineAst )
342+ {
343+ PipelineAst pipeAst = stAst as PipelineAst ;
344+ if ( pipeAst . PipelineElements != null )
345+ {
346+ foreach ( CommandBaseAst cmdBaseAst in pipeAst . PipelineElements )
347+ {
348+ if ( cmdBaseAst is CommandExpressionAst )
349+ {
350+ exportedFunctions . UnionWith ( Helper . Instance . GetStringsFromArrayLiteral ( ( cmdBaseAst as CommandExpressionAst ) . Expression as ArrayLiteralAst ) ) ;
351+ }
352+ }
353+ }
354+ }
355+ }
356+ }
357+ }
358+ }
359+
360+ i += 1 ;
361+ }
362+ }
363+
364+ return exportedFunctions ;
365+ }
366+
232367 /// <summary>
233368 /// Given a filePath. Returns true if it is a powershell help file
234369 /// </summary>
0 commit comments