From 679e80f1658442e4ae1ed958b648064f314882d7 Mon Sep 17 00:00:00 2001 From: Steve Dower Date: Wed, 25 May 2016 10:36:51 -0700 Subject: [PATCH 1/3] Fixes #1251 No completions in virtual env REPL Enables getting the project associated with an interpreter ID so that we can flow settings through to the interactive window. Also fixes a potential crash on VS shutdown. --- .../IInterpreterRegistryService.cs | 2 + .../IPythonInterpreterFactoryProvider.cs | 5 ++ .../Interpreter/InterpreterRegistryService.cs | 5 ++ .../CanopyInterpreterFactoryProvider.cs | 2 + .../IronPythonInterpreterFactoryProvider.cs | 1 + .../PythonTools/PythonTools/Extensions.cs | 20 ++++++- .../Repl/PythonInteractiveEvaluator.cs | 57 +++++++++++-------- .../PythonUwpInterpreterFactoryProvider.cs | 2 + .../CPythonInterpreterFactoryProvider.cs | 10 ++++ ...SBuildProjectInterpreterFactoryProvider.cs | 5 ++ Python/Tests/Core/ReplEvaluatorTests.cs | 2 + .../MockInterpreterOptionsService.cs | 4 ++ .../MockPythonInterpreterFactoryProvider.cs | 2 + 13 files changed, 90 insertions(+), 27 deletions(-) diff --git a/Python/Product/Analysis/Interpreter/IInterpreterRegistryService.cs b/Python/Product/Analysis/Interpreter/IInterpreterRegistryService.cs index 7f0b5e5b6c..fcdd0ec5b4 100644 --- a/Python/Product/Analysis/Interpreter/IInterpreterRegistryService.cs +++ b/Python/Product/Analysis/Interpreter/IInterpreterRegistryService.cs @@ -45,6 +45,8 @@ public interface IInterpreterRegistryService { InterpreterConfiguration FindConfiguration(string id); + string FindAssociatedProjectMoniker(string id); + /// /// Raised when the set of interpreters changes. This is not raised when /// the set is first initialized. diff --git a/Python/Product/Analysis/Interpreter/IPythonInterpreterFactoryProvider.cs b/Python/Product/Analysis/Interpreter/IPythonInterpreterFactoryProvider.cs index 67bc4a8919..10929406df 100644 --- a/Python/Product/Analysis/Interpreter/IPythonInterpreterFactoryProvider.cs +++ b/Python/Product/Analysis/Interpreter/IPythonInterpreterFactoryProvider.cs @@ -46,6 +46,11 @@ public interface IPythonInterpreterFactoryProvider { /// Gets a specific configured interpreter /// IPythonInterpreterFactory GetInterpreterFactory(string id); + + /// + /// Gets the associated project moniker, if any. + /// + string GetAssociatedProjectMoniker(string id); } public static class PythonInterpreterExtensions { diff --git a/Python/Product/Analysis/Interpreter/InterpreterRegistryService.cs b/Python/Product/Analysis/Interpreter/InterpreterRegistryService.cs index 2718d62bfd..07bcf8f823 100644 --- a/Python/Product/Analysis/Interpreter/InterpreterRegistryService.cs +++ b/Python/Product/Analysis/Interpreter/InterpreterRegistryService.cs @@ -361,6 +361,11 @@ public InterpreterConfiguration FindConfiguration(string id) { return null; } + public string FindAssociatedProjectMoniker(string id) { + var factoryProvider = GetFactoryProvider(id); + return factoryProvider?.GetAssociatedProjectMoniker(id); + } + private IPythonInterpreterFactoryProvider GetFactoryProvider(string id) { var interpAndId = id.Split(new[] { '|' }, 2); if (interpAndId.Length == 2) { diff --git a/Python/Product/CanopyInterpreter/CanopyInterpreterFactoryProvider.cs b/Python/Product/CanopyInterpreter/CanopyInterpreterFactoryProvider.cs index ede22f4fb1..615cb7c354 100644 --- a/Python/Product/CanopyInterpreter/CanopyInterpreterFactoryProvider.cs +++ b/Python/Product/CanopyInterpreter/CanopyInterpreterFactoryProvider.cs @@ -230,6 +230,8 @@ public IPythonInterpreterFactory GetInterpreterFactory(string id) { .FirstOrDefault(); } + public string GetAssociatedProjectMoniker(string id) => null; + public event EventHandler InterpreterFactoriesChanged; private void OnInterpreterFactoriesChanged() { diff --git a/Python/Product/IronPython/Interpreter/IronPythonInterpreterFactoryProvider.cs b/Python/Product/IronPython/Interpreter/IronPythonInterpreterFactoryProvider.cs index f9eabd5c96..e5b82b09c5 100644 --- a/Python/Product/IronPython/Interpreter/IronPythonInterpreterFactoryProvider.cs +++ b/Python/Product/IronPython/Interpreter/IronPythonInterpreterFactoryProvider.cs @@ -171,6 +171,7 @@ private void DiscoverInterpreterFactories() { public event EventHandler InterpreterFactoriesChanged; + public string GetAssociatedProjectMoniker(string id) => null; #endregion diff --git a/Python/Product/PythonTools/PythonTools/Extensions.cs b/Python/Product/PythonTools/PythonTools/Extensions.cs index 55f061b1e0..52ce0e06ee 100644 --- a/Python/Product/PythonTools/PythonTools/Extensions.cs +++ b/Python/Product/PythonTools/PythonTools/Extensions.cs @@ -290,8 +290,15 @@ internal static bool TryGetAnalysisEntry(this ITextView view, ITextBuffer buffer string path = buffer.GetFilePath(); if (path != null) { - var docTable = provider.GetService(typeof(SVsRunningDocumentTable)) as IVsRunningDocumentTable4; - var cookie = docTable.GetDocumentCookie(path); + var docTable = (IVsRunningDocumentTable4)provider.GetService(typeof(SVsRunningDocumentTable)); + var cookie = VSConstants.VSCOOKIE_NIL; + try { + cookie = docTable.GetDocumentCookie(path); + } catch (ArgumentException) { + // Exception may be raised while VS is shutting down + entry = null; + return false; + } VsProjectAnalyzer analyzer = null; if (cookie != VSConstants.VSCOOKIE_NIL) { IVsHierarchy hierarchy; @@ -486,7 +493,14 @@ internal static PythonProjectNode GetProjectFromFile(this IServiceProvider servi IVsHierarchy hierarchy; uint itemid; docTable.GetDocumentHierarchyItem(cookie, out hierarchy, out itemid); - return hierarchy.GetProject()?.GetPythonProject(); + var project = hierarchy.GetProject(); + if (project != null) { + return project.GetPythonProject(); + } + + object projectObj; + ErrorHandler.ThrowOnFailure(hierarchy.GetProperty(itemid, (int)__VSHPROPID.VSHPROPID_ExtObject, out projectObj)); + return (projectObj as EnvDTE.Project)?.GetPythonProject(); } return null; } diff --git a/Python/Product/PythonTools/PythonTools/Repl/PythonInteractiveEvaluator.cs b/Python/Product/PythonTools/PythonTools/Repl/PythonInteractiveEvaluator.cs index 758c810050..b373318543 100644 --- a/Python/Product/PythonTools/PythonTools/Repl/PythonInteractiveEvaluator.cs +++ b/Python/Product/PythonTools/PythonTools/Repl/PythonInteractiveEvaluator.cs @@ -134,7 +134,17 @@ public VsProjectAnalyzer Analyzer { if (config == null) { _analyzer = _serviceProvider.GetPythonToolsService().DefaultAnalyzer; } else { - _analyzer = new VsProjectAnalyzer(_serviceProvider, interpreterService.FindInterpreter(config.Interpreter.Id)); + Build.Evaluation.Project projectFile = null; + var moniker = ProjectMoniker ?? + interpreterService.FindAssociatedProjectMoniker(config.Interpreter.Id); + if (!string.IsNullOrEmpty(moniker)) { + projectFile = _serviceProvider.GetProjectFromFile(moniker)?.BuildProject; + } + _analyzer = new VsProjectAnalyzer( + _serviceProvider, + interpreterService.FindInterpreter(config.Interpreter.Id), + projectFile: projectFile + ); } return _analyzer; } @@ -283,22 +293,20 @@ protected async Task EnsureConnectedAsync() { } return await _serviceProvider.GetUIThread().InvokeTask(async () => { - if (!string.IsNullOrEmpty(ProjectMoniker)) { - try { - UpdatePropertiesFromProjectMoniker(); - } catch (NoInterpretersException ex) { - WriteError(ex.ToString()); - return null; - } catch (MissingInterpreterException ex) { - WriteError(ex.ToString()); - return null; - } catch (DirectoryNotFoundException ex) { - WriteError(ex.ToString()); - return null; - } catch (Exception ex) when (!ex.IsCriticalException()) { - WriteError(ex.ToUnhandledExceptionMessage(GetType())); - return null; - } + try { + UpdatePropertiesFromProjectMoniker(); + } catch (NoInterpretersException ex) { + WriteError(ex.ToString()); + return null; + } catch (MissingInterpreterException ex) { + WriteError(ex.ToString()); + return null; + } catch (DirectoryNotFoundException ex) { + WriteError(ex.ToString()); + return null; + } catch (Exception ex) when (!ex.IsCriticalException()) { + WriteError(ex.ToUnhandledExceptionMessage(GetType())); + return null; } var scriptsPath = ScriptsPath; @@ -351,17 +359,18 @@ protected virtual async Task ExecuteStartupScripts(string scriptsPath) { } internal void UpdatePropertiesFromProjectMoniker() { - var solution = _serviceProvider.GetService(typeof(SVsSolution)) as IVsSolution; - if (solution == null) { - return; + var moniker = ProjectMoniker; + var interpreter = Configuration?.Interpreter; + if (interpreter != null && string.IsNullOrEmpty(moniker)) { + var interpreterService = _serviceProvider.GetComponentModel().GetService(); + moniker = interpreterService?.FindAssociatedProjectMoniker(Configuration.Interpreter.Id); } - IVsHierarchy hier; - if (string.IsNullOrEmpty(ProjectMoniker) || - ErrorHandler.Failed(solution.GetProjectOfUniqueName(ProjectMoniker, out hier))) { + if (string.IsNullOrEmpty(moniker)) { return; } - var pyProj = hier?.GetProject()?.GetPythonProject(); + + var pyProj = _serviceProvider.GetProjectFromFile(moniker)?.GetPythonProject(); if (pyProj == null) { return; } diff --git a/Python/Product/Uwp.Interpreter/PythonUwpInterpreterFactoryProvider.cs b/Python/Product/Uwp.Interpreter/PythonUwpInterpreterFactoryProvider.cs index 517fc10e43..752313dd0c 100644 --- a/Python/Product/Uwp.Interpreter/PythonUwpInterpreterFactoryProvider.cs +++ b/Python/Product/Uwp.Interpreter/PythonUwpInterpreterFactoryProvider.cs @@ -120,5 +120,7 @@ public IPythonInterpreterFactory GetInterpreterFactory(string id) { .Where(x => x.Configuration.Id == id) .FirstOrDefault(); } + + public string GetAssociatedProjectMoniker(string id) => null; } } \ No newline at end of file diff --git a/Python/Product/VSInterpreters/CPythonInterpreterFactoryProvider.cs b/Python/Product/VSInterpreters/CPythonInterpreterFactoryProvider.cs index 7e005eea86..c9707eb2a1 100644 --- a/Python/Product/VSInterpreters/CPythonInterpreterFactoryProvider.cs +++ b/Python/Product/VSInterpreters/CPythonInterpreterFactoryProvider.cs @@ -24,6 +24,7 @@ using System.Text.RegularExpressions; using System.Threading; using Microsoft.PythonTools.Infrastructure; +using Microsoft.PythonTools.Parsing; using Microsoft.Win32; namespace Microsoft.PythonTools.Interpreter { @@ -180,6 +181,13 @@ private static void TryRegisterInterpreter(Dictionary null; + #endregion class InterpreterInformation { diff --git a/Python/Product/VSInterpreters/MSBuildProjectInterpreterFactoryProvider.cs b/Python/Product/VSInterpreters/MSBuildProjectInterpreterFactoryProvider.cs index b0062eb136..42d5e88230 100644 --- a/Python/Product/VSInterpreters/MSBuildProjectInterpreterFactoryProvider.cs +++ b/Python/Product/VSInterpreters/MSBuildProjectInterpreterFactoryProvider.cs @@ -129,6 +129,11 @@ public IPythonInterpreterFactory GetInterpreterFactory(string id) { return null; } + public string GetAssociatedProjectMoniker(string id) { + var moniker = id.Substring(id.LastIndexOf('|') + 1); + return PathUtils.IsValidPath(moniker) ? moniker : null; + } + public static string GetInterpreterId(string file, string id) { return String.Join("|", MSBuildProviderName, id, file); } diff --git a/Python/Tests/Core/ReplEvaluatorTests.cs b/Python/Tests/Core/ReplEvaluatorTests.cs index 05f0a726f3..2e52159871 100644 --- a/Python/Tests/Core/ReplEvaluatorTests.cs +++ b/Python/Tests/Core/ReplEvaluatorTests.cs @@ -235,6 +235,8 @@ public IPythonInterpreterFactory GetInterpreterFactory(string id) { .FirstOrDefault(); } + public string GetAssociatedProjectMoniker(string id) => null; + public event EventHandler InterpreterFactoriesChanged { add { } remove { } } } diff --git a/Python/Tests/Utilities.Python.Analysis/MockInterpreterOptionsService.cs b/Python/Tests/Utilities.Python.Analysis/MockInterpreterOptionsService.cs index 19cfcc23b1..5459e8494c 100644 --- a/Python/Tests/Utilities.Python.Analysis/MockInterpreterOptionsService.cs +++ b/Python/Tests/Utilities.Python.Analysis/MockInterpreterOptionsService.cs @@ -165,5 +165,9 @@ public InterpreterConfiguration FindConfiguration(string id) { public string AddConfigurableInterpreter(string name, InterpreterConfiguration config) { throw new NotImplementedException(); } + + public string FindAssociatedProjectMoniker(string id) { + throw new NotImplementedException(); + } } } diff --git a/Python/Tests/Utilities.Python.Analysis/MockPythonInterpreterFactoryProvider.cs b/Python/Tests/Utilities.Python.Analysis/MockPythonInterpreterFactoryProvider.cs index 9db2fe604c..ca7c46b855 100644 --- a/Python/Tests/Utilities.Python.Analysis/MockPythonInterpreterFactoryProvider.cs +++ b/Python/Tests/Utilities.Python.Analysis/MockPythonInterpreterFactoryProvider.cs @@ -90,6 +90,8 @@ public IPythonInterpreterFactory GetInterpreterFactory(string id) { .FirstOrDefault(); } + public string GetAssociatedProjectMoniker(string id) => null; + public event EventHandler InterpreterFactoriesChanged; } } From bc631c2310fadbc49b0f3d6279666f602acb2b4d Mon Sep 17 00:00:00 2001 From: Steve Dower Date: Thu, 26 May 2016 16:37:46 -0700 Subject: [PATCH 2/3] Generalises GetAssociatedProjectMoniker function into GetProperty. --- .../Interpreter/IInterpreterRegistryService.cs | 11 ++++++++++- .../Interpreter/IPythonInterpreterFactoryProvider.cs | 10 ++++++++-- .../Interpreter/InterpreterRegistryService.cs | 4 ++-- .../CanopyInterpreterFactoryProvider.cs | 2 +- .../IronPythonInterpreterFactoryProvider.cs | 2 +- .../PythonTools/Repl/PythonInteractiveEvaluator.cs | 4 ++-- .../PythonUwpInterpreterFactoryProvider.cs | 2 +- .../CPythonInterpreterFactoryProvider.cs | 2 +- .../MSBuildProjectInterpreterFactoryProvider.cs | 9 ++++++--- Python/Tests/Core/ReplEvaluatorTests.cs | 2 +- .../MockInterpreterOptionsService.cs | 2 +- .../MockPythonInterpreterFactoryProvider.cs | 2 +- 12 files changed, 35 insertions(+), 17 deletions(-) diff --git a/Python/Product/Analysis/Interpreter/IInterpreterRegistryService.cs b/Python/Product/Analysis/Interpreter/IInterpreterRegistryService.cs index fcdd0ec5b4..5a2c6f622b 100644 --- a/Python/Product/Analysis/Interpreter/IInterpreterRegistryService.cs +++ b/Python/Product/Analysis/Interpreter/IInterpreterRegistryService.cs @@ -45,7 +45,16 @@ public interface IInterpreterRegistryService { InterpreterConfiguration FindConfiguration(string id); - string FindAssociatedProjectMoniker(string id); + /// + /// Gets a property value relating to a specific interpreter. + /// + /// If the property is not set, returns null. + /// + /// The interpreter identifier. + /// A case-sensitive string identifying the + /// property. Values will be compared by ordinal. + /// The property value, or null if not set. + object GetProperty(string id, string propName); /// /// Raised when the set of interpreters changes. This is not raised when diff --git a/Python/Product/Analysis/Interpreter/IPythonInterpreterFactoryProvider.cs b/Python/Product/Analysis/Interpreter/IPythonInterpreterFactoryProvider.cs index 10929406df..f12725cbe6 100644 --- a/Python/Product/Analysis/Interpreter/IPythonInterpreterFactoryProvider.cs +++ b/Python/Product/Analysis/Interpreter/IPythonInterpreterFactoryProvider.cs @@ -48,9 +48,15 @@ public interface IPythonInterpreterFactoryProvider { IPythonInterpreterFactory GetInterpreterFactory(string id); /// - /// Gets the associated project moniker, if any. + /// Gets a property value associated with the specified interpreter. If + /// the property is not set or available, return null. + /// + /// Property values should not change over the process lifetime. /// - string GetAssociatedProjectMoniker(string id); + /// The interpreter id. + /// A case-sensitive string identifying the name + /// of the property. Values will be compared by ordinal. + object GetProperty(string id, string propName); } public static class PythonInterpreterExtensions { diff --git a/Python/Product/Analysis/Interpreter/InterpreterRegistryService.cs b/Python/Product/Analysis/Interpreter/InterpreterRegistryService.cs index 07bcf8f823..823af5c0ba 100644 --- a/Python/Product/Analysis/Interpreter/InterpreterRegistryService.cs +++ b/Python/Product/Analysis/Interpreter/InterpreterRegistryService.cs @@ -361,9 +361,9 @@ public InterpreterConfiguration FindConfiguration(string id) { return null; } - public string FindAssociatedProjectMoniker(string id) { + public object GetProperty(string id, string propName) { var factoryProvider = GetFactoryProvider(id); - return factoryProvider?.GetAssociatedProjectMoniker(id); + return factoryProvider?.GetProperty(id, propName); } private IPythonInterpreterFactoryProvider GetFactoryProvider(string id) { diff --git a/Python/Product/CanopyInterpreter/CanopyInterpreterFactoryProvider.cs b/Python/Product/CanopyInterpreter/CanopyInterpreterFactoryProvider.cs index 615cb7c354..8c49a8dc03 100644 --- a/Python/Product/CanopyInterpreter/CanopyInterpreterFactoryProvider.cs +++ b/Python/Product/CanopyInterpreter/CanopyInterpreterFactoryProvider.cs @@ -230,7 +230,7 @@ public IPythonInterpreterFactory GetInterpreterFactory(string id) { .FirstOrDefault(); } - public string GetAssociatedProjectMoniker(string id) => null; + public object GetProperty(string id, string propName) => null; public event EventHandler InterpreterFactoriesChanged; diff --git a/Python/Product/IronPython/Interpreter/IronPythonInterpreterFactoryProvider.cs b/Python/Product/IronPython/Interpreter/IronPythonInterpreterFactoryProvider.cs index e5b82b09c5..22120921e9 100644 --- a/Python/Product/IronPython/Interpreter/IronPythonInterpreterFactoryProvider.cs +++ b/Python/Product/IronPython/Interpreter/IronPythonInterpreterFactoryProvider.cs @@ -171,7 +171,7 @@ private void DiscoverInterpreterFactories() { public event EventHandler InterpreterFactoriesChanged; - public string GetAssociatedProjectMoniker(string id) => null; + public object GetProperty(string id, string propName) => null; #endregion diff --git a/Python/Product/PythonTools/PythonTools/Repl/PythonInteractiveEvaluator.cs b/Python/Product/PythonTools/PythonTools/Repl/PythonInteractiveEvaluator.cs index b373318543..4087603353 100644 --- a/Python/Product/PythonTools/PythonTools/Repl/PythonInteractiveEvaluator.cs +++ b/Python/Product/PythonTools/PythonTools/Repl/PythonInteractiveEvaluator.cs @@ -136,7 +136,7 @@ public VsProjectAnalyzer Analyzer { } else { Build.Evaluation.Project projectFile = null; var moniker = ProjectMoniker ?? - interpreterService.FindAssociatedProjectMoniker(config.Interpreter.Id); + interpreterService.GetProperty(config.Interpreter.Id, "ProjectMoniker") as string; if (!string.IsNullOrEmpty(moniker)) { projectFile = _serviceProvider.GetProjectFromFile(moniker)?.BuildProject; } @@ -363,7 +363,7 @@ internal void UpdatePropertiesFromProjectMoniker() { var interpreter = Configuration?.Interpreter; if (interpreter != null && string.IsNullOrEmpty(moniker)) { var interpreterService = _serviceProvider.GetComponentModel().GetService(); - moniker = interpreterService?.FindAssociatedProjectMoniker(Configuration.Interpreter.Id); + moniker = interpreterService?.GetProperty(Configuration.Interpreter.Id, "ProjectMoniker") as string; } if (string.IsNullOrEmpty(moniker)) { diff --git a/Python/Product/Uwp.Interpreter/PythonUwpInterpreterFactoryProvider.cs b/Python/Product/Uwp.Interpreter/PythonUwpInterpreterFactoryProvider.cs index 752313dd0c..80295b6d34 100644 --- a/Python/Product/Uwp.Interpreter/PythonUwpInterpreterFactoryProvider.cs +++ b/Python/Product/Uwp.Interpreter/PythonUwpInterpreterFactoryProvider.cs @@ -121,6 +121,6 @@ public IPythonInterpreterFactory GetInterpreterFactory(string id) { .FirstOrDefault(); } - public string GetAssociatedProjectMoniker(string id) => null; + public object GetProperty(string id, string propName) => null; } } \ No newline at end of file diff --git a/Python/Product/VSInterpreters/CPythonInterpreterFactoryProvider.cs b/Python/Product/VSInterpreters/CPythonInterpreterFactoryProvider.cs index c9707eb2a1..c714a96403 100644 --- a/Python/Product/VSInterpreters/CPythonInterpreterFactoryProvider.cs +++ b/Python/Product/VSInterpreters/CPythonInterpreterFactoryProvider.cs @@ -361,7 +361,7 @@ private void OnInterpreterFactoriesChanged() { _interpFactoriesChanged?.Invoke(this, EventArgs.Empty); } - public string GetAssociatedProjectMoniker(string id) => null; + public object GetProperty(string id, string propName) => null; #endregion diff --git a/Python/Product/VSInterpreters/MSBuildProjectInterpreterFactoryProvider.cs b/Python/Product/VSInterpreters/MSBuildProjectInterpreterFactoryProvider.cs index 42d5e88230..bebfa9a34a 100644 --- a/Python/Product/VSInterpreters/MSBuildProjectInterpreterFactoryProvider.cs +++ b/Python/Product/VSInterpreters/MSBuildProjectInterpreterFactoryProvider.cs @@ -129,9 +129,12 @@ public IPythonInterpreterFactory GetInterpreterFactory(string id) { return null; } - public string GetAssociatedProjectMoniker(string id) { - var moniker = id.Substring(id.LastIndexOf('|') + 1); - return PathUtils.IsValidPath(moniker) ? moniker : null; + public object GetProperty(string id, string propName) { + if (propName == "ProjectMoniker") { + var moniker = id.Substring(id.LastIndexOf('|') + 1); + return PathUtils.IsValidPath(moniker) ? moniker : null; + } + return null; } public static string GetInterpreterId(string file, string id) { diff --git a/Python/Tests/Core/ReplEvaluatorTests.cs b/Python/Tests/Core/ReplEvaluatorTests.cs index 2e52159871..3e22e30d27 100644 --- a/Python/Tests/Core/ReplEvaluatorTests.cs +++ b/Python/Tests/Core/ReplEvaluatorTests.cs @@ -235,7 +235,7 @@ public IPythonInterpreterFactory GetInterpreterFactory(string id) { .FirstOrDefault(); } - public string GetAssociatedProjectMoniker(string id) => null; + public object GetProperty(string id, string propName) => null; public event EventHandler InterpreterFactoriesChanged { add { } remove { } } } diff --git a/Python/Tests/Utilities.Python.Analysis/MockInterpreterOptionsService.cs b/Python/Tests/Utilities.Python.Analysis/MockInterpreterOptionsService.cs index 5459e8494c..91c74e7b21 100644 --- a/Python/Tests/Utilities.Python.Analysis/MockInterpreterOptionsService.cs +++ b/Python/Tests/Utilities.Python.Analysis/MockInterpreterOptionsService.cs @@ -166,7 +166,7 @@ public string AddConfigurableInterpreter(string name, InterpreterConfiguration c throw new NotImplementedException(); } - public string FindAssociatedProjectMoniker(string id) { + public object GetProperty(string id, string propName) { throw new NotImplementedException(); } } diff --git a/Python/Tests/Utilities.Python.Analysis/MockPythonInterpreterFactoryProvider.cs b/Python/Tests/Utilities.Python.Analysis/MockPythonInterpreterFactoryProvider.cs index ca7c46b855..fb94563e86 100644 --- a/Python/Tests/Utilities.Python.Analysis/MockPythonInterpreterFactoryProvider.cs +++ b/Python/Tests/Utilities.Python.Analysis/MockPythonInterpreterFactoryProvider.cs @@ -90,7 +90,7 @@ public IPythonInterpreterFactory GetInterpreterFactory(string id) { .FirstOrDefault(); } - public string GetAssociatedProjectMoniker(string id) => null; + public object GetProperty(string id, string propName) => null; public event EventHandler InterpreterFactoriesChanged; } From 2c69ea7da1da8d6c5d66f22333198637256be143 Mon Sep 17 00:00:00 2001 From: Steve Dower Date: Thu, 26 May 2016 16:55:14 -0700 Subject: [PATCH 3/3] Refactored GetAssociatedPythonProject function. --- .../Repl/PythonInteractiveEvaluator.cs | 41 ++++++++++--------- 1 file changed, 22 insertions(+), 19 deletions(-) diff --git a/Python/Product/PythonTools/PythonTools/Repl/PythonInteractiveEvaluator.cs b/Python/Product/PythonTools/PythonTools/Repl/PythonInteractiveEvaluator.cs index 4087603353..7cf4d0d5b5 100644 --- a/Python/Product/PythonTools/PythonTools/Repl/PythonInteractiveEvaluator.cs +++ b/Python/Product/PythonTools/PythonTools/Repl/PythonInteractiveEvaluator.cs @@ -122,24 +122,38 @@ internal virtual void OnConnected() { } internal virtual void OnAttach() { } internal virtual void OnDetach() { } + private PythonProjectNode GetAssociatedPythonProject(InterpreterConfiguration interpreter = null) { + var moniker = ProjectMoniker; + if (interpreter == null) { + interpreter = Configuration?.Interpreter; + } + + if (string.IsNullOrEmpty(moniker) && interpreter != null) { + var interpreterService = _serviceProvider.GetComponentModel().GetService(); + moniker = interpreterService.GetProperty(interpreter.Id, "ProjectMoniker") as string; + } + + if (string.IsNullOrEmpty(moniker)) { + return null; + } + + return _serviceProvider.GetProjectFromFile(moniker); + } + + public VsProjectAnalyzer Analyzer { get { if (_analyzer != null) { return _analyzer; } - var interpreterService = _serviceProvider.GetComponentModel().GetService(); var config = Configuration; if (config == null) { _analyzer = _serviceProvider.GetPythonToolsService().DefaultAnalyzer; } else { - Build.Evaluation.Project projectFile = null; - var moniker = ProjectMoniker ?? - interpreterService.GetProperty(config.Interpreter.Id, "ProjectMoniker") as string; - if (!string.IsNullOrEmpty(moniker)) { - projectFile = _serviceProvider.GetProjectFromFile(moniker)?.BuildProject; - } + var projectFile = GetAssociatedPythonProject(config.Interpreter)?.BuildProject; + var interpreterService = _serviceProvider.GetComponentModel().GetService(); _analyzer = new VsProjectAnalyzer( _serviceProvider, interpreterService.FindInterpreter(config.Interpreter.Id), @@ -359,18 +373,7 @@ protected virtual async Task ExecuteStartupScripts(string scriptsPath) { } internal void UpdatePropertiesFromProjectMoniker() { - var moniker = ProjectMoniker; - var interpreter = Configuration?.Interpreter; - if (interpreter != null && string.IsNullOrEmpty(moniker)) { - var interpreterService = _serviceProvider.GetComponentModel().GetService(); - moniker = interpreterService?.GetProperty(Configuration.Interpreter.Id, "ProjectMoniker") as string; - } - - if (string.IsNullOrEmpty(moniker)) { - return; - } - - var pyProj = _serviceProvider.GetProjectFromFile(moniker)?.GetPythonProject(); + var pyProj = GetAssociatedPythonProject(); if (pyProj == null) { return; }