77using System . Threading ;
88using System . Threading . Tasks ;
99using Microsoft . AspNetCore . Razor ;
10+ using Microsoft . AspNetCore . Razor . Language ;
1011using Microsoft . AspNetCore . Razor . PooledObjects ;
1112using Microsoft . CodeAnalysis . ExternalAccess . Razor ;
13+ using Microsoft . CodeAnalysis . Razor . DocumentExcerpt ;
1214using Microsoft . CodeAnalysis . Razor . DocumentMapping ;
1315using Microsoft . CodeAnalysis . Razor . Protocol ;
1416using Microsoft . CodeAnalysis . Razor . Remote ;
@@ -30,6 +32,54 @@ protected override IRemoteSpanMappingService CreateService(in ServiceArgs args)
3032 private readonly IDocumentMappingService _documentMappingService = args . ExportProvider . GetExportedValue < IDocumentMappingService > ( ) ;
3133 private readonly ITelemetryReporter _telemetryReporter = args . ExportProvider . GetExportedValue < ITelemetryReporter > ( ) ;
3234
35+ public ValueTask < RemoteExcerptResult ? > TryExcerptAsync ( RazorPinnedSolutionInfoWrapper solutionInfo , DocumentId generatedDocumentId , TextSpan span , RazorExcerptMode mode , RazorClassificationOptionsWrapper options , CancellationToken cancellationToken )
36+ => RunServiceAsync (
37+ solutionInfo ,
38+ solution => TryExcerptAsync ( solution , generatedDocumentId , span , mode , options , cancellationToken ) ,
39+ cancellationToken ) ;
40+
41+ private async ValueTask < RemoteExcerptResult ? > TryExcerptAsync ( Solution solution , DocumentId generatedDocumentId , TextSpan span , RazorExcerptMode mode , RazorClassificationOptionsWrapper options , CancellationToken cancellationToken )
42+ {
43+ var generatedDocument = await solution . GetSourceGeneratedDocumentAsync ( generatedDocumentId , cancellationToken ) . ConfigureAwait ( false ) ;
44+ if ( generatedDocument is null )
45+ {
46+ return null ;
47+ }
48+
49+ var razorDocument = await TryGetRazorDocumentForGeneratedDocumentAsync ( generatedDocument , cancellationToken ) . ConfigureAwait ( false ) ;
50+ if ( razorDocument is null )
51+ {
52+ return null ;
53+ }
54+
55+ var documentSnapshot = _snapshotManager . GetSnapshot ( razorDocument ) ;
56+ var codeDocument = await documentSnapshot . GetGeneratedOutputAsync ( cancellationToken ) . ConfigureAwait ( false ) ;
57+
58+ var mappedSpans = MapSpans ( codeDocument , [ span ] ) ;
59+ if ( mappedSpans is not [ { IsDefault : false } mappedSpan ] )
60+ {
61+ return null ;
62+ }
63+
64+ var razorDocumentText = await razorDocument . GetTextAsync ( cancellationToken ) . ConfigureAwait ( false ) ;
65+ var razorDocumentSpan = razorDocumentText . GetTextSpan ( mappedSpan . LinePositionSpan ) ;
66+
67+ // First compute the range of text we want to we to display relative to the primary document.
68+ var excerptSpan = DocumentExcerptHelper . ChooseExcerptSpan ( razorDocumentText , razorDocumentSpan , ( ExcerptModeInternal ) mode ) ;
69+
70+ // Then we'll classify the spans based on the primary document, since that's the coordinate
71+ // space that our output mappings use.
72+ var mappings = codeDocument . GetRequiredCSharpDocument ( ) . SourceMappings ;
73+ var classifiedSpans = await DocumentExcerptHelper . ClassifyPreviewAsync (
74+ excerptSpan ,
75+ generatedDocument ,
76+ mappings ,
77+ options ,
78+ cancellationToken ) . ConfigureAwait ( false ) ;
79+
80+ return new RemoteExcerptResult ( razorDocument . Id , razorDocumentSpan , excerptSpan , classifiedSpans . ToImmutable ( ) , span ) ;
81+ }
82+
3383 public ValueTask < ImmutableArray < RazorMappedSpanResult > > MapSpansAsync ( RazorPinnedSolutionInfoWrapper solutionInfo , DocumentId generatedDocumentId , ImmutableArray < TextSpan > spans , CancellationToken cancellationToken )
3484 => RunServiceAsync (
3585 solutionInfo ,
@@ -45,12 +95,17 @@ private async ValueTask<ImmutableArray<RazorMappedSpanResult>> MapSpansAsync(Sol
4595 }
4696
4797 var documentSnapshot = _snapshotManager . GetSnapshot ( razorDocument ) ;
48- var output = await documentSnapshot . GetGeneratedOutputAsync ( cancellationToken ) . ConfigureAwait ( false ) ;
98+ var codeDocument = await documentSnapshot . GetGeneratedOutputAsync ( cancellationToken ) . ConfigureAwait ( false ) ;
99+
100+ return MapSpans ( codeDocument , spans ) ;
101+ }
49102
50- var source = output . Source . Text ;
103+ private static ImmutableArray < RazorMappedSpanResult > MapSpans ( RazorCodeDocument codeDocument , ImmutableArray < TextSpan > spans )
104+ {
105+ var source = codeDocument . Source . Text ;
51106
52- var csharpDocument = output . GetRequiredCSharpDocument ( ) ;
53- var filePath = output . Source . FilePath . AssumeNotNull ( ) ;
107+ var csharpDocument = codeDocument . GetRequiredCSharpDocument ( ) ;
108+ var filePath = codeDocument . Source . FilePath . AssumeNotNull ( ) ;
54109
55110 using var results = new PooledArrayBuilder < RazorMappedSpanResult > ( ) ;
56111
@@ -118,6 +173,11 @@ private async ValueTask<ImmutableArray<RazorMappedEditResult>> MapTextChangesAsy
118173 return null ;
119174 }
120175
176+ return await TryGetRazorDocumentForGeneratedDocumentAsync ( generatedDocument , cancellationToken ) . ConfigureAwait ( false ) ;
177+ }
178+
179+ private async Task < TextDocument ? > TryGetRazorDocumentForGeneratedDocumentAsync ( SourceGeneratedDocument generatedDocument , CancellationToken cancellationToken )
180+ {
121181 var identity = RazorGeneratedDocumentIdentity . Create ( generatedDocument ) ;
122182 if ( ! identity . IsRazorSourceGeneratedDocument ( ) )
123183 {
0 commit comments