예제 #1
0
        public void ProjectSnapshotManager_Changed_DocumentRemoved_DoesNotEvictDocument()
        {
            // Arrange
            var documentVersionCache   = new DefaultDocumentVersionCache(Dispatcher);
            var projectSnapshotManager = TestProjectSnapshotManager.Create(Dispatcher);

            projectSnapshotManager.AllowNotifyListeners = true;
            documentVersionCache.Initialize(projectSnapshotManager);
            var document = TestDocumentSnapshot.Create("C:/file.cshtml");

            document.TryGetText(out var text);
            document.TryGetTextVersion(out var textVersion);
            var textAndVersion = TextAndVersion.Create(text, textVersion);

            documentVersionCache.TrackDocumentVersion(document, 1337);
            projectSnapshotManager.ProjectAdded(document.ProjectInternal.HostProject);
            projectSnapshotManager.DocumentAdded(document.ProjectInternal.HostProject, document.State.HostDocument, TextLoader.From(textAndVersion));

            // Act - 1
            var result = documentVersionCache.TryGetDocumentVersion(document, out var version);

            // Assert - 1
            Assert.True(result);

            // Act - 2
            projectSnapshotManager.DocumentRemoved(document.ProjectInternal.HostProject, document.State.HostDocument);
            result = documentVersionCache.TryGetDocumentVersion(document, out version);

            // Assert - 2
            Assert.True(result);
        }
예제 #2
0
        public void TryGetLatestVersionFromPath_UntrackedDocument_ReturnsFalse()
        {
            // Arrange
            var documentVersionCache = new DefaultDocumentVersionCache(Dispatcher);

            // Act
            var result = documentVersionCache.TryGetLatestVersionFromPath("C:/file.cshtml", out var version);

            // Assert
            Assert.False(result);
            Assert.Null(version);
        }
예제 #3
0
        public void TryGetDocumentVersion_UntrackedDocumentPath_ReturnsFalse()
        {
            // Arrange
            var documentVersionCache = new DefaultDocumentVersionCache(Dispatcher);
            var document             = TestDocumentSnapshot.Create("C:/file.cshtml");

            // Act
            var result = documentVersionCache.TryGetDocumentVersion(document, out var version);

            // Assert
            Assert.False(result);
            Assert.Null(version);
        }
예제 #4
0
        public void TryGetDocumentVersion_KnownDocument_ReturnsTrue()
        {
            // Arrange
            var documentVersionCache = new DefaultDocumentVersionCache(Dispatcher);
            var document             = TestDocumentSnapshot.Create("C:/file.cshtml");

            documentVersionCache.TrackDocumentVersion(document, 1337);

            // Act
            var result = documentVersionCache.TryGetDocumentVersion(document, out var version);

            // Assert
            Assert.True(result);
            Assert.Equal(1337, version);
        }
예제 #5
0
        public void MarkAsLatestVersion_KnownDocument_TracksNewDocumentAsLatest()
        {
            // Arrange
            var documentVersionCache = new DefaultDocumentVersionCache(Dispatcher);
            var documentInitial      = TestDocumentSnapshot.Create("C:/file.cshtml");

            documentVersionCache.TrackDocumentVersion(documentInitial, 123);
            var documentLatest = TestDocumentSnapshot.Create(documentInitial.FilePath);

            // Act
            documentVersionCache.MarkAsLatestVersion(documentLatest);

            // Assert
            Assert.True(documentVersionCache.TryGetDocumentVersion(documentLatest, out var version));
            Assert.Equal(123, version);
        }
예제 #6
0
        public void TryGetDocumentVersion_EvictedDocument_ReturnsFalse()
        {
            // Arrange
            var documentVersionCache = new DefaultDocumentVersionCache(Dispatcher);
            var document             = TestDocumentSnapshot.Create("C:/file.cshtml");
            var evictedDocument      = TestDocumentSnapshot.Create(document.FilePath);

            documentVersionCache.TrackDocumentVersion(document, 1337);

            // Act
            var result = documentVersionCache.TryGetDocumentVersion(evictedDocument, out var version);

            // Assert
            Assert.False(result);
            Assert.Equal(-1, version);
        }
예제 #7
0
        public void MarkAsLatestVersion_UntrackedDocument_Noops()
        {
            // Arrange
            var documentVersionCache = new DefaultDocumentVersionCache(Dispatcher);
            var document             = TestDocumentSnapshot.Create("C:/file.cshtml");

            documentVersionCache.TrackDocumentVersion(document, 123);
            var untrackedDocument = TestDocumentSnapshot.Create("C:/other.cshtml");

            // Act
            documentVersionCache.MarkAsLatestVersion(untrackedDocument);

            // Assert
            Assert.False(documentVersionCache.TryGetDocumentVersion(untrackedDocument, out var version));
            Assert.Null(version);
        }
        public void TryGetDocumentVersion_DeletedDocument_ReturnsFalse()
        {
            // Arrange
            var documentVersionCache = new DefaultDocumentVersionCache(Dispatcher, FilePathNormalizer);
            var document             = TestDocumentSnapshot.Create("C:/file.cshtml");

            documentVersionCache.TrackDocumentVersion(document, 1337);
            documentVersionCache.RazorFileChanged(document.FilePath, RazorFileChangeKind.Removed);

            // Act
            var result = documentVersionCache.TryGetDocumentVersion(document, out var version);

            // Assert
            Assert.False(result);
            Assert.Equal(-1, version);
        }
