1use cairo_lang_diagnostics::{Diagnostics, DiagnosticsBuilder, Maybe, ToMaybe};
2use cairo_lang_filesystem::db::FilesGroup;
3use cairo_lang_filesystem::ids::{FileId, FileKind};
4use cairo_lang_syntax::node::ast::{Expr, SyntaxFile};
5use cairo_lang_syntax::node::db::SyntaxGroup;
6use cairo_lang_syntax::node::{SyntaxNode, TypedSyntaxNode};
7use cairo_lang_utils::Upcast;
8
9use crate::diagnostic::ParserDiagnostic;
10use crate::parser::Parser;
11
12#[cfg(test)]
13#[path = "db_test.rs"]
14mod db_test;
15
16#[salsa::query_group(ParserDatabase)]
18pub trait ParserGroup: SyntaxGroup + Upcast<dyn SyntaxGroup> + FilesGroup {
19 fn priv_file_syntax_data(&self, file_id: FileId) -> SyntaxData;
22 fn file_syntax(&self, file_id: FileId) -> Maybe<SyntaxNode>;
24 fn file_module_syntax(&self, file_id: FileId) -> Maybe<SyntaxFile>;
26 fn file_expr_syntax(&self, file_id: FileId) -> Maybe<Expr>;
28 fn file_syntax_diagnostics(&self, file_id: FileId) -> Diagnostics<ParserDiagnostic>;
30}
31
32#[derive(Clone, PartialEq, Eq, Debug)]
33pub struct SyntaxData {
34 diagnostics: Diagnostics<ParserDiagnostic>,
35 syntax: Maybe<SyntaxNode>,
36}
37
38pub fn priv_file_syntax_data(db: &dyn ParserGroup, file_id: FileId) -> SyntaxData {
39 let mut diagnostics = DiagnosticsBuilder::default();
40 let syntax = db.file_content(file_id).to_maybe().map(|s| match file_id.kind(db.upcast()) {
41 FileKind::Module => {
42 Parser::parse_file(db.upcast(), &mut diagnostics, file_id, &s).as_syntax_node()
43 }
44 FileKind::Expr => {
45 Parser::parse_file_expr(db.upcast(), &mut diagnostics, file_id, &s).as_syntax_node()
46 }
47 });
48 SyntaxData { diagnostics: diagnostics.build(), syntax }
49}
50
51pub fn file_syntax(db: &dyn ParserGroup, file_id: FileId) -> Maybe<SyntaxNode> {
52 db.priv_file_syntax_data(file_id).syntax
53}
54
55pub fn file_module_syntax(db: &dyn ParserGroup, file_id: FileId) -> Maybe<SyntaxFile> {
56 assert_eq!(file_id.kind(db.upcast()), FileKind::Module, "file_id must be a module");
57 Ok(SyntaxFile::from_syntax_node(db.upcast(), db.file_syntax(file_id)?))
58}
59
60pub fn file_expr_syntax(db: &dyn ParserGroup, file_id: FileId) -> Maybe<Expr> {
61 assert_eq!(file_id.kind(db.upcast()), FileKind::Expr, "file_id must be a module");
62 Ok(Expr::from_syntax_node(db.upcast(), db.file_syntax(file_id)?))
63}
64
65pub fn file_syntax_diagnostics(
66 db: &dyn ParserGroup,
67 file_id: FileId,
68) -> Diagnostics<ParserDiagnostic> {
69 db.priv_file_syntax_data(file_id).diagnostics
70}