Compare commits

..

No commits in common. "master" and "v0.4.0-beta2" have entirely different histories.

705 changed files with 676 additions and 10820 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

2
.gitignore vendored
View File

@ -3,5 +3,3 @@ bin
*.d.out
.dub
dub.selections.json
.gdb_history
bin/dfmt

8
.gitmodules vendored
View File

@ -1,9 +1,3 @@
[submodule "libdparse"]
path = libdparse
url = https://github.com/dlang-community/libdparse.git
[submodule "stdx-allocator"]
path = 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
url = https://github.com/Hackerpilot/libdparse.git

3
.travis.yml Normal file
View File

@ -0,0 +1,3 @@
language: d
script:
- git submodule update --init --recursive && make test

119
README.md
View File

@ -1,66 +1,46 @@
# 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/Hackerpilot/dfmt.svg)](https://travis-ci.org/Hackerpilot/dfmt)
**dfmt** is a formatter for D source code
## Status
**dfmt** is beta quality. Make backups of your files or use source control
when using the **--inplace** option.
## Installation
### Installing with DUB
```sh
> dub run dfmt -- -h
```
### Building from source using Make
## Building
### Using Make
* Clone the repository
* Run ```git submodule update --init --recursive``` in the dfmt directory
* Run ```git submodule update --init``` in the dfmt directory
* To compile with DMD, run ```make``` in the dfmt directory. To compile with
LDC, run ```make ldc``` instead. The generated binary will be placed in ```dfmt/bin/```.
### Building from source using dub
* Clone the repository
* run `dub build --build=release`, optionally with `--compiler=ldc2`
## Using
By default, dfmt reads its input from **stdin** and writes to **stdout**.
If a file name is specified on the command line, input will be read from the
file instead, and output will be written to **stdout**.
**dfmt** uses [EditorConfig](http://editorconfig.org/) files for configuration. If you run **dfmt** on a
source file it will look for *.editorconfig* files that apply to that source file.
If no file is specified on the command line, **dfmt** will look for *.editorconfig*
**dfmt** uses EditorConfig files for configuration. If you run **dfmt** on a
source file it will look for .editorconfig files that apply to that source file.
If no file is specified on the command line, **dfmt** will look for .editorconfig
files that would apply to a D file in the current working directory. Command
line options can be used instead of *.editorconfig* files, or to override options
found there.
line options can be used instead of .editorconfig files, or to override options
found in .editorconfig files.
### Options
* `--help | -h`: Display command line options.
* `--inplace | -i`: A file name is required and the file will be edited in-place.
* `--align_switch_statements`: *see dfmt_align_switch_statements [below](#dfmt-specific-properties)*
* `--brace_style`: *see dfmt_brace_style [below](#dfmt-specific-properties)*
* `--compact_labeled_statements`: *see dfmt_compact_labeled_statements [below](#dfmt-specific-properties)*
* `--end_of_line`: *see end_of_line [below](#standard-editorconfig-properties)*
* `--indent_size`: *see indent_size [below](#standard-editorconfig-properties)*
* `--indent_style | -t`: *see indent_style [below](#standard-editorconfig-properties)*
* `--max_line_length`: *see max_line_length [below](#standard-editorconfig-properties)*
* `--outdent_attributes`: *see dfmt_outdent_attributes [below](#dfmt-specific-properties)*
* `--selective_import_space`: *see dfmt_selective_import_space [below](#dfmt-specific-properties)*
* `--single_template_constraint_indent`: *see dfmt_single_template_constraint_indent [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_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)*
* **--help**: Display command line options
* **--inplace**: A file name is required and the file will be edited in-place.
* **--align_switch_statements**: See **dfmt_align_switch_statements** below
* **--brace_style**: See **brace_style** below
* **--end_of_line**: See **end_of_line** below
* **--indent_size**: See **indent_size** below
* **--indent_style**: See **indent_style** below
* **--max_line_length**: See **max_line_length** below
* **--soft_max_line_length**: See **dfmt_soft_max_line_length** below
* **--outdent_attributes**: See **dfmt_outdent_attributes** below
* **--space_after_cast**: See **dfmt_space_after_cast** below
* **--split_operator_at_line_end**: See **dfmt_split_operator_at_line_end** below
* **--tab_width**: See **tab_width** below
* **--selective_import_space**: See **dfmt_selective_import_space** below
* **--compact_labeled_statements**: See **dfmt_compact_labeled_statements** below
### Example
```
@ -94,37 +74,28 @@ void main(string[] args)
**dfmt** uses [EditorConfig](http://editorconfig.org/) configuration files.
**dfmt**-specific properties are prefixed with *dfmt_*.
### 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) 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)
indent_size | positive integers (**`4`**) | [See EditorConfig documentation.](https://github.com/editorconfig/editorconfig/wiki/EditorConfig-Properties#indent_size)
tab_width | positive integers (**`4`**) | [See EditorConfig documentation.](https://github.com/editorconfig/editorconfig/wiki/EditorConfig-Properties#tab_width)
trim_trailing_whitespace | **`true`** | Not supported. `dfmt` does not emit trailing whitespace.
max_line_length | positive integers (**`120`**) | [See EditorConfig documentation.](https://github.com/editorconfig/editorconfig/wiki/EditorConfig-Properties#max_line_length)
Property Name | Allowed Values | Default Value | Description
--------------|----------------|---------------|------------
end_of_line | `cr`, `crlf` and `lf` | `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.
charset | | `UTf-8` | Not supported. `dfmt` only works correctly on UTF-8.
indent_style | `tab`, `space` | `space` | [See EditorConfig documentation.](https://github.com/editorconfig/editorconfig/wiki/EditorConfig-Properties#indent_style)
indent_size | positive integers | `4` | [See EditorConfig documentation.](https://github.com/editorconfig/editorconfig/wiki/EditorConfig-Properties#indent_size)
tab_width | positive integers | `8` | [See EditorConfig documentation.](https://github.com/editorconfig/editorconfig/wiki/EditorConfig-Properties#tab_width)
trim_trailing_whitespace | | `true` | Not supported. `dfmt` does not emit trailing whitespace.
max_line_length | positive integers | `120` | [See EditorConfig documentation.](https://github.com/editorconfig/editorconfig/wiki/EditorConfig-Properties#max_line_length)
### dfmt-specific properties
Property Name | Allowed Values | Description
--------------|----------------|------------
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.
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_keywords (Not yet implemented) | **`true`**, `false` | Insert space after `if`, `while`, `foreach`, etc, and before the `(`.
dfmt_space_before_function_parameters | `true`, **`false`** | Insert space before the opening paren of a function parameter list.
dfmt_selective_import_space | **`true`**, `false` | Insert space after the module name and before the `:` for selective imports.
dfmt_compact_labeled_statements | **`true`**, `false` | Place labels on the same line as the labeled `switch`, `for`, `foreach`, or `while` statement.
dfmt_template_constraint_style | **`conditional_newline_indent`** `conditional_newline` `always_newline` `always_newline_indent` | 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.).
Property Name | Allowed Values | Default Value | Description
--------------|----------------|---------------|------------
dfmt_brace_style | `allman`, `otbs`, or `stroustrup` | `allman` | [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 (Not yet implemented) | `true`, `false` | `true` | Align labels, cases, and defaults with their enclosing switch
dfmt_outdent_attributes (Not yet implemented) | `true`, `false` | `true` | Decrease the indentation level of attributes
dfmt_split_operator_at_line_end | `true`, `false` | `false` | Place operators on the end of the previous line when splitting lines
dfmt_space_after_cast | `true`, `false` | `false` | Insert space after the closing paren of a `cast` expression
dfmt_space_after_keywords (Not yet implemented) | `true`, `false` | `true` | Insert space after `if`, `while`, `foreach`, etc, and before the `(`
dfmt_selective_import_space | `true`, `false` | `true` | Insert space after the module name and before the `:` for selective imports
dfmt_compact_labeled_statements | `true`, `false` | `true` | Place labels on the same line as the labeled `switch`, `for`, `foreach`, or `while` statement
## Terminology
* Braces - `{` and `}`

View File

@ -1,67 +0,0 @@
# Completion for dfmt
_dfmt()
{
local cur prev opts
COMPREPLY=()
cur="${COMP_WORDS[COMP_CWORD]}"
prev="${COMP_WORDS[COMP_CWORD-1]}"
booleans="--align_switch_statements --outdent_attributes --space_after_cast\
--space_before_function_parameters --selective_import_space\
--split_operator_at_line_end --compact_labeled_statements"
# Uncomment code below to print the list of boolean options incase you edit it
# and replace it in the case below
#
#booleans=${booleans// / }
#booleans=${booleans// / }
#bared_booleans=\"${booleans// /\"|\"}\"
#echo ${bared_booleans}
opts="--help -h --inplace -i --version --brace_style\
--end_of_line --indent_size --indent_style -t --soft_max_line_length\
--max_line_length ${booleans} --template_constraint_style"
eolOpts="lf cr crlf"
boolOpts="true false"
braceOpts="allman otbs stroustrup knr"
indentOpts="tab space"
constraintOpts="conditional_newline_indent conditional_newline always_newline always_newline_indent"
if [[ ${cur} == -* ]]; then
COMPREPLY=($(compgen -W "${opts}" -- ${cur}))
return 0;
fi
case "${prev}" in
"--brace_style")
COMPREPLY=($(compgen -W "${braceOpts}" -- ${cur}))
return 0
;;
"--end_of_line")
COMPREPLY=($(compgen -W "${eolOpts}" -- ${cur}))
return 0
;;
"-t")
;&
"--indent_style")
COMPREPLY=($(compgen -W "${indentOpts}" -- ${cur}))
return 0
;;
"--template_constraint_style")
COMPREPLY=($(compgen -W "${constraintOpts}" -- ${cur}))
return 0
;;
"--align_switch_statements"|"--outdent_attributes"|"--space_after_cast"|"--space_before_function_parameters"|"--selective_import_space"|"--split_operator_at_line_end"|"--compact_labeled_statements")
COMPREPLY=($(compgen -W "${boolOpts}" -- ${cur}))
return 0
;;
*)
COMPREPLY=($(compgen -f -- ${cur}))
return 0
;;
esac
COMPREPLY=($(compgen -W "${opts}" -- ${cur}))
}
complete -F _dfmt dfmt

View File

@ -1,37 +1,15 @@
@echo off
setlocal enabledelayedexpansion
IF "%DC%"=="" SET DC="dmd"
set DFLAGS=-g
set CORE=
set STD=
set STDD=
set STDXALLOCATOR=
set STDXALLOCATORBLOCKS=
set OBIN=bin\dfmt
:: git might not be installed, so we provide 0.0.0 as a fallback or use
:: the existing githash file if existent
if not exist "bin" mkdir bin
git describe --tags > bin\githash_.txt
for /f %%i in ("bin\githash_.txt") do set githashsize=%%~zi
if %githashsize% == 0 (
if not exist "bin\githash.txt" (
echo v0.0.0 > bin\githash.txt
)
) else (
move /y bin\githash_.txt bin\githash.txt
)
for %%x in (src\dfmt\*.d) do set CORE=!CORE! %%x
for %%x in (libdparse\src\std\experimental\*.d) do set STD=!STD! %%x
for %%x in (libdparse\src\dparse\*.d) do set STDD=!STDD! %%x
for %%x in (stdx-allocator\source\stdx\allocator\*.d) do set STDXALLOCATOR=!STDXALLOCATOR! %%x
for %%x in (stdx-allocator\source\stdx\allocator\building_blocks\*.d) do set STDXALLOCATORBLOCKS=!STDXALLOCATORBLOCKS! %%x
for %%x in (src\*.d) do set CORE=!CORE! %%x
for %%x in (libdparse\src\std\*.d) do set STD=!STD! %%x
for %%x in (libdparse\src\std\d\*.d) do set STDD=!STDD! %%x
@echo on
%DC% %CORE% %STD% %STDD% %STDE% %STDXALLOCATOR% %STDXALLOCATORBLOCKS% -I"stdx-allocator\source" -I"libdparse\src" -Jbin %DFLAGS% -of%OBIN%.exe
dmd %CORE% %STD% %STDD% %DFLAGS% -ofbin\dfmt.exe
if exist %OBIN%.obj del %OBIN%.obj

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

View File

@ -1,20 +1,10 @@
{
"name": "dfmt",
"description": "Dfmt is a formatter for D source code",
"targetType": "autodetect",
"version": "0.4.0-beta",
"targetType": "executable",
"license": "BSL-1.0",
"dependencies": {
"libdparse": ">=0.19.2 <1.0.0"
},
"targetPath" : "bin/",
"targetName" : "dfmt",
"stringImportPaths" : [
"bin"
],
"versions" : [
"built_with_dub"
],
"preBuildCommands" : [
"$DC -run \"$PACKAGE_DIR/dubhash.d\""
]
"libdparse": "~master"
}
}

View File

@ -1,23 +0,0 @@
import std.algorithm;
import std.ascii;
import std.conv;
import std.exception;
import std.file;
import std.path;
import std.process;
import std.range;
import std.string;
void main()
{
auto dir = environment.get("DUB_PACKAGE_DIR");
auto hashFile = dir.buildPath("bin", "dubhash.txt");
auto gitVer = executeShell("git -C " ~ dir ~ " describe --tags");
auto ver = (gitVer.status == 0 ? gitVer.output.strip
: "v" ~ dir.dirName.baseName.findSplitAfter(
environment.get("DUB_ROOT_PACKAGE") ~ "-")[1]).ifThrown("0.0.0")
.chain(newline).to!string.strip;
dir.buildPath("bin").mkdirRecurse;
if (!hashFile.exists || ver != hashFile.readText.strip)
hashFile.write(ver);
}

@ -1 +1 @@
Subproject commit fe6d1e38fb4fc04323170389cfec67ed7fd4e24a
Subproject commit b3303ab6fd15e9cbde50c6987b303b6ed296d493

View File

@ -1,63 +1,33 @@
PREFIX = /usr/local
SRC := $(shell find src -name "*.d") \
$(shell find libdparse/src -name "*.d")
IMPORTS := -Ilibdparse/src -Isrc -Jbin
DC ?= dmd
LDC ?= ldc2
GDC ?= gdc
DMD_COMMON_FLAGS := -w $(IMPORTS)
DMD_DEBUG_FLAGS := -debug -g $(DMD_COMMON_FLAGS)
$(shell find libdparse/src -name "*.d") \
$(shell find libdparse/experimental_allocator/src -name "*.d")
INCLUDE_PATHS := -Ilibdparse/src -Isrc -Ilibdparse/experimental_allocator/src
DMD_COMMON_FLAGS := -dip25 -w $(INCLUDE_PATHS)
DMD_DEBUG_FLAGS := -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)
LDC_FLAGS := -g -w -oq $(INCLUDE_PATHS)
GDC_FLAGS := -g -w -oq $(INCLUDE_PATHS)
.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
.PHONY: dmd ldc gdc test
dmd: bin/dfmt
ldc: bin/githash.txt
$(LDC) $(SRC) $(LDC_FLAGS) -ofbin/dfmt
ldc: $(SRC)
ldc2 $(LDC_FLAGS) $^ -ofbin/dfmt
-rm -f *.o
gdc: bin/githash.txt
$(GDC) $(SRC) $(GDC_FLAGS) -obin/dfmt
gdc: $(SRC)
gdc $(GDC_FLAGS) $^ -obin/dfmt
test: debug
cd tests && ./test.d
test: bin/dfmt
cd tests && ./test.sh
bin/dfmt-test: bin/githash.txt $(SRC)
$(DC) $(DMD_TEST_FLAGS) $(filter %.d,$^) -of$@
bin/dfmt-test: $(SRC)
dmd $(DMD_TEST_FLAGS) $^ -of$@
bin/dfmt: bin/githash.txt $(SRC)
$(DC) $(DMD_FLAGS) $(filter %.d,$^) -of$@
bin/dfmt: $(SRC)
dmd $(DMD_FLAGS) $^ -of$@
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 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
$(MAKE) bin/githash.txt
debug: $(SRC)
dmd $(DMD_DEBUG_FLAGS) $^ -ofbin/dfmt

View File

@ -1,21 +0,0 @@
#!/usr/bin/env bash
# Build the Windows binaries under Linux
set -eux -o pipefail
BIN_NAME=dfmt
# Allow the script to be run from anywhere
DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
cd $DIR
source setup-ldc-windows.sh
# Run LDC with cross-compilation
archiveName="$BIN_NAME-$VERSION-$OS-$ARCH_SUFFIX.zip"
echo "Building $archiveName"
mkdir -p bin
DC=ldmd2 make ldc
cd bin
mv "${BIN_NAME}" "${BIN_NAME}.exe"
zip "$archiveName" "${BIN_NAME}.exe"

View File

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

View File

@ -1,70 +0,0 @@
#!/usr/bin/env bash
# sets up LDC for cross-compilation. Source this script, s.t. the new LDC is in PATH
LDC_VERSION="1.13.0"
ARCH=${ARCH:-32}
VERSION=$(git describe --abbrev=0 --tags)
OS=windows
# Step 0: install ldc
if [ ! -f install.sh ] ; then
wget https://dlang.org/install.sh
fi
. $(bash ./install.sh -a "ldc-${LDC_VERSION}")
# for the install.sh script only
LDC_PATH="$(dirname $(dirname $(which ldc2)))"
# Step 1a: download the LDC x64 windows binaries
if [ "${ARCH}" == 64 ] && [ ! -d "ldc2-${LDC_VERSION}-windows-x64" ] ; then
wget "https://github.com/ldc-developers/ldc/releases/download/v1.13.0/ldc2-${LDC_VERSION}-windows-x64.7z"
7z x "ldc2-${LDC_VERSION}-windows-x64.7z" > /dev/null
# Step 2a: Add LDC windows binaries to LDC Linux
if [ ! -d "${LDC_PATH}/lib-win64" ] ; then
cp -r ldc2-1.13.0-windows-x64/lib "${LDC_PATH}/lib-win64"
cat >> "$LDC_PATH"/etc/ldc2.conf <<EOF
"x86_64-.*-windows-msvc":
{
switches = [
"-defaultlib=phobos2-ldc,druntime-ldc",
"-link-defaultlib-shared=false",
];
lib-dirs = [
"%%ldcbinarypath%%/../lib-win64",
];
};
EOF
fi
fi
# Step 1b: download the LDC x86 windows binaries
if [ "${ARCH}" == 32 ] && [ ! -d "ldc2-${LDC_VERSION}-windows-x86" ] ; then
wget "https://github.com/ldc-developers/ldc/releases/download/v1.13.0/ldc2-${LDC_VERSION}-windows-x86.7z"
7z x "ldc2-${LDC_VERSION}-windows-x86.7z" > /dev/null
# Step 2b: Add LDC windows binaries to LDC Linux
if [ ! -d "${LDC_PATH}/lib-win32" ] ; then
cp -r ldc2-1.13.0-windows-x86/lib "${LDC_PATH}/lib-win32"
cat >> "$LDC_PATH"/etc/ldc2.conf <<EOF
"i686-.*-windows-msvc":
{
switches = [
"-defaultlib=phobos2-ldc,druntime-ldc",
"-link-defaultlib-shared=false",
];
lib-dirs = [
"%%ldcbinarypath%%/../lib-win32",
];
};
EOF
fi
fi
# set suffices and compilation flags
if [ "$ARCH" == "64" ] ; then
ARCH_SUFFIX="x86_64"
export DFLAGS="-mtriple=x86_64-windows-msvc"
else
ARCH_SUFFIX="x86"
export DFLAGS="-mtriple=i686-windows-msvc"
fi

View File

@ -5,29 +5,8 @@
module dfmt.ast_info;
import dparse.lexer;
import dparse.ast;
enum BraceIndentInfoFlags
{
tempIndent = 1 << 0,
}
struct BraceIndentInfo
{
size_t startLocation;
size_t endLocation;
uint flags;
uint beginIndentLevel;
}
struct StructInitializerInfo
{
size_t startLocation;
size_t endLocation;
}
import std.d.lexer;
import std.d.ast;
/// AST information that is needed by the formatter.
struct ASTInformation
@ -35,14 +14,12 @@ struct ASTInformation
/// Sorts the arrays so that binary search will work on them
void cleanup()
{
import std.algorithm : sort, uniq;
import std.array : array;
import std.algorithm : sort;
sort(doubleNewlineLocations);
sort(spaceAfterLocations);
sort(unaryLocations);
sort(attributeDeclarationLines);
sort(atAttributeStartLocations);
sort(caseEndLocations);
sort(structInitStartLocations);
sort(structInitEndLocations);
@ -51,20 +28,7 @@ struct ASTInformation
sort(conditionalWithElseLocations);
sort(conditionalStatementLocations);
sort(arrayStartLocations);
sort(assocArrayStartLocations);
sort(contractLocations);
sort(constraintLocations);
sort(constructorDestructorLocations);
sort(staticConstructorDestructorLocations);
sort(sharedStaticConstructorDestructorLocations);
sort!((a,b) => a.endLocation < b.endLocation)
(indentInfoSortedByEndLocation);
sort!((a,b) => a.endLocation < b.endLocation)
(structInfoSortedByEndLocation);
sort(ufcsHintLocations);
ufcsHintLocations = ufcsHintLocations.uniq().array();
sort(ternaryColonLocations);
sort(namedArgumentColonLocations);
}
/// Locations of end braces for struct bodies
@ -79,9 +43,6 @@ struct ASTInformation
/// Lines containing attribute declarations
size_t[] attributeDeclarationLines;
/// Lines containing attribute declarations that can be followed by a new line
size_t[] atAttributeStartLocations;
/// Case statement colon locations
size_t[] caseEndLocations;
@ -97,12 +58,6 @@ struct ASTInformation
/// Closing braces of function literals
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
size_t[] conditionalWithElseLocations;
@ -112,44 +67,13 @@ struct ASTInformation
/// Locations of start locations of array initializers
size_t[] arrayStartLocations;
/// Locations of start locations of associative array initializers
size_t[] assocArrayStartLocations;
/// Locations of "in" and "out" tokens that begin contracts
size_t[] contractLocations;
/// Locations of template constraint "if" tokens
size_t[] constraintLocations;
/// Locations of constructor/destructor "shared" tokens ?
size_t[] sharedStaticConstructorDestructorLocations;
/// Locations of constructor/destructor "static" tokens ?
size_t[] staticConstructorDestructorLocations;
/// Locations of constructor/destructor "this" tokens ?
size_t[] constructorDestructorLocations;
/// Locations of '.' characters that might be UFCS chains.
size_t[] ufcsHintLocations;
BraceIndentInfo[] indentInfoSortedByEndLocation;
/// 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
final class FormatVisitor : ASTVisitor
{
alias visit = ASTVisitor.visit;
/**
* Params:
* astInformation = the AST information that will be filled in
@ -165,76 +89,14 @@ final class FormatVisitor : ASTVisitor
arrayInitializer.accept(this);
}
override void visit(const ArrayLiteral arrayLiteral)
{
astInformation.arrayStartLocations ~= arrayLiteral.tokens[0].index;
arrayLiteral.accept(this);
}
override void visit(const AssocArrayLiteral assocArrayLiteral)
{
astInformation.arrayStartLocations ~= assocArrayLiteral.tokens[0].index;
astInformation.assocArrayStartLocations ~= assocArrayLiteral.tokens[0].index;
assocArrayLiteral.accept(this);
}
override void visit (const SharedStaticConstructor sharedStaticConstructor)
{
astInformation.sharedStaticConstructorDestructorLocations ~= sharedStaticConstructor.location;
sharedStaticConstructor.accept(this);
}
override void visit (const SharedStaticDestructor sharedStaticDestructor)
{
astInformation.sharedStaticConstructorDestructorLocations ~= sharedStaticDestructor.location;
sharedStaticDestructor.accept(this);
}
override void visit (const StaticConstructor staticConstructor)
{
astInformation.staticConstructorDestructorLocations ~= staticConstructor.location;
staticConstructor.accept(this);
}
override void visit (const StaticDestructor staticDestructor)
{
astInformation.staticConstructorDestructorLocations ~= staticDestructor.location;
staticDestructor.accept(this);
}
override void visit (const Constructor constructor)
{
astInformation.constructorDestructorLocations ~= constructor.location;
constructor.accept(this);
}
override void visit (const Destructor destructor)
{
astInformation.constructorDestructorLocations ~= destructor.index;
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)
{
if (dec.hasElse)
if (dec.falseDeclaration !is null)
{
auto condition = dec.compileCondition;
if (condition.versionCondition !is null)
{
astInformation.conditionalWithElseLocations
~= condition.versionCondition.versionIndex;
astInformation.conditionalWithElseLocations ~= condition.versionCondition.versionIndex;
}
else if (condition.debugCondition !is null)
{
@ -246,12 +108,6 @@ final class FormatVisitor : ASTVisitor
dec.accept(this);
}
override void visit(const Constraint constraint)
{
astInformation.constraintLocations ~= constraint.location;
constraint.accept(this);
}
override void visit(const ConditionalStatement statement)
{
auto condition = statement.compileCondition;
@ -268,15 +124,8 @@ final class FormatVisitor : ASTVisitor
override void visit(const FunctionLiteralExpression funcLit)
{
if (funcLit.specifiedFunctionBody !is null)
{
const bs = funcLit.specifiedFunctionBody.blockStatement;
astInformation.funLitStartLocations ~= bs.startLocation;
astInformation.funLitEndLocations ~= bs.endLocation;
astInformation.indentInfoSortedByEndLocation ~=
BraceIndentInfo(bs.startLocation, bs.endLocation);
}
astInformation.funLitStartLocations ~= funcLit.functionBody.blockStatement.startLocation;
astInformation.funLitEndLocations ~= funcLit.functionBody.blockStatement.endLocation;
funcLit.accept(this);
}
@ -298,22 +147,19 @@ final class FormatVisitor : ASTVisitor
caseRangeStatement.accept(this);
}
override void visit(const SpecifiedFunctionBody specifiedFunctionBody)
override void visit(const FunctionBody functionBody)
{
if (specifiedFunctionBody.blockStatement !is null)
astInformation.doubleNewlineLocations ~= specifiedFunctionBody.blockStatement.endLocation;
specifiedFunctionBody.accept(this);
if (functionBody.blockStatement !is null)
astInformation.doubleNewlineLocations ~= functionBody.blockStatement.endLocation;
if (functionBody.bodyStatement !is null && functionBody.bodyStatement.blockStatement !is null)
astInformation.doubleNewlineLocations ~= functionBody.bodyStatement.blockStatement.endLocation;
functionBody.accept(this);
}
override void visit(const StructInitializer structInitializer)
{
astInformation.structInitStartLocations ~= structInitializer.startLocation;
astInformation.structInitEndLocations ~= structInitializer.endLocation;
astInformation.structInfoSortedByEndLocation ~=
StructInitializerInfo(structInitializer.startLocation, structInitializer.endLocation);
astInformation.indentInfoSortedByEndLocation ~=
BraceIndentInfo(structInitializer.startLocation, structInitializer.endLocation);
structInitializer.accept(this);
}
@ -331,15 +177,12 @@ final class FormatVisitor : ASTVisitor
override void visit(const Invariant invariant_)
{
if (invariant_.blockStatement !is null)
astInformation.doubleNewlineLocations ~= invariant_.blockStatement.endLocation;
invariant_.accept(this);
}
override void visit(const StructBody structBody)
{
astInformation.aggregateBodyLocations ~= structBody.startLocation;
astInformation.doubleNewlineLocations ~= structBody.endLocation;
structBody.accept(this);
}
@ -359,29 +202,9 @@ final class FormatVisitor : ASTVisitor
override void visit(const UnaryExpression unary)
{
import std.typecons : rebindable;
int chainLength;
auto u = rebindable(unary);
while (u !is null)
{
if (u.identifierOrTemplateInstance !is null
&& u.identifierOrTemplateInstance.templateInstance !is null)
chainLength++;
u = u.unaryExpression;
}
if (chainLength > 1)
{
u = unary;
while (u.unaryExpression !is null)
{
astInformation.ufcsHintLocations ~= u.dotLocation;
u = u.unaryExpression;
}
}
if (unary.prefix.type == tok!"~" || unary.prefix.type == tok!"&"
|| unary.prefix.type == tok!"*"
|| unary.prefix.type == tok!"+" || unary.prefix.type == tok!"-")
|| unary.prefix.type == tok!"*" || unary.prefix.type == tok!"+"
|| unary.prefix.type == tok!"-")
{
astInformation.unaryLocations ~= unary.prefix.index;
}
@ -394,110 +217,19 @@ final class FormatVisitor : ASTVisitor
attributeDeclaration.accept(this);
}
override void visit(const FunctionAttribute functionAttribute)
{
if (functionAttribute.atAttribute !is null)
astInformation.atAttributeStartLocations ~= functionAttribute.atAttribute.startLocation;
functionAttribute.accept(this);
}
override void visit(const MemberFunctionAttribute memberFunctionAttribute)
{
if (memberFunctionAttribute.atAttribute !is null)
astInformation.atAttributeStartLocations ~= memberFunctionAttribute.atAttribute.startLocation;
memberFunctionAttribute.accept(this);
}
override void visit(const Attribute attribute)
{
if (attribute.atAttribute !is null)
astInformation.atAttributeStartLocations ~= attribute.atAttribute.startLocation;
attribute.accept(this);
}
override void visit(const StorageClass storageClass)
{
if (storageClass.atAttribute !is null)
astInformation.atAttributeStartLocations ~= storageClass.atAttribute.startLocation;
storageClass.accept(this);
}
override void visit(const InContractExpression inContractExpression)
{
astInformation.contractLocations ~= inContractExpression.inTokenLocation;
inContractExpression.accept(this);
}
override void visit(const InStatement inStatement)
{
astInformation.contractLocations ~= inStatement.inTokenLocation;
inStatement.accept(this);
}
override void visit(const OutContractExpression outContractExpression)
{
astInformation.contractLocations ~= outContractExpression.outTokenLocation;
outContractExpression.accept(this);
}
override void visit(const OutStatement outStatement)
{
astInformation.contractLocations ~= outStatement.outTokenLocation;
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:
ASTInformation* astInformation;
alias visit = ASTVisitor.visit;
}

View File

@ -10,24 +10,13 @@ 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)
otbs,
/// $(LINK https://en.wikipedia.org/wiki/Indent_style#Variant:_Stroustrup)
stroustrup,
/// $(LINK https://en.wikipedia.org/wiki/Indentation_style#K&R_style)
knr,
}
enum TemplateConstraintStyle
{
_unspecified,
conditional_newline_indent,
conditional_newline,
always_newline,
always_newline_indent
stroustrup
}
/// Configuration options for formatting
@ -46,32 +35,15 @@ struct Config
///
OptionalBoolean dfmt_space_after_keywords;
///
OptionalBoolean dfmt_space_before_function_parameters;
///
OptionalBoolean dfmt_split_operator_at_line_end;
///
OptionalBoolean dfmt_selective_import_space;
///
OptionalBoolean dfmt_compact_labeled_statements;
///
TemplateConstraintStyle dfmt_template_constraint_style;
///
OptionalBoolean dfmt_single_template_constraint_indent;
///
OptionalBoolean dfmt_space_before_aa_colon;
///
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;
/**
* Initializes the standard EditorConfig properties with default values that
* make sense for D code.
@ -79,7 +51,7 @@ struct Config
void initializeWithDefaults()
{
pattern = "*.d";
end_of_line = EOL._default;
end_of_line = EOL.lf;
indent_style = IndentStyle.space;
indent_size = 4;
tab_width = 4;
@ -90,17 +62,9 @@ struct Config
dfmt_soft_max_line_length = 80;
dfmt_space_after_cast = OptionalBoolean.t;
dfmt_space_after_keywords = OptionalBoolean.t;
dfmt_space_before_function_parameters = OptionalBoolean.f;
dfmt_split_operator_at_line_end = OptionalBoolean.f;
dfmt_selective_import_space = OptionalBoolean.t;
dfmt_compact_labeled_statements = OptionalBoolean.t;
dfmt_template_constraint_style = TemplateConstraintStyle.conditional_newline_indent;
dfmt_single_template_constraint_indent = OptionalBoolean.f;
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

@ -2,7 +2,7 @@ module dfmt.editorconfig;
import std.regex : ctRegex;
static if (__VERSION__ >= 2067)
public import std.traits : FieldNameTuple;
import std.traits : FieldNameTuple;
else
{
private enum NameOf(alias T) = T.stringof;
@ -26,22 +26,21 @@ 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,
_default,
unspecified,
lf,
cr,
crlf
@ -62,10 +61,9 @@ mixin template StandardEditorConfigFields()
void merge(ref const typeof(this) other, const string fileName)
{
import dfmt.globmatch_editorconfig : globMatchEditorConfig;
import std.array : front, popFront, empty, save;
import std.path : globMatch;
if (other.pattern is null || !ecMatch(fileName, other.pattern))
if (other.pattern is null || !fileName.globMatch(other.pattern))
return;
foreach (N; FieldNameTuple!(typeof(this)))
{
@ -74,43 +72,16 @@ mixin template StandardEditorConfigFields()
auto thisN = &mixin("this." ~ N);
static if (N == "pattern")
continue;
else static if (is(T == enum))
*thisN = otherN != T._unspecified ? otherN : *thisN;
else static if (is(T == int))
else static if (is (T == enum))
*thisN = otherN != T.unspecified ? otherN : *thisN;
else static if (is (T == int))
*thisN = otherN != -1 ? otherN : *thisN;
else static if (is(T == string))
else static if (is (T == string))
*thisN = otherN !is null ? otherN : *thisN;
else
static assert(false);
}
}
private bool ecMatch(string fileName, string patt)
{
import std.algorithm : canFind;
import std.path : baseName;
import dfmt.globmatch_editorconfig : globMatchEditorConfig;
if (!pattern.canFind("/"))
fileName = fileName.baseName;
return fileName.globMatchEditorConfig(patt);
}
}
unittest
{
struct Config
{
mixin StandardEditorConfigFields;
}
Config config1;
Config config2;
config2.pattern = "test.d";
config2.end_of_line = EOL.crlf;
assert(config1.end_of_line != config2.end_of_line);
config1.merge(config2, "a/b/test.d");
assert(config1.end_of_line == config2.end_of_line);
}
/**
@ -123,19 +94,15 @@ EC getConfigFor(EC)(string path)
{
import std.stdio : File;
import std.regex : regex, match;
import std.path : globMatch, dirName, baseName, pathSplitter, buildPath,
absolutePath;
import std.path : globMatch, dirName, baseName, pathSplitter, buildPath;
import std.algorithm : reverse, map, filter;
import std.array : array;
import std.file : isDir;
EC result;
EC[][] configs;
immutable expanded = absolutePath(path);
immutable bool id = isDir(expanded);
immutable string fileName = id ? "dummy.d" : baseName(expanded);
string[] pathParts = cast(string[]) pathSplitter(expanded).array();
string dir = dirName(path);
immutable string fileName = baseName(path);
string[] pathParts = cast(string[]) pathSplitter(dir).array();
for (size_t i = pathParts.length; i > 1; i--)
{
EC[] sections = parseConfig!EC(buildPath(pathParts[0 .. i]));
@ -148,7 +115,6 @@ EC getConfigFor(EC)(string path)
static if (__VERSION__ >= 2067)
{
import std.algorithm : each;
configs.each!(a => a.each!(b => result.merge(b, fileName)))();
}
else

File diff suppressed because it is too large Load Diff

View File

@ -1,239 +0,0 @@
module dfmt.globmatch_editorconfig;
import std.path : CaseSensitive;
import std.range : isForwardRange, ElementEncodingType;
import std.traits : isSomeChar, isSomeString;
import std.range.primitives : empty, save, front, popFront;
import std.traits : Unqual;
import std.conv : to;
import std.path : filenameCharCmp, isDirSeparator;
// From std.path with changes:
// * 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
if (isForwardRange!Range && isSomeChar!(ElementEncodingType!Range)
&& isSomeChar!C && is(Unqual!C == Unqual!(ElementEncodingType!Range)))
in
{
// Verify that pattern[] is valid
import std.algorithm : balancedParens;
assert(balancedParens(pattern, '[', ']', 0));
assert(balancedParens(pattern, '{', '}', 0));
}
do
{
alias RC = Unqual!(ElementEncodingType!Range);
static if (RC.sizeof == 1 && isSomeString!Range)
{
import std.utf : byChar;
return globMatchEditorConfig!cs(path.byChar, pattern);
}
else static if (RC.sizeof == 2 && isSomeString!Range)
{
import std.utf : byWchar;
return globMatchEditorConfig!cs(path.byWchar, pattern);
}
else
{
C[] pattmp;
foreach (ref pi; 0 .. pattern.length)
{
const pc = pattern[pi];
switch (pc)
{
case '*':
if (pi < pattern.length - 1 && pattern[pi + 1] == '*')
{
if (pi + 2 == pattern.length)
return true;
for (; !path.empty; path.popFront())
{
auto p = path.save;
if (globMatchEditorConfig!(cs, C)(p, pattern[pi + 2 .. pattern.length]))
return true;
}
return false;
}
else
{
if (pi + 1 == pattern.length)
return true;
for (; !path.empty; path.popFront())
{
auto p = path.save;
//if (p[0].to!dchar.isDirSeparator() && !pattern[pi+1].isDirSeparator())
// return false;
if (globMatchEditorConfig!(cs, C)(p, pattern[pi + 1 .. pattern.length]))
return true;
if (p[0].to!dchar.isDirSeparator())
return false;
}
return false;
}
case '?':
if (path.empty)
return false;
path.popFront();
break;
case '[':
if (path.empty)
return false;
auto nc = path.front;
path.popFront();
auto not = false;
++pi;
if (pattern[pi] == '!')
{
not = true;
++pi;
}
auto anymatch = false;
while (1)
{
const pc2 = pattern[pi];
if (pc2 == ']')
break;
if (!anymatch && (filenameCharCmp!cs(nc, pc2) == 0))
anymatch = true;
++pi;
}
if (anymatch == not)
return false;
break;
case '{':
// find end of {} section
auto piRemain = pi;
for (; piRemain < pattern.length && pattern[piRemain] != '}'; ++piRemain)
{
}
if (piRemain < pattern.length)
++piRemain;
++pi;
while (pi < pattern.length)
{
const pi0 = pi;
C pc3 = pattern[pi];
// find end of current alternative
for (; pi < pattern.length && pc3 != '}' && pc3 != ','; ++pi)
{
pc3 = pattern[pi];
}
auto p = path.save;
if (pi0 == pi)
{
if (globMatchEditorConfig!(cs, C)(p, pattern[piRemain .. $]))
{
return true;
}
++pi;
}
else
{
/* Match for:
* pattern[pi0..pi-1] ~ pattern[piRemain..$]
*/
if (pattmp.ptr == null) // Allocate this only once per function invocation.
// Should do it with malloc/free, but that would make it impure.
pattmp = new C[pattern.length];
const len1 = pi - 1 - pi0;
pattmp[0 .. len1] = pattern[pi0 .. pi - 1];
const len2 = pattern.length - piRemain;
pattmp[len1 .. len1 + len2] = pattern[piRemain .. $];
if (globMatchEditorConfig!(cs, C)(p, pattmp[0 .. len1 + len2]))
{
return true;
}
}
if (pc3 == '}')
{
break;
}
}
return false;
default:
if (path.empty)
return false;
if (filenameCharCmp!cs(pc, path.front) != 0)
return false;
path.popFront();
break;
}
}
return path.empty;
}
}
unittest
{
assert(globMatchEditorConfig!(CaseSensitive.no)("foo", "Foo"));
assert(!globMatchEditorConfig!(CaseSensitive.yes)("foo", "Foo"));
assert(globMatchEditorConfig("foo", "*"));
assert(globMatchEditorConfig("foo.bar"w, "*"w));
assert(globMatchEditorConfig("foo.bar"d, "*.*"d));
assert(globMatchEditorConfig("foo.bar", "foo*"));
assert(globMatchEditorConfig("foo.bar"w, "f*bar"w));
assert(globMatchEditorConfig("foo.bar"d, "f*b*r"d));
assert(globMatchEditorConfig("foo.bar", "f???bar"));
assert(globMatchEditorConfig("foo.bar"w, "[fg]???bar"w));
assert(globMatchEditorConfig("foo.bar"d, "[!gh]*bar"d));
assert(!globMatchEditorConfig("foo", "bar"));
assert(!globMatchEditorConfig("foo"w, "*.*"w));
assert(!globMatchEditorConfig("foo.bar"d, "f*baz"d));
assert(!globMatchEditorConfig("foo.bar", "f*b*x"));
assert(!globMatchEditorConfig("foo.bar", "[gh]???bar"));
assert(!globMatchEditorConfig("foo.bar"w, "[!fg]*bar"w));
assert(!globMatchEditorConfig("foo.bar"d, "[fg]???baz"d));
assert(!globMatchEditorConfig("foo.di", "*.d")); // test issue 6634: triggered bad assertion
assert(globMatchEditorConfig("foo.bar", "{foo,bif}.bar"));
assert(globMatchEditorConfig("bif.bar"w, "{foo,bif}.bar"w));
assert(globMatchEditorConfig("bar.foo"d, "bar.{foo,bif}"d));
assert(globMatchEditorConfig("bar.bif", "bar.{foo,bif}"));
assert(globMatchEditorConfig("bar.fooz"w, "bar.{foo,bif}z"w));
assert(globMatchEditorConfig("bar.bifz"d, "bar.{foo,bif}z"d));
assert(globMatchEditorConfig("bar.foo", "bar.{biz,,baz}foo"));
assert(globMatchEditorConfig("bar.foo"w, "bar.{biz,}foo"w));
assert(globMatchEditorConfig("bar.foo"d, "bar.{,biz}foo"d));
assert(globMatchEditorConfig("bar.foo", "bar.{}foo"));
assert(globMatchEditorConfig("bar.foo"w, "bar.{ar,,fo}o"w));
assert(globMatchEditorConfig("bar.foo"d, "bar.{,ar,fo}o"d));
assert(globMatchEditorConfig("bar.o", "bar.{,ar,fo}o"));
assert(!globMatchEditorConfig("foo", "foo?"));
assert(!globMatchEditorConfig("foo", "foo[]"));
assert(!globMatchEditorConfig("foo", "foob"));
assert(!globMatchEditorConfig("foo", "foo{b}"));
assert(globMatchEditorConfig(`foo/foo\bar`, "f**b**r"));
assert(globMatchEditorConfig("foo", "**"));
assert(globMatchEditorConfig("foo/bar", "foo/bar"));
assert(globMatchEditorConfig("foo/bar", "foo/*"));
assert(globMatchEditorConfig("foo/bar", "*/bar"));
assert(globMatchEditorConfig("/foo/bar/gluu/sar.png", "**/sar.png"));
assert(globMatchEditorConfig("/foo/bar/gluu/sar.png", "**/*.png"));
assert(!globMatchEditorConfig("/foo/bar/gluu/sar.png", "*/sar.png"));
assert(!globMatchEditorConfig("/foo/bar/gluu/sar.png", "*/*.png"));
static assert(globMatchEditorConfig("foo.bar", "[!gh]*bar"));
}

