This commit is contained in:
Daniel Zuncke 2023-10-26 10:23:57 +02:00
parent 35e55bc9b2
commit 1f412fe794
No known key found for this signature in database
GPG Key ID: A2A8C43610B6B485
9 changed files with 176 additions and 1 deletions

View File

@ -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)*
@ -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.

View File

@ -64,6 +64,7 @@ struct ASTInformation
sort(ufcsHintLocations);
ufcsHintLocations = ufcsHintLocations.uniq().array();
sort(ternaryColonLocations);
sort(namedArgumentColonLocations);
}
/// Locations of end braces for struct bodies
@ -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
@ -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;
}

View File

@ -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;
@ -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;
}
/**

View File

@ -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)
{
@ -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))

View File

@ -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;
@ -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,
@ -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
`,

View File

@ -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
tests/issue0586.d Normal file
View File

@ -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
tests/knr/issue0586.d.ref Normal file
View File

@ -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);
}

View File

@ -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);
}