Compare commits

..

No commits in common. "master" and "v0.12.0" have entirely different histories.

398 changed files with 504 additions and 5563 deletions

16
.gitattributes vendored
View File

@ -1,16 +0,0 @@
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

View File

@ -1,34 +0,0 @@
# 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

3
.gitmodules vendored
View File

@ -4,6 +4,3 @@
[submodule "stdx-allocator"] [submodule "stdx-allocator"]
path = stdx-allocator path = stdx-allocator
url = https://github.com/dlang-community/stdx-allocator url = https://github.com/dlang-community/stdx-allocator
[submodule "d-test-utils"]
path = d-test-utils
url = https://github.com/dlang-community/d-test-utils.git

15
.travis.sh Executable file
View File

@ -0,0 +1,15 @@
#!/bin/bash
set -e
if [[ $BUILD == dub ]]; then
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

94
.travis.yml Normal file
View File

@ -0,0 +1,94 @@
sudo: false
language: d
d:
- dmd
- ldc
os:
- linux
- osx
branches:
only:
- master
- /^v\d+\.\d+\.\d+([+-]\S*)*$/
env:
- BUILD=
- BUILD=dub
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,5 +1,4 @@
# 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 [![Build Status](https://travis-ci.org/dlang-community/dfmt.svg?branch=master)](https://travis-ci.org/dlang-community/dfmt)
**dfmt** is a formatter for D source code **dfmt** is a formatter for D source code
## Status ## Status
@ -11,7 +10,7 @@ when using the **--inplace** option.
### Installing with DUB ### Installing with DUB
```sh ```sh
> dub run dfmt -- -h > dub fetch --version='~master' dfmt && dub run dfmt -- -h
``` ```
### Building from source using Make ### Building from source using Make
@ -52,15 +51,11 @@ found there.
* `--soft_max_line_length`: *see dfmt_soft_max_line_length [below](#dfmt-specific-properties)* * `--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_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_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)* * `--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)* * `--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)* * `--tab_width`: *see tab_width [below](#standard-editorconfig-properties)*
* `--template_constraint_style`: *see dfmt_template_constraint_style [below](#dfmt-specific-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)* * `--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 ### Example
``` ```
@ -96,7 +91,7 @@ void main(string[] args)
### Standard EditorConfig properties ### Standard EditorConfig properties
Property Name | Allowed Values | Description 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) When not set, `dfmt` adopts the first line ending in the input. end_of_line | `cr`, `crlf` and **`lf`** | [See EditorConfig documentation.](https://github.com/editorconfig/editorconfig/wiki/EditorConfig-Properties#end_of_line)
insert_final_newline | **`true`** | Not supported. `dfmt` always inserts a final newline. insert_final_newline | **`true`** | Not supported. `dfmt` always inserts a final newline.
charset | **`UTF-8`** | Not supported. `dfmt` only works correctly on UTF-8. 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) indent_style | `tab`, **`space`** | [See EditorConfig documentation.](https://github.com/editorconfig/editorconfig/wiki/EditorConfig-Properties#indent_style)
@ -107,9 +102,9 @@ max_line_length | positive integers (**`120`**) | [See EditorConfig documentatio
### dfmt-specific properties ### dfmt-specific properties
Property Name | Allowed Values | Description Property Name | Allowed Values | Description
--------------|----------------|------------ --------------|----------------|------------
dfmt_brace_style | **`allman`**, `otbs`, `stroustrup` or `knr` | [See Wikipedia](https://en.wikipedia.org/wiki/Brace_style) dfmt_brace_style | **`allman`**, `otbs`, or `stroustrup` | [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_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_align_switch_statements (Not yet implemented) | **`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. dfmt_outdent_attributes (Not yet implemented) | **`true`**, `false`| Decrease the indentation level of attributes.
dfmt_split_operator_at_line_end | `true`, **`false`** | Place operators on the end of the previous line when splitting lines. dfmt_split_operator_at_line_end | `true`, **`false`** | Place operators on the end of the previous line when splitting lines.
dfmt_space_after_cast | **`true`**, `false` | Insert space after the closing paren of a `cast` expression. dfmt_space_after_cast | **`true`**, `false` | Insert space after the closing paren of a `cast` expression.
@ -120,11 +115,7 @@ dfmt_compact_labeled_statements | **`true`**, `false` | Place labels on the same
dfmt_template_constraint_style | **`conditional_newline_indent`** `conditional_newline` `always_newline` `always_newline_indent` | Control the formatting of template constraints. dfmt_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_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_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_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 ## Terminology
* Braces - `{` and `}` * Braces - `{` and `}`

112
appveyor.yml Normal file
View File

@ -0,0 +1,112 @@
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" eolOpts="lf cr crlf"
boolOpts="true false" boolOpts="true false"
braceOpts="allman otbs stroustrup knr" braceOpts="allman otbs stroustrup"
indentOpts="tab space" indentOpts="tab space"
constraintOpts="conditional_newline_indent conditional_newline always_newline always_newline_indent" constraintOpts="conditional_newline_indent conditional_newline always_newline always_newline_indent"

@ -1 +0,0 @@
Subproject commit 206a2e6abd97b4462f3a320e4f2d23986fad3cff

View File

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

@ -1 +1 @@
Subproject commit fe6d1e38fb4fc04323170389cfec67ed7fd4e24a Subproject commit 597d9a697b1f8a51fb2f441c61d0c6cc4eadc6d1

View File

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

View File

@ -63,8 +63,6 @@ struct ASTInformation
(structInfoSortedByEndLocation); (structInfoSortedByEndLocation);
sort(ufcsHintLocations); sort(ufcsHintLocations);
ufcsHintLocations = ufcsHintLocations.uniq().array(); ufcsHintLocations = ufcsHintLocations.uniq().array();
sort(ternaryColonLocations);
sort(namedArgumentColonLocations);
} }
/// Locations of end braces for struct bodies /// Locations of end braces for struct bodies
@ -97,12 +95,6 @@ struct ASTInformation
/// Closing braces of function literals /// Closing braces of function literals
size_t[] funLitEndLocations; size_t[] funLitEndLocations;
/// Locations of aggregate bodies (struct, class, union)
size_t[] aggregateBodyLocations;
/// Locations of function bodies
size_t[] funBodyLocations;
/// Conditional statements that have matching "else" statements /// Conditional statements that have matching "else" statements
size_t[] conditionalWithElseLocations; size_t[] conditionalWithElseLocations;
@ -137,12 +129,6 @@ struct ASTInformation
/// Opening & closing braces of struct initializers /// Opening & closing braces of struct initializers
StructInitializerInfo[] structInfoSortedByEndLocation; 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 /// Collects information from the AST that is useful for the formatter
@ -214,18 +200,6 @@ final class FormatVisitor : ASTVisitor
destructor.accept(this); destructor.accept(this);
} }
override void visit (const FunctionBody functionBody)
{
if (auto bd = functionBody.specifiedFunctionBody)
{
if (bd.blockStatement)
{
astInformation.funBodyLocations ~= bd.blockStatement.startLocation;
}
}
functionBody.accept(this);
}
override void visit(const ConditionalDeclaration dec) override void visit(const ConditionalDeclaration dec)
{ {
if (dec.hasElse) if (dec.hasElse)
@ -339,7 +313,6 @@ final class FormatVisitor : ASTVisitor
override void visit(const StructBody structBody) override void visit(const StructBody structBody)
{ {
astInformation.aggregateBodyLocations ~= structBody.startLocation;
astInformation.doubleNewlineLocations ~= structBody.endLocation; astInformation.doubleNewlineLocations ~= structBody.endLocation;
structBody.accept(this); structBody.accept(this);
} }
@ -446,58 +419,6 @@ final class FormatVisitor : ASTVisitor
outStatement.accept(this); outStatement.accept(this);
} }
override void visit(const TernaryExpression ternaryExpression)
{
astInformation.ternaryColonLocations ~= ternaryExpression.colon.index;
ternaryExpression.accept(this);
}
override void visit(const FunctionCallExpression functionCall)
{
visit(functionCall.arguments);
functionCall.accept(this);
}
override void visit(const NewExpression newCall)
{
visit(newCall.arguments);
newCall.accept(this);
}
override void visit(const NewAnonClassExpression newAnonClassCall)
{
visit(newAnonClassCall.constructorArguments);
newAnonClassCall.accept(this);
}
private void visit(const Arguments arguments)
{
// Check if call has any arguments.
if (!arguments || arguments.namedArgumentList is null)
{
return;
}
foreach (item; 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;
}
}
}
}
private: private:
ASTInformation* astInformation; ASTInformation* astInformation;
} }

