@@ -300,7 +300,11 @@ extension SwiftLanguageServer {
300300 return
301301 }
302302
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+ }
304308
305309 guard let offset = snapshot. utf8Offset ( of: completionPos) else {
306310 log ( " invalid completion position \( req. params. position) (adjusted: \( completionPos) " )
@@ -387,29 +391,35 @@ extension SwiftLanguageServer {
387391 return result
388392 }
389393
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
393399 }
400+ let lineSlice = snapshot. lineTable [ pos. line]
401+ let startIndex = lineSlice. startIndex
394402
395403 let identifierChars = CharacterSet . alphanumerics. union ( CharacterSet ( charactersIn: " _ " ) )
396404
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
402415 }
403416
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
411420
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)
413423 }
414424
415425 func hover( _ req: Request < HoverRequest > ) {
0 commit comments