Merge 21411a1059
into 8333180e27
This commit is contained in:
commit
2c615cfd79
|
@ -4,9 +4,6 @@ set -e
|
||||||
|
|
||||||
if [[ $BUILD == dub ]]; then
|
if [[ $BUILD == dub ]]; then
|
||||||
dub build --build=release
|
dub build --build=release
|
||||||
|
|
||||||
mkdir bin
|
|
||||||
mv dfmt ./bin
|
|
||||||
elif [[ $DC == ldc2 ]]; then
|
elif [[ $DC == ldc2 ]]; then
|
||||||
git submodule update --init --recursive
|
git submodule update --init --recursive
|
||||||
make ldc -j2
|
make ldc -j2
|
||||||
|
|
52
.travis.yml
52
.travis.yml
|
@ -43,3 +43,55 @@ jobs:
|
||||||
on:
|
on:
|
||||||
tags: true # must be a git tag
|
tags: true # must be a git tag
|
||||||
repo: dlang-community/dfmt # must be a tag on dlang-community
|
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)
|
||||||
|
|
|
@ -41,6 +41,7 @@ found in .editorconfig files.
|
||||||
* **--max_line_length**: See **max_line_length** below
|
* **--max_line_length**: See **max_line_length** below
|
||||||
* **--soft_max_line_length**: See **dfmt_soft_max_line_length** below
|
* **--soft_max_line_length**: See **dfmt_soft_max_line_length** below
|
||||||
* **--outdent_attributes**: See **dfmt_outdent_attributes** 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_after_cast**: See **dfmt_space_after_cast** below
|
||||||
* **--space_before_function_parameters**: See **dfmt_space_before_function_parameters** 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
|
* **--split_operator_at_line_end**: See **dfmt_split_operator_at_line_end** below
|
||||||
|
@ -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_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_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_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
|
## Terminology
|
||||||
* Braces - `{` and `}`
|
* Braces - `{` and `}`
|
||||||
|
|
6
dub.json
6
dub.json
|
@ -4,6 +4,8 @@
|
||||||
"targetType": "autodetect",
|
"targetType": "autodetect",
|
||||||
"license": "BSL-1.0",
|
"license": "BSL-1.0",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"libdparse": "~>0.8.0-alpha.5"
|
"libdparse": "~>0.8.6"
|
||||||
}
|
},
|
||||||
|
"targetPath" : "bin/",
|
||||||
|
"targetName" : "dfmt",
|
||||||
}
|
}
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
Subproject commit ee0fa01ab74b6bf27bed3c7bdb9d6fb789963342
|
Subproject commit 086cf06051bb1f33c94891ba6c39a57f164ee296
|
3
makefile
3
makefile
|
@ -44,3 +44,6 @@ pkg: dmd
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
$(RM) bin/dfmt
|
$(RM) bin/dfmt
|
||||||
|
|
||||||
|
release:
|
||||||
|
./release.sh
|
||||||
|
|
|
@ -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
|
|
@ -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
|
|
@ -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.
|
|
|
@ -8,13 +8,29 @@ module dfmt.ast_info;
|
||||||
import dparse.lexer;
|
import dparse.lexer;
|
||||||
import dparse.ast;
|
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.
|
/// AST information that is needed by the formatter.
|
||||||
struct ASTInformation
|
struct ASTInformation
|
||||||
{
|
{
|
||||||
/// Sorts the arrays so that binary search will work on them
|
/// Sorts the arrays so that binary search will work on them
|
||||||
void cleanup()
|
void cleanup()
|
||||||
{
|
{
|
||||||
import std.algorithm : sort;
|
import std.algorithm : sort, uniq;
|
||||||
|
import std.array : array;
|
||||||
|
|
||||||
sort(doubleNewlineLocations);
|
sort(doubleNewlineLocations);
|
||||||
sort(spaceAfterLocations);
|
sort(spaceAfterLocations);
|
||||||
|
@ -33,6 +49,10 @@ struct ASTInformation
|
||||||
sort(constructorDestructorLocations);
|
sort(constructorDestructorLocations);
|
||||||
sort(staticConstructorDestructorLocations);
|
sort(staticConstructorDestructorLocations);
|
||||||
sort(sharedStaticConstructorDestructorLocations);
|
sort(sharedStaticConstructorDestructorLocations);
|
||||||
|
sort!((a,b) => a.endLocation < b.endLocation)
|
||||||
|
(indentInfoSortedByEndLocation);
|
||||||
|
sort(ufcsHintLocations);
|
||||||
|
ufcsHintLocations = ufcsHintLocations.uniq().array();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Locations of end braces for struct bodies
|
/// Locations of end braces for struct bodies
|
||||||
|
@ -85,6 +105,11 @@ struct ASTInformation
|
||||||
|
|
||||||
/// Locations of constructor/destructor "this" tokens ?
|
/// Locations of constructor/destructor "this" tokens ?
|
||||||
size_t[] constructorDestructorLocations;
|
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
|
/// Collects information from the AST that is useful for the formatter
|
||||||
|
@ -187,8 +212,12 @@ final class FormatVisitor : ASTVisitor
|
||||||
{
|
{
|
||||||
if (funcLit.functionBody !is null)
|
if (funcLit.functionBody !is null)
|
||||||
{
|
{
|
||||||
astInformation.funLitStartLocations ~= funcLit.functionBody.blockStatement.startLocation;
|
const bs = funcLit.functionBody.blockStatement;
|
||||||
astInformation.funLitEndLocations ~= funcLit.functionBody.blockStatement.endLocation;
|
|
||||||
|
astInformation.funLitStartLocations ~= bs.startLocation;
|
||||||
|
astInformation.funLitEndLocations ~= bs.endLocation;
|
||||||
|
astInformation.indentInfoSortedByEndLocation ~=
|
||||||
|
BraceIndentInfo(bs.startLocation, bs.endLocation);
|
||||||
}
|
}
|
||||||
funcLit.accept(this);
|
funcLit.accept(this);
|
||||||
}
|
}
|
||||||
|
@ -226,6 +255,9 @@ final class FormatVisitor : ASTVisitor
|
||||||
{
|
{
|
||||||
astInformation.structInitStartLocations ~= structInitializer.startLocation;
|
astInformation.structInitStartLocations ~= structInitializer.startLocation;
|
||||||
astInformation.structInitEndLocations ~= structInitializer.endLocation;
|
astInformation.structInitEndLocations ~= structInitializer.endLocation;
|
||||||
|
astInformation.indentInfoSortedByEndLocation ~=
|
||||||
|
BraceIndentInfo(structInitializer.startLocation, structInitializer.endLocation);
|
||||||
|
|
||||||
structInitializer.accept(this);
|
structInitializer.accept(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -268,6 +300,26 @@ final class FormatVisitor : ASTVisitor
|
||||||
|
|
||||||
override void visit(const UnaryExpression unary)
|
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!"&"
|
if (unary.prefix.type == tok!"~" || unary.prefix.type == tok!"&"
|
||||||
|| unary.prefix.type == tok!"*"
|
|| unary.prefix.type == tok!"*"
|
||||||
|| unary.prefix.type == tok!"+" || unary.prefix.type == tok!"-")
|
|| unary.prefix.type == tok!"+" || unary.prefix.type == tok!"-")
|
||||||
|
|
|
@ -53,6 +53,8 @@ struct Config
|
||||||
OptionalBoolean dfmt_compact_labeled_statements;
|
OptionalBoolean dfmt_compact_labeled_statements;
|
||||||
///
|
///
|
||||||
TemplateConstraintStyle dfmt_template_constraint_style;
|
TemplateConstraintStyle dfmt_template_constraint_style;
|
||||||
|
///
|
||||||
|
OptionalBoolean dfmt_single_template_constraint_indent;
|
||||||
|
|
||||||
mixin StandardEditorConfigFields;
|
mixin StandardEditorConfigFields;
|
||||||
|
|
||||||
|
@ -79,6 +81,7 @@ struct Config
|
||||||
dfmt_selective_import_space = OptionalBoolean.t;
|
dfmt_selective_import_space = OptionalBoolean.t;
|
||||||
dfmt_compact_labeled_statements = OptionalBoolean.t;
|
dfmt_compact_labeled_statements = OptionalBoolean.t;
|
||||||
dfmt_template_constraint_style = TemplateConstraintStyle.conditional_newline_indent;
|
dfmt_template_constraint_style = TemplateConstraintStyle.conditional_newline_indent;
|
||||||
|
dfmt_single_template_constraint_indent = OptionalBoolean.f;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -283,6 +283,10 @@ private:
|
||||||
{
|
{
|
||||||
formatKeyword();
|
formatKeyword();
|
||||||
}
|
}
|
||||||
|
else if (current.text == "body" && peekBackIsFunctionDeclarationEnding())
|
||||||
|
{
|
||||||
|
formatKeyword();
|
||||||
|
}
|
||||||
else if (isBasicType(current.type))
|
else if (isBasicType(current.type))
|
||||||
{
|
{
|
||||||
writeToken();
|
writeToken();
|
||||||
|
@ -324,6 +328,7 @@ private:
|
||||||
|
|
||||||
void formatConstraint()
|
void formatConstraint()
|
||||||
{
|
{
|
||||||
|
import dfmt.editorconfig : OB = OptionalBoolean;
|
||||||
with (TemplateConstraintStyle) final switch (config.dfmt_template_constraint_style)
|
with (TemplateConstraintStyle) final switch (config.dfmt_template_constraint_style)
|
||||||
{
|
{
|
||||||
case unspecified:
|
case unspecified:
|
||||||
|
@ -342,15 +347,19 @@ private:
|
||||||
immutable l = currentLineLength + betweenParenLength(tokens[index + 1 .. $]);
|
immutable l = currentLineLength + betweenParenLength(tokens[index + 1 .. $]);
|
||||||
if (l > config.dfmt_soft_max_line_length)
|
if (l > config.dfmt_soft_max_line_length)
|
||||||
{
|
{
|
||||||
pushWrapIndent(tok!"!");
|
config.dfmt_single_template_constraint_indent == OB.t ?
|
||||||
|
pushWrapIndent() : pushWrapIndent(tok!"!");
|
||||||
newline();
|
newline();
|
||||||
}
|
}
|
||||||
else if (peekBackIs(tok!")"))
|
else if (peekBackIs(tok!")"))
|
||||||
write(" ");
|
write(" ");
|
||||||
break;
|
break;
|
||||||
case always_newline_indent:
|
case always_newline_indent:
|
||||||
pushWrapIndent(tok!"!");
|
{
|
||||||
|
config.dfmt_single_template_constraint_indent == OB.t ?
|
||||||
|
pushWrapIndent() : pushWrapIndent(tok!"!");
|
||||||
newline();
|
newline();
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
// if
|
// if
|
||||||
|
@ -370,7 +379,12 @@ private:
|
||||||
if (commentText[0 .. 2] == "//")
|
if (commentText[0 .. 2] == "//")
|
||||||
commentText = commentText[2 .. $];
|
commentText = commentText[2 .. $];
|
||||||
else
|
else
|
||||||
|
{
|
||||||
|
if (commentText.length > 3)
|
||||||
commentText = commentText[2 .. $ - 2];
|
commentText = commentText[2 .. $ - 2];
|
||||||
|
else
|
||||||
|
commentText = commentText[2 .. $];
|
||||||
|
}
|
||||||
return commentText.strip();
|
return commentText.strip();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -586,8 +600,10 @@ private:
|
||||||
indents.pop();
|
indents.pop();
|
||||||
|
|
||||||
if (parenDepth == 0 && (peekIs(tok!"is") || peekIs(tok!"in")
|
if (parenDepth == 0 && (peekIs(tok!"is") || peekIs(tok!"in")
|
||||||
|| peekIs(tok!"out") || peekIs(tok!"body")))
|
|| peekIs(tok!"out") || peekIs(tok!"do") || peekIsBody))
|
||||||
|
{
|
||||||
writeToken();
|
writeToken();
|
||||||
|
}
|
||||||
else if (peekIsLiteralOrIdent() || peekIsBasicType())
|
else if (peekIsLiteralOrIdent() || peekIsBasicType())
|
||||||
{
|
{
|
||||||
writeToken();
|
writeToken();
|
||||||
|
@ -732,7 +748,9 @@ private:
|
||||||
{
|
{
|
||||||
import std.algorithm : map, sum, canFind;
|
import std.algorithm : map, sum, canFind;
|
||||||
|
|
||||||
if (astInformation.structInitStartLocations.canFindIndex(tokens[index].index))
|
auto tIndex = tokens[index].index;
|
||||||
|
|
||||||
|
if (astInformation.structInitStartLocations.canFindIndex(tIndex))
|
||||||
{
|
{
|
||||||
sBraceDepth++;
|
sBraceDepth++;
|
||||||
auto e = expressionEndIndex(index);
|
auto e = expressionEndIndex(index);
|
||||||
|
@ -741,13 +759,21 @@ private:
|
||||||
writeToken();
|
writeToken();
|
||||||
if (l > config.dfmt_soft_max_line_length)
|
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!"{");
|
indents.push(tok!"{");
|
||||||
newline();
|
newline();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
niBraceDepth++;
|
niBraceDepth++;
|
||||||
}
|
}
|
||||||
else if (astInformation.funLitStartLocations.canFindIndex(tokens[index].index))
|
else if (astInformation.funLitStartLocations.canFindIndex(tIndex))
|
||||||
{
|
{
|
||||||
sBraceDepth++;
|
sBraceDepth++;
|
||||||
if (peekBackIs(tok!")"))
|
if (peekBackIs(tok!")"))
|
||||||
|
@ -803,15 +829,34 @@ private:
|
||||||
|
|
||||||
void formatRightBrace()
|
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)
|
if (sBraceDepth > 0)
|
||||||
sBraceDepth--;
|
sBraceDepth--;
|
||||||
if (niBraceDepth > 0)
|
if (niBraceDepth > 0)
|
||||||
niBraceDepth--;
|
niBraceDepth--;
|
||||||
|
|
||||||
|
auto indentInfo = astInformation.indentInfoSortedByEndLocation[pos];
|
||||||
|
if (indentInfo.flags & BraceIndentInfoFlags.tempIndent)
|
||||||
|
{
|
||||||
|
popToBeginIndent(indentInfo);
|
||||||
|
simpleNewline();
|
||||||
|
indent();
|
||||||
|
}
|
||||||
writeToken();
|
writeToken();
|
||||||
}
|
}
|
||||||
else if (astInformation.funLitEndLocations.canFindIndex(tokens[index].index))
|
else if (astInformation.funLitEndLocations.canFindIndex(tokens[index].index, &pos))
|
||||||
{
|
{
|
||||||
if (niBraceDepth > 0)
|
if (niBraceDepth > 0)
|
||||||
{
|
{
|
||||||
|
@ -913,9 +958,11 @@ private:
|
||||||
if (!currentIs(tok!"{") && !currentIs(tok!";"))
|
if (!currentIs(tok!"{") && !currentIs(tok!";"))
|
||||||
write(" ");
|
write(" ");
|
||||||
}
|
}
|
||||||
else if (!currentIs(tok!"{") && !currentIs(tok!";")
|
else if (!currentIs(tok!"{") && !currentIs(tok!";") && !currentIs(tok!"in") &&
|
||||||
&& !currentIs(tok!"in") && !currentIs(tok!"out") && !currentIs(tok!"body"))
|
!currentIs(tok!"out") && !currentIs(tok!"do") && current.text != "body")
|
||||||
|
{
|
||||||
newline();
|
newline();
|
||||||
|
}
|
||||||
else if (currentIs(tok!"{") && indents.topAre(tok!"static", tok!"if"))
|
else if (currentIs(tok!"{") && indents.topAre(tok!"static", tok!"if"))
|
||||||
{
|
{
|
||||||
// Hacks to format braced vs non-braced static if declarations.
|
// Hacks to format braced vs non-braced static if declarations.
|
||||||
|
@ -1004,7 +1051,12 @@ private:
|
||||||
if (!currentIs(tok!"{"))
|
if (!currentIs(tok!"{"))
|
||||||
newline();
|
newline();
|
||||||
break;
|
break;
|
||||||
case tok!"body":
|
case tok!"identifier":
|
||||||
|
if (current.text == "body")
|
||||||
|
goto case tok!"do";
|
||||||
|
else
|
||||||
|
goto default;
|
||||||
|
case tok!"do":
|
||||||
if (!peekBackIs(tok!"}"))
|
if (!peekBackIs(tok!"}"))
|
||||||
newline();
|
newline();
|
||||||
writeToken();
|
writeToken();
|
||||||
|
@ -1190,11 +1242,14 @@ private:
|
||||||
break;
|
break;
|
||||||
case tok!".":
|
case tok!".":
|
||||||
regenLineBreakHintsIfNecessary(index);
|
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))
|
&& currentLineLength + nextTokenLength() > config.max_line_length))
|
||||||
{
|
{
|
||||||
pushWrapIndent();
|
pushWrapIndent();
|
||||||
newline();
|
newline();
|
||||||
|
if (ufcsWrap)
|
||||||
|
regenLineBreakHints(index);
|
||||||
}
|
}
|
||||||
writeToken();
|
writeToken();
|
||||||
break;
|
break;
|
||||||
|
@ -1317,7 +1372,18 @@ private:
|
||||||
|
|
||||||
void regenLineBreakHints(immutable size_t i)
|
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
|
// Use magical negative value for array literals and wrap indents
|
||||||
immutable inLvl = (indents.topIsWrap() || indents.topIs(tok!"]")) ? -indentLevel
|
immutable inLvl = (indents.topIsWrap() || indents.topIs(tok!"]")) ? -indentLevel
|
||||||
: indentLevel;
|
: indentLevel;
|
||||||
|
@ -1659,10 +1725,7 @@ const pure @safe @nogc:
|
||||||
|
|
||||||
const(Token) peekBack(uint distance = 1) nothrow
|
const(Token) peekBack(uint distance = 1) nothrow
|
||||||
{
|
{
|
||||||
if (index < distance)
|
assert(index >= distance, "Trying to peek before the first token");
|
||||||
{
|
|
||||||
assert(0, "Trying to peek before the first token");
|
|
||||||
}
|
|
||||||
return tokens[index - distance];
|
return tokens[index - distance];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1793,6 +1856,18 @@ const pure @safe @nogc:
|
||||||
return peekImplementation(tokenType, 1, ignoreComments);
|
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
|
bool peekBackIsSlashSlash() nothrow
|
||||||
{
|
{
|
||||||
return index > 0 && tokens[index - 1].type == tok!"comment"
|
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;
|
import std.range : assumeSorted;
|
||||||
|
if (!pos)
|
||||||
|
{
|
||||||
return !assumeSorted(items).equalRange(index).empty;
|
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");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -68,7 +68,13 @@ struct IndentStack
|
||||||
void push(IdType item) pure nothrow
|
void push(IdType item) pure nothrow
|
||||||
{
|
{
|
||||||
arr[index] = item;
|
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
|
void pop() pure nothrow
|
||||||
{
|
{
|
||||||
index = index == 0 ? index : index - 1;
|
if (index)
|
||||||
|
index--;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -85,9 +85,9 @@ else
|
||||||
void handleBooleans(string option, string value)
|
void handleBooleans(string option, string value)
|
||||||
{
|
{
|
||||||
import dfmt.editorconfig : OptionalBoolean;
|
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
|
immutable OptionalBoolean optVal = value == "true" ? OptionalBoolean.t
|
||||||
: OptionalBoolean.f;
|
: OptionalBoolean.f;
|
||||||
switch (option)
|
switch (option)
|
||||||
|
@ -113,6 +113,9 @@ else
|
||||||
case "compact_labeled_statements":
|
case "compact_labeled_statements":
|
||||||
optConfig.dfmt_compact_labeled_statements = optVal;
|
optConfig.dfmt_compact_labeled_statements = optVal;
|
||||||
break;
|
break;
|
||||||
|
case "single_template_constraint_indent":
|
||||||
|
optConfig.dfmt_single_template_constraint_indent = optVal;
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
assert(false, "Invalid command-line switch");
|
assert(false, "Invalid command-line switch");
|
||||||
}
|
}
|
||||||
|
@ -139,6 +142,7 @@ else
|
||||||
"space_before_function_parameters", &handleBooleans,
|
"space_before_function_parameters", &handleBooleans,
|
||||||
"split_operator_at_line_end", &handleBooleans,
|
"split_operator_at_line_end", &handleBooleans,
|
||||||
"compact_labeled_statements", &handleBooleans,
|
"compact_labeled_statements", &handleBooleans,
|
||||||
|
"single_template_constraint_indent", &handleBooleans,
|
||||||
"tab_width", &optConfig.tab_width,
|
"tab_width", &optConfig.tab_width,
|
||||||
"template_constraint_style", &optConfig.dfmt_template_constraint_style);
|
"template_constraint_style", &optConfig.dfmt_template_constraint_style);
|
||||||
// dfmt on
|
// 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;
|
enum optionsToString = () {
|
||||||
import std.conv : to;
|
|
||||||
|
|
||||||
string result = "(";
|
string result = "(";
|
||||||
foreach (i, option; EnumMembers!E)
|
foreach (s; [__traits(allMembers, E)])
|
||||||
{
|
{
|
||||||
immutable s = to!string(option);
|
|
||||||
if (s != "unspecified")
|
if (s != "unspecified")
|
||||||
result ~= s ~ "|";
|
result ~= s ~ "|";
|
||||||
}
|
}
|
||||||
result = result[0 .. $ - 1] ~ ")";
|
result = result[0 .. $ - 1] ~ ")";
|
||||||
return result;
|
return result;
|
||||||
|
} ();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void printHelp()
|
private void printHelp()
|
||||||
{
|
{
|
||||||
writeln(`dfmt `, VERSION, `
|
writeln(`dfmt `, VERSION, `
|
||||||
https://github.com/Hackerpilot/dfmt
|
https://github.com/dlang-community/dfmt
|
||||||
|
|
||||||
Options:
|
Options:
|
||||||
--help, -h Print this help message
|
--help, -h Print this help message
|
||||||
|
@ -322,23 +325,24 @@ Options:
|
||||||
|
|
||||||
Formatting Options:
|
Formatting Options:
|
||||||
--align_switch_statements
|
--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_size
|
||||||
--indent_style, -t `,
|
--indent_style, -t `,
|
||||||
optionsToString!(typeof(Config.indent_style))(), `
|
optionsToString!(typeof(Config.indent_style)), `
|
||||||
--soft_max_line_length
|
--soft_max_line_length
|
||||||
--max_line_length
|
--max_line_length
|
||||||
--outdent_attributes
|
--outdent_attributes
|
||||||
--space_after_cast
|
--space_after_cast
|
||||||
--space_before_function_parameters
|
--space_before_function_parameters
|
||||||
--selective_import_space
|
--selective_import_space
|
||||||
|
--single_template_constraint_indent
|
||||||
--split_operator_at_line_end
|
--split_operator_at_line_end
|
||||||
--compact_labeled_statements
|
--compact_labeled_statements
|
||||||
--template_constraint_style
|
--template_constraint_style
|
||||||
`,
|
`,
|
||||||
optionsToString!(typeof(Config.dfmt_template_constraint_style))());
|
optionsToString!(typeof(Config.dfmt_template_constraint_style)));
|
||||||
}
|
}
|
||||||
|
|
||||||
private string createFilePath(bool readFromStdin, string fileName)
|
private string createFilePath(bool readFromStdin, string fileName)
|
||||||
|
|
|
@ -217,7 +217,7 @@ private string generateFixedLengthCases()
|
||||||
a => format(`case tok!"%s": return %d + 1;`, a, a.length)).join("\n\t");
|
a => format(`case tok!"%s": return %d + 1;`, a, a.length)).join("\n\t");
|
||||||
|
|
||||||
string[] identifierTokens = [
|
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",
|
"break", "byte", "case", "cast", "catch", "cdouble", "cent", "cfloat", "char", "class",
|
||||||
"const", "continue", "creal", "dchar", "debug", "default", "delegate", "delete", "deprecated",
|
"const", "continue", "creal", "dchar", "debug", "default", "delegate", "delete", "deprecated",
|
||||||
"do", "double", "else", "enum", "export", "extern", "false", "final", "finally", "float",
|
"do", "double", "else", "enum", "export", "extern", "false", "final", "finally", "float",
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
Subproject commit 7487970b58f4a2c0d495679329a8a2857111f3fd
|
Subproject commit b7778fd6bf5f9aaaa87dd27f989cefbf9b3b365f
|
|
@ -3,7 +3,8 @@ unittest
|
||||||
{
|
{
|
||||||
{
|
{
|
||||||
foreach (abcde, def; abcdef.map!(battlecruiser => battlecruiser[123 .. 1231231])
|
foreach (abcde, def; abcdef.map!(battlecruiser => battlecruiser[123 .. 1231231])
|
||||||
.filter!(bravo => charlie[10] > 90000).sum())
|
.filter!(bravo => charlie[10] > 90000)
|
||||||
|
.sum())
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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)
|
||||||
|
{
|
||||||
|
}
|
|
@ -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)
|
||||||
|
{
|
||||||
|
}
|
|
@ -0,0 +1,19 @@
|
||||||
|
import character.body;
|
||||||
|
|
||||||
|
void body() @nogc
|
||||||
|
in
|
||||||
|
{
|
||||||
|
}
|
||||||
|
body
|
||||||
|
{
|
||||||
|
body = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
void body()
|
||||||
|
in
|
||||||
|
{
|
||||||
|
}
|
||||||
|
do
|
||||||
|
{
|
||||||
|
body = null;
|
||||||
|
}
|
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,6 @@
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
stuff[].map!(things => stuff.doThings)
|
||||||
|
.filter!(stuff)
|
||||||
|
.array();
|
||||||
|
}
|
|
@ -0,0 +1,2 @@
|
||||||
|
--template_constraint_style=conditional_newline_indent
|
||||||
|
--single_template_constraint_indent=true
|
|
@ -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) {}
|
|
@ -0,0 +1,2 @@
|
||||||
|
--template_constraint_style=always_newline_indent
|
||||||
|
--single_template_constraint_indent=true
|
|
@ -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) {}
|
|
@ -0,0 +1,7 @@
|
||||||
|
import character.body;
|
||||||
|
|
||||||
|
void body() @nogc
|
||||||
|
in{} body{body = null;}
|
||||||
|
|
||||||
|
void body()
|
||||||
|
in{} do{ body = null;}
|
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
|
@ -2,7 +2,8 @@ unittest {
|
||||||
{
|
{
|
||||||
{
|
{
|
||||||
foreach (abcde, def; abcdef.map!(battlecruiser => battlecruiser[123 .. 1231231])
|
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)
|
abcdeabcdeabcde(12341234).abcdeabcdeabcde(12341234).abcdeabcdeabcde(12341234)
|
||||||
|
|
|
@ -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) {
|
||||||
|
}
|
|
@ -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) {
|
||||||
|
}
|
|
@ -0,0 +1,15 @@
|
||||||
|
import character.body;
|
||||||
|
|
||||||
|
void body() @nogc
|
||||||
|
in {
|
||||||
|
}
|
||||||
|
body {
|
||||||
|
body = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
void body()
|
||||||
|
in {
|
||||||
|
}
|
||||||
|
do {
|
||||||
|
body = null;
|
||||||
|
}
|
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,5 @@
|
||||||
|
void main() {
|
||||||
|
stuff[].map!(things => stuff.doThings)
|
||||||
|
.filter!(stuff)
|
||||||
|
.array();
|
||||||
|
}
|
|
@ -0,0 +1,4 @@
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
stuff[].map!(things => stuff.doThings).filter!(stuff).array();
|
||||||
|
}
|
Loading…
Reference in New Issue