View File

@ -5,11 +5,7 @@
module dfmt.indentation;
import dfmt.config;
import dfmt.editorconfig;
import dparse.lexer;
import std.bitmanip : bitfields;
import std.d.lexer;
/**
* Returns: true if the given token type is a wrap indent type
@ -17,15 +13,15 @@ import std.bitmanip : bitfields;
bool isWrapIndent(IdType type) pure nothrow @nogc @safe
{
return type != tok!"{" && type != tok!"case" && type != tok!"@"
&& type != tok!"]" && type != tok!"(" && type != tok!")" && isOperator(type);
&& type != tok!"]" && isOperator(type);
}
/**
* Returns: true if the given token type is a temporary indent type
* Returns: true if the given token type is a wrap indent type
*/
bool isTempIndent(IdType type) pure nothrow @nogc @safe
{
return type != tok!")" && type != tok!"{" && type != tok!"case" && type != tok!"@";
return type != tok!"{" && type != tok!"case" && type != tok!"@";
}
/**
@ -33,33 +29,9 @@ bool isTempIndent(IdType type) pure nothrow @nogc @safe
*/
struct IndentStack
{
/// Configuration
private const Config* config;
this(const Config* config)
{
this.config = config;
}
static struct Details
{
mixin(bitfields!(
// generally true for all operators except {, case, @, ], (, )
bool, "wrap", 1,
// temporary indentation which get's reverted when a block starts
// generally true for all tokens except ), {, case, @
bool, "temp", 1,
// emit minimal newlines
bool, "mini", 1,
// for associative arrays or arrays containing them, break after every item
bool, "breakEveryItem", 1,
// when an item inside an array would break mid-item, definitely break at the comma first
bool, "preferLongBreaking", 1,
uint, "", 27));
}
/**
* Get the indent size at the most recent occurrence of the given indent type
* Modifies the indent stack to match the state that it had at the most
* recent appearance of the given token type.
*/
int indentToMostRecent(IdType item) const
{
@ -84,7 +56,7 @@ struct IndentStack
int tempIndentCount = 0;
for (size_t i = index; i > 0; i--)
{
if (!details[i - 1].wrap && arr[i - 1] != tok!"]")
if (!isWrapIndent(arr[i - 1]) && arr[i - 1] != tok!"]")
break;
tempIndentCount++;
}
@ -95,27 +67,9 @@ struct IndentStack
* Pushes the given indent type on to the stack.
*/
void push(IdType item) pure nothrow
{
Details detail;
detail.wrap = isWrapIndent(item);
detail.temp = isTempIndent(item);
push(item, detail);
}
/**
* Pushes the given indent type on to the stack.
*/
void push(IdType item, Details detail) pure nothrow
{
arr[index] = item;
details[index] = detail;
//FIXME this is actually a bad thing to do,
//we should not just override when the stack is
//at it's limit
if (index < arr.length)
{
index++;
}
index = index + 1 == arr.length ? index : index + 1;
}
/**
@ -123,8 +77,7 @@ struct IndentStack
*/
void pop() pure nothrow
{
if (index)
index--;
index = index == 0 ? index : index - 1;
}
/**
@ -132,7 +85,7 @@ struct IndentStack
*/
void popWrapIndents() pure nothrow @safe @nogc
{
while (index > 0 && details[index - 1].wrap)
while (index > 0 && isWrapIndent(arr[index - 1]))
index--;
}
@ -141,18 +94,10 @@ struct IndentStack
*/
void popTempIndents() pure nothrow @safe @nogc
{
while (index > 0 && details[index - 1].temp)
while (index > 0 && isTempIndent(arr[index - 1]))
index--;
}
bool topAre(IdType[] types...)
{
if (types.length > index)
return false;
return arr[index - types.length .. index] == types;
}
/**
* Returns: `true` if the top of the indent stack is the given indent type.
*/
@ -166,15 +111,7 @@ struct IndentStack
*/
bool topIsTemp()
{
return index > 0 && index <= arr.length && details[index - 1].temp;
}
/**
* Returns: `true` if the top of the indent stack is a temporary indent with the specified token
*/
bool topIsTemp(IdType item)
{
return index > 0 && index <= arr.length && arr[index - 1] == item && details[index - 1].temp;
return index > 0 && index <= arr.length && isTempIndent(arr[index - 1]);
}
/**
@ -182,15 +119,7 @@ struct IndentStack
*/
bool topIsWrap()
{
return index > 0 && index <= arr.length && details[index - 1].wrap;
}
/**
* Returns: `true` if the top of the indent stack is a temporary indent with the specified token
*/
bool topIsWrap(IdType item)
{
return index > 0 && index <= arr.length && arr[index - 1] == item && details[index - 1].wrap;
return index > 0 && index <= arr.length && isWrapIndent(arr[index - 1]);
}
/**
@ -213,11 +142,6 @@ struct IndentStack
return arr[index - 1];
}
Details topDetails() const pure nothrow @property @safe @nogc
{
return details[index - 1];
}
int indentLevel() const pure nothrow @property @safe @nogc
{
return indentSize();
@ -228,93 +152,34 @@ struct IndentStack
return cast(int) index;
}
/**
* 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
{
import dparse.lexer : str;
import std.algorithm.iteration : map;
import std.stdio : stderr;
if (pos == size_t.max)
stderr.writefln("\033[31m%s:%d %(%s %)\033[0m", file, line, arr[0 .. index].map!(a => str(a)));
else
stderr.writefln("\033[31m%s:%d at %d %(%s %)\033[0m", file, line, pos, arr[0 .. index].map!(a => str(a)));
}
private:
size_t index;
IdType[256] arr;
Details[arr.length] details;
int indentSize(const size_t k = size_t.max) const pure nothrow @safe @nogc
{
import std.algorithm : among;
if (index == 0 || k == 0)
return 0;
immutable size_t j = k == size_t.max ? index : k;
int size = 0;
int parenCount;
foreach (i; 0 .. j)
{
immutable int pc = (arr[i] == tok!"!" || arr[i] == tok!"(" || arr[i] == tok!")") ? parenCount + 1
: parenCount;
if ((details[i].wrap || arr[i] == tok!"(") && parenCount > 1)
{
parenCount = pc;
continue;
}
if (i + 1 < index)
{
if (config.dfmt_single_indent == OptionalBoolean.t && skipDoubleIndent(i, parenCount))
{
parenCount = pc;
if (arr[i] == tok!"]")
continue;
immutable bool currentIsTemp = isTempIndent(arr[i]);
immutable bool nextIsTemp = isTempIndent(arr[i + 1]);
immutable bool nextIsSwitch = arr[i + 1] == tok!"switch";
if (currentIsTemp && (!nextIsTemp || nextIsSwitch))
continue;
}
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!"{"))
{
parenCount = pc;
continue;
}
if (currentIsNonWrapTemp && (arr[i + 1] == tok!"switch"
|| arr[i + 1] == tok!"{" || arr[i + 1] == tok!")"))
{
parenCount = pc;
continue;
}
}
else if (parenCount == 0 && arr[i] == tok!"(" && config.dfmt_single_indent == OptionalBoolean.f)
size++;
if (arr[i] == tok!"!")
size++;
parenCount = pc;
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

View File

@ -5,46 +5,18 @@
module dfmt.main;
import std.string : strip;
static immutable VERSION = () {
debug
{
enum DEBUG_SUFFIX = "-debug";
}
else
{
enum DEBUG_SUFFIX = "";
}
version (built_with_dub)
{
enum DFMT_VERSION = import("dubhash.txt").strip;
}
else
{
/**
* Current build's Git commit hash
*/
enum DFMT_VERSION = import("githash.txt").strip;
}
return DFMT_VERSION ~ DEBUG_SUFFIX;
} ();
version (NoMain)
{
}
else
{
import std.array : front, popFront;
import std.stdio : stdout, stdin, stderr, writeln, File;
import dfmt.config : Config;
import dfmt.editorconfig : getConfigFor;
import dfmt.formatter : format;
import std.array : appender, front, popFront;
import std.path : buildPath, expandTilde;
import dfmt.editorconfig : getConfigFor;
import std.getopt : getopt, GetOptException;
import std.path : buildPath, dirName, expandTilde;
import std.stdio : File, stderr, stdin, stdout, writeln;
int main(string[] args)
{
@ -52,17 +24,13 @@ else
Config optConfig;
optConfig.pattern = "*.d";
bool showHelp;
bool showVersion;
string explicitConfigDir;
void handleBooleans(string option, string value)
{
import dfmt.editorconfig : OptionalBoolean;
import std.exception : enforce;
enforce!GetOptException(value == "true" || value == "false", "Invalid argument");
immutable OptionalBoolean optVal = value == "true" ? OptionalBoolean.t
: OptionalBoolean.f;
import std.exception : enforceEx;
enforceEx!GetOptException(value == "true" || value == "false", "Invalid argument");
immutable OptionalBoolean optVal = value == "true" ? OptionalBoolean.t : OptionalBoolean.f;
switch (option)
{
case "align_switch_statements":
@ -74,9 +42,6 @@ else
case "space_after_cast":
optConfig.dfmt_space_after_cast = optVal;
break;
case "space_before_function_parameters":
optConfig.dfmt_space_before_function_parameters = optVal;
break;
case "split_operator_at_line_end":
optConfig.dfmt_split_operator_at_line_end = optVal;
break;
@ -86,63 +51,28 @@ else
case "compact_labeled_statements":
optConfig.dfmt_compact_labeled_statements = optVal;
break;
case "single_template_constraint_indent":
optConfig.dfmt_single_template_constraint_indent = optVal;
break;
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");
default: assert(false, "Invalid command-line switch");
}
}
try
{
// dfmt off
getopt(args,
"version", &showVersion,
"align_switch_statements", &handleBooleans,
"brace_style", &optConfig.dfmt_brace_style,
"config|c", &explicitConfigDir,
"end_of_line", &optConfig.end_of_line,
"help|h", &showHelp,
"indent_size", &optConfig.indent_size,
"indent_style|t", &optConfig.indent_style,
"inplace|i", &inplace,
"inplace", &inplace,
"max_line_length", &optConfig.max_line_length,
"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,
"reflow_property_chains", &handleBooleans);
// dfmt on
"tab_width", &optConfig.tab_width);
}
catch (GetOptException e)
{
@ -150,12 +80,6 @@ else
return 1;
}
if (showVersion)
{
writeln(VERSION);
return 0;
}
if (showHelp)
{
printHelp();
@ -164,62 +88,22 @@ else
args.popFront();
immutable bool readFromStdin = args.length == 0;
immutable string filePath = createFilePath(readFromStdin, readFromStdin ? null : args[0]);
Config config;
config.initializeWithDefaults();
Config fileConfig = getConfigFor!Config(filePath);
fileConfig.pattern = "*.d";
config.merge(fileConfig, filePath);
config.merge(optConfig, filePath);
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 = stdout.fileno;
_setmode(fd, _O_BINARY);
version (CRuntime_DigitalMars)
{
import core.atomic : atomicOp;
import core.stdc.stdio : __fhnd_info, FHND_TEXT;
atomicOp!"&="(__fhnd_info[fd], ~FHND_TEXT);
}
}
}
ubyte[] buffer;
Config explicitConfig;
if (explicitConfigDir)
{
import std.file : exists, isDir;
if (!exists(explicitConfigDir) || !isDir(explicitConfigDir))
{
stderr.writeln("--config|c must specify existing directory path");
if (!config.isValid())
return 1;
}
explicitConfig = getConfigFor!Config(explicitConfigDir);
explicitConfig.pattern = "*.d";
}
File output = stdout;
ubyte[] buffer;
if (readFromStdin)
{
import std.file : getcwd;
auto cwdDummyPath = buildPath(getcwd(), "dummy.d");
Config config;
config.initializeWithDefaults();
if (explicitConfigDir != "")
{
config.merge(explicitConfig, buildPath(explicitConfigDir, "dummy.d"));
}
else
{
Config fileConfig = getConfigFor!Config(getcwd());
fileConfig.pattern = "*.d";
config.merge(fileConfig, cwdDummyPath);
}
config.merge(optConfig, cwdDummyPath);
if (!config.isValid())
return 1;
ubyte[4096] inputBuffer;
ubyte[] b;
while (true)
@ -230,9 +114,7 @@ else
else
break;
}
immutable bool formatSuccess = format("stdin", buffer,
stdout.lockingTextWriter(), &config);
return formatSuccess ? 0 : 1;
dfmt.formatter.format("stdin", buffer, output.lockingTextWriter(), &config);
}
else
{
@ -240,7 +122,6 @@ else
if (args.length >= 2)
inplace = true;
int retVal;
while (args.length > 0)
{
const path = args.front;
@ -249,115 +130,46 @@ else
{
inplace = true;
foreach (string name; dirEntries(path, "*.d", SpanMode.depth))
{
args ~= name;
}
continue;
}
Config config;
config.initializeWithDefaults();
if (explicitConfigDir != "")
{
config.merge(explicitConfig, buildPath(explicitConfigDir, "dummy.d"));
}
else
{
Config fileConfig = getConfigFor!Config(path);
fileConfig.pattern = "*.d";
config.merge(fileConfig, path);
}
config.merge(optConfig, path);
if (!config.isValid())
return 1;
File f = File(path);
// ignore empty files
if (f.size)
{
buffer = new ubyte[](cast(size_t) f.size);
f.rawRead(buffer);
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;
output = File(path, "wb");
dfmt.formatter.format(path, buffer, output.lockingTextWriter(), &config);
}
}
return retVal;
return 0;
}
}
}
private version (Windows)
{
version(CRuntime_DigitalMars)
{
extern(C) int setmode(int, int) nothrow @nogc;
alias _setmode = setmode;
}
else version(CRuntime_Microsoft)
{
extern(C) int _setmode(int, int) nothrow @nogc;
}
}
template optionsToString(E) if (is(E == enum))
{
import std.algorithm.searching : startsWith;
enum optionsToString = () {
string result = "(";
foreach (s; [__traits(allMembers, E)])
{
if (!s.startsWith("_"))
result ~= s ~ "|";
}
result = result[0 .. $ - 1] ~ ")";
return result;
} ();
}
private void printHelp()
{
writeln(`dfmt `, VERSION, `
https://github.com/dlang-community/dfmt
writeln(`dfmt 0.4.0-beta
Options:
--help, -h Print this help message
--inplace, -i Edit files in place
--config, -c Path to directory to load .editorconfig file from.
--version Print the version number and then exit
--help | -h Print this help message
--inplace Edit files in place
Formatting Options:
--align_switch_statements
--brace_style `, optionsToString!(typeof(Config.dfmt_brace_style)),
`
--end_of_line `, optionsToString!(typeof(Config.end_of_line)), `
--brace_style
--end_of_line
--help|h
--indent_size
--indent_style, -t `,
optionsToString!(typeof(Config.indent_style)), `
--keep_line_breaks
--indent_style|t
--inplace
--soft_max_line_length
--max_line_length
--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)));
--compact_labeled_statements`);
}
private string createFilePath(bool readFromStdin, string fileName)

View File

@ -5,38 +5,15 @@
module dfmt.tokens;
import dparse.lexer;
import std.d.lexer;
/// Length of an invalid token
enum int INVALID_TOKEN_LENGTH = -1;
uint betweenParenLength(const Token[] tokens) pure @safe @nogc
in
{
assert(tokens[0].type == tok!"(");
}
do
{
uint length = 0;
size_t i = 1;
int depth = 1;
while (i < tokens.length && depth > 0)
{
if (tokens[i].type == tok!"(")
depth++;
else if (tokens[i].type == tok!")")
depth--;
length += tokenLength(tokens[i]);
i++;
}
return length;
}
int tokenLength(ref const Token t) pure @safe @nogc
{
import std.algorithm : countUntil;
int c;
switch (t.type)
{
case tok!"doubleLiteral":
@ -56,7 +33,7 @@ int tokenLength(ref const Token t) pure @safe @nogc
case tok!"wstringLiteral":
case tok!"dstringLiteral":
// TODO: Unicode line breaks and old-Mac line endings
c = cast(int) t.text.countUntil('\n');
auto c = cast(int) t.text.countUntil('\n');
if (c == -1)
return cast(int) t.text.length;
else
@ -112,7 +89,6 @@ bool isBreakToken(IdType t) pure nothrow @safe @nogc
case tok!"/":
case tok!"..":
case tok!"*=":
case tok!"*":
case tok!"&=":
case tok!"%=":
case tok!"%":
@ -127,19 +103,19 @@ bool isBreakToken(IdType t) pure nothrow @safe @nogc
}
}
int breakCost(IdType p, IdType c) pure nothrow @safe @nogc
int breakCost(IdType t) pure nothrow @safe @nogc
{
switch (c)
switch (t)
{
case tok!"||":
case tok!"&&":
case tok!",":
case tok!"?":
return 0;
case tok!"(":
return 60;
case tok!"[":
return 300;
return 400;
case tok!":":
case tok!";":
case tok!"^^":
case tok!"^=":
@ -170,11 +146,11 @@ int breakCost(IdType p, IdType c) pure nothrow @safe @nogc
case tok!"!=":
case tok!"!>=":
case tok!"!>":
case tok!"?":
case tok!"/=":
case tok!"/":
case tok!"..":
case tok!"*=":
case tok!"*":
case tok!"&=":
case tok!"%=":
case tok!"%":
@ -183,12 +159,8 @@ int breakCost(IdType p, IdType c) pure nothrow @safe @nogc
case tok!"~":
case tok!"+=":
return 200;
case tok!":":
// colon could be after a label or an import, where it should normally wrap like before
// for everything else (associative arrays) try not breaking around colons
return p == tok!"identifier" ? 0 : 300;
case tok!".":
return p == tok!")" ? 0 : 300;
return 900;
default:
return 1000;
}
@ -198,9 +170,10 @@ pure nothrow @safe @nogc unittest
{
foreach (ubyte u; 0 .. ubyte.max)
if (isBreakToken(u))
assert(breakCost(tok!".", u) != 1000);
assert(breakCost(u) != 1000);
}
private string generateFixedLengthCases()
{
import std.algorithm : map;
@ -210,32 +183,34 @@ private string generateFixedLengthCases()
assert(__ctfe);
string[] spacedOperatorTokens = [
",", "..", "...", "/", "/=", "!", "!<", "!<=", "!<>", "!<>=", "!=",
"!>", "!>=", "%", "%=", "&", "&&", "&=", "*", "*=", "+", "+=", "-",
"-=", ":", ";", "<", "<<", "<<=", "<=", "<>", "<>=", "=", "==", "=>",
">", ">=", ">>", ">>=", ">>>", ">>>=", "?", "@", "^", "^=", "^^",
"^^=", "|", "|=", "||", "~", "~="
",", "..", "...", "/", "/=", "!", "!<", "!<=", "!<>", "!<>=", "!=", "!>",
"!>=", "%", "%=", "&", "&&", "&=", "*", "*=", "+", "+=", "-", "-=", ":",
";", "<", "<<", "<<=", "<=", "<>", "<>=", "=", "==", "=>", ">", ">=",
">>", ">>=", ">>>", ">>>=", "?", "@", "^", "^=", "^^", "^^=", "|", "|=", "||",
"~", "~="
];
immutable spacedOperatorTokenCases = spacedOperatorTokens.map!(
a => format(`case tok!"%s": return %d + 1;`, a, a.length)).join("\n\t");
string[] identifierTokens = [
"abstract", "alias", "align", "asm", "assert", "auto", "bool",
"break", "byte", "case", "cast", "catch", "cdouble", "cent", "cfloat", "char", "class",
"const", "continue", "creal", "dchar", "debug", "default", "delegate", "delete", "deprecated",
"do", "double", "else", "enum", "export", "extern", "false", "final", "finally", "float",
"for", "foreach", "foreach_reverse", "function", "goto", "idouble", "if", "ifloat", "immutable",
"import", "in", "inout", "int", "interface", "invariant", "ireal", "is",
"lazy", "long", "macro", "mixin", "module", "new", "nothrow", "null", "out", "override",
"package", "pragma", "private", "protected", "public", "pure", "real", "ref", "return", "scope",
"shared", "short", "static", "struct", "super", "switch", "synchronized", "template", "this",
"throw", "true", "try", "typedef", "typeid", "typeof", "ubyte", "ucent", "uint", "ulong",
"union", "unittest", "ushort", "version", "void", "wchar",
"while", "with", "__DATE__", "__EOF__", "__FILE__",
"__FUNCTION__", "__gshared", "__LINE__", "__MODULE__", "__parameters",
"__PRETTY_FUNCTION__", "__TIME__", "__TIMESTAMP__",
"__traits", "__vector", "__VENDOR__", "__VERSION__", "$", "++", "--",
".", "[", "]", "(", ")", "{", "}"
"abstract", "alias", "align", "asm", "assert", "auto", "body", "bool",
"break", "byte", "case", "cast", "catch", "cdouble", "cent", "cfloat",
"char", "class", "const", "continue", "creal", "dchar", "debug",
"default", "delegate", "delete", "deprecated", "do", "double", "else",
"enum", "export", "extern", "false", "final", "finally", "float", "for",
"foreach", "foreach_reverse", "function", "goto", "idouble", "if",
"ifloat", "immutable", "import", "in", "inout", "int", "interface",
"invariant", "ireal", "is", "lazy", "long", "macro", "mixin", "module",
"new", "nothrow", "null", "out", "override", "package", "pragma",
"private", "protected", "public", "pure", "real", "ref", "return",
"scope", "shared", "short", "static", "struct", "super", "switch",
"synchronized", "template", "this", "throw", "true", "try", "typedef",
"typeid", "typeof", "ubyte", "ucent", "uint", "ulong", "union",
"unittest", "ushort", "version", "void", "volatile", "wchar", "while",
"with", "__DATE__", "__EOF__", "__FILE__", "__FUNCTION__", "__gshared",
"__LINE__", "__MODULE__", "__parameters", "__PRETTY_FUNCTION__",
"__TIME__", "__TIMESTAMP__", "__traits", "__vector", "__VENDOR__",
"__VERSION__", "$", "++", "--", ".", "[", "]", "(", ")", "{", "}"
];
immutable identifierTokenCases = identifierTokens.map!(
a => format(`case tok!"%s": return %d;`, a, a.length)).join("\n\t");

View File

@ -5,7 +5,7 @@
module dfmt.wrapping;
import dparse.lexer;
import std.d.lexer;
import dfmt.tokens;
import dfmt.config;
@ -18,50 +18,49 @@ struct State
import core.bitop : popcnt, bsf;
import std.algorithm : min, map, sum;
immutable int remainingCharsMultiplier = 25;
immutable int newlinePenalty = 480;
immutable int remainingCharsMultiplier = config.max_line_length - config.dfmt_soft_max_line_length;
immutable int newlinePenalty = remainingCharsMultiplier * 20;
this.breaks = breaks;
this._cost = 0;
this._solved = true;
int ll = currentLineLength;
if (breaks == 0)
{
immutable int l = currentLineLength + tokens.map!(a => tokenLength(a)).sum();
if (l > config.dfmt_soft_max_line_length)
{
immutable int longPenalty = (l - config.dfmt_soft_max_line_length)
* remainingCharsMultiplier;
immutable int longPenalty = (l - config.dfmt_soft_max_line_length) * remainingCharsMultiplier;
this._cost += longPenalty;
this._solved = longPenalty < newlinePenalty;
}
else
this._solved = true;
}
else
{
foreach (size_t i; 0 .. (uint.sizeof * 8))
for (size_t i = 0; i != uint.sizeof * 8; ++i)
{
if (((1 << i) & breaks) == 0)
continue;
immutable prevType = i > 0 ? tokens[i - 1].type : tok!"";
immutable currentType = tokens[i].type;
immutable b = tokens[i].type;
immutable p = abs(depths[i]);
immutable bc = breakCost(prevType, currentType) * (p == 0 ? 1 : p * 2);
this._cost += bc + newlinePenalty;
immutable bc = breakCost(b) * (p == 0 ? 1 : p * 2);
this._cost += bc;
}
int ll = currentLineLength;
size_t i = 0;
foreach (_; 0 .. uint.sizeof * 8)
{
immutable uint k = breaks >>> i;
immutable bool b = k == 0;
immutable uint bits = b ? ALGORITHMIC_COMPLEXITY_SUCKS : bsf(k);
immutable uint bits = b ? 0 : bsf(k);
immutable size_t j = min(i + bits + 1, tokens.length);
ll += tokens[i .. j].map!(a => tokenLength(a)).sum();
if (ll > config.dfmt_soft_max_line_length)
{
immutable int longPenalty = (ll - config.dfmt_soft_max_line_length)
* remainingCharsMultiplier;
immutable int longPenalty = (ll - config.dfmt_soft_max_line_length) * remainingCharsMultiplier;
this._cost += longPenalty;
}
if (ll > config.max_line_length)
@ -70,14 +69,12 @@ struct State
break;
}
i = j;
if (indentLevel < 0)
ll = (abs(indentLevel) + 1) * config.indent_size;
else
ll = (indentLevel + (i == 0 ? 0 : 1)) * config.indent_size;
ll = indentLevel * config.indent_size;
if (b)
break;
}
}
this._cost += popcnt(breaks) * newlinePenalty;
}
int cost() const pure nothrow @safe @property
@ -94,12 +91,13 @@ struct State
{
import core.bitop : bsf, popcnt;
if (_cost < other._cost)
if (_cost < other._cost || (_cost == other._cost && ((breaks != 0
&& other.breaks != 0 && bsf(breaks) > bsf(other.breaks))
|| (_solved && !other.solved))))
{
return -1;
if (_cost == other._cost && (breaks != 0 && other.breaks != 0
&& bsf(breaks) > bsf(other.breaks)))
return -1;
return _cost > other._cost;
}
return other._cost > _cost;
}
bool opEquals(ref const State other) const pure nothrow @safe
@ -119,12 +117,6 @@ private:
bool _solved;
}
private enum ALGORITHMIC_COMPLEXITY_SUCKS = uint.sizeof * 8;
/**
* Note: Negative values for `indentLevel` are treated specially: costs for
* continuation indents are reduced. This is used for array literals.
*/
size_t[] chooseLineBreakTokens(size_t index, const Token[] tokens,
immutable short[] depths, const Config* config, int currentLineLength, int indentLevel)
{
@ -142,36 +134,39 @@ size_t[] chooseLineBreakTokens(size_t index, const Token[] tokens,
return retVal;
}
enum ALGORITHMIC_COMPLEXITY_SUCKS = uint.sizeof * 8;
immutable size_t tokensEnd = min(tokens.length, ALGORITHMIC_COMPLEXITY_SUCKS);
auto open = new RedBlackTree!State;
open.insert(State(0, tokens[0 .. tokensEnd], depths[0 .. tokensEnd], config,
currentLineLength, indentLevel));
State lowest;
lowest._solved = false;
int tries = 0;
while (!open.empty && tries < 10_00)
while (!open.empty)
{
tries++;
State current = open.front();
if (current.cost < lowest.cost)
lowest = current;
open.removeFront();
if (current.solved)
{
return genRetVal(current.breaks, index);
if (current < lowest)
lowest = current;
validMoves!(typeof(open))(open, tokens[0 .. tokensEnd], depths[0 .. tokensEnd],
current.breaks, config, currentLineLength, indentLevel);
}
validMoves!(typeof(open))(open, tokens[0 .. tokensEnd],
depths[0 .. tokensEnd], current.breaks, config, currentLineLength, indentLevel);
}
if (open.empty)
return genRetVal(lowest.breaks, index);
foreach (r; open[].filter!(a => a.solved))
return genRetVal(r.breaks, index);
if (open[].front < lowest)
return genRetVal(open[].front.breaks, index);
else
return genRetVal(lowest.breaks, index);
assert(false);
}
void validMoves(OR)(auto ref OR output, const Token[] tokens, immutable short[] depths,
uint current, const Config* config, int currentLineLength, int indentLevel)
void validMoves(OR)(auto ref OR output, const Token[] tokens,
immutable short[] depths, uint current, const Config* config,
int currentLineLength, int indentLevel)
{
import std.algorithm : sort, canFind;
import std.array : insertInPlace;
foreach (i, token; tokens)
{
if (!isBreakToken(token.type) || (((1 << i) & current) != 0))

@ -1 +0,0 @@
Subproject commit ae237cabd1843774cc78aad0729c914a3dd579db

View File

@ -1,17 +0,0 @@
unittest
{
targets = [[RectangleShape.create(tex, vec2(-8 * scale, -32 * scale),
vec2(16 * scale, 48 * scale), vec4(14 / 16.0, 0, 16 / 16.0, 3 / 16.0)),
RectangleShape.create(tex, vec2(-8 * scale, -32 * scale), vec2(16 * scale,
32 * scale), vec4(14 / 16.0, 3 / 16.0, 16 / 16.0, 5 / 16.0))],
[RectangleShape.create(tex, vec2(-8 * scale, -8 * scale), vec2(16 * scale,
16 * scale), vec4(14 / 16.0, 5 / 16.0, 15 / 16.0, 6 / 16.0)), RectangleShape.create(tex,
vec2(-8 * scale, -8 * scale), vec2(16 * scale, 16 * scale),
vec4(15 / 16.0, 5 / 16.0, 16 / 16.0, 6 / 16.0))]];
int[][] foo = [[1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32], [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32]];
float[3][3] mat = [[234.3456,42435.8653,23.5],[3.245,235.3,234.664],[14324.6453,23434.645,9678.345]];
}
string[][] globalArray = [["123456789012345678901234567890", "123456789012345678901234567890"], ["123456789012345678901234567890", "123456789012345678901234567890"]];

View File

@ -1,38 +0,0 @@
unittest
{
targets = [
[
RectangleShape.create(tex, vec2(-8 * scale, -32 * scale),
vec2(16 * scale, 48 * scale), vec4(14 / 16.0, 0, 16 / 16.0, 3 / 16.0)),
RectangleShape.create(tex, vec2(-8 * scale, -32 * scale),
vec2(16 * scale, 32 * scale), vec4(14 / 16.0, 3 / 16.0, 16 / 16.0, 5 / 16.0))
],
[
RectangleShape.create(tex, vec2(-8 * scale, -8 * scale),
vec2(16 * scale, 16 * scale), vec4(14 / 16.0, 5 / 16.0, 15 / 16.0, 6 / 16.0)),
RectangleShape.create(tex, vec2(-8 * scale, -8 * scale),
vec2(16 * scale, 16 * scale), vec4(15 / 16.0, 5 / 16.0, 16 / 16.0, 6 / 16.0))
]
];
int[][] foo = [
[
1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19,
20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32
],
[
1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19,
20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32
]
];
float[3][3] mat = [
[234.3456, 42435.8653, 23.5], [3.245, 235.3, 234.664],
[14324.6453, 23434.645, 9678.345]
];
}
string[][] globalArray = [
["123456789012345678901234567890", "123456789012345678901234567890"],
["123456789012345678901234567890", "123456789012345678901234567890"]
];

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 +0,0 @@
unittest
{
foo([
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

@ -1,26 +0,0 @@
unittest
{
Bson base = Bson([
"maps": Bson([
Bson(["id": Bson(4), "comment": Bson("hello")]),
Bson(["id": Bson(49), "comment": Bson(null)])
]),
"short": Bson(["a": "b", "c": "d"]),
"numbers": Bson([
1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2,
3, 4, 5, 6, 7, 8, 9, 0
]),
"shuffleOnReset": serializeToBson([
"all": false,
"selected": true,
"maybe": false
]),
"resetOnEmpty": Bson(false),
"applyMods": Bson(true),
"sendComments": Bson(true)
]);
int[] x = [
1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3,
4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0
];
}

View File

@ -1,25 +0,0 @@
auto find()
{
return Map.findRange([
"$and": [
["deleted": Bson(false)],
[
"$or": Bson([
serializeToBson(["forceUpdate": Bson(true)]),
serializeToBson([
"info.approved": ["$eq": Bson(1)],
"fetchDate": [
"$lte": Bson(BsonDate(currentTime - 60.days))
]
]),
serializeToBson([
"info.approved": ["$ne": Bson(1)],
"fetchDate": [
"$lte": Bson(BsonDate(currentTime - 14.days))
]
])
])
]
]
]);
}

View File

@ -1,17 +0,0 @@
struct SomeStructName
{
static struct InnerStruct
{
version (linux)
{
static if (condition)
{
void longFunctionName(AAAAAAAA)(AAAAAAAA a) @property
if (someThingsAreTrue!AAAAAAAA && long_condition
&& is(elaborate == expression))
{
}
}
}
}
}

View File

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

View File

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

View File

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

View File

@ -1,8 +0,0 @@
void main()
{
if (true)
debug
{
foo();
}
}

View File

@ -1,7 +0,0 @@
void main()
{
debug (0)
foo();
else
bar();
}

View File

@ -1,21 +0,0 @@
int foo(int arg)
in
{
assert(arg > 0);
}
out (result)
{
assert(result == 0);
}
do
{
return 0;
}
int bar(int arg)
in (arg > 0)
out (; true)
out /*Major*/ ( /*Tom*/ result /*To ground control*/ ; result == 0)
{
return 0;
}

View File

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

View File

@ -1,6 +0,0 @@
enum Foo
{
deprecated member0,
@UDA(0) member1
}

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 @@
void foo(@UDA(0) @UDA(1) Bar bar);

View File

@ -3,7 +3,8 @@ import std.stdio, std.random, std.typecons, std.conv, std.string, std.range;
void main()
{
immutable interval = tuple(1, 100);
writefln("Guess my target number that is between " ~ "%d and %d (inclusive).\n", interval[]);
writefln("Guess my target number that is between " ~ "%d and %d (inclusive).\n",
interval[]);
immutable target = uniform!"[]"(interval[]);
foreach (immutable i; sequence!q{n})

View File

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

View File

@ -1,4 +1,3 @@
immutable NameId[] namesA = [
{"Aacgr", 0x00386}, // GREEK CAPITAL LETTER ALPHA WITH TONOS
{"aacgr", 0x003AC}, // GREEK SMALL LETTER ALPHA WITH TONOS
immutable NameId[] namesA = [{"Aacgr", 0x00386}, // GREEK CAPITAL LETTER ALPHA WITH TONOS
{"aacgr", 0x003AC}, // GREEK SMALL LETTER ALPHA WITH TONOS
];

View File

@ -10,27 +10,27 @@ string generateFixedLengthCases()
string[] fixedLengthTokens = [
"abstract", "alias", "align", "asm", "assert", "auto", "body", "bool",
"break", "byte", "case", "cast", "catch", "cdouble", "cent", "cfloat",
"char", "class", "const", "continue", "creal", "dchar", "debug", "default",
"delegate", "delete", "deprecated", "do", "double", "else", "enum",
"export", "extern", "false", "final", "finally", "float", "for", "foreach",
"foreach_reverse", "function", "goto", "idouble", "if", "ifloat",
"immutable", "import", "in", "inout", "int", "interface", "invariant",
"ireal", "is", "lazy", "long", "macro", "mixin", "module", "new",
"nothrow", "null", "out", "override", "package", "pragma", "private",
"protected", "public", "pure", "real", "ref", "return", "scope", "shared",
"short", "static", "struct", "super", "switch", "synchronized", "template",
"this", "throw", "true", "try", "typedef", "typeid", "typeof", "ubyte",
"ucent", "uint", "ulong", "union", "unittest", "ushort", "version", "void",
"volatile", "wchar", "while", "with", "__DATE__", "__EOF__",
"__FILE__", "__FUNCTION__", "__gshared", "__LINE__",
"__MODULE__", "__parameters", "__PRETTY_FUNCTION__", "__TIME__",
"__TIMESTAMP__", "__traits", "__vector", "__VENDOR__", "__VERSION__",
",", ".", "..", "...", "/", "/=", "!", "!<", "!<=", "!<>", "!<>=",
"!=", "!>", "!>=", "$", "%", "%=", "&", "&&", "&=", "(", ")", "*",
"*=", "+", "++", "+=", "-", "--", "-=", ":", ";", "<", "<<", "<<=",
"<=", "<>", "<>=", "=", "==", "=>", ">", ">=", ">>", ">>=", ">>>",
">>>=", "?", "@", "[", "]", "^", "^=", "^^", "^^=", "{", "|", "|=", "||",
"}", "~", "~="
"char", "class", "const", "continue", "creal", "dchar", "debug",
"default", "delegate", "delete", "deprecated", "do", "double", "else",
"enum", "export", "extern", "false", "final", "finally", "float",
"for", "foreach", "foreach_reverse", "function", "goto", "idouble",
"if", "ifloat", "immutable", "import", "in", "inout", "int",
"interface", "invariant", "ireal", "is", "lazy", "long", "macro",
"mixin", "module", "new", "nothrow", "null", "out", "override",
"package", "pragma", "private", "protected", "public", "pure", "real",
"ref", "return", "scope", "shared", "short", "static", "struct",
"super", "switch", "synchronized", "template", "this", "throw", "true",
"try", "typedef", "typeid", "typeof", "ubyte", "ucent", "uint",
"ulong", "union", "unittest", "ushort", "version", "void", "volatile",
"wchar", "while", "with", "__DATE__", "__EOF__", "__FILE__",
"__FUNCTION__", "__gshared", "__LINE__", "__MODULE__", "__parameters",
"__PRETTY_FUNCTION__", "__TIME__", "__TIMESTAMP__", "__traits",
"__vector", "__VENDOR__", "__VERSION__", ",", ".", "..", "...", "/",
"/=", "!", "!<", "!<=", "!<>", "!<>=", "!=", "!>", "!>=", "$", "%",
"%=", "&", "&&", "&=", "(", ")", "*", "*=", "+", "++", "+=", "-",
"--", "-=", ":", ";", "<", "<<", "<<=", "<=", "<>", "<>=", "=", "==",
"=>", ">", ">=", ">>", ">>=", ">>>", ">>>=", "?", "@", "[", "]", "^",
"^=", "^^", "^^=", "{", "|", "|=", "||", "}", "~", "~="
];
}

View File

@ -16,7 +16,8 @@ unittest
}
void doStuff(const Token[] tokens, ref const State current,
const FormatterConfig* formatterConfig, int currentLineLength, int indentLevel, int depth)
const FormatterConfig* formatterConfig, int currentLineLength, int indentLevel,
int depth)
{
return;
}

View File

@ -1,7 +1,7 @@
struct Test
{
this(string name, string[] aliasList, string briefDescription, string examDesc, string onOpenDesc,
string openDesc, string onCloseDesc, string closeDesc,
this(string name, string[] aliasList, string briefDescription, string examDesc,
string onOpenDesc, string openDesc, string onCloseDesc, string closeDesc,
Flag!"canOpen" canOpen, Flag!"canClose" canClose, Flag!"isOpen" isOpen)
{
}

View File

@ -1,15 +0,0 @@
unittest
{
testScene = new Scene("TestScene : Test", sceneDescriptions["TestScene"],
connectDescriptions["TestScene"], delegate(Scene scene) {
import std.stdio;
if (!scene.alreadyEntered)
{
fwriteln(
"This is a test. This is a test. This is a test. This is a test. This is a test. Test12.");
auto p = cast(Portal) sceneManager.previousScene;
scene.destroyCurrentScript();
}
});
}

View File

@ -1,15 +0,0 @@
unittest
{
testScene = new Scene(longArgument, longArgument, longArgument,
longArgument, longArgument, longArgument, delegate(Scene scene) {
import std.stdio;
if (!scene.alreadyEntered)
{
fwriteln(
"This is a test. This is a test. This is a test. This is a test. This is a test. Test12.");
auto p = cast(Portal) sceneManager.previousScene;
scene.destroyCurrentScript();
}
});
}

View File

@ -1,5 +1,5 @@
auto fun = function() {};
auto fun = () {};
auto fun = function() { };
auto fun = () { };
auto fun = {};
auto fun = { int i; };
@ -17,8 +17,9 @@ unittest
});
callFunc({
int i = 10;
foo(alpha_longVarName, bravo_longVarName, charlie_longVarName, delta_longVarName,
echo_longVarName, foxtrot_longVarName, golf_longVarName, echo_longVarName);
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 foo()
{
string command;
version (Posix)
command ~= " 2> /dev/null 1> /dev/null";
version (Posix)
command ~= " 2> /dev/null 1> /dev/null";
unittest
{
version (Posix)
command ~= " 2> /dev/null 1> /dev/null";
}
}

View File

@ -1,5 +1,5 @@
class Foo(T) : FirstInterfaceWithVeryLongName, SecondInterfaceWithVeryLongName
if (is(T : Bar))
class Foo(T) : FirstInterfaceWithVeryLongName,
SecondInterfaceWithVeryLongName if (is(T : Bar))
{
void foo()
{

View File

@ -1,6 +1,5 @@
@Foo enum Bar
{
a
}
@foo class Baz

View File

@ -1,7 +0,0 @@
final class FormatVisitor : ASTVisitor
{
this(ASTInformation* astInformation)
{
this.astInformation = astInformation;
}
}

View File

@ -1,5 +0,0 @@
void merge()
{
static if (is(T == enum))
*thisN = x;
}

View File

@ -1,29 +0,0 @@
unittest
{
{
}
//
{
}
}
unittest
{
{
}
//
{
}
}
unittest
{
{
}
//
{
}
}

View File

@ -1,15 +0,0 @@
unittest
{
do
++a;
while (true);
}
unittest
{
do
{
++a;
}
while (true);
}

View File

@ -1,29 +0,0 @@
void functionName()
{
}
void main()
{
static if (true)
{
if (true && {
functionName();
functionName();
functionName();
functionName();
return true;
}())
{
}
else
{
}
}
else
{
}
}

View File

@ -1,3 +0,0 @@
void doStuff(T)() @safe if (isNumeric!T)
{
}

View File

@ -1,21 +0,0 @@
unittest
{
Test("Something") in
{
abcde_abcde_abcde();
abcde_abcde_abcde();
abcde_abcde_abcde();
abcde_abcde_abcde();
abcde_abcde_abcde();
abcde_abcde_abcde();
};
}
void aFunction(ParamType param)
in
{
assert(stuff);
}
body
{
}

View File

@ -1,8 +0,0 @@
unittest
{
asm
{
dl 12345;
movdqu [R8], XMM0;
}
}

View File

@ -1,12 +0,0 @@
module test;
void main()
{
test("stringLiteral") in
{
foreach (thing; things)
{
doStuff(thing);
}
};
}

View File

@ -1,16 +0,0 @@
void main()
{
auto myTid = runTask({
auto conn = connectTCP("localhost", 4222);
auto l = Lexer(conn);
foreach (t; l)
{
}
conn.close();
});
// foo
runEventLoop();
}

View File

@ -1,13 +0,0 @@
version (Foo)
{
version (D_Version2)
{
public import core.memory;
}
else:
}
version (Bar)
int foo();
else:
int foo(int);

View File

@ -1,8 +0,0 @@
unittest
{
asm
{
}
d[] = a[];
c[] = d[];
}

View File

@ -1,8 +0,0 @@
unittest
{
import std.stdio : stderr;
{
a = 10;
}
}

View File

@ -1,11 +0,0 @@
enum a
{
a,
b,
c,
d,
/* a comment */
e,
f,
g
}

View File

@ -1,7 +0,0 @@
unittest
{
if (a && !is(b == q))
{
}
}

View File

@ -1,23 +0,0 @@
unittest
{
{
public Vector!(T) opBinary(string op, string file = __FILE__, size_t line = __LINE__)(
const Vector!(T) x) const if (op == "*")
in
{
}
body
{
}
}
}
public Vector!(T) opBinary(string op, string file = __FILE__, size_t line = __LINE__)(
const Vector!(T) x) const if (op == "*")
in
{
}
body
{
}

View File

@ -1,2 +0,0 @@
static assert(call(x) !is y);
static assert(call(x) is y);

View File

@ -1,4 +0,0 @@
enum
{
x = 3
}

View File

@ -1,6 +0,0 @@
version (linux)
import core.sys.linux.elf;
else version (FreeBSD)
import core.sys.freebsd.sys.elf;
else version (Solaris)
import core.sys.solaris.elf;

View File

@ -1,18 +0,0 @@
module example;
bool aTemplatedFunction(One)(One alpha) if (isNumeric!One)
{
}
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)
{
}
}
}

View File

@ -1,18 +0,0 @@
module example;
bool aTemplatedFunction(One)(One alpha) if (isNumeric!One)
{
}
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)
{
}
}
}

View File

@ -1,19 +0,0 @@
module example;
bool aTemplatedFunction(One)(One alpha)
if (isNumeric!One)
{
}
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)
{
}
}
}

View File

@ -1,19 +0,0 @@
module example;
bool aTemplatedFunction(One)(One alpha)
if (isNumeric!One)
{
}
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)
{
}
}
}

View File

@ -1,7 +0,0 @@
unittest
{
if (something || somethingElse || // I like putting comments here for no good reason
thirdThing)
{
}
}

View File

@ -1,6 +0,0 @@
@OneOf("group1")
{
JSONValue[string] fred;
bool mertz;
bool ethel;
}

View File

@ -1,68 +0,0 @@
static if (someCondition)
void doStuff()
{
}
else
void doStuff()
{
}
static if (someCondition)
void doStuff()
{
}
else static if (otherCondition)
void doStuff()
{
}
static if (someCondition)
void doStuff()
{
}
else static if (otherCondition)
void doStuff()
{
}
else
void doStuff()
{
}
static if (condition)
int a;
else
int b;
static if (condition)
int a;
else static if (otherCondition)
int c;
else
int b;
void doStuff();
static if (stuff)
int a;
else
class C
{
public:
void aFunction();
private:
int a;
int b;
}
static if (condition)
int a;
else
int b;
static if (condition)
int a;
else static if (otherCondition)
int c;
else
int b;

View File

@ -1,5 +0,0 @@
unittest
{
static if (stuff) // comment
things();
}

View File

@ -1,5 +0,0 @@
unittest
{
return (complicated % expression) / //-------------------
(other * complicated + expression);
}

View File

@ -1,7 +0,0 @@
unittest
{
if (info > 0)
throw new ExceptionWithLongName(std.string.format(
"During the LU factorization, it was found that the " ~ "%sth diagonal value is exactly zero.",
info), file, line);
}

View File

@ -1,6 +0,0 @@
unittest
{
int a, /// comment
b, /// comment
c; /// comment
}

View File

@ -1,5 +0,0 @@
static if (condition)
int declaration;
else
{
}

View File

@ -1,15 +0,0 @@
unittest
{
auto a = 1234567890 + 1234567890 + 1234567890 + 1234567890 + 1234567890
+ 1234567890 + 1234567890 + 1234567890 + 1234567890 + 1234567890
+ 1234567890 + 1234567890 + 1234567890 + 1234567890 + 1234567890
+ 1234567890 + 1234567890 + 1234567890;
auto a = 1234567890 - 1234567890 - 1234567890 - 1234567890 - 1234567890
- 1234567890 - 1234567890 - 1234567890 - 1234567890 - 1234567890
- 1234567890 - 1234567890 - 1234567890 - 1234567890 - 1234567890
- 1234567890 - 1234567890 - 1234567890;
auto a = 1234567890 * 1234567890 * 1234567890 * 1234567890 * 1234567890
* 1234567890 * 1234567890 * 1234567890 * 1234567890 * 1234567890
* 1234567890 * 1234567890 * 1234567890 * 1234567890 * 1234567890
* 1234567890 * 1234567890 * 1234567890;
}

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,24 +0,0 @@
enum
{
SQL_CA2_READ_ONLY_CONCURRENCY = 0x00000001L,
SQL_CA2_LOCK_CONCURRENCY = 0x00000002L,
SQL_CA2_OPT_ROWVER_CONCURRENCY = 0x00000004L,
SQL_CA2_OPT_VALUES_CONCURRENCY = 0x00000008L,
SQL_CA2_SENSITIVITY_ADDITIONS = 0x00000010L,
SQL_CA2_SENSITIVITY_DELETIONS = 0x00000020L,
SQL_CA2_SENSITIVITY_UPDATES = 0x00000040L,
// * semantics of SQL_ATTR_MAX_ROWS *
SQL_CA2_MAX_ROWS_SELECT = 0x00000080L,
SQL_CA2_MAX_ROWS_INSERT = 0x00000100L,
SQL_CA2_MAX_ROWS_DELETE = 0x00000200L,
SQL_CA2_MAX_ROWS_UPDATE = 0x00000400L,
SQL_CA2_MAX_ROWS_CATALOG = 0x00000800L,
SQL_CA2_MAX_ROWS_AFFECTS_ALL = (
SQL_CA2_MAX_ROWS_SELECT | SQL_CA2_MAX_ROWS_INSERT | SQL_CA2_MAX_ROWS_DELETE
| SQL_CA2_MAX_ROWS_UPDATE | SQL_CA2_MAX_ROWS_CATALOG),
SQL_CA2_CRC_EXACT = 0x00001000L,
SQL_CA2_CRC_APPROXIMATE = 0x00002000L,
SQL_CA2_SIMULATE_NON_UNIQUE = 0x00004000L,
SQL_CA2_SIMULATE_TRY_UNIQUE = 0x00008000L,
SQL_CA2_SIMULATE_UNIQUE = 0x00010000L
}

View File

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

View File

@ -1,4 +0,0 @@
void round()
body
{
}

View File

@ -1,5 +0,0 @@
enum Status : bool
{
abort = true,
ignore = false
}

View File

@ -1,23 +0,0 @@
unittest
{
with (Object)
{
// do something
}
with (Object) with (Object)
{
// do something
}
with (Object) with (Object) with (Object)
{
// do something
}
with (Object)
{
with (Object)
{
// do something
}
}
}

View File

@ -1,11 +0,0 @@
T[] arrayOp(T, Args...)(T res, Filter!(isType, Args) args) @trusted @nogc pure @things
if (Args[$ - 1] != "=")
{
}
T[] arrayOp(T, Args...)(T res, Filter!(isType, Args) args) @trusted @nogc pure nothrow
if (Args[$ - 1] != "=")
{
}

View File

@ -1,9 +0,0 @@
void stuff()
{
asm
{
int 80;
int 0b10;
int 0x80;
}
}

View File

@ -1,11 +0,0 @@
void main()
{
S s1 = {a: 3};
S s2 = {a: 3, b: "test string"};
S s3 = {a: 3, b: "test string", c: {x: 3.14, y: 3 + 4}};
T t = {
someStructMember1: 2, someStructMember2: 42, someStructMember3: null, // foobar
someOtherMember1: objA, someOtherMember2: objB, someOtherMember3: 0,
somethingMore: null, someFlagInThisStruct: -1
};
}

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