View File

@ -10,20 +10,18 @@ import dfmt.editorconfig;
/// Brace styles /// Brace styles
enum BraceStyle enum BraceStyle
{ {
_unspecified, unspecified,
/// $(LINK https://en.wikipedia.org/wiki/Indent_style#Allman_style) /// $(LINK https://en.wikipedia.org/wiki/Indent_style#Allman_style)
allman, allman,
/// $(LINK https://en.wikipedia.org/wiki/Indent_style#Variant:_1TBS) /// $(LINK https://en.wikipedia.org/wiki/Indent_style#Variant:_1TBS)
otbs, otbs,
/// $(LINK https://en.wikipedia.org/wiki/Indent_style#Variant:_Stroustrup) /// $(LINK https://en.wikipedia.org/wiki/Indent_style#Variant:_Stroustrup)
stroustrup, stroustrup
/// $(LINK https://en.wikipedia.org/wiki/Indentation_style#K&R_style)
knr,
} }
enum TemplateConstraintStyle enum TemplateConstraintStyle
{ {
_unspecified, unspecified,
conditional_newline_indent, conditional_newline_indent,
conditional_newline, conditional_newline,
always_newline, always_newline,
@ -61,14 +59,6 @@ struct Config
OptionalBoolean dfmt_space_before_aa_colon; OptionalBoolean dfmt_space_before_aa_colon;
/// ///
OptionalBoolean dfmt_keep_line_breaks; 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; mixin StandardEditorConfigFields;
@ -79,7 +69,7 @@ struct Config
void initializeWithDefaults() void initializeWithDefaults()
{ {
pattern = "*.d"; pattern = "*.d";
end_of_line = EOL._default; end_of_line = EOL.lf;
indent_style = IndentStyle.space; indent_style = IndentStyle.space;
indent_size = 4; indent_size = 4;
tab_width = 4; tab_width = 4;
@ -98,9 +88,6 @@ struct Config
dfmt_single_template_constraint_indent = OptionalBoolean.f; dfmt_single_template_constraint_indent = OptionalBoolean.f;
dfmt_space_before_aa_colon = OptionalBoolean.f; dfmt_space_before_aa_colon = OptionalBoolean.f;
dfmt_keep_line_breaks = 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,22 +26,21 @@ private auto commentRe = ctRegex!(`^\s*[#;].*$`);
enum OptionalBoolean : ubyte enum OptionalBoolean : ubyte
{ {
_unspecified = 3, unspecified = 3,
t = 1, t = 1,
f = 0 f = 0
} }
enum IndentStyle : ubyte enum IndentStyle : ubyte
{ {
_unspecified, unspecified,
tab, tab,
space space
} }
enum EOL : ubyte enum EOL : ubyte
{ {
_unspecified, unspecified,
_default,
lf, lf,
cr, cr,
crlf crlf
@ -75,7 +74,7 @@ mixin template StandardEditorConfigFields()
static if (N == "pattern") static if (N == "pattern")
continue; continue;
else static if (is(T == enum)) else static if (is(T == enum))
*thisN = otherN != T._unspecified ? otherN : *thisN; *thisN = otherN != T.unspecified ? otherN : *thisN;
else static if (is(T == int)) else static if (is(T == int))
*thisN = otherN != -1 ? otherN : *thisN; *thisN = otherN != -1 ? otherN : *thisN;
else static if (is(T == string)) else static if (is(T == string))

View File

@ -9,13 +9,12 @@ module dfmt.formatter;
import dparse.lexer; import dparse.lexer;
import dparse.parser; import dparse.parser;
import dparse.rollback_allocator; import dparse.rollback_allocator;
import dfmt.ast_info;
import dfmt.config; import dfmt.config;
import dfmt.ast_info;
import dfmt.indentation; import dfmt.indentation;
import dfmt.tokens; import dfmt.tokens;
import dfmt.wrapping; import dfmt.wrapping;
import std.array; import std.array;
import std.algorithm.comparison : among, max;
/** /**
* Formats the code contained in `buffer` into `output`. * Formats the code contained in `buffer` into `output`.
@ -111,7 +110,6 @@ struct TokenFormatter(OutputRange)
this.output = output; this.output = output;
this.astInformation = astInformation; this.astInformation = astInformation;
this.config = config; this.config = config;
this.indents = IndentStack(config);
{ {
auto eol = config.end_of_line; auto eol = config.end_of_line;
@ -121,13 +119,8 @@ struct TokenFormatter(OutputRange)
this.eolString = "\n"; this.eolString = "\n";
else if (eol == eol.crlf) else if (eol == eol.crlf)
this.eolString = "\r\n"; this.eolString = "\r\n";
else if (eol == eol._unspecified) else if (eol == eol.unspecified)
assert(false, "config.end_of_line was unspecified"); assert(false, "config.end_of_line was unspecified");
else
{
assert (eol == eol._default);
this.eolString = eolStringFromInput;
}
} }
} }
@ -201,22 +194,6 @@ private:
/// True if the next "else" should be formatted as a single line /// True if the next "else" should be formatted as a single line
bool inlineElse; 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() void formatStep()
{ {
import std.range : assumeSorted; import std.range : assumeSorted;
@ -234,9 +211,7 @@ private:
{ {
immutable t = tokens[index].type; immutable t = tokens[index].type;
if (t == tok!"identifier" || isStringLiteral(t) if (t == tok!"identifier" || isStringLiteral(t)
|| isNumberLiteral(t) || t == tok!"characterLiteral" || isNumberLiteral(t) || t == tok!"characterLiteral")
// a!"b" function()
|| t == tok!"function" || t == tok!"delegate")
write(" "); write(" ");
} }
} }
@ -247,9 +222,7 @@ private:
else if (currentIs(tok!"return")) else if (currentIs(tok!"return"))
{ {
writeToken(); writeToken();
if (hasCurrent && (!currentIs(tok!";") && !currentIs(tok!")") && !currentIs(tok!"{") if (!currentIs(tok!";") && !currentIs(tok!")"))
&& !currentIs(tok!"in") && !currentIs(tok!"out") && !currentIs(tok!"do")
&& tokens[index].text != "body"))
write(" "); write(" ");
} }
else if (currentIs(tok!"with")) else if (currentIs(tok!"with"))
@ -257,21 +230,17 @@ private:
if (indents.length == 0 || !indents.topIsOneOf(tok!"switch", tok!"with")) if (indents.length == 0 || !indents.topIsOneOf(tok!"switch", tok!"with"))
indents.push(tok!"with"); indents.push(tok!"with");
writeToken(); writeToken();
if (config.dfmt_space_after_keywords) {
write(" "); write(" ");
} if (currentIs(tok!"("))
if (hasCurrent && currentIs(tok!"("))
writeParens(false); writeParens(false);
if (hasCurrent && !currentIs(tok!"switch") && !currentIs(tok!"with") if (!currentIs(tok!"switch") && !currentIs(tok!"with")
&& !currentIs(tok!"{") && !(currentIs(tok!"final") && peekIs(tok!"switch"))) && !currentIs(tok!"{") && !(currentIs(tok!"final") && peekIs(tok!"switch")))
{ {
newline(); newline();
} }
else if (hasCurrent && !currentIs(tok!"{")) else if (!currentIs(tok!"{"))
{
write(" "); write(" ");
} }
}
else if (currentIs(tok!"switch")) else if (currentIs(tok!"switch"))
{ {
formatSwitch(); formatSwitch();
@ -301,10 +270,6 @@ private:
else else
formatBlockHeader(); formatBlockHeader();
} }
else if ((current.text == "body" || current == tok!"do") && peekBackIsFunctionDeclarationEnding())
{
formatKeyword();
}
else if (currentIs(tok!"do")) else if (currentIs(tok!"do"))
{ {
formatBlockHeader(); formatBlockHeader();
@ -352,10 +317,14 @@ private:
inlineElse = true; inlineElse = true;
formatKeyword(); formatKeyword();
} }
else if (current.text == "body" && peekBackIsFunctionDeclarationEnding())
{
formatKeyword();
}
else if (isBasicType(current.type)) else if (isBasicType(current.type))
{ {
writeToken(); writeToken();
if (hasCurrent && (currentIs(tok!"identifier") || isKeyword(current.type) || inAsm)) if (currentIs(tok!"identifier") || isKeyword(current.type) || inAsm)
write(" "); write(" ");
} }
else if (isOperator(current.type)) else if (isOperator(current.type))
@ -396,7 +365,7 @@ private:
import dfmt.editorconfig : OB = OptionalBoolean; 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:
assert(false, "Config was not validated properly"); assert(false, "Config was not validated properly");
case conditional_newline: case conditional_newline:
immutable l = currentLineLength + betweenParenLength(tokens[index + 1 .. $]); immutable l = currentLineLength + betweenParenLength(tokens[index + 1 .. $]);
@ -503,9 +472,6 @@ private:
if (peekIs(tok!"(") && (peekBackIs(tok!")") || peekBack2Is(tok!"!"))) if (peekIs(tok!"(") && (peekBackIs(tok!")") || peekBack2Is(tok!"!")))
pushWrapIndent(tok!"("); pushWrapIndent(tok!"(");
if (peekIs(tok!".") && !indents.topIs(tok!"."))
indents.push(tok!".");
} }
writeToken(); writeToken();
immutable j = justAddedExtraNewline; immutable j = justAddedExtraNewline;
@ -625,7 +591,6 @@ private:
writeToken(); writeToken();
if (p == tok!"(") if (p == tok!"(")
{ {
++parenDepthOnLine;
// If the file starts with an open paren, just give up. This isn't // If the file starts with an open paren, just give up. This isn't
// valid D code. // valid D code.
if (index < 2) if (index < 2)
@ -643,10 +608,23 @@ private:
immutable bool arrayInitializerStart = p == tok!"[" immutable bool arrayInitializerStart = p == tok!"["
&& astInformation.arrayStartLocations.canFindIndex(tokens[index - 1].index); && astInformation.arrayStartLocations.canFindIndex(tokens[index - 1].index);
if (arrayInitializerStart && isMultilineAt(index - 1)) if (p == tok!"[" && config.dfmt_keep_line_breaks == OptionalBoolean.t)
{ {
revertParenIndentation(); IndentStack.Details detail;
detail.wrap = false;
detail.temp = false;
detail.breakEveryItem = false;
detail.mini = tokens[index].line == tokens[index - 1].line;
indents.push(tok!"]", detail);
if (!detail.mini)
{
newline();
}
}
else if (arrayInitializerStart && isMultilineAt(index - 1))
{
// Use the close bracket as the indent token to distinguish // Use the close bracket as the indent token to distinguish
// the array initialiazer from an array index in the newline // the array initialiazer from an array index in the newline
// handling code // handling code
@ -667,22 +645,6 @@ private:
linebreakHints = chooseLineBreakTokens(index, tokens[index .. j], linebreakHints = chooseLineBreakTokens(index, tokens[index .. j],
depths[index .. j], config, currentLineLength, indentLevel); depths[index .. j], config, currentLineLength, indentLevel);
} }
else if (p == tok!"[" && config.dfmt_keep_line_breaks == OptionalBoolean.t)
{
revertParenIndentation();
IndentStack.Details detail;
detail.wrap = false;
detail.temp = false;
detail.breakEveryItem = false;
detail.mini = tokens[index].line == tokens[index - 1].line;
indents.push(tok!"]", detail);
if (!detail.mini)
{
newline();
}
}
else if (arrayInitializerStart) else if (arrayInitializerStart)
{ {
// This is a short (non-breaking) array/AA value // This is a short (non-breaking) array/AA value
@ -722,24 +684,6 @@ 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() void formatRightParen()
in in
{ {
@ -747,15 +691,12 @@ private:
} }
do do
{ {
parenDepthOnLine = max(parenDepthOnLine - 1, 0);
parenDepth--; parenDepth--;
indents.popWrapIndents(); indents.popWrapIndents();
while (indents.topIsOneOf(tok!"!", tok!")")) while (indents.topIsOneOf(tok!"!", tok!")"))
indents.pop(); indents.pop();
if (indents.topIs(tok!"(")) if (indents.topIs(tok!"("))
indents.pop(); indents.pop();
if (indents.topIs(tok!"."))
indents.pop();
if (onNextLine) if (onNextLine)
{ {
@ -770,13 +711,13 @@ private:
{ {
writeToken(); writeToken();
if (spaceAfterParens || parenDepth > 0) if (spaceAfterParens || parenDepth > 0)
writeSpace(); write(" ");
} }
else if ((peekIsKeyword() || peekIs(tok!"@")) && spaceAfterParens else if ((peekIsKeyword() || peekIs(tok!"@")) && spaceAfterParens
&& !peekIs(tok!"in") && !peekIs(tok!"is") && !peekIs(tok!"if")) && !peekIs(tok!"in") && !peekIs(tok!"is") && !peekIs(tok!"if"))
{ {
writeToken(); writeToken();
writeSpace(); write(" ");
} }
else else
writeToken(); writeToken();
@ -822,12 +763,18 @@ private:
} }
else if (hasCurrent && (currentIs(tok!"@") else if (hasCurrent && (currentIs(tok!"@")
|| isBasicType(tokens[index].type) || isBasicType(tokens[index].type)
|| currentIs(tok!"invariant")
|| currentIs(tok!"extern") || currentIs(tok!"extern")
|| currentIs(tok!"identifier")) || currentIs(tok!"identifier"))
&& !currentIsIndentedTemplateConstraint()) && !currentIsIndentedTemplateConstraint())
{ {
writeSpace(); if (onNextLine)
{
newline();
}
else
{
write(" ");
}
} }
} }
@ -835,13 +782,12 @@ private:
{ {
import dfmt.editorconfig : OptionalBoolean; import dfmt.editorconfig : OptionalBoolean;
import std.algorithm : canFind, any; import std.algorithm : canFind, any;
immutable bool isCase = astInformation.caseEndLocations.canFindIndex(current.index); immutable bool isCase = astInformation.caseEndLocations.canFindIndex(current.index);
immutable bool isAttribute = astInformation.attributeDeclarationLines.canFindIndex( immutable bool isAttribute = astInformation.attributeDeclarationLines.canFindIndex(
current.line); current.line);
immutable bool isStructInitializer = astInformation.structInfoSortedByEndLocation immutable bool isStructInitializer = astInformation.structInfoSortedByEndLocation
.canFind!(st => st.startLocation < current.index && current.index < st.endLocation); .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) if (isCase || isAttribute)
{ {
@ -857,17 +803,6 @@ private:
newline(); newline();
} }
} }
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") else if (peekBackIs(tok!"identifier")
&& [tok!"{", tok!"}", tok!";", tok!":", tok!","] && [tok!"{", tok!"}", tok!";", tok!":", tok!","]
.any!((ptrdiff_t token) => peekBack2Is(cast(IdType)token, true)) .any!((ptrdiff_t token) => peekBack2Is(cast(IdType)token, true))
@ -901,6 +836,11 @@ private:
} }
else else
{ {
const inAA = indents.topIs(tok!"]") && indents.topDetails.breakEveryItem;
if (inAA && !config.dfmt_space_before_aa_colon)
write(": ");
else
write(" : "); write(" : ");
index++; index++;
} }
@ -1025,10 +965,6 @@ private:
if (config.dfmt_brace_style == BraceStyle.allman if (config.dfmt_brace_style == BraceStyle.allman
|| peekBackIsOneOf(true, tok!"{", tok!"}")) || peekBackIsOneOf(true, tok!"{", tok!"}"))
newline(); newline();
else if (config.dfmt_brace_style == BraceStyle.knr
&& astInformation.funBodyLocations.canFindIndex(tIndex)
&& (peekBackIs(tok!")") || (!peekBackIs(tok!"do") && peekBack().text != "body")))
newline();
else if (!peekBackIsOneOf(true, tok!"{", tok!"}", tok!";")) else if (!peekBackIsOneOf(true, tok!"{", tok!"}", tok!";"))
write(" "); write(" ");
writeToken(); writeToken();
@ -1060,21 +996,6 @@ private:
if (niBraceDepth > 0) if (niBraceDepth > 0)
niBraceDepth--; 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]; auto indentInfo = astInformation.indentInfoSortedByEndLocation[pos];
if (indentInfo.flags & BraceIndentInfoFlags.tempIndent) if (indentInfo.flags & BraceIndentInfoFlags.tempIndent)
{ {
@ -1112,7 +1033,7 @@ private:
currentLineLength = 0; currentLineLength = 0;
justAddedExtraNewline = true; justAddedExtraNewline = true;
} }
if (config.dfmt_brace_style.among(BraceStyle.otbs, BraceStyle.knr) if (config.dfmt_brace_style == BraceStyle.otbs
&& ((peekIs(tok!"else") && ((peekIs(tok!"else")
&& !indents.topAre(tok!"static", tok!"if") && !indents.topAre(tok!"static", tok!"if")
&& !indents.topIs(tok!"foreach") && !indents.topIs(tok!"for") && !indents.topIs(tok!"foreach") && !indents.topIs(tok!"for")
@ -1144,11 +1065,8 @@ private:
indents.pop(); indents.pop();
indents.push(tok!"switch"); indents.push(tok!"switch");
writeToken(); // switch writeToken(); // switch
if (config.dfmt_space_after_keywords)
{
write(" "); write(" ");
} }
}
void formatBlockHeader() void formatBlockHeader()
{ {
@ -1177,27 +1095,17 @@ private:
writeToken(); writeToken();
if (currentIs(tok!"(")) if (currentIs(tok!"("))
{
if (config.dfmt_space_after_keywords)
{ {
write(" "); write(" ");
}
writeParens(false); writeParens(false);
} }
if (hasCurrent) if (hasCurrent)
{ {
if (currentIs(tok!"switch") || (currentIs(tok!"final") && peekIs(tok!"switch"))) if (currentIs(tok!"switch") || (currentIs(tok!"final") && peekIs(tok!"switch")))
{
if (config.dfmt_space_after_keywords)
{
write(" "); write(" ");
}
}
else if (currentIs(tok!"comment")) else if (currentIs(tok!"comment"))
{
formatStep(); formatStep();
}
else if (!shouldPushIndent) else if (!shouldPushIndent)
{ {
if (!currentIs(tok!"{") && !currentIs(tok!";")) if (!currentIs(tok!"{") && !currentIs(tok!";"))
@ -1278,26 +1186,24 @@ private:
break; break;
case tok!"cast": case tok!"cast":
writeToken(); writeToken();
if (hasCurrent && currentIs(tok!"(")) if (currentIs(tok!"("))
writeParens(config.dfmt_space_after_cast == OptionalBoolean.t); writeParens(config.dfmt_space_after_cast == OptionalBoolean.t);
break; break;
case tok!"out": case tok!"out":
if (!peekBackIsSlashSlash) {
if (!peekBackIs(tok!"}") if (!peekBackIs(tok!"}")
&& astInformation.contractLocations.canFindIndex(current.index)) && astInformation.contractLocations.canFindIndex(current.index))
newline(); newline();
else if (peekBackIsKeyword) else if (peekBackIsKeyword)
write(" "); write(" ");
}
writeToken(); writeToken();
if (hasCurrent && !currentIs(tok!"{") && !currentIs(tok!"comment")) if (!currentIs(tok!"{") && !currentIs(tok!"comment"))
write(" "); write(" ");
break; break;
case tok!"try": case tok!"try":
case tok!"finally": case tok!"finally":
indents.push(current.type); indents.push(current.type);
writeToken(); writeToken();
if (hasCurrent && !currentIs(tok!"{")) if (!currentIs(tok!"{"))
newline(); newline();
break; break;
case tok!"identifier": case tok!"identifier":
@ -1312,7 +1218,6 @@ private:
break; break;
case tok!"in": case tok!"in":
immutable isContract = astInformation.contractLocations.canFindIndex(current.index); immutable isContract = astInformation.contractLocations.canFindIndex(current.index);
if (!peekBackIsSlashSlash) {
if (isContract) if (isContract)
{ {
indents.popTempIndents(); indents.popTempIndents();
@ -1320,10 +1225,7 @@ private:
} }
else if (!peekBackIsOneOf(false, tok!"(", tok!",", tok!"!")) else if (!peekBackIsOneOf(false, tok!"(", tok!",", tok!"!"))
write(" "); write(" ");
}
writeToken(); writeToken();
if (!hasCurrent)
return;
immutable isFunctionLit = astInformation.funLitStartLocations.canFindIndex( immutable isFunctionLit = astInformation.funLitStartLocations.canFindIndex(
current.index); current.index);
if (isFunctionLit && config.dfmt_brace_style == BraceStyle.allman) if (isFunctionLit && config.dfmt_brace_style == BraceStyle.allman)
@ -1336,12 +1238,12 @@ private:
tok!"}", tok!"=", tok!"&&", tok!"||") && !peekBackIsKeyword()) tok!"}", tok!"=", tok!"&&", tok!"||") && !peekBackIsKeyword())
write(" "); write(" ");
writeToken(); writeToken();
if (hasCurrent && !currentIs(tok!"(") && !currentIs(tok!"{") && !currentIs(tok!"comment")) if (!currentIs(tok!"(") && !currentIs(tok!"{") && !currentIs(tok!"comment"))
write(" "); write(" ");
break; break;
case tok!"case": case tok!"case":
writeToken(); writeToken();
if (hasCurrent && !currentIs(tok!";")) if (!currentIs(tok!";"))
write(" "); write(" ");
break; break;
case tok!"enum": case tok!"enum":
@ -1355,7 +1257,7 @@ private:
write(" "); write(" ");
indents.push(tok!"enum"); indents.push(tok!"enum");
writeToken(); writeToken();
if (hasCurrent && !currentIs(tok!":") && !currentIs(tok!"{")) if (!currentIs(tok!":") && !currentIs(tok!"{"))
write(" "); write(" ");
} }
break; break;
@ -1379,13 +1281,20 @@ private:
goto default; goto default;
case tok!"invariant": case tok!"invariant":
writeToken(); writeToken();
if (hasCurrent && currentIs(tok!"(")) if (currentIs(tok!"("))
write(" "); write(" ");
break; break;
default: default:
if (peekBackIs(tok!"identifier")) if (peekBackIs(tok!"identifier"))
{ {
writeSpace(); if (onNextLine)
{
newline();
}
else
{
write(" ");
}
} }
if (index + 1 < tokens.length) if (index + 1 < tokens.length)
{ {
@ -1399,7 +1308,14 @@ private:
writeToken(); writeToken();
if (!currentIsIndentedTemplateConstraint()) if (!currentIsIndentedTemplateConstraint())
{ {
writeSpace(); if (onNextLine)
{
newline();
}
else
{
write(" ");
}
} }
} }
} }
@ -1503,16 +1419,13 @@ private:
break; break;
case tok!".": case tok!".":
regenLineBreakHintsIfNecessary(index); regenLineBreakHintsIfNecessary(index);
immutable bool ufcsWrap = config.dfmt_reflow_property_chains == OptionalBoolean.t immutable bool ufcsWrap = astInformation.ufcsHintLocations.canFindIndex(current.index);
&& astInformation.ufcsHintLocations.canFindIndex(current.index);
if (ufcsWrap || linebreakHints.canFind(index) || onNextLine if (ufcsWrap || linebreakHints.canFind(index) || onNextLine
|| (linebreakHints.length == 0 && currentLineLength + nextTokenLength() > config.max_line_length)) || (linebreakHints.length == 0 && currentLineLength + nextTokenLength() > config.max_line_length))
{ {
if (!indents.topIs(tok!".")) pushWrapIndent();
indents.push(tok!".");
if (!peekBackIs(tok!"comment"))
newline(); newline();
if (ufcsWrap || onNextLine) if (ufcsWrap)
regenLineBreakHints(index); regenLineBreakHints(index);
} }
writeToken(); writeToken();
@ -1573,7 +1486,6 @@ private:
{ {
if (!indents.topIs(tok!"enum")) if (!indents.topIs(tok!"enum"))
pushWrapIndent(); pushWrapIndent();
if (!peekBackIs(tok!"comment"))
newline(); newline();
} }
else else
@ -1589,7 +1501,6 @@ private:
if (rightOperandLine > operatorLine) if (rightOperandLine > operatorLine)
{ {
if (!peekBackIs(tok!"comment"))
newline(); newline();
} }
else else
@ -1673,10 +1584,6 @@ private:
const commaLine = tokens[index].line; const commaLine = tokens[index].line;
writeToken(); writeToken();
if (indents.topIsWrap && !indents.topIs(tok!","))
{
indents.pop;
}
if (!currentIs(tok!")") && !currentIs(tok!"]") if (!currentIs(tok!")") && !currentIs(tok!"]")
&& !currentIs(tok!"}") && !currentIs(tok!"comment")) && !currentIs(tok!"}") && !currentIs(tok!"comment"))
{ {
@ -1695,10 +1602,6 @@ private:
{ {
pushWrapIndent(); pushWrapIndent();
writeToken(); writeToken();
if (indents.topIsWrap && !indents.topIs(tok!","))
{
indents.pop;
}
newline(); newline();
} }
else else
@ -1717,21 +1620,16 @@ private:
{ {
import std.range : assumeSorted; import std.range : assumeSorted;
import std.algorithm.comparison : min; import std.algorithm.comparison : min;
import std.algorithm.searching : canFind, countUntil; import std.algorithm.searching : countUntil;
// The end of the tokens considered by the line break algorithm is // The end of the tokens considered by the line break algorithm is
// either the expression end index or the next mandatory line break // either the expression end index or the next mandatory line break,
// or a newline inside a string literal, whichever is first. // whichever is first.
auto r = assumeSorted(astInformation.ufcsHintLocations).upperBound(tokens[i].index); auto r = assumeSorted(astInformation.ufcsHintLocations).upperBound(tokens[i].index);
immutable ufcsBreakLocation = r.empty immutable ufcsBreakLocation = r.empty
? size_t.max ? size_t.max
: tokens[i .. $].countUntil!(t => t.index == r.front) + i; : tokens[i .. $].countUntil!(t => t.index == r.front) + i;
immutable multilineStringLocation = tokens[i .. $] immutable size_t j = min(expressionEndIndex(i), ufcsBreakLocation);
.countUntil!(t => t.text.canFind('\n'));
immutable size_t j = min(
expressionEndIndex(i),
ufcsBreakLocation,
multilineStringLocation == -1 ? size_t.max : multilineStringLocation + i + 1);
// 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;
@ -1783,8 +1681,6 @@ private:
if (hasCurrent) if (hasCurrent)
{ {
const isNamedArg = index + 1 < tokens.length
&& astInformation.namedArgumentColonLocations.canFindIndex(tokens[index + 1].index);
if (currentIs(tok!"else")) if (currentIs(tok!"else"))
{ {
immutable i = indents.indentToMostRecent(tok!"if"); immutable i = indents.indentToMostRecent(tok!"if");
@ -1793,7 +1689,7 @@ private:
if (mostRecent != -1) if (mostRecent != -1)
indentLevel = mostRecent; indentLevel = mostRecent;
} }
else if (currentIs(tok!"identifier") && peekIs(tok!":") && !isNamedArg) else if (currentIs(tok!"identifier") && peekIs(tok!":"))
{ {
if (peekBackIs(tok!"}", true) || peekBackIs(tok!";", true)) if (peekBackIs(tok!"}", true) || peekBackIs(tok!";", true))
indents.popTempIndents(); indents.popTempIndents();
@ -1806,8 +1702,8 @@ private:
assert(l2 != -1, "Recent '{' is not found despite being in struct initializer"); assert(l2 != -1, "Recent '{' is not found despite being in struct initializer");
indentLevel = l2 + 1; indentLevel = l2 + 1;
} }
else if ((config.dfmt_compact_labeled_statements == OptionalBoolean.f else if (config.dfmt_compact_labeled_statements == OptionalBoolean.f
|| !isBlockHeader(2) || peek2Is(tok!"if")) && !indents.topIs(tok!"]")) || !isBlockHeader(2) || peek2Is(tok!"if"))
{ {
immutable l2 = indents.indentToMostRecent(tok!"{"); immutable l2 = indents.indentToMostRecent(tok!"{");
indentLevel = l2 != -1 ? l2 : indents.indentLevel - 1; indentLevel = l2 != -1 ? l2 : indents.indentLevel - 1;
@ -1817,14 +1713,7 @@ private:
} }
else if (currentIs(tok!"case") || currentIs(tok!"default")) else if (currentIs(tok!"case") || currentIs(tok!"default"))
{ {
if (peekBackIs(tok!"}", true) || peekBackIs(tok!";", true))
if (peekBackIs(tok!"}", true) || peekBackIs(tok!";", true)
/**
* The following code is valid and should be indented flatly
* case A:
* case B:
*/
|| peekBackIs(tok!":", true))
{ {
indents.popTempIndents(); indents.popTempIndents();
if (indents.topIs(tok!"case")) if (indents.topIs(tok!"case"))
@ -1877,19 +1766,7 @@ private:
if (indents.topIs(tok!"]")) if (indents.topIs(tok!"]"))
{ {
indents.pop(); indents.pop();
}
// 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; indentLevel = indents.indentLevel;
while (savedIndents.length > 0) {
indents.push(savedIndents.top, savedIndents.topDetails);
savedIndents.pop;
} }
} }
else if (astInformation.attributeDeclarationLines.canFindIndex(current.line)) else if (astInformation.attributeDeclarationLines.canFindIndex(current.line))
@ -1920,7 +1797,6 @@ private:
} }
indent(); indent();
} }
parenDepthOnLine = 0;
} }
void write(string str) void write(string str)
@ -1933,8 +1809,6 @@ private:
{ {
import std.range:retro; import std.range:retro;
import std.algorithm.searching:countUntil; import std.algorithm.searching:countUntil;
import std.algorithm.iteration:joiner;
import std.string:lineSplitter;
if (current.text is null) if (current.text is null)
{ {
@ -1944,18 +1818,19 @@ private:
} }
else else
{ {
output.put(current.text.lineSplitter.joiner(eolString)); // 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);
switch (current.type) switch (current.type)
{ {
case tok!"stringLiteral": case tok!"stringLiteral":
case tok!"wstringLiteral": case tok!"wstringLiteral":
case tok!"dstringLiteral": case tok!"dstringLiteral":
immutable o = current.text.retro().countUntil('\n'); immutable o = current.text.retro().countUntil('\n');
if (o == -1) { currentLineLength += o == -1 ? current.text.length : o;
currentLineLength += current.text.length;
} else {
currentLineLength = cast(uint) o;
}
break; break;
default: default:
currentLineLength += current.text.length; currentLineLength += current.text.length;
@ -2050,18 +1925,6 @@ private:
indents.push(type, detail); indents.push(type, detail);
} }
void writeSpace()
{
if (onNextLine)
{
newline();
}
else
{
write(" ");
}
}
const pure @safe @nogc: const pure @safe @nogc:
size_t expressionEndIndex(size_t i, bool matchComma = false) nothrow size_t expressionEndIndex(size_t i, bool matchComma = false) nothrow

View File

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

View File

@ -5,8 +5,6 @@
module dfmt.indentation; module dfmt.indentation;
import dfmt.config;
import dfmt.editorconfig;
import dparse.lexer; import dparse.lexer;
import std.bitmanip : bitfields; import std.bitmanip : bitfields;
@ -33,14 +31,6 @@ bool isTempIndent(IdType type) pure nothrow @nogc @safe
*/ */
struct IndentStack struct IndentStack
{ {
/// Configuration
private const Config* config;
this(const Config* config)
{
this.config = config;
}
static struct Details static struct Details
{ {
mixin(bitfields!( mixin(bitfields!(
@ -231,7 +221,7 @@ struct IndentStack
/** /**
* Dumps the current state of the indentation stack to `stderr`. Used for debugging. * Dumps the current state of the indentation stack to `stderr`. Used for debugging.
*/ */
void dump(size_t pos = size_t.max, string file = __FILE__, uint line = __LINE__) const void dump(size_t pos = size_t.max, string file = __FILE__, uint line = __LINE__)
{ {
import dparse.lexer : str; import dparse.lexer : str;
import std.algorithm.iteration : map; import std.algorithm.iteration : map;
@ -270,20 +260,8 @@ private:
if (i + 1 < index) if (i + 1 < index)
{ {
if (config.dfmt_single_indent == OptionalBoolean.t && skipDoubleIndent(i, parenCount))
{
parenCount = pc;
continue;
}
immutable currentIsNonWrapTemp = !details[i].wrap immutable currentIsNonWrapTemp = !details[i].wrap
&& details[i].temp && arr[i] != tok!")" && arr[i] != tok!"!"; && details[i].temp && arr[i] != tok!")" && arr[i] != tok!"!";
if (currentIsNonWrapTemp && arr[i + 1] == tok!"]")
{
parenCount = pc;
continue;
}
if (arr[i] == tok!"static" if (arr[i] == tok!"static"
&& arr[i + 1].among!(tok!"if", tok!"else", tok!"foreach", tok!"foreach_reverse") && arr[i + 1].among!(tok!"if", tok!"else", tok!"foreach", tok!"foreach_reverse")
&& (i + 2 >= index || arr[i + 2] != tok!"{")) && (i + 2 >= index || arr[i + 2] != tok!"{"))
@ -298,7 +276,7 @@ private:
continue; continue;
} }
} }
else if (parenCount == 0 && arr[i] == tok!"(" && config.dfmt_single_indent == OptionalBoolean.f) else if (parenCount == 0 && arr[i] == tok!"(")
size++; size++;
if (arr[i] == tok!"!") if (arr[i] == tok!"!")
@ -309,12 +287,6 @@ private:
} }
return size; return size;
} }
bool skipDoubleIndent(size_t i, int parenCount) const pure nothrow @safe @nogc
{
return (details[i + 1].wrap && arr[i] == tok!")")
|| (parenCount == 0 && arr[i + 1] == tok!"," && arr[i] == tok!"(");
}
} }
unittest unittest

View File

@ -38,13 +38,13 @@ version (NoMain)
} }
else else
{ {
import std.array : front, popFront;
import std.stdio : stdout, stdin, stderr, writeln, File;
import dfmt.config : Config; import dfmt.config : Config;
import dfmt.editorconfig : getConfigFor;
import dfmt.formatter : format; import dfmt.formatter : format;
import std.array : appender, front, popFront;
import std.getopt : getopt, GetOptException;
import std.path : buildPath, dirName, expandTilde; import std.path : buildPath, dirName, expandTilde;
import std.stdio : File, stderr, stdin, stdout, writeln; import dfmt.editorconfig : getConfigFor;
import std.getopt : getopt, GetOptException;
int main(string[] args) int main(string[] args)
{ {
@ -92,21 +92,9 @@ else
case "space_before_aa_colon": case "space_before_aa_colon":
optConfig.dfmt_space_before_aa_colon = optVal; optConfig.dfmt_space_before_aa_colon = optVal;
break; break;
case "space_before_named_arg_colon":
optConfig.dfmt_space_before_named_arg_colon = optVal;
break;
case "keep_line_breaks": case "keep_line_breaks":
optConfig.dfmt_keep_line_breaks = optVal; optConfig.dfmt_keep_line_breaks = optVal;
break; 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: default:
assert(false, "Invalid command-line switch"); assert(false, "Invalid command-line switch");
} }
@ -129,19 +117,15 @@ else
"soft_max_line_length", &optConfig.dfmt_soft_max_line_length, "soft_max_line_length", &optConfig.dfmt_soft_max_line_length,
"outdent_attributes", &handleBooleans, "outdent_attributes", &handleBooleans,
"space_after_cast", &handleBooleans, "space_after_cast", &handleBooleans,
"space_after_keywords", &handleBooleans,
"selective_import_space", &handleBooleans, "selective_import_space", &handleBooleans,
"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, "single_template_constraint_indent", &handleBooleans,
"space_before_aa_colon", &handleBooleans, "space_before_aa_colon", &handleBooleans,
"space_before_named_arg_colon", &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,
"keep_line_breaks", &handleBooleans, "keep_line_breaks", &handleBooleans);
"single_indent", &handleBooleans,
"reflow_property_chains", &handleBooleans);
// dfmt on // dfmt on
} }
catch (GetOptException e) catch (GetOptException e)
@ -165,13 +149,14 @@ else
args.popFront(); args.popFront();
immutable bool readFromStdin = args.length == 0; immutable bool readFromStdin = args.length == 0;
File output = stdout;
version (Windows) version (Windows)
{ {
// On Windows, set stdout to binary mode (needed for correct EOL writing) // On Windows, set stdout to binary mode (needed for correct EOL writing)
// See Phobos' stdio.File.rawWrite // See Phobos' stdio.File.rawWrite
{ {
import std.stdio : _O_BINARY; import std.stdio : _O_BINARY;
immutable fd = stdout.fileno; immutable fd = output.fileno;
_setmode(fd, _O_BINARY); _setmode(fd, _O_BINARY);
version (CRuntime_DigitalMars) version (CRuntime_DigitalMars)
{ {
@ -192,7 +177,7 @@ else
if (!exists(explicitConfigDir) || !isDir(explicitConfigDir)) if (!exists(explicitConfigDir) || !isDir(explicitConfigDir))
{ {
stderr.writeln("--config|c must specify existing directory path"); stderr.writeln("--config_dir|c must specify existing directory path");
return 1; return 1;
} }
explicitConfig = getConfigFor!Config(explicitConfigDir); explicitConfig = getConfigFor!Config(explicitConfigDir);
@ -231,7 +216,7 @@ else
break; break;
} }
immutable bool formatSuccess = format("stdin", buffer, immutable bool formatSuccess = format("stdin", buffer,
stdout.lockingTextWriter(), &config); output.lockingTextWriter(), &config);
return formatSuccess ? 0 : 1; return formatSuccess ? 0 : 1;
} }
else else
@ -273,16 +258,10 @@ else
{ {
buffer = new ubyte[](cast(size_t) f.size); buffer = new ubyte[](cast(size_t) f.size);
f.rawRead(buffer); f.rawRead(buffer);
auto output = appender!string;
immutable bool formatSuccess = format(path, buffer, output, &config);
if (formatSuccess)
{
if (inplace) if (inplace)
File(path, "wb").rawWrite(output.data); output = File(path, "wb");
else immutable bool formatSuccess = format(path, buffer, output.lockingTextWriter(), &config);
stdout.rawWrite(output.data); if (!formatSuccess)
}
else
retVal = 1; retVal = 1;
} }
} }
@ -306,14 +285,12 @@ private version (Windows)
template optionsToString(E) if (is(E == enum)) template optionsToString(E) if (is(E == enum))
{ {
import std.algorithm.searching : startsWith;
enum optionsToString = () { enum optionsToString = () {
string result = "("; string result = "(";
foreach (s; [__traits(allMembers, E)]) foreach (s; [__traits(allMembers, E)])
{ {
if (!s.startsWith("_")) if (s != "unspecified")
result ~= s ~ "|"; result ~= s ~ "|";
} }
result = result[0 .. $ - 1] ~ ")"; result = result[0 .. $ - 1] ~ ")";
@ -329,7 +306,7 @@ https://github.com/dlang-community/dfmt
Options: Options:
--help, -h Print this help message --help, -h Print this help message
--inplace, -i Edit files in place --inplace, -i Edit files in place
--config, -c Path to directory to load .editorconfig file from. --config_dir, -c Path to directory to load .editorconfig file from.
--version Print the version number and then exit --version Print the version number and then exit
Formatting Options: Formatting Options:
@ -346,16 +323,12 @@ Formatting Options:
--outdent_attributes --outdent_attributes
--space_after_cast --space_after_cast
--space_before_function_parameters --space_before_function_parameters
--space_after_keywords
--selective_import_space --selective_import_space
--single_template_constraint_indent --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
--space_before_aa_colon --space_before_aa_colon
--space_before_named_arg_colon
--single_indent
--reflow_property_chains
`, `,
optionsToString!(typeof(Config.dfmt_template_constraint_style))); optionsToString!(typeof(Config.dfmt_template_constraint_style)));
} }

View File

@ -172,6 +172,9 @@ size_t[] chooseLineBreakTokens(size_t index, const Token[] tokens,
void validMoves(OR)(auto ref OR output, const Token[] tokens, immutable short[] depths, void validMoves(OR)(auto ref OR output, const Token[] tokens, immutable short[] depths,
uint current, const Config* config, int currentLineLength, int indentLevel) uint current, const Config* config, int currentLineLength, int indentLevel)
{ {
import std.algorithm : sort, canFind, min;
import std.array : insertInPlace;
foreach (i, token; tokens) foreach (i, token; tokens)
{ {
if (!isBreakToken(token.type) || (((1 << i) & current) != 0)) if (!isBreakToken(token.type) || (((1 << i) & current) != 0))

View File

@ -1,23 +0,0 @@
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

@ -1,31 +0,0 @@
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,7 +1,7 @@
unittest unittest
{ {
foo([ foo([
target.value.region[1], target.value.region[1], target.value.region[1], target.value.region[1], target.value.region[1],
target.value.region[1], target.value.region[1] target.value.region[1], target.value.region[1], target.value.region[1]
]); ]);
} }

View File

@ -1,8 +0,0 @@
void main()
{
string key;
int[string] var = [
key: 5
];
}

View File

@ -7,8 +7,8 @@ unittest
]), ]),
"short": Bson(["a": "b", "c": "d"]), "short": Bson(["a": "b", "c": "d"]),
"numbers": Bson([ "numbers": Bson([
1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
3, 4, 5, 6, 7, 8, 9, 0 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0
]), ]),
"shuffleOnReset": serializeToBson([ "shuffleOnReset": serializeToBson([
"all": false, "all": false,

View File

@ -1,54 +0,0 @@
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

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

View File

@ -1,8 +0,0 @@
/* 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

@ -1,40 +0,0 @@
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

@ -1,40 +0,0 @@
class C
{
abstract void f1() //
in (true);
abstract void f2() /* */
in (true);
abstract bool f3() //
out (r; r);
abstract bool f4() /* */
out (r; r);
abstract void f5() //
do
{
}
abstract void f6() /* */
do
{
}
abstract bool f7() //
in (true) //
out (r; r) //
do //
{
return true;
}
abstract bool f8() /* */
in (true) /* */
out (r; r) /* */
do /* */
{
return true;
}
}

View File

@ -1,8 +0,0 @@
bool asdf(const string owner, const string mail) @safe
{
requestHTTP(url, (scope HTTPClientRequest request) {
request.writeFormBody([owner: owner, mail: mail]);
}, (scope HTTPClientResponse response) {});
return true;
}

View File

@ -1,7 +0,0 @@
string BuildForwardCall()
{
return `static if (is(typeof(mocked___.` ~ methodString ~ argsPassed ~ `)))
{
return (mocked___.` ~ methodString ~ argsPassed ~ `);
}`;
}

View File

@ -1,15 +0,0 @@
module tests.issue0483;
void main()
{
switch (0)
{
case 1:
case 2:
label:
case 3:
break;
default:
break;
}
}

View File

@ -1,5 +0,0 @@
void main()
{
int a;
int[int] hashmap = [a : a, a : a, a : a];
}

View File

@ -1,5 +0,0 @@
void main()
{
auto someAutoVariableName = this.firstLink.secondLink
.filter!(shouldBeProbablySomeIdentifierOrNot);
}

View File

@ -1,29 +0,0 @@
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

@ -1,74 +0,0 @@
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

@ -1,34 +0,0 @@
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

@ -1,5 +0,0 @@
alias f1 = S function();
alias f2 = S!"foo" function();
alias f3 = S!5 function();
alias f4 = S!S function();
alias f5 = S!(S) function();

View File

@ -1,4 +0,0 @@
void main()
{
auto aa = ["aaa": 1, "bbb": 2];
}

View File

@ -1,15 +0,0 @@
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

@ -1,40 +0,0 @@
deprecated("foo")
void test()
{
}
package(foo)
void bar()
{
}
@uda()
void baz()
{
}
deprecated
deprecated_()
{
}
@uda
void uda_()
{
}
@property
void property()
{
}
deprecated("Reason") @uda
void propertyuda()
{
}
deprecated("Reason")
@uda
void udaproperty()
{
}

View File

@ -1,7 +0,0 @@
struct S
{
@safe invariant
{
assert(true);
}
}

View File

@ -1,34 +0,0 @@
void main()
{
string a = "foo"
~ "bar" // bar
~ "baz";
}
void foo()
{
afdsafds
.asdf // blah
.flub;
}
void main()
{
string a = "foo"
~ "bar" /* bar */
~ "baz";
}
void foo()
{
afdsafds
.asdf /* blah */
.flub;
}
void foo() // hello
{ // world
// ok
writeln("hi"); // hi!
} // done
//finish

View File

@ -1,7 +0,0 @@
struct S
{
ref S foo() return
{
return this;
}
}

View File

@ -1,17 +0,0 @@
public int f() return
in (true)
{
return 0;
}
public int g() return
out (; true)
{
return 0;
}
public int h() return
body
{
return 0;
}

View File

@ -1,4 +0,0 @@
void f() return
do
{
}

View File

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

View File

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

View File

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

View File

@ -1,8 +0,0 @@
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

@ -1,38 +0,0 @@
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);
}
void test()
{
return Struct(foo: field.foo, bar: field.bar, baz: field.baz);
return new Class(foo: field.foo, bar: field.bar, baz: field.baz);
// anonymous class
return new class(foo: field.foo, bar: field.bar, baz: field.baz) Class
{
};
}

View File

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

View File

@ -1,7 +0,0 @@
unittest
{
functionLengthDoesMatter([
firstFunctionInChain("A").seconFunctionInChain("B").value,
firstFunctionInChain("A").seconFunctionInChain("B").value
]);
}

View File

@ -1,49 +0,0 @@
unittest
{
{
bool anotherTemplatedFunction(One, Two, Three)(One alpha, Two bravo,
Three charlie, double delta)
{
if (isNumeric!One && isNumeric!Two && isNumeric!Three && echo
&& foxtrot && golf && hotel && india && juliet)
{
}
}
}
}
void f()
{
string a = "foo"
~ "bar" /* bar */
~ "baz";
}
unittest
{
if (a)
{
while (sBraceDepth == 0 && indents.topIsTemp()
&& ((indents.top != tok!"if" && indents.top != tok!"version")
|| !peekIs(tok!"else")))
a();
}
}
unittest
{
callFunc({ int i = 10; return i; });
callFunc({
int i = 10;
foo(alpha, bravo, charlie, delta, echo, foxtrot, golf, echo);
doStuff(withThings, andOtherStuff);
return i;
});
callFunc({
int i = 10;
foo(alpha_longVarName, bravo_longVarName, charlie_longVarName, delta_longVarName,
echo_longVarName, foxtrot_longVarName, golf_longVarName, echo_longVarName);
doStuff(withThings, andOtherStuff);
return i;
}, more_stuff);
}

View File

@ -1,41 +0,0 @@
unittest
{
{
bool anotherTemplatedFunction(One, Two, Three)(One alpha, Two bravo,
Three charlie, double delta)
{
if (isNumeric!One && isNumeric!Two && isNumeric!Three && echo
&& foxtrot && golf && hotel && india && juliet)
{
}
}
}
}
unittest
{
if (a)
{
while (sBraceDepth == 0 && indents.topIsTemp()
&& ((indents.top != tok!"if" && indents.top != tok!"version") || !peekIs(tok!"else")))
a();
}
}
unittest
{
callFunc({ int i = 10; return i; });
callFunc({
int i = 10;
foo(alpha, bravo, charlie, delta, echo, foxtrot, golf, echo);
doStuff(withThings, andOtherStuff);
return i;
});
callFunc({
int i = 10;
foo(alpha_longVarName, bravo_longVarName, charlie_longVarName, delta_longVarName,
echo_longVarName, foxtrot_longVarName, golf_longVarName, echo_longVarName);
doStuff(withThings, andOtherStuff);
return i;
}, more_stuff);
}

View File

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

View File

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

View File

@ -1,60 +0,0 @@
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

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

View File

@ -1,31 +0,0 @@
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 +0,0 @@
--keep_line_breaks=true

View File

@ -1,8 +0,0 @@
void main()
{
string key;
int[string] var = [
key: 5
];
}

View File

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

View File

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

View File

@ -1,53 +0,0 @@
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

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

View File

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

View File

@ -1,8 +0,0 @@
/* 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

@ -1,38 +0,0 @@
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

@ -1,40 +0,0 @@
class C
{
abstract void f1() //
in (true);
abstract void f2() /* */
in (true);
abstract bool f3() //
out (r; r);
abstract bool f4() /* */
out (r; r);
abstract void f5() //
do
{
}
abstract void f6() /* */
do
{
}
abstract bool f7() //
in (true) //
out (r; r) //
do //
{
return true;
}
abstract bool f8() /* */
in (true) /* */
out (r; r) /* */
do /* */
{
return true;
}
}

View File

@ -1,9 +0,0 @@
bool asdf(const string owner, const string mail) @safe
{
requestHTTP(url, (scope HTTPClientRequest request) {
request.writeFormBody([owner: owner, mail:
mail]);
}, (scope HTTPClientResponse response) {});
return true;
}

View File

@ -1,7 +0,0 @@
string BuildForwardCall()
{
return `static if (is(typeof(mocked___.` ~ methodString ~ argsPassed ~ `)))
{
return (mocked___.` ~ methodString ~ argsPassed ~ `);
}`;
}

View File

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

View File

@ -1,15 +0,0 @@
module tests.issue0483;
void main()
{
switch (0)
{
case 1:
case 2:
label:
case 3:
break;
default:
break;
}
}

View File

@ -1 +0,0 @@
--space_before_aa_colon true

View File

@ -1,5 +0,0 @@
void main()
{
int a;
int[int] hashmap = [a : a, a : a, a : a];
}

View File

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

View File

@ -1,5 +0,0 @@
void main()
{
auto someAutoVariableName = this.firstLink.secondLink
.filter!(shouldBeProbablySomeIdentifierOrNot);
}

View File

@ -1,33 +0,0 @@
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

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

View File

@ -1,74 +0,0 @@
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

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

View File

@ -1,33 +0,0 @@
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

@ -1,5 +0,0 @@
alias f1 = S function();
alias f2 = S!"foo" function();
alias f3 = S!5 function();
alias f4 = S!S function();
alias f5 = S!(S) function();

View File

@ -1,4 +0,0 @@
void main()
{
auto aa = ["aaa": 1, "bbb":2];
}

View File

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

View File

@ -1,14 +0,0 @@
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

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

View File

@ -1,40 +0,0 @@
deprecated("foo")
void test()
{
}
package(foo)
void bar()
{
}
@uda()
void baz()
{
}
deprecated
deprecated_()
{
}
@uda
void uda_()
{
}
@property
void property()
{
}
deprecated("Reason") @uda
void propertyuda()
{
}
deprecated("Reason")
@uda
void udaproperty()
{
}

View File

@ -1 +0,0 @@
struct S {@safe invariant { assert(true); }}

View File

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

View File

@ -1,34 +0,0 @@
void main()
{
string a = "foo"
~ "bar" // bar
~ "baz";
}
void foo()
{
afdsafds
.asdf // blah
.flub;
}
void main()
{
string a = "foo"
~ "bar" /* bar */
~ "baz";
}
void foo()
{
afdsafds
.asdf /* blah */
.flub;
}
void foo() // hello
{ // world
// ok
writeln("hi"); // hi!
} // done
//finish

View File

@ -1,7 +0,0 @@
struct S
{
ref S foo() return
{
return this;
}
}

View File

@ -1,17 +0,0 @@
public int f() return
in (true)
{
return 0;
}
public int g() return
out (; true)
{
return 0;
}
public int h() return
body
{
return 0;
}

View File

@ -1,4 +0,0 @@
void f() return
do
{
}

View File

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

View File

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

View File

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

View File

@ -1,8 +0,0 @@
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];
}

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