Skip to main content

oak_csharp/builder/
mod.rs

1use crate::{ast::*, language::CSharpLanguage, lexer::token_type::CSharpTokenType, parser::CSharpElementType};
2use core::range::Range;
3use oak_core::{
4    GreenNode, Parser, TokenType,
5    builder::{BuildOutput, Builder, BuilderCache},
6    source::{Source, TextEdit},
7    tree::red_tree::{RedNode, RedTree},
8};
9
10pub struct CSharpBuilder<'config> {
11    language: &'config CSharpLanguage,
12}
13
14impl<'config> CSharpBuilder<'config> {
15    pub fn new(language: &'config CSharpLanguage) -> Self {
16        Self { language }
17    }
18
19    fn build_root(&self, green: &GreenNode<CSharpLanguage>, source: &str) -> CSharpRoot {
20        let red = RedNode::new(green, 0);
21        let mut items = Vec::new();
22
23        for child in red.children() {
24            if let RedTree::Node(node) = child {
25                if let Some(item) = self.build_item(node, source) {
26                    items.push(item);
27                }
28            }
29        }
30
31        CSharpRoot { items }
32    }
33
34    fn build_item(&self, node: RedNode<CSharpLanguage>, source: &str) -> Option<Item> {
35        match node.green.kind {
36            CSharpElementType::NamespaceDeclaration => Some(Item::Namespace(self.build_namespace(node, source))),
37            CSharpElementType::UsingDirective => Some(Item::Using(self.build_using(node, source))),
38            CSharpElementType::ClassDeclaration => Some(Item::Class(self.build_class(node, source))),
39            CSharpElementType::InterfaceDeclaration => Some(Item::Interface(self.build_interface(node, source))),
40            CSharpElementType::StructDeclaration => Some(Item::Struct(self.build_struct(node, source))),
41            CSharpElementType::EnumDeclaration => Some(Item::Enum(self.build_enum(node, source))),
42            CSharpElementType::RecordDeclaration => Some(Item::Record(self.build_record(node, source))),
43            CSharpElementType::DelegateDeclaration => Some(Item::Delegate(self.build_delegate(node, source))),
44            _ => None,
45        }
46    }
47
48    fn get_text<'a>(&self, span: Range<usize>, source: &'a str) -> &'a str {
49        let start = span.start;
50        let end = span.end;
51        if start > source.len() || end > source.len() || start > end {
52            return "";
53        }
54        &source[start..end]
55    }
56
57    fn extract_identifier(&self, node: RedNode<CSharpLanguage>, source: &str) -> String {
58        for child in node.children() {
59            match child {
60                RedTree::Leaf(leaf) => {
61                    if leaf.kind == CSharpTokenType::Identifier {
62                        return self.get_text(leaf.span, source).trim().to_string();
63                    }
64                }
65                RedTree::Node(sub_node) => {
66                    if sub_node.kind::<CSharpElementType>() == CSharpElementType::IdentifierName {
67                        return self.get_text(sub_node.span(), source).trim().to_string();
68                    }
69                    let id = self.extract_identifier(sub_node, source);
70                    if !id.is_empty() {
71                        return id;
72                    }
73                }
74            }
75        }
76        String::new()
77    }
78
79    fn extract_attributes(&self, node: RedNode<CSharpLanguage>, source: &str) -> Vec<Attribute> {
80        let mut attributes = Vec::new();
81        for child in node.children() {
82            if let RedTree::Node(sub_node) = child {
83                if sub_node.green.kind == CSharpElementType::AttributeList {
84                    for attr_child in sub_node.children() {
85                        if let RedTree::Node(attr_node) = attr_child {
86                            if attr_node.green.kind == CSharpElementType::Attribute {
87                                let name = self.extract_identifier(attr_node.clone(), source);
88                                let mut arguments = Vec::new();
89                                // TODO: Extract arguments
90                                attributes.push(Attribute { name, arguments })
91                            }
92                        }
93                    }
94                }
95            }
96        }
97        attributes
98    }
99
100    fn build_namespace(&self, node: RedNode<CSharpLanguage>, source: &str) -> NamespaceDeclaration {
101        let name = self.extract_identifier(node.clone(), source);
102        let attributes = self.extract_attributes(node.clone(), source);
103        let mut items = Vec::new();
104
105        for child in node.children() {
106            if let RedTree::Node(sub_node) = child {
107                if let Some(item) = self.build_item(sub_node, source) {
108                    items.push(item)
109                }
110            }
111        }
112
113        NamespaceDeclaration { name, attributes, items, span: node.span() }
114    }
115
116    fn build_using(&self, node: RedNode<CSharpLanguage>, source: &str) -> UsingDirective {
117        let path = self.extract_identifier(node.clone(), source);
118        let is_static = self.get_text(node.span(), source).contains("static");
119        let is_global = self.get_text(node.span(), source).contains("global");
120        UsingDirective {
121            path,
122            is_static,
123            alias: None, // TODO
124            is_global,
125            span: node.span(),
126        }
127    }
128
129    fn build_class(&self, node: RedNode<CSharpLanguage>, source: &str) -> ClassDeclaration {
130        let name = self.extract_identifier(node.clone(), source);
131        let mut members = Vec::new();
132        let modifiers = self.extract_modifiers(node.clone(), source);
133        let attributes = self.extract_attributes(node.clone(), source);
134
135        for child in node.children() {
136            if let RedTree::Node(sub_node) = child {
137                self.collect_members(sub_node, source, &mut members)
138            }
139        }
140
141        ClassDeclaration { name, attributes, modifiers, base_types: Vec::new(), type_parameters: Vec::new(), constraints: Vec::new(), members, span: node.span() }
142    }
143
144    fn build_interface(&self, node: RedNode<CSharpLanguage>, source: &str) -> InterfaceDeclaration {
145        let name = self.extract_identifier(node.clone(), source);
146        let modifiers = self.extract_modifiers(node.clone(), source);
147        let attributes = self.extract_attributes(node.clone(), source);
148        let mut members = Vec::new();
149        for child in node.children() {
150            if let RedTree::Node(sub_node) = child {
151                self.collect_members(sub_node, source, &mut members)
152            }
153        }
154        InterfaceDeclaration { name, attributes, modifiers, members, type_parameters: Vec::new(), span: node.span() }
155    }
156
157    fn build_struct(&self, node: RedNode<CSharpLanguage>, source: &str) -> StructDeclaration {
158        let name = self.extract_identifier(node.clone(), source);
159        let modifiers = self.extract_modifiers(node.clone(), source);
160        let attributes = self.extract_attributes(node.clone(), source);
161        let mut members = Vec::new();
162        for child in node.children() {
163            if let RedTree::Node(sub_node) = child {
164                self.collect_members(sub_node, source, &mut members)
165            }
166        }
167        StructDeclaration { name, attributes, modifiers, members, type_parameters: Vec::new(), span: node.span() }
168    }
169
170    fn build_enum(&self, node: RedNode<CSharpLanguage>, source: &str) -> EnumDeclaration {
171        let name = self.extract_identifier(node.clone(), source);
172        let modifiers = self.extract_modifiers(node.clone(), source);
173        let attributes = self.extract_attributes(node.clone(), source);
174        let mut members = Vec::new();
175        // 处理枚举成员
176        for child in node.children() {
177            if let RedTree::Node(sub_node) = child {
178                if sub_node.kind::<CSharpElementType>() == CSharpElementType::IdentifierName {
179                    members.push(EnumMember { name: self.get_text(sub_node.span(), source).to_string(), attributes: Vec::new(), value: None })
180                }
181            }
182        }
183        EnumDeclaration { name, attributes, modifiers, members, span: node.span() }
184    }
185
186    fn build_record(&self, node: RedNode<CSharpLanguage>, source: &str) -> RecordDeclaration {
187        let name = self.extract_identifier(node.clone(), source);
188        let modifiers = self.extract_modifiers(node.clone(), source);
189        let attributes = self.extract_attributes(node.clone(), source);
190        let mut members = Vec::new();
191        for child in node.children() {
192            if let RedTree::Node(sub_node) = child {
193                self.collect_members(sub_node, source, &mut members)
194            }
195        }
196        RecordDeclaration { name, attributes, modifiers, members, type_parameters: Vec::new(), span: node.span() }
197    }
198
199    fn build_delegate(&self, node: RedNode<CSharpLanguage>, source: &str) -> DelegateDeclaration {
200        let name = self.extract_identifier(node.clone(), source);
201        let modifiers = self.extract_modifiers(node.clone(), source);
202        let attributes = self.extract_attributes(node.clone(), source);
203        DelegateDeclaration { name, attributes, modifiers, return_type: "void".to_string(), type_parameters: Vec::new(), parameters: Vec::new(), span: node.span() }
204    }
205
206    fn extract_modifiers(&self, node: RedNode<CSharpLanguage>, source: &str) -> Vec<String> {
207        let mut modifiers = Vec::new();
208        for child in node.children() {
209            if let RedTree::Leaf(leaf) = child {
210                if leaf.kind.is_keyword() {
211                    let text = self.get_text(leaf.span, source).trim();
212                    match text {
213                        "public" | "private" | "protected" | "internal" | "static" | "readonly" | "abstract" | "virtual" | "override" | "async" | "volatile" | "sealed" | "extern" | "partial" | "new" | "unsafe" => modifiers.push(text.to_string()),
214                        _ => {}
215                    }
216                }
217            }
218        }
219        modifiers
220    }
221
222    fn collect_members(&self, node: RedNode<CSharpLanguage>, source: &str, members: &mut Vec<Member>) {
223        match node.green.kind {
224            CSharpElementType::MethodDeclaration => members.push(Member::Method(self.build_method(node, source))),
225            CSharpElementType::FieldDeclaration => members.push(Member::Field(self.build_field(node, source))),
226            CSharpElementType::PropertyDeclaration => members.push(Member::Property(self.build_property(node, source))),
227            CSharpElementType::IndexerDeclaration => members.push(Member::Indexer(self.build_indexer(node, source))),
228            CSharpElementType::EventDeclaration => members.push(Member::Event(self.build_event(node, source))),
229            _ => {
230                for child in node.children() {
231                    if let RedTree::Node(sub_node) = child {
232                        self.collect_members(sub_node, source, members)
233                    }
234                }
235            }
236        }
237    }
238
239    fn build_method(&self, node: RedNode<CSharpLanguage>, source: &str) -> MethodDeclaration {
240        let name = self.extract_identifier(node.clone(), source);
241        let modifiers = self.extract_modifiers(node.clone(), source);
242        let attributes = self.extract_attributes(node.clone(), source);
243        let is_async = modifiers.contains(&"async".to_string());
244
245        MethodDeclaration {
246            name,
247            attributes,
248            modifiers,
249            return_type: "void".to_string(), // TODO
250            type_parameters: Vec::new(),     // TODO
251            parameters: Vec::new(),          // TODO
252            body: self.build_body(node.clone(), source),
253            is_async,
254            span: node.span(),
255        }
256    }
257
258    fn build_field(&self, node: RedNode<CSharpLanguage>, source: &str) -> FieldDeclaration {
259        let name = self.extract_identifier(node.clone(), source);
260        let attributes = self.extract_attributes(node.clone(), source);
261        FieldDeclaration {
262            name,
263            attributes,
264            r#type: "object".to_string(), // TODO
265            modifiers: self.extract_modifiers(node, source),
266            initializer: None, // TODO
267            span: Range::default(),
268        }
269    }
270
271    fn build_property(&self, node: RedNode<CSharpLanguage>, source: &str) -> PropertyDeclaration {
272        let name = self.extract_identifier(node.clone(), source);
273        let attributes = self.extract_attributes(node.clone(), source);
274        PropertyDeclaration {
275            name,
276            attributes,
277            r#type: "object".to_string(), // TODO
278            modifiers: self.extract_modifiers(node, source),
279            get_accessor: None, // TODO
280            set_accessor: None, // TODO
281            span: node.span(),
282        }
283    }
284
285    fn build_indexer(&self, node: RedNode<CSharpLanguage>, source: &str) -> IndexerDeclaration {
286        let attributes = self.extract_attributes(node.clone(), source);
287        IndexerDeclaration {
288            attributes,
289            r#type: "object".to_string(), // TODO
290            parameters: Vec::new(),       // TODO
291            get_accessor: None,           // TODO
292            set_accessor: None,           // TODO
293            span: node.span(),
294        }
295    }
296
297    fn build_event(&self, node: RedNode<CSharpLanguage>, source: &str) -> EventDeclaration {
298        let name = self.extract_identifier(node.clone(), source);
299        let attributes = self.extract_attributes(node.clone(), source);
300        EventDeclaration {
301            name,
302            attributes,
303            r#type: "object".to_string(), // TODO
304            modifiers: self.extract_modifiers(node, source),
305            span: node.span(),
306        }
307    }
308
309    fn build_body(&self, node: RedNode<CSharpLanguage>, source: &str) -> Option<Vec<Statement>> {
310        for child in node.children() {
311            if let RedTree::Node(sub_node) = child {
312                if sub_node.green.kind == CSharpElementType::Block {
313                    let mut statements = Vec::new();
314                    for grandchild in sub_node.children() {
315                        if let RedTree::Node(grandchild_node) = grandchild {
316                            if let Some(stmt) = self.build_statement(grandchild_node, source) {
317                                statements.push(stmt)
318                            }
319                        }
320                    }
321                    return Some(statements);
322                }
323            }
324        }
325        None
326    }
327
328    fn build_statement(&self, node: RedNode<CSharpLanguage>, source: &str) -> Option<Statement> {
329        match node.green.kind {
330            CSharpElementType::ExpressionStatement => {
331                for child in node.children() {
332                    if let RedTree::Node(sub_node) = child {
333                        if let Some(expr) = self.build_expression(sub_node, source) {
334                            return Some(Statement::Expression(expr));
335                        }
336                    }
337                }
338                None
339            }
340            CSharpElementType::ReturnStatement => {
341                for child in node.children() {
342                    if let RedTree::Node(sub_node) = child {
343                        if let Some(expr) = self.build_expression(sub_node, source) {
344                            return Some(Statement::Return(Some(expr)));
345                        }
346                    }
347                }
348                Some(Statement::Return(None))
349            }
350            CSharpElementType::Block => {
351                let mut statements = Vec::new();
352                for child in node.children() {
353                    if let RedTree::Node(sub_node) = child {
354                        if let Some(stmt) = self.build_statement(sub_node, source) {
355                            statements.push(stmt)
356                        }
357                    }
358                }
359                Some(Statement::Block(statements))
360            }
361            CSharpElementType::IfStatement => {
362                // Simplified
363                Some(Statement::If { condition: Expression::Literal(Literal::Boolean(true)), then_branch: Box::new(Statement::Block(Vec::new())), else_branch: None })
364            }
365            CSharpElementType::BreakStatement => Some(Statement::Break),
366            CSharpElementType::ContinueStatement => Some(Statement::Continue),
367            _ => None,
368        }
369    }
370
371    fn build_expression(&self, node: RedNode<CSharpLanguage>, source: &str) -> Option<Expression> {
372        match node.green.kind {
373            CSharpElementType::LiteralExpression => {
374                let text = self.get_text(node.span(), source).trim();
375                if text == "true" {
376                    Some(Expression::Literal(Literal::Boolean(true)))
377                }
378                else if text == "false" {
379                    Some(Expression::Literal(Literal::Boolean(false)))
380                }
381                else if text == "null" {
382                    Some(Expression::Literal(Literal::Null))
383                }
384                else if let Ok(n) = text.parse::<i64>() {
385                    Some(Expression::Literal(Literal::Integer(n)))
386                }
387                else {
388                    Some(Expression::Literal(Literal::String(text.to_string())))
389                }
390            }
391            CSharpElementType::IdentifierName => Some(Expression::Identifier(self.get_text(node.span(), source).trim().to_string())),
392            CSharpElementType::AwaitExpression => {
393                for child in node.children() {
394                    if let RedTree::Node(sub_node) = child {
395                        if let Some(expr) = self.build_expression(sub_node, source) {
396                            return Some(Expression::Await(Box::new(expr)));
397                        }
398                    }
399                }
400                None
401            }
402            _ => None,
403        }
404    }
405}
406
407impl<'config> Builder<CSharpLanguage> for CSharpBuilder<'config> {
408    fn build<'a, S: Source + ?Sized>(&self, source: &'a S, edits: &[TextEdit], cache: &'a mut impl BuilderCache<CSharpLanguage>) -> BuildOutput<CSharpLanguage> {
409        let mut session = oak_core::parser::ParseSession::<CSharpLanguage>::default();
410        let parser = crate::parser::CSharpParser::new(self.language);
411        let output = parser.parse(source, edits, &mut session);
412
413        let mut result = Err(oak_core::OakError::custom_error("Build failed"));
414        if let Ok(green) = &output.result {
415            let root = self.build_root(green, source.get_text_in((0..source.length()).into()).as_ref());
416            result = Ok(root)
417        }
418
419        oak_core::errors::OakDiagnostics { result, diagnostics: output.diagnostics }
420    }
421}