Skip to content
This repository was archived by the owner on Apr 14, 2022. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion src/Analysis/Engine/Impl/Analyzer/DDG.cs
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,6 @@ public void Analyze(Deque<AnalysisUnit> queue, CancellationToken cancel, Action<
SetCurrentUnit(_unit);
AnalyzedEntries.Add(_unit.ProjectEntry);
_unit.Analyze(this, cancel);
_unit.ProjectEntry.SetCompleteAnalysis();
}

if (reportQueueSize != null) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,6 @@

namespace Microsoft.PythonTools.Analysis.Infrastructure {
internal static class TaskCompletionSourceExtensions {
public static void TrySetResultOnThreadPool<T>(this TaskCompletionSource<T> taskCompletionSource, T result) {
if (!taskCompletionSource.Task.IsCompleted) {
ThreadPool.QueueUserWorkItem(new TrySetResultStateAction<T>(taskCompletionSource, result).Invoke);
}
}

public static CancellationTokenRegistration RegisterForCancellation<T>(this TaskCompletionSource<T> taskCompletionSource, CancellationToken cancellationToken)
=> taskCompletionSource.RegisterForCancellation(-1, cancellationToken);

Expand Down
2 changes: 2 additions & 0 deletions src/Analysis/Engine/Impl/Infrastructure/PathUtils.cs
Original file line number Diff line number Diff line change
Expand Up @@ -362,6 +362,8 @@ public static FileStream OpenWithRetry(string file, FileMode mode, FileAccess ac
return null;
} catch (DirectoryNotFoundException) when (!create) {
return null;
} catch (UnauthorizedAccessException) {
Thread.Sleep(10);
} catch (IOException) {
if (create) {
var dir = Path.GetDirectoryName(file);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ class AstScrapedPythonModule : IPythonModule

public AstScrapedPythonModule(string name, string filePath) {
Name = name ?? throw new ArgumentNullException(nameof(name));
ParseErrors = Enumerable.Empty<string>();
_filePath = filePath;
_members = new Dictionary<string, IMember>();
_scraped = false;
Expand Down
9 changes: 6 additions & 3 deletions src/Analysis/Engine/Impl/ProjectEntry.cs
Original file line number Diff line number Diff line change
Expand Up @@ -152,19 +152,22 @@ public IPythonParse GetCurrentParse() {
}
}, cancellationToken);

return Task.WhenAny(timeoutTask, _analysisTcs.Task).Unwrap();
return Task.WhenAny(timeoutTask, task).Unwrap();
}

internal void SetCompleteAnalysis() {
lock (this) {
_analysisTcs.TrySetResultOnThreadPool(Analysis);
_analysisTcs.TrySetResult(Analysis);
}
}

internal void ResetCompleteAnalysis() {
TaskCompletionSource<ModuleAnalysis> analysisTcs;
lock (this) {
_analysisTcs = new TaskCompletionSource<ModuleAnalysis>();
analysisTcs = _analysisTcs;
_analysisTcs = new TaskCompletionSource<ModuleAnalysis>(TaskCreationOptions.RunContinuationsAsynchronously);
}
analysisTcs?.TrySetCanceled();
}

public void SetCurrentParse(PythonAst tree, IAnalysisCookie cookie, bool notify = true) {
Expand Down
1 change: 1 addition & 0 deletions src/Analysis/Engine/Impl/PythonAnalyzer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -953,6 +953,7 @@ public void AnalyzeQueuedEntries(CancellationToken cancel) {
var ddg = new DDG();
ddg.Analyze(Queue, cancel, _reportQueueSize, _reportQueueInterval);
foreach (var entry in ddg.AnalyzedEntries) {
entry.SetCompleteAnalysis();
entry.RaiseOnNewAnalysis();
}
}
Expand Down
19 changes: 6 additions & 13 deletions src/Analysis/Engine/Test/AnalysisTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1489,21 +1489,14 @@ print abc
}
}

[TestMethod, Priority(0)]
public async Task LambdaInComprehension() {
[DataRow(PythonLanguageVersion.V27)]
[DataRow(PythonLanguageVersion.V31)]
[DataRow(PythonLanguageVersion.V33)]
[DataTestMethod, Priority(0)]
public async Task LambdaInComprehension(PythonLanguageVersion version) {
var text = "x = [(lambda a:[a**i for i in range(a+1)])(j) for j in range(5)]";

using (var server = await CreateServerAsync(PythonVersions.Required_Python27X)) {
var analysis = await server.OpenDefaultDocumentAndGetAnalysisAsync(text);
analysis.Should().HaveVariable("x").OfType(BuiltinTypeId.List);
}

using (var server = await CreateServerAsync(PythonVersions.Required_Python31X)) {
var analysis = await server.OpenDefaultDocumentAndGetAnalysisAsync(text);
analysis.Should().HaveVariable("x").OfType(BuiltinTypeId.List);
}

using (var server = await CreateServerAsync(PythonVersions.Required_Python33X)) {
using (var server = await CreateServerAsync(PythonVersions.GetRequiredCPythonConfiguration(version))) {
var analysis = await server.OpenDefaultDocumentAndGetAnalysisAsync(text);
analysis.Should().HaveVariable("x").OfType(BuiltinTypeId.List);
}
Expand Down
3 changes: 3 additions & 0 deletions src/Analysis/Engine/Test/PythonVersions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,9 @@ public static class PythonVersions {
Python27,
Python27_x64).First();

public static InterpreterConfiguration GetRequiredCPythonConfiguration(PythonLanguageVersion version)
=> GetCPythonVersion(version, InterpreterArchitecture.x86) ?? GetCPythonVersion(version, InterpreterArchitecture.x64) ?? NotInstalled(version.ToString());

private static IEnumerable<InterpreterConfiguration> GetVersions(params InterpreterConfiguration[] configurations) => configurations.Where(v => v != null);

private static InterpreterConfiguration GetCPythonVersion(PythonLanguageVersion version, InterpreterArchitecture arch) {
Expand Down
4 changes: 2 additions & 2 deletions src/LanguageServer/Impl/LanguageServer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -562,12 +562,12 @@ private struct QueueItem {
public bool IsAwaitable { get; }

public QueueItem(bool isAwaitable, CancellationToken cancellationToken) {
_tcs = new TaskCompletionSource<IDisposable>();
_tcs = new TaskCompletionSource<IDisposable>(TaskCreationOptions.RunContinuationsAsynchronously);
IsAwaitable = isAwaitable;
_tcs.RegisterForCancellation(cancellationToken).UnregisterOnCompletion(_tcs.Task);
}

public void SetResult(IDisposable disposable) => _tcs.TrySetResultOnThreadPool(disposable);
public void SetResult(IDisposable disposable) => _tcs.TrySetResult(disposable);
}

private class PrioritizerDisposable : IDisposable {
Expand Down
2 changes: 1 addition & 1 deletion src/UnitTests/Core/Impl/TestData.cs
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ private static string CalculateTestDataRoot() {
if (Directory.Exists(path)) {
foreach (var landmark in new[] {
"TestData",
@"Python\Tests\TestData"
@"src\UnitTests\TestData"
}) {
var candidate = PathUtils.GetAbsoluteDirectoryPath(path, landmark);
if (Directory.Exists(candidate)) {
Expand Down
27 changes: 27 additions & 0 deletions src/UnitTests/TestData/AstAnalysis/Classes.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
class C1:
"""C1"""
pass

class C2(object): pass
class C3(C2): pass
class C4(C1, C2, C3): pass

C5 = C1

if True:
class D: pass

if False:
class E: pass

class F1:
class F2: pass
class F3:
if True:
class F4: pass
else:
class F5: pass
F6 = C1

def f():
class X: pass
21 changes: 21 additions & 0 deletions src/UnitTests/TestData/AstAnalysis/Functions.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
def f():
'''f'''
pass
def f1(): pass

f2 = f

if True:
def g(): pass
else:
def h(): pass

class C:
def i(self): pass

def j(self):
def j2(self):
pass

class C2:
def k(self): pass
4 changes: 4 additions & 0 deletions src/UnitTests/TestData/AstAnalysis/Imports.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
from __future__ import absolute_imports

from sys import version_info
import a_made_up_module
6 changes: 6 additions & 0 deletions src/UnitTests/TestData/AstAnalysis/InstanceMethod.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
class C:
def f(self): pass

f1 = C.f
c = C()
f2 = c.f
15 changes: 15 additions & 0 deletions src/UnitTests/TestData/AstAnalysis/MultiValues.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
from Values import x, y, z
l = []
t = ()
s = {1}

XY = x
XY = y
XYZ = z
XYZ = XY

D = l
D = t
D = s
D = s # ensure multiple assignments do not clear it
from Values import D
4 changes: 4 additions & 0 deletions src/UnitTests/TestData/AstAnalysis/Package-stubs/Module.pyi
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@

class Class:
def typed_method(self, a : int) -> float: ...

4 changes: 4 additions & 0 deletions src/UnitTests/TestData/AstAnalysis/Package/Module.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@

class Class:
def untyped_method(self, a): pass
def inferred_method(self, a = 1): return 3.14
Empty file.
2 changes: 2 additions & 0 deletions src/UnitTests/TestData/AstAnalysis/ReturnAnnotations.pyi
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
def f(p : int = ...) -> int: ...
def g() -> str: ...
15 changes: 15 additions & 0 deletions src/UnitTests/TestData/AstAnalysis/ReturnValues.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
def r_a(a, b):
return a

def r_b(a, b):
return b

def r_str():
return ''

def r_object():
return object()

class A:
def r_A(self):
return type(self)()
4 changes: 4 additions & 0 deletions src/UnitTests/TestData/AstAnalysis/Stubs/Package/Module.pyi
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@

class Class:
def typed_method_2(self, a : int) -> float: ...

7 changes: 7 additions & 0 deletions src/UnitTests/TestData/AstAnalysis/TopLevelCompletions.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
x = 1
y = 'a'
z = b'b'

def f(a):

pass
17 changes: 17 additions & 0 deletions src/UnitTests/TestData/AstAnalysis/Values.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
x = 1
y = 'a'
z = b'b'
pi = 3.1415
l = []
t = ()
d = {}
s = {1}

X = x
Y = y
Z = z
PI = pi
L = l
T = t
D = d
S = s