예제 #9
0
        public void TryGetLatestVersionFromPath_TrackedDocument_ReturnsTrue()
        {
            // Arrange
            var documentVersionCache = new DefaultDocumentVersionCache(Dispatcher);
            var filePath             = "C:/file.cshtml";
            var document1            = TestDocumentSnapshot.Create(filePath);
            var document2            = TestDocumentSnapshot.Create(filePath);

            documentVersionCache.TrackDocumentVersion(document1, 123);
            documentVersionCache.TrackDocumentVersion(document2, 1337);

            // Act
            var result = documentVersionCache.TryGetLatestVersionFromPath(filePath, out var version);

            // Assert
            Assert.True(result);
            Assert.Equal(1337, version);
        }
예제 #10
0
        public void TrackDocumentVersion_AddsFirstEntry()
        {
            // Arrange
            var documentVersionCache = new DefaultDocumentVersionCache(Dispatcher);
            var document             = TestDocumentSnapshot.Create("C:/file.cshtml");

            // Act
            documentVersionCache.TrackDocumentVersion(document, 1337);

            // Assert
            var kvp = Assert.Single(documentVersionCache._documentLookup);

            Assert.Equal(document.FilePath, kvp.Key);
            var entry = Assert.Single(kvp.Value);

            Assert.True(entry.Document.TryGetTarget(out var actualDocument));
            Assert.Same(document, actualDocument);
            Assert.Equal(1337, entry.Version);
        }
예제 #11
0
        public void TrackDocumentVersion_EvictsOldEntries()
        {
            // Arrange
            var documentVersionCache = new DefaultDocumentVersionCache(Dispatcher);
            var document             = TestDocumentSnapshot.Create("C:/file.cshtml");

            for (var i = 0; i < DefaultDocumentVersionCache.MaxDocumentTrackingCount; i++)
            {
                documentVersionCache.TrackDocumentVersion(document, i);
            }

            // Act
            documentVersionCache.TrackDocumentVersion(document, 1337);

            // Assert
            var kvp = Assert.Single(documentVersionCache._documentLookup);

            Assert.Equal(DefaultDocumentVersionCache.MaxDocumentTrackingCount, kvp.Value.Count);
            Assert.Equal(1337, kvp.Value.Last().Version);
        }
