public async Task GenericClassMethod() { const string code = @" from typing import TypeVar, Generic _T = TypeVar('_T') class Box(Generic[_T]): def get(self) -> _T: return self.v boxedint = Box(1234) x = boxedint.get() boxedstr = Box('str') y = boxedstr.get() "; var analysis = await GetAnalysisAsync(code, PythonVersions.LatestAvailable3X); var src = new SignatureSource(new PlainTextDocumentationSource()); var sig = src.GetSignature(analysis, new SourceLocation(11, 18)); sig.signatures.Should().NotBeNull(); sig.signatures.Length.Should().Be(1); sig.signatures[0].label.Should().Be("get() -> int"); sig = src.GetSignature(analysis, new SourceLocation(14, 18)); sig.signatures.Should().NotBeNull(); sig.signatures.Length.Should().Be(1); sig.signatures[0].label.Should().Be("get() -> str"); }
public async Task MethodSignature(bool clientSupportsParameterLabelOffsets) { const string code = @" class C: def method(self, a:int, b) -> float: return 1.0 C().method() "; var analysis = await GetAnalysisAsync(code); var src = new SignatureSource(new PlainTextDocumentationSource(), clientSupportsParameterLabelOffsets); var sig = src.GetSignature(analysis, new SourceLocation(6, 12)); sig.activeSignature.Should().Be(0); sig.activeParameter.Should().Be(0); sig.signatures.Length.Should().Be(1); sig.signatures[0].label.Should().Be("method(a: int, b) -> float"); var labels = sig.signatures[0].parameters.Select(p => p.label); if (clientSupportsParameterLabelOffsets) { var parameterSpans = labels.OfType <int[]>().SelectMany(x => x); parameterSpans.Should().ContainInOrder(7, 8, 15, 16); } else { var parameterSpans = labels.OfType <string>(); parameterSpans.Should().ContainInOrder("a", "b"); } }
public async Task ForwardRefMethod() { const string code = @" class Box(): def get(self) -> 'int': return self.v boxedint = Box() x = boxedint.get() def get() -> 'int': pass y = get() "; var analysis = await GetAnalysisAsync(code, PythonVersions.LatestAvailable3X); var src = new SignatureSource(new PlainTextDocumentationSource()); var sig = src.GetSignature(analysis, new SourceLocation(7, 18)); sig.signatures.Should().NotBeNull(); sig.signatures.Length.Should().Be(1); sig.signatures[0].label.Should().Be("get() -> int"); sig = src.GetSignature(analysis, new SourceLocation(12, 9)); sig.signatures.Should().NotBeNull(); sig.signatures.Length.Should().Be(1); sig.signatures[0].label.Should().Be("get() -> int"); }
public async Task PositionalOnly() { const string code = @" def f(a, b, /, c, d, *, e, f): pass f() "; var analysis = await GetAnalysisAsync(code, PythonVersions.LatestAvailable3X); var src = new SignatureSource(new PlainTextDocumentationSource()); var sig = src.GetSignature(analysis, new SourceLocation(5, 3)); sig.signatures.Should().NotBeNull(); sig.signatures.Length.Should().Be(1); sig.signatures[0].label.Should().Be("f(a, b, /, c, d, *, e, f)"); }
public async Task UnknownForwardRefParam() { const string code = @" def get(v: 'tmp[unknown_type]') -> 'unknown_type': pass y = get() "; var analysis = await GetAnalysisAsync(code, PythonVersions.LatestAvailable3X); var src = new SignatureSource(new PlainTextDocumentationSource()); var sig = src.GetSignature(analysis, new SourceLocation(5, 9)); sig.signatures.Should().NotBeNull(); sig.signatures.Length.Should().Be(1); sig.signatures[0].label.Should().Be("get(v) -> 'unknown_type'"); }
public async Task ForwardRefUnboundFunction() { const string code = @" def get() -> 'int': pass y = get() "; var analysis = await GetAnalysisAsync(code, PythonVersions.LatestAvailable3X); var src = new SignatureSource(new PlainTextDocumentationSource()); var sig = src.GetSignature(analysis, new SourceLocation(5, 9)); sig.signatures.Should().NotBeNull(); sig.signatures.Length.Should().Be(1); sig.signatures[0].label.Should().Be("get() -> int"); }
public async Task GenericUnboundForwardRefFunction() { const string code = @" from typing import Dict def tmp(v: 'Dict[str, int]') -> 'Dict[str, int]': pass h = tmp() "; var analysis = await GetAnalysisAsync(code, PythonVersions.LatestAvailable3X); var src = new SignatureSource(new PlainTextDocumentationSource()); var sig = src.GetSignature(analysis, new SourceLocation(5, 9)); sig.signatures.Should().NotBeNull(); sig.signatures.Length.Should().Be(1); sig.signatures[0].label.Should().Be("tmp(v: Dict[str, int]) -> Dict[str, int]"); }
public async Task DefaultValues() { const string code = @" def hello(a, b=100, c={'a':4}): return a + b hello() "; var analysis = await GetAnalysisAsync(code, PythonVersions.LatestAvailable3X); var src = new SignatureSource(new PlainTextDocumentationSource()); var sig = src.GetSignature(analysis, new SourceLocation(5, 7)); sig.signatures.Should().NotBeNull(); sig.signatures.Length.Should().Be(1); sig.signatures[0].label.Should().Be("hello(a, b=100, c={'a':4})"); }
public async Task ClassInitializer() { const string code = @" class C: def __init__(self, a:int, b): pass C() "; var analysis = await GetAnalysisAsync(code); var src = new SignatureSource(new PlainTextDocumentationSource()); var sig = src.GetSignature(analysis, new SourceLocation(6, 3)); sig.activeSignature.Should().Be(0); sig.activeParameter.Should().Be(0); sig.signatures.Length.Should().Be(1); sig.signatures[0].label.Should().Be("C(a: int, b)"); }
public async Task MethodSignature() { const string code = @" class C: def method(self, a:int, b) -> float: return 1.0 C().method() "; var analysis = await GetAnalysisAsync(code); var src = new SignatureSource(new PlainTextDocumentationSource()); var sig = src.GetSignature(analysis, new SourceLocation(6, 12)); sig.activeSignature.Should().Be(0); sig.activeParameter.Should().Be(0); sig.signatures.Length.Should().Be(1); sig.signatures[0].label.Should().Be("method(a: int, b) -> float"); }
public async Task ImportedClassInitializer() { const string module1Code = @" class C: def __init__(self, a:int, b): pass "; const string appCode = @" import module1 module1.C() "; var module1Uri = TestData.GetTestSpecificUri("module1.py"); var appUri = TestData.GetTestSpecificUri("app.py"); var root = Path.GetDirectoryName(appUri.AbsolutePath); await CreateServicesAsync(root, PythonVersions.LatestAvailable3X); var rdt = Services.GetService <IRunningDocumentTable>(); var analyzer = Services.GetService <IPythonAnalyzer>(); rdt.OpenDocument(module1Uri, module1Code); var app = rdt.OpenDocument(appUri, appCode); await analyzer.WaitForCompleteAnalysisAsync(); var analysis = await app.GetAnalysisAsync(-1); var src = new SignatureSource(new PlainTextDocumentationSource()); var sig = src.GetSignature(analysis, new SourceLocation(4, 11)); sig.activeSignature.Should().Be(0); sig.activeParameter.Should().Be(0); sig.signatures.Length.Should().Be(1); sig.signatures[0].label.Should().Be("C(a: int, b)"); }
public async Task ForwardRefNestedQuotedGenericReturnValue() { const string code = @" from typing import List, Sequence class Box(): def get(self, x: 'Sequence[List[int]]') -> 'Sequence[List[int]]': return self.v boxedint = Box() x = boxedint.get(5) "; var analysis = await GetAnalysisAsync(code, PythonVersions.LatestAvailable3X); var src = new SignatureSource(new PlainTextDocumentationSource()); var sig = src.GetSignature(analysis, new SourceLocation(9, 19)); sig.signatures.Should().NotBeNull(); sig.signatures.Length.Should().Be(1); sig.signatures[0].label.Should().Be("get(x: Sequence[List[int]]) -> Sequence[List[int]]"); }
public async Task ForwardRefQuotedGenericTypeParameter() { const string code = @" from typing import List class X: ... class Box(): def get(self) -> List['X']: return self.v boxedint = Box() x = boxedint.get() "; var analysis = await GetAnalysisAsync(code, PythonVersions.LatestAvailable3X); var src = new SignatureSource(new PlainTextDocumentationSource()); var sig = src.GetSignature(analysis, new SourceLocation(11, 18)); sig.signatures.Should().NotBeNull(); sig.signatures.Length.Should().Be(1); sig.signatures[0].label.Should().Be("get() -> List[X]"); }
public async Task InitializedAsync(InitializedParams @params, CancellationToken cancellationToken = default, IReadOnlyList <string> userConfiguredPaths = null) { var initializationOptions = _initParams?.initializationOptions; _services.AddService(new DiagnosticsService(_services)); _analyzer = new PythonAnalyzer(_services); _services.AddService(_analyzer); _analyzer.AnalysisComplete += OnAnalysisComplete; _disposableBag.Add(() => _analyzer.AnalysisComplete -= OnAnalysisComplete); _services.AddService(new RunningDocumentTable(_services)); _rdt = _services.GetService <IRunningDocumentTable>(); var interpeterPath = initializationOptions?.interpreter.properties?.InterpreterPath; Version version = null; if (!string.IsNullOrWhiteSpace(interpeterPath)) { Version.TryParse(initializationOptions?.interpreter.properties?.Version, out version); } else { var fs = _services.GetService <IFileSystem>(); var exePath = PathUtils.LookPath(fs, "python"); if (exePath != null && TryGetPythonVersion(exePath, out version)) { _log?.Log(TraceEventType.Information, Resources.UsingPythonFromPATH); interpeterPath = exePath; } else { interpeterPath = null; } } var configuration = new InterpreterConfiguration( interpreterPath: interpeterPath, version: version ); //_services.AddService(new ModuleDatabase(_services)); var typeshedPath = initializationOptions?.typeStubSearchPaths.FirstOrDefault(); userConfiguredPaths = userConfiguredPaths ?? initializationOptions?.searchPaths; _interpreter = await PythonInterpreter.CreateAsync(configuration, Root, _services, typeshedPath, userConfiguredPaths.ToImmutableArray(), cancellationToken); _log?.Log(TraceEventType.Information, string.IsNullOrEmpty(_interpreter.Configuration.InterpreterPath) ? Resources.InitializingForGenericInterpreter : Resources.InitializingForPythonInterpreter.FormatInvariant(_interpreter.Configuration.InterpreterPath)); var fileSystem = _services.GetService <IFileSystem>(); _indexManager = new IndexManager(fileSystem, _interpreter.LanguageVersion, Root, initializationOptions?.includeFiles, initializationOptions?.excludeFiles, _services.GetService <IIdleTimeService>()); _indexManager.IndexWorkspace().DoNotWait(); _analyzer.AnalysisComplete += IndexLibraries; _disposableBag.Add(() => _analyzer.AnalysisComplete -= IndexLibraries); _services.AddService(_indexManager); _disposableBag.Add(_indexManager); var textDocCaps = _initParams?.capabilities?.textDocument; _completionSource = new CompletionSource( ChooseDocumentationSource(textDocCaps?.completion?.completionItem?.documentationFormat), Settings.completion, Services ); _hoverSource = new HoverSource( ChooseDocumentationSource(textDocCaps?.hover?.contentFormat) ); var sigInfo = textDocCaps?.signatureHelp?.signatureInformation; _signatureSource = new SignatureSource( ChooseDocumentationSource(sigInfo?.documentationFormat), sigInfo?.parameterInformation?.labelOffsetSupport == true ); _initialized = true; }
public async Task <InitializeResult> InitializeAsync(InitializeParams @params, CancellationToken cancellationToken) { _disposableBag.ThrowIfDisposed(); _clientCaps = @params.capabilities; _log = _services.GetService <ILogger>(); _services.AddService(new DiagnosticsService(_services)); var analyzer = new PythonAnalyzer(_services); _services.AddService(analyzer); _services.AddService(new RunningDocumentTable(_services)); _rdt = _services.GetService <IRunningDocumentTable>(); _rootDir = @params.rootUri != null? @params.rootUri.ToAbsolutePath() : @params.rootPath; if (_rootDir != null) { _rootDir = PathUtils.NormalizePath(_rootDir); _rootDir = PathUtils.TrimEndSeparator(_rootDir); } Version.TryParse(@params.initializationOptions.interpreter.properties?.Version, out var version); var configuration = new InterpreterConfiguration(null, null, interpreterPath: @params.initializationOptions.interpreter.properties?.InterpreterPath, moduleCachePath: @params.initializationOptions.interpreter.properties?.DatabasePath, version: version ) { // 1) Split on ';' to support older VS Code extension versions which send paths as a single entry separated by ';'. TODO: Eventually remove. // 2) Normalize paths. // 3) If a path isn't rooted, then root it relative to the workspace root. If _rootDir is null, then accept the path as-is. // 4) Trim off any ending separator for a consistent style. // 5) Filter out any entries which are the same as the workspace root; they are redundant. Also ignore "/" to work around the extension (for now). // 6) Remove duplicates. SearchPaths = @params.initializationOptions.searchPaths .Select(p => p.Split(';', StringSplitOptions.RemoveEmptyEntries)).SelectMany() .Select(PathUtils.NormalizePath) .Select(p => _rootDir == null || Path.IsPathRooted(p) ? p : Path.GetFullPath(p, _rootDir)) .Select(PathUtils.TrimEndSeparator) .Where(p => !string.IsNullOrWhiteSpace(p) && p != "/" && !p.PathEquals(_rootDir)) .Distinct(PathEqualityComparer.Instance) .ToList(), TypeshedPath = @params.initializationOptions.typeStubSearchPaths.FirstOrDefault() }; _interpreter = await PythonInterpreter.CreateAsync(configuration, _rootDir, _services, cancellationToken); _services.AddService(_interpreter); var fileSystem = _services.GetService <IFileSystem>(); _indexManager = new IndexManager(fileSystem, _interpreter.LanguageVersion, _rootDir, @params.initializationOptions.includeFiles, @params.initializationOptions.excludeFiles, _services.GetService <IIdleTimeService>()); _indexManager.IndexWorkspace().DoNotWait(); _services.AddService(_indexManager); _disposableBag.Add(_indexManager); DisplayStartupInfo(); _completionSource = new CompletionSource( ChooseDocumentationSource(_clientCaps?.textDocument?.completion?.completionItem?.documentationFormat), Settings.completion ); _hoverSource = new HoverSource( ChooseDocumentationSource(_clientCaps?.textDocument?.hover?.contentFormat) ); _signatureSource = new SignatureSource( ChooseDocumentationSource(_clientCaps?.textDocument?.signatureHelp?.signatureInformation?.documentationFormat) ); return(GetInitializeResult()); }
public async Task <InitializeResult> InitializeAsync(InitializeParams @params, CancellationToken cancellationToken) { _disposableBag.ThrowIfDisposed(); _clientCaps = @params.capabilities; _log = _services.GetService <ILogger>(); _services.AddService(new DiagnosticsService(_services)); var analyzer = new PythonAnalyzer(_services); _services.AddService(analyzer); _services.AddService(new RunningDocumentTable(_services)); _rdt = _services.GetService <IRunningDocumentTable>(); // TODO: multi-root workspaces. var rootDir = @params.rootUri != null? @params.rootUri.ToAbsolutePath() : PathUtils.NormalizePath(@params.rootPath); Version.TryParse(@params.initializationOptions.interpreter.properties?.Version, out var version); var configuration = new InterpreterConfiguration(null, null, interpreterPath: @params.initializationOptions.interpreter.properties?.InterpreterPath, moduleCachePath: @params.initializationOptions.interpreter.properties?.DatabasePath, version: version ) { // TODO: Remove this split once the extension is updated and no longer passes the interpreter search paths directly. // This is generally harmless to keep around. SearchPaths = @params.initializationOptions.searchPaths.Select(p => p.Split(';', StringSplitOptions.RemoveEmptyEntries)).SelectMany().ToList(), TypeshedPath = @params.initializationOptions.typeStubSearchPaths.FirstOrDefault() }; _interpreter = await PythonInterpreter.CreateAsync(configuration, rootDir, _services, cancellationToken); _services.AddService(_interpreter); var fileSystem = _services.GetService <IFileSystem>(); _indexManager = new IndexManager(fileSystem, _interpreter.LanguageVersion, rootDir, @params.initializationOptions.includeFiles, @params.initializationOptions.excludeFiles, _services.GetService <IIdleTimeService>()); _indexManager.IndexWorkspace().DoNotWait(); _services.AddService(_indexManager); _disposableBag.Add(_indexManager); DisplayStartupInfo(); _completionSource = new CompletionSource( ChooseDocumentationSource(_clientCaps?.textDocument?.completion?.completionItem?.documentationFormat), Settings.completion ); _hoverSource = new HoverSource( ChooseDocumentationSource(_clientCaps?.textDocument?.hover?.contentFormat) ); _signatureSource = new SignatureSource( ChooseDocumentationSource(_clientCaps?.textDocument?.signatureHelp?.signatureInformation?.documentationFormat) ); return(GetInitializeResult()); }
public async Task <InitializeResult> InitializeAsync(InitializeParams @params, CancellationToken cancellationToken) { _disposableBag.ThrowIfDisposed(); _clientCaps = @params.capabilities; _log = _services.GetService <ILogger>(); _services.AddService(new DiagnosticsService(_services)); var cacheFolderPath = @params.initializationOptions.cacheFolderPath; var fs = _services.GetService <IFileSystem>(); if (cacheFolderPath != null && !fs.DirectoryExists(cacheFolderPath)) { _log?.Log(TraceEventType.Warning, Resources.Error_InvalidCachePath); cacheFolderPath = null; } var analyzer = new PythonAnalyzer(_services, cacheFolderPath); _services.AddService(analyzer); analyzer.AnalysisComplete += OnAnalysisComplete; _disposableBag.Add(() => analyzer.AnalysisComplete -= OnAnalysisComplete); _services.AddService(new RunningDocumentTable(_services)); _rdt = _services.GetService <IRunningDocumentTable>(); _rootDir = @params.rootUri != null? @params.rootUri.ToAbsolutePath() : @params.rootPath; if (_rootDir != null) { _rootDir = PathUtils.NormalizePathAndTrim(_rootDir); } Version.TryParse(@params.initializationOptions.interpreter.properties?.Version, out var version); var configuration = new InterpreterConfiguration(null, null, interpreterPath: @params.initializationOptions.interpreter.properties?.InterpreterPath, version: version ) { // Split on ';' to support older VS Code extension versions which send paths as a single entry separated by ';'. TODO: Eventually remove. // Note that the actual classification of these paths as user/library is done later in MainModuleResolution.ReloadAsync. SearchPaths = @params.initializationOptions.searchPaths .Select(p => p.Split(';', StringSplitOptions.RemoveEmptyEntries)).SelectMany() .ToList(), TypeshedPath = @params.initializationOptions.typeStubSearchPaths.FirstOrDefault() }; _interpreter = await PythonInterpreter.CreateAsync(configuration, _rootDir, _services, cancellationToken); _services.AddService(_interpreter); var fileSystem = _services.GetService <IFileSystem>(); _indexManager = new IndexManager(fileSystem, _interpreter.LanguageVersion, _rootDir, @params.initializationOptions.includeFiles, @params.initializationOptions.excludeFiles, _services.GetService <IIdleTimeService>()); _indexManager.IndexWorkspace().DoNotWait(); _services.AddService(_indexManager); _disposableBag.Add(_indexManager); DisplayStartupInfo(); _completionSource = new CompletionSource( ChooseDocumentationSource(_clientCaps?.textDocument?.completion?.completionItem?.documentationFormat), Settings.completion ); _hoverSource = new HoverSource( ChooseDocumentationSource(_clientCaps?.textDocument?.hover?.contentFormat) ); var sigInfo = _clientCaps?.textDocument?.signatureHelp?.signatureInformation; _signatureSource = new SignatureSource( ChooseDocumentationSource(sigInfo?.documentationFormat), sigInfo?.parameterInformation?.labelOffsetSupport == true ); return(GetInitializeResult()); }
public async Task InitializedAsync(InitializedParams @params, CancellationToken cancellationToken = default, IReadOnlyList <string> userConfiguredPaths = null) { var initializationOptions = _initParams?.initializationOptions; _services.AddService(new DiagnosticsService(_services)); var cacheFolderPath = initializationOptions?.cacheFolderPath; var fs = _services.GetService <IFileSystem>(); if (cacheFolderPath != null && !fs.DirectoryExists(cacheFolderPath)) { _log?.Log(TraceEventType.Warning, Resources.Error_InvalidCachePath); cacheFolderPath = null; } var analyzer = new PythonAnalyzer(_services, cacheFolderPath); _services.AddService(analyzer); analyzer.AnalysisComplete += OnAnalysisComplete; _disposableBag.Add(() => analyzer.AnalysisComplete -= OnAnalysisComplete); _services.AddService(new RunningDocumentTable(_services)); _rdt = _services.GetService <IRunningDocumentTable>(); Version.TryParse(initializationOptions?.interpreter.properties?.Version, out var version); var configuration = new InterpreterConfiguration(null, null, interpreterPath: initializationOptions?.interpreter.properties?.InterpreterPath, version: version ); var typeshedPath = initializationOptions?.typeStubSearchPaths.FirstOrDefault(); userConfiguredPaths = userConfiguredPaths ?? initializationOptions?.searchPaths; _interpreter = await PythonInterpreter.CreateAsync(configuration, Root, _services, typeshedPath, userConfiguredPaths.ToImmutableArray(), cancellationToken); _services.AddService(_interpreter); _log?.Log(TraceEventType.Information, string.IsNullOrEmpty(_interpreter.Configuration.InterpreterPath) ? Resources.InitializingForGenericInterpreter : Resources.InitializingForPythonInterpreter.FormatInvariant(_interpreter.Configuration.InterpreterPath)); var fileSystem = _services.GetService <IFileSystem>(); _indexManager = new IndexManager(fileSystem, _interpreter.LanguageVersion, Root, initializationOptions?.includeFiles, initializationOptions?.excludeFiles, _services.GetService <IIdleTimeService>()); _indexManager.IndexWorkspace().DoNotWait(); _services.AddService(_indexManager); _disposableBag.Add(_indexManager); var textDocCaps = _initParams?.capabilities?.textDocument; _completionSource = new CompletionSource( ChooseDocumentationSource(textDocCaps?.completion?.completionItem?.documentationFormat), Settings.completion ); _hoverSource = new HoverSource( ChooseDocumentationSource(textDocCaps?.hover?.contentFormat) ); var sigInfo = textDocCaps?.signatureHelp?.signatureInformation; _signatureSource = new SignatureSource( ChooseDocumentationSource(sigInfo?.documentationFormat), sigInfo?.parameterInformation?.labelOffsetSupport == true ); }