Skip to main content

oak_typescript/highlighter/
mod.rs

1use crate::{kind::TypeScriptSyntaxKind, language::TypeScriptLanguage, lexer::TypeScriptLexer};
2use oak_core::{Lexer, SourceText, TextEdit, TokenType, UniversalTokenRole};
3
4/// 高亮类型的本地定义
5#[derive(Debug, Clone, Copy, PartialEq, Eq)]
6pub enum HighlightKind {
7    /// 关键字
8    Keyword,
9    /// 字符串
10    String,
11    /// 数字
12    Number,
13    /// 注释
14    Comment,
15    /// 标识符
16    Identifier,
17    /// 操作符
18    Operator,
19    /// 标点符号
20    Punctuation,
21    /// 错误
22    Error,
23}
24
25/// 高亮器 trait
26pub trait Highlighter {
27    /// 对给定的文本进行高亮处理
28    fn highlight(&self, text: &str) -> Vec<(usize, usize, HighlightKind)>;
29}
30
31/// TypeScript 语法高亮器
32pub struct TypeScriptHighlighter<'config> {
33    lexer: TypeScriptLexer<'config>,
34}
35
36impl<'config> TypeScriptHighlighter<'config> {
37    pub fn new(config: &'config TypeScriptLanguage) -> Self {
38        Self { lexer: TypeScriptLexer::new(config) }
39    }
40}
41
42impl<'config> Highlighter for TypeScriptHighlighter<'config> {
43    fn highlight(&self, text: &str) -> Vec<(usize, usize, HighlightKind)> {
44        let mut session = oak_core::parser::session::ParseSession::<TypeScriptLanguage>::default();
45        let edits = Vec::<TextEdit>::new();
46        let source = SourceText::new(text);
47        let output = self.lexer.lex(&source, &edits, &mut session);
48
49        let mut highlights = Vec::new();
50        if let Ok(tokens) = output.result {
51            for token in tokens.iter() {
52                let kind = match token.kind.role() {
53                    UniversalTokenRole::Keyword => HighlightKind::Keyword,
54                    UniversalTokenRole::Literal => match token.kind {
55                        TypeScriptSyntaxKind::StringLiteral | TypeScriptSyntaxKind::TemplateString | TypeScriptSyntaxKind::RegexLiteral => HighlightKind::String,
56                        TypeScriptSyntaxKind::NumericLiteral | TypeScriptSyntaxKind::BigIntLiteral => HighlightKind::Number,
57                        _ => HighlightKind::String,
58                    },
59                    UniversalTokenRole::Comment => HighlightKind::Comment,
60                    UniversalTokenRole::Name => HighlightKind::Identifier,
61                    UniversalTokenRole::Operator => HighlightKind::Operator,
62                    UniversalTokenRole::Punctuation => HighlightKind::Punctuation,
63                    _ => continue,
64                };
65                highlights.push((token.span.start, token.span.end, kind));
66            }
67        }
68
69        highlights
70    }
71}