From 430c48a61ac1cf9c41b81e6f85c29b93439cbcfa Mon Sep 17 00:00:00 2001 From: ef3d0c3e Date: Thu, 24 Oct 2024 14:49:39 +0200 Subject: [PATCH] Graph semantics --- src/elements/graphviz.rs | 55 +++++++++++++++++++++++++++++++++++++++- src/elements/layout.rs | 12 ++++++--- src/lsp/semantic.rs | 10 ++++++++ 3 files changed, 72 insertions(+), 5 deletions(-) diff --git a/src/elements/graphviz.rs b/src/elements/graphviz.rs index e569b2a..1be9d19 100644 --- a/src/elements/graphviz.rs +++ b/src/elements/graphviz.rs @@ -14,6 +14,7 @@ use crypto::sha2::Sha512; use graphviz_rust::cmd::Format; use graphviz_rust::cmd::Layout; use graphviz_rust::exec_dot; +use lsp::semantic::Semantics; use mlua::Error::BadArgument; use mlua::Function; use mlua::Lua; @@ -335,13 +336,33 @@ impl RegexRule for GraphRule { state.push( document, Box::new(Graphviz { - location: token, + location: token.clone(), dot: graph_content, layout: graph_layout, width: graph_width, }), ); + if let Some((sems, tokens)) = + Semantics::from_source(token.source(), &state.shared.semantics) + { + let range = token.range; + sems.add( + range.start..range.start + 7, + tokens.graph_sep, + ); + if let Some(props) = matches.get(1).map(|m| m.range()) { + sems.add(props.start - 1..props.start, tokens.tex_props_sep); + sems.add(props.clone(), tokens.tex_props); + sems.add(props.end..props.end + 1, tokens.tex_props_sep); + } + sems.add(matches.get(2).unwrap().range(), tokens.tex_content); + sems.add( + range.end - 8..range.end, + tokens.graph_sep, + ); + } + reports } @@ -453,4 +474,36 @@ Another graph Graphviz { dot == "Another graph" }; ); } + + #[test] + fn semantic() { + let source = Rc::new(SourceFile::with_content( + "".to_string(), + r#" +[graph][width=50%] +digraph { +} +[/graph] + "# + .to_string(), + None, + )); + let parser = LangParser::default(); + let (_, state) = parser.parse( + ParserState::new_with_semantics(&parser, None), + source.clone(), + None, + ParseMode::default(), + ); + validate_semantics!(state, source.clone(), 0, + graph_sep { delta_line == 1, delta_start == 0, length == 7 }; + graph_props_sep { delta_line == 0, delta_start == 7, length == 1 }; + graph_props { delta_line == 0, delta_start == 1, length == 9 }; + graph_props_sep { delta_line == 0, delta_start == 9, length == 1 }; + graph_content { delta_line == 0, delta_start == 1, length == 1 }; + graph_content { delta_line == 1, delta_start == 0, length == 10 }; + graph_content { delta_line == 1, delta_start == 0, length == 2 }; + graph_sep { delta_line == 1, delta_start == 0, length == 8 }; + ); + } } diff --git a/src/elements/layout.rs b/src/elements/layout.rs index 7e24bd6..7bd6ca0 100644 --- a/src/elements/layout.rs +++ b/src/elements/layout.rs @@ -547,6 +547,7 @@ impl RegexRule for LayoutRule { if layout_type.expects().end < tokens.len() // Too many blocks { + let start = &tokens[0]; report_err!( &mut reports, token.source(), @@ -558,6 +559,11 @@ impl RegexRule for LayoutRule { layout_type.expects().end.fg(state.parser.colors().info), tokens.len().fg(state.parser.colors().info), ) + ), + span( + start.source(), + start.start() + 1..start.end(), + format!("Layout starts here",) ) ); return reports; @@ -639,10 +645,8 @@ impl RegexRule for LayoutRule { ), span( start.source(), - start.start() + 1.. start.end(), - format!( - "Layout begins here", - ) + start.start() + 1..start.end(), + format!("Layout starts here",) ) ); return reports; diff --git a/src/lsp/semantic.rs b/src/lsp/semantic.rs index a9d42ea..cd30bf4 100644 --- a/src/lsp/semantic.rs +++ b/src/lsp/semantic.rs @@ -151,6 +151,11 @@ pub struct Tokens { pub tex_props: (u32, u32), pub tex_content: (u32, u32), + pub graph_sep: (u32, u32), + pub graph_props_sep: (u32, u32), + pub graph_props: (u32, u32), + pub graph_content: (u32, u32), + pub layout_sep: (u32, u32), pub layout_token: (u32, u32), pub layout_props_sep: (u32, u32), @@ -223,6 +228,11 @@ impl Tokens { tex_props: token!("enum"), tex_content: token!("string"), + graph_sep: token!("modifier"), + graph_props_sep: token!("operator"), + graph_props: token!("enum"), + graph_content: token!("string"), + layout_sep: token!("number"), layout_token: token!("number"), layout_props_sep: token!("operator"),