Skip to content

Avoid crashing on invalid range in editDocument #2179

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 2 commits into
base: main
Choose a base branch
from

Conversation

hamishknight
Copy link
Contributor

Rename LineTable.replace(utf8Offset:length:with) to tryReplace and bail if the provided range is out of bounds of the buffer. This ensures we match the behavior of SourceKit when handling an editor.replacetext request.

rdar://90385969

Copy link
Member

@ahoppen ahoppen left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice find

/// - parameter replacement: The new text for the given range.
@inlinable
mutating package func replace(
mutating package func tryReplace(
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it’s odd that the UTF-8-based replace methods now continue on error while the UTF-16-based methods trap (even though it is indicated by tryReplace vs replace). What do you think about changing replace to throws and then let the client handle an out-of-bounds error. For SourceKit-LSP I think crashing is still a reasonable resolution because we would definitely have an out-of-date document state and if we crash, the editor should re-launch us and thus send the new document state. For the plugin, I think wrapping it in orLog is reasonable to match the current behavior of SourceKitService. Although I find it quite concerning if we get out-of-bound replacements.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For SourceKit-LSP I think crashing is still a reasonable resolution

Maybe I'm misunderstanding, but doesn't LSP currently recover by clipping the provided location to the start and end locations?

switch self.lineSlice(at: line, callerFile: callerFile, callerLine: callerLine) {
case .beforeFirstLine:
return self.content.startIndex
case .afterLastLine:
return self.content.endIndex

But yeah, I changed the name to tryReplace to indicate it has a different behavior to replace. Happy to make it throw + orLog instead.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Updated to throw an error

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Huh, I could have sworn that we crashed for out-of-bound edits but I changed that in #1798. Sorry for the back and forth but I think my main motivation is that the UTF-8 and UTF-16-based methods should behave consistently. With that new information, I think I’d prefer if we’d just match the UTF-16 behavior for UTF-8 and use

let start = self.stringIndexOf(line: fromLine, utf8Column: fromOff)
let end = self.stringIndexOf(line: toLine, utf8Column: toOff)

That should fix the crash with the standard log behavior, right?

Rename `LineTable.replace(utf8Offset:length:with)` to `tryReplace`
and bail if the provided range is out of bounds of the buffer. This
ensures we match the behavior of SourceKit when handling an
`editor.replacetext` request.

rdar://90385969
@hamishknight
Copy link
Contributor Author

@swift-ci please test

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants