public async Task <Unit> Handle(DidChangeTextDocumentParams notification, CancellationToken token) { _foregroundDispatcher.AssertBackgroundThread(); var document = await Task.Factory.StartNew(() => { _documentResolver.TryResolveDocument(notification.TextDocument.Uri.GetAbsoluteOrUNCPath(), out var documentSnapshot); return(documentSnapshot); }, CancellationToken.None, TaskCreationOptions.None, _foregroundDispatcher.ForegroundScheduler); var sourceText = await document.GetTextAsync(); sourceText = ApplyContentChanges(notification.ContentChanges, sourceText); if (notification.TextDocument.Version is null) { throw new InvalidOperationException("Provided version should not be null."); } await Task.Factory.StartNew( () => _projectService.UpdateDocument(document.FilePath, sourceText, notification.TextDocument.Version.Value), CancellationToken.None, TaskCreationOptions.None, _foregroundDispatcher.ForegroundScheduler); return(Unit.Value); }
public async Task <Unit> Handle(AddDocumentParams request, CancellationToken cancellationToken) { _foregroundDispatcher.AssertBackgroundThread(); await Task.Factory.StartNew( () => _projectService.AddDocument(request.FilePath), CancellationToken.None, TaskCreationOptions.None, _foregroundDispatcher.ForegroundScheduler); return(Unit.Value); }
protected override async Task OnProjectChangedAsync() { ForegroundDispatcher.AssertBackgroundThread(); await ExecuteWithLockAsync(async() => { var referencedAssemblies = await DotNetProject.GetReferencedAssemblies(ConfigurationSelector.Default); var mvcReference = referencedAssemblies.FirstOrDefault(IsMvcAssembly); if (mvcReference == null) { // Ok we can't find an MVC version. Let's assume this project isn't using Razor then. await UpdateHostProjectUnsafeAsync(null).ConfigureAwait(false); return; } var version = GetAssemblyVersion(mvcReference.FilePath); if (version == null) { // Ok we can't find an MVC version. Let's assume this project isn't using Razor then. await UpdateHostProjectUnsafeAsync(null).ConfigureAwait(false); return; } var configuration = FallbackRazorConfiguration.SelectConfiguration(version); var hostProject = new HostProject(DotNetProject.FileName.FullPath, configuration); await UpdateHostProjectUnsafeAsync(hostProject).ConfigureAwait(false); }); }
public async Task <Uri> GetProjectPathAsync(Uri documentFilePath, CancellationToken cancellationToken) { if (documentFilePath == null) { throw new ArgumentNullException(nameof(documentFilePath)); } _foregroundDispatcher.AssertBackgroundThread(); await _joinableTaskFactory.SwitchToMainThreadAsync(cancellationToken); if (_openDocumentShell == null) { _openDocumentShell = ServiceProvider.GlobalProvider.GetService(typeof(SVsUIShellOpenDocument)) as IVsUIShellOpenDocument; } var hostDocumentFilePath = _session.ConvertSharedUriToLocalPath(documentFilePath); var hr = _openDocumentShell.IsDocumentInAProject(hostDocumentFilePath, out var hierarchy, out _, out _, out _); if (ErrorHandler.Succeeded(hr) && hierarchy != null) { ErrorHandler.ThrowOnFailure(((IVsProject)hierarchy).GetMkDocument((uint)VSConstants.VSITEMID.Root, out var path), VSConstants.E_NOTIMPL); return(_session.ConvertLocalPathToSharedUri(path)); } return(null); }
private void Onidle(object sender, ElapsedEventArgs e) { _dispatcher.AssertBackgroundThread(); var textViews = Array.Empty <ITextView>(); foreach (var textView in textViews) { if (_completionBroker.IsCompletionActive(textView)) { return; } } _idleTimer.Stop(); Reparse(); }
public async Task <CompletionContext> GetCompletionContextAsync( IAsyncCompletionSession session, CompletionTrigger trigger, SnapshotPoint triggerLocation, SnapshotSpan applicableSpan, CancellationToken token) { _foregroundDispatcher.AssertBackgroundThread(); try { var codeDocument = await _parser.GetLatestCodeDocumentAsync(triggerLocation.Snapshot, token); if (codeDocument == null) { return(CompletionContext.Empty); } var location = new SourceSpan(triggerLocation.Position, 0); var syntaxTree = codeDocument.GetSyntaxTree(); var tagHelperDocumentContext = codeDocument.GetTagHelperContext(); var razorCompletionItems = _completionFactsService.GetCompletionItems(syntaxTree, tagHelperDocumentContext, location); var completionItems = new List <CompletionItem>(); foreach (var razorCompletionItem in razorCompletionItems) { if (razorCompletionItem.Kind != RazorCompletionItemKind.Directive) { // Don't support any other types of completion kinds other than directives. continue; } var completionItem = new CompletionItem( displayText: razorCompletionItem.DisplayText, filterText: razorCompletionItem.DisplayText, insertText: razorCompletionItem.InsertText, source: this, icon: DirectiveImageGlyph, filters: DirectiveCompletionFilters, suffix: string.Empty, sortText: razorCompletionItem.DisplayText, attributeIcons: ImmutableArray <ImageElement> .Empty); var completionDescription = razorCompletionItem.GetDirectiveCompletionDescription(); completionItem.Properties.AddProperty(DescriptionKey, completionDescription); completionItems.Add(completionItem); } var context = new CompletionContext(completionItems.ToImmutableArray()); return(context); } catch (OperationCanceledException) { return(CompletionContext.Empty); } }
public async Task <CompletionList> Handle(CompletionParams request, CancellationToken cancellationToken) { _foregroundDispatcher.AssertBackgroundThread(); var document = await Task.Factory.StartNew(() => { _documentResolver.TryResolveDocument(request.TextDocument.Uri.AbsolutePath, out var documentSnapshot); return(documentSnapshot); }, CancellationToken.None, TaskCreationOptions.None, _foregroundDispatcher.ForegroundScheduler); var codeDocument = await document.GetGeneratedOutputAsync(); var syntaxTree = codeDocument.GetSyntaxTree(); var sourceText = await document.GetTextAsync(); var linePosition = new LinePosition((int)request.Position.Line, (int)request.Position.Character); var hostDocumentIndex = sourceText.Lines.GetPosition(linePosition); var location = new SourceSpan(hostDocumentIndex, 0); var razorCompletionItems = _completionFactsService.GetCompletionItems(syntaxTree, location); _logger.LogTrace($"Found {razorCompletionItems.Count} Razor specific completion items."); var completionItems = new List <CompletionItem>(); foreach (var razorCompletionItem in razorCompletionItems) { if (razorCompletionItem.Kind != RazorCompletionItemKind.Directive) { // Don't support any other types of completion kinds other than directives. continue; } var directiveCompletionItem = new CompletionItem() { Label = razorCompletionItem.DisplayText, InsertText = razorCompletionItem.InsertText, Detail = razorCompletionItem.Description, Documentation = razorCompletionItem.Description, FilterText = razorCompletionItem.DisplayText, SortText = razorCompletionItem.DisplayText, Kind = CompletionItemKind.Struct, }; completionItems.Add(directiveCompletionItem); } var completionList = new CompletionList(completionItems, isIncomplete: false); return(completionList); }
public async Task <Unit> Handle(DidChangeTextDocumentParams notification, CancellationToken token) { _foregroundDispatcher.AssertBackgroundThread(); var document = await Task.Factory.StartNew(() => { _documentResolver.TryResolveDocument(notification.TextDocument.Uri.AbsolutePath, out var documentSnapshot); return(documentSnapshot); }, CancellationToken.None, TaskCreationOptions.None, _foregroundDispatcher.ForegroundScheduler); var sourceText = await document.GetTextAsync(); sourceText = ApplyContentChanges(notification.ContentChanges, sourceText); await Task.Factory.StartNew( () => _projectService.UpdateDocument(document.FilePath, sourceText, notification.TextDocument.Version), CancellationToken.None, TaskCreationOptions.None, _foregroundDispatcher.ForegroundScheduler); return(Unit.Value); }
private async void Timer_Tick(object state) // Yeah I know. { try { _foregroundDispatcher.AssertBackgroundThread(); // Timer is stopped. _timer.Change(Timeout.Infinite, Timeout.Infinite); OnStartingBackgroundWork(); ProjectSnapshotUpdateContext[] work; lock (_projects) { work = _projects.Values.ToArray(); _projects.Clear(); } var updates = new(ProjectSnapshotUpdateContext context, Exception exception)[work.Length];
protected override async Task OnProjectChangedAsync() { ForegroundDispatcher.AssertBackgroundThread(); await ExecuteWithLockAsync(async() => { var projectProperties = DotNetProject.MSBuildProject.EvaluatedProperties; var projectItems = DotNetProject.MSBuildProject.EvaluatedItems; if (TryGetConfiguration(projectProperties, projectItems, out var configuration)) { var hostProject = new HostProject(DotNetProject.FileName.FullPath, configuration); await UpdateHostProjectUnsafeAsync(hostProject).ConfigureAwait(false); } else { // Ok we can't find a configuration. Let's assume this project isn't using Razor then. await UpdateHostProjectUnsafeAsync(null).ConfigureAwait(false); } }); }
public Task <CompletionContext> GetCompletionContextAsync( IAsyncCompletionSession session, CompletionTrigger trigger, SnapshotPoint triggerLocation, SnapshotSpan applicableSpan, CancellationToken token) { _foregroundDispatcher.AssertBackgroundThread(); var syntaxTree = _parser.CodeDocument?.GetSyntaxTree(); var location = new SourceSpan(applicableSpan.Start.Position, applicableSpan.Length); var razorCompletionItems = _completionFactsService.GetCompletionItems(syntaxTree, location); var completionItems = new List <CompletionItem>(); foreach (var razorCompletionItem in razorCompletionItems) { if (razorCompletionItem.Kind != RazorCompletionItemKind.Directive) { // Don't support any other types of completion kinds other than directives. continue; } var completionItem = new CompletionItem( displayText: razorCompletionItem.DisplayText, filterText: razorCompletionItem.DisplayText, insertText: razorCompletionItem.InsertText, source: this, icon: DirectiveImageGlyph, filters: DirectiveCompletionFilters, suffix: string.Empty, sortText: razorCompletionItem.DisplayText, attributeIcons: ImmutableArray <ImageElement> .Empty); completionItem.Properties.AddProperty(DescriptionKey, razorCompletionItem.Description); completionItems.Add(completionItem); } var context = new CompletionContext(completionItems.ToImmutableArray()); return(Task.FromResult(context)); }
public async Task <CompletionList> Handle(CompletionParams request, CancellationToken cancellationToken) { _foregroundDispatcher.AssertBackgroundThread(); var document = await Task.Factory.StartNew(() => { _documentResolver.TryResolveDocument(request.TextDocument.Uri.GetAbsoluteOrUNCPath(), out var documentSnapshot); return(documentSnapshot); }, CancellationToken.None, TaskCreationOptions.None, _foregroundDispatcher.ForegroundScheduler); if (document is null || cancellationToken.IsCancellationRequested) { return(new CompletionList(isIncomplete: false)); } var codeDocument = await document.GetGeneratedOutputAsync(); if (codeDocument.IsUnsupported()) { return(new CompletionList(isIncomplete: false)); } var syntaxTree = codeDocument.GetSyntaxTree(); var tagHelperDocumentContext = codeDocument.GetTagHelperContext(); var sourceText = await document.GetTextAsync(); var linePosition = new LinePosition((int)request.Position.Line, (int)request.Position.Character); var hostDocumentIndex = sourceText.Lines.GetPosition(linePosition); var location = new SourceSpan(hostDocumentIndex, 0); var razorCompletionItems = _completionFactsService.GetCompletionItems(syntaxTree, tagHelperDocumentContext, location); _logger.LogTrace($"Resolved {razorCompletionItems.Count} completion items."); var completionList = CreateLSPCompletionList(razorCompletionItems); return(completionList); }
// Must be called inside the lock. protected async Task UpdateHostProjectUnsafeAsync(HostProject newHostProject) { _foregroundDispatcher.AssertBackgroundThread(); await Task.Factory.StartNew(UpdateHostProjectForeground, newHostProject, CancellationToken.None, TaskCreationOptions.None, ForegroundDispatcher.ForegroundScheduler); }
public async Task <CompletionList> Handle(CompletionParams request, CancellationToken cancellationToken) { _foregroundDispatcher.AssertBackgroundThread(); var document = await Task.Factory.StartNew(() => { _documentResolver.TryResolveDocument(request.TextDocument.Uri.GetAbsoluteOrUNCPath(), out var documentSnapshot); return(documentSnapshot); }, CancellationToken.None, TaskCreationOptions.None, _foregroundDispatcher.ForegroundScheduler); if (document is null || cancellationToken.IsCancellationRequested) { return(new CompletionList(isIncomplete: false)); } var codeDocument = await document.GetGeneratedOutputAsync(); if (codeDocument.IsUnsupported()) { return(new CompletionList(isIncomplete: false)); } var syntaxTree = codeDocument.GetSyntaxTree(); var tagHelperDocumentContext = codeDocument.GetTagHelperContext(); var sourceText = await document.GetTextAsync(); var linePosition = new LinePosition((int)request.Position.Line, (int)request.Position.Character); var hostDocumentIndex = sourceText.Lines.GetPosition(linePosition); var location = new SourceSpan(hostDocumentIndex, 0); var directiveCompletionItems = _completionFactsService.GetCompletionItems(syntaxTree, tagHelperDocumentContext, location); _logger.LogTrace($"Found {directiveCompletionItems.Count} directive completion items."); var completionItems = new List <CompletionItem>(); foreach (var razorCompletionItem in directiveCompletionItems) { if (TryConvert(razorCompletionItem, out var completionItem)) { completionItems.Add(completionItem); } } var parameterCompletions = completionItems.Where(completionItem => completionItem.TryGetRazorCompletionKind(out var completionKind) && completionKind == RazorCompletionItemKind.DirectiveAttributeParameter); if (parameterCompletions.Any()) { // Parameters are present in the completion list, even though TagHelpers are technically valid we shouldn't flood the completion list // with non parameter completions. Filter out the rest. completionItems = parameterCompletions.ToList(); } else { var tagHelperCompletionItems = _tagHelperCompletionService.GetCompletionsAt(location, codeDocument); _logger.LogTrace($"Found {tagHelperCompletionItems.Count} TagHelper completion items."); completionItems.AddRange(tagHelperCompletionItems); } var completionList = new CompletionList(completionItems, isIncomplete: false); return(completionList); }
#pragma warning disable VSTHRD100 // Avoid async void methods private async void Timer_Tick(object state) #pragma warning restore VSTHRD100 // Avoid async void methods { try { _foregroundDispatcher.AssertBackgroundThread(); OnStartingBackgroundWork(); KeyValuePair <string, DocumentSnapshot>[] work; lock (_work) { work = _work.ToArray(); _work.Clear(); } OnBackgroundCapturedWorkload(); for (var i = 0; i < work.Length; i++) { var document = work[i].Value; try { await document.GetGeneratedOutputAsync(); } catch (Exception ex) { ReportError(ex); } } OnCompletingBackgroundWork(); await Task.Factory.StartNew( () => { NotifyDocumentsProcessed(work); }, CancellationToken.None, TaskCreationOptions.None, _foregroundDispatcher.ForegroundScheduler); lock (_work) { // Resetting the timer allows another batch of work to start. _timer.Dispose(); _timer = null; // If more work came in while we were running start the worker again. if (_work.Count > 0) { StartWorker(); } } OnCompletedBackgroundWork(); } catch (Exception ex) { // This is something totally unexpected, let's just send it over to the workspace. ReportError(ex); _timer?.Dispose(); _timer = null; } }
private async void Timer_Tick(object state) { try { _foregroundDispatcher.AssertBackgroundThread(); // Timer is stopped. _timer.Change(Timeout.Infinite, Timeout.Infinite); OnStartingBackgroundWork(); KeyValuePair <string, DocumentSnapshot>[] work; lock (_work) { work = _work.ToArray(); _work.Clear(); } OnBackgroundCapturedWorkload(); for (var i = 0; i < work.Length; i++) { var document = work[i].Value; try { await document.GetGeneratedOutputAsync(); } catch (Exception ex) { ReportError(ex); _logger.LogError("Error when processing document: " + document.FilePath); } } OnCompletingBackgroundWork(); await Task.Factory.StartNew( () => ReportUnsynchronizableContent(work), CancellationToken.None, TaskCreationOptions.None, _foregroundDispatcher.ForegroundScheduler); lock (_work) { // Resetting the timer allows another batch of work to start. _timer.Dispose(); _timer = null; // If more work came in while we were running start the worker again. if (_work.Count > 0) { StartWorker(); } } OnCompletedBackgroundWork(); } catch (Exception ex) { // This is something totally unexpected, let's just send it over to the workspace. ReportError(ex); } }
public async Task <CompletionContext> GetCompletionContextAsync(IAsyncCompletionSession session, CompletionTrigger trigger, SnapshotPoint triggerLocation, SnapshotSpan applicableToSpan, CancellationToken token) { _foregroundDispatcher.AssertBackgroundThread(); try { var codeDocument = await _parser.GetLatestCodeDocumentAsync(triggerLocation.Snapshot, token); if (codeDocument == null) { // Code document not available yet. return(CompletionContext.Empty); } var syntaxTree = codeDocument.GetSyntaxTree(); var tagHelperDocumentContext = codeDocument.GetTagHelperContext(); var location = new SourceSpan(triggerLocation.Position, 0); var razorCompletionItems = _completionFactsService.GetCompletionItems(syntaxTree, tagHelperDocumentContext, location); if (razorCompletionItems.Count == 0) { return(CompletionContext.Empty); } // Check if we're providing completion items while a legacy completion session is active. If so // we'll need to dismiss the legacy completion session to ensure we don't get two completion lists. var activeSessions = _completionBroker.GetSessions(session.TextView); foreach (var activeSession in activeSessions) { if (activeSession.Properties.ContainsProperty(nameof(IAsyncCompletionSession))) { continue; } // Legacy completion is also active, we need to dismiss it. _ = Task.Factory.StartNew( () => activeSession.Dismiss(), CancellationToken.None, TaskCreationOptions.None, _foregroundDispatcher.ForegroundScheduler); } var completionItems = new List <CompletionItem>(); var completionItemKinds = new HashSet <RazorCompletionItemKind>(); foreach (var razorCompletionItem in razorCompletionItems) { if (razorCompletionItem.Kind != RazorCompletionItemKind.DirectiveAttribute && razorCompletionItem.Kind != RazorCompletionItemKind.DirectiveAttributeParameter) { // Don't support any other types of completion kinds other than directive attributes and their parameters. continue; } var completionItem = new CompletionItem( displayText: razorCompletionItem.DisplayText, filterText: razorCompletionItem.DisplayText, insertText: razorCompletionItem.InsertText, source: this, icon: DirectiveAttributeImageGlyph, filters: DirectiveAttributeCompletionFilters, suffix: string.Empty, sortText: razorCompletionItem.DisplayText, attributeIcons: ImmutableArray <ImageElement> .Empty); completionItems.Add(completionItem); completionItemKinds.Add(razorCompletionItem.Kind); var completionDescription = razorCompletionItem.GetAttributeCompletionDescription(); completionItem.Properties[DescriptionKey] = completionDescription; } session.Properties.SetCompletionItemKinds(completionItemKinds); var orderedCompletionItems = completionItems.OrderBy(item => item.DisplayText); var context = new CompletionContext(orderedCompletionItems.ToImmutableArray()); return(context); } catch (OperationCanceledException) { return(CompletionContext.Empty); } }