Compare commits

...

40 commits

Author SHA1 Message Date
Nicholas Wilson
d8e43e23ec remove explicit nothrow from globMatchEditorConfig
The in contract may throw.
2024-08-21 09:58:22 +02:00
Andrei Horodniceanu
0ea0572e86 makefile: Remove stdx-allocator from imports and sources
Signed-off-by: Andrei Horodniceanu <a.horodniceanu@proton.me>
2024-05-11 20:07:03 +02:00
Andrei Horodniceanu
5ea76cd293 makefile: fix bin/dfmt-test target
Don't call the D compiler with bin/githash.txt as a source file.

Signed-off-by: Andrei Horodniceanu <a.horodniceanu@proton.me>
2024-05-11 20:07:03 +02:00
Jeremy Baxter
fa463b472c improve makefile
o  add 'install' target
 o  shorten the name of INCLUDE_PATHS to IMPORTS
 o  use filename prerequisities and targets rather than phony keywords
 o  add a dependency on .git/refs/tags for the githash target
 o  add githash.txt and dfmt-test to the clean target
 o  add more targets to .PHONY
2024-02-15 10:41:02 +01:00
Daniel Zuncke
2ea6c43a66 Use libdparse to check for named arg
Remove custom named arg parser
2023-10-26 20:10:50 +00:00
Daniel Zuncke
9f377100f0 Remove unnecessary tok!"comment" filter 2023-10-26 20:10:50 +00:00
Daniel Zuncke
20b8badf8c Fix issue #586 2023-10-26 20:10:50 +00:00
Daniel Zuncke
35e55bc9b2
Fix #578 ternary expressions in AA literals not properly formatted (#591) 2023-10-22 17:52:14 +09:00
Daniel Zuncke
08fe5d6855 Confirm token equality, safer loop
Using different variable to iterate to guarantee unchanged behaviour
if anything doesn't work as intended.
2023-10-18 10:22:48 +02:00
Daniel Zuncke
c0452dbd11 Update test to include both known cases
I have formatted them both to look like the the individual bad output
and not like the actual output from formatting the issue0432.d file with
the current implementation. The current implementation makes it look
like a new / different problem.
2023-10-18 10:22:48 +02:00
Daniel Zuncke
876bbe33c1 Fix issue #432
Overview:
Array astInformation.structInitEndLocations is used to find index to use
in astInformation.indentInfoSortedByEndLocation.
Both are sorted, first is used to find the array index, second is
accessed at that index to get brace indentation information.

Problem:
structInitEndLocations is generated from struct initializers
exclusively while the brace information array also contains entries
for function literal initializers. Thus when function literal init(s)
are used, we get accumulating off by one errors in the second array:

match value in structInitEndLocations and take that index:
[3, 50]
    ^--> index 1

take brace indent information from that index:
[3, 15, 50]
    |   ^--> the one we want
    ^------> the one we get (function literal init)

Solution:
This guarantees that searching forward works.
While better search strategies than linear are possible, this should be
enough for any sane and most of the insane code files.
2023-10-18 10:22:48 +02:00
WebFreak001
1e765fb781 add knr test variant for no_space_after_keyword
The generator is so outdated and basic that it didn't generate this.
2023-07-26 16:13:48 +02:00
Robert Schadek
c43803575d No space after keywords
Readme update

test files
2023-07-26 16:13:48 +02:00
WebFreak001
470e65f7cc bump minimum libdparse version, fix #583 2023-07-19 14:43:24 +02:00
Eugen Wissner
6f41b20d5b Remove travis 2023-05-01 23:01:54 +02:00
Razvan Nitu
49b9fe4051
Merge pull request #579 from belka-ew/bug/revert-array-indent-on-line
Keep "(" indentation with a "]" in the same line
2023-04-07 23:19:48 +08:00
Eugen Wissner
fec7394175 Add reflow_property_chains option
Recalculate the splitting of property chains into multiple lines.
2023-03-29 11:29:59 +02:00
Eugen Wissner
727472c365
Keep "(" indentation with a "]" in the same line 2023-03-20 18:23:33 +01:00
WebFreak001
840aeee45e add missing test 2023-03-01 22:07:37 +01:00
WebFreak001
a91f044958 add some missing hasCurrent checks 2023-03-01 22:07:37 +01:00
Eugen Wissner
dba8c87ebc Revert operator indentation in an argument list 2023-02-06 10:17:09 +01:00
Eugen Wissner
a4fbc6f881 Revert chain indentation in an argument list 2023-01-15 20:51:03 +01:00
Eugen Wissner
57f57d95de Fix else indentation after array literal 2023-01-14 02:18:28 +01:00
WebFreak001
4a6078779a Fix #568, don't output empty files without error
Now when an error in formatting happens, it never outputs anything and
doesn't override the file when working inplace.

Additionally dfmt is no longer able to fail in the middle of a file, as
now we first write everything to a buffer and only if everything was
successful, that buffer is printed to stdout or written to the inplace
file.

