diff --git a/internal/compiler/parser.rs b/internal/compiler/parser.rs index 8e75d57b8a..ed5d88eb76 100644 --- a/internal/compiler/parser.rs +++ b/internal/compiler/parser.rs @@ -693,6 +693,31 @@ impl SyntaxToken { pub fn parent(&self) -> SyntaxNode { SyntaxNode { node: self.token.parent().unwrap(), source_file: self.source_file.clone() } } + pub fn next_token(&self) -> Option { + // 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 { @@ -745,6 +770,11 @@ impl SyntaxNode { pub fn parent(&self) -> Option { self.node.parent().map(|node| SyntaxNode { node, source_file: self.source_file.clone() }) } + pub fn first_token(&self) -> Option { + self.node + .first_token() + .map(|token| SyntaxToken { token, source_file: self.source_file.clone() }) + } } #[derive(Debug, Clone, derive_more::From)] diff --git a/tools/lsp/semantic_tokens.rs b/tools/lsp/semantic_tokens.rs index d43968b41f..03c48d76ea 100644 --- a/tools/lsp/semantic_tokens.rs +++ b/tools/lsp/semantic_tokens.rs @@ -44,7 +44,7 @@ pub fn get_semantic_tokens( SyntaxKind::StringLiteral => Some((self::STRING, 0)), SyntaxKind::NumberLiteral => 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)), // the id of the element SyntaxKind::SubElement => Some((self::VARIABLE, 1 << self::DEFINITION)), @@ -55,7 +55,7 @@ pub fn get_semantic_tokens( SyntaxKind::CallbackConnection => Some((self::FUNCTION, 0)), SyntaxKind::PropertyDeclaration => 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)), // the base type SyntaxKind::Element => Some((self::TYPE, 0)), @@ -66,7 +66,7 @@ pub fn get_semantic_tokens( _ => None, }, SyntaxKind::DeclaredIdentifier => { - match token.parent()?.parent()?.kind() { + match token.parent().parent()?.kind() { SyntaxKind::Component => Some((self::TYPE, 1 << self::DEFINITION)), SyntaxKind::RepeatedElement => { Some((self::PROPERTY, 1 << self::DEFINITION)) @@ -104,7 +104,7 @@ pub fn get_semantic_tokens( SyntaxKind::ExportIdentifier => { Some(( 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) }) { 0 @@ -118,7 +118,7 @@ pub fn get_semantic_tokens( SyntaxKind::ImportIdentifier => Some((self::KEYWORD, 0)), SyntaxKind::ExternalName => Some(( 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) }) { 0 @@ -141,7 +141,7 @@ pub fn get_semantic_tokens( | SyntaxKind::NotEqual | SyntaxKind::OrOr | SyntaxKind::AndAnd => Some((self::OPERATOR, 0)), - SyntaxKind::LAngle | SyntaxKind::RAngle => (token.parent()?.kind() + SyntaxKind::LAngle | SyntaxKind::RAngle => (token.parent().kind() == SyntaxKind::PropertyDeclaration) .then(|| (self::OPERATOR, 0)), SyntaxKind::Plus