@@ -311,9 +311,18 @@ bool FilesToSnippets(
311311 return true ;
312312 }
313313
314+ string ? lineExpression = null ;
315+
316+ if ( key . Contains ( '#' ) )
317+ {
318+ var splitByHash = key . Split ( '#' , StringSplitOptions . None ) ;
319+ key = splitByHash [ 0 ] ;
320+ lineExpression = splitByHash [ 1 ] ;
321+ }
322+
314323 if ( RelativeFile . Find ( allFiles , targetDirectory , key , relativePath , linePath , out var path ) )
315324 {
316- snippetsForKey = SnippetsForFile ( key , path ) ;
325+ snippetsForKey = SnippetsForFile ( key , path , lineExpression ) ;
317326 return true ;
318327 }
319328
@@ -322,8 +331,7 @@ bool FilesToSnippets(
322331 }
323332
324333
325- List < Snippet > SnippetsForFile ( string key , string relativeToRoot ) =>
326- [ FileToSnippet ( key , relativeToRoot , null ) ] ;
334+ List < Snippet > SnippetsForFile ( string key , string relativeToRoot , string ? lines = null ) => [ FileToSnippet ( key , relativeToRoot , null , lines ) ] ;
327335
328336 bool GetForHttp ( string key , out IReadOnlyList < Snippet > snippetsForKey )
329337 {
@@ -338,22 +346,77 @@ bool GetForHttp(string key, out IReadOnlyList<Snippet> snippetsForKey)
338346 return true ;
339347 }
340348
341- Snippet FileToSnippet ( string key , string file , string ? path )
349+ Snippet FileToSnippet ( string key , string file , string ? path , string ? linesExpression = null )
350+ {
351+ var language = Path . GetExtension ( file ) [ 1 ..] ;
352+
353+ if ( linesExpression == null )
354+ {
355+ var ( text , endLine ) = ReadNonStartEndLines ( file ) ;
356+ return Snippet . Build ( startLine : 0 , endLine : endLine , value : text , key : key , language : language , path : path ) ;
357+ }
358+
359+ if ( linesExpression [ 0 ] == 'L' )
360+ {
361+ return ParseSpecificLines ( key , file , path , linesExpression , language ) ;
362+ }
363+
364+ if ( linesExpression [ 0 ] == 'M' && language == "cs" )
365+ {
366+ return ParseCSharpMethod ( key , file , path , linesExpression , language ) ;
367+ }
368+
369+ throw new SnippetException ( $ "Unable to parse expression '{ linesExpression } '") ;
370+ }
371+
372+ static Snippet ParseCSharpMethod ( string key , string file , string ? path , string linesExpression , string language )
342373 {
343- var ( text , lineCount ) = ReadNonStartEndLines ( file ) ;
374+ var methodName = linesExpression [ 2 ..] ;
375+
376+ var code = File . ReadAllText ( file ) ;
377+ var tree = CSharpSyntaxTree . ParseText ( code ) ;
378+ var root = tree . GetCompilationUnitRoot ( ) ;
379+
380+ var method = root . DescendantNodes ( )
381+ . OfType < MethodDeclarationSyntax > ( )
382+ . FirstOrDefault ( m => m . Identifier . Text == methodName ) ;
383+
384+ if ( method != null )
385+ {
386+ var text = method . ToFullString ( ) ;
387+ var startLine = method . Span . Start ;
388+ var endLine = method . Span . End ;
389+
390+ return Snippet . Build ( startLine : startLine , endLine : endLine , value : text , key : key , language : language , path : path ) ;
391+ }
392+
393+ throw new SnippetException (
394+ $ """
395+ Failed to find method { methodName } in file { file } configuration.
396+ Content:
397+ { code }
398+ """ ) ;
399+ }
400+
401+ static Snippet ParseSpecificLines ( string key , string file , string ? path , string linesExpression , string language )
402+ {
403+ var text = string . Empty ;
404+
405+ var expressionSplit = linesExpression . Split ( '-' ) ;
406+ var startLine = int . Parse ( expressionSplit [ 0 ] [ 1 ..] ) ;
407+ var endLine = int . Parse ( expressionSplit [ 1 ] ) ;
408+
409+ var fileLines = File . ReadAllLines ( file ) ;
410+
411+ var selectedText = new StringBuilder ( ) ;
344412
345- if ( lineCount == 0 )
413+ for ( var index = startLine ; index < endLine ; index ++ )
346414 {
347- lineCount ++ ;
415+ selectedText . AppendLine ( fileLines [ index ] ) ;
416+ text = selectedText . ToString ( ) ;
348417 }
349418
350- return Snippet . Build (
351- startLine : 1 ,
352- endLine : lineCount ,
353- value : text ,
354- key : key ,
355- language : Path . GetExtension ( file ) [ 1 ..] ,
356- path : path ) ;
419+ return Snippet . Build ( startLine : 1 , endLine : endLine , value : text , key : key , language : language , path : path ) ;
357420 }
358421
359422 ( string text , int lineCount ) ReadNonStartEndLines ( string file )
0 commit comments