This should also guard against segfaults with inplace file formatting
erasing parts of the file, as well as the user thinking it was
successful, even though dfmt didn't finish properly.
2022-10-15 02:33:04 +02:00
Iain Buclaw
e251e4343a Remove appveyor.yml
This pipeline isn't in use anymore.
2022-10-06 21:10:01 +02:00
Iain Buclaw
02070df593 Update downloads.dlang.org links to use https 2022-10-06 21:10:01 +02:00
Andrey Proskurin
6744df20f3 Add knr brace style to README 2022-09-14 13:25:04 +02:00
Eugen Wissner
8d42254d47 Fix indentation of callchains with comments
Weird formatting and indentation of multiline callchains with comments
in the middle.
2022-08-06 08:55:43 +02:00
Bastiaan Veelo
2a4af7a2b2
Retain line ending by default. (#553) 2022-07-28 17:21:10 +02:00
Eugen Wissner
026a58e273 Very long chained calls in array literals are indented weirdly 2022-07-28 17:14:01 +02:00
Bastiaan Veelo
4947beec6b CI
Add GitHub action.
2022-07-14 23:19:37 +02:00
belka-ew
d862d8aef1
Fix array literal indentation in foreach (#554) 2022-06-14 12:35:54 +00:00
skyline131313
036da91542
Update dub.json to remove dependency on rdmd (#547) 2022-06-13 16:23:56 +02:00
Max Haughton
ed5fc2ffd2
Merge pull request #551 from veelo/d_test_script
Port `test.sh` to platform independent D.
2022-05-30 00:15:49 +01:00
Bastiaan Veelo
b8da7c5cd4 Refactor courtesy WebFreak001.
Co-authored-by: Jan Jurzitza <gh@webfreak.org>
2022-05-27 19:47:47 +02:00
Bastiaan Veelo
f6d9d04e43 Port test.sh to platform independent D.
This executes also way faster by not spawning GNU diff.
2022-05-26 16:10:07 +02:00
Bastiaan Veelo
f81ddeadbd
obey end_of_line setting in all tokens (#550)
Multi-line tokens would be written with `LF`, regardless the `end_of_line` setting.

Fixes #228 and also produces end_of_line specified line-endings in strings.
2022-05-25 13:21:07 +02:00
Bastiaan Veelo
3e1e643972
Merge branch 'dlang-community:master' into master 2022-05-23 16:23:20 +02:00
Eugen Wissner
77e2ba4e3d Fix array indentation as argument 2022-05-23 14:09:26 +02:00
Bastiaan Veelo
5274e5531e
Merge pull request #1 from dlang-community/master
Allow comments in selective imports. (#403)
2018-10-29 12:04:52 +01:00
101 changed files with 1891 additions and 340 deletions

16
.gitattributes vendored Normal file
View file

@ -0,0 +1,16 @@
tests/issue0228.d text eol=lf
tests/allman/issue0228.d.ref text eol=crlf
tests/knr/issue0228.d.ref text eol=crlf
tests/otbs/issue0228.d.ref text eol=crlf
tests/issue0552_lf.d text eol=lf
tests/allman/issue0552_lf.d.ref text eol=lf
tests/knr/issue0552_lf.d.ref text eol=lf
tests/otbs/issue0552_lf.d.ref text eol=lf
tests/issue0552_cr.d text eol=cr
tests/allman/issue0552_cr.d.ref text eol=cr
tests/knr/issue0552_cr.d.ref text eol=cr
tests/otbs/issue0552_cr.d.ref text eol=cr
tests/issue0552_crlf.d text eol=crlf
tests/allman/issue0552_crlf.d.ref text eol=crlf
tests/knr/issue0552_crlf.d.ref text eol=crlf
tests/otbs/issue0552_crlf.d.ref text eol=crlf

34
.github/workflows/d.yml vendored Normal file
View file

@ -0,0 +1,34 @@
# This workflow uses actions that are not certified by GitHub.
# They are provided by a third-party and are governed by
# separate terms of service, privacy policy, and support
# documentation.
name: D
on:
push:
branches: [ "master" ]
pull_request:
branches: [ "master" ]
permissions:
contents: read
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: dlang-community/setup-dlang@4c99aa991ce7d19dd3064de0a4f2f6b2f152e2d7
- name: 'Build & Test'
run: |
# Build the project, with its main file included, without unittests
dub build --compiler=$DC
# Build and run tests, as defined by `unittest` configuration
# In this mode, `mainSourceFile` is excluded and `version (unittest)` are included
# See https://dub.pm/package-format-json.html#configurations
dub test --compiler=$DC
# Run tests
cd tests && rdmd test

View file

@ -1,15 +0,0 @@
#!/bin/bash
set -e
if [[ $BUILD == dub ]]; then
rdmd ./d-test-utils/test_with_package.d $LIBDPARSE_VERSION libdparse -- dub build --build=release
elif [[ $DC == ldc2 ]]; then
git submodule update --init --recursive
make ldc -j2
else
git submodule update --init --recursive
make debug -j2
fi
cd tests && ./test.sh

View file

@ -1,95 +0,0 @@
sudo: false
language: d
d:
- dmd
- ldc
os:
- linux
- osx
branches:
only:
- master
- /^v\d+\.\d+\.\d+([+-]\S*)*$/
env:
- BUILD=
- BUILD=dub LIBDPARSE_VERSION=min
- BUILD=dub LIBDPARSE_VERSION=max
script: ./.travis.sh
jobs:
include:
- stage: GitHub Release
#if: tag IS present
d: ldc-1.13.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.13.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
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
- stage: GitHub Release
#if: tag IS present
d: dmd
os: linux
language: generic
sudo: yes
script: echo "Deploying to GitHub releases ..." && ARCH=64 ./release-windows.sh
addons:
apt:
packages:
- p7zip-full
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

@ -1,4 +1,5 @@
# dfmt [![Build Status](https://travis-ci.org/dlang-community/dfmt.svg?branch=master)](https://travis-ci.org/dlang-community/dfmt)
# dfmt [![Build Status](https://github.com/dlang-community/dfmt/actions/workflows/d.yml/badge.svg)](https://github.com/dlang-community/dfmt/actions?query=workflow%3A%22D%22)
**dfmt** is a formatter for D source code
## Status
@ -51,11 +52,15 @@ 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)*
* `--template_constraint_style`: *see dfmt_template_constraint_style [below](#dfmt-specific-properties)*
* `--keep_line_breaks`: *see dfmt_keep_line_breaks [below](#dfmt-specific-properties)*
* `--single_indent`: *see dfmt_single_indent [below](#dfmt-specific-properties)*
* `--reflow_property_chains`: *see dfmt_property_chains [below](#dfmt-specific-properties)*
* `--space_after_keywords`: *see dfmt_space_after_keywords [below](#dfmt-specific-properties)*
### Example
```
@ -91,7 +96,7 @@ void main(string[] args)
### Standard EditorConfig properties
Property Name | Allowed Values | Description
--------------|----------------|------------
end_of_line | `cr`, `crlf` and **`lf`** | [See EditorConfig documentation.](https://github.com/editorconfig/editorconfig/wiki/EditorConfig-Properties#end_of_line)
end_of_line | `cr`, `crlf` and `lf` | [See EditorConfig documentation.](https://github.com/editorconfig/editorconfig/wiki/EditorConfig-Properties#end_of_line) When not set, `dfmt` adopts the first line ending in the input.
insert_final_newline | **`true`** | Not supported. `dfmt` always inserts a final newline.
charset | **`UTF-8`** | Not supported. `dfmt` only works correctly on UTF-8.
indent_style | `tab`, **`space`** | [See EditorConfig documentation.](https://github.com/editorconfig/editorconfig/wiki/EditorConfig-Properties#indent_style)
@ -102,7 +107,7 @@ max_line_length | positive integers (**`120`**) | [See EditorConfig documentatio
### dfmt-specific properties
Property Name | Allowed Values | Description
--------------|----------------|------------
dfmt_brace_style | **`allman`**, `otbs`, or `stroustrup` | [See Wikipedia](https://en.wikipedia.org/wiki/Brace_style)
dfmt_brace_style | **`allman`**, `otbs`, `stroustrup` or `knr` | [See Wikipedia](https://en.wikipedia.org/wiki/Brace_style)
dfmt_soft_max_line_length | positive integers (**`80`**) | The formatting process will usually keep lines below this length, but they may be up to *max_line_length* columns long.
dfmt_align_switch_statements | **`true`**, `false` | Align labels, cases, and defaults with their enclosing switch.
dfmt_outdent_attributes (Not yet implemented) | **`true`**, `false`| Decrease the indentation level of attributes.
@ -115,8 +120,11 @@ 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.
dfmt_space_after_keywords | **`true`**, `false` | Insert space after keywords (if,while,foreach,for, etc.).
## Terminology
* Braces - `{` and `}`

View file

@ -1,112 +0,0 @@
platform: x64
environment:
matrix:
- DC: dmd
DVersion: stable
arch: x64
- DC: dmd
DVersion: stable
arch: x86
# - DC: ldc
# DVersion: beta
# arch: x86
# - DC: ldc
# DVersion: beta
# arch: x64
# - DC: ldc
# DVersion: stable
# arch: x86
# - DC: ldc
# DVersion: stable
# arch: x64
skip_tags: false
branches:
only:
- master
- /^v\d+\.\d+\.\d+([+-]\S*)*$/
install:
- ps: function ResolveLatestDMD
{
$version = $env:DVersion;
if($version -eq "stable") {
$latest = (Invoke-WebRequest "http://downloads.dlang.org/releases/LATEST").toString();
$url = "http://downloads.dlang.org/releases/2.x/$($latest)/dmd.$($latest).windows.7z";
}elseif($version -eq "beta") {
$latest = (Invoke-WebRequest "http://downloads.dlang.org/pre-releases/LATEST").toString();
$latestVersion = $latest.split("-")[0].split("~")[0];
$url = "http://downloads.dlang.org/pre-releases/2.x/$($latestVersion)/dmd.$($latest).windows.7z";
}elseif($version -eq "nightly") {
$url = "http://nightlies.dlang.org/dmd-master-2017-05-20/dmd.master.windows.7z"
}else {
$url = "http://downloads.dlang.org/releases/2.x/$($version)/dmd.$($version).windows.7z";
}
$env:PATH += ";C:\dmd2\windows\bin;";
return $url;
}
- ps: function ResolveLatestLDC
{
$version = $env:DVersion;
if($version -eq "stable") {
$latest = (Invoke-WebRequest "https://ldc-developers.github.io/LATEST").toString().replace("`n","").replace("`r","");
$url = "https://github.com/ldc-developers/ldc/releases/download/v$($latest)/ldc2-$($latest)-win64-msvc.zip";
}elseif($version -eq "beta") {
$latest = (Invoke-WebRequest "https://ldc-developers.github.io/LATEST_BETA").toString().replace("`n","").replace("`r","");
$url = "https://github.com/ldc-developers/ldc/releases/download/v$($latest)/ldc2-$($latest)-win64-msvc.zip";
} else {
$latest = $version;
$url = "https://github.com/ldc-developers/ldc/releases/download/v$($version)/ldc2-$($version)-win64-msvc.zip";
}
$env:PATH += ";C:\ldc2-$($latest)-win64-msvc\bin";
$env:DC = "ldc2";
return $url;
}
- ps: function SetUpDCompiler
{
$env:toolchain = "msvc";
if($env:DC -eq "dmd"){
echo "downloading ...";
$url = ResolveLatestDMD;
echo $url;
Invoke-WebRequest $url -OutFile "c:\dmd.7z";
echo "finished.";
pushd c:\\;
7z x dmd.7z > $null;
popd;
}
elseif($env:DC -eq "ldc"){
echo "downloading ...";
$url = ResolveLatestLDC;
echo $url;
Invoke-WebRequest $url -OutFile "c:\ldc.zip";
echo "finished.";
pushd c:\\;
7z x ldc.zip > $null;
popd;
}
}
- ps: SetUpDCompiler
build_script:
- ps: if($env:arch -eq "x86"){
$env:compilersetupargs = "x86";
$env:Darch = "x86";
$env:DConf = "m32";
}elseif($env:arch -eq "x64"){
$env:compilersetupargs = "amd64";
$env:Darch = "x86_64";
$env:DConf = "m64";
}
- ps: $env:compilersetup = "C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\vcvarsall";
- '"%compilersetup%" %compilersetupargs%'
test_script:
- echo %PLATFORM%
- echo %Darch%
- echo %DC%
- echo %PATH%
- '%DC% --version'
- dub test --arch=%Darch% --compiler=%DC%
- git submodule update --init --recursive
- build.bat

View file

@ -24,7 +24,7 @@ _dfmt()
eolOpts="lf cr crlf"
boolOpts="true false"
braceOpts="allman otbs stroustrup"
braceOpts="allman otbs stroustrup knr"
indentOpts="tab space"
constraintOpts="conditional_newline_indent conditional_newline always_newline always_newline_indent"

View file

@ -4,7 +4,7 @@
"targetType": "autodetect",
"license": "BSL-1.0",
"dependencies": {
"libdparse": ">=0.14.0 <1.0.0"
"libdparse": ">=0.19.2 <1.0.0"
},
"targetPath" : "bin/",
"targetName" : "dfmt",
@ -14,7 +14,7 @@
"versions" : [
"built_with_dub"
],
"preGenerateCommands" : [
"rdmd \"$PACKAGE_DIR/dubhash.d\""
"preBuildCommands" : [
"$DC -run \"$PACKAGE_DIR/dubhash.d\""
]
}

@ -1 +1 @@
Subproject commit 7112880dae3f25553d96dae53a445c16261de7f9
Subproject commit fe6d1e38fb4fc04323170389cfec67ed7fd4e24a

View file

@ -1,53 +1,63 @@
PREFIX = /usr/local
SRC := $(shell find src -name "*.d") \
$(shell find libdparse/src -name "*.d") \
$(shell find stdx-allocator/source -name "*.d")
INCLUDE_PATHS := -Ilibdparse/src -Istdx-allocator/source -Isrc -Jbin
DMD_COMMON_FLAGS := -dip25 -w $(INCLUDE_PATHS)
DMD_DEBUG_FLAGS := -debug -g $(DMD_COMMON_FLAGS)
DMD_FLAGS := -O -inline $(DMD_COMMON_FLAGS)
DMD_TEST_FLAGS := -unittest -g $(DMD_COMMON_FLAGS)
LDC_FLAGS := -g -w -oq $(INCLUDE_PATHS)
GDC_FLAGS := -g -w -oq $(INCLUDE_PATHS)
override DMD_FLAGS += $(DFLAGS)
override LDC_FLAGS += $(DFLAGS)
override GDC_FLAGS += $(DFLAGS)
$(shell find libdparse/src -name "*.d")
IMPORTS := -Ilibdparse/src -Isrc -Jbin
DC ?= dmd
LDC ?= ldc2
GDC ?= gdc
.PHONY: dmd ldc gdc test
DMD_COMMON_FLAGS := -w $(IMPORTS)
DMD_DEBUG_FLAGS := -debug -g $(DMD_COMMON_FLAGS)
DMD_FLAGS := -O -inline $(DMD_COMMON_FLAGS)
DMD_TEST_FLAGS := -unittest -g $(DMD_COMMON_FLAGS)
LDC_FLAGS := -g -w -oq $(IMPORTS)
GDC_FLAGS := -g -w -oq $(IMPORTS)
override DMD_FLAGS += $(DFLAGS)
override LDC_FLAGS += $(DFLAGS)
override GDC_FLAGS += $(DFLAGS)
dmd: bin/dfmt
.PHONY: all clean install debug dmd ldc gdc pkg release test
githash:
all: bin/dfmt
bin/githash.txt:
mkdir -p bin
git describe --tags > bin/githash.txt
ldc: githash
dmd: bin/dfmt
ldc: bin/githash.txt
$(LDC) $(SRC) $(LDC_FLAGS) -ofbin/dfmt
-rm -f *.o
gdc:githash
gdc: bin/githash.txt
$(GDC) $(SRC) $(GDC_FLAGS) -obin/dfmt
test: debug
cd tests && ./test.sh
cd tests && ./test.d
bin/dfmt-test: githash $(SRC)
$(DC) $(DMD_TEST_FLAGS) $^ -of$@
bin/dfmt-test: bin/githash.txt $(SRC)
$(DC) $(DMD_TEST_FLAGS) $(filter %.d,$^) -of$@
bin/dfmt: githash $(SRC)
bin/dfmt: bin/githash.txt $(SRC)
$(DC) $(DMD_FLAGS) $(filter %.d,$^) -of$@
debug: githash $(SRC)
debug: bin/githash.txt $(SRC)
$(DC) $(DMD_DEBUG_FLAGS) $(filter %.d,$^) -ofbin/dfmt
pkg: dmd
$(MAKE) -f makd/Makd.mak pkg
clean:
$(RM) bin/dfmt
$(RM) bin/dfmt bin/dfmt-test bin/githash.txt
install:
chmod +x bin/dfmt
mkdir -p $(DESTDIR)$(PREFIX)/bin
cp -f bin/dfmt $(DESTDIR)$(PREFIX)/bin/dfmt
release:
./release.sh
githash
$(MAKE) bin/githash.txt

View file

@ -63,6 +63,8 @@ struct ASTInformation
(structInfoSortedByEndLocation);
sort(ufcsHintLocations);
ufcsHintLocations = ufcsHintLocations.uniq().array();
sort(ternaryColonLocations);
sort(namedArgumentColonLocations);
}
/// Locations of end braces for struct bodies
@ -135,6 +137,12 @@ struct ASTInformation
/// Opening & closing braces of struct initializers
StructInitializerInfo[] structInfoSortedByEndLocation;
/// 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
@ -438,6 +446,43 @@ final class FormatVisitor : ASTVisitor
outStatement.accept(this);
}
override void visit(const TernaryExpression ternaryExpression)
{
astInformation.ternaryColonLocations ~= ternaryExpression.colon.index;
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;
}
foreach (item; functionCall.arguments.namedArgumentList.items)
{
// Do nothing if not a named argument.
if (item.name == tok!"")
{
continue;
}
// Find first colon if named argument.
foreach (t; item.tokens)
{
if (t.type == tok!":")
{
astInformation.namedArgumentColonLocations ~= t.index;
break;
}
}
}
functionCall.accept(this);
}
private:
ASTInformation* astInformation;
}

View file

@ -10,7 +10,7 @@ import dfmt.editorconfig;
/// Brace styles
enum BraceStyle
{
unspecified,
_unspecified,
/// $(LINK https://en.wikipedia.org/wiki/Indent_style#Allman_style)
allman,
/// $(LINK https://en.wikipedia.org/wiki/Indent_style#Variant:_1TBS)
@ -23,7 +23,7 @@ enum BraceStyle
enum TemplateConstraintStyle
{
unspecified,
_unspecified,
conditional_newline_indent,
conditional_newline,
always_newline,
@ -63,6 +63,12 @@ struct Config
OptionalBoolean dfmt_keep_line_breaks;
///
OptionalBoolean dfmt_single_indent;
///
OptionalBoolean dfmt_reflow_property_chains;
///
OptionalBoolean dfmt_space_after_statement_keyword;
///
OptionalBoolean dfmt_space_before_named_arg_colon;
mixin StandardEditorConfigFields;
@ -73,7 +79,7 @@ struct Config
void initializeWithDefaults()
{
pattern = "*.d";
end_of_line = EOL.lf;
end_of_line = EOL._default;
indent_style = IndentStyle.space;
indent_size = 4;
tab_width = 4;
@ -93,6 +99,8 @@ struct Config
dfmt_space_before_aa_colon = OptionalBoolean.f;
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

@ -26,21 +26,22 @@ private auto commentRe = ctRegex!(`^\s*[#;].*$`);
enum OptionalBoolean : ubyte
{
unspecified = 3,
_unspecified = 3,
t = 1,
f = 0
}
enum IndentStyle : ubyte
{
unspecified,
_unspecified,
tab,
space
}
enum EOL : ubyte
{
unspecified,
_unspecified,
_default,
lf,
cr,
crlf
@ -74,7 +75,7 @@ mixin template StandardEditorConfigFields()
static if (N == "pattern")
continue;
else static if (is(T == enum))
*thisN = otherN != T.unspecified ? otherN : *thisN;
*thisN = otherN != T._unspecified ? otherN : *thisN;
else static if (is(T == int))
*thisN = otherN != -1 ? otherN : *thisN;
else static if (is(T == string))

View file

@ -15,7 +15,7 @@ import dfmt.indentation;
import dfmt.tokens;
import dfmt.wrapping;
import std.array;
import std.algorithm.comparison : among;
import std.algorithm.comparison : among, max;
/**
* Formats the code contained in `buffer` into `output`.
@ -121,8 +121,13 @@ struct TokenFormatter(OutputRange)
this.eolString = "\n";
else if (eol == eol.crlf)
this.eolString = "\r\n";
else if (eol == eol.unspecified)
else if (eol == eol._unspecified)
assert(false, "config.end_of_line was unspecified");
else
{
assert (eol == eol._default);
this.eolString = eolStringFromInput;
}
}
}
@ -196,6 +201,22 @@ private:
/// True if the next "else" should be formatted as a single line
bool inlineElse;
/// Tracks paren depth on a single line. This information can be used to
/// indent array literals inside parens, since arrays are indented only once
/// and paren indentation is ignored. Line breaks and "[" reset the counter.
int parenDepthOnLine;
string eolStringFromInput() const
{
import std.algorithm : countUntil;
// Intentional wraparound, -1 turns into uint.max when not found:
const firstCR = cast(uint) rawSource.countUntil("\r");
if (firstCR < cast(uint) rawSource.countUntil("\n"))
return firstCR == rawSource.countUntil("\r\n") ? "\r\n" : "\r";
return "\n";
}
void formatStep()
{
import std.range : assumeSorted;
@ -226,9 +247,9 @@ private:
else if (currentIs(tok!"return"))
{
writeToken();
if (!currentIs(tok!";") && !currentIs(tok!")") && !currentIs(tok!"{")
if (hasCurrent && (!currentIs(tok!";") && !currentIs(tok!")") && !currentIs(tok!"{")
&& !currentIs(tok!"in") && !currentIs(tok!"out") && !currentIs(tok!"do")
&& (hasCurrent && tokens[index].text != "body"))
&& tokens[index].text != "body"))
write(" ");
}
else if (currentIs(tok!"with"))
@ -236,16 +257,20 @@ private:
if (indents.length == 0 || !indents.topIsOneOf(tok!"switch", tok!"with"))
indents.push(tok!"with");
writeToken();
write(" ");
if (currentIs(tok!"("))
if (config.dfmt_space_after_keywords) {
write(" ");
}
if (hasCurrent && currentIs(tok!"("))
writeParens(false);
if (!currentIs(tok!"switch") && !currentIs(tok!"with")
if (hasCurrent && !currentIs(tok!"switch") && !currentIs(tok!"with")
&& !currentIs(tok!"{") && !(currentIs(tok!"final") && peekIs(tok!"switch")))
{
newline();
}
else if (!currentIs(tok!"{"))
else if (hasCurrent && !currentIs(tok!"{"))
{
write(" ");
}
}
else if (currentIs(tok!"switch"))
{
@ -330,7 +355,7 @@ private:
else if (isBasicType(current.type))
{
writeToken();
if (currentIs(tok!"identifier") || isKeyword(current.type) || inAsm)
if (hasCurrent && (currentIs(tok!"identifier") || isKeyword(current.type) || inAsm))
write(" ");
}
else if (isOperator(current.type))
@ -371,7 +396,7 @@ private:
import dfmt.editorconfig : OB = OptionalBoolean;
with (TemplateConstraintStyle) final switch (config.dfmt_template_constraint_style)
{
case unspecified:
case _unspecified:
assert(false, "Config was not validated properly");
case conditional_newline:
immutable l = currentLineLength + betweenParenLength(tokens[index + 1 .. $]);
@ -478,6 +503,9 @@ private:
if (peekIs(tok!"(") && (peekBackIs(tok!")") || peekBack2Is(tok!"!")))
pushWrapIndent(tok!"(");
if (peekIs(tok!".") && !indents.topIs(tok!"."))
indents.push(tok!".");
}
writeToken();
immutable j = justAddedExtraNewline;
@ -597,6 +625,7 @@ private:
writeToken();
if (p == tok!"(")
{
++parenDepthOnLine;
// If the file starts with an open paren, just give up. This isn't
// valid D code.
if (index < 2)
@ -616,9 +645,7 @@ private:
if (arrayInitializerStart && isMultilineAt(index - 1))
{
if (peekBack2Is(tok!"(")) {
indents.pop();
}
revertParenIndentation();
// Use the close bracket as the indent token to distinguish
// the array initialiazer from an array index in the newline
@ -642,6 +669,7 @@ private:
}
else if (p == tok!"[" && config.dfmt_keep_line_breaks == OptionalBoolean.t)
{
revertParenIndentation();
IndentStack.Details detail;
detail.wrap = false;
@ -694,6 +722,24 @@ private:
}
}
void revertParenIndentation()
{
import std.algorithm.searching : canFind, until;
if (tokens[index .. $].until!(tok => tok.line != current.line).canFind!(x => x.type == tok!"]"))
{
return;
}
if (parenDepthOnLine)
{
foreach (i; 0 .. parenDepthOnLine)
{
indents.pop();
}
}
parenDepthOnLine = 0;
}
void formatRightParen()
in
{
@ -701,12 +747,15 @@ private:
}
do
{
parenDepthOnLine = max(parenDepthOnLine - 1, 0);
parenDepth--;
indents.popWrapIndents();
while (indents.topIsOneOf(tok!"!", tok!")"))
indents.pop();
if (indents.topIs(tok!"("))
indents.pop();
if (indents.topIs(tok!"."))
indents.pop();
if (onNextLine)
{
@ -786,12 +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)
{
@ -807,11 +857,17 @@ private:
newline();
}
}
else if (indents.topIs(tok!"]")) // Associative array
else if (indents.topIs(tok!"]") && !isTernary) // Associative array
{
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))
@ -1004,6 +1060,21 @@ private:
if (niBraceDepth > 0)
niBraceDepth--;
// Account for possible function literals in this array which offset
// the previously set index (pos). Fixes issue #432.
size_t newPos = pos;
while(astInformation.indentInfoSortedByEndLocation[newPos].endLocation <
tokens[index].index)
{
newPos++;
}
if (astInformation.indentInfoSortedByEndLocation[newPos].endLocation ==
tokens[index].index)
{
pos = newPos;
}
auto indentInfo = astInformation.indentInfoSortedByEndLocation[pos];
if (indentInfo.flags & BraceIndentInfoFlags.tempIndent)
{
@ -1073,7 +1144,10 @@ private:
indents.pop();
indents.push(tok!"switch");
writeToken(); // switch
write(" ");
if (config.dfmt_space_after_keywords)
{
write(" ");
}
}
void formatBlockHeader()
@ -1104,16 +1178,26 @@ private:
if (currentIs(tok!"("))
{
write(" ");
if (config.dfmt_space_after_keywords)
{
write(" ");
}
writeParens(false);
}
if (hasCurrent)
{
if (currentIs(tok!"switch") || (currentIs(tok!"final") && peekIs(tok!"switch")))
write(" ");
{
if (config.dfmt_space_after_keywords)
{
write(" ");
}
}
else if (currentIs(tok!"comment"))
{
formatStep();
}
else if (!shouldPushIndent)
{
if (!currentIs(tok!"{") && !currentIs(tok!";"))
@ -1194,7 +1278,7 @@ private:
break;
case tok!"cast":
writeToken();
if (currentIs(tok!"("))
if (hasCurrent && currentIs(tok!"("))
writeParens(config.dfmt_space_after_cast == OptionalBoolean.t);
break;
case tok!"out":
@ -1206,14 +1290,14 @@ private:
write(" ");
}
writeToken();
if (!currentIs(tok!"{") && !currentIs(tok!"comment"))
if (hasCurrent && !currentIs(tok!"{") && !currentIs(tok!"comment"))
write(" ");
break;
case tok!"try":
case tok!"finally":
indents.push(current.type);
writeToken();
if (!currentIs(tok!"{"))
if (hasCurrent && !currentIs(tok!"{"))
newline();
break;
case tok!"identifier":
@ -1238,6 +1322,8 @@ private:
write(" ");
}
writeToken();
if (!hasCurrent)
return;
immutable isFunctionLit = astInformation.funLitStartLocations.canFindIndex(
current.index);
if (isFunctionLit && config.dfmt_brace_style == BraceStyle.allman)
@ -1250,12 +1336,12 @@ private:
tok!"}", tok!"=", tok!"&&", tok!"||") && !peekBackIsKeyword())
write(" ");
writeToken();
if (!currentIs(tok!"(") && !currentIs(tok!"{") && !currentIs(tok!"comment"))
if (hasCurrent && !currentIs(tok!"(") && !currentIs(tok!"{") && !currentIs(tok!"comment"))
write(" ");
break;
case tok!"case":
writeToken();
if (!currentIs(tok!";"))
if (hasCurrent && !currentIs(tok!";"))
write(" ");
break;
case tok!"enum":
@ -1269,7 +1355,7 @@ private:
write(" ");
indents.push(tok!"enum");
writeToken();
if (!currentIs(tok!":") && !currentIs(tok!"{"))
if (hasCurrent && !currentIs(tok!":") && !currentIs(tok!"{"))
write(" ");
}
break;
@ -1293,7 +1379,7 @@ private:
goto default;
case tok!"invariant":
writeToken();
if (currentIs(tok!"("))
if (hasCurrent && currentIs(tok!"("))
write(" ");
break;
default:
@ -1417,11 +1503,13 @@ private:
break;
case tok!".":
regenLineBreakHintsIfNecessary(index);
immutable bool ufcsWrap = astInformation.ufcsHintLocations.canFindIndex(current.index);
immutable bool ufcsWrap = config.dfmt_reflow_property_chains == OptionalBoolean.t
&& astInformation.ufcsHintLocations.canFindIndex(current.index);
if (ufcsWrap || linebreakHints.canFind(index) || onNextLine
|| (linebreakHints.length == 0 && currentLineLength + nextTokenLength() > config.max_line_length))
{
pushWrapIndent();
if (!indents.topIs(tok!"."))
indents.push(tok!".");
if (!peekBackIs(tok!"comment"))
newline();
if (ufcsWrap || onNextLine)
@ -1585,6 +1673,10 @@ private:
const commaLine = tokens[index].line;
writeToken();
if (indents.topIsWrap && !indents.topIs(tok!","))
{
indents.pop;
}
if (!currentIs(tok!")") && !currentIs(tok!"]")
&& !currentIs(tok!"}") && !currentIs(tok!"comment"))
{
@ -1603,6 +1695,10 @@ private:
{
pushWrapIndent();
writeToken();
if (indents.topIsWrap && !indents.topIs(tok!","))
{
indents.pop;
}
newline();
}
else
@ -1779,7 +1875,19 @@ private:
if (indents.topIs(tok!"]"))
{
indents.pop();
indentLevel = indents.indentLevel;
}
// Find the initial indentation of constructs like "if" and
// "foreach" without removing them from the stack, since they
// still can be used later to indent "else".
auto savedIndents = IndentStack(config);
while (indents.length >= 0 && indents.topIsTemp) {
savedIndents.push(indents.top, indents.topDetails);
indents.pop;
}
indentLevel = indents.indentLevel;
while (savedIndents.length > 0) {
indents.push(savedIndents.top, savedIndents.topDetails);
savedIndents.pop;
}
}
else if (astInformation.attributeDeclarationLines.canFindIndex(current.line))
@ -1810,6 +1918,7 @@ private:
}
indent();
}
parenDepthOnLine = 0;
}
void write(string str)
@ -1822,6 +1931,8 @@ private:
{
import std.range:retro;
import std.algorithm.searching:countUntil;
import std.algorithm.iteration:joiner;
import std.string:lineSplitter;
if (current.text is null)
{
@ -1831,12 +1942,7 @@ private:
}
else
{
// You know what's awesome? Windows can't handle its own line
// endings correctly.
version (Windows)
output.put(current.text.replace("\r", ""));
else
output.put(current.text);
output.put(current.text.lineSplitter.joiner(eolString));
switch (current.type)
{
case tok!"stringLiteral":

View file

@ -12,7 +12,7 @@ import std.path : filenameCharCmp, isDirSeparator;
// * changes meaning to match all characters except '/'
// ** added to take over the old meaning of *
bool globMatchEditorConfig(CaseSensitive cs = CaseSensitive.osDefault, C, Range)(
Range path, const(C)[] pattern) @safe pure nothrow
Range path, const(C)[] pattern) @safe pure
if (isForwardRange!Range && isSomeChar!(ElementEncodingType!Range)
&& isSomeChar!C && is(Unqual!C == Unqual!(ElementEncodingType!Range)))
in

View file

@ -278,6 +278,12 @@ private:
immutable currentIsNonWrapTemp = !details[i].wrap
&& details[i].temp && arr[i] != tok!")" && arr[i] != tok!"!";
if (currentIsNonWrapTemp && arr[i + 1] == tok!"]")
{
parenCount = pc;
continue;
}
if (arr[i] == tok!"static"
&& arr[i + 1].among!(tok!"if", tok!"else", tok!"foreach", tok!"foreach_reverse")
&& (i + 2 >= index || arr[i + 2] != tok!"{"))

View file

@ -38,13 +38,13 @@ version (NoMain)
}
else
{
import std.array : front, popFront;
import std.stdio : stdout, stdin, stderr, writeln, File;
import dfmt.config : Config;
import dfmt.formatter : format;
import std.path : buildPath, dirName, expandTilde;
import dfmt.editorconfig : getConfigFor;
import dfmt.formatter : format;
import std.array : appender, front, popFront;
import std.getopt : getopt, GetOptException;
import std.path : buildPath, dirName, expandTilde;
import std.stdio : File, stderr, stdin, stdout, writeln;
int main(string[] args)
{
@ -92,12 +92,21 @@ 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;
case "single_indent":
optConfig.dfmt_single_indent = optVal;
break;
case "reflow_property_chains":
optConfig.dfmt_reflow_property_chains = optVal;
break;
case "space_after_keywords":
optConfig.dfmt_space_after_keywords = optVal;
break;
default:
assert(false, "Invalid command-line switch");
}
@ -120,16 +129,19 @@ else
"soft_max_line_length", &optConfig.dfmt_soft_max_line_length,
"outdent_attributes", &handleBooleans,
"space_after_cast", &handleBooleans,
"space_after_keywords", &handleBooleans,
"selective_import_space", &handleBooleans,
"space_before_function_parameters", &handleBooleans,
"split_operator_at_line_end", &handleBooleans,
"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,
"single_indent", &handleBooleans);
"single_indent", &handleBooleans,
"reflow_property_chains", &handleBooleans);
// dfmt on
}
catch (GetOptException e)
@ -153,14 +165,13 @@ else
args.popFront();
immutable bool readFromStdin = args.length == 0;
File output = stdout;
version (Windows)
{
// On Windows, set stdout to binary mode (needed for correct EOL writing)
// See Phobos' stdio.File.rawWrite
{
import std.stdio : _O_BINARY;
immutable fd = output.fileno;
immutable fd = stdout.fileno;
_setmode(fd, _O_BINARY);
version (CRuntime_DigitalMars)
{
@ -220,7 +231,7 @@ else
break;
}
immutable bool formatSuccess = format("stdin", buffer,
output.lockingTextWriter(), &config);
stdout.lockingTextWriter(), &config);
return formatSuccess ? 0 : 1;
}
else
@ -262,10 +273,16 @@ else
{
buffer = new ubyte[](cast(size_t) f.size);
f.rawRead(buffer);
if (inplace)
output = File(path, "wb");
immutable bool formatSuccess = format(path, buffer, output.lockingTextWriter(), &config);
if (!formatSuccess)
auto output = appender!string;
immutable bool formatSuccess = format(path, buffer, output, &config);
if (formatSuccess)
{
if (inplace)
File(path, "wb").rawWrite(output.data);
else
stdout.rawWrite(output.data);
}
else
retVal = 1;
}
}
@ -289,12 +306,14 @@ private version (Windows)
template optionsToString(E) if (is(E == enum))
{
import std.algorithm.searching : startsWith;
enum optionsToString = () {
string result = "(";
foreach (s; [__traits(allMembers, E)])
{
if (s != "unspecified")
if (!s.startsWith("_"))
result ~= s ~ "|";
}
result = result[0 .. $ - 1] ~ ")";
@ -327,13 +346,16 @@ Formatting Options:
--outdent_attributes
--space_after_cast
--space_before_function_parameters
--space_after_keywords
--selective_import_space
--single_template_constraint_indent
--split_operator_at_line_end
--compact_labeled_statements
--template_constraint_style
--space_before_aa_colon
--space_before_named_arg_colon
--single_indent
--reflow_property_chains
`,
optionsToString!(typeof(Config.dfmt_template_constraint_style)));
}

View file

@ -0,0 +1,23 @@
class C
{
void f()
{
if (true)
{
f(map.map.map.map.map.map.map.map.map.map.map.map.map.map.map.map
.map.map.map.map.map.map, __FILE__, __FILE__, __FILE__, __FILE__, __FILE__,
__FILE__, __FILE__, __FILE__, __FILE__, __FILE__, __FILE__,
__FILE__, __FILE__, __FILE__, __FILE__, __FILE__, __LINE__);
g(map && map && map && map && map && map && map && map && map && map && map
&& map, __FILE__, __FILE__, __FILE__, __FILE__, __FILE__,
__FILE__, __FILE__, __LINE__);
h(map || map || map || map || map || map || map || map || map || map || map
|| map, __FILE__, __FILE__, __FILE__, __FILE__, __FILE__,
__FILE__, __FILE__, __LINE__);
i(map + map + map + map + map + map + map + map + map + map + map + map + map
+ map + map + map + map + map, __FILE__, __FILE__, __FILE__,
__FILE__, __FILE__, __FILE__, __FILE__, __LINE__);
}
}
}

View file

@ -0,0 +1,31 @@
class C
{
void f()
{
if (true)
{
f(
array.map!(a => a.prop)
.array
.to!string,
__FILE__,
__LINE__);
g(
map &&
map,
__FILE__,
__LINE__);
h(
map ||
map,
__FILE__,
__LINE__);
i(
map
+ map,
__FILE__,
__LINE__);
}
}
}

View file

@ -2,6 +2,6 @@ int /*sneaky*/ foo( /*comments*/ ) /*everywhere*/
{
// comment on its own line
foo() // comment on same line
.bar(); // also on same line
.bar(); // also on same line
/* again */ // same line
}

View file

@ -0,0 +1,54 @@
static foreach (x; [
1,
2,
3,
])
{
}
static foreach_reverse (x; [
1,
2,
3,
])
{
}
void f()
{
foreach (x; [
1,
2,
3,
])
{
}
foreach_reverse (x; [
1,
2,
3,
])
{
}
if (!SymbolTool.instance.workspacesFilesUris.canFind!sameFile(uri))
{
send(TextDocument.publishDiagnostics, new PublishDiagnosticsParams(uri, [
]));
}
foreach (x; map([
1,
2,
3,
]))
{
}
foreach (x; foo!(map!([
1,
2,
3,
])))
{
}
}

View file

@ -0,0 +1 @@
alias u8 = ubyte

View file

@ -0,0 +1,8 @@
/* This test relies on ../.gitattributes to contain these lines:
tests/issue0228.d text eol=lf
tests/allman/issue0228.d.ref text eol=crlf
tests/knr/issue0228.d.ref text eol=crlf
tests/otbs/issue0228.d.ref text eol=crlf
*/

View file

@ -0,0 +1,40 @@
struct S1
{
ulong x;
ulong y;
ulong function(ulong) f;
}
struct S2
{
ulong x;
ulong y;
ulong z;
ulong w;
}
// -----------------------------------------------------------------------------
// Example 1
// Anonymous function in struct, long struct initializer
immutable S1 s1 = {
1111111111111111111, 1111111111111111111, (x) { return x + 1111; },
};
void f1()
{
}
// -----------------------------------------------------------------------------
// Example 2
// Anonymous function anywhere, long struct initializer
int function(int) f2 = (x) { return x + 1111; };
immutable S2 s = {
1111111111111111111, 1111111111111111111, 1111111111111111111, 1111111111111111111,
};
void f2()
{
}

View file

@ -0,0 +1,29 @@
void main()
{
const a1 = [
builder.rebuild!((x, y, z) => x + y + z)
.rebuild!(x => x)
.rebuild!(x => x),
];
const a2 = [
builder.rebuild!(x => x)
.rebuild!(x => x)
.rebuild!(x => x),
builder.rebuild!(x => x)
.rebuild!(x => x)
.rebuild!(x => x),
];
foo([
line1,
value_line2_bla_bla_bla.propertyCallBlaBlaBla(a, b, c)
.propertyCallBlaBlaBla(a, b, c, d).propertyCallBlaBlaBla(a, b, c)
.propertyCallBlaBlaBla(a, b, c).value,
]);
}
void foo()
{
afdsafds.asdf.flub;
}

View file

@ -0,0 +1,74 @@
private void selectMember(Args...)(Args args)
{
static if (true)
{
static if (args[0])
{
}
else
{
}
}
if (true)
{
if (args[0])
{
}
else
{
}
}
}
private void selectMember(Args...)(Args args)
{
static if (true)
{
static if ([
0,
1,
2,
3,
4,
])
{
}
else
{
}
}
if (true)
{
if (args[
0,
1,
2,
3,
4,
])
{
}
else
{
}
}
}
void f()
{
foreach (x; y)
if (foo)
{
}
else
{
}
if (a)
if (b)
{
}
else
{
}
}

View file

@ -0,0 +1,34 @@
void main()
{
const a1 = [
builder
.rebuild!((x, y, z) => x + y + z)
.rebuild!(x => x)
.rebuild!(x => x),
];
const a2 = [
builder
.rebuild!(x => x)
.rebuild!(x => x)
.rebuild!(x => x),
builder
.rebuild!(x => x)
.rebuild!(x => x)
.rebuild!(x => x),
];
foo([
line1,
value_line2_bla_bla_bla.propertyCallBlaBlaBla(a, b, c)
.propertyCallBlaBlaBla(a, b, c, d).propertyCallBlaBlaBla(a, b, c)
.propertyCallBlaBlaBla(a, b, c).value,
]);
}
void foo()
{
afdsafds
.asdf
.flub;
}

View file

@ -0,0 +1,15 @@
string f()
{
return duration.total!"seconds".to!string;
}
string g()
{
return duration.total!"seconds"().to!string;
}
string h()
{
return duration.total!"seconds"().to!string.to!string.to!string.to!string.to!string.to!string
.to!string.to!string.to!string;
}

View file

@ -0,0 +1 @@
/// Testing CR line endings. void main() { }

View file

@ -0,0 +1,4 @@
/// Testing CRLF line endings.
void main()
{
}

View file

@ -0,0 +1,4 @@
/// Testing LF line endings.
void main()
{
}

View file

@ -0,0 +1,8 @@
void f()
{
auto t = true ? 1 : 0;
auto a = [true ? 1 : 0];
auto aa1 = [0: true ? 1 : 0];
auto aa2 = [0: true ? (false ? 1 : 2) : 3];
auto aa3 = [0: true ? false ? 1 : 2 : 3];
}

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

View file

@ -0,0 +1,11 @@
unittest
{
f([
x
]);
}
void f(T[] x,
const U y)
{
}

View file

@ -0,0 +1,15 @@
void main(string[] args)
{
for(int i = 0; i < 10; ++i)
{
if(i == 9)
break;
}
while(false)
{
}
foreach(i; 0 .. 9)
{
}
}

View file

@ -0,0 +1 @@
--single_indent=true

View file

@ -0,0 +1,60 @@
class C
{
void f()
{
if (true)
{
f(
map.map.map.map.map.map.map.map.map.map.map.map.map.map.map.map.map.map.map.map.map.map,
__FILE__,
__FILE__,
__FILE__,
__FILE__,
__FILE__,
__FILE__,
__FILE__,
__FILE__,
__FILE__,
__FILE__,
__FILE__,
__FILE__,
__FILE__,
__FILE__,
__FILE__,
__FILE__,
__LINE__);
g(
map && map && map && map && map && map && map && map && map && map && map && map,
__FILE__,
__FILE__,
__FILE__,
__FILE__,
__FILE__,
__FILE__,
__FILE__,
__LINE__);
h(
map || map || map || map || map || map || map || map || map || map || map || map,
__FILE__,
__FILE__,
__FILE__,
__FILE__,
__FILE__,
__FILE__,
__FILE__,
__LINE__);
i(
map + map + map + map + map + map + map + map + map + map + map + map + map + map + map + map + map
+ map,
__FILE__,
__FILE__,
__FILE__,
__FILE__,
__FILE__,
__FILE__,
__FILE__,
__LINE__);
}
}
}

View file

@ -0,0 +1,2 @@
--single_indent=true
--keep_line_breaks=true

View file

@ -0,0 +1,31 @@
class C
{
void f()
{
if (true)
{
f(
array.map!(a => a.prop)
.array
.to!string,
__FILE__,
__LINE__);
g(
map &&
map,
__FILE__,
__LINE__);
h(
map ||
map,
__FILE__,
__LINE__);
i(
map
+ map,
__FILE__,
__LINE__);
}
}
}

View file

@ -0,0 +1 @@
### This file should not be erased just because it is not formatted correctly

1
tests/foreach_array.args Normal file
View file

@ -0,0 +1 @@
--keep_line_breaks true

53
tests/foreach_array.d Normal file
View file

@ -0,0 +1,53 @@
static foreach (x; [
1,
2,
3,
])
{
}
static foreach_reverse (x; [
1,
2,
3,
])
{
}
void f()
{
foreach (x; [
1,
2,
3,
])
{
}
foreach_reverse (x; [
1,
2,
3,
])
{
}
if (!SymbolTool.instance.workspacesFilesUris.canFind!sameFile(uri))
{
send(TextDocument.publishDiagnostics, new PublishDiagnosticsParams(uri, []));
}
foreach (x; map([
1,
2,
3,
]))
{
}
foreach (x; foo!(map!([
1,
2,
3,
])))
{
}
}

1
tests/incomplete_alias.d Normal file
View file

@ -0,0 +1 @@
alias u8 = ubyte

1
tests/issue0228.args Normal file
View file

@ -0,0 +1 @@
--end_of_line=crlf

8
tests/issue0228.d Normal file
View file

@ -0,0 +1,8 @@
/* This test relies on ../.gitattributes to contain these lines:
tests/issue0228.d text eol=lf
tests/allman/issue0228.d.ref text eol=crlf
tests/knr/issue0228.d.ref text eol=crlf
tests/otbs/issue0228.d.ref text eol=crlf
*/

38
tests/issue0432.d Normal file
View file

@ -0,0 +1,38 @@
struct S1
{
ulong x;
ulong y;
ulong function(ulong)f;
}
struct S2
{
ulong x;
ulong y;
ulong z;
ulong w;
}
// -----------------------------------------------------------------------------
// Example 1
// Anonymous function in struct, long struct initializer
immutable S1 s1 = {
1111111111111111111, 1111111111111111111, (x) { return x + 1111; },};
void f1()
{
}
// -----------------------------------------------------------------------------
// Example 2
// Anonymous function anywhere, long struct initializer
int function(int) f2 = (x) { return x + 1111; };
immutable S2 s = {
1111111111111111111, 1111111111111111111, 1111111111111111111, 1111111111111111111,};
void f2()
{
}

33
tests/issue0494.d Normal file
View file

@ -0,0 +1,33 @@
void main()
{
const a1 = [
builder
.rebuild!((x, y, z) => x + y + z)
.rebuild!(x => x)
.rebuild!(x => x),
];
const a2 = [
builder
.rebuild!(x => x)
.rebuild!(x => x)
.rebuild!(x => x),
builder
.rebuild!(x => x)
.rebuild!(x => x)
.rebuild!(x => x),
];
foo([
line1,
value_line2_bla_bla_bla.propertyCallBlaBlaBla(a, b, c)
.propertyCallBlaBlaBla(a, b, c, d).propertyCallBlaBlaBla(a, b, c)
.propertyCallBlaBlaBla(a, b, c).value,
]);
}
void foo() {
afdsafds
.asdf
.flub;
}

74
tests/issue0494_else.d Normal file
View file

@ -0,0 +1,74 @@
private void selectMember(Args...)(Args args)
{
static if (true)
{
static if (args[0])
{
}
else
{
}
}
if (true)
{
if (args[0])
{
}
else
{
}
}
}
private void selectMember(Args...)(Args args)
{
static if (true)
{
static if ([
0,
1,
2,
3,
4,
])
{
}
else
{
}
}
if (true)
{
if (args[
0,
1,
2,
3,
4,
])
{
}
else
{
}
}
}
void f()
{
foreach (x; y)
if (foo)
{
}
else
{
}
if (a)
if (b)
{
}
else
{
}
}

View file

@ -0,0 +1 @@
--keep_line_breaks=true

View file

@ -0,0 +1,33 @@
void main()
{
const a1 = [
builder
.rebuild!((x, y, z) => x + y + z)
.rebuild!(x => x)
.rebuild!(x => x),
];
const a2 = [
builder
.rebuild!(x => x)
.rebuild!(x => x)
.rebuild!(x => x),
builder
.rebuild!(x => x)
.rebuild!(x => x)
.rebuild!(x => x),
];
foo([
line1,
value_line2_bla_bla_bla.propertyCallBlaBlaBla(a, b, c)
.propertyCallBlaBlaBla(a, b, c, d).propertyCallBlaBlaBla(a, b, c)
.propertyCallBlaBlaBla(a, b, c).value,
]);
}
void foo() {
afdsafds
.asdf
.flub;
}

1
tests/issue0503.args Normal file
View file

@ -0,0 +1 @@
--reflow_property_chains=false

14
tests/issue0503.d Normal file
View file

@ -0,0 +1,14 @@
string f()
{
return duration.total!"seconds".to!string;
}
string g()
{
return duration.total!"seconds"().to!string;
}
string h()
{
return duration.total!"seconds"().to!string.to!string.to!string.to!string.to!string.to!string.to!string.to!string.to!string;
}

1
tests/issue0552_cr.d Normal file
View file

@ -0,0 +1 @@
/// Testing CR line endings. void main() { }

4
tests/issue0552_crlf.d Normal file
View file

@ -0,0 +1,4 @@
/// Testing CRLF line endings.
void main()
{
}

4
tests/issue0552_lf.d Normal file
View file

@ -0,0 +1,4 @@
/// Testing LF line endings.
void main()
{
}

8
tests/issue0578.d Normal file
View file

@ -0,0 +1,8 @@
void f()
{
auto t = true ? 1 : 0;
auto a = [true ? 1: 0];
auto aa1 = [0: true ? 1: 0];
auto aa2 = [0: true ? (false ? 1: 2): 3];
auto aa3 = [0: true ? false ? 1: 2: 3];
}

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

View file

@ -0,0 +1 @@
--keep_line_breaks=true

View file

@ -0,0 +1,11 @@
unittest
{
f([
x
]);
}
void f(T[] x,
const U y)
{
}

View file

@ -0,0 +1 @@
--keep_line_breaks=true

View file

@ -0,0 +1,21 @@
class C {
void f()
{
if (true) {
f(map.map.map.map.map.map.map.map.map.map.map.map.map.map.map.map
.map.map.map.map.map.map, __FILE__, __FILE__, __FILE__, __FILE__, __FILE__,
__FILE__, __FILE__, __FILE__, __FILE__, __FILE__, __FILE__,
__FILE__, __FILE__, __FILE__, __FILE__, __FILE__, __LINE__);
g(map && map && map && map && map && map && map && map && map && map && map
&& map, __FILE__, __FILE__, __FILE__, __FILE__, __FILE__,
__FILE__, __FILE__, __LINE__);
h(map || map || map || map || map || map || map || map || map || map || map
|| map, __FILE__, __FILE__, __FILE__, __FILE__, __FILE__,
__FILE__, __FILE__, __LINE__);
i(map + map + map + map + map + map + map + map + map + map + map + map + map
+ map + map + map + map + map, __FILE__, __FILE__, __FILE__,
__FILE__, __FILE__, __FILE__, __FILE__, __LINE__);
}
}
}

View file

@ -0,0 +1,29 @@
class C {
void f()
{
if (true) {
f(
array.map!(a => a.prop)
.array
.to!string,
__FILE__,
__LINE__);
g(
map &&
map,
__FILE__,
__LINE__);
h(
map ||
map,
__FILE__,
__LINE__);
i(
map
+ map,
__FILE__,
__LINE__);
}
}
}

View file

@ -2,6 +2,6 @@ int /*sneaky*/ foo( /*comments*/ ) /*everywhere*/
{
// comment on its own line
foo() // comment on same line
.bar(); // also on same line
.bar(); // also on same line
/* again */ // same line
}

View file

@ -0,0 +1,47 @@
static foreach (x; [
1,
2,
3,
]) {
}
static foreach_reverse (x; [
1,
2,
3,
]) {
}
void f()
{
foreach (x; [
1,
2,
3,
]) {
}
foreach_reverse (x; [
1,
2,
3,
]) {
}
if (!SymbolTool.instance.workspacesFilesUris.canFind!sameFile(uri)) {
send(TextDocument.publishDiagnostics, new PublishDiagnosticsParams(uri, [
]));
}
foreach (x; map([
1,
2,
3,
])) {
}
foreach (x; foo!(map!([
1,
2,
3,
]))) {
}
}

View file

@ -0,0 +1 @@
alias u8 = ubyte

View file

@ -0,0 +1,8 @@
/* This test relies on ../.gitattributes to contain these lines:
tests/issue0228.d text eol=lf
tests/allman/issue0228.d.ref text eol=crlf
tests/knr/issue0228.d.ref text eol=crlf
tests/otbs/issue0228.d.ref text eol=crlf
*/

38
tests/knr/issue0432.d.ref Normal file
View file

@ -0,0 +1,38 @@
struct S1 {
ulong x;
ulong y;
ulong function(ulong) f;
}
struct S2 {
ulong x;
ulong y;
ulong z;
ulong w;
}
// -----------------------------------------------------------------------------
// Example 1
// Anonymous function in struct, long struct initializer
immutable S1 s1 = {
1111111111111111111, 1111111111111111111, (x) { return x + 1111; },
};
void f1()
{
}
// -----------------------------------------------------------------------------
// Example 2
// Anonymous function anywhere, long struct initializer
int function(int) f2 = (x) { return x + 1111; };
immutable S2 s = {
1111111111111111111, 1111111111111111111, 1111111111111111111, 1111111111111111111,
};
void f2()
{
}

29
tests/knr/issue0494.d.ref Normal file
View file

@ -0,0 +1,29 @@
void main()
{
const a1 = [
builder.rebuild!((x, y, z) => x + y + z)
.rebuild!(x => x)
.rebuild!(x => x),
];
const a2 = [
builder.rebuild!(x => x)
.rebuild!(x => x)
.rebuild!(x => x),
builder.rebuild!(x => x)
.rebuild!(x => x)
.rebuild!(x => x),
];
foo([
line1,
value_line2_bla_bla_bla.propertyCallBlaBlaBla(a, b, c)
.propertyCallBlaBlaBla(a, b, c, d).propertyCallBlaBlaBla(a, b, c)
.propertyCallBlaBlaBla(a, b, c).value,
]);
}
void foo()
{
afdsafds.asdf.flub;
}

View file

@ -0,0 +1,52 @@
private void selectMember(Args...)(Args args)
{
static if (true) {
static if (args[0]) {
} else {
}
}
if (true) {
if (args[0]) {
} else {
}
}
}
private void selectMember(Args...)(Args args)
{
static if (true) {
static if ([
0,
1,
2,
3,
4,
]) {
} else {
}
}
if (true) {
if (args[
0,
1,
2,
3,
4,
]) {
} else {
}
}
}
void f()
{
foreach (x; y)
if (foo) {
} else {
}
if (a)
if (b) {
} else {
}
}

View file

@ -0,0 +1,34 @@
void main()
{
const a1 = [
builder
.rebuild!((x, y, z) => x + y + z)
.rebuild!(x => x)
.rebuild!(x => x),
];
const a2 = [
builder
.rebuild!(x => x)
.rebuild!(x => x)
.rebuild!(x => x),
builder
.rebuild!(x => x)
.rebuild!(x => x)
.rebuild!(x => x),
];
foo([
line1,
value_line2_bla_bla_bla.propertyCallBlaBlaBla(a, b, c)
.propertyCallBlaBlaBla(a, b, c, d).propertyCallBlaBlaBla(a, b, c)
.propertyCallBlaBlaBla(a, b, c).value,
]);
}
void foo()
{
afdsafds
.asdf
.flub;
}

15
tests/knr/issue0503.d.ref Normal file
View file

@ -0,0 +1,15 @@
string f()
{
return duration.total!"seconds".to!string;
}
string g()
{
return duration.total!"seconds"().to!string;
}
string h()
{
return duration.total!"seconds"().to!string.to!string.to!string.to!string.to!string.to!string
.to!string.to!string.to!string;
}

View file

@ -0,0 +1 @@
/// Testing CR line endings. void main() { }

View file

@ -0,0 +1,4 @@
/// Testing CRLF line endings.
void main()
{
}

View file

@ -0,0 +1,4 @@
/// Testing LF line endings.
void main()
{
}

View file

@ -0,0 +1,8 @@
void f()
{
auto t = true ? 1 : 0;
auto a = [true ? 1 : 0];
auto aa1 = [0: true ? 1 : 0];
auto aa2 = [0: true ? (false ? 1 : 2) : 3];
auto aa3 = [0: true ? false ? 1 : 2 : 3];
}

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,10 @@
unittest {
f([
x
]);
}
void f(T[] x,
const U y)
{
}

View file

@ -0,0 +1,12 @@
void main(string[] args)
{
for(int i = 0; i < 10; ++i) {
if(i == 9)
break;
}
while(false) {
}
foreach(i; 0 .. 9) {
}
}

View file

@ -0,0 +1,20 @@
class C {
void f() {
if (true) {
f(map.map.map.map.map.map.map.map.map.map.map.map.map.map.map.map
.map.map.map.map.map.map, __FILE__, __FILE__, __FILE__, __FILE__, __FILE__,
__FILE__, __FILE__, __FILE__, __FILE__, __FILE__, __FILE__,
__FILE__, __FILE__, __FILE__, __FILE__, __FILE__, __LINE__);
g(map && map && map && map && map && map && map && map && map && map && map
&& map, __FILE__, __FILE__, __FILE__, __FILE__, __FILE__,
__FILE__, __FILE__, __LINE__);
h(map || map || map || map || map || map || map || map || map || map || map
|| map, __FILE__, __FILE__, __FILE__, __FILE__, __FILE__,
__FILE__, __FILE__, __LINE__);
i(map + map + map + map + map + map + map + map + map + map + map + map + map
+ map + map + map + map + map, __FILE__, __FILE__, __FILE__,
__FILE__, __FILE__, __FILE__, __FILE__, __LINE__);
}
}
}

View file

@ -0,0 +1,28 @@
class C {
void f() {
if (true) {
f(
array.map!(a => a.prop)
.array
.to!string,
__FILE__,
__LINE__);
g(
map &&
map,
__FILE__,
__LINE__);
h(
map ||
map,
__FILE__,
__LINE__);
i(
map
+ map,
__FILE__,
__LINE__);
}
}
}

View file

@ -1,6 +1,6 @@
int /*sneaky*/ foo( /*comments*/ ) /*everywhere*/ {
// comment on its own line
foo() // comment on same line
.bar(); // also on same line
.bar(); // also on same line
/* again */ // same line
}

View file

@ -0,0 +1,46 @@
static foreach (x; [
1,
2,
3,
]) {
}
static foreach_reverse (x; [
1,
2,
3,
]) {
}
void f() {
foreach (x; [
1,
2,
3,
]) {
}
foreach_reverse (x; [
1,
2,
3,
]) {
}
if (!SymbolTool.instance.workspacesFilesUris.canFind!sameFile(uri)) {
send(TextDocument.publishDiagnostics, new PublishDiagnosticsParams(uri, [
]));
}
foreach (x; map([
1,
2,
3,
])) {
}
foreach (x; foo!(map!([
1,
2,
3,
]))) {
}
}

View file

@ -0,0 +1 @@
alias u8 = ubyte

View file

@ -0,0 +1,8 @@
/* This test relies on ../.gitattributes to contain these lines:
tests/issue0228.d text eol=lf
tests/allman/issue0228.d.ref text eol=crlf
tests/knr/issue0228.d.ref text eol=crlf
tests/otbs/issue0228.d.ref text eol=crlf
*/

View file

@ -0,0 +1,36 @@
struct S1 {
ulong x;
ulong y;
ulong function(ulong) f;
}
struct S2 {
ulong x;
ulong y;
ulong z;
ulong w;
}
// -----------------------------------------------------------------------------
// Example 1
// Anonymous function in struct, long struct initializer
immutable S1 s1 = {
1111111111111111111, 1111111111111111111, (x) { return x + 1111; },
};
void f1() {
}
// -----------------------------------------------------------------------------
// Example 2
// Anonymous function anywhere, long struct initializer
int function(int) f2 = (x) { return x + 1111; };
immutable S2 s = {
1111111111111111111, 1111111111111111111, 1111111111111111111, 1111111111111111111,
};
void f2() {
}

View file

@ -0,0 +1,27 @@
void main() {
const a1 = [
builder.rebuild!((x, y, z) => x + y + z)
.rebuild!(x => x)
.rebuild!(x => x),
];
const a2 = [
builder.rebuild!(x => x)
.rebuild!(x => x)
.rebuild!(x => x),
builder.rebuild!(x => x)
.rebuild!(x => x)
.rebuild!(x => x),
];
foo([
line1,
value_line2_bla_bla_bla.propertyCallBlaBlaBla(a, b, c)
.propertyCallBlaBlaBla(a, b, c, d).propertyCallBlaBlaBla(a, b, c)
.propertyCallBlaBlaBla(a, b, c).value,
]);
}
void foo() {
afdsafds.asdf.flub;
}

View file

@ -0,0 +1,49 @@
private void selectMember(Args...)(Args args) {
static if (true) {
static if (args[0]) {
} else {
}
}
if (true) {
if (args[0]) {
} else {
}
}
}
private void selectMember(Args...)(Args args) {
static if (true) {
static if ([
0,
1,
2,
3,
4,
]) {
} else {
}
}
if (true) {
if (args[
0,
1,
2,
3,
4,
]) {
} else {
}
}
}
void f() {
foreach (x; y)
if (foo) {
} else {
}
if (a)
if (b) {
} else {
}
}

View file

@ -0,0 +1,32 @@
void main() {
const a1 = [
builder
.rebuild!((x, y, z) => x + y + z)
.rebuild!(x => x)
.rebuild!(x => x),
];
const a2 = [
builder
.rebuild!(x => x)
.rebuild!(x => x)
.rebuild!(x => x),
builder
.rebuild!(x => x)
.rebuild!(x => x)
.rebuild!(x => x),
];
foo([
line1,
value_line2_bla_bla_bla.propertyCallBlaBlaBla(a, b, c)
.propertyCallBlaBlaBla(a, b, c, d).propertyCallBlaBlaBla(a, b, c)
.propertyCallBlaBlaBla(a, b, c).value,
]);
}
void foo() {
afdsafds
.asdf
.flub;
}

View file

@ -0,0 +1,12 @@
string f() {
return duration.total!"seconds".to!string;
}
string g() {
return duration.total!"seconds"().to!string;
}
string h() {
return duration.total!"seconds"().to!string.to!string.to!string.to!string.to!string.to!string
.to!string.to!string.to!string;
}

View file

@ -0,0 +1 @@
/// Testing CR line endings. void main() { }

View file

@ -0,0 +1,3 @@
/// Testing CRLF line endings.
void main() {
}

View file

@ -0,0 +1,3 @@
/// Testing LF line endings.
void main() {
}

View file

@ -0,0 +1,7 @@
void f() {
auto t = true ? 1 : 0;
auto a = [true ? 1 : 0];
auto aa1 = [0: true ? 1 : 0];
auto aa2 = [0: true ? (false ? 1 : 2) : 3];
auto aa3 = [0: true ? false ? 1 : 2 : 3];
}

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

View file

@ -0,0 +1,9 @@
unittest {
f([
x
]);
}
void f(T[] x,
const U y) {
}

View file

@ -0,0 +1,11 @@
void main(string[] args) {
for(int i = 0; i < 10; ++i) {
if(i == 9)
break;
}
while(false) {
}
foreach(i; 0 .. 9) {
}
}

View file

@ -0,0 +1 @@
--space_after_keywords=false

View file

@ -0,0 +1,10 @@
void main(string[] args)
{
for (int i = 0; i < 10; ++i) {
if (i == 9) break;
}
while (false) {}
foreach (i; 0 .. 9) {
}
}

83
tests/test.d Executable file
View file

@ -0,0 +1,83 @@
#!/usr/bin/env rdmd
/**
Platform independent port of `test.sh`. Runs the tests in this directory.
Ignores differences in line endings, unless the test uses `--end_of_line`.
**/
import std.algorithm, std.array, std.conv, std.file, std.path, std.process;
import std.stdio, std.string, std.typecons, std.range, std.uni;
version (Windows)
enum dfmt = `..\bin\dfmt.exe`;
else
enum dfmt = `../bin/dfmt`;
int main()
{
foreach (braceStyle; ["allman", "otbs", "knr"])
foreach (entry; dirEntries(".", "*.d", SpanMode.shallow).filter!(e => e.baseName(".d") != "test"))
{
const source = entry.baseName;
const outFileName = buildPath(braceStyle, source ~ ".out");
const refFileName = buildPath(braceStyle, source ~ ".ref");
const argsFile = source.stripExtension ~ ".args";
const dfmtCommand =
[dfmt, "--brace_style=" ~ braceStyle] ~
(argsFile.exists ? readText(argsFile).split : []) ~
[source];
writeln(dfmtCommand.join(" "));
if (const result = spawnProcess(dfmtCommand, stdin, File(outFileName, "w")).wait)
return result;
if (int ret = diff(refFileName, outFileName))
return ret;
}
foreach (entry; dirEntries("expected_failures", "*.d", SpanMode.shallow))
{
string copied = entry ~ ".out.d";
copy(entry, copied);
scope (exit)
remove(copied);
if (execute([dfmt, copied, "--inplace"]).status == 0)
{
stderr.writeln("Expected failure on test ", entry, " but passed.");
return 1;
}
if (int ret = diff(entry, copied))
return ret;
}
writeln("All tests succeeded.");
return 0;
}
int diff(string refFileName, string outFileName)
{
const outText = outFileName.readText;
const refText = refFileName.readText;
const outLines = outText.splitLines(Yes.keepTerminator);
const refLines = refText.splitLines(Yes.keepTerminator);
foreach (i; 0 .. min(refLines.length, outLines.length))
if (outLines[i] != refLines[i])
{
writeln("Found difference between ", outFileName, " and ", refFileName, " on line ", i + 1, ":");
writefln("out: %(%s%)", [outLines[i]]); // Wrapping in array shows line endings.
writefln("ref: %(%s%)", [refLines[i]]);
return 1;
}
if (outLines.length < refLines.length)
{
writeln("Line ", outLines.length + 1, " in ", refFileName, " not found in ", outFileName, ":");
writefln("%(%s%)", [refLines[outLines.length]]);
return 1;
}
if (outLines.length > refLines.length)
{
writeln("Line ", outLines.length + 1, " in ", outFileName, " not present in ", refFileName, ":");
writefln("%(%s%)", [outLines[refLines.length]]);
return 1;
}
return 0;
}

Some files were not shown because too many files have changed in this diff Show more