@@ -300,7 +300,11 @@ extension SwiftLanguageServer {
300
300
return
301
301
}
302
302
303
- let completionPos = adjustCompletionLocation ( req. params. position, in: snapshot)
303
+ guard let completionPos = adjustCompletionLocation ( req. params. position, in: snapshot) else {
304
+ log ( " invalid completion position \( req. params. position) " )
305
+ req. reply ( CompletionList ( isIncomplete: true , items: [ ] ) )
306
+ return
307
+ }
304
308
305
309
guard let offset = snapshot. utf8Offset ( of: completionPos) else {
306
310
log ( " invalid completion position \( req. params. position) (adjusted: \( completionPos) " )
@@ -387,29 +391,35 @@ extension SwiftLanguageServer {
387
391
return result
388
392
}
389
393
390
- func adjustCompletionLocation( _ pos: Position , in snapshot: DocumentSnapshot ) -> Position {
391
- guard let requestedLoc = snapshot. index ( of: pos) , requestedLoc != snapshot. text. startIndex else {
392
- return pos
394
+ /// Adjust completion position to the start of identifier characters.
395
+ func adjustCompletionLocation( _ pos: Position , in snapshot: DocumentSnapshot ) -> Position ? {
396
+ guard pos. line < snapshot. lineTable. count else {
397
+ // Line out of range.
398
+ return nil
393
399
}
400
+ let lineSlice = snapshot. lineTable [ pos. line]
401
+ let startIndex = lineSlice. startIndex
394
402
395
403
let identifierChars = CharacterSet . alphanumerics. union ( CharacterSet ( charactersIn: " _ " ) )
396
404
397
- var prev = requestedLoc
398
- var loc = snapshot. text. index ( before: requestedLoc)
399
- while identifierChars. contains ( snapshot. text [ loc] . unicodeScalars. first!) {
400
- prev = loc
401
- loc = snapshot. text. index ( before: loc)
405
+ guard var loc = lineSlice. utf16. index ( startIndex, offsetBy: pos. utf16index, limitedBy: lineSlice. endIndex) else {
406
+ // Column out of range.
407
+ return nil
408
+ }
409
+ while loc != startIndex {
410
+ let prev = lineSlice. index ( before: loc)
411
+ if !identifierChars. contains ( lineSlice. unicodeScalars [ prev] ) {
412
+ break
413
+ }
414
+ loc = prev
402
415
}
403
416
404
- // #aabccccccdddddd
405
- // ^^- prev ^-requestedLoc
406
- // `- loc
407
- //
408
- // We offset the column by (requestedLoc - prev), which must be >=0 and on the same line.
409
-
410
- let delta = requestedLoc. encodedOffset - prev. encodedOffset
417
+ // ###aabccccccdddddd
418
+ // ^ ^- loc ^-requestedLoc
419
+ // `- startIndex
411
420
412
- return Position ( line: pos. line, utf16index: pos. utf16index - delta)
421
+ let adjustedOffset = lineSlice. utf16. distance ( from: startIndex, to: loc)
422
+ return Position ( line: pos. line, utf16index: adjustedOffset)
413
423
}
414
424
415
425
func hover( _ req: Request < HoverRequest > ) {
0 commit comments