Skip to content
This repository was archived by the owner on Apr 14, 2022. It is now read-only.

Fix wait for analysis complete, fix tests and avoid reload on all config changes #110

Merged
merged 17 commits into from
Sep 20, 2018
Merged

Conversation

MikhailArkhipov
Copy link

@MikhailArkhipov MikhailArkhipov commented Sep 19, 2018

Fixes #111

  • Improves Reloading modules leaks memory #109 - avoid reloading modules on any configuration change. Still need to debug why reloading modules leaks.

  • Improves test stability as well as Rename/FindReferences/DocumentSymbols/GotoDefinition by waiting for the complete analysis.

var package = state.AddModule("fob", "from .y import abc", "fob\\__init__.py");
var x = state.AddModule("fob.x", "from .y import abc");
var y = state.AddModule("fob.y", "abc = 42");
/*
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We don't need this offset.

@@ -712,5 +703,39 @@ private sealed class ReloadModulesQueueItem : IAnalyzable {
return false;
}
#endregion

internal Task WaitForCompleteAnalysisAsync(CancellationToken cancellationToken) {
var tcs = new TaskCompletionSource<object>();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

=> Task.WhenAny(WaitForCompleteAnalysisWorker(cancellationToken), Task.Delay(Timeout.Infinite, cancellationToken)).Unwrap();

@@ -83,6 +87,7 @@ public sealed partial class LanguageServer: IDisposable {
}

public void Dispose() {
_shutdownCts.Cancel();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

_shutdownCts can be added to _disposables

MikhailArkhipov added 5 commits September 19, 2018 16:53
Fix analysis of modules that import changed one
@@ -157,9 +157,13 @@ private class ActivePythonParse : IPythonParse {

internal void SetCompleteAnalysis() {
lock (this) {
_analysisTcs.TrySetResult(Analysis);
if (AnalysisVersion == _expectedParse) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this can be simplified a bit:

lock (this) {
    if (AnalysisVersion != _expectedParse) {
        return;
    }
    _analysisTcs.TrySetResult(Analysis);
}
RaiseNewAnalysis(); 

}
OnDocumentChangeProcessingComplete(doc, t.Result as VersionCookie, enqueueForAnalysis, priority, p);
}).DoNotWait();
await OnDocumentChangeProcessingCompleteAsync(doc, cookie as VersionCookie, enqueueForAnalysis, priority, p);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Before the change, EnqueueItem has been completed before ParseQueue.EnqueueAsync was completed. Now it waits for the parse to finish. Also, before the change exceptions from ParseQueue.Enqueue were logged but didn't affect the caller. Right now, exception will be propagated up to the DidChangeTextDocument.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I can make it about the same so we don't change logic too much. What concerns me is that pending disposable in finally. Would it be disposed before cookieTask actually starts?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe it should be

catch {
      pending?.Dispose();
      throw
  }

}
}

// The call must be fire and forget, but should not be yielding.
// It is called from DidChangeTextDocument which must fully finish
// since otherwise Complete() may come before the change is enqueued
// for processing and the completion list will be driven off the stale data.
var p = pending;
cookieTask.ContinueWith(t => {
return cookieTask.ContinueWith(async t => {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It looks like we should do

cookieTask.ContinueWith(...).DoNotWait();
return cookieTask;

But if it is working as it is, let's leave it as it is :)

@@ -100,5 +101,10 @@ internal sealed class ProjectFiles : IDisposable {
throw new ObjectDisposedException(nameof(ProjectFiles));
}
}

#region IEnumerable<IProjectEntry>
public IEnumerator<IProjectEntry> GetEnumerator() => All.GetEnumerator();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we use it anywhere?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Used to be foreach (var pf in ProjectFiles.All), enumerabe makes it simpler

@@ -121,6 +122,7 @@ internal sealed class EditorFile {
})
));

cancellationToken.ThrowIfCancellationRequested();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe check it before doc.UpdateDocument?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure

jakebailey pushed a commit to jakebailey/python-language-server that referenced this pull request Nov 1, 2019
Fix wait for analysis complete, fix tests and avoid reload on all config changes
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants