diff --git a/jinja-lsp-queries/src/search/definition.rs b/jinja-lsp-queries/src/search/definition.rs index cb9ff7e..8692144 100644 --- a/jinja-lsp-queries/src/search/definition.rs +++ b/jinja-lsp-queries/src/search/definition.rs @@ -29,32 +29,69 @@ pub enum Definition { impl Definition { fn collect(self, ids: &mut Vec) { match self { - Definition::ForLoop { key, value, .. } => { + Definition::ForLoop { mut key, value, .. } => { + key.identifier_type = IdentifierType::ForLoopKey; ids.push(key); - if let Some(value) = value { + if let Some(mut value) = value { + value.identifier_type = IdentifierType::ForLoopValue; ids.push(value); } } - Definition::Set { key, .. } => { + Definition::Set { mut key, .. } => { + key.identifier_type = IdentifierType::SetVariable; ids.push(key); } Definition::With { keys, .. } => { - for key in keys { + for mut key in keys { + key.identifier_type = IdentifierType::WithVariable; ids.push(key); } } Definition::Macro { keys, .. } => { - for key in keys { - ids.push(key); + for mut key in keys.into_iter().enumerate() { + if key.0 == 0 { + key.1.identifier_type = IdentifierType::MacroName; + } else { + key.1.identifier_type = IdentifierType::MacroParameter; + } + ids.push(key.1); } } - Definition::Block { name, .. } => { + Definition::Block { mut name, .. } => { + name.identifier_type = IdentifierType::TemplateBlock; ids.push(name); } } } } +impl From<&str> for Definition { + fn from(value: &str) -> Self { + match value { + "for" => Self::ForLoop { + key: Identifier::default(), + value: None, + }, + "set" => Self::Set { + key: Identifier::default(), + equals: false, + }, + "with" => Self::With { keys: vec![] }, + "macro" => Definition::Macro { + keys: vec![], + scope: 0, + }, + "block" => Self::Block { + name: Identifier::default(), + }, + _ => Self::ForLoop { + key: Identifier::default(), + value: None, + }, + } + } +} + #[derive(Default, Clone, Copy, PartialEq, Eq, Hash, Debug)] pub enum Current { For, @@ -87,29 +124,13 @@ impl Current { _ => Self::NoDefinition, } } - - fn from_rest(name: &str) -> Self { - match name { - "for" => Current::For, - "set" => Current::Set, - "with" => Current::With, - "macro" => Current::Macro, - "block" => Current::Block, - "if" | "elseif" => Current::If, - "else" => Current::Else, - "filter" => Current::Filter, - "autoescape" => Current::Autoescape, - "raw" => Current::Raw, - _ => Current::NoDefinition, - } - } } #[derive(Default, Debug)] pub struct Scope { - id: usize, - start: Point, - end: Point, + pub id: usize, + pub start: Point, + pub end: Point, } impl Scope { @@ -125,316 +146,142 @@ impl Scope { #[derive(Default, Debug)] pub struct JinjaDefinitions { pub definitions: Vec, - pub current_definition: Current, + can_close_scope: bool, + can_open_scope: bool, + can_add_id: bool, + is_end: bool, pub current_scope: LinkedList, pub all_scopes: Vec, all_ids: HashSet, - pub in_end: bool, } impl JinjaDefinitions { - pub fn exist(&self, id: usize) -> bool { - self.all_ids.iter().any(|item| item == &id) - } - - pub fn add(&mut self, id: usize, current: Current) { - self.current_definition = current; - let mut def = None; - let mut add_scope = false; - match current { - Current::For => { - def = Some(Definition::ForLoop { - key: Identifier::default(), - value: None, - }); - add_scope = true; - } - Current::Set => { - // if !self.all_ids.contains(&id) { - self.all_ids.insert(id); - def = Some(Definition::Set { - key: Identifier::default(), - equals: false, - }); - // } - } - Current::With => { - def = Some(Definition::With { keys: vec![] }); - add_scope = true; - } - Current::Macro => { - def = Some(Definition::Macro { - keys: vec![], - scope: self.current_scope.front().unwrap_or(&Scope::default()).id, - }); - add_scope = true; - } - Current::Block => { - def = Some(Definition::Block { - name: Identifier::default(), - }); - add_scope = true; - } - Current::NoDefinition => (), - _ => { - add_scope = true; - } - } - if let Some(def) = def { - // let same_def = self.definitions.iter().find(|item| item.) - self.definitions.push(def); - self.all_ids.insert(id); - } - if add_scope { - self.current_scope.push_front(Scope { - id, - ..Default::default() - }); - } - } - fn check(&mut self, name: &str, capture: &QueryCapture<'_>, text: &str) -> Option { + let id = capture.node.id(); match name { - "error" => { - return None; - } - "for" => { - if !self.exist(capture.node.id()) { - self.add(capture.node.id(), Current::For); - } else { - self.current_definition = Current::NoDefinition; - } - } - - "for_key" => { - if self.current_definition == Current::For { - let def = self.definitions.last_mut()?; - if let Definition::ForLoop { key, .. } = def { - let start = capture.node.start_position(); - let end = capture.node.end_position(); - let content = capture.node.utf8_text(text.as_bytes()).ok()?; - key.name = content.to_string(); - key.start = start; - key.end = end; - key.identifier_type = IdentifierType::ForLoopKey; - key.scope_ends.0 = - self.current_scope.front().unwrap_or(&Scope::default()).id; - } + "definition" => { + if self.all_ids.contains(&id) { + return Some(false); } - } - - "for_value" => { - if self.current_definition == Current::For { - let def = self.definitions.last_mut()?; - if let Definition::ForLoop { value, .. } = def { - let mut identifier = Identifier::default(); - let start = capture.node.start_position(); - let end = capture.node.end_position(); - let content = capture.node.utf8_text(text.as_bytes()).ok()?; - identifier.name = content.to_owned(); - identifier.start = start; - identifier.end = end; - identifier.identifier_type = IdentifierType::ForLoopValue; - identifier.scope_ends.0 = - self.current_scope.front().unwrap_or(&Scope::default()).id; - *value = Some(identifier); - } + let content = capture.node.utf8_text(text.as_bytes()).unwrap(); + self.all_ids.insert(id); + let mut add_new_scope = true; + let mut definition = Definition::from(content); + if let Definition::Set { .. } = definition { + add_new_scope = false; + } else if let Definition::Macro { ref mut scope, .. } = &mut definition { + let current_scope = self.current_scope.front().unwrap_or(&Scope::default()).id; + *scope = current_scope; } - } - - "set" => { - if !self.exist(capture.node.id()) { - self.add(capture.node.id(), Current::Set); + self.definitions.push(definition); + if add_new_scope { + self.current_scope.push_front(Scope { + id, + ..Default::default() + }); + self.can_close_scope = false; + self.can_open_scope = true; + self.is_end = false; + self.can_add_id = true; } else { - self.current_definition = Current::NoDefinition; + self.can_add_id = true; } } - - "set_identifier" => { - if self.current_definition == Current::Set { - let def = self.definitions.last_mut()?; - if let Definition::Set { key, .. } = def { - let start = capture.node.start_position(); - let end = capture.node.end_position(); - let content = capture.node.utf8_text(text.as_bytes()).ok()?; - if content == key.name { - return None; - } - key.name = content.to_string(); - key.start = start; - key.end = end; - let scope = self.current_scope.front().unwrap_or(&Scope::default()).id; - key.scope_ends.0 = scope; - key.identifier_type = IdentifierType::SetVariable; - } - } - } - - "equals" => { - if self.current_definition == Current::Set { - let def = self.definitions.last_mut()?; - if let Definition::Set { equals, key } = def { - *equals = true; - key.scope_ends.0 = - self.current_scope.front().unwrap_or(&Scope::default()).id; - } - } - } - - "with" => { - if !self.exist(capture.node.id()) { - self.add(capture.node.id(), Current::With); - } else { - // self.current_definition = Current::NoDefinition; - } + "scope" => { + self.can_close_scope = false; + self.can_open_scope = true; + self.is_end = false; + self.can_add_id = false; + self.current_scope.push_front(Scope { + id, + ..Default::default() + }); } - - "with_identifier" => { - if self.current_definition == Current::With { - let def = self.definitions.last_mut()?; - if let Definition::With { keys, .. } = def { - let start = capture.node.start_position(); - let end = capture.node.end_position(); - let content = capture.node.utf8_text(text.as_bytes()).ok()?; - let mut key = Identifier::new(content, start, end); - key.identifier_type = IdentifierType::WithVariable; - key.scope_ends.0 = - self.current_scope.front().unwrap_or(&Scope::default()).id; - keys.push(key); - } - } + "endblock" => { + self.is_end = true; + self.can_close_scope = true; + self.can_open_scope = false; } - "block" => { - if !self.exist(capture.node.id()) { - self.add(capture.node.id(), Current::Block); - } else { - self.current_definition = Current::NoDefinition; + "equals" => { + let last = self.definitions.last_mut(); + if let Some(Definition::Set { equals, .. }) = last { + *equals = true; + self.can_open_scope = false; } } - - "block_identifier" => { - if self.current_definition == Current::Block { - let def = self.definitions.last_mut()?; - if let Definition::Block { name, .. } = def { - let start = capture.node.start_position(); - let end = capture.node.end_position(); - let content = capture.node.utf8_text(text.as_bytes()).ok()?; - name.name = content.to_string(); - name.start = start; - name.end = end; - name.identifier_type = IdentifierType::TemplateBlock; - name.scope_ends.0 = - self.current_scope.front().unwrap_or(&Scope::default()).id; - } - } + "error" => { + return None; } - - "macro" => { - if !self.exist(capture.node.id()) { - self.add(capture.node.id(), Current::Macro); - } else { - self.current_definition = Current::Macro; - // self.current_definition = Current::NoDefinition; + "id" => { + if !self.can_add_id { + return Some(false); } - } - - "macro_identifier" => { - if self.current_definition == Current::Macro { - let def = self.definitions.last_mut()?; - if let Definition::Macro { keys, .. } = def { - let start = capture.node.start_position(); - let end = capture.node.end_position(); - let content = capture.node.utf8_text(text.as_bytes()).ok()?; - - let mut key = Identifier::new(content, start, end); - key.scope_ends.0 = - self.current_scope.front().unwrap_or(&Scope::default()).id; - if keys.is_empty() { - key.identifier_type = IdentifierType::MacroName; - } else { - key.identifier_type = IdentifierType::MacroParameter; + let mut identifier = Identifier::default(); + let start = capture.node.start_position(); + let end = capture.node.end_position(); + let content = capture.node.utf8_text(text.as_bytes()).ok()?; + let current_scope = self.current_scope.front().unwrap_or(&Scope::default()).id; + identifier.start = start; + identifier.end = end; + identifier.name = content.to_owned(); + identifier.scope_ends.0 = current_scope; + let last = self.definitions.last_mut(); + if let Some(last) = last { + match last { + Definition::ForLoop { key, value } => { + if key.name.is_empty() { + *key = identifier; + } else if let Some(value) = value { + if value.name.is_empty() { + *value = identifier; + self.can_add_id = false; + } + } + } + Definition::Set { key, .. } => { + if key.name.is_empty() { + *key = identifier; + self.can_add_id = false; + } + } + Definition::With { keys } => { + keys.push(identifier); + } + Definition::Macro { keys, scope } => { + if keys.is_empty() { + identifier.scope_ends.0 = *scope; + } + keys.push(identifier); + } + Definition::Block { name } => { + if name.name.is_empty() { + *name = identifier; + self.can_add_id = false; + } } - keys.push(key); } } } - - "if" | "elif" | "else" | "filter" | "autoescape" | "raw" => { - let current = Current::from_rest(name); - self.add(capture.node.id(), current); - } - "ended" => { - self.in_end = true; - } - - "range_end" => { - if self.in_end { - self.in_end = false; - let mut last = self.current_scope.pop_front()?; - if last.end == Point::default() { + "scope_end" => { + if self.can_close_scope && self.is_end { + self.can_close_scope = false; + self.can_add_id = false; + self.is_end = false; + if let Some(mut last) = self.current_scope.pop_front() { last.end = capture.node.start_position(); - self.current_definition = Current::NoDefinition; self.all_scopes.push(last); } } } - - "range_start" => { - let mut can_add = true; - let mut is_set = false; - if let Some(last) = self.current_scope.front_mut() { - if let Some(Definition::Set { equals, .. }) = self.definitions.last() { - is_set = !equals; - if self.current_definition == Current::Set && *equals { - can_add = false; - } - } - if is_set && can_add { - self.current_scope.push_front(Scope { - id: capture.node.id(), - start: capture.node.end_position(), - ..Default::default() - }); - } else if can_add { + "scope_start" => { + if self.can_open_scope { + self.can_open_scope = false; + self.can_add_id = false; + if let Some(last) = self.current_scope.front_mut() { last.start = capture.node.end_position(); } - } else if self.current_definition != Current::NoDefinition { - if let Some(Definition::Set { equals, .. }) = self.definitions.last() { - if self.current_definition == Current::Set && !(*equals) { - can_add = true; - } - } - - if can_add { - self.current_scope.push_front(Scope { - id: capture.node.id(), - start: capture.node.end_position(), - ..Default::default() - }); - } } } - - // "range_end" => { - // let last = self.definitions.last()?; - // match last { - // Definition::ForLoop { .. } => { - // self.current = Current::For; - // } - // Definition::Set { .. } => { - // self.current = Current::Set; - // } - // Definition::With { .. } => { - // self.current = Current::With; - // } - // Definition::Macro { .. } => { - // self.current = Current::Macro; - // } - // Definition::Block { .. } => { - // self.current = Current::Block; - // } - // } - // } _ => {} } Some(true) @@ -445,6 +292,7 @@ impl JinjaDefinitions { for id in self.definitions { id.collect(&mut ids); } + ids } diff --git a/jinja-lsp-queries/src/search/queries.rs b/jinja-lsp-queries/src/search/queries.rs index 2668103..509700d 100644 --- a/jinja-lsp-queries/src/search/queries.rs +++ b/jinja-lsp-queries/src/search/queries.rs @@ -29,145 +29,6 @@ impl Default for Queries { } } -const DEFINITIONS: &str = r#" -( - [ - (statement - (statement_begin) - (keyword) @for_keyword - [ - ( - (operator)? @open_par - (identifier)? @for_key - . - (operator)? @comma - . - (identifier)? @for_value - . - (operator)? @close_par - (_). - ) @for2 - - ( - (identifier) @for_key - ) @for1 - ] - - - (#eq? @open_par "\(") - (#match-eq? @comma ",") - (#eq? @close_par "\)") - (#not-match? @for_key "(^\\d+$)") - (#not-match? @for_value "(^\\d+$)") - - (keyword) @in - (#eq @in "in") - (#eq? @for_keyword "for") - (identifier) @for_items - (_)? @other - (statement_end) @range_start - ) @for - - ( - (statement - (statement_begin) - (keyword) @set_keyword - (identifier) @set_identifier - (operator)? @equals - (_)? @others - (statement_end) @range_start - - (#eq? @set_keyword "set") - (#not-match? @set_identifier "(^\\d+$)") - (#eq? @equals "= ") - ) - ) @set - - (statement - (statement_begin) - (keyword) @with_keyword - (identifier) @with_identifier - (#eq? @with_keyword "with") - (#not-match? @with_identifier "(^\\d+$)") - (statement_end) @range_start - ) @with - - (statement - (statement_begin) - (keyword) @macro_keyword - (identifier) @macro_identifier - (#eq? @macro_keyword "macro") - (#not-match? @macro_identifier "(^\\d+$)") - (statement_end) @range_start - ) @macro - - (statement - (statement_begin) - (keyword) @block_keyword - (identifier) @block_identifier - (#eq? @block_keyword "block") - (#not-match? @block_identifier "(^\\d+$)") - (statement_end) @range_start - ) @block - - - (statement - (statement_begin) - (keyword) @ifkeyword - (#eq? @ifkeyword "if") - (statement_end) @range_start - ) @if - - (statement - (statement_begin) - (keyword) @elifkeyword - (#eq? @elifkeyword "elif") - (statement_end) @range_start - ) @elif - - (statement - (statement_begin) - (keyword) @elsekeyword - (#eq? @elsekeyword "else") - (statement_end) @range_start - ) @else - - - (statement - (statement_begin) - (keyword) @filterkeyword - (#eq? @filterkeyword "filter") - (statement_end) @range_start - ) @filter - - (statement - (statement_begin) - (keyword) @autokeyword - (#eq? @autokeyword "autoescape") - (statement_end) @range_start - ) @autoescape - - (statement - (statement_begin) - (keyword) @rawkeyword - (#eq? @rawkeyword "raw") - (statement_end) @range_start - ) @raw - (ERROR) @error - ] -) -[ - (statement - (statement_begin) @range_end - (keyword) @endkeyword - (#match? @endkeyword "^end") - (statement_end) - ) @ended - -] - -"#; - const OBJECTS: &str = r#" ( [ @@ -302,3 +163,37 @@ const JINJA_SNIPPETS: &str = r#" ) ] "#; + +const DEFINITIONS: &str = r#" +(statement + (statement_begin) @scope_end + + (statement_end) @scope_start +) + +( + (identifier) @id + (#not-match? @id "^(\\d+)$") +) + ( + (keyword) @definition + (#match? @definition "^(for|set|with|macro|block)$") + ) + + ( + (keyword) @scope + (#match? @scope "^(if|elif|else|filter|autoescape|raw)$") + ) + + ( + (keyword) @endblock + (#match? @endblock "^end") + ) + +( + (operator) @equals + (#match? @equals "=") +) + +(ERROR) @error +"#; diff --git a/jinja-lsp-queries/src/search/test_queries.rs b/jinja-lsp-queries/src/search/test_queries.rs index 90c2e96..41cd8b5 100644 --- a/jinja-lsp-queries/src/search/test_queries.rs +++ b/jinja-lsp-queries/src/search/test_queries.rs @@ -260,7 +260,7 @@ mod query_tests { let templates = rust_templates_query(query, &tree, trigger_point, source, false); if let Some(template) = templates.in_template(trigger_point) { if let Some(completion) = completion_start(trigger_point, template) { - assert_eq!(completion, "accoun"); + assert_eq!(completion, "accou"); } } }