diff --git a/Engine/Commands/InvokeScriptAnalyzerCommand.cs b/Engine/Commands/InvokeScriptAnalyzerCommand.cs index 4ef01699a..c2cced646 100644 --- a/Engine/Commands/InvokeScriptAnalyzerCommand.cs +++ b/Engine/Commands/InvokeScriptAnalyzerCommand.cs @@ -250,6 +250,10 @@ protected override void ProcessRecord() using (var moduleHandler = new ModuleDependencyHandler(rsp)) { ScriptAnalyzer.Instance.ModuleHandler = moduleHandler; + this.WriteVerbose( + String.Format( + "Temporary module location: {0}", + moduleHandler.TempModulePath)); ProcessInput(); } } diff --git a/Engine/Generic/ModuleDependencyHandler.cs b/Engine/Generic/ModuleDependencyHandler.cs index bd1edd642..d96882a3c 100644 --- a/Engine/Generic/ModuleDependencyHandler.cs +++ b/Engine/Generic/ModuleDependencyHandler.cs @@ -445,10 +445,10 @@ public static IEnumerable GetModuleNameFromErrorExtent(ParseError error, } // find a parameter named modulename - int k; + int k; for (k = 1; k < dynamicKywdAst.CommandElements.Count; k++) { - var paramAst = dynamicKywdAst.CommandElements[1] as CommandParameterAst; + var paramAst = dynamicKywdAst.CommandElements[k] as CommandParameterAst; // TODO match the initial letters only if (paramAst == null || !paramAst.ParameterName.Equals("ModuleName", StringComparison.OrdinalIgnoreCase)) { diff --git a/Engine/ScriptAnalyzer.cs b/Engine/ScriptAnalyzer.cs index b39db8b87..41ffc3e2d 100644 --- a/Engine/ScriptAnalyzer.cs +++ b/Engine/ScriptAnalyzer.cs @@ -1290,6 +1290,39 @@ private void BuildScriptPathList( } } + private bool TrySaveModules(ParseError[] errors, ScriptBlockAst scriptAst) + { + bool modulesSaved = false; + if (moduleHandler == null || errors == null || errors.Length == 0) + { + return modulesSaved; + } + foreach (var error in errors.Where(IsModuleNotFoundError)) + { + var moduleNames = moduleHandler.GetUnavailableModuleNameFromErrorExtent(error, scriptAst); + if (moduleNames == null) + { + continue; + } + foreach(var moduleName in moduleNames) + { + this.outputWriter.WriteVerbose( + String.Format( + "Saving module {0} from PSGallery", + moduleName)); + var moduleSaved = moduleHandler.TrySaveModule(moduleName); + if (!moduleSaved) + { + this.outputWriter.WriteVerbose( + String.Format( + "Cannot download {0} from PSGallery", + moduleName)); + } + modulesSaved |= moduleSaved; + } + } + return modulesSaved; + } private IEnumerable AnalyzeFile(string filePath) { @@ -1315,23 +1348,8 @@ private IEnumerable AnalyzeFile(string filePath) return null; } #if !PSV3 - bool parseAgain = false; - if (moduleHandler != null && errors != null && errors.Length > 0) - { - foreach (ParseError error in errors.Where(IsModuleNotFoundError)) - { - var moduleNames = moduleHandler.GetUnavailableModuleNameFromErrorExtent(error, scriptAst); - if (moduleNames != null) - { - parseAgain |= moduleNames.Any(x => moduleHandler.TrySaveModule(x)); - } - } - } - //try parsing again - //var oldDefault = Runspace.DefaultRunspace; - //Runspace.DefaultRunspace = moduleHandler.Runspace; - if (parseAgain) + if (TrySaveModules(errors, scriptAst)) { scriptAst = Parser.ParseFile(filePath, out scriptTokens, out errors); } diff --git a/Tests/Engine/ModuleDependencyHandler.tests.ps1 b/Tests/Engine/ModuleDependencyHandler.tests.ps1 index 889683553..526406df6 100644 --- a/Tests/Engine/ModuleDependencyHandler.tests.ps1 +++ b/Tests/Engine/ModuleDependencyHandler.tests.ps1 @@ -72,7 +72,7 @@ Describe "Resolve DSC Resource Dependency" { {$moduleHandlerType::new($rsp)} | Should Throw $rsp.Dispose() } - + It "Extracts 1 module name" { $sb = @" {Configuration SomeConfiguration @@ -84,9 +84,9 @@ Describe "Resolve DSC Resource Dependency" { $parseError = $null $ast = [System.Management.Automation.Language.Parser]::ParseInput($sb, [ref]$tokens, [ref]$parseError) $resultModuleNames = $moduleHandlerType::GetModuleNameFromErrorExtent($parseError[0], $ast).ToArray() - $resultModuleNames[0] | Should Be 'SomeDscModule1' + $resultModuleNames[0] | Should Be 'SomeDscModule1' } - + It "Extracts more than 1 module names" { $sb = @" {Configuration SomeConfiguration @@ -102,6 +102,21 @@ Describe "Resolve DSC Resource Dependency" { $resultModuleNames[1] | Should Be 'SomeDscModule2' $resultModuleNames[2] | Should Be 'SomeDscModule3' } + + + It "Extracts module names when ModuleName parameter is not the first named parameter" { + $sb = @" +{Configuration SomeConfiguration +{ + Import-DscResource -Name SomeName -ModuleName SomeDscModule1 +}} +"@ + $tokens = $null + $parseError = $null + $ast = [System.Management.Automation.Language.Parser]::ParseInput($sb, [ref]$tokens, [ref]$parseError) + $resultModuleNames = $moduleHandlerType::GetModuleNameFromErrorExtent($parseError[0], $ast).ToArray() + $resultModuleNames[0] | Should Be 'SomeDscModule1' + } } Context "Invoke-ScriptAnalyzer without switch" {