Skip to content

Commit

Permalink
Fix issue #586
Browse files Browse the repository at this point in the history
  • Loading branch information
danielzuncke authored and WebFreak001 committed Oct 26, 2023
1 parent 35e55bc commit 20b8bad
Show file tree
Hide file tree
Showing 9 changed files with 176 additions and 1 deletion.
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ found there.
* `--soft_max_line_length`: *see dfmt_soft_max_line_length [below](#dfmt-specific-properties)*
* `--space_after_cast`: *see dfmt_space_after_cast [below](#dfmt-specific-properties)*
* `--space_before_aa_colon`: *see dfmt_space_before_aa_colon [below](#dfmt-specific-properties)*
* `--space_before_named_arg_colon`: *see dfmt_space_before_named_arg_colon [below](#dfmt-specific-properties)*
* `--space_before_function_parameters`: *see dfmt_space_before_function_parameters [below](#dfmt-specific-properties)*
* `--split_operator_at_line_end`: *see dfmt_split_operator_at_line_end [below](#dfmt-specific-properties)*
* `--tab_width`: *see tab_width [below](#standard-editorconfig-properties)*
Expand Down Expand Up @@ -119,6 +120,7 @@ dfmt_compact_labeled_statements | **`true`**, `false` | Place labels on the same
dfmt_template_constraint_style | **`conditional_newline_indent`** `conditional_newline` `always_newline` `always_newline_indent` | Control the formatting of template constraints.
dfmt_single_template_constraint_indent | `true`, **`false`** | Set if the constraints are indented by a single tab instead of two. Has only an effect if the style set to `always_newline_indent` or `conditional_newline_indent`.
dfmt_space_before_aa_colon | `true`, **`false`** | Adds a space after an associative array key before the `:` like in older dfmt versions.
dfmt_space_before_named_arg_colon | `true`, **`false`** | Adds a space after a named function argument or named struct constructor argument before the `:`.
dfmt_keep_line_breaks | `true`, **`false`** | Keep existing line breaks if these don't violate other formatting rules.
dfmt_single_indent | `true`, **`false`** | Set if the code in parens is indented by a single tab instead of two.
dfmt_reflow_property_chains | **`true`**, `false` | Recalculate the splitting of property chains into multiple lines.
Expand Down
49 changes: 49 additions & 0 deletions src/dfmt/ast_info.d
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ struct ASTInformation
sort(ufcsHintLocations);
ufcsHintLocations = ufcsHintLocations.uniq().array();
sort(ternaryColonLocations);
sort(namedArgumentColonLocations);
}

/// Locations of end braces for struct bodies
Expand Down Expand Up @@ -139,6 +140,9 @@ struct ASTInformation

/// Locations ternary expression colons.
size_t[] ternaryColonLocations;

/// Locations of named arguments of function call or struct constructor.
size_t[] namedArgumentColonLocations;
}

/// Collects information from the AST that is useful for the formatter
Expand Down Expand Up @@ -448,6 +452,51 @@ final class FormatVisitor : ASTVisitor
ternaryExpression.accept(this);
}

override void visit(const FunctionCallExpression functionCall)
{
// Check if function has any arguments.
if (functionCall.arguments.namedArgumentList is null)
{
functionCall.accept(this);
return;
}

/+
Items are function arguments: f(<item>, <item>);
Iterate them and check if they are named arguments: tok!":" belongs to a
named argument if it is preceeded by one tok!"identifier" (+ any number
of comments):
+/
foreach (item; functionCall.arguments.namedArgumentList.items)
{
// Set to true after first tok!"identifier".
auto foundIdentifier = false;

foreach (t; item.tokens)
{
if (t.type == tok!"comment")
{
continue;
}

if (t.type == tok!"identifier" && !foundIdentifier)
{
foundIdentifier = true;
continue;
}

if (t.type == tok!":" && foundIdentifier)
{
astInformation.namedArgumentColonLocations ~= t.index;
}

break;
}
}

functionCall.accept(this);
}

private:
ASTInformation* astInformation;
}
3 changes: 3 additions & 0 deletions src/dfmt/config.d
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,8 @@ struct Config
OptionalBoolean dfmt_reflow_property_chains;
///
OptionalBoolean dfmt_space_after_statement_keyword;
///
OptionalBoolean dfmt_space_before_named_arg_colon;

mixin StandardEditorConfigFields;

Expand Down Expand Up @@ -98,6 +100,7 @@ struct Config
dfmt_keep_line_breaks = OptionalBoolean.f;
dfmt_single_indent = OptionalBoolean.f;
dfmt_reflow_property_chains = OptionalBoolean.t;
dfmt_space_before_named_arg_colon = OptionalBoolean.f;
}

/**
Expand Down
8 changes: 7 additions & 1 deletion src/dfmt/formatter.d
Original file line number Diff line number Diff line change
Expand Up @@ -835,13 +835,13 @@ private:
{
import dfmt.editorconfig : OptionalBoolean;
import std.algorithm : canFind, any;

immutable bool isCase = astInformation.caseEndLocations.canFindIndex(current.index);
immutable bool isAttribute = astInformation.attributeDeclarationLines.canFindIndex(
current.line);
immutable bool isStructInitializer = astInformation.structInfoSortedByEndLocation
.canFind!(st => st.startLocation < current.index && current.index < st.endLocation);
immutable bool isTernary = astInformation.ternaryColonLocations.canFindIndex(current.index);
immutable bool isNamedArg = astInformation.namedArgumentColonLocations.canFindIndex(current.index);

if (isCase || isAttribute)
{
Expand All @@ -862,6 +862,12 @@ private:
write(config.dfmt_space_before_aa_colon ? " : " : ": ");
++index;
}
// Named function or struct constructor arguments.
else if (isNamedArg)
{
write(config.dfmt_space_before_named_arg_colon ? " : " : ": ");
++index;
}
else if (peekBackIs(tok!"identifier")
&& [tok!"{", tok!"}", tok!";", tok!":", tok!","]
.any!((ptrdiff_t token) => peekBack2Is(cast(IdType)token, true))
Expand Down
5 changes: 5 additions & 0 deletions src/dfmt/main.d
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,9 @@ else
case "space_before_aa_colon":
optConfig.dfmt_space_before_aa_colon = optVal;
break;
case "space_before_named_arg_colon":
optConfig.dfmt_space_before_named_arg_colon = optVal;
break;
case "keep_line_breaks":
optConfig.dfmt_keep_line_breaks = optVal;
break;
Expand Down Expand Up @@ -133,6 +136,7 @@ else
"compact_labeled_statements", &handleBooleans,
"single_template_constraint_indent", &handleBooleans,
"space_before_aa_colon", &handleBooleans,
"space_before_named_arg_colon", &handleBooleans,
"tab_width", &optConfig.tab_width,
"template_constraint_style", &optConfig.dfmt_template_constraint_style,
"keep_line_breaks", &handleBooleans,
Expand Down Expand Up @@ -349,6 +353,7 @@ Formatting Options:
--compact_labeled_statements
--template_constraint_style
--space_before_aa_colon
--space_before_named_arg_colon
--single_indent
--reflow_property_chains
`,
Expand Down
28 changes: 28 additions & 0 deletions tests/allman/issue0586.d.ref
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
void temp(int v1, int v2)
{
}

int f(int i)
{
return i;
}

struct S
{
int i;
int j;
}

void main()
{
temp(v1: 1, v2: 2);
temp(v1: 1, v2: 2,);

auto s = S(5, j: 3);

temp(v1: 1, v2: f(i: 2));

temp(v1: true ? i : false ? 2 : f(i: 3), v2: 4);

temp(v1: () { S s = S(i: 5); return s.i; }, v2: 1);
}
31 changes: 31 additions & 0 deletions tests/issue0586.d
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
void temp(int v1, int v2)
{
}

int f(int i)
{
return i;
}

struct S
{
int i;
int j;
}

void main()
{
temp(v1: 1, v2: 2);
temp(
v1: 1,
v2: 2,
);

auto s = S(5, j: 3);

temp(v1: 1, v2: f(i: 2));

temp(v1: true ? i : false ? 2 : f(i: 3), v2: 4);

temp(v1: () { S s = S(i: 5); return s.i; }, v2: 1);
}
27 changes: 27 additions & 0 deletions tests/knr/issue0586.d.ref
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
void temp(int v1, int v2)
{
}

int f(int i)
{
return i;
}

struct S {
int i;
int j;
}

void main()
{
temp(v1: 1, v2: 2);
temp(v1: 1, v2: 2,);

auto s = S(5, j: 3);

temp(v1: 1, v2: f(i: 2));

temp(v1: true ? i : false ? 2 : f(i: 3), v2: 4);

temp(v1: () { S s = S(i: 5); return s.i; }, v2: 1);
}
24 changes: 24 additions & 0 deletions tests/otbs/issue0586.d.ref
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
void temp(int v1, int v2) {
}

int f(int i) {
return i;
}

struct S {
int i;
int j;
}

void main() {
temp(v1: 1, v2: 2);
temp(v1: 1, v2: 2,);

auto s = S(5, j: 3);

temp(v1: 1, v2: f(i: 2));

temp(v1: true ? i : false ? 2 : f(i: 3), v2: 4);

temp(v1: () { S s = S(i: 5); return s.i; }, v2: 1);
}

0 comments on commit 20b8bad

Please sign in to comment.