diff --git a/src/Analysis/Ast/Impl/Modules/PythonModule.cs b/src/Analysis/Ast/Impl/Modules/PythonModule.cs index 5b0972ebd..ec07498c1 100644 --- a/src/Analysis/Ast/Impl/Modules/PythonModule.cs +++ b/src/Analysis/Ast/Impl/Modules/PythonModule.cs @@ -215,10 +215,10 @@ protected virtual string LoadContent() { return null; // Keep content as null so module can be loaded later. } - private void InitializeContent(string content) { + private void InitializeContent(string content, int version = 0) { bool startParse; lock (AnalysisLock) { - LoadContent(content); + LoadContent(content, version); startParse = ContentState < State.Parsing && _parsingTask == null; if (startParse) { @@ -231,11 +231,11 @@ private void InitializeContent(string content) { } } - private void LoadContent(string content) { + private void LoadContent(string content, int version) { if (ContentState < State.Loading) { try { content = content ?? LoadContent(); - _buffer.Reset(0, content); + _buffer.Reset(version, content); ContentState = State.Loaded; } catch (IOException) { } catch (UnauthorizedAccessException) { } } @@ -330,7 +330,8 @@ public void Update(IEnumerable changes) { public void Reset(string content) { lock (AnalysisLock) { if (content != Content) { - InitializeContent(content); + ContentState = State.None; + InitializeContent(content, _buffer.Version + 1); } } } diff --git a/src/Analysis/Ast/Impl/Modules/Resolution/MainModuleResolution.cs b/src/Analysis/Ast/Impl/Modules/Resolution/MainModuleResolution.cs index 15d89318d..21748b4cb 100644 --- a/src/Analysis/Ast/Impl/Modules/Resolution/MainModuleResolution.cs +++ b/src/Analysis/Ast/Impl/Modules/Resolution/MainModuleResolution.cs @@ -180,7 +180,11 @@ internal async Task LoadBuiltinTypesAsync(CancellationToken cancellationToken = await BuiltinsModule.LoadAndAnalyzeAsync(cancellationToken); Check.InvalidOperation(!(BuiltinsModule.Analysis is EmptyAnalysis), "After await"); + // Add built-in module names + SetBuiltinModuleNames(); + } + private void SetBuiltinModuleNames() { // Add built-in module names var builtinModuleNamesMember = BuiltinsModule.GetAnyMember("__builtin_module_names__"); if (builtinModuleNamesMember.TryGetConstant(out var s)) { @@ -203,6 +207,7 @@ public async Task ReloadAsync(CancellationToken cancellationToken = default) { Modules[BuiltinModuleName] = builtins; PathResolver = new PathResolver(_interpreter.LanguageVersion); + SetBuiltinModuleNames(); var addedRoots = new HashSet(); addedRoots.UnionWith(PathResolver.SetRoot(_root)); diff --git a/src/LanguageServer/Impl/Implementation/Server.cs b/src/LanguageServer/Impl/Implementation/Server.cs index e74f17475..94ba30e9d 100644 --- a/src/LanguageServer/Impl/Implementation/Server.cs +++ b/src/LanguageServer/Impl/Implementation/Server.cs @@ -40,12 +40,16 @@ public sealed partial class Server : IDisposable { private readonly DisposableBag _disposableBag = DisposableBag.Create(); private readonly CancellationTokenSource _shutdownCts = new CancellationTokenSource(); private readonly IServiceManager _services; + private readonly object _reloadLock = new object(); private IPythonInterpreter _interpreter; private IRunningDocumentTable _rdt; private ClientCapabilities _clientCaps; private ILogger _log; private IIndexManager _indexManager; + private string _rootDir; + private DateTime _lastPackageReload = DateTime.Now; + public Server(IServiceManager services) { _services = services; @@ -65,6 +69,7 @@ public Server(IServiceManager services) { public void Dispose() => _disposableBag.TryDispose(); #region Client message handling + private InitializeResult GetInitializeResult() => new InitializeResult { capabilities = new ServerCapabilities { textDocumentSync = new TextDocumentSyncOptions { @@ -72,10 +77,10 @@ public Server(IServiceManager services) { change = TextDocumentSyncKind.Incremental }, completionProvider = new CompletionOptions { - triggerCharacters = new[] { "." } + triggerCharacters = new[] {"."} }, hoverProvider = true, - signatureHelpProvider = new SignatureHelpOptions { triggerCharacters = new[] { "(", ",", ")" } }, + signatureHelpProvider = new SignatureHelpOptions {triggerCharacters = new[] {"(", ",", ")"}}, definitionProvider = true, referencesProvider = true, workspaceSymbolProvider = true, @@ -83,7 +88,7 @@ public Server(IServiceManager services) { renameProvider = true, documentOnTypeFormattingProvider = new DocumentOnTypeFormattingOptions { firstTriggerCharacter = "\n", - moreTriggerCharacter = new[] { ";", ":" } + moreTriggerCharacter = new[] {";", ":"} }, } }; @@ -121,10 +126,10 @@ public async Task InitializeAsync(InitializeParams @params, Ca _services.AddService(_interpreter); var fileSystem = _services.GetService(); - _indexManager = new IndexManager(fileSystem, _interpreter.LanguageVersion, rootDir, - @params.initializationOptions.includeFiles, - @params.initializationOptions.excludeFiles, - _services.GetService()); + _indexManager = new IndexManager(fileSystem, _interpreter.LanguageVersion, _rootDir, + @params.initializationOptions.includeFiles, + @params.initializationOptions.excludeFiles, + _services.GetService()); _services.AddService(_indexManager); _disposableBag.Add(_indexManager); @@ -158,6 +163,7 @@ public void DidChangeConfiguration(DidChangeConfigurationParams @params, Cancell if (HandleConfigurationChanges(settings)) { RestartAnalysis(); } + break; } default: @@ -165,15 +171,17 @@ public void DidChangeConfiguration(DidChangeConfigurationParams @params, Cancell break; } } + #endregion #region Private Helpers + private void DisplayStartupInfo() { _log?.Log(TraceEventType.Information, Resources.LanguageServerVersion.FormatInvariant(Assembly.GetExecutingAssembly().GetName().Version)); _log?.Log(TraceEventType.Information, string.IsNullOrEmpty(_interpreter.Configuration.InterpreterPath) - ? Resources.InitializingForGenericInterpreter - : Resources.InitializingForPythonInterpreter.FormatInvariant(_interpreter.Configuration.InterpreterPath)); + ? Resources.InitializingForGenericInterpreter + : Resources.InitializingForPythonInterpreter.FormatInvariant(_interpreter.Configuration.InterpreterPath)); } private bool HandleConfigurationChanges(ServerSettings newSettings) { @@ -212,25 +220,31 @@ private IDocumentationSource ChooseDocumentationSource(string[] kinds) { return new PlainTextDocumentationSource(); } + #endregion public void NotifyPackagesChanged(CancellationToken cancellationToken) { - var interpreter = _services.GetService(); - _log?.Log(TraceEventType.Information, Resources.ReloadingModules); - // No need to reload typeshed resolution since it is a static storage. - // User does can add stubs while application is running, but it is - // by design at this time that the app should be restarted. - interpreter.ModuleResolution.ReloadAsync(cancellationToken).ContinueWith(t => { - _log?.Log(TraceEventType.Information, Resources.Done); - _log?.Log(TraceEventType.Information, Resources.AnalysisRestarted); - RestartAnalysis(); - }, cancellationToken).DoNotWait(); - + lock (_reloadLock) { + if ((DateTime.Now - _lastPackageReload).TotalMilliseconds > 10000) { + var interpreter = _services.GetService(); + _log?.Log(TraceEventType.Information, Resources.ReloadingModules); + // No need to reload typeshed resolution since it is a static storage. + // User does can add stubs while application is running, but it is + // by design at this time that the app should be restarted. + interpreter.ModuleResolution.ReloadAsync(cancellationToken).ContinueWith(t => { + _log?.Log(TraceEventType.Information, Resources.Done); + _log?.Log(TraceEventType.Information, Resources.AnalysisRestarted); + RestartAnalysis(); + }, cancellationToken).DoNotWait(); + } + } } private void RestartAnalysis() { - foreach (var doc in _rdt) { - doc.Reset(null); + lock (_reloadLock) { + foreach (var doc in _rdt) { + doc.Reset(null); + } } } } diff --git a/src/LanguageServer/Impl/PathsWatcher.cs b/src/LanguageServer/Impl/PathsWatcher.cs index fe331385d..1ebcfefc3 100644 --- a/src/LanguageServer/Impl/PathsWatcher.cs +++ b/src/LanguageServer/Impl/PathsWatcher.cs @@ -80,7 +80,7 @@ private void OnChanged(object sender, FileSystemEventArgs e) { // if there is massive change to the file structure. lock (_lock) { _changedSinceLastTick = true; - _throttleTimer = _throttleTimer ?? new Timer(TimerProc, null, 500, 500); + _throttleTimer = _throttleTimer ?? new Timer(TimerProc, null, 2000, 2000); } }