1919using System . ComponentModel . Composition ;
2020using System . Globalization ;
2121using System . Text . RegularExpressions ;
22+ using System . Diagnostics ;
2223
2324namespace Microsoft . Windows . PowerShell . ScriptAnalyzer . BuiltinRules
2425{
@@ -29,6 +30,12 @@ namespace Microsoft.Windows.PowerShell.ScriptAnalyzer.BuiltinRules
2930 [ Export ( typeof ( IScriptRule ) ) ]
3031 public class UseToExportFieldsInManifest : IScriptRule
3132 {
33+
34+ private const string functionsToExport = "FunctionsToExport" ;
35+ private const string cmdletsToExport = "CmdletsToExport" ;
36+ private const string variablesToExport = "VariablesToExport" ;
37+ private const string aliasesToExport = "AliasesToExport" ;
38+
3239 /// <summary>
3340 /// AnalyzeScript: Analyzes the AST to check if AliasToExport, CmdletsToExport, FunctionsToExport
3441 /// and VariablesToExport fields do not use wildcards and $null in their entries.
@@ -48,43 +55,101 @@ public IEnumerable<DiagnosticRecord> AnalyzeScript(Ast ast, string fileName)
4855 yield break ;
4956 }
5057
51- if ( ! IsValidManifest ( ast , fileName ) )
52- {
58+ // check if valid module manifest
59+ IEnumerable < ErrorRecord > errorRecord = null ;
60+ PSModuleInfo psModuleInfo = Helper . Instance . GetModuleManifest ( fileName , out errorRecord ) ;
61+ if ( ( errorRecord != null && errorRecord . Count ( ) > 0 ) || psModuleInfo == null )
62+ {
5363 yield break ;
5464 }
55-
56- String [ ] manifestFields = { "FunctionsToExport" , "CmdletsToExport" , "VariablesToExport" , "AliasesToExport" } ;
65+
5766 var hashtableAst = ast . Find ( x => x is HashtableAst , false ) as HashtableAst ;
5867
5968 if ( hashtableAst == null )
6069 {
6170 yield break ;
6271 }
6372
64- foreach ( String field in manifestFields )
73+ string [ ] manifestFields = { functionsToExport , cmdletsToExport , variablesToExport , aliasesToExport } ;
74+
75+ foreach ( string field in manifestFields )
6576 {
6677 IScriptExtent extent ;
6778 if ( ! HasAcceptableExportField ( field , hashtableAst , ast . Extent . Text , out extent ) && extent != null )
6879 {
69- yield return new DiagnosticRecord ( GetError ( field ) , extent , GetName ( ) , DiagnosticSeverity . Warning , fileName ) ;
80+ yield return new DiagnosticRecord (
81+ GetError ( field ) ,
82+ extent ,
83+ GetName ( ) ,
84+ DiagnosticSeverity . Warning ,
85+ fileName ,
86+ suggestedCorrections : GetCorrectionExtent ( field , extent , psModuleInfo ) ) ;
7087 }
7188 }
7289
7390 }
74-
75- /// <summary>
76- /// Checks if the manifest file is valid.
77- /// </summary>
78- /// <param name="ast"></param>
79- /// <param name="fileName"></param>
80- /// <returns>A boolean value indicating the validity of the manifest file.</returns>
81- private bool IsValidManifest ( Ast ast , string fileName )
91+
92+ private string GetListLiteral < T > ( Dictionary < string , T > exportedItems )
8293 {
83- var missingManifestRule = new MissingModuleManifestField ( ) ;
84- return ! missingManifestRule . AnalyzeScript ( ast , fileName ) . GetEnumerator ( ) . MoveNext ( ) ;
85-
94+ if ( exportedItems == null || exportedItems . Keys == null )
95+ {
96+ return null ;
97+ }
98+ var sbuilder = new System . Text . StringBuilder ( ) ;
99+ sbuilder . Append ( "@(" ) ;
100+ sbuilder . Append ( string . Join ( ", " , exportedItems . Keys . Select ( key => string . Format ( "'{0}'" , key ) ) ) ) ;
101+ sbuilder . Append ( ")" ) ;
102+ return sbuilder . ToString ( ) ;
86103 }
87104
105+
106+ private List < CorrectionExtent > GetCorrectionExtent ( string field , IScriptExtent extent , PSModuleInfo psModuleInfo )
107+ {
108+ Debug . Assert ( field != null ) ;
109+ Debug . Assert ( psModuleInfo != null ) ;
110+ Debug . Assert ( extent != null ) ;
111+ var corrections = new List < CorrectionExtent > ( ) ;
112+ string correctionText = null ;
113+ switch ( field )
114+ {
115+ case functionsToExport :
116+ correctionText = GetListLiteral ( psModuleInfo . ExportedFunctions ) ;
117+ break ;
118+ case cmdletsToExport :
119+ correctionText = GetListLiteral ( psModuleInfo . ExportedCmdlets ) ;
120+ break ;
121+ case variablesToExport :
122+ correctionText = GetListLiteral ( psModuleInfo . ExportedVariables ) ;
123+ break ;
124+ case aliasesToExport :
125+ correctionText = GetListLiteral ( psModuleInfo . ExportedAliases ) ;
126+ break ;
127+ default :
128+ throw new NotImplementedException ( string . Format ( "{0} not implemented" , field ) ) ;
129+ }
130+ corrections . Add ( new CorrectionExtent (
131+ extent . StartLineNumber ,
132+ extent . EndLineNumber ,
133+ extent . StartColumnNumber ,
134+ extent . EndColumnNumber ,
135+ correctionText ,
136+ extent . File ) ) ;
137+ return corrections ;
138+ }
139+
140+ ///// <summary>
141+ ///// Checks if the manifest file is valid.
142+ ///// </summary>
143+ ///// <param name="ast"></param>
144+ ///// <param name="fileName"></param>
145+ ///// <returns>A boolean value indicating the validity of the manifest file.</returns>
146+ //private bool IsValidManifest(Ast ast, string fileName)
147+ //{
148+ // var missingManifestRule = new MissingModuleManifestField();
149+ // return !missingManifestRule.AnalyzeScript(ast, fileName).GetEnumerator().MoveNext();
150+
151+ //}
152+
88153 /// <summary>
89154 /// Checks if the ast contains wildcard character.
90155 /// </summary>
0 commit comments