diff --git a/src/Analysis/Engine/Impl/Intellisense/AnalysisQueue.cs b/src/Analysis/Engine/Impl/Intellisense/AnalysisQueue.cs index 143e66ed8..8a964eea2 100644 --- a/src/Analysis/Engine/Impl/Intellisense/AnalysisQueue.cs +++ b/src/Analysis/Engine/Impl/Intellisense/AnalysisQueue.cs @@ -67,7 +67,7 @@ private async Task ConsumerLoop() { return; } catch (Exception ex) when (!ex.IsCriticalException()) { UnhandledException?.Invoke(this, new UnhandledExceptionEventArgs(ex, false)); - Dispose(); + throw; } } RaiseEventOnThreadPool(AnalysisComplete); diff --git a/src/Analysis/Engine/Impl/Values/BuiltinNamespace.cs b/src/Analysis/Engine/Impl/Values/BuiltinNamespace.cs index 6d3101ca9..499efdbcb 100644 --- a/src/Analysis/Engine/Impl/Values/BuiltinNamespace.cs +++ b/src/Analysis/Engine/Impl/Values/BuiltinNamespace.cs @@ -16,6 +16,7 @@ using System; using System.Collections.Generic; +using System.Linq; using Microsoft.PythonTools.Analysis.Infrastructure; using Microsoft.PythonTools.Interpreter; using Microsoft.PythonTools.Parsing.Ast; @@ -101,7 +102,7 @@ public bool TryGetMember(string name, out IAnalysisSet value) { public virtual ILocatedMember GetLocatedMember() => null; - public override IEnumerable Locations => GetLocatedMember()?.Locations.MaybeEnumerate(); + public override IEnumerable Locations => GetLocatedMember()?.Locations ?? Enumerable.Empty(); public override bool Equals(object obj) { if (obj is BuiltinNamespace bn && GetType() == bn.GetType()) { diff --git a/src/Analysis/Engine/Impl/Values/SpecializedNamespace.cs b/src/Analysis/Engine/Impl/Values/SpecializedNamespace.cs index 2b12d7669..8da4c6506 100644 --- a/src/Analysis/Engine/Impl/Values/SpecializedNamespace.cs +++ b/src/Analysis/Engine/Impl/Values/SpecializedNamespace.cs @@ -209,15 +209,15 @@ public override bool IsOfType(IAnalysisSet klass) { return _original.IsOfType(klass); } - public override IEnumerable Locations => _original?.Locations.MaybeEnumerate(); + public override IEnumerable Locations => _original?.Locations ?? Enumerable.Empty(); public override string Name => _original == null ? base.Name : _original.Name; - public override IEnumerable Overloads => _original?.Overloads.MaybeEnumerate(); + public override IEnumerable Overloads => _original?.Overloads ?? Enumerable.Empty(); public override IPythonType PythonType => _original?.PythonType; - internal override IEnumerable References => _original?.References.MaybeEnumerate(); + internal override IEnumerable References => _original?.References ?? Enumerable.Empty(); public override PythonMemberType MemberType => _original == null ? PythonMemberType.Unknown : _original.MemberType; diff --git a/src/LanguageServer/Impl/LanguageServer.Lifetime.cs b/src/LanguageServer/Impl/LanguageServer.Lifetime.cs index 4b8f7aef4..1c2ea8b62 100644 --- a/src/LanguageServer/Impl/LanguageServer.Lifetime.cs +++ b/src/LanguageServer/Impl/LanguageServer.Lifetime.cs @@ -64,14 +64,14 @@ public async Task Shutdown() { // https://microsoft.github.io/language-server-protocol/specification#shutdown await _server.Shutdown(); _shutdown = true; - _idleTimeTracker.Dispose(); + _idleTimeTracker?.Dispose(); } [JsonRpcMethod("exit")] public async Task Exit() { await _server.Exit(); _sessionTokenSource.Cancel(); - _idleTimeTracker.Dispose(); + _idleTimeTracker?.Dispose(); // Per https://microsoft.github.io/language-server-protocol/specification#exit Environment.Exit(_shutdown ? 0 : 1); } diff --git a/src/LanguageServer/Impl/LanguageServer.cs b/src/LanguageServer/Impl/LanguageServer.cs index 001a9595a..48e2105f5 100644 --- a/src/LanguageServer/Impl/LanguageServer.cs +++ b/src/LanguageServer/Impl/LanguageServer.cs @@ -17,6 +17,7 @@ using System; using System.Collections.Generic; using System.Diagnostics; +using System.IO; using System.Linq; using System.Threading; using System.Threading.Tasks; @@ -168,7 +169,16 @@ public async Task DidChangeConfiguration(JToken token, CancellationToken cancell await _server.DidChangeConfiguration(new DidChangeConfigurationParams { settings = settings }, cancellationToken); if (!_filesLoaded) { - await LoadDirectoryFiles(); + try { + await LoadDirectoryFiles(); + } catch (Exception ex) when ( + ex is IOException // FileNotFoundException, DirectoryNotFoundException, PathTooLongException, etc + || ex is UnauthorizedAccessException + ) { + // These exceptions are not caused by the LS, but by invalid/inaccessible user-specified paths. + _server.ShowMessage(MessageType.Error, $"Failed to load files in {_initParams.rootPath} - {ex.GetType().Name}: {ex.Message}"); + return; + } } _filesLoaded = true; }