This commit is contained in:
Sebastian Wilzbach 2018-09-05 22:54:28 +00:00 committed by GitHub
commit 2c615cfd79
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
35 changed files with 530 additions and 69 deletions

View File

@ -4,9 +4,6 @@ set -e
if [[ $BUILD == dub ]]; then
dub build --build=release
mkdir bin
mv dfmt ./bin
elif [[ $DC == ldc2 ]]; then
git submodule update --init --recursive
make ldc -j2

View File

@ -43,3 +43,55 @@ jobs:
on:
tags: true # must be a git tag
repo: dlang-community/dfmt # must be a tag on dlang-community
- stage: GitHub Release
#if: tag IS present
d: ldc-1.8.0
os: linux
script: echo "Deploying to GitHub releases ..." && ./release.sh
deploy:
provider: releases
api_key: $GH_REPO_TOKEN
file_glob: true
file: bin/dfmt-*.tar.gz
skip_cleanup: true
on:
repo: dlang-community/dfmt
tags: true
- stage: GitHub Release
#if: tag IS present
d: ldc-1.8.0
os: osx
script: echo "Deploying to GitHub releases ..." && ./release.sh
deploy:
provider: releases
api_key: $GH_REPO_TOKEN
file_glob: true
file: bin/dfmt-*.tar.gz
skip_cleanup: true
on:
repo: dlang-community/dfmt
tags: true
- stage: GitHub Release
#if: tag IS present
d: dmd
os: linux
language: generic
sudo: yes
script: echo "Deploying to GitHub releases ..." && ./release-windows.sh
addons:
apt:
packages:
- p7zip-full
- wine
deploy:
provider: releases
api_key: $GH_REPO_TOKEN
file_glob: true
file: bin/dfmt-*.zip
skip_cleanup: true
on:
repo: dlang-community/dfmt
tags: true
stages:
- name: test
if: type = pull_request or (type = push and branch = master)

View File

@ -41,6 +41,7 @@ found in .editorconfig files.
* **--max_line_length**: See **max_line_length** below
* **--soft_max_line_length**: See **dfmt_soft_max_line_length** below
* **--outdent_attributes**: See **dfmt_outdent_attributes** below
* **--single_template_constraint_indent**: See **dfmt_template_constraint_style** below
* **--space_after_cast**: See **dfmt_space_after_cast** below
* **--space_before_function_parameters**: See **dfmt_space_before_function_parameters** below
* **--split_operator_at_line_end**: See **dfmt_split_operator_at_line_end** below
@ -68,7 +69,7 @@ void main(string[] args)
// argument list normally
getopt(args, "optionOne", &optionOne, "optionTwo", &optionTwo, "optionThree", &optionThree);
// dfmt off
// dfmt off
getopt(args,
"optionOne", &optionOne,
"optionTwo", &optionTwo,
@ -105,6 +106,7 @@ dfmt_space_before_function_parameters | `true`, `false` | `false` | Insert space
dfmt_selective_import_space | `true`, `false` | `true` | Insert space after the module name and before the `:` for selective imports.
dfmt_compact_labeled_statements | `true`, `false` | `true` | Place labels on the same line as the labeled `switch`, `for`, `foreach`, or `while` statement.
dfmt_template_constraint_style | `conditional_newline_indent` `conditional_newline` `always_newline` `always_newline_indent` | `conditional_newline_indent` | Control the formatting of template constraints.
dfmt_single_template_constraint_indent | `true`, `false` | `false` | Set if the constraints are indented by a single tab instead of two. Has only an effect for if indentation style if set to `always_newline_indent` or `conditional_newline_indent`.
## Terminology
* Braces - `{` and `}`

View File

@ -4,6 +4,8 @@
"targetType": "autodetect",
"license": "BSL-1.0",
"dependencies": {
"libdparse": "~>0.8.0-alpha.5"
}
"libdparse": "~>0.8.6"
},
"targetPath" : "bin/",
"targetName" : "dfmt",
}

@ -1 +1 @@
Subproject commit ee0fa01ab74b6bf27bed3c7bdb9d6fb789963342
Subproject commit 086cf06051bb1f33c94891ba6c39a57f164ee296

View File

@ -44,3 +44,6 @@ pkg: dmd
clean:
$(RM) bin/dfmt
release:
./release.sh

25
release-windows.sh Executable file
View File

