use crate::{ContainerBody, Import, Language, LanguageSymbols};
use tree_sitter::Node;
pub struct Hlsl;
impl Language for Hlsl {
fn name(&self) -> &'static str {
"HLSL"
}
fn extensions(&self) -> &'static [&'static str] {
&["hlsl", "hlsli", "fx", "fxh", "cginc"]
}
fn grammar_name(&self) -> &'static str {
"hlsl"
}
fn as_symbols(&self) -> Option<&dyn LanguageSymbols> {
Some(self)
}
fn extract_imports(&self, node: &Node, content: &str) -> Vec<Import> {
if node.kind() != "preproc_include" {
return Vec::new();
}
let text = &content[node.byte_range()];
let line = node.start_position().row + 1;
let module = text
.split('"')
.nth(1)
.or_else(|| text.split('<').nth(1).and_then(|s| s.split('>').next()))
.map(|s| s.to_string());
if let Some(module) = module {
return vec![Import {
module,
names: Vec::new(),
alias: None,
is_wildcard: false,
is_relative: text.contains('"'),
line,
}];
}
Vec::new()
}
fn format_import(&self, import: &Import, _names: Option<&[&str]>) -> String {
if import.is_relative {
format!("#include \"{}\"", import.module)
} else {
format!("#include <{}>", import.module)
}
}
fn container_body<'a>(&self, node: &'a Node<'a>) -> Option<Node<'a>> {
node.child_by_field_name("body")
}
fn analyze_container_body(
&self,
body_node: &Node,
content: &str,
inner_indent: &str,
) -> Option<ContainerBody> {
crate::body::analyze_brace_body(body_node, content, inner_indent)
}
fn node_name<'a>(&self, node: &Node, content: &'a str) -> Option<&'a str> {
node.child_by_field_name("declarator")
.and_then(|d| d.child_by_field_name("declarator"))
.map(|n| &content[n.byte_range()])
.or_else(|| {
node.child_by_field_name("name")
.map(|n| &content[n.byte_range()])
})
}
}
impl LanguageSymbols for Hlsl {}
#[cfg(test)]
mod tests {
use super::*;
use crate::validate_unused_kinds_audit;
#[test]
fn unused_node_kinds_audit() {
#[rustfmt::skip]
let documented_unused: &[&str] = &[
"abstract_function_declarator", "access_specifier", "alias_declaration",
"alignas_qualifier", "alignof_expression", "assignment_expression",
"attribute_declaration", "attribute_specifier", "attributed_statement",
"base_class_clause", "binary_expression", "bitfield_clause", "break_statement",
"call_expression", "cast_expression", "catch_clause",
"class_specifier", "co_await_expression", "co_return_statement", "co_yield_statement",
"comma_expression", "compound_literal_expression", "concept_definition",
"condition_clause", "consteval_block_declaration", "continue_statement",
"declaration", "declaration_list", "decltype", "default_method_clause",
"delete_expression", "delete_method_clause", "dependent_type", "destructor_name",
"discard_statement", "do_statement", "else_clause", "enum_specifier", "enumerator",
"enumerator_list", "expansion_statement", "explicit_function_specifier",
"explicit_object_parameter_declaration", "export_declaration", "expression_statement",
"extension_expression", "field_declaration", "field_declaration_list",
"field_expression", "field_identifier", "fold_expression", "for_range_loop",
"friend_declaration", "function_declarator", "generic_expression",
"global_module_fragment_declaration", "gnu_asm_expression", "gnu_asm_qualifier",
"goto_statement", "identifier", "import_declaration", "init_statement",
"labeled_statement", "lambda_capture_initializer", "lambda_capture_specifier",
"lambda_declarator", "lambda_default_capture", "lambda_expression", "lambda_specifier",
"linkage_specification", "module_declaration", "module_name", "module_partition",
"ms_based_modifier", "ms_call_modifier", "ms_declspec_modifier", "ms_pointer_modifier",
"ms_restrict_modifier", "ms_signed_ptr_modifier", "ms_unaligned_ptr_modifier",
"ms_unsigned_ptr_modifier", "namespace_alias_definition", "namespace_definition",
"namespace_identifier", "nested_namespace_specifier", "new_expression", "noexcept",
"offsetof_expression", "operator_cast", "operator_name", "optional_parameter_declaration",
"optional_type_parameter_declaration", "parameter_declaration", "parenthesized_expression",
"placeholder_type_specifier", "pointer_expression", "pointer_type_declarator",
"preproc_elif", "preproc_elifdef", "preproc_else", "preproc_function_def",
"preproc_if", "preproc_ifdef", "primitive_type", "private_module_fragment_declaration",
"pure_virtual_clause", "qualified_identifier", "qualifiers", "ref_qualifier",
"reflect_expression", "requires_clause", "requires_expression", "return_statement",
"seh_except_clause", "seh_finally_clause", "seh_leave_statement", "seh_try_statement",
"sized_type_specifier", "sizeof_expression", "splice_expression", "splice_specifier",
"splice_type_specifier", "statement_identifier", "static_assert_declaration",
"storage_class_specifier", "structured_binding_declarator", "subscript_expression",
"template_declaration", "template_function", "template_method",
"template_template_parameter_declaration", "template_type", "throw_specifier",
"throw_statement", "trailing_return_type", "try_statement", "type_definition",
"type_descriptor", "type_identifier", "type_parameter_declaration", "type_qualifier",
"type_requirement", "unary_expression", "union_specifier", "update_expression",
"using_declaration", "variadic_parameter_declaration",
"variadic_type_parameter_declaration", "virtual_specifier",
"conditional_expression",
"case_statement",
"for_statement",
"compound_statement",
"if_statement",
"switch_statement",
"while_statement",
];
validate_unused_kinds_audit(&Hlsl, documented_unused)
.expect("HLSL unused node kinds audit failed");
}
}