예제 #12
0
        public static Task <ILanguageServer> CreateAsync(Stream input, Stream output, Trace trace)
        {
            Serializer.Instance.JsonSerializer.Converters.RegisterRazorConverters();

            ILanguageServer server = null;

            server = OmniSharp.Extensions.LanguageServer.Server.LanguageServer.PreInit(options =>
                                                                                       options
                                                                                       .WithInput(input)
                                                                                       .WithOutput(output)
                                                                                       .ConfigureLogging(builder => builder
                                                                                                         .AddLanguageServer()
                                                                                                         .SetMinimumLevel(RazorLSPOptions.GetLogLevelForTrace(trace)))
                                                                                       .OnInitialized(async(s, request, response) =>
            {
                var fileChangeDetectorManager = s.Services.GetRequiredService <RazorFileChangeDetectorManager>();
                await fileChangeDetectorManager.InitializedAsync(s);

                // Workaround for https://github.com/OmniSharp/csharp-language-server-protocol/issues/106
                var languageServer = (OmniSharp.Extensions.LanguageServer.Server.LanguageServer)server;
                if (request.Capabilities.Workspace.Configuration.IsSupported)
                {
                    // Initialize our options for the first time.
                    var optionsMonitor = languageServer.Services.GetRequiredService <RazorLSPOptionsMonitor>();
                    _ = Task.Delay(TimeSpan.FromSeconds(3)).ContinueWith(async(_) => await optionsMonitor.UpdateAsync());
                }
            })
                                                                                       .WithHandler <RazorDocumentSynchronizationEndpoint>()
                                                                                       .WithHandler <RazorCompletionEndpoint>()
                                                                                       .WithHandler <RazorHoverEndpoint>()
                                                                                       .WithHandler <RazorLanguageEndpoint>()
                                                                                       .WithHandler <RazorConfigurationEndpoint>()
                                                                                       .WithHandler <RazorFormattingEndpoint>()
                                                                                       .WithHandler <RazorOnTypeFormattingEndpoint>()
                                                                                       .WithHandler <RazorSemanticTokenEndpoint>()
                                                                                       .WithHandler <RazorSemanticTokenLegendEndpoint>()
                                                                                       .WithServices(services =>
            {
                var filePathNormalizer = new FilePathNormalizer();
                services.AddSingleton <FilePathNormalizer>(filePathNormalizer);

                var foregroundDispatcher = new DefaultForegroundDispatcher();
                services.AddSingleton <ForegroundDispatcher>(foregroundDispatcher);

                var generatedDocumentPublisher = new DefaultGeneratedDocumentPublisher(foregroundDispatcher, new Lazy <OmniSharp.Extensions.LanguageServer.Protocol.Server.ILanguageServer>(() => server));
                services.AddSingleton <ProjectSnapshotChangeTrigger>(generatedDocumentPublisher);
                services.AddSingleton <GeneratedDocumentPublisher>(generatedDocumentPublisher);

                var documentVersionCache = new DefaultDocumentVersionCache(foregroundDispatcher);
                services.AddSingleton <DocumentVersionCache>(documentVersionCache);
                services.AddSingleton <ProjectSnapshotChangeTrigger>(documentVersionCache);
                var containerStore = new DefaultGeneratedDocumentContainerStore(
                    foregroundDispatcher,
                    documentVersionCache,
                    generatedDocumentPublisher);
                services.AddSingleton <GeneratedDocumentContainerStore>(containerStore);
                services.AddSingleton <ProjectSnapshotChangeTrigger>(containerStore);

                services.AddSingleton <RemoteTextLoaderFactory, DefaultRemoteTextLoaderFactory>();
                services.AddSingleton <ProjectResolver, DefaultProjectResolver>();
                services.AddSingleton <DocumentResolver, DefaultDocumentResolver>();
                services.AddSingleton <RazorProjectService, DefaultRazorProjectService>();
                services.AddSingleton <ProjectSnapshotChangeTrigger, BackgroundDocumentGenerator>();
                services.AddSingleton <RazorDocumentMappingService, DefaultRazorDocumentMappingService>();
                services.AddSingleton <RazorFileChangeDetectorManager>();

                // Options
                services.AddSingleton <RazorConfigurationService, DefaultRazorConfigurationService>();
                services.AddSingleton <RazorLSPOptionsMonitor>();
                services.AddSingleton <IOptionsMonitor <RazorLSPOptions>, RazorLSPOptionsMonitor>();

                // File change listeners
                services.AddSingleton <IProjectConfigurationFileChangeListener, ProjectConfigurationStateSynchronizer>();
                services.AddSingleton <IProjectFileChangeListener, ProjectFileSynchronizer>();
                services.AddSingleton <IRazorFileChangeListener, RazorFileSynchronizer>();

                // File Change detectors
                services.AddSingleton <IFileChangeDetector, ProjectConfigurationFileChangeDetector>();
                services.AddSingleton <IFileChangeDetector, ProjectFileChangeDetector>();
                services.AddSingleton <IFileChangeDetector, RazorFileChangeDetector>();

                // Document processed listeners
                services.AddSingleton <DocumentProcessedListener, RazorDiagnosticsPublisher>();
                services.AddSingleton <DocumentProcessedListener, UnsynchronizableContentDocumentProcessedListener>();

                services.AddSingleton <HostDocumentFactory, DefaultHostDocumentFactory>();
                services.AddSingleton <ProjectSnapshotManagerAccessor, DefaultProjectSnapshotManagerAccessor>();
                services.AddSingleton <TagHelperFactsService, DefaultTagHelperFactsService>();
                services.AddSingleton <VisualStudio.Editor.Razor.TagHelperCompletionService, VisualStudio.Editor.Razor.DefaultTagHelperCompletionService>();
                services.AddSingleton <TagHelperDescriptionFactory, DefaultTagHelperDescriptionFactory>();

                // Completion
                services.AddSingleton <Completion.TagHelperCompletionService, Completion.DefaultTagHelperCompletionService>();
                services.AddSingleton <RazorCompletionItemProvider, DirectiveCompletionItemProvider>();
                services.AddSingleton <RazorCompletionItemProvider, DirectiveAttributeCompletionItemProvider>();
                services.AddSingleton <RazorCompletionItemProvider, DirectiveAttributeParameterCompletionItemProvider>();
                services.AddSingleton <RazorCompletionItemProvider, DirectiveAttributeTransitionCompletionItemProvider>();
                services.AddSingleton <RazorCompletionItemProvider, MarkupTransitionCompletionItemProvider>();

                // Formatting
                services.AddSingleton <RazorFormatOnTypeProvider, HtmlSmartIndentFormatOnTypeProvider>();
                services.AddSingleton <RazorFormatOnTypeProvider, CloseRazorCommentFormatOnTypeProvider>();
                services.AddSingleton <RazorFormatOnTypeProvider, CloseTextTagFormatOnTypeProvider>();
                services.AddSingleton <RazorFormattingService, DefaultRazorFormattingService>();

                services.AddSingleton <RazorCompletionFactsService, DefaultRazorCompletionFactsService>();
                services.AddSingleton <RazorSemanticTokenInfoService, DefaultRazorSemanticTokenInfoService>();
                services.AddSingleton <RazorHoverInfoService, DefaultRazorHoverInfoService>();
                services.AddSingleton <HtmlFactsService, DefaultHtmlFactsService>();
            }));

            server.OnShutdown(() =>
            {
                TempDirectory.Instance.Dispose();
                return(Unit.Task);
            });

            try
            {
                var factory = new LoggerFactory();
                var logger  = factory.CreateLogger <RazorLanguageServer>();
                var assemblyInformationAttribute = typeof(RazorLanguageServer).Assembly.GetCustomAttribute <AssemblyInformationalVersionAttribute>();
                logger.LogInformation("Razor Language Server version " + assemblyInformationAttribute.InformationalVersion);
            }
            catch
            {
                // Swallow exceptions from determining assembly information.
            }

            return(Task.FromResult(server));
        }
        public static Task <RazorLanguageServer> CreateAsync(Stream input, Stream output, Trace trace, Action <RazorLanguageServerBuilder> configure = null)
        {
            Serializer.Instance.JsonSerializer.Converters.RegisterRazorConverters();

            // Custom ClientCapabilities deserializer to extract experimental capabilities
            Serializer.Instance.JsonSerializer.Converters.Add(ExtendableClientCapabilitiesJsonConverter.Instance);

            ILanguageServer server   = null;
            var             logLevel = RazorLSPOptions.GetLogLevelForTrace(trace);
            var             initializedCompletionSource = new TaskCompletionSource <bool>();

            server = OmniSharp.Extensions.LanguageServer.Server.LanguageServer.PreInit(options =>
                                                                                       options
                                                                                       .WithInput(input)
                                                                                       .WithOutput(output)
                                                                                       // StreamJsonRpc has both Serial and Parallel requests. With WithContentModifiedSupport(true) (which is default) when a Serial
                                                                                       // request is made any Parallel requests will be cancelled because the assumption is that Serial requests modify state, and that
                                                                                       // therefore any Parallel request is now invalid and should just try again. A specific instance of this can be seen when you
                                                                                       // hover over a TagHelper while the switch is set to true. Hover is parallel, and a lot of our endpoints like
                                                                                       // textDocument/_ms_onAutoInsert, and razor/languageQuery are Serial. I BELIEVE that specifically what happened is the serial
                                                                                       // languageQuery event gets fired by our semantic tokens endpoint (which fires constantly), cancelling the hover, which red-bars.
                                                                                       // We can prevent that behavior entirely by doing WithContentModifiedSupport, at the possible expense of some delays due doing all requests in serial.
                                                                                       //
                                                                                       // I recommend that we attempt to resolve this and switch back to WithContentModifiedSupport(true) in the future,
                                                                                       // I think that would mean either having 0 Serial Handlers in the whole LS, or making VSLanguageServerClient handle this more gracefully.
                                                                                       .WithContentModifiedSupport(false)
                                                                                       .WithSerializer(Serializer.Instance)
                                                                                       .OnInitialized(async(s, request, response, cancellationToken) =>
            {
                var handlersManager        = s.GetRequiredService <IHandlersManager>();
                var jsonRpcHandlers        = handlersManager.Descriptors.Select(d => d.Handler);
                var registrationExtensions = jsonRpcHandlers.OfType <IRegistrationExtension>().Distinct();
                if (registrationExtensions.Any())
                {
                    var capabilities      = new ExtendableServerCapabilities(response.Capabilities, registrationExtensions);
                    response.Capabilities = capabilities;
                }
                var fileChangeDetectorManager = s.Services.GetRequiredService <RazorFileChangeDetectorManager>();
                await fileChangeDetectorManager.InitializedAsync();

                // Workaround for https://github.com/OmniSharp/csharp-language-server-protocol/issues/106
                var languageServer = (OmniSharp.Extensions.LanguageServer.Server.LanguageServer)server;
                if (request.Capabilities.Workspace.Configuration.IsSupported)
                {
                    // Initialize our options for the first time.
                    var optionsMonitor = languageServer.Services.GetRequiredService <RazorLSPOptionsMonitor>();

                    // Explicitly not passing in the same CancellationToken as that might get cancelled before the update happens.
                    _ = Task.Delay(TimeSpan.FromSeconds(3))
                        .ContinueWith(async(_) => await optionsMonitor.UpdateAsync(), TaskScheduler.Default);
                }
            })
                                                                                       .WithHandler <RazorDocumentSynchronizationEndpoint>()
                                                                                       .WithHandler <RazorCompletionEndpoint>()
                                                                                       .WithHandler <RazorHoverEndpoint>()
                                                                                       .WithHandler <RazorLanguageEndpoint>()
                                                                                       .WithHandler <RazorDiagnosticsEndpoint>()
                                                                                       .WithHandler <RazorConfigurationEndpoint>()
                                                                                       .WithHandler <RazorFormattingEndpoint>()
                                                                                       .WithHandler <RazorSemanticTokensEndpoint>()
                                                                                       .AddHandlerLink(LanguageServerConstants.RazorSemanticTokensEditEndpoint, LanguageServerConstants.LegacyRazorSemanticTokensEditEndpoint)
                                                                                       .AddHandlerLink(LanguageServerConstants.RazorSemanticTokensEndpoint, LanguageServerConstants.LegacyRazorSemanticTokensEndpoint)
                                                                                       .WithHandler <RazorSemanticTokensLegendEndpoint>()
                                                                                       .WithHandler <OnAutoInsertEndpoint>()
                                                                                       .WithHandler <CodeActionEndpoint>()
                                                                                       .WithHandler <CodeActionResolutionEndpoint>()
                                                                                       .WithHandler <MonitorProjectConfigurationFilePathEndpoint>()
                                                                                       .WithHandler <RazorComponentRenameEndpoint>()
                                                                                       .WithHandler <RazorDefinitionEndpoint>()
                                                                                       .WithServices(services =>
            {
                services.AddLogging(builder => builder
                                    .SetMinimumLevel(logLevel)
                                    .AddLanguageProtocolLogging(logLevel));

                var filePathNormalizer = new FilePathNormalizer();
                services.AddSingleton <FilePathNormalizer>(filePathNormalizer);

                var foregroundDispatcher = new DefaultForegroundDispatcher();
                services.AddSingleton <ForegroundDispatcher>(foregroundDispatcher);

                var generatedDocumentPublisher = new DefaultGeneratedDocumentPublisher(foregroundDispatcher, new Lazy <OmniSharp.Extensions.LanguageServer.Protocol.Server.ILanguageServer>(() => server));
                services.AddSingleton <ProjectSnapshotChangeTrigger>(generatedDocumentPublisher);
                services.AddSingleton <GeneratedDocumentPublisher>(generatedDocumentPublisher);

                var documentVersionCache = new DefaultDocumentVersionCache(foregroundDispatcher);
                services.AddSingleton <DocumentVersionCache>(documentVersionCache);
                services.AddSingleton <ProjectSnapshotChangeTrigger>(documentVersionCache);
                var containerStore = new DefaultGeneratedDocumentContainerStore(
                    foregroundDispatcher,
                    documentVersionCache,
                    generatedDocumentPublisher);
                services.AddSingleton <GeneratedDocumentContainerStore>(containerStore);
                services.AddSingleton <ProjectSnapshotChangeTrigger>(containerStore);

                services.AddSingleton <RemoteTextLoaderFactory, DefaultRemoteTextLoaderFactory>();
                services.AddSingleton <ProjectResolver, DefaultProjectResolver>();
                services.AddSingleton <DocumentResolver, DefaultDocumentResolver>();
                services.AddSingleton <RazorProjectService, DefaultRazorProjectService>();
                services.AddSingleton <ProjectSnapshotChangeTrigger, BackgroundDocumentGenerator>();
                services.AddSingleton <RazorDocumentMappingService, DefaultRazorDocumentMappingService>();
                services.AddSingleton <RazorFileChangeDetectorManager>();

                services.AddSingleton <ProjectSnapshotChangeTrigger, RazorServerReadyPublisher>();

                services.AddSingleton <ClientNotifierServiceBase, DefaultClientNotifierService>();

                services.AddSingleton <IOnLanguageServerStarted, DefaultClientNotifierService>();

                // Options
                services.AddSingleton <RazorConfigurationService, DefaultRazorConfigurationService>();
                services.AddSingleton <RazorLSPOptionsMonitor>();
                services.AddSingleton <IOptionsMonitor <RazorLSPOptions>, RazorLSPOptionsMonitor>();

                // File change listeners
                services.AddSingleton <IProjectConfigurationFileChangeListener, ProjectConfigurationStateSynchronizer>();
                services.AddSingleton <IProjectFileChangeListener, ProjectFileSynchronizer>();
                services.AddSingleton <IRazorFileChangeListener, RazorFileSynchronizer>();

                // File Change detectors
                services.AddSingleton <IFileChangeDetector, ProjectConfigurationFileChangeDetector>();
                services.AddSingleton <IFileChangeDetector, ProjectFileChangeDetector>();
                services.AddSingleton <IFileChangeDetector, RazorFileChangeDetector>();

                // Document processed listeners
                services.AddSingleton <DocumentProcessedListener, RazorDiagnosticsPublisher>();
                services.AddSingleton <DocumentProcessedListener, UnsynchronizableContentDocumentProcessedListener>();

                services.AddSingleton <HostDocumentFactory, DefaultHostDocumentFactory>();
                services.AddSingleton <ProjectSnapshotManagerAccessor, DefaultProjectSnapshotManagerAccessor>();
                services.AddSingleton <TagHelperFactsService, DefaultTagHelperFactsService>();
                services.AddSingleton <TagHelperDescriptionFactory, DefaultTagHelperDescriptionFactory>();

                // Completion
                services.AddSingleton <TagHelperCompletionService, DefaultTagHelperCompletionService>();
                services.AddSingleton <RazorCompletionFactsService, DefaultRazorCompletionFactsService>();
                services.AddSingleton <RazorCompletionItemProvider, DirectiveCompletionItemProvider>();
                services.AddSingleton <RazorCompletionItemProvider, DirectiveAttributeCompletionItemProvider>();
                services.AddSingleton <RazorCompletionItemProvider, DirectiveAttributeParameterCompletionItemProvider>();
                services.AddSingleton <RazorCompletionItemProvider, DirectiveAttributeTransitionCompletionItemProvider>();
                services.AddSingleton <RazorCompletionItemProvider, MarkupTransitionCompletionItemProvider>();
                services.AddSingleton <RazorCompletionItemProvider, TagHelperCompletionProvider>();

                // Auto insert
                services.AddSingleton <RazorOnAutoInsertProvider, HtmlSmartIndentOnAutoInsertProvider>();
                services.AddSingleton <RazorOnAutoInsertProvider, CloseRazorCommentOnAutoInsertProvider>();
                services.AddSingleton <RazorOnAutoInsertProvider, CloseTextTagOnAutoInsertProvider>();
                services.AddSingleton <RazorOnAutoInsertProvider, AttributeSnippetOnAutoInsertProvider>();

                // Formatting
                services.AddSingleton <RazorFormattingService, DefaultRazorFormattingService>();

                // Formatting Passes
                services.AddSingleton <IFormattingPass, HtmlFormattingPass>();
                services.AddSingleton <IFormattingPass, CSharpFormattingPass>();
                services.AddSingleton <IFormattingPass, CSharpOnTypeFormattingPass>();
                services.AddSingleton <IFormattingPass, FormattingDiagnosticValidationPass>();
                services.AddSingleton <IFormattingPass, FormattingContentValidationPass>();

                // Razor Code actions
                services.AddSingleton <RazorCodeActionProvider, ExtractToCodeBehindCodeActionProvider>();
                services.AddSingleton <RazorCodeActionResolver, ExtractToCodeBehindCodeActionResolver>();
                services.AddSingleton <RazorCodeActionProvider, ComponentAccessibilityCodeActionProvider>();
                services.AddSingleton <RazorCodeActionResolver, CreateComponentCodeActionResolver>();
                services.AddSingleton <RazorCodeActionResolver, AddUsingsCodeActionResolver>();

                // CSharp Code actions
                services.AddSingleton <CSharpCodeActionProvider, TypeAccessibilityCodeActionProvider>();
                services.AddSingleton <CSharpCodeActionProvider, ImplementInterfaceAbstractClassCodeActionProvider>();
                services.AddSingleton <CSharpCodeActionProvider, DefaultCSharpCodeActionProvider>();
                services.AddSingleton <CSharpCodeActionResolver, DefaultCSharpCodeActionResolver>();
                services.AddSingleton <CSharpCodeActionResolver, AddUsingsCSharpCodeActionResolver>();

                // Other
                services.AddSingleton <RazorSemanticTokensInfoService, DefaultRazorSemanticTokensInfoService>();
                services.AddSingleton <RazorHoverInfoService, DefaultRazorHoverInfoService>();
                services.AddSingleton <HtmlFactsService, DefaultHtmlFactsService>();
                services.AddSingleton <WorkspaceDirectoryPathResolver, DefaultWorkspaceDirectoryPathResolver>();
                services.AddSingleton <RazorComponentSearchEngine, DefaultRazorComponentSearchEngine>();

                if (configure != null)
                {
                    var builder = new RazorLanguageServerBuilder(services);
                    configure(builder);
                }

                // Defaults: For when the caller hasn't provided them through the `configure` action.
                services.TryAddSingleton <LanguageServerFeatureOptions, DefaultLanguageServerFeatureOptions>();
            }));

            try
            {
                var factory = new LoggerFactory();
                var logger  = factory.CreateLogger <RazorLanguageServer>();
                var assemblyInformationAttribute = typeof(RazorLanguageServer).Assembly.GetCustomAttribute <AssemblyInformationalVersionAttribute>();
                logger.LogInformation("Razor Language Server version " + assemblyInformationAttribute.InformationalVersion);
                factory.Dispose();
            }
            catch
            {
                // Swallow exceptions from determining assembly information.
            }

            var razorLanguageServer = new RazorLanguageServer(server);

            IDisposable exitSubscription = null;

            exitSubscription = server.Exit.Subscribe((_) =>
            {
                exitSubscription.Dispose();
                razorLanguageServer.Dispose();
            });

            return(Task.FromResult(razorLanguageServer));
        }
        public static Task <RazorLanguageServer> CreateAsync(Stream input, Stream output, Trace trace, Action <RazorLanguageServerBuilder> configure = null)
        {
            Serializer.Instance.Settings.Converters.Add(SemanticTokensOrSemanticTokensEditsConverter.Instance);
            Serializer.Instance.JsonSerializer.Converters.RegisterRazorConverters();

            // Custom ClientCapabilities deserializer to extract experimental capabilities
            Serializer.Instance.JsonSerializer.Converters.Add(ExtendableClientCapabilitiesJsonConverter.Instance);

            ILanguageServer server = null;

            server = OmniSharp.Extensions.LanguageServer.Server.LanguageServer.PreInit(options =>
                                                                                       options
                                                                                       .WithInput(input)
                                                                                       .WithOutput(output)
                                                                                       .ConfigureLogging(builder => builder
                                                                                                         .AddLanguageServer(RazorLSPOptions.GetLogLevelForTrace(trace))
                                                                                                         .SetMinimumLevel(LogLevel.Trace)) // We set the minimum level here to "Trace" to ensure that other providers still get the opportunity to act on logs if they prefer.
                                                                                       .OnInitialized(async(s, request, response) =>
            {
                var jsonRpcHandlers        = s.Services.GetServices <IJsonRpcHandler>();
                var registrationExtensions = jsonRpcHandlers.OfType <IRegistrationExtension>();
                if (registrationExtensions.Any())
                {
                    var capabilities      = new ExtendableServerCapabilities(response.Capabilities, registrationExtensions);
                    response.Capabilities = capabilities;
                }

                var fileChangeDetectorManager = s.Services.GetRequiredService <RazorFileChangeDetectorManager>();
                await fileChangeDetectorManager.InitializedAsync();

                // Workaround for https://github.com/OmniSharp/csharp-language-server-protocol/issues/106
                var languageServer = (OmniSharp.Extensions.LanguageServer.Server.LanguageServer)server;
                if (request.Capabilities.Workspace.Configuration.IsSupported)
                {
                    // Initialize our options for the first time.
                    var optionsMonitor = languageServer.Services.GetRequiredService <RazorLSPOptionsMonitor>();
                    _ = Task.Delay(TimeSpan.FromSeconds(3)).ContinueWith(async(_) => await optionsMonitor.UpdateAsync());
                }
            })
                                                                                       .WithHandler <RazorDocumentSynchronizationEndpoint>()
                                                                                       .WithHandler <RazorCompletionEndpoint>()
                                                                                       .WithHandler <RazorHoverEndpoint>()
                                                                                       .WithHandler <RazorLanguageEndpoint>()
                                                                                       .WithHandler <RazorConfigurationEndpoint>()
                                                                                       .WithHandler <RazorFormattingEndpoint>()
                                                                                       .WithHandler <RazorSemanticTokensEndpoint>()
                                                                                       .WithHandler <RazorSemanticTokensLegendEndpoint>()
                                                                                       .WithHandler <OnAutoInsertEndpoint>()
                                                                                       .WithHandler <CodeActionEndpoint>()
                                                                                       .WithHandler <CodeActionResolutionEndpoint>()
                                                                                       .WithHandler <MonitorProjectConfigurationFilePathEndpoint>()
                                                                                       .WithHandler <RazorComponentRenameEndpoint>()
                                                                                       .WithHandler <RazorDefinitionEndpoint>()
                                                                                       .WithServices(services =>
            {
                if (configure != null)
                {
                    var builder = new RazorLanguageServerBuilder(services);
                    configure(builder);
                }

                var filePathNormalizer = new FilePathNormalizer();
                services.AddSingleton <FilePathNormalizer>(filePathNormalizer);

                var foregroundDispatcher = new DefaultForegroundDispatcher();
                services.AddSingleton <ForegroundDispatcher>(foregroundDispatcher);

                var generatedDocumentPublisher = new DefaultGeneratedDocumentPublisher(foregroundDispatcher, new Lazy <OmniSharp.Extensions.LanguageServer.Protocol.Server.ILanguageServer>(() => server));
                services.AddSingleton <ProjectSnapshotChangeTrigger>(generatedDocumentPublisher);
                services.AddSingleton <GeneratedDocumentPublisher>(generatedDocumentPublisher);

                var documentVersionCache = new DefaultDocumentVersionCache(foregroundDispatcher);
                services.AddSingleton <DocumentVersionCache>(documentVersionCache);
                services.AddSingleton <ProjectSnapshotChangeTrigger>(documentVersionCache);
                var containerStore = new DefaultGeneratedDocumentContainerStore(
                    foregroundDispatcher,
                    documentVersionCache,
                    generatedDocumentPublisher);
                services.AddSingleton <GeneratedDocumentContainerStore>(containerStore);
                services.AddSingleton <ProjectSnapshotChangeTrigger>(containerStore);

                services.AddSingleton <RemoteTextLoaderFactory, DefaultRemoteTextLoaderFactory>();
                services.AddSingleton <ProjectResolver, DefaultProjectResolver>();
                services.AddSingleton <DocumentResolver, DefaultDocumentResolver>();
                services.AddSingleton <RazorProjectService, DefaultRazorProjectService>();
                services.AddSingleton <ProjectSnapshotChangeTrigger, BackgroundDocumentGenerator>();
                services.AddSingleton <RazorDocumentMappingService, DefaultRazorDocumentMappingService>();
                services.AddSingleton <RazorFileChangeDetectorManager>();

                // Options
                services.AddSingleton <RazorConfigurationService, DefaultRazorConfigurationService>();
                services.AddSingleton <RazorLSPOptionsMonitor>();
                services.AddSingleton <IOptionsMonitor <RazorLSPOptions>, RazorLSPOptionsMonitor>();

                // File change listeners
                services.AddSingleton <IProjectConfigurationFileChangeListener, ProjectConfigurationStateSynchronizer>();
                services.AddSingleton <IProjectFileChangeListener, ProjectFileSynchronizer>();
                services.AddSingleton <IRazorFileChangeListener, RazorFileSynchronizer>();

                // File Change detectors
                services.AddSingleton <IFileChangeDetector, ProjectConfigurationFileChangeDetector>();
                services.AddSingleton <IFileChangeDetector, ProjectFileChangeDetector>();
                services.AddSingleton <IFileChangeDetector, RazorFileChangeDetector>();

                // Document processed listeners
                services.AddSingleton <DocumentProcessedListener, RazorDiagnosticsPublisher>();
                services.AddSingleton <DocumentProcessedListener, UnsynchronizableContentDocumentProcessedListener>();

                services.AddSingleton <HostDocumentFactory, DefaultHostDocumentFactory>();
                services.AddSingleton <ProjectSnapshotManagerAccessor, DefaultProjectSnapshotManagerAccessor>();
                services.AddSingleton <TagHelperFactsService, DefaultTagHelperFactsService>();
                services.AddSingleton <VisualStudio.Editor.Razor.TagHelperCompletionService, VisualStudio.Editor.Razor.DefaultTagHelperCompletionService>();
                services.AddSingleton <TagHelperDescriptionFactory, DefaultTagHelperDescriptionFactory>();

                // Completion
                services.AddSingleton <Completion.TagHelperCompletionService, Completion.DefaultTagHelperCompletionService>();
                services.AddSingleton <RazorCompletionItemProvider, DirectiveCompletionItemProvider>();
                services.AddSingleton <RazorCompletionItemProvider, DirectiveAttributeCompletionItemProvider>();
                services.AddSingleton <RazorCompletionItemProvider, DirectiveAttributeParameterCompletionItemProvider>();
                services.AddSingleton <RazorCompletionItemProvider, DirectiveAttributeTransitionCompletionItemProvider>();
                services.AddSingleton <RazorCompletionItemProvider, MarkupTransitionCompletionItemProvider>();

                // Auto insert
                services.AddSingleton <RazorOnAutoInsertProvider, HtmlSmartIndentOnAutoInsertProvider>();
                services.AddSingleton <RazorOnAutoInsertProvider, CloseRazorCommentOnAutoInsertProvider>();
                services.AddSingleton <RazorOnAutoInsertProvider, CloseTextTagOnAutoInsertProvider>();
                services.AddSingleton <RazorOnAutoInsertProvider, AttributeSnippetOnAutoInsertProvider>();

                // Formatting
                services.AddSingleton <RazorFormattingService, DefaultRazorFormattingService>();

                // Formatting Passes
                services.AddSingleton <IFormattingPass, CodeBlockDirectiveFormattingPass>();
                services.AddSingleton <IFormattingPass, CSharpOnTypeFormattingPass>();
                services.AddSingleton <IFormattingPass, FormattingStructureValidationPass>();
                services.AddSingleton <IFormattingPass, FormattingContentValidationPass>();

                // Code actions
                services.AddSingleton <RazorCodeActionProvider, ExtractToCodeBehindCodeActionProvider>();
                services.AddSingleton <RazorCodeActionResolver, ExtractToCodeBehindCodeActionResolver>();
                services.AddSingleton <RazorCodeActionProvider, ComponentAccessibilityCodeActionProvider>();
                services.AddSingleton <RazorCodeActionResolver, CreateComponentCodeActionResolver>();
                services.AddSingleton <RazorCodeActionResolver, AddUsingsCodeActionResolver>();

                // Other
                services.AddSingleton <RazorCompletionFactsService, DefaultRazorCompletionFactsService>();
                services.AddSingleton <RazorSemanticTokensInfoService, DefaultRazorSemanticTokensInfoService>();
                services.AddSingleton <RazorHoverInfoService, DefaultRazorHoverInfoService>();
                services.AddSingleton <HtmlFactsService, DefaultHtmlFactsService>();
                services.AddSingleton <WorkspaceDirectoryPathResolver, DefaultWorkspaceDirectoryPathResolver>();
                services.AddSingleton <RazorComponentSearchEngine, DefaultRazorComponentSearchEngine>();
            }));

            try
            {
                var factory = new LoggerFactory();
                var logger  = factory.CreateLogger <RazorLanguageServer>();
                var assemblyInformationAttribute = typeof(RazorLanguageServer).Assembly.GetCustomAttribute <AssemblyInformationalVersionAttribute>();
                logger.LogInformation("Razor Language Server version " + assemblyInformationAttribute.InformationalVersion);
                factory.Dispose();
            }
            catch
            {
                // Swallow exceptions from determining assembly information.
            }

            var razorLanguageServer = new RazorLanguageServer(server);

            IDisposable exitSubscription = null;

            exitSubscription = server.Exit.Subscribe((_) =>
            {
                exitSubscription.Dispose();
                razorLanguageServer.Dispose();
            });

            return(Task.FromResult(razorLanguageServer));
        }