@ -0,0 +1,25 @@
#!/usr/bin/env bash
# Build the Windows binaries under Linux (requires wine)
set -eux -o pipefail
VERSION=$(git describe --abbrev=0 --tags)
OS=windows
ARCH_SUFFIX="x86"
# Allow the script to be run from anywhere
DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
cd $DIR
# Step 1: download the DMD binaries
if [ ! -d dmd2 ] ; then
wget http://downloads.dlang.org/releases/2.x/2.079.0/dmd.2.079.0.windows.7z
7z x dmd.2.079.0.windows.7z > /dev/null
fi
# Step 2: Run DMD via wineconsole
archiveName="dfmt-$VERSION-$OS-$ARCH_SUFFIX.zip"
echo "Building $archiveName"
mkdir -p bin
DC="$DIR/dmd2/windows/bin/dmd.exe" wine cmd /C build.bat
cd bin
zip "$archiveName" dfmt.exe

23
release.sh Executable file
View File

@ -0,0 +1,23 @@
#!/usr/bin/env bash
set -eux -o pipefail
VERSION=$(git describe --abbrev=0 --tags)
ARCH="${ARCH:-64}"
LDC_FLAGS=()
unameOut="$(uname -s)"
case "$unameOut" in
Linux*) OS=linux; LDC_FLAGS=("-flto=full" "-linker=gold" "-static") ;;
Darwin*) OS=osx; LDC_FLAGS+=("-L-macosx_version_min" "-L10.7" "-L-lcrt1.o"); ;;
*) echo "Unknown OS: $unameOut"; exit 1
esac
case "$ARCH" in
64) ARCH_SUFFIX="x86_64";;
32) ARCH_SUFFIX="x86";;
*) echo "Unknown ARCH: $ARCH"; exit 1
esac
archiveName="dfmt-$VERSION-$OS-$ARCH_SUFFIX.tar.gz"
echo "Building $archiveName"
${MAKE:-make} ldc LDC_FLAGS="${LDC_FLAGS[*]}"
tar cvfz "bin/$archiveName" -C bin dfmt

View File

@ -1,5 +0,0 @@
### First dfmt release with neptune!
Well there we go, from now on with proper Changelog and all that.
Since previous releases were done without using neptune guidelines, we are missing proper release notes / a changelog for this release, but for new releases you can expect much more comprehensive release notes.

View File

