editor: Fix double $ sign on completion accept in PHP (#34726)
Closes #33510 https://github.com/zed-extensions/php/issues/29 If certain language servers do not provide an insert/replace range, we use `surrounding_word` as a fallback for that range, which internally uses `word_characters`. It makes sense to use `completion_query_characters` instead of `word_characters` to get that range, because we use `completion_query_characters` to query completions in the first place. That means, for some hypothetical reason (e.g., if the Tailwind server stops providing insert/replace ranges), we would correctly fall back to the range "bg-blue-200^" instead of "200^", because `completion_query_characters` includes "-" in this case. For this particular fix, right now the default PHP language server `phpactor` does not provide an insert/replace range, and hence completion query character is used, which is `$` in this case. Note that `$` isn't in word characters for reasons mentioned here: https://github.com/zed-extensions/php/issues/14 Release Notes: - Fixed an issue where accepting variable completion in PHP would result in a double $ sign in the prefix.
This commit is contained in:
parent
8bc8d61fa6
commit
1dd470ca48
3 changed files with 14 additions and 8 deletions
|
@ -5451,7 +5451,7 @@ impl Editor {
|
||||||
};
|
};
|
||||||
|
|
||||||
let (word_replace_range, word_to_exclude) = if let (word_range, Some(CharKind::Word)) =
|
let (word_replace_range, word_to_exclude) = if let (word_range, Some(CharKind::Word)) =
|
||||||
buffer_snapshot.surrounding_word(buffer_position)
|
buffer_snapshot.surrounding_word(buffer_position, false)
|
||||||
{
|
{
|
||||||
let word_to_exclude = buffer_snapshot
|
let word_to_exclude = buffer_snapshot
|
||||||
.text_for_range(word_range.clone())
|
.text_for_range(word_range.clone())
|
||||||
|
@ -6605,8 +6605,8 @@ impl Editor {
|
||||||
}
|
}
|
||||||
|
|
||||||
let snapshot = cursor_buffer.read(cx).snapshot();
|
let snapshot = cursor_buffer.read(cx).snapshot();
|
||||||
let (start_word_range, _) = snapshot.surrounding_word(cursor_buffer_position);
|
let (start_word_range, _) = snapshot.surrounding_word(cursor_buffer_position, false);
|
||||||
let (end_word_range, _) = snapshot.surrounding_word(tail_buffer_position);
|
let (end_word_range, _) = snapshot.surrounding_word(tail_buffer_position, false);
|
||||||
if start_word_range != end_word_range {
|
if start_word_range != end_word_range {
|
||||||
self.document_highlights_task.take();
|
self.document_highlights_task.take();
|
||||||
self.clear_background_highlights::<DocumentHighlightRead>(cx);
|
self.clear_background_highlights::<DocumentHighlightRead>(cx);
|
||||||
|
@ -22137,7 +22137,7 @@ impl SemanticsProvider for Entity<Project> {
|
||||||
// Fallback on using TreeSitter info to determine identifier range
|
// Fallback on using TreeSitter info to determine identifier range
|
||||||
buffer.read_with(cx, |buffer, _| {
|
buffer.read_with(cx, |buffer, _| {
|
||||||
let snapshot = buffer.snapshot();
|
let snapshot = buffer.snapshot();
|
||||||
let (range, kind) = snapshot.surrounding_word(position);
|
let (range, kind) = snapshot.surrounding_word(position, false);
|
||||||
if kind != Some(CharKind::Word) {
|
if kind != Some(CharKind::Word) {
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
|
|
|
@ -3364,13 +3364,19 @@ impl BufferSnapshot {
|
||||||
|
|
||||||
/// Returns a tuple of the range and character kind of the word
|
/// Returns a tuple of the range and character kind of the word
|
||||||
/// surrounding the given position.
|
/// surrounding the given position.
|
||||||
pub fn surrounding_word<T: ToOffset>(&self, start: T) -> (Range<usize>, Option<CharKind>) {
|
pub fn surrounding_word<T: ToOffset>(
|
||||||
|
&self,
|
||||||
|
start: T,
|
||||||
|
for_completion: bool,
|
||||||
|
) -> (Range<usize>, Option<CharKind>) {
|
||||||
let mut start = start.to_offset(self);
|
let mut start = start.to_offset(self);
|
||||||
let mut end = start;
|
let mut end = start;
|
||||||
let mut next_chars = self.chars_at(start).take(128).peekable();
|
let mut next_chars = self.chars_at(start).take(128).peekable();
|
||||||
let mut prev_chars = self.reversed_chars_at(start).take(128).peekable();
|
let mut prev_chars = self.reversed_chars_at(start).take(128).peekable();
|
||||||
|
|
||||||
let classifier = self.char_classifier_at(start);
|
let classifier = self
|
||||||
|
.char_classifier_at(start)
|
||||||
|
.for_completion(for_completion);
|
||||||
let word_kind = cmp::max(
|
let word_kind = cmp::max(
|
||||||
prev_chars.peek().copied().map(|c| classifier.kind(c)),
|
prev_chars.peek().copied().map(|c| classifier.kind(c)),
|
||||||
next_chars.peek().copied().map(|c| classifier.kind(c)),
|
next_chars.peek().copied().map(|c| classifier.kind(c)),
|
||||||
|
|
|
@ -350,7 +350,7 @@ impl LspCommand for PrepareRename {
|
||||||
}
|
}
|
||||||
Some(lsp::PrepareRenameResponse::DefaultBehavior { .. }) => {
|
Some(lsp::PrepareRenameResponse::DefaultBehavior { .. }) => {
|
||||||
let snapshot = buffer.snapshot();
|
let snapshot = buffer.snapshot();
|
||||||
let (range, _) = snapshot.surrounding_word(self.position);
|
let (range, _) = snapshot.surrounding_word(self.position, false);
|
||||||
let range = snapshot.anchor_after(range.start)..snapshot.anchor_before(range.end);
|
let range = snapshot.anchor_after(range.start)..snapshot.anchor_before(range.end);
|
||||||
Ok(PrepareRenameResponse::Success(range))
|
Ok(PrepareRenameResponse::Success(range))
|
||||||
}
|
}
|
||||||
|
@ -2297,7 +2297,7 @@ impl LspCommand for GetCompletions {
|
||||||
range_for_token
|
range_for_token
|
||||||
.get_or_insert_with(|| {
|
.get_or_insert_with(|| {
|
||||||
let offset = self.position.to_offset(&snapshot);
|
let offset = self.position.to_offset(&snapshot);
|
||||||
let (range, kind) = snapshot.surrounding_word(offset);
|
let (range, kind) = snapshot.surrounding_word(offset, true);
|
||||||
let range = if kind == Some(CharKind::Word) {
|
let range = if kind == Some(CharKind::Word) {
|
||||||
range
|
range
|
||||||
} else {
|
} else {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue