mirror of
https://github.com/joshuadavidthomas/django-language-server.git
synced 2025-09-10 04:16:30 +00:00
remove variable type
This commit is contained in:
parent
360276af1a
commit
1295247aa9
4 changed files with 44 additions and 68 deletions
|
@ -127,9 +127,6 @@ pub enum Block {
|
||||||
tag: Tag,
|
tag: Tag,
|
||||||
template_name: String,
|
template_name: String,
|
||||||
},
|
},
|
||||||
Variable {
|
|
||||||
tag: Tag,
|
|
||||||
},
|
|
||||||
Closing {
|
Closing {
|
||||||
tag: Tag,
|
tag: Tag,
|
||||||
},
|
},
|
||||||
|
@ -231,21 +228,6 @@ Examples:
|
||||||
- `{% include "template.html" %}`
|
- `{% include "template.html" %}`
|
||||||
- `{% extends "base.html" %}`
|
- `{% extends "base.html" %}`
|
||||||
|
|
||||||
##### `Block::Variable`
|
|
||||||
|
|
||||||
Represents tags that output a value directly.
|
|
||||||
|
|
||||||
```rust
|
|
||||||
Block::Variable {
|
|
||||||
tag: Tag, // The Tag of the variable tag
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
Examples:
|
|
||||||
|
|
||||||
- `{% cycle %}`
|
|
||||||
- `{% firstof %}`
|
|
||||||
|
|
||||||
##### `Block::Closing`
|
##### `Block::Closing`
|
||||||
|
|
||||||
Represents closing tags corresponding to opening block tags.
|
Represents closing tags corresponding to opening block tags.
|
||||||
|
@ -270,15 +252,21 @@ Tag Specifications (TagSpecs) define how tags are parsed and understood. They al
|
||||||
|
|
||||||
```toml
|
```toml
|
||||||
[package.module.path.tag_name] # Path where tag is registered, e.g., django.template.defaulttags
|
[package.module.path.tag_name] # Path where tag is registered, e.g., django.template.defaulttags
|
||||||
type = "block" | "inclusion" | "tag" | "variable"
|
type = "block" | "inclusion" | "tag"
|
||||||
closing = "closing_tag_name" # For block tags that require a closing tag
|
closing = "closing_tag_name" # For block tags that require a closing tag
|
||||||
branches = ["branch_tag_name", ...] # For block tags that support branches
|
branches = ["branch_tag_name", ...] # For block tags that support branches
|
||||||
|
|
||||||
[[package.module.path.tag_name.args]]
|
# Arguments can be positional (matched by order) or keyword (matched by name)
|
||||||
name = "argument_name"
|
args = [
|
||||||
required = true | false
|
# Positional argument (position inferred from array index)
|
||||||
|
{ name = "setting", required = true, allowed_values = ["on", "off"] },
|
||||||
|
# Keyword argument
|
||||||
|
{ name = "key", required = false, is_kwarg = true }
|
||||||
|
]
|
||||||
```
|
```
|
||||||
|
|
||||||
|
The `name` field in args should match the internal name used in Django's node implementation. For example, the `autoescape` tag's argument is stored as `setting` in Django's `AutoEscapeControlNode`.
|
||||||
|
|
||||||
### Tag Types
|
### Tag Types
|
||||||
|
|
||||||
- `block`: Tags that wrap content and require a closing tag
|
- `block`: Tags that wrap content and require a closing tag
|
||||||
|
@ -301,13 +289,6 @@ required = true | false
|
||||||
{% csrf_token %}
|
{% csrf_token %}
|
||||||
```
|
```
|
||||||
|
|
||||||
- `variable`: Tags that output a value directly
|
|
||||||
|
|
||||||
```django
|
|
||||||
{% cycle 'odd' 'even' %}
|
|
||||||
{% firstof var1 var2 var3 %}
|
|
||||||
```
|
|
||||||
|
|
||||||
### Configuration
|
### Configuration
|
||||||
|
|
||||||
- **Built-in TagSpecs**: The parser includes TagSpecs for Django's built-in tags and popular third-party tags.
|
- **Built-in TagSpecs**: The parser includes TagSpecs for Django's built-in tags and popular third-party tags.
|
||||||
|
@ -322,10 +303,7 @@ required = true | false
|
||||||
type = "block"
|
type = "block"
|
||||||
closing = "endif"
|
closing = "endif"
|
||||||
branches = ["elif", "else"]
|
branches = ["elif", "else"]
|
||||||
|
args = [{ name = "condition", required = true }]
|
||||||
[[django.template.defaulttags.if.args]]
|
|
||||||
name = "condition"
|
|
||||||
required = true
|
|
||||||
```
|
```
|
||||||
|
|
||||||
#### Include Tag
|
#### Include Tag
|
||||||
|
@ -333,19 +311,25 @@ required = true
|
||||||
```toml
|
```toml
|
||||||
[django.template.defaulttags.includes]
|
[django.template.defaulttags.includes]
|
||||||
type = "inclusion"
|
type = "inclusion"
|
||||||
|
args = [{ name = "template_name", required = true }]
|
||||||
[[django.template.defaulttags.includes.args]]
|
|
||||||
name = "template_name"
|
|
||||||
required = true
|
|
||||||
```
|
```
|
||||||
|
|
||||||
#### Custom Tag
|
#### Autoescape Tag
|
||||||
|
|
||||||
|
```toml
|
||||||
|
[django.template.defaulttags.autoescape]
|
||||||
|
type = "block"
|
||||||
|
closing = "endautoescape"
|
||||||
|
args = [{ name = "setting", required = true, allowed_values = ["on", "off"] }]
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Custom Tag with Kwargs
|
||||||
|
|
||||||
```toml
|
```toml
|
||||||
[my_module.templatetags.my_tags.my_custom_tag]
|
[my_module.templatetags.my_tags.my_custom_tag]
|
||||||
type = "tag"
|
type = "tag"
|
||||||
|
args = [
|
||||||
{[my_module.templatetags.my_tags.my_custom_tag.args]]
|
{ name = "arg1", required = true },
|
||||||
name = "arg1"
|
{ name = "kwarg1", required = false, is_kwarg = true }
|
||||||
required = false
|
]
|
||||||
```
|
```
|
||||||
|
|
|
@ -162,9 +162,6 @@ pub enum Block {
|
||||||
tag: Tag,
|
tag: Tag,
|
||||||
template_name: String,
|
template_name: String,
|
||||||
},
|
},
|
||||||
Variable {
|
|
||||||
tag: Tag,
|
|
||||||
},
|
|
||||||
Closing {
|
Closing {
|
||||||
tag: Tag,
|
tag: Tag,
|
||||||
},
|
},
|
||||||
|
@ -177,7 +174,6 @@ impl Block {
|
||||||
| Self::Branch { tag, .. }
|
| Self::Branch { tag, .. }
|
||||||
| Self::Tag { tag }
|
| Self::Tag { tag }
|
||||||
| Self::Inclusion { tag, .. }
|
| Self::Inclusion { tag, .. }
|
||||||
| Self::Variable { tag }
|
|
||||||
| Self::Closing { tag } => tag,
|
| Self::Closing { tag } => tag,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -110,7 +110,6 @@ impl Parser {
|
||||||
Some(spec) => match spec.tag_type {
|
Some(spec) => match spec.tag_type {
|
||||||
TagType::Block => self.parse_block_tag(tag, spec),
|
TagType::Block => self.parse_block_tag(tag, spec),
|
||||||
TagType::Tag => Ok(Node::Block(Block::Tag { tag })),
|
TagType::Tag => Ok(Node::Block(Block::Tag { tag })),
|
||||||
TagType::Variable => Ok(Node::Block(Block::Variable { tag })),
|
|
||||||
TagType::Inclusion => {
|
TagType::Inclusion => {
|
||||||
let template_name = tag.bits.get(1).cloned().unwrap_or_default();
|
let template_name = tag.bits.get(1).cloned().unwrap_or_default();
|
||||||
Ok(Node::Block(Block::Inclusion { tag, template_name }))
|
Ok(Node::Block(Block::Inclusion { tag, template_name }))
|
||||||
|
|
|
@ -117,11 +117,6 @@ impl TagSpec {
|
||||||
let name = prefix.map_or_else(String::new, |p| {
|
let name = prefix.map_or_else(String::new, |p| {
|
||||||
p.split('.').last().unwrap_or(p).to_string()
|
p.split('.').last().unwrap_or(p).to_string()
|
||||||
});
|
});
|
||||||
eprintln!(
|
|
||||||
"Found tag spec at '{}', using name '{}'",
|
|
||||||
prefix.unwrap_or(""),
|
|
||||||
name
|
|
||||||
);
|
|
||||||
specs.insert(name, tag_spec);
|
specs.insert(name, tag_spec);
|
||||||
}
|
}
|
||||||
Err(_) => {
|
Err(_) => {
|
||||||
|
@ -131,7 +126,6 @@ impl TagSpec {
|
||||||
None => key.clone(),
|
None => key.clone(),
|
||||||
Some(p) => format!("{}.{}", p, key),
|
Some(p) => format!("{}.{}", p, key),
|
||||||
};
|
};
|
||||||
eprintln!("Recursing into prefix: {}", new_prefix);
|
|
||||||
Self::extract_specs(value, Some(&new_prefix), specs)?;
|
Self::extract_specs(value, Some(&new_prefix), specs)?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -146,13 +140,16 @@ pub enum TagType {
|
||||||
Block,
|
Block,
|
||||||
Tag,
|
Tag,
|
||||||
Inclusion,
|
Inclusion,
|
||||||
Variable,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, Deserialize)]
|
#[derive(Clone, Debug, Deserialize)]
|
||||||
pub struct ArgSpec {
|
pub struct ArgSpec {
|
||||||
pub name: String,
|
pub name: String,
|
||||||
pub required: bool,
|
pub required: bool,
|
||||||
|
#[serde(default)]
|
||||||
|
pub allowed_values: Option<Vec<String>>,
|
||||||
|
#[serde(default)]
|
||||||
|
pub is_kwarg: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ArgSpec {
|
impl ArgSpec {
|
||||||
|
@ -179,12 +176,8 @@ mod tests {
|
||||||
|
|
||||||
assert!(!specs.0.is_empty(), "Should have loaded at least one spec");
|
assert!(!specs.0.is_empty(), "Should have loaded at least one spec");
|
||||||
|
|
||||||
for (name, spec) in &specs.0 {
|
for name in specs.0.keys() {
|
||||||
assert!(!name.is_empty(), "Tag name should not be empty");
|
assert!(!name.is_empty(), "Tag name should not be empty");
|
||||||
assert!(
|
|
||||||
spec.tag_type == TagType::Block || spec.tag_type == TagType::Variable,
|
|
||||||
"Tag type should be block or variable"
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
@ -193,31 +186,35 @@ mod tests {
|
||||||
fn test_builtin_django_tags() -> Result<(), anyhow::Error> {
|
fn test_builtin_django_tags() -> Result<(), anyhow::Error> {
|
||||||
let specs = TagSpecs::load_builtin_specs()?;
|
let specs = TagSpecs::load_builtin_specs()?;
|
||||||
|
|
||||||
let expected_tags = ["block", "for", "if"];
|
let expected_tags = [
|
||||||
let missing_tags = [
|
|
||||||
"autoescape",
|
"autoescape",
|
||||||
|
"block",
|
||||||
"comment",
|
"comment",
|
||||||
"csrf_token",
|
|
||||||
"cycle",
|
"cycle",
|
||||||
"debug",
|
"debug",
|
||||||
"extends",
|
"extends",
|
||||||
"filter",
|
"filter",
|
||||||
|
"for",
|
||||||
"firstof",
|
"firstof",
|
||||||
"ifchanged",
|
"if",
|
||||||
"include",
|
"include",
|
||||||
"load",
|
"load",
|
||||||
"lorem",
|
|
||||||
"now",
|
"now",
|
||||||
"querystring", // 5.1
|
|
||||||
"regroup",
|
|
||||||
"resetcycle",
|
|
||||||
"spaceless",
|
"spaceless",
|
||||||
"templatetag",
|
"templatetag",
|
||||||
"url",
|
"url",
|
||||||
"verbatim",
|
"verbatim",
|
||||||
"widthratio",
|
|
||||||
"with",
|
"with",
|
||||||
];
|
];
|
||||||
|
let missing_tags = [
|
||||||
|
"csrf_token",
|
||||||
|
"ifchanged",
|
||||||
|
"lorem",
|
||||||
|
"querystring", // 5.1
|
||||||
|
"regroup",
|
||||||
|
"resetcycle",
|
||||||
|
"widthratio",
|
||||||
|
];
|
||||||
|
|
||||||
for tag in expected_tags {
|
for tag in expected_tags {
|
||||||
assert!(specs.get(tag).is_some(), "{} tag should be present", tag);
|
assert!(specs.get(tag).is_some(), "{} tag should be present", tag);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue