mirror of
https://github.com/slint-ui/slint.git
synced 2025-11-03 13:23:00 +00:00
Fix LSP semantic coloration bailing out sometimes
Step to reproduce:
```
xx := Window {
TouchArea {
clicked => {
if (true) {}
// note: because there is no else, the semantic colouring is bailing out now
}
}
TouchArea { clicked => {} }
}
```
This is caused by a bug in rowan::SyntaxToken::next_token that doesn't visit
the next token if it has an empty node
Unfortunately, the LSP has no tests, so I couldn't add one easily
This commit is contained in:
parent
458c88cfa4
commit
c5ef368a3f
2 changed files with 36 additions and 6 deletions
|
|
@ -693,6 +693,31 @@ impl SyntaxToken {
|
||||||
pub fn parent(&self) -> SyntaxNode {
|
pub fn parent(&self) -> SyntaxNode {
|
||||||
SyntaxNode { node: self.token.parent().unwrap(), source_file: self.source_file.clone() }
|
SyntaxNode { node: self.token.parent().unwrap(), source_file: self.source_file.clone() }
|
||||||
}
|
}
|
||||||
|
pub fn next_token(&self) -> Option<SyntaxToken> {
|
||||||
|
// Due to a bug (as of rowan 0.15.3), rowan::SyntaxToken::next_token doesn't work if a
|
||||||
|
// sibling don't have tokens.
|
||||||
|
// For example, if we have an expression like `if (true) {}` the
|
||||||
|
// ConditionalExpression has an empty Expression/CodeBlock for the else part,
|
||||||
|
// and next_token doesn't go into that.
|
||||||
|
// So re-implement
|
||||||
|
|
||||||
|
let token = self
|
||||||
|
.token
|
||||||
|
.next_sibling_or_token()
|
||||||
|
.and_then(|e| match e {
|
||||||
|
rowan::NodeOrToken::Node(n) => n.first_token(),
|
||||||
|
rowan::NodeOrToken::Token(t) => Some(t),
|
||||||
|
})
|
||||||
|
.or_else(|| {
|
||||||
|
self.token.ancestors().find_map(|it| it.next_sibling_or_token()).and_then(|e| {
|
||||||
|
match e {
|
||||||
|
rowan::NodeOrToken::Node(n) => n.first_token(),
|
||||||
|
rowan::NodeOrToken::Token(t) => Some(t),
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})?;
|
||||||
|
Some(SyntaxToken { token, source_file: self.source_file.clone() })
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl std::fmt::Display for SyntaxToken {
|
impl std::fmt::Display for SyntaxToken {
|
||||||
|
|
@ -745,6 +770,11 @@ impl SyntaxNode {
|
||||||
pub fn parent(&self) -> Option<SyntaxNode> {
|
pub fn parent(&self) -> Option<SyntaxNode> {
|
||||||
self.node.parent().map(|node| SyntaxNode { node, source_file: self.source_file.clone() })
|
self.node.parent().map(|node| SyntaxNode { node, source_file: self.source_file.clone() })
|
||||||
}
|
}
|
||||||
|
pub fn first_token(&self) -> Option<SyntaxToken> {
|
||||||
|
self.node
|
||||||
|
.first_token()
|
||||||
|
.map(|token| SyntaxToken { token, source_file: self.source_file.clone() })
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, derive_more::From)]
|
#[derive(Debug, Clone, derive_more::From)]
|
||||||
|
|
|
||||||
|
|
@ -44,7 +44,7 @@ pub fn get_semantic_tokens(
|
||||||
SyntaxKind::StringLiteral => Some((self::STRING, 0)),
|
SyntaxKind::StringLiteral => Some((self::STRING, 0)),
|
||||||
SyntaxKind::NumberLiteral => Some((self::NUMBER, 0)),
|
SyntaxKind::NumberLiteral => Some((self::NUMBER, 0)),
|
||||||
SyntaxKind::ColorLiteral => Some((self::NUMBER, 0)),
|
SyntaxKind::ColorLiteral => Some((self::NUMBER, 0)),
|
||||||
SyntaxKind::Identifier => match token.parent()?.kind() {
|
SyntaxKind::Identifier => match token.parent().kind() {
|
||||||
SyntaxKind::Component => Some((self::KEYWORD, 0)),
|
SyntaxKind::Component => Some((self::KEYWORD, 0)),
|
||||||
// the id of the element
|
// the id of the element
|
||||||
SyntaxKind::SubElement => Some((self::VARIABLE, 1 << self::DEFINITION)),
|
SyntaxKind::SubElement => Some((self::VARIABLE, 1 << self::DEFINITION)),
|
||||||
|
|
@ -55,7 +55,7 @@ pub fn get_semantic_tokens(
|
||||||
SyntaxKind::CallbackConnection => Some((self::FUNCTION, 0)),
|
SyntaxKind::CallbackConnection => Some((self::FUNCTION, 0)),
|
||||||
SyntaxKind::PropertyDeclaration => Some((self::KEYWORD, 0)),
|
SyntaxKind::PropertyDeclaration => Some((self::KEYWORD, 0)),
|
||||||
SyntaxKind::PropertyAnimation => Some((self::KEYWORD, 0)),
|
SyntaxKind::PropertyAnimation => Some((self::KEYWORD, 0)),
|
||||||
SyntaxKind::QualifiedName => match token.parent()?.parent()?.kind() {
|
SyntaxKind::QualifiedName => match token.parent().parent()?.kind() {
|
||||||
SyntaxKind::Type => Some((self::TYPE, 0)),
|
SyntaxKind::Type => Some((self::TYPE, 0)),
|
||||||
// the base type
|
// the base type
|
||||||
SyntaxKind::Element => Some((self::TYPE, 0)),
|
SyntaxKind::Element => Some((self::TYPE, 0)),
|
||||||
|
|
@ -66,7 +66,7 @@ pub fn get_semantic_tokens(
|
||||||
_ => None,
|
_ => None,
|
||||||
},
|
},
|
||||||
SyntaxKind::DeclaredIdentifier => {
|
SyntaxKind::DeclaredIdentifier => {
|
||||||
match token.parent()?.parent()?.kind() {
|
match token.parent().parent()?.kind() {
|
||||||
SyntaxKind::Component => Some((self::TYPE, 1 << self::DEFINITION)),
|
SyntaxKind::Component => Some((self::TYPE, 1 << self::DEFINITION)),
|
||||||
SyntaxKind::RepeatedElement => {
|
SyntaxKind::RepeatedElement => {
|
||||||
Some((self::PROPERTY, 1 << self::DEFINITION))
|
Some((self::PROPERTY, 1 << self::DEFINITION))
|
||||||
|
|
@ -104,7 +104,7 @@ pub fn get_semantic_tokens(
|
||||||
SyntaxKind::ExportIdentifier => {
|
SyntaxKind::ExportIdentifier => {
|
||||||
Some((
|
Some((
|
||||||
self::TYPE,
|
self::TYPE,
|
||||||
if token.parent()?.parent().map_or(false, |p| {
|
if token.parent().parent().map_or(false, |p| {
|
||||||
p.children().any(|n| n.kind() == SyntaxKind::ExportName)
|
p.children().any(|n| n.kind() == SyntaxKind::ExportName)
|
||||||
}) {
|
}) {
|
||||||
0
|
0
|
||||||
|
|
@ -118,7 +118,7 @@ pub fn get_semantic_tokens(
|
||||||
SyntaxKind::ImportIdentifier => Some((self::KEYWORD, 0)),
|
SyntaxKind::ImportIdentifier => Some((self::KEYWORD, 0)),
|
||||||
SyntaxKind::ExternalName => Some((
|
SyntaxKind::ExternalName => Some((
|
||||||
self::TYPE,
|
self::TYPE,
|
||||||
if token.parent()?.parent().map_or(false, |p| {
|
if token.parent().parent().map_or(false, |p| {
|
||||||
p.children().any(|n| n.kind() == SyntaxKind::InternalName)
|
p.children().any(|n| n.kind() == SyntaxKind::InternalName)
|
||||||
}) {
|
}) {
|
||||||
0
|
0
|
||||||
|
|
@ -141,7 +141,7 @@ pub fn get_semantic_tokens(
|
||||||
| SyntaxKind::NotEqual
|
| SyntaxKind::NotEqual
|
||||||
| SyntaxKind::OrOr
|
| SyntaxKind::OrOr
|
||||||
| SyntaxKind::AndAnd => Some((self::OPERATOR, 0)),
|
| SyntaxKind::AndAnd => Some((self::OPERATOR, 0)),
|
||||||
SyntaxKind::LAngle | SyntaxKind::RAngle => (token.parent()?.kind()
|
SyntaxKind::LAngle | SyntaxKind::RAngle => (token.parent().kind()
|
||||||
== SyntaxKind::PropertyDeclaration)
|
== SyntaxKind::PropertyDeclaration)
|
||||||
.then(|| (self::OPERATOR, 0)),
|
.then(|| (self::OPERATOR, 0)),
|
||||||
SyntaxKind::Plus
|
SyntaxKind::Plus
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue