diff --git a/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Diagnostics/RazorTranslateDiagnosticsService.cs b/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Diagnostics/RazorTranslateDiagnosticsService.cs index 57c508300c6..ada0dc0e66e 100644 --- a/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Diagnostics/RazorTranslateDiagnosticsService.cs +++ b/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Diagnostics/RazorTranslateDiagnosticsService.cs @@ -453,13 +453,19 @@ private static bool InAttributeContainingCSharp( if (markupAttributeValue is not null) { - if (!processedAttributes.TryGetValue(markupAttributeValue.Span, out var doesAttributeContainNonMarkup)) + if (!processedAttributes.TryGetValue(markupAttributeValue.Span, out var shouldFilterDiagnostic)) { - doesAttributeContainNonMarkup = CheckIfAttributeContainsNonMarkupNodes(markupAttributeValue); - processedAttributes.Add(markupAttributeValue.Span, doesAttributeContainNonMarkup); + // If a component attribute is spread across multiple lines, it's not valid Html so the Html server can't be expected to reason + // about the contents correctly + shouldFilterDiagnostic = markupAttributeValue is MarkupTagHelperAttributeValueSyntax && + markupAttributeValue.GetLinePositionSpan(syntaxTree.Source).SpansMultipleLines(); + + // Similarly, if the attribute value contains non-markup, the Html could report false positives + shouldFilterDiagnostic |= CheckIfAttributeContainsNonMarkupNodes(markupAttributeValue); + processedAttributes.Add(markupAttributeValue.Span, shouldFilterDiagnostic); } - return doesAttributeContainNonMarkup; + return shouldFilterDiagnostic; } return false; diff --git a/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/Cohost/CohostDocumentPullDiagnosticsTest.cs b/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/Cohost/CohostDocumentPullDiagnosticsTest.cs index 563c963418c..29eb46212af 100644 --- a/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/Cohost/CohostDocumentPullDiagnosticsTest.cs +++ b/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/Cohost/CohostDocumentPullDiagnosticsTest.cs @@ -420,6 +420,58 @@ public Task FilterPropertyNameInCss() }]); } + [Fact] + public Task FilterFromMultilineComponentAttributes() + { + var firstLine = "Hello this is a"; + TestCode input = $$""" + + + @code + { + [Parameter] + public string Title { get; set; } + } + """; + + return VerifyDiagnosticsAsync(input, + htmlResponse: [new VSInternalDiagnosticReport + { + Diagnostics = + [ + new LspDiagnostic + { + Code = HtmlErrorCodes.MismatchedAttributeQuotesErrorCode, + Range = SourceText.From(input.Text).GetRange(new TextSpan(input.Text.IndexOf(firstLine), firstLine.Length)) + }, + ] + }]); + } + + [Fact] + public Task DontFilterFromMultilineHtmlAttributes() + { + var firstLine = "Hello this is a"; + TestCode input = $$""" +
+ """; + + return VerifyDiagnosticsAsync(input, + htmlResponse: [new VSInternalDiagnosticReport + { + Diagnostics = + [ + new LspDiagnostic + { + Code = HtmlErrorCodes.MismatchedAttributeQuotesErrorCode, + Range = SourceText.From(input.Text).GetRange(new TextSpan(input.Text.IndexOf(firstLine), firstLine.Length)) + }, + ] + }]); + } + [Theory] [InlineData("", "\"")] [InlineData("", "'")]