|
1 | 1 | // Copyright (c) .NET Foundation. All rights reserved. |
2 | 2 | // Licensed under the MIT license. See License.txt in the project root for license information. |
3 | 3 |
|
4 | | -using System; |
5 | 4 | using System.Collections.Immutable; |
6 | 5 | using System.Linq; |
7 | 6 | using System.Text; |
8 | 7 | using System.Threading.Tasks; |
9 | 8 | using Microsoft.AspNetCore.Razor; |
10 | 9 | using Microsoft.AspNetCore.Razor.Language; |
| 10 | +using Microsoft.AspNetCore.Razor.PooledObjects; |
11 | 11 | using Microsoft.CodeAnalysis.Razor.Workspaces; |
12 | 12 | using Microsoft.CodeAnalysis.Testing; |
13 | 13 | using Microsoft.CodeAnalysis.Text; |
@@ -197,40 +197,93 @@ public void M() {[| |
197 | 197 | }|] |
198 | 198 | """); |
199 | 199 |
|
| 200 | + [Fact] |
| 201 | + public Task HtmlAndCSharp() |
| 202 | + => VerifyFoldingRangesAsync(""" |
| 203 | + <div>{|html: |
| 204 | + Hello @_name |
| 205 | +
|
| 206 | + <div>{|html: |
| 207 | + Nests aren't just for birds! |
| 208 | + </div>|} |
| 209 | + </div>|} |
| 210 | +
|
| 211 | + @code {[| |
| 212 | + private string _name = "Dave"; |
| 213 | +
|
| 214 | + public void M() {[| |
| 215 | + }|] |
| 216 | + }|] |
| 217 | + """); |
| 218 | + |
200 | 219 | private async Task VerifyFoldingRangesAsync(string input, string? fileKind = null) |
201 | 220 | { |
202 | | - TestFileMarkupParser.GetSpans(input, out var source, out ImmutableArray<TextSpan> expected); |
| 221 | + TestFileMarkupParser.GetSpans(input, out var source, out ImmutableDictionary<string, ImmutableArray<TextSpan>> spans); |
203 | 222 | var document = CreateProjectAndRazorDocument(source, fileKind); |
204 | | - |
205 | | - var requestInvoker = new TestLSPRequestInvoker([(Methods.TextDocumentFoldingRangeName, Array.Empty<FoldingRange>())]); |
| 223 | + var inputText = await document.GetTextAsync(DisposalToken); |
| 224 | + |
| 225 | + var htmlSpans = spans.GetValueOrDefault("html").NullToEmpty(); |
| 226 | + var htmlRanges = htmlSpans |
| 227 | + .Select(span => |
| 228 | + { |
| 229 | + inputText.GetLineAndOffset(span.Start, out var startLine, out var startCharacter); |
| 230 | + inputText.GetLineAndOffset(span.End, out var endLine, out var endCharacter); |
| 231 | + return new FoldingRange() |
| 232 | + { |
| 233 | + StartLine = startLine, |
| 234 | + StartCharacter = startCharacter, |
| 235 | + EndLine = endLine, |
| 236 | + EndCharacter = endCharacter |
| 237 | + }; |
| 238 | + }) |
| 239 | + .ToArray(); |
| 240 | + |
| 241 | + var requestInvoker = new TestLSPRequestInvoker([(Methods.TextDocumentFoldingRangeName, htmlRanges)]); |
206 | 242 |
|
207 | 243 | var endpoint = new CohostFoldingRangeEndpoint(RemoteServiceInvoker, TestHtmlDocumentSynchronizer.Instance, requestInvoker, LoggerFactory); |
208 | 244 |
|
209 | 245 | var result = await endpoint.GetTestAccessor().HandleRequestAsync(document, DisposalToken); |
210 | 246 |
|
211 | | - if (expected.Length == 0) |
| 247 | + if (spans.Count == 0) |
212 | 248 | { |
213 | 249 | Assert.Null(result); |
214 | 250 | return; |
215 | 251 | } |
216 | 252 |
|
217 | | - // Rather than comparing numbers and spans, its nicer to reconstruct the test input data and use string comparisons so we can |
218 | | - // more easily understand what went wrong. |
| 253 | + var actual = GenerateTestInput(inputText, htmlSpans, result.AssumeNotNull()); |
219 | 254 |
|
220 | | - var inputText = SourceText.From(source); |
| 255 | + AssertEx.EqualOrDiff(input, actual); |
| 256 | + } |
| 257 | + |
| 258 | + private static string GenerateTestInput(SourceText inputText, ImmutableArray<TextSpan> htmlSpans, FoldingRange[] result) |
| 259 | + { |
221 | 260 | var markerPositions = result |
222 | 261 | .SelectMany(r => |
223 | 262 | new[] { |
224 | 263 | (index: inputText.GetRequiredAbsoluteIndex(r.StartLine, r.StartCharacter.AssumeNotNull()), isStart: true), |
225 | 264 | (index: inputText.GetRequiredAbsoluteIndex(r.EndLine, r.EndCharacter.AssumeNotNull()), isStart: false) |
226 | 265 | }); |
227 | 266 |
|
228 | | - var actual = new StringBuilder(source); |
| 267 | + var actual = new StringBuilder(inputText.ToString()); |
229 | 268 | foreach (var marker in markerPositions.OrderByDescending(p => p.index)) |
230 | 269 | { |
231 | | - actual.Insert(marker.index, marker.isStart ? "[|" : "|]"); |
| 270 | + actual.Insert(marker.index, GetMarker(marker.index, marker.isStart, htmlSpans)); |
| 271 | + } |
| 272 | + |
| 273 | + static string GetMarker(int index, bool isStart, ImmutableArray<TextSpan> htmlSpans) |
| 274 | + { |
| 275 | + if (isStart) |
| 276 | + { |
| 277 | + return htmlSpans.Any(r => r.Start == index) |
| 278 | + ? "{|html:" |
| 279 | + : "[|"; |
| 280 | + } |
| 281 | + |
| 282 | + return htmlSpans.Any(r => r.End == index) |
| 283 | + ? "|}" |
| 284 | + : "|]"; |
232 | 285 | } |
233 | 286 |
|
234 | | - AssertEx.EqualOrDiff(input, actual.ToString()); |
| 287 | + return actual.ToString(); |
235 | 288 | } |
236 | 289 | } |
0 commit comments