@ -8,13 +8,29 @@ module dfmt.ast_info;
import dparse.lexer;
import dparse.ast;
enum BraceIndentInfoFlags
{
tempIndent = 1 << 0,
}
struct BraceIndentInfo
{
size_t startLocation;
size_t endLocation;
uint flags;
uint beginIndentLevel;
}
/// AST information that is needed by the formatter.
struct ASTInformation
{
/// Sorts the arrays so that binary search will work on them
void cleanup()
{
import std.algorithm : sort;
import std.algorithm : sort, uniq;
import std.array : array;
sort(doubleNewlineLocations);
sort(spaceAfterLocations);
@ -33,6 +49,10 @@ struct ASTInformation
sort(constructorDestructorLocations);
sort(staticConstructorDestructorLocations);
sort(sharedStaticConstructorDestructorLocations);
sort!((a,b) => a.endLocation < b.endLocation)
(indentInfoSortedByEndLocation);
sort(ufcsHintLocations);
ufcsHintLocations = ufcsHintLocations.uniq().array();
}
/// Locations of end braces for struct bodies
@ -85,6 +105,11 @@ struct ASTInformation
/// Locations of constructor/destructor "this" tokens ?
size_t[] constructorDestructorLocations;
/// Locations of '.' characters that might be UFCS chains.
size_t[] ufcsHintLocations;
BraceIndentInfo[] indentInfoSortedByEndLocation;
}
/// Collects information from the AST that is useful for the formatter
@ -187,8 +212,12 @@ final class FormatVisitor : ASTVisitor
{
if (funcLit.functionBody !is null)
{
astInformation.funLitStartLocations ~= funcLit.functionBody.blockStatement.startLocation;
astInformation.funLitEndLocations ~= funcLit.functionBody.blockStatement.endLocation;
const bs = funcLit.functionBody.blockStatement;
astInformation.funLitStartLocations ~= bs.startLocation;
astInformation.funLitEndLocations ~= bs.endLocation;
astInformation.indentInfoSortedByEndLocation ~=
BraceIndentInfo(bs.startLocation, bs.endLocation);
}
funcLit.accept(this);
}
@ -226,6 +255,9 @@ final class FormatVisitor : ASTVisitor
{
astInformation.structInitStartLocations ~= structInitializer.startLocation;
astInformation.structInitEndLocations ~= structInitializer.endLocation;
astInformation.indentInfoSortedByEndLocation ~=
BraceIndentInfo(structInitializer.startLocation, structInitializer.endLocation);
structInitializer.accept(this);
}
@ -268,6 +300,26 @@ final class FormatVisitor : ASTVisitor
override void visit(const UnaryExpression unary)
{
import std.typecons : rebindable;
int chainLength;
auto u = rebindable(unary);
while (u !is null)
{
if (u.identifierOrTemplateInstance !is null
&& u.identifierOrTemplateInstance.templateInstance !is null)
chainLength++;
u = u.unaryExpression;
}
if (chainLength > 1)
{
u = unary;
while (u.unaryExpression !is null)
{
astInformation.ufcsHintLocations ~= u.dotLocation;
u = u.unaryExpression;
}
}
if (unary.prefix.type == tok!"~" || unary.prefix.type == tok!"&"
|| unary.prefix.type == tok!"*"
|| unary.prefix.type == tok!"+" || unary.prefix.type == tok!"-")

View File

@ -53,6 +53,8 @@ struct Config
OptionalBoolean dfmt_compact_labeled_statements;
///
TemplateConstraintStyle dfmt_template_constraint_style;
///
OptionalBoolean dfmt_single_template_constraint_indent;
mixin StandardEditorConfigFields;
@ -79,6 +81,7 @@ struct Config
dfmt_selective_import_space = OptionalBoolean.t;
dfmt_compact_labeled_statements = OptionalBoolean.t;
dfmt_template_constraint_style = TemplateConstraintStyle.conditional_newline_indent;
dfmt_single_template_constraint_indent = OptionalBoolean.f;
}
/**

View File

@ -283,6 +283,10 @@ private:
{
formatKeyword();
}
else if (current.text == "body" && peekBackIsFunctionDeclarationEnding())
{
formatKeyword();
}
else if (isBasicType(current.type))
{
writeToken();
@ -324,6 +328,7 @@ private:
void formatConstraint()
{
import dfmt.editorconfig : OB = OptionalBoolean;
with (TemplateConstraintStyle) final switch (config.dfmt_template_constraint_style)
{
case unspecified:
@ -342,15 +347,19 @@ private:
immutable l = currentLineLength + betweenParenLength(tokens[index + 1 .. $]);
if (l > config.dfmt_soft_max_line_length)
{
pushWrapIndent(tok!"!");
config.dfmt_single_template_constraint_indent == OB.t ?
pushWrapIndent() : pushWrapIndent(tok!"!");
newline();
}
else if (peekBackIs(tok!")"))
write(" ");
break;
case always_newline_indent:
pushWrapIndent(tok!"!");
newline();
{
config.dfmt_single_template_constraint_indent == OB.t ?
pushWrapIndent() : pushWrapIndent(tok!"!");
newline();
}
break;
}
// if
@ -370,7 +379,12 @@ private:
if (commentText[0 .. 2] == "//")
commentText = commentText[2 .. $];
else
commentText = commentText[2 .. $ - 2];
{
if (commentText.length > 3)
commentText = commentText[2 .. $ - 2];
else
commentText = commentText[2 .. $];
}
return commentText.strip();
}
@ -586,8 +600,10 @@ private:
indents.pop();
if (parenDepth == 0 && (peekIs(tok!"is") || peekIs(tok!"in")
|| peekIs(tok!"out") || peekIs(tok!"body")))
|| peekIs(tok!"out") || peekIs(tok!"do") || peekIsBody))
{
writeToken();
}
else if (peekIsLiteralOrIdent() || peekIsBasicType())
{
writeToken();
@ -732,7 +748,9 @@ private:
{
import std.algorithm : map, sum, canFind;
if (astInformation.structInitStartLocations.canFindIndex(tokens[index].index))
auto tIndex = tokens[index].index;
if (astInformation.structInitStartLocations.canFindIndex(tIndex))
{
sBraceDepth++;
auto e = expressionEndIndex(index);
@ -741,13 +759,21 @@ private:
writeToken();
if (l > config.dfmt_soft_max_line_length)
{
import std.algorithm.searching : find;
auto indentInfo = astInformation.indentInfoSortedByEndLocation
.find!((a,b) => a.startLocation == b)(tIndex);
assert(indentInfo.length > 0);
cast()indentInfo[0].flags |= BraceIndentInfoFlags.tempIndent;
cast()indentInfo[0].beginIndentLevel = indents.indentLevel;
indents.push(tok!"{");
newline();
}
else
niBraceDepth++;
}
else if (astInformation.funLitStartLocations.canFindIndex(tokens[index].index))
else if (astInformation.funLitStartLocations.canFindIndex(tIndex))
{
sBraceDepth++;
if (peekBackIs(tok!")"))
@ -803,15 +829,34 @@ private:
void formatRightBrace()
{
if (astInformation.structInitEndLocations.canFindIndex(tokens[index].index))
void popToBeginIndent(BraceIndentInfo indentInfo)
{
foreach(i; indentInfo.beginIndentLevel .. indents.indentLevel)
{
indents.pop();
}
indentLevel = indentInfo.beginIndentLevel;
}
size_t pos;
if (astInformation.structInitEndLocations.canFindIndex(tokens[index].index, &pos))
{
if (sBraceDepth > 0)
sBraceDepth--;
if (niBraceDepth > 0)
niBraceDepth--;
auto indentInfo = astInformation.indentInfoSortedByEndLocation[pos];
if (indentInfo.flags & BraceIndentInfoFlags.tempIndent)
{
popToBeginIndent(indentInfo);
simpleNewline();
indent();
}
writeToken();
}
else if (astInformation.funLitEndLocations.canFindIndex(tokens[index].index))
else if (astInformation.funLitEndLocations.canFindIndex(tokens[index].index, &pos))
{
if (niBraceDepth > 0)
{
@ -913,9 +958,11 @@ private:
if (!currentIs(tok!"{") && !currentIs(tok!";"))
write(" ");
}
else if (!currentIs(tok!"{") && !currentIs(tok!";")
&& !currentIs(tok!"in") && !currentIs(tok!"out") && !currentIs(tok!"body"))
else if (!currentIs(tok!"{") && !currentIs(tok!";") && !currentIs(tok!"in") &&
!currentIs(tok!"out") && !currentIs(tok!"do") && current.text != "body")
{
newline();
}
else if (currentIs(tok!"{") && indents.topAre(tok!"static", tok!"if"))
{
// Hacks to format braced vs non-braced static if declarations.
@ -1004,7 +1051,12 @@ private:
if (!currentIs(tok!"{"))
newline();
break;
case tok!"body":
case tok!"identifier":
if (current.text == "body")
goto case tok!"do";
else
goto default;
case tok!"do":
if (!peekBackIs(tok!"}"))
newline();
writeToken();
@ -1190,11 +1242,14 @@ private:
break;
case tok!".":
regenLineBreakHintsIfNecessary(index);
if (linebreakHints.canFind(index) || (linebreakHints.length == 0
immutable bool ufcsWrap = astInformation.ufcsHintLocations.canFindIndex(current.index);
if (ufcsWrap || linebreakHints.canFind(index) || (linebreakHints.length == 0
&& currentLineLength + nextTokenLength() > config.max_line_length))
{
pushWrapIndent();
newline();
if (ufcsWrap)
regenLineBreakHints(index);
}
writeToken();
break;
@ -1317,7 +1372,18 @@ private:
void regenLineBreakHints(immutable size_t i)
{
immutable size_t j = expressionEndIndex(i);
import std.range : assumeSorted;
import std.algorithm.comparison : min;
import std.algorithm.searching : countUntil;
// The end of the tokens considered by the line break algorithm is
// either the expression end index or the next mandatory line break,
// whichever is first.
auto r = assumeSorted(astInformation.ufcsHintLocations).upperBound(tokens[i].index);
immutable ufcsBreakLocation = r.empty
? size_t.max
: tokens[i .. $].countUntil!(t => t.index == r.front) + i;
immutable size_t j = min(expressionEndIndex(i), ufcsBreakLocation);
// Use magical negative value for array literals and wrap indents
immutable inLvl = (indents.topIsWrap() || indents.topIs(tok!"]")) ? -indentLevel
: indentLevel;
@ -1659,10 +1725,7 @@ const pure @safe @nogc:
const(Token) peekBack(uint distance = 1) nothrow
{
if (index < distance)
{
assert(0, "Trying to peek before the first token");
}
assert(index >= distance, "Trying to peek before the first token");
return tokens[index - distance];
}
@ -1793,6 +1856,18 @@ const pure @safe @nogc:
return peekImplementation(tokenType, 1, ignoreComments);
}
bool peekIsBody() nothrow
{
return index + 1 < tokens.length && tokens[index + 1].text == "body";
}
bool peekBackIsFunctionDeclarationEnding() nothrow
{
return peekBackIsOneOf(false, tok!")", tok!"const", tok!"immutable",
tok!"inout", tok!"shared", tok!"@", tok!"pure", tok!"nothrow",
tok!"return", tok!"scope");
}
bool peekBackIsSlashSlash() nothrow
{
return index > 0 && tokens[index - 1].type == tok!"comment"
@ -1844,9 +1919,28 @@ const pure @safe @nogc:
}
}
bool canFindIndex(const size_t[] items, size_t index) pure @safe @nogc
bool canFindIndex(const size_t[] items, size_t index, size_t* pos = null) pure @safe @nogc
{
import std.range : assumeSorted;
return !assumeSorted(items).equalRange(index).empty;
if (!pos)
{
return !assumeSorted(items).equalRange(index).empty;
}
else
{
auto trisection_result = assumeSorted(items).trisect(index);
if (trisection_result[1].length == 1)
{
*pos = trisection_result[0].length;
return true;
}
else if (trisection_result[1].length == 0)
{
return false;
}
else
{
assert(0, "the constraint of having unique locations has been violated");
}
}
}

View File

@ -68,7 +68,13 @@ struct IndentStack
void push(IdType item) pure nothrow
{
arr[index] = item;
index = index + 1 == arr.length ? index : index + 1;
//FIXME this is actually a bad thing to do,
//we should not just override when the stack is
//at it's limit
if (index < arr.length)
{
index++;
}
}
/**
@ -76,7 +82,8 @@ struct IndentStack
*/
void pop() pure nothrow
{
index = index == 0 ? index : index - 1;
if (index)
index--;
}
/**

View File

@ -18,18 +18,18 @@ static immutable VERSION = () {
{
// takes the `git describe --tags` output and removes the leading
// 'v' as well as any kind of newline
// if the tag is considered malformed it gets used verbatim
// if the tag is considered malformed it gets used verbatim
enum gitDescribeOutput = import("VERSION");
string result;
string result;
if (gitDescribeOutput[0] == 'v')
result = gitDescribeOutput[1 .. $];
else
result = null;
uint minusCount;
uint minusCount;
foreach (i, c; result)
{
@ -39,17 +39,17 @@ static immutable VERSION = () {
break;
}
if (c == '-')
{
if (c == '-')
{
++minusCount;
}
}
if (minusCount > 1)
result = null;
result = null;
return result ? result ~ DEBUG_SUFFIX
: gitDescribeOutput ~ DEBUG_SUFFIX;
: gitDescribeOutput ~ DEBUG_SUFFIX;
}
else
@ -85,9 +85,9 @@ else
void handleBooleans(string option, string value)
{
import dfmt.editorconfig : OptionalBoolean;
import std.exception : enforceEx;
import std.exception : enforce;
enforceEx!GetOptException(value == "true" || value == "false", "Invalid argument");
enforce!GetOptException(value == "true" || value == "false", "Invalid argument");
immutable OptionalBoolean optVal = value == "true" ? OptionalBoolean.t
: OptionalBoolean.f;
switch (option)
@ -103,7 +103,7 @@ else
break;
case "space_before_function_parameters":
optConfig.dfmt_space_before_function_parameters = optVal;
break;
break;
case "split_operator_at_line_end":
optConfig.dfmt_split_operator_at_line_end = optVal;
break;
@ -113,6 +113,9 @@ else
case "compact_labeled_statements":
optConfig.dfmt_compact_labeled_statements = optVal;
break;
case "single_template_constraint_indent":
optConfig.dfmt_single_template_constraint_indent = optVal;
break;
default:
assert(false, "Invalid command-line switch");
}
@ -139,6 +142,7 @@ else
"space_before_function_parameters", &handleBooleans,
"split_operator_at_line_end", &handleBooleans,
"compact_labeled_statements", &handleBooleans,
"single_template_constraint_indent", &handleBooleans,
"tab_width", &optConfig.tab_width,
"template_constraint_style", &optConfig.dfmt_template_constraint_style);
// dfmt on
@ -293,26 +297,25 @@ private version (Windows)
}
}
private string optionsToString(E)() if (is(E == enum))
template optionsToString(E) if (is(E == enum))
{
import std.traits : EnumMembers;
import std.conv : to;
enum optionsToString = () {
string result = "(";
foreach (i, option; EnumMembers!E)
{
immutable s = to!string(option);
if (s != "unspecified")
result ~= s ~ "|";
}
result = result[0 .. $ - 1] ~ ")";
return result;
string result = "(";
foreach (s; [__traits(allMembers, E)])
{
if (s != "unspecified")
result ~= s ~ "|";
}
result = result[0 .. $ - 1] ~ ")";
return result;
} ();
}
private void printHelp()
{
writeln(`dfmt `, VERSION, `
https://github.com/Hackerpilot/dfmt
https://github.com/dlang-community/dfmt
Options:
--help, -h Print this help message
@ -322,23 +325,24 @@ Options:
Formatting Options:
--align_switch_statements
--brace_style `, optionsToString!(typeof(Config.dfmt_brace_style))(),
--brace_style `, optionsToString!(typeof(Config.dfmt_brace_style)),
`
--end_of_line `, optionsToString!(typeof(Config.end_of_line))(), `
--end_of_line `, optionsToString!(typeof(Config.end_of_line)), `
--indent_size
--indent_style, -t `,
optionsToString!(typeof(Config.indent_style))(), `
optionsToString!(typeof(Config.indent_style)), `
--soft_max_line_length
--max_line_length
--outdent_attributes
--space_after_cast
--space_before_function_parameters
--selective_import_space
--single_template_constraint_indent
--split_operator_at_line_end
--compact_labeled_statements
--template_constraint_style
`,
optionsToString!(typeof(Config.dfmt_template_constraint_style))());
optionsToString!(typeof(Config.dfmt_template_constraint_style)));
}
private string createFilePath(bool readFromStdin, string fileName)

View File

@ -217,7 +217,7 @@ private string generateFixedLengthCases()
a => format(`case tok!"%s": return %d + 1;`, a, a.length)).join("\n\t");
string[] identifierTokens = [
"abstract", "alias", "align", "asm", "assert", "auto", "body", "bool",
"abstract", "alias", "align", "asm", "assert", "auto", "bool",
"break", "byte", "case", "cast", "catch", "cdouble", "cent", "cfloat", "char", "class",
"const", "continue", "creal", "dchar", "debug", "default", "delegate", "delete", "deprecated",
"do", "double", "else", "enum", "export", "extern", "false", "final", "finally", "float",

@ -1 +1 @@
Subproject commit 7487970b58f4a2c0d495679329a8a2857111f3fd
Subproject commit b7778fd6bf5f9aaaa87dd27f989cefbf9b3b365f

View File

@ -3,7 +3,8 @@ unittest
{
{
foreach (abcde, def; abcdef.map!(battlecruiser => battlecruiser[123 .. 1231231])
.filter!(bravo => charlie[10] > 90000).sum())
.filter!(bravo => charlie[10] > 90000)
.sum())
{
}

View File

@ -0,0 +1,9 @@
void foo()()
if (dogs && pigs && birds && ants && foxes && flies && cats && bugs && bees
&& cows && sheeps && monkeys && whales)
{
}
void foo()() if (dogs && pigs && birds)
{
}

View File

@ -0,0 +1,10 @@
void foo()()
if (dogs && pigs && birds && ants && foxes && flies && cats && bugs && bees
&& cows && sheeps && monkeys && whales)
{
}
void foo()()
if (dogs && pigs && birds)
{
}

View File

@ -0,0 +1,19 @@
import character.body;
void body() @nogc
in
{
}
body
{
body = null;
}
void body()
in
{
}
do
{
body = null;
}

View File

@ -0,0 +1,40 @@
void fn()
{
{
{
{
auto file = {
"integrationtest/feed/etc/config.iniaasdfaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
"etc/config.ini"
};
{
int x;
}
}
}
}
}
struct A
{
int x, y, z;
}
int main()
{
int fun()
{
import std.stdio : writeln;
import std.typecons : tuple;
A a = {
tuple(Variant(1))[0].get!int, tuple(Variant(2))[0].get!int,
tuple(Variant(3))[0].get!int
};
A b = {
tuple(Variant(1))[0].get!int, tuple(Variant(2))[0].get!int,
tuple(Variant(3))[0].get!int
};
writeln(a);
}
}

View File

@ -0,0 +1,6 @@
void main()
{
stuff[].map!(things => stuff.doThings)
.filter!(stuff)
.array();
}

View File

@ -0,0 +1,2 @@
--template_constraint_style=conditional_newline_indent
--single_template_constraint_indent=true

View File

@ -0,0 +1,4 @@
void foo()() if (dogs && pigs && birds && ants && foxes && flies && cats && bugs && bees && cows && sheeps && monkeys && whales)
{}
void foo()() if (dogs && pigs && birds) {}

View File

@ -0,0 +1,2 @@
--template_constraint_style=always_newline_indent
--single_template_constraint_indent=true

View File

@ -0,0 +1,4 @@
void foo()() if (dogs && pigs && birds && ants && foxes && flies && cats && bugs && bees && cows && sheeps && monkeys && whales)
{}
void foo()() if (dogs && pigs && birds) {}

7
tests/do_body.d Normal file
View File

@ -0,0 +1,7 @@
import character.body;
void body() @nogc
in{} body{body = null;}
void body()
in{} do{ body = null;}

22
tests/issue0237.d Normal file
View File

@ -0,0 +1,22 @@
void fn () {{{{
auto file =
{ "integrationtest/feed/etc/config.iniaasdfaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
"etc/config.ini" };
{ int x; }
}}}}
struct A
{
int x, y, z;
}
int main()
{
int fun()
{
import std.stdio : writeln;
import std.typecons : tuple;
A a = { tuple(Variant(1))[0].get!int, tuple(Variant(2))[0].get!int, tuple(Variant(3))[0].get!int };
A b = { tuple(Variant(1))[0].get!int, tuple(Variant(2))[0].get!int, tuple(Variant(3))[0].get!int };
writeln(a);
}
}

View File

@ -2,7 +2,8 @@ unittest {
{
{
foreach (abcde, def; abcdef.map!(battlecruiser => battlecruiser[123 .. 1231231])
.filter!(bravo => charlie[10] > 90000).sum()) {
.filter!(bravo => charlie[10] > 90000)
.sum()) {
}
abcdeabcdeabcde(12341234).abcdeabcdeabcde(12341234).abcdeabcdeabcde(12341234)

View File

@ -0,0 +1,7 @@
void foo()()
if (dogs && pigs && birds && ants && foxes && flies && cats && bugs && bees
&& cows && sheeps && monkeys && whales) {
}
void foo()() if (dogs && pigs && birds) {
}

View File

@ -0,0 +1,8 @@
void foo()()
if (dogs && pigs && birds && ants && foxes && flies && cats && bugs && bees
&& cows && sheeps && monkeys && whales) {
}
void foo()()
if (dogs && pigs && birds) {
}

15
tests/otbs/do_body.d.ref Normal file
View File

@ -0,0 +1,15 @@
import character.body;
void body() @nogc
in {
}
body {
body = null;
}
void body()
in {
}
do {
body = null;
}

View File

@ -0,0 +1,36 @@
void fn() {
{
{
{
auto file = {
"integrationtest/feed/etc/config.iniaasdfaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
"etc/config.ini"
};
{
int x;
}
}
}
}
}
struct A {
int x, y, z;
}
int main() {
int fun() {
import std.stdio : writeln;
import std.typecons : tuple;
A a = {
tuple(Variant(1))[0].get!int, tuple(Variant(2))[0].get!int,
tuple(Variant(3))[0].get!int
};
A b = {
tuple(Variant(1))[0].get!int, tuple(Variant(2))[0].get!int,
tuple(Variant(3))[0].get!int
};
writeln(a);
}
}

View File

@ -0,0 +1,5 @@
void main() {
stuff[].map!(things => stuff.doThings)
.filter!(stuff)
.array();
}

4
tests/ufcschain.d Normal file
View File

@ -0,0 +1,4 @@
void main()
{
stuff[].map!(things => stuff.doThings).filter!(stuff).array();
}