@@ -48,6 +48,14 @@ public override string ToString()
4848 this . StartLine , this . StartColumn ,
4949 this . EndLine , this . EndColumn ) ;
5050 }
51+
52+ public bool ContainsLocation ( int line , int column = 0 )
53+ {
54+ if ( column == 0 )
55+ return line >= StartLine && line <= EndLine ;
56+ return ( StartLine < line || ( StartLine == line && StartColumn <= column ) )
57+ && ( line < EndLine || ( line == EndLine && column <= EndColumn ) ) ;
58+ }
5159 }
5260
5361 public struct ILRange
@@ -185,14 +193,14 @@ public SequencePoint GetSequencePoint(IMethod method, int iloffset)
185193 var realSeqPoints = sequencePoints . Where ( p => p . StartLine != 0xFEEFEE ) ;
186194
187195 // Find point for which (ilstart <= iloffset < ilend) or fallback to the next valid sequence point
188- var sequencePoint = realSeqPoints . FirstOrDefault ( p => p . ILRanges . Any ( r => r . From <= iloffset && iloffset < r . To ) ) ??
189- realSeqPoints . FirstOrDefault ( p => iloffset <= p . ILOffset ) ;
196+ var sequencePoint = realSeqPoints . FirstOrDefault ( p => p . ILRanges . Any ( r => r . From <= iloffset && iloffset < r . To ) )
197+ ?? realSeqPoints . FirstOrDefault ( p => iloffset <= p . ILOffset ) ;
190198
191199 if ( sequencePoint != null ) {
192200 // VB.NET sometimes produces temporary files which it then deletes
193201 // (eg 17d14f5c-a337-4978-8281-53493378c1071.vb)
194202 string name = Path . GetFileName ( sequencePoint . Filename ) ;
195- if ( name . Length == 40 && name . EndsWith ( ".vb" ) ) {
203+ if ( name . Length == 40 && name . EndsWith ( ".vb" , StringComparison . OrdinalIgnoreCase ) ) {
196204 if ( name . Substring ( 0 , name . Length - 3 ) . All ( c => ( '0' <= c && c <= '9' ) || ( 'a' <= c && c <= 'f' ) || ( 'A' <= c && c <= 'F' ) || ( c == '-' ) ) ) {
197205 return null ;
198206 }
@@ -232,19 +240,47 @@ public IEnumerable<SequencePoint> GetSequencePoints(Module module, string filena
232240
233241 foreach ( ISymUnmanagedMethod symMethod in symMethods ) {
234242 var corFunction = module . CorModule . GetFunctionFromToken ( symMethod . GetToken ( ) ) ;
235- int codesize = ( int ) corFunction . GetILCode ( ) . GetSize ( ) ;
236- var seqPoints = symMethod . GetSequencePoints ( codesize ) . Where ( s => s . StartLine != 0xFEEFEE ) ;
237- SequencePoint seqPoint = null ;
238- if ( column != 0 ) {
239- seqPoint = seqPoints . FirstOrDefault ( s => ( s . StartLine < line || ( s . StartLine == line && s . StartColumn <= column ) ) &&
240- ( line < s . EndLine || ( line == s . EndLine && column <= s . EndColumn ) ) ) ;
241- }
242- seqPoint = seqPoint ?? seqPoints . FirstOrDefault ( s => line <= s . StartLine ) ;
243+ int codeSize = ( int ) corFunction . GetILCode ( ) . GetSize ( ) ;
244+ var seqPoints = symMethod . GetSequencePoints ( codeSize ) . Where ( s => s . StartLine != 0xFEEFEE ) . OrderBy ( s => s . StartLine ) . ToArray ( ) ;
245+ SequencePoint seqPoint = FindNearestMatchingSequencePoint ( seqPoints , line , column ) ;
243246 if ( seqPoint != null )
244247 yield return seqPoint ;
245248 }
246249 }
247250
251+ SequencePoint FindNearestMatchingSequencePoint ( SequencePoint [ ] seqPoints , int line , int column )
252+ {
253+ // value is nearest offset in lines;
254+ // negative numbers: (Start|End)Line is same as line, value is offset in columns
255+ int nearestOffset = 0 ;
256+ SequencePoint bestMatch = null ;
257+ for ( int i = 0 ; i < seqPoints . Length ; i ++ ) {
258+ var s = seqPoints [ i ] ;
259+ if ( s . ContainsLocation ( line , column ) )
260+ return seqPoints [ i ] ;
261+
262+ if ( bestMatch == null ) {
263+ bestMatch = s ;
264+ nearestOffset = GetOffsetValue ( s , line , column ) ;
265+ } else {
266+ int newOffset = GetOffsetValue ( s , line , column ) ;
267+ if ( ( newOffset < 0 && nearestOffset < 0 && newOffset > nearestOffset ) || ( newOffset < nearestOffset ) ) {
268+ bestMatch = s ;
269+ nearestOffset = newOffset ;
270+ }
271+ }
272+ }
273+
274+ return bestMatch ;
275+ }
276+
277+ static int GetOffsetValue ( SequencePoint s , int line , int column )
278+ {
279+ if ( line == s . StartLine || s . EndLine == line )
280+ return - Math . Min ( Math . Abs ( s . StartColumn - column ) , Math . Abs ( s . EndColumn - column ) ) ;
281+ return Math . Min ( Math . Abs ( s . StartLine - line ) , Math . Abs ( s . EndLine - line ) ) ;
282+ }
283+
248284 public IEnumerable < ILRange > GetIgnoredILRanges ( IMethod method )
249285 {
250286 var symMethod = method . GetSymMethod ( ) ;
0 commit comments