From d69938f36de3861e03924050341f875e5ca79655 Mon Sep 17 00:00:00 2001 From: "N. Taylor Mullen" Date: Thu, 27 Feb 2020 21:11:04 -0800 Subject: [PATCH] Initialize LSP documents earlier. - Prior to this we would start tracking LSP documents when an `ITextView` was associated with our `ITextBuffer`. The issue with this is when the `ILanguageClient` infrastructure initializes itself before we do and starts our `LanguageServer` it's we start retrieving requests that require access to our `LSPDocumentManager`. That's an issue because our `LSPDocumentManager` may not have been initialized yet resulting in failure to fulfill requests. - Changed how we initialize `ITextBuffer`s. Before we were setting up all of the logic to change the content type of a text buffer and populate its properties at the `EditorFactory` layer; however, how we were doing it (waiting for the ITextBuffer to load) resulted in `ITextDocumentListener` events firing prior to our content type changes would occur. This is a problem becasue the `ILanguageaClient` infrastructure will start making its decision to turn on LSP features for your `ITextBuffer` at the point and time. Now we change the `ITextBuffer`s content type (and set properties) during the `ITextDocumentListener` created pipeline. This resulted in almost all of our logic in our editor factory to be split out into two classes. 1. `LSPEditorFeatureDetector`, we needed to be able to detect the "enabledness" of features in two locations. Once at the `EditorFactory` layer to ensure we know when to disallow other editor factories participation in the `ITextBuffer` creation and a second at the `ITextDocumentListener` layer when we inspect an `ITextDocument` and need to determine if we want to "initialize" it (change its content type etc.). 2. `RazorLSPTextDocumentCreatedListener`, this is our `ITextDocumentListener` i've been referring to. It now houses the logic on how to change the content type and populate the `ITextBuffer`'s properties. - Changed our `LSPDocumentManager` to no longer depend on `ITextView`s for ref counting documents. Instead we just take an `ITextBuffer` and keep an internal count of how many times we've been asked to track a document. In practice this number never goes past 1 however it doesn't hurt to be defensive. - Added IVT from CodeAnalysis.Razor to our LanguageServerClient project in order to enable the retrieval of our `FilePathComparison` type. - Given the new refactoring of our feature detector and the `ITextDocumentListener` pieces I was able to add extensive testing to ensure all things work as expected. Fixes dotnet/aspnetcoredotnet/aspnetcore-tooling#19160 \n\nCommit migrated from https://github.com/dotnet/aspnetcore-tooling/commit/d0a7dfce094b3bd283a1718fbe22eabcdec9e68f --- .../Microsoft.CodeAnalysis.Razor/src/Properties/AssemblyInfo.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Razor/Microsoft.CodeAnalysis.Razor/src/Properties/AssemblyInfo.cs b/src/Razor/Microsoft.CodeAnalysis.Razor/src/Properties/AssemblyInfo.cs index 30de565649..f59363b736 100644 --- a/src/Razor/Microsoft.CodeAnalysis.Razor/src/Properties/AssemblyInfo.cs +++ b/src/Razor/Microsoft.CodeAnalysis.Razor/src/Properties/AssemblyInfo.cs @@ -12,6 +12,7 @@ using System.Runtime.CompilerServices; [assembly: InternalsVisibleTo("Microsoft.AspNetCore.Razor.Language.Test, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")] [assembly: InternalsVisibleTo("Microsoft.AspNetCore.Razor.LanguageServer.Test, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")] [assembly: InternalsVisibleTo("Microsoft.AspNetCore.Razor.Test.Common, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")] +[assembly: InternalsVisibleTo("Microsoft.VisualStudio.LanguageServerClient.Razor, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")] [assembly: InternalsVisibleTo("Microsoft.VisualStudio.LiveShare.Razor, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")] [assembly: InternalsVisibleTo("Microsoft.VisualStudio.LiveShare.Razor.Test, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")] [assembly: InternalsVisibleTo("Microsoft.CodeAnalysis.Razor.Test, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")]