mirror of
https://github.com/oxalica/nil.git
synced 2024-11-25 18:41:40 +03:00
Fine tuning token selection at given position
This commit is contained in:
parent
1b6b4534b3
commit
26c5d73015
@ -128,34 +128,43 @@ macro_rules! match_ast {
|
|||||||
}};
|
}};
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Pick the most meaningful token at given cursor offset.
|
/// Pick the most likely interested token at given cursor offset.
|
||||||
pub fn best_token_at_offset(node: &SyntaxNode, offset: TextSize) -> Option<SyntaxToken> {
|
pub fn best_token_at_offset(node: &SyntaxNode, offset: TextSize) -> Option<SyntaxToken> {
|
||||||
fn score(tok: SyntaxKind) -> u8 {
|
fn score(tok: SyntaxKind) -> u8 {
|
||||||
match tok {
|
match tok {
|
||||||
SyntaxKind::ERROR | SyntaxKind::SPACE => 0,
|
SyntaxKind::ERROR | SyntaxKind::SPACE => 0,
|
||||||
SyntaxKind::COMMENT => 1,
|
SyntaxKind::COMMENT => 1,
|
||||||
|
|
||||||
|
// Avoid returning sibling delimiters, which may be in another region.
|
||||||
|
// Sorted by the nesting level in AST.
|
||||||
|
// `{ ...;|b = ... }`
|
||||||
|
T![;] | T![,] => 2,
|
||||||
|
T![=] | T![:] | T![@] => 3,
|
||||||
|
T!['('] | T!['['] | T!['{'] | T!["${"] | T![')'] | T![']'] | T!['}'] => 4,
|
||||||
|
|
||||||
|
// The rest are mostly operators, including `.` and `?`.
|
||||||
|
k if k.is_punct() => 5,
|
||||||
|
|
||||||
|
// Literal parts.
|
||||||
|
T!['"'] | T!["''"] => 10,
|
||||||
SyntaxKind::PATH_START
|
SyntaxKind::PATH_START
|
||||||
| SyntaxKind::PATH_END
|
| SyntaxKind::PATH_END
|
||||||
| SyntaxKind::PATH_FRAGMENT
|
| SyntaxKind::PATH_FRAGMENT
|
||||||
| SyntaxKind::STRING_FRAGMENT => 2,
|
| SyntaxKind::STRING_FRAGMENT => 11,
|
||||||
SyntaxKind::STRING_ESCAPE => 3,
|
SyntaxKind::STRING_ESCAPE => 12,
|
||||||
k if k.is_punct() => 4,
|
|
||||||
k if k.is_keyword() => 5,
|
// Atoms.
|
||||||
|
k if k.is_keyword() => 13,
|
||||||
// IDENT, INT, and etc.
|
// IDENT, INT, and etc.
|
||||||
_ => 6,
|
_ => 14,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
match node.token_at_offset(offset) {
|
match node.token_at_offset(offset) {
|
||||||
TokenAtOffset::None => None,
|
TokenAtOffset::None => None,
|
||||||
TokenAtOffset::Single(tok) => Some(tok),
|
TokenAtOffset::Single(tok) => Some(tok),
|
||||||
TokenAtOffset::Between(lhs, rhs) => {
|
// Slightly prefer RHS for equal scores.
|
||||||
// Slightly prefer RHS.
|
TokenAtOffset::Between(lhs, rhs) if score(lhs.kind()) > score(rhs.kind()) => Some(lhs),
|
||||||
if score(lhs.kind()) > score(rhs.kind()) {
|
TokenAtOffset::Between(_, rhs) => Some(rhs),
|
||||||
Some(lhs)
|
|
||||||
} else {
|
|
||||||
Some(rhs)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user