public override async Task <InterceptionResult> ApplyChangesAsync(JToken token, string containedLanguageName, CancellationToken cancellationToken) { if (token is null) { throw new ArgumentNullException(nameof(token)); } cancellationToken.ThrowIfCancellationRequested(); // The diagnostics interceptor isn't a part of the HTMLCSharpLanguageServer stack as it's lifecycle is a bit different. // It initializes before the actual language server, as we export it to be used directly with WTE. // Consequently, if we don't initialize the logger here, then the logger will be unavailable for logging. await InitializeLogHubLoggerAsync(cancellationToken).ConfigureAwait(false); var diagnosticParams = token.ToObject <PublishDiagnosticParams>(); if (diagnosticParams?.Uri is null) { var exception = new ArgumentException("Conversion of token failed."); _logger?.LogError(exception, $"Not a {nameof(PublishDiagnosticParams)}"); throw exception; } // We only support interception of Virtual HTML Files if (!RazorLSPConventions.IsVirtualHtmlFile(diagnosticParams.Uri)) { return(CreateDefaultResponse(token)); } _logger?.LogInformation($"Received HTML Publish diagnostic request for {diagnosticParams.Uri} with {diagnosticParams.Diagnostics.Length} diagnostics."); var htmlDocumentUri = diagnosticParams.Uri; var razorDocumentUri = RazorLSPConventions.GetRazorDocumentUri(htmlDocumentUri); // Note; this is an `interceptor` & not a handler, hence // it's possible another interceptor mutates this request // later in the toolchain. Such an interceptor would likely // expect a `__virtual.html` suffix instead of `.razor`. diagnosticParams.Uri = razorDocumentUri; if (!_documentManager.TryGetDocument(razorDocumentUri, out var razorDocumentSnapshot)) { _logger?.LogInformation($"Failed to find document {razorDocumentUri}."); return(CreateEmptyDiagnosticsResponse(diagnosticParams)); } if (!razorDocumentSnapshot.TryGetVirtualDocument <HtmlVirtualDocumentSnapshot>(out var htmlDocumentSnapshot) || !htmlDocumentSnapshot.Uri.Equals(htmlDocumentUri)) { _logger?.LogInformation($"Failed to find virtual HTML document {htmlDocumentUri}."); return(CreateEmptyDiagnosticsResponse(diagnosticParams)); } // Return early if there aren't any diagnostics to process if (diagnosticParams.Diagnostics?.Any() != true) { _logger?.LogInformation("No diagnostics to process."); return(CreateResponse(diagnosticParams)); } var processedDiagnostics = await _diagnosticsProvider.TranslateAsync( RazorLanguageKind.Html, razorDocumentUri, diagnosticParams.Diagnostics, cancellationToken ).ConfigureAwait(false); if (processedDiagnostics is null) { _logger?.LogWarning($"Failed to semnd request to diagnostic translation server for {htmlDocumentUri}."); return(CreateEmptyDiagnosticsResponse(diagnosticParams)); } // Note it's possible the document version changed between when the diagnostics were created // and when we finished remapping the diagnostics. This could result in lingering / misaligned diagnostics. // We're choosing to do this over clearing out the diagnostics as that would lead to flickering. // // This'll need to be revisited based on preferences with flickering vs lingering. _logger?.LogInformation($"Returning {processedDiagnostics.Diagnostics.Length} diagnostics."); diagnosticParams.Diagnostics = processedDiagnostics.Diagnostics; return(CreateResponse(diagnosticParams));
public override async Task <InterceptionResult> ApplyChangesAsync(JToken token, string containedLanguageName, CancellationToken cancellationToken) { if (token is null) { throw new ArgumentNullException(nameof(token)); } cancellationToken.ThrowIfCancellationRequested(); var diagnosticParams = token.ToObject <VSPublishDiagnosticParams>(); if (diagnosticParams is null) { throw new ArgumentException("Conversion of token failed."); } // We only support interception of Virtual HTML Files if (!RazorLSPConventions.IsVirtualHtmlFile(diagnosticParams.Uri)) { return(CreateDefaultResponse(token)); } var htmlDocumentUri = diagnosticParams.Uri; var razorDocumentUri = RazorLSPConventions.GetRazorDocumentUri(htmlDocumentUri); // Note; this is an `interceptor` & not a handler, hence // it's possible another interceptor mutates this request // later in the toolchain. Such an interceptor would likely // expect a `__virtual.html` suffix instead of `.razor`. diagnosticParams.Uri = razorDocumentUri; if (!_documentManager.TryGetDocument(razorDocumentUri, out var razorDocumentSnapshot)) { return(CreateEmptyDiagnosticsResponse(diagnosticParams)); } if (!razorDocumentSnapshot.TryGetVirtualDocument <HtmlVirtualDocumentSnapshot>(out var htmlDocumentSnapshot) || !htmlDocumentSnapshot.Uri.Equals(htmlDocumentUri)) { return(CreateEmptyDiagnosticsResponse(diagnosticParams)); } // Return early if there aren't any diagnostics to process if (diagnosticParams.Diagnostics?.Any() != true) { return(CreateResponse(diagnosticParams)); } var processedDiagnostics = await _diagnosticsProvider.TranslateAsync( RazorLanguageKind.Html, razorDocumentUri, diagnosticParams.Diagnostics, cancellationToken ).ConfigureAwait(false); // Note it's possible the document version changed between when the diagnostics were created // and when we finished remapping the diagnostics. This could result in lingering / misaligned diagnostics. // We're choosing to do this over clearing out the diagnostics as that would lead to flickering. // // This'll need to be revisited based on preferences with flickering vs lingering. diagnosticParams.Diagnostics = processedDiagnostics.Diagnostics; return(CreateResponse(diagnosticParams));