@@ -56,8 +56,8 @@ static BreakpointLocation create(Object key, SourceElement[] sourceElements, Sou
5656 return new BreakpointSourceLocation (key , sourceElements , sourceSection , tag );
5757 }
5858
59- static BreakpointLocation create (Object key , SourceElement [] sourceElements , int line , int column , Class <? extends Tag > tag ) {
60- return new BreakpointSourceLocation (key , sourceElements , line , column , tag );
59+ static BreakpointLocation create (Object key , SourceElement [] sourceElements , int line , int column , int sectionLength , Class <? extends Tag > tag ) {
60+ return new BreakpointSourceLocation (key , sourceElements , line , column , sectionLength , tag );
6161 }
6262
6363 static BreakpointLocation create (SourceElement [] sourceElements , SuspensionFilter filter ) {
@@ -88,6 +88,9 @@ private static final class BreakpointSourceLocation extends BreakpointLocation {
8888 private final SourceSection sourceSection ;
8989 private int line ;
9090 private int column ;
91+ private int sectionLength ;
92+
93+ private SourceSection perfectMatch ;
9194
9295 private final Class <? extends Tag > tag ;
9396
@@ -102,6 +105,7 @@ private static final class BreakpointSourceLocation extends BreakpointLocation {
102105 this .sourceSection = sourceSection ;
103106 this .line = -1 ;
104107 this .column = -1 ;
108+ this .sectionLength = -1 ;
105109 this .tag = tag ;
106110 }
107111
@@ -110,14 +114,15 @@ private static final class BreakpointSourceLocation extends BreakpointLocation {
110114 * @param line 1-based line number
111115 * @param column 1-based column number, -1 for unspecified
112116 */
113- BreakpointSourceLocation (Object key , SourceElement [] sourceElements , int line , int column , Class <? extends Tag > tag ) {
117+ BreakpointSourceLocation (Object key , SourceElement [] sourceElements , int line , int column , int sectionLength , Class <? extends Tag > tag ) {
114118 assert key instanceof Source || key instanceof URI ;
115119 assert line > 0 ;
116120 assert column > 0 || column == -1 ;
117121 this .key = key ;
118122 this .sourceElements = sourceElements ;
119123 this .line = line ;
120124 this .column = column ;
125+ this .sectionLength = sectionLength ;
121126 this .sourceSection = null ;
122127 this .tag = tag ;
123128 }
@@ -127,6 +132,7 @@ private BreakpointSourceLocation() {
127132 this .sourceElements = null ;
128133 this .line = -1 ;
129134 this .column = -1 ;
135+ this .sectionLength = -1 ;
130136 this .sourceSection = null ;
131137 this .tag = null ;
132138 }
@@ -164,27 +170,39 @@ SourceSection adjustLocation(Source source, TruffleInstrument.Env env, SuspendAn
164170 if (sourceSection != null ) {
165171 return sourceSection ;
166172 }
173+ if (perfectMatch != null ) {
174+ return perfectMatch ;
175+ }
167176 if (key == null ) {
168177 return null ;
169178 }
170179 boolean hasColumn = column > 0 ;
171- SourceSection location = SuspendableLocationFinder .findNearest (source , sourceElements , line , column , tag , suspendAnchor , env );
180+ boolean hasLength = sectionLength > 0 ;
181+ SourceSection location = SuspendableLocationFinder .findNearest (source , sourceElements , line , column , sectionLength , tag , suspendAnchor , env );
172182 if (location != null ) {
173- switch (suspendAnchor ) {
174- case BEFORE :
175- line = location .getStartLine ();
176- if (hasColumn ) {
177- column = location .getStartColumn ();
178- }
179- break ;
180- case AFTER :
181- line = location .getEndLine ();
182- if (hasColumn ) {
183- column = location .getEndColumn ();
184- }
185- break ;
186- default :
187- throw new IllegalArgumentException ("Unknown suspend anchor: " + suspendAnchor );
183+ if (hasLength && hasColumn &&
184+ line == location .getStartLine () &&
185+ column == location .getStartColumn () &&
186+ sectionLength == location .getCharLength ()) {
187+ assert perfectMatch == null ;
188+ perfectMatch = location ;
189+ } else {
190+ switch (suspendAnchor ) {
191+ case BEFORE :
192+ line = location .getStartLine ();
193+ if (hasColumn ) {
194+ column = location .getStartColumn ();
195+ }
196+ break ;
197+ case AFTER :
198+ line = location .getEndLine ();
199+ if (hasColumn ) {
200+ column = location .getEndColumn ();
201+ }
202+ break ;
203+ default :
204+ throw new IllegalArgumentException ("Unknown suspend anchor: " + suspendAnchor );
205+ }
188206 }
189207 }
190208 return location ;
@@ -201,7 +219,7 @@ SourceSectionFilter createLocationFilter(Source source, SuspendAnchor suspendAnc
201219 } else {
202220 f .sourceFilter (createSourceFilter ());
203221 }
204- if (line != -1 ) {
222+ if (perfectMatch == null && line != -1 ) {
205223 switch (suspendAnchor ) {
206224 case BEFORE :
207225 f .lineStartsIn (IndexRange .byLength (line , 1 ));
@@ -221,6 +239,9 @@ SourceSectionFilter createLocationFilter(Source source, SuspendAnchor suspendAnc
221239 }
222240 if (sourceSection != null ) {
223241 f .sourceSectionEquals (sourceSection );
242+ assert perfectMatch == null ;
243+ } else if (perfectMatch != null ) {
244+ f .sourceSectionEquals (perfectMatch );
224245 }
225246 setTags (f , sourceElements , tag );
226247 return f .build ();
@@ -238,7 +259,7 @@ public String toString() {
238259 } else {
239260 keyDescription = key .toString ();
240261 }
241- return keyDescription + ", line=" + line + ", column=" + column ;
262+ return keyDescription + ", line=" + line + ", column=" + column + ", length=" + sectionLength ;
242263 }
243264
244265 }
0 commit comments