Skip to content
This repository was archived by the owner on Nov 4, 2024. It is now read-only.

Commit c0f34ef

Browse files
author
Mikhail Arkhipov
authored
Optimize references removal (microsoft#925)
* Fix microsoft#668 (partial) * Tests * Revert "Tests" This reverts commit 7ffc9db. * Exp * Limit concurrency * Concurrency limit * Drop cache after analysis * Fix regression * Fix test * Optimize references removal * Dead code
1 parent 33199f8 commit c0f34ef

File tree

2 files changed

+91
-5
lines changed

2 files changed

+91
-5
lines changed

src/Analysis/Ast/Impl/Modules/PythonModule.cs

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -403,10 +403,18 @@ public void NotifyAnalysisBegins() {
403403
lock (AnalysisLock) {
404404
if (_updated) {
405405
_updated = false;
406-
var analyzer = Services.GetService<IPythonAnalyzer>();
407-
foreach (var gs in analyzer.LoadedModules.Select(m => m.GlobalScope).OfType<IScope>().ExcludeDefault()) {
408-
foreach (var v in gs.TraverseDepthFirst(c => c.Children).SelectMany(s => s.Variables)) {
409-
v.RemoveReferences(this);
406+
// In all variables find those imported, then traverse imported modules
407+
// and remove references to this module. If variable refers to a module,
408+
// recurse into module but only process global scope.
409+
var importedVariables = ((IScope)GlobalScope)
410+
.TraverseDepthFirst(c => c.Children)
411+
.SelectMany(s => s.Variables)
412+
.Where(v => v.Source == VariableSource.Import);
413+
414+
foreach (var v in importedVariables) {
415+
v.RemoveReferences(this);
416+
if(v.Value is IPythonModule module) {
417+
RemoveReferencesInModule(module);
410418
}
411419
}
412420
}
@@ -448,6 +456,12 @@ public Task<IDocumentAnalysis> GetAnalysisAsync(int waitTime = 200, Cancellation
448456

449457
#endregion
450458

459+
private void RemoveReferencesInModule(IPythonModule module) {
460+
foreach (var v in module.GlobalScope.Variables) {
461+
v.RemoveReferences(this);
462+
}
463+
}
464+
451465
private string TryGetDocFromModuleInitFile() {
452466
if (string.IsNullOrEmpty(FilePath) || !FileSystem.FileExists(FilePath)) {
453467
return string.Empty;

src/LanguageServer/Test/ReferencesTests.cs

Lines changed: 73 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -241,7 +241,7 @@ def func(x):
241241
var uri1 = TestData.GetDefaultModuleUri();
242242
var uri2 = TestData.GetNextModuleUri();
243243

244-
var code2 = $@"
244+
const string code2 = @"
245245
from module import x, y
246246
a = x
247247
b = y
@@ -284,6 +284,78 @@ def func(x):
284284
refs[0].uri.Should().Be(uri1);
285285
}
286286

287+
[TestMethod, Priority(0)]
288+
public async Task RemoveReferenceNested() {
289+
const string code1 = @"
290+
x = 1
291+
292+
def func(x):
293+
return x
294+
295+
y = func(x)
296+
x = 2
297+
";
298+
const string code2 = @"
299+
from module import x, y
300+
a = x
301+
b = y
302+
";
303+
var code3 = @"
304+
from module1 import x, y
305+
a = x
306+
b = y
307+
";
308+
var uri1 = TestData.GetDefaultModuleUri();
309+
var uri2 = TestData.GetNextModuleUri();
310+
var uri3 = TestData.GetNextModuleUri();
311+
312+
await CreateServicesAsync(PythonVersions.LatestAvailable3X, uri1.AbsolutePath);
313+
314+
var rdt = Services.GetService<IRunningDocumentTable>();
315+
var doc1 = rdt.OpenDocument(uri1, code1);
316+
var doc2 = rdt.OpenDocument(uri2, code2);
317+
var doc3 = rdt.OpenDocument(uri3, code3);
318+
319+
var analysis = await GetDocumentAnalysisAsync(doc1);
320+
321+
var rs = new ReferenceSource(Services);
322+
var refs = await rs.FindAllReferencesAsync(analysis.Document.Uri, new SourceLocation(7, 1), ReferenceSearchOptions.All);
323+
324+
refs.Should().HaveCount(5);
325+
refs[0].range.Should().Be(6, 0, 6, 1);
326+
refs[0].uri.Should().Be(uri1);
327+
refs[1].range.Should().Be(1, 22, 1, 23);
328+
refs[1].uri.Should().Be(uri2);
329+
refs[2].range.Should().Be(3, 4, 3, 5);
330+
refs[2].uri.Should().Be(uri2);
331+
refs[3].range.Should().Be(1, 23, 1, 24);
332+
refs[3].uri.Should().Be(uri3);
333+
refs[4].range.Should().Be(3, 4, 3, 5);
334+
refs[4].uri.Should().Be(uri3);
335+
336+
doc3.Update(new[] {
337+
new DocumentChange {
338+
InsertedText = string.Empty,
339+
ReplacedSpan = new SourceSpan(4, 1, 4, 6)
340+
},
341+
new DocumentChange {
342+
InsertedText = string.Empty,
343+
ReplacedSpan = new SourceSpan(2, 22, 2, 25)
344+
}
345+
});
346+
await GetDocumentAnalysisAsync(doc3);
347+
348+
refs = await rs.FindAllReferencesAsync(analysis.Document.Uri, new SourceLocation(7, 1), ReferenceSearchOptions.All);
349+
350+
refs.Should().HaveCount(3);
351+
refs[0].range.Should().Be(6, 0, 6, 1);
352+
refs[0].uri.Should().Be(uri1);
353+
refs[1].range.Should().Be(1, 22, 1, 23);
354+
refs[1].uri.Should().Be(uri2);
355+
refs[2].range.Should().Be(3, 4, 3, 5);
356+
refs[2].uri.Should().Be(uri2);
357+
}
358+
287359
[TestMethod, Priority(0)]
288360
public async Task UpdateReferencesOnEdit() {
289361
const string code = @"

0 commit comments

Comments
 (0)