diff --git a/queries/gdscript.scm b/queries/gdscript.scm index b9aab5d..9d6d853 100644 --- a/queries/gdscript.scm +++ b/queries/gdscript.scm @@ -246,3 +246,10 @@ (get_node) @leaf (line_continuation) @prepend_space @append_antispace @append_hardline +; Indent nodes that immediately follows a line continuation ("\") by two levels, +; following the GDScript style guide. The line_continuation token only appears +; as a direct child of these three node types. We're leaving arrays, dicts, and +; enums out because they should have a single indent level inside their bodies +(attribute (line_continuation) @append_indent_start @append_indent_start . (_) @append_indent_end @append_indent_end) +(binary_operator (line_continuation) @append_indent_start @append_indent_start . (_) @append_indent_end @append_indent_end) +(variable_statement (line_continuation) @append_indent_start @append_indent_start . (_) @append_indent_end @append_indent_end) diff --git a/src/formatter.rs b/src/formatter.rs index 1c07baf..3e42380 100644 --- a/src/formatter.rs +++ b/src/formatter.rs @@ -53,6 +53,7 @@ struct Formatter { input_tree: GdTree, tree: Tree, original_source: Option, + indent_string: String, } impl Formatter { @@ -72,6 +73,11 @@ impl Formatter { } else { None }; + let indent_string = if config.use_spaces { + " ".repeat(config.indent_size) + } else { + "\t".to_string() + }; Self { original_source, @@ -80,22 +86,17 @@ impl Formatter { tree, input_tree, parser, + indent_string, } } #[inline(always)] fn format(&mut self) -> Result<&mut Self, Box> { - let indent_string = if self.config.use_spaces { - " ".repeat(self.config.indent_size) - } else { - "\t".to_string() - }; - let language = Language { name: "gdscript".to_owned(), query: TopiaryQuery::new(&tree_sitter_gdscript::LANGUAGE.into(), QUERY).unwrap(), grammar: tree_sitter_gdscript::LANGUAGE.into(), - indent: Some(indent_string), + indent: Some(self.indent_string.clone()), }; let mut output = Vec::new(); @@ -509,7 +510,9 @@ impl Formatter { .root_node() .descendant_for_byte_range(start_byte, start_byte) .unwrap(); - if node.kind() == "string" { + // String nodes may also contain escape_sequence nodes. These are + // found when a backslash is present within a string. + if node.kind() == "string" || node.kind() == "escape_sequence" { continue; } diff --git a/tests/expected/line_continuation.gd b/tests/expected/line_continuation.gd index 6b5890e..b36d879 100644 --- a/tests/expected/line_continuation.gd +++ b/tests/expected/line_continuation.gd @@ -1,4 +1,4 @@ func _handles(resource: Resource) -> bool: return resource is NoiseTexture2D \ - or resource is GradientTexture1D \ - or resource is GradientTexture2D + or resource is GradientTexture1D \ + or resource is GradientTexture2D diff --git a/tests/expected/line_continuation_indent.gd b/tests/expected/line_continuation_indent.gd new file mode 100644 index 0000000..17e51ac --- /dev/null +++ b/tests/expected/line_continuation_indent.gd @@ -0,0 +1,31 @@ +var is_valid: bool = some_condition \ + and another_condition + + +func _handles(resource: Resource) -> bool: + return resource is NoiseTexture2D \ + or resource is GradientTexture1D + + +func _process(delta: float) -> void: + if is_on_floor() \ + and not is_jumping: + apply_gravity(delta) + + +func _calculate() -> float: + var x: float = some_long_value \ + + another_value + return x + + +func _ready() -> void: + node.set_position(Vector2.ZERO) \ + .rotated(PI) + + +# string with \ must not change indentation +func _get_message() -> String: + var greeting: String = "\ + Hello world" + return greeting diff --git a/tests/input/line_continuation_indent.gd b/tests/input/line_continuation_indent.gd new file mode 100644 index 0000000..e786ec2 --- /dev/null +++ b/tests/input/line_continuation_indent.gd @@ -0,0 +1,31 @@ +var is_valid: bool = some_condition \ +and another_condition + + +func _handles(resource: Resource) -> bool: + return resource is NoiseTexture2D \ + or resource is GradientTexture1D + + +func _process(delta: float) -> void: + if is_on_floor() \ + and not is_jumping: + apply_gravity(delta) + + +func _calculate() -> float: + var x: float = some_long_value \ + + another_value + return x + + +func _ready() -> void: + node.set_position(Vector2.ZERO) \ + .rotated(PI) + + +# string with \ must not change indentation +func _get_message() -> String: + var greeting: String = "\ + Hello world" + return greeting