예제 #15
0
        public static async Task MainAsync(string[] args)
        {
            var logLevel = LogLevel.Information;

            for (var i = 0; i < args.Length; i++)
            {
                if (args[i].IndexOf("debug", StringComparison.OrdinalIgnoreCase) >= 0)
                {
                    while (!Debugger.IsAttached)
                    {
                        Thread.Sleep(1000);
                    }

                    Debugger.Break();
                    continue;
                }

                if (args[i] == "--logLevel" && i + 1 < args.Length)
                {
                    var logLevelString = args[++i];
                    if (!Enum.TryParse(logLevelString, out logLevel))
                    {
                        logLevel = LogLevel.Information;
                        Console.WriteLine($"Invalid log level '{logLevelString}'. Defaulting to {logLevel.ToString()}.");
                    }
                }
            }

            Serializer.Instance.JsonSerializer.Converters.RegisterRazorConverters();

            var             factory = new LoggerFactory();
            ILanguageServer server  = null;

            server = await OmniSharp.Extensions.LanguageServer.Server.LanguageServer.From(options =>
                                                                                          options
                                                                                          .WithInput(Console.OpenStandardInput())
                                                                                          .WithOutput(Console.OpenStandardOutput())
                                                                                          .WithLoggerFactory(factory)
                                                                                          .AddDefaultLoggingProvider()
                                                                                          .WithMinimumLogLevel(logLevel)
                                                                                          .WithHandler <RazorDocumentSynchronizationEndpoint>()
                                                                                          .WithHandler <RazorCompletionEndpoint>()
                                                                                          .WithHandler <RazorHoverEndpoint>()
                                                                                          .WithHandler <RazorLanguageEndpoint>()
                                                                                          .WithHandler <RazorProjectEndpoint>()
                                                                                          .WithServices(services =>
            {
                services.AddSingleton <RemoteTextLoaderFactory, DefaultRemoteTextLoaderFactory>();
                services.AddSingleton <ProjectResolver, DefaultProjectResolver>();
                services.AddSingleton <DocumentResolver, DefaultDocumentResolver>();
                services.AddSingleton <FilePathNormalizer>();
                services.AddSingleton <RazorProjectService, DefaultRazorProjectService>();
                services.AddSingleton <ProjectSnapshotChangeTrigger, BackgroundDocumentGenerator>();

                // Document processed listeners
                services.AddSingleton <DocumentProcessedListener, RazorDiagnosticsPublisher>();
                services.AddSingleton <DocumentProcessedListener, UnsynchronizableContentDocumentProcessedListener>();

                services.AddSingleton <HostDocumentFactory, DefaultHostDocumentFactory>();
                services.AddSingleton <ProjectSnapshotManagerAccessor, DefaultProjectSnapshotManagerAccessor>();
                services.AddSingleton <TagHelperFactsService, DefaultTagHelperFactsService>();
                services.AddSingleton <VisualStudio.Editor.Razor.TagHelperCompletionService, VisualStudio.Editor.Razor.DefaultTagHelperCompletionService>();
                services.AddSingleton <TagHelperDescriptionFactory, DefaultTagHelperDescriptionFactory>();

                // Completion
                services.AddSingleton <Completion.TagHelperCompletionService, Completion.DefaultTagHelperCompletionService>();
                services.AddSingleton <RazorCompletionItemProvider, DirectiveCompletionItemProvider>();
                services.AddSingleton <RazorCompletionItemProvider, DirectiveAttributeCompletionItemProvider>();
                services.AddSingleton <RazorCompletionItemProvider, DirectiveAttributeParameterCompletionItemProvider>();
                services.AddSingleton <RazorCompletionItemProvider, DirectiveAttributeTransitionCompletionItemProvider>();

                var foregroundDispatcher = new VSCodeForegroundDispatcher();
                services.AddSingleton <ForegroundDispatcher>(foregroundDispatcher);

                var csharpPublisher = new DefaultCSharpPublisher(foregroundDispatcher, new Lazy <OmniSharp.Extensions.LanguageServer.Protocol.Server.ILanguageServer>(() => server));
                services.AddSingleton <ProjectSnapshotChangeTrigger>(csharpPublisher);
                services.AddSingleton <CSharpPublisher>(csharpPublisher);

                services.AddSingleton <RazorCompletionFactsService, DefaultRazorCompletionFactsService>();
                services.AddSingleton <RazorHoverInfoService, DefaultRazorHoverInfoService>();
                services.AddSingleton <HtmlFactsService, DefaultHtmlFactsService>();
                var documentVersionCache = new DefaultDocumentVersionCache(foregroundDispatcher);
                services.AddSingleton <DocumentVersionCache>(documentVersionCache);
                services.AddSingleton <ProjectSnapshotChangeTrigger>(documentVersionCache);
                var containerStore = new DefaultGeneratedCodeContainerStore(
                    foregroundDispatcher,
                    documentVersionCache,
                    csharpPublisher);
                services.AddSingleton <GeneratedCodeContainerStore>(containerStore);
                services.AddSingleton <ProjectSnapshotChangeTrigger>(containerStore);
            }));

            // Workaround for https://github.com/OmniSharp/csharp-language-server-protocol/issues/106
            var languageServer = (OmniSharp.Extensions.LanguageServer.Server.LanguageServer)server;

            languageServer.MinimumLogLevel = logLevel;

            try
            {
                var logger = factory.CreateLogger <Program>();
                var assemblyInformationAttribute = typeof(Program).Assembly.GetCustomAttribute <AssemblyInformationalVersionAttribute>();
                logger.LogInformation("Razor Language Server version " + assemblyInformationAttribute.InformationalVersion);
            }
            catch
            {
                // Swallow exceptions from determining assembly information.
            }

            await server.WaitForExit;

            TempDirectory.Instance.Dispose();
        }