Skip to content

Commit 4f00abb

Browse files
refactor, terminate by semicolons
1 parent 4e5521c commit 4f00abb

File tree

3 files changed

+66
-42
lines changed

3 files changed

+66
-42
lines changed

crates/pgt_text_size/src/range.rs

+18
Original file line numberDiff line numberDiff line change
@@ -281,6 +281,24 @@ impl TextRange {
281281
})
282282
}
283283

284+
/// Expand the range's end by the given offset.
285+
///
286+
/// # Examples
287+
///
288+
/// ```rust
289+
/// # use pgt_text_size::*;
290+
/// assert_eq!(
291+
/// TextRange::new(2.into(), 4.into()).checked_expand_end(16.into()).unwrap(),
292+
/// TextRange::new(2.into(), 20.into()),
293+
/// );
294+
/// ```
295+
#[inline]
296+
pub fn checked_expand_end(self, offset: TextSize) -> Option<TextRange> {
297+
Some(TextRange {
298+
start: self.start,
299+
end: self.end.checked_add(offset)?,
300+
})
301+
}
284302
/// Subtract an offset from this range.
285303
///
286304
/// Note that this is not appropriate for changing where a `TextRange` is

crates/pgt_workspace/src/workspace/server.rs

+38-42
Original file line numberDiff line numberDiff line change
@@ -541,61 +541,57 @@ impl Workspace for WorkspaceServer {
541541
.ok_or(WorkspaceError::not_found())?;
542542

543543
let count = doc.statement_count();
544+
// no arms no cookies
545+
if count == 0 {
546+
return Ok(CompletionsResult::default());
547+
}
544548

545-
let maybe_statement = if count == 0 {
546-
None
547-
} else if count == 1 {
549+
/*
550+
* We allow an offset of two for the statement:
551+
*
552+
* select * from | <-- we want to suggest items for the next token.
553+
*
554+
* However, if the current statement is terminated by a semicolon, we don't apply any
555+
* offset.
556+
*
557+
* select * from users; | <-- no autocompletions here.
558+
*/
559+
let matches_expanding_range =
560+
|stmt_id: StatementId, range: &TextRange, position: TextSize| {
561+
let measuring_range = if doc.is_terminated_by_semicolon(stmt_id).unwrap() {
562+
*range
563+
} else {
564+
range.checked_expand_end(2.into()).unwrap_or(*range)
565+
};
566+
measuring_range.contains(position)
567+
};
568+
569+
let maybe_statement = if count == 1 {
548570
let (stmt, range, txt) = doc.iter_statements_with_text_and_range().next().unwrap();
549-
let expanded_range = TextRange::new(
550-
range.start(),
551-
range
552-
.end()
553-
.checked_add(TextSize::new(2))
554-
.unwrap_or(range.end()),
555-
);
556-
if expanded_range.contains(params.position) {
571+
if matches_expanding_range(stmt.id, range, params.position) {
557572
Some((stmt, range, txt))
558573
} else {
559574
None
560575
}
561576
} else {
562-
let mut stmts = doc.iter_statements_with_text_and_range().tuple_windows();
563-
stmts.find(|((_, rcurrent, _), (_, rnext, _))| {
564577
/*
565-
* We allow an offset of two for the statement:
566-
*
567-
* (| is the user's cursor.)
568-
*
569-
* select * from | <-- we want to suggest items for the next token.
578+
* If we have multiple statements, we want to make sure that we do not overlap
579+
* with the next one.
570580
*
581+
* select 1 |select 1;
571582
*/
572-
let expanded_range = TextRange::new(
573-
rcurrent.start(),
574-
rcurrent
575-
.end()
576-
.checked_add(TextSize::new(2))
577-
.unwrap_or(rcurrent.end()),
578-
);
579-
let is_within_range = expanded_range.contains(params.position);
580-
581-
/*
582-
* However, we do not allow this if the there the offset overlaps
583-
* with an adjacent statement:
584-
*
585-
* select 1; |select 1;
586-
*/
587-
let overlaps_next = !rnext.contains(params.position);
588-
589-
590-
tracing::warn!("Current range {:?}, next range {:?}, position: {:?}, contains range: {}, overlaps :{}", rcurrent, rnext, params.position, is_within_range, overlaps_next);
591-
592-
is_within_range && !overlaps_next
593-
594-
}).map(|(t1,_t2)| t1)
583+
let mut stmts = doc.iter_statements_with_text_and_range().tuple_windows();
584+
stmts
585+
.find(|((current_stmt, rcurrent, _), (_, rnext, _))| {
586+
let overlaps_next = rnext.contains(params.position);
587+
matches_expanding_range(current_stmt.id, &rcurrent, params.position)
588+
&& !overlaps_next
589+
})
590+
.map(|t| t.0)
595591
};
596592

597593
let (statement, stmt_range, text) = match maybe_statement {
598-
Some(tuple) => tuple,
594+
Some(it) => it,
599595
None => {
600596
tracing::debug!("No matching statement found for completion.");
601597
return Ok(CompletionsResult::default());

crates/pgt_workspace/src/workspace/server/document.rs

+10
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,16 @@ impl Document {
117117
stmt.to_owned()
118118
})
119119
}
120+
121+
pub fn is_terminated_by_semicolon(&self, stmt_id: StatementId) -> Option<bool> {
122+
self.positions
123+
.iter()
124+
.find(|pos| pos.0 == stmt_id)
125+
.map(|(_, range)| {
126+
let final_char = self.content.chars().nth(range.end().into());
127+
final_char == Some(';')
128+
})
129+
}
120130
}
121131

122132
pub(crate) struct IdGenerator {

0 commit comments

Comments
 (0)