This repository was archived by the owner on Apr 14, 2022. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 133
Async Indexer for new LanguageServer #558
Merged
Merged
Changes from 12 commits
Commits
Show all changes
128 commits
Select commit
Hold shift + click to select a range
b9b2554
IndexParser
brianbok cd1878d
Workspace Index Manage
brianbok 6a6a38d
Sorting using as configured on repo
brianbok 765653b
Removing unuseful empty property
brianbok b42d1f4
Moving directory reader to DirectoryInfo
brianbok 8a4d3d6
EnumerateFiles returns non-lazily
brianbok 33d768a
IndexParser throws FileNotFoundException
brianbok 1db8030
Events on files
brianbok 52dd812
Adding update event to index manager
brianbok 7c535c3
Async IndexParser
brianbok 05f3b4e
Async IndexManager
brianbok e5791d3
Check ArgumentNotNull using Diagnostics
brianbok b39ecf4
Async fixes
brianbok b767fbd
PythonVersions.LatestAvailable3X
brianbok 703de21
SymbolIndex fixes
brianbok af85966
SymbolIndex moving method from HierarchicalSymbol
brianbok 2c7dc2d
SymbolIndex corrections
brianbok 26bef41
SymbolIndex return style
brianbok 93d0464
Adding symbolIndex tests
brianbok c93c496
SymbolIndex return style
brianbok 28685c6
Using strings (plain path) instead of Uri
brianbok 0091933
More tests
brianbok c0a0387
More Uri to string type transforming
brianbok 6e4a0f5
Removing FileNotFoundException
brianbok 2e8ecdf
Single Line Return
brianbok 332358f
SymbolIndex Interface
brianbok 0048bf8
Fix AddRoot Test
brianbok 8f4343e
Disposing test fix
brianbok 36ed2e6
Blocking tests new fake
brianbok d58cc6b
Wait for AddRootTask in symbol querying
brianbok 2b3d450
Refactor tests and async add root
brianbok 36c6f85
Adding license header
brianbok a897585
TraverseBreadth variable rename
brianbok 7a2b9c3
deleting unused variable
brianbok b493294
Limiting API
brianbok fb7f8b3
Dispose test fixed
brianbok c4dcf23
Limiting API fix and styling
brianbok aedb206
Dispose testing
brianbok ac2098a
Merge branch 'master' into indexer
brianbok 1363efc
Moved everything into language server
brianbok d788f16
Tests refactor and connecting index to ls
brianbok 98c18aa
Adding file events
brianbok eb83604
async fix
brianbok 8b90ac7
Enumerable fix
brianbok fae4315
Delete copy of SymbolKind
brianbok d3f7da1
Revert "Delete copy of SymbolKind"
brianbok 9c0cb66
Deleting cast
brianbok 7d159bc
Async handling update of AST
brianbok a03c022
Versioned symbolindex
brianbok f6c854b
More versioned syncronization
brianbok 6cf5057
Removing event handler from doc
brianbok 4406a71
Safely executing matcher
brianbok ab650eb
Casting instead of 'as'
brianbok 2617c92
Cast
brianbok a62bf81
Returning on execute matcher
brianbok fa32e97
Adding empty workspace path check
brianbok b38e22b
Merge branch 'master' into indexer
brianbok 93e4d0d
Resolving race condition
brianbok 80d4d39
Async rename
brianbok 57d5ec8
Idling for index
brianbok 78f12c8
Adding delay to idling
brianbok 4a724c7
New async interface
brianbok 0f331c2
Passed more tests
brianbok d3b4761
Removing fields of test
brianbok 74e9bed
Passes every test again
brianbok 59bccd2
Working version
brianbok 0727619
Readonly fields
brianbok dc7b9eb
IndexParser refactoring
brianbok 935f6ba
IndexParser fixes
brianbok 6578616
No Tcs in IndexParser
brianbok e5bf1d8
Disposing streams
brianbok 108259f
Implementing tcs pattern
brianbok 1ff0935
PR comments fixes and typos
brianbok 0bc72c3
Rework of tcs in indexmanager
brianbok 2bba9dc
Delete unused variable
brianbok 9c5bb3a
Disposal check
brianbok 8de9f3a
TCS no reuse
brianbok e2bf0fe
Reorder layers
brianbok d04d375
Making interface for mostrecent symbols
brianbok f7f09fb
Copyright comments
brianbok 9952681
Unused var
brianbok 91b836c
Changin default delay
brianbok 29ecef7
Rename and style correct
brianbok 846f9a9
Getting rid of comment
brianbok 8b19e45
Fix limiting in workspace symbols query
brianbok bad44b1
Better disposal
brianbok 615e483
CancellationToken on querying
brianbok da29542
Walker walks annotated assignments
brianbok 5dd8e2c
Removing use of MaybeEnumerate in Traverse
brianbok 53766a6
Var instead of explicit Uri type
brianbok 5384825
Null check
brianbok 803b67f
max Concurrency handling
brianbok 66f7ae4
Merge branch 'master' into indexer
brianbok 8f704dd
Simple workspace querying
brianbok 17a9d0a
Simplifying disposing
brianbok 88ba453
Simplification
brianbok d9f8d57
Unused method
brianbok 2c60d4f
CancellationToken
brianbok 4825065
First state machine
brianbok fffb215
Tests for states of symbolIndex
brianbok 25b6590
Rename of state
brianbok 4a569ef
Comment on name of state
brianbok 08f6287
File Open FileSystem back to how it was
brianbok 05e711d
Server.Symbols
brianbok 9213ca7
Reference to deleted field
brianbok 0e3c42d
Extra new lines
brianbok 9fcdbe5
Extra spaces
brianbok 08858f0
Delete unused code
brianbok ccef536
Pattern matching in walker
brianbok d60b481
Merge branch 'master' into indexer
brianbok 121a8b0
Unused methods
brianbok c83112b
Using matcher for checking files in workspace
brianbok eba45f2
State machine changes
brianbok 3881c9c
Change exception type
brianbok 5b87d0f
Double releasing semaphore fix`
brianbok 58d5396
Removing continuewith in mostrecentdoc
brianbok 0ae25d8
Setting state, only one assignment per method
brianbok 8ef5750
Disposing index parser in symbol index
brianbok 14d3d90
Make includePatterns optional for match
brianbok a87deac
Not calling excludePatterns if unnecessary
brianbok 2ee4b55
Use of concurrent dictionary instead of lock on object
brianbok ad258cc
Const instead of static
brianbok 190f8a5
Merge branch 'indexer' of github.com:brianbok/python-language-server …
brianbok 4fb33db
IndexParser task creation in a cleaner way
brianbok 61039d5
Use of disposablebag everywhere`
brianbok 2a23b61
Delete unused fields and params
brianbok 6e44942
More disposablebag usage
brianbok 5485c9c
Unused imports
brianbok File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
using System; | ||
using System.Threading; | ||
using System.Threading.Tasks; | ||
using Microsoft.Python.Analysis.Documents; | ||
|
||
namespace Microsoft.Python.Analysis.Indexing { | ||
internal interface IIndexManager : IDisposable { | ||
Task AddRootDirectory(CancellationToken workspaceCancellationToken = default); | ||
void ProcessFile(Uri uri, IDocument doc); | ||
brianbok marked this conversation as resolved.
Show resolved
Hide resolved
|
||
Task ProcessClosedFile(Uri uri, CancellationToken fileCancellationToken = default); | ||
brianbok marked this conversation as resolved.
Show resolved
Hide resolved
|
||
void ProcessFileIfIndexed(Uri uri, IDocument doc); | ||
brianbok marked this conversation as resolved.
Show resolved
Hide resolved
|
||
} | ||
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
using System; | ||
using System.Threading; | ||
using System.Threading.Tasks; | ||
|
||
namespace Microsoft.Python.Analysis.Indexing { | ||
internal interface IIndexParser : IDisposable { | ||
Task ParseAsync(Uri uri, CancellationToken cancellationToken = default); | ||
} | ||
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
using System; | ||
using System.Collections.Generic; | ||
using Microsoft.Python.Parsing.Ast; | ||
|
||
namespace Microsoft.Python.Analysis.Indexing { | ||
internal interface ISymbolIndex { | ||
brianbok marked this conversation as resolved.
Show resolved
Hide resolved
|
||
void UpdateIndex(Uri uri, PythonAst pythonAst); | ||
IEnumerable<FlatSymbol> WorkspaceSymbols(string query); | ||
void Delete(Uri uri); | ||
} | ||
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,96 @@ | ||
using System; | ||
using System.Collections.Concurrent; | ||
using System.Collections.Generic; | ||
using System.Threading; | ||
using System.Threading.Tasks; | ||
using Microsoft.Python.Analysis.Core.Interpreter; | ||
using Microsoft.Python.Analysis.Documents; | ||
using Microsoft.Python.Core.Diagnostics; | ||
using Microsoft.Python.Core.IO; | ||
using Microsoft.Python.Parsing; | ||
|
||
namespace Microsoft.Python.Analysis.Indexing { | ||
internal class IndexManager : IIndexManager { | ||
private readonly ISymbolIndex _symbolIndex; | ||
private readonly IFileSystem _fileSystem; | ||
private readonly IndexParser _indexParser; | ||
private readonly string _workspaceRootPath; | ||
private readonly string[] _includeFiles; | ||
private readonly string[] _excludeFiles; | ||
private readonly ConcurrentDictionary<Uri, bool> _indexedFiles = new ConcurrentDictionary<Uri, bool>(); | ||
private readonly CancellationTokenSource _allIndexCts = new CancellationTokenSource(); | ||
|
||
public IndexManager(ISymbolIndex symbolIndex, IFileSystem fileSystem, PythonLanguageVersion version, string rootPath, string[] includeFiles, | ||
string[] excludeFiles) { | ||
Check.ArgumentNotNull(nameof(fileSystem), fileSystem); | ||
Check.ArgumentNotNull(nameof(rootPath), rootPath); | ||
Check.ArgumentNotNull(nameof(includeFiles), includeFiles); | ||
Check.ArgumentNotNull(nameof(excludeFiles), excludeFiles); | ||
|
||
_symbolIndex = symbolIndex; | ||
_fileSystem = fileSystem; | ||
_indexParser = new IndexParser(symbolIndex, fileSystem, version); | ||
_workspaceRootPath = rootPath; | ||
_includeFiles = includeFiles; | ||
_excludeFiles = excludeFiles; | ||
} | ||
|
||
public Task AddRootDirectory(CancellationToken workspaceCancellationToken = default) { | ||
brianbok marked this conversation as resolved.
Show resolved
Hide resolved
|
||
var linkedCts = CancellationTokenSource.CreateLinkedTokenSource(workspaceCancellationToken, _allIndexCts.Token); | ||
var parseTasks = new List<Task>(); | ||
foreach (var fileInfo in WorkspaceFiles()) { | ||
if (ModulePath.IsPythonSourceFile(fileInfo.FullName)) { | ||
Uri uri = new Uri(fileInfo.FullName); | ||
parseTasks.Add(_indexParser.ParseAsync(uri, linkedCts.Token).ContinueWith((task) => { | ||
linkedCts.Token.ThrowIfCancellationRequested(); | ||
_indexedFiles[uri] = true; | ||
})); | ||
} | ||
} | ||
return Task.WhenAll(parseTasks.ToArray()); | ||
} | ||
|
||
private IEnumerable<IFileSystemInfo> WorkspaceFiles() { | ||
return _fileSystem.GetDirectoryInfo(_workspaceRootPath).EnumerateFileSystemInfos(_includeFiles, _excludeFiles); | ||
} | ||
|
||
private bool IsFileIndexed(Uri uri) { | ||
_indexedFiles.TryGetValue(uri, out var val); | ||
brianbok marked this conversation as resolved.
Show resolved
Hide resolved
|
||
return val; | ||
} | ||
|
||
public Task ProcessClosedFile(Uri uri, CancellationToken fileCancellationToken = default) { | ||
var linkedCts = CancellationTokenSource.CreateLinkedTokenSource(fileCancellationToken, _allIndexCts.Token); | ||
// If path is on workspace | ||
if (IsFileOnWorkspace(uri)) { | ||
// updates index and ignores previous AST | ||
return _indexParser.ParseAsync(uri, linkedCts.Token); | ||
} else { | ||
// remove file from index | ||
_indexedFiles.TryRemove(uri, out _); | ||
_symbolIndex.Delete(uri); | ||
return Task.CompletedTask; | ||
} | ||
} | ||
|
||
private bool IsFileOnWorkspace(Uri uri) { | ||
return _fileSystem.IsPathUnderRoot(_workspaceRootPath, uri.AbsolutePath); | ||
} | ||
|
||
public void ProcessFile(Uri uri, IDocument doc) { | ||
_indexedFiles[uri] = true; | ||
_symbolIndex.UpdateIndex(uri, doc.GetAnyAst()); | ||
} | ||
|
||
public void ProcessFileIfIndexed(Uri uri, IDocument doc) { | ||
if (IsFileIndexed(uri)) { | ||
ProcessFile(uri, doc); | ||
} | ||
} | ||
|
||
public void Dispose() { | ||
_allIndexCts.Cancel(); | ||
_allIndexCts.Dispose(); | ||
} | ||
} | ||
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
using System; | ||
using System.IO; | ||
using System.Threading; | ||
using System.Threading.Tasks; | ||
using Microsoft.Python.Core.Diagnostics; | ||
using Microsoft.Python.Core.IO; | ||
using Microsoft.Python.Parsing; | ||
|
||
namespace Microsoft.Python.Analysis.Indexing { | ||
internal sealed class IndexParser : IIndexParser { | ||
private readonly ISymbolIndex _symbolIndex; | ||
private readonly IFileSystem _fileSystem; | ||
private readonly PythonLanguageVersion _version; | ||
private readonly CancellationTokenSource _allProcessingCts = new CancellationTokenSource(); | ||
|
||
public IndexParser(ISymbolIndex symbolIndex, IFileSystem fileSystem, PythonLanguageVersion version) { | ||
Check.ArgumentNotNull(nameof(symbolIndex), symbolIndex); | ||
Check.ArgumentNotNull(nameof(fileSystem), fileSystem); | ||
|
||
_symbolIndex = symbolIndex; | ||
_fileSystem = fileSystem; | ||
_version = version; | ||
} | ||
|
||
public void Dispose() { | ||
_allProcessingCts.Cancel(); | ||
_allProcessingCts.Dispose(); | ||
} | ||
|
||
public Task ParseAsync(Uri uri, CancellationToken parseCancellationToken = default) { | ||
brianbok marked this conversation as resolved.
Show resolved
Hide resolved
|
||
var linkedParseCts = CancellationTokenSource.CreateLinkedTokenSource(_allProcessingCts.Token, parseCancellationToken); | ||
brianbok marked this conversation as resolved.
Show resolved
Hide resolved
|
||
var linkedParseToken = linkedParseCts.Token; | ||
return Task.Run(() => { | ||
if (!_fileSystem.FileExists(uri.AbsolutePath)) { | ||
throw new FileNotFoundException($"{uri.AbsolutePath} does not exist", uri.AbsolutePath); | ||
} | ||
using (var stream = _fileSystem.FileOpen(uri.AbsolutePath, FileMode.Open)) { | ||
var parser = Parser.CreateParser(stream, _version); | ||
linkedParseToken.ThrowIfCancellationRequested(); | ||
_symbolIndex.UpdateIndex(uri, parser.ParseFile()); | ||
} | ||
}, linkedParseToken); | ||
} | ||
} | ||
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
using System; | ||
using System.Collections.Concurrent; | ||
using System.Collections.Generic; | ||
using System.Linq; | ||
using Microsoft.Python.Core; | ||
using Microsoft.Python.Parsing.Ast; | ||
|
||
namespace Microsoft.Python.Analysis.Indexing { | ||
internal sealed class SymbolIndex : ISymbolIndex { | ||
private readonly ConcurrentDictionary<Uri, IReadOnlyList<HierarchicalSymbol>> _index = new ConcurrentDictionary<Uri, IReadOnlyList<HierarchicalSymbol>>(); | ||
|
||
public IEnumerable<HierarchicalSymbol> HierarchicalDocumentSymbols(Uri uri) | ||
brianbok marked this conversation as resolved.
Show resolved
Hide resolved
|
||
=> _index.TryGetValue(uri, out var list) ? list : Enumerable.Empty<HierarchicalSymbol>(); | ||
|
||
public IEnumerable<FlatSymbol> WorkspaceSymbols(string query) { | ||
foreach (var kvp in _index) { | ||
foreach (var found in WorkspaceSymbolsQuery(query, kvp.Key, kvp.Value)) { | ||
yield return found; | ||
brianbok marked this conversation as resolved.
Show resolved
Hide resolved
|
||
} | ||
} | ||
} | ||
|
||
private IEnumerable<FlatSymbol> WorkspaceSymbolsQuery(string query, Uri uri, IEnumerable<HierarchicalSymbol> symbols) { | ||
// Some semblance of a BFS. | ||
var queue = new Queue<(HierarchicalSymbol, string)>(symbols.Select(s => (s, (string)null))); | ||
brianbok marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
while (queue.Count > 0) { | ||
var (sym, parent) = queue.Dequeue(); | ||
|
||
if (sym.Name.ContainsOrdinal(query, ignoreCase: true)) { | ||
yield return new FlatSymbol(sym.Name, sym.Kind, uri, sym.SelectionRange, parent); | ||
} | ||
|
||
foreach (var child in sym.Children.MaybeEnumerate()) { | ||
queue.Enqueue((child, sym.Name)); | ||
} | ||
} | ||
} | ||
|
||
public void UpdateIndex(Uri uri, PythonAst ast) { | ||
var walker = new SymbolIndexWalker(ast); | ||
ast.Walk(walker); | ||
_index[uri] = walker.Symbols; | ||
} | ||
|
||
public void Delete(Uri uri) => _index.TryRemove(uri, out var _); | ||
} | ||
} |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.