mirror of
https://github.com/joshuadavidthomas/django-language-server.git
synced 2025-09-14 14:25:36 +00:00
Fix: Improve TagSpec extraction to differentiate namespaces from specs
This commit is contained in:
parent
d9ddfa6d14
commit
0795974f1b
1 changed files with 47 additions and 38 deletions
|
@ -179,42 +179,24 @@ fn extract_specs(
|
||||||
current_path: &str, // The path leading up to current_value, e.g., "django.template.defaulttags"
|
current_path: &str, // The path leading up to current_value, e.g., "django.template.defaulttags"
|
||||||
specs_map: &mut HashMap<String, TagSpec>,
|
specs_map: &mut HashMap<String, TagSpec>,
|
||||||
) -> Result<(), String> {
|
) -> Result<(), String> {
|
||||||
// First, check if the current_value *itself* could be a TagSpec definition.
|
let mut is_namespace_table = false;
|
||||||
// This happens when the current_path represents the full path to the tag.
|
|
||||||
// We only attempt this if current_path is not empty (i.e., we are not at the root base table).
|
|
||||||
if !current_path.is_empty() {
|
|
||||||
match TagSpec::deserialize(current_value.clone()) {
|
|
||||||
// Successfully deserialized as a TagSpec
|
|
||||||
Ok(tag_spec) => {
|
|
||||||
// Success! current_value represents a TagSpec definition.
|
|
||||||
// Extract tag_name from the *end* of current_path.
|
|
||||||
if let Some(tag_name) = current_path.split('.').last().filter(|s| !s.is_empty()) {
|
|
||||||
// Insert into the map. Handle potential duplicates/overrides if needed.
|
|
||||||
specs_map.insert(tag_name.to_string(), tag_spec);
|
|
||||||
} else {
|
|
||||||
// This case should ideally not happen if current_path is not empty,
|
|
||||||
// but handle defensively.
|
|
||||||
return Err(format!(
|
|
||||||
"Could not extract tag name from non-empty path '{}'",
|
|
||||||
current_path
|
|
||||||
));
|
|
||||||
}
|
|
||||||
// Since we successfully parsed this node as a TagSpec,
|
|
||||||
// we assume it's a leaf node for specs and don't recurse further down
|
|
||||||
// into its fields (like 'end' or 'intermediates').
|
|
||||||
return Ok(()); // Stop processing this branch
|
|
||||||
}
|
|
||||||
// Failed to deserialize as TagSpec - it might be a namespace table.
|
|
||||||
Err(_) => { // Keep Err(_) to catch deserialization errors gracefully
|
|
||||||
// Deserialization as TagSpec failed. It might be a namespace table.
|
|
||||||
// Continue below to check if it's a table and recurse.
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// If we reached here, it means the node was NOT successfully deserialized as a TagSpec
|
|
||||||
// (either because the path was empty, or deserialization failed).
|
|
||||||
// check if it's a table and recurse into its children.
|
|
||||||
if let Some(table) = current_value.as_table() {
|
if let Some(table) = current_value.as_table() {
|
||||||
|
// Check if it contains keys other than 'end' or 'intermediates'
|
||||||
|
for key in table.keys() {
|
||||||
|
if key != "end" && key != "intermediates" {
|
||||||
|
is_namespace_table = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Not a table. Cannot be a spec or a namespace. Ignore.
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
|
||||||
|
if is_namespace_table {
|
||||||
|
// It's a namespace table, recurse into its children
|
||||||
|
// We know it's a table because is_namespace_table is true only if it was a table.
|
||||||
|
let table = current_value.as_table().unwrap(); // Safe unwrap
|
||||||
for (key, inner_value) in table.iter() {
|
for (key, inner_value) in table.iter() {
|
||||||
// Construct the new path for the recursive call
|
// Construct the new path for the recursive call
|
||||||
let new_path = if current_path.is_empty() {
|
let new_path = if current_path.is_empty() {
|
||||||
|
@ -225,7 +207,34 @@ fn extract_specs(
|
||||||
// Recurse
|
// Recurse
|
||||||
extract_specs(inner_value, &new_path, specs_map)?; // Propagate errors using ?
|
extract_specs(inner_value, &new_path, specs_map)?; // Propagate errors using ?
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
// It's NOT a namespace table (only 'end'/'intermediates' keys or empty table).
|
||||||
|
// Try to deserialize it as a TagSpec, but only if the path is non-empty.
|
||||||
|
if !current_path.is_empty() {
|
||||||
|
match TagSpec::deserialize(current_value.clone()) {
|
||||||
|
Ok(tag_spec) => {
|
||||||
|
if let Some(tag_name) = current_path.split('.').last().filter(|s| !s.is_empty()) {
|
||||||
|
specs_map.insert(tag_name.to_string(), tag_spec);
|
||||||
|
} else {
|
||||||
|
return Err(format!(
|
||||||
|
"Could not extract tag name from non-empty path '{}'",
|
||||||
|
current_path
|
||||||
|
));
|
||||||
}
|
}
|
||||||
|
// Don't recurse further, we found the spec leaf node.
|
||||||
|
}
|
||||||
|
Err(e) => {
|
||||||
|
// Deserialization failed for a node that *should* have been a spec.
|
||||||
|
return Err(format!(
|
||||||
|
"Failed to deserialize potential TagSpec at path '{}': {}",
|
||||||
|
current_path, e
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// If current_path was empty (root table), we don't try to deserialize, just continue.
|
||||||
|
}
|
||||||
|
|
||||||
// If it's not a table and not a TagSpec, ignore it.
|
// If it's not a table and not a TagSpec, ignore it.
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue