Compare commits
425 Commits
v0.4.0-bet
...
master
| Author | SHA1 | Date |
|---|---|---|
|
|
aa49b9035c | |
|
|
49612a48a6 | |
|
|
a12e83e8a4 | |
|
|
d8e43e23ec | |
|
|
0ea0572e86 | |
|
|
5ea76cd293 | |
|
|
fa463b472c | |
|
|
2ea6c43a66 | |
|
|
9f377100f0 | |
|
|
20b8badf8c | |
|
|
35e55bc9b2 | |
|
|
08fe5d6855 | |
|
|
c0452dbd11 | |
|
|
876bbe33c1 | |
|
|
1e765fb781 | |
|
|
c43803575d | |
|
|
470e65f7cc | |
|
|
6f41b20d5b | |
|
|
49b9fe4051 | |
|
|
fec7394175 | |
|
|
727472c365 | |
|
|
840aeee45e | |
|
|
a91f044958 | |
|
|
dba8c87ebc | |
|
|
a4fbc6f881 | |
|
|
57f57d95de | |
|
|
4a6078779a | |
|
|
e251e4343a | |
|
|
02070df593 | |
|
|
6744df20f3 | |
|
|
8d42254d47 | |
|
|
2a4af7a2b2 | |
|
|
026a58e273 | |
|
|
4947beec6b | |
|
|
d862d8aef1 | |
|
|
036da91542 | |
|
|
ed5fc2ffd2 | |
|
|
b8da7c5cd4 | |
|
|
f6d9d04e43 | |
|
|
f81ddeadbd | |
|
|
3e1e643972 | |
|
|
77e2ba4e3d | |
|
|
6a24f0dc7c | |
|
|
b776d5a9b9 | |
|
|
2beb819851 | |
|
|
f1e57135bb | |
|
|
e5e11604f0 | |
|
|
e8bd41c70d | |
|
|
b3b8ff1a43 | |
|
|
0e5615e13e | |
|
|
f6490b31c9 | |
|
|
995c21ab87 | |
|
|
821b9be9e9 | |
|
|
ea36fbf58b | |
|
|
0f61586438 | |
|
|
e35bde0815 | |
|
|
e79ba9f0c8 | |
|
|
3479e73707 | |
|
|
1f21a97713 | |
|
|
c4b6a7e7e3 | |
|
|
e6199aaa9b | |
|
|
e880e00e73 | |
|
|
41e8c05558 | |
|
|
7659b1ae1a | |
|
|
eab4cac12f | |
|
|
94351246f6 | |
|
|
d100c40dab | |
|
|
58b2c6ebc6 | |
|
|
b5dbb0e031 | |
|
|
e4f2f20720 | |
|
|
d92a6799ac | |
|
|
e5eda5c14a | |
|
|
f80bffcf84 | |
|
|
ad00b113a9 | |
|
|
83f8a4c65d | |
|
|
f59f25bb09 | |
|
|
09caf255e5 | |
|
|
34810aa928 | |
|
|
cb1dfe091f | |
|
|
7b955c18d1 | |
|
|
1964f807cf | |
|
|
ef83514541 | |
|
|
394da5d02a | |
|
|
66faac49f1 | |
|
|
e9034f4fec | |
|
|
b17304accd | |
|
|
c41c0349a2 | |
|
|
5f0d2843e6 | |
|
|
63a29ab757 | |
|
|
2dc19b6577 | |
|
|
fbd8559ceb | |
|
|
977318214d | |
|
|
4db5ba44b2 | |
|
|
399041c84f | |
|
|
d38c3d96bf | |
|
|
da51958770 | |
|
|
27929e4cc5 | |
|
|
0795a477f1 | |
|
|
8f779b33bf | |
|
|
024c6e6a63 | |
|
|
8c2076d4f2 | |
|
|
70bae7487e | |
|
|
79ae2c09d0 | |
|
|
28b32d9d77 | |
|
|
d33b878965 | |
|
|
a4d4d94a50 | |
|
|
30ab6e103d | |
|
|
3f141b272d | |
|
|
06881d8654 | |
|
|
ac8e34815f | |
|
|
b3946b7525 | |
|
|
05db8ae8fa | |
|
|
81c607a115 | |
|
|
1024f16715 | |
|
|
ac61efe767 | |
|
|
4fea171d2f | |
|
|
3af8edc57f | |
|
|
6d2a56e15e | |
|
|
f8f34ff097 | |
|
|
999c044020 | |
|
|
2cc1f59235 | |
|
|
436d157b4f | |
|
|
0878430125 | |
|
|
ac5f8b18aa | |
|
|
793a575b1c | |
|
|
313b886799 | |
|
|
54a84bd927 | |
|
|
b4e97d3381 | |
|
|
b34acc9f26 | |
|
|
dae7d85c80 | |
|
|
6b9eddde5d | |
|
|
a79a43a9dc | |
|
|
b00d3490bf | |
|
|
bdac7361a5 | |
|
|
7f41c8ae7f | |
|
|
989c0da60c | |
|
|
6dea7b689e | |
|
|
98cd73ec80 | |
|
|
eebd341343 | |
|
|
733898e013 | |
|
|
188c0dca03 | |
|
|
60b2cff18a | |
|
|
1da1ca6545 | |
|
|
48b2b84c33 | |
|
|
fcad21ba61 | |
|
|
85c7d57167 | |
|
|
053b775cd1 | |
|
|
6e4136a353 | |
|
|
3b094b16d9 | |
|
|
460096728b | |
|
|
c3537a5d51 | |
|
|
fc4cb9eecc | |
|
|
909164708a | |
|
|
ced64acae0 | |
|
|
bb679b1b6e | |
|
|
5508e9ced1 | |
|
|
f4417dc1b5 | |
|
|
fd1f2f5161 | |
|
|
67664c2835 | |
|
|
dc8e7a087c | |
|
|
5274e5531e | |
|
|
92d5e1ac8c | |
|
|
6ad2fbb6fc | |
|
|
3917c32925 | |
|
|
a1cb44eb80 | |
|
|
049f86ebfd | |
|
|
2578dbf2a7 | |
|
|
908f32e433 | |
|
|
18eea577f8 | |
|
|
b928eb6d84 | |
|
|
810e4b464f | |
|
|
6ff47e106a | |
|
|
72dd6e83b3 | |
|
|
c84db53c7c | |
|
|
f3463cdd34 | |
|
|
16c3811261 | |
|
|
886903f8ea | |
|
|
494f70b429 | |
|
|
dca9e15483 | |
|
|
5e6dd58502 | |
|
|
0fc4149907 | |
|
|
7fb46c9aa5 | |
|
|
647bb6daa9 | |
|
|
1fd19a1375 | |
|
|
ae76778801 | |
|
|
56097fd106 | |
|
|
4256f988bf | |
|
|
cff6eb908e | |
|
|
c58e54fe71 | |
|
|
46788e53ba | |
|
|
c66fea0fe5 | |
|
|
4fd89f1f41 | |
|
|
8f76cce8db | |
|
|
b416d72221 | |
|
|
2284d98ef7 | |
|
|
1753127e74 | |
|
|
c4b9178e81 | |
|
|
c2aea82395 | |
|
|
6eb7b95173 | |
|
|
c4e7335850 | |
|
|
08f73d216b | |
|
|
8c95061c1a | |
|
|
4168c232ab | |
|
|
25cdc1f885 | |
|
|
b3411a3303 | |
|
|
0167863b33 | |
|
|
eb576e21fd | |
|
|
0cc3543c2b | |
|
|
e535f0b2b0 | |
|
|
dca63110f7 | |
|
|
c4a7f9cb04 | |
|
|
b01c624ef0 | |
|
|
95905cdbf1 | |
|
|
8333180e27 | |
|
|
d04afa8ea7 | |
|
|
b545048ac1 | |
|
|
294c975d49 | |
|
|
4f7f37d664 | |
|
|
06d58ff83a | |
|
|
181f388d17 | |
|
|
4725a622c6 | |
|
|
358b6e91ea | |
|
|
5da7fd4dc9 | |
|
|
e9273c169e | |
|
|
aab2f07f16 | |
|
|
0b650cc5ae | |
|
|
40f3d5b0a8 | |
|
|
c697d88bb2 | |
|
|
851434ce9d | |
|
|
35d7da7391 | |
|
|
fc3232308a | |
|
|
89b890241d | |
|
|
5ce4df17a2 | |
|
|
2856641b12 | |
|
|
a8ac400830 | |
|
|
763d61031c | |
|
|
f0b34c9889 | |
|
|
8cebd50ea6 | |
|
|
5aedb2b84b | |
|
|
19a869377a | |
|
|
0a351990c2 | |
|
|
ef0c81876a | |
|
|
1ca3bd9255 | |
|
|
19e774ebf7 | |
|
|
060d3f5a80 | |
|
|
0b71891072 | |
|
|
30f1d2c8c0 | |
|
|
a58be55592 | |
|
|
96948fd0da | |
|
|
6e598c197d | |
|
|
d88e1fa5dd | |
|
|
6887982cb2 | |
|
|
7004683d9d | |
|
|
d8f9cfeae1 | |
|
|
23bd2b408c | |
|
|
ddd86f96d8 | |
|
|
82ec339251 | |
|
|
aa45bda1a8 | |
|
|
4feb467dab | |
|
|
01a1716183 | |
|
|
5ed20e0a3c | |
|
|
b69e966df6 | |
|
|
8cd9265384 | |
|
|
abc3e6d47e | |
|
|
a163eb105f | |
|
|
b227c66146 | |
|
|
d1974d95fb | |
|
|
ab45e03701 | |
|
|
0847016346 | |
|
|
9b4de1a3e5 | |
|
|
797b4f2005 | |
|
|
6de8ff2037 | |
|
|
ec2e223b9a | |
|
|
3559aa9e52 | |
|
|
1c22b3d5e1 | |
|
|
00fda4f5eb | |
|
|
cc39c3fce4 | |
|
|
e35d41d75e | |
|
|
2de336c39e | |
|
|
7f472d8ddf | |
|
|
02a735cb0c | |
|
|
02ba81333e | |
|
|
87fd168e06 | |
|
|
7c0e4747ed | |
|
|
45c2a961a6 | |
|
|
2645e9cc1f | |
|
|
aa93473702 | |
|
|
aba1116775 | |
|
|
ea72aa5492 | |
|
|
7480230ee1 | |
|
|
31e498f3b0 | |
|
|
f26f1f28bd | |
|
|
fef85e388a | |
|
|
7f9e6ac7b5 | |
|
|
50a3241f04 | |
|
|
b7c3a3686b | |
|
|
80fe7c02e6 | |
|
|
8361a3a153 | |
|
|
a93efb66fb | |
|
|
0e5d314eb5 | |
|
|
a7f6a0007a | |
|
|
019d42a4dc | |
|
|
9fb13d0caf | |
|
|
fcd2b50e60 | |
|
|
98aad22f67 | |
|
|
4a4704896b | |
|
|
b50d36bf12 | |
|
|
d95d69e31b | |
|
|
593b9885ff | |
|
|
7961bfc15f | |
|
|
5da2a71a67 | |
|
|
821f9439e4 | |
|
|
e3bf26987b | |
|
|
e92b90bbf8 | |
|
|
90b68b7e57 | |
|
|
afd5799eb1 | |
|
|
c353f484a6 | |
|
|
d6861cc5a2 | |
|
|
049b151bac | |
|
|
2d18ded428 | |
|
|
0f7727e31b | |
|
|
2031dbdc71 | |
|
|
789019fc86 | |
|
|
2145766d89 | |
|
|
09867bc3e5 | |
|
|
1392ef52cf | |
|
|
1a80fd742a | |
|
|
d7737c0da5 | |
|
|
649ee08e62 | |
|
|
be6f5706ae | |
|
|
65ac0871fd | |
|
|
19801d4796 | |
|
|
1d7ee7b3e7 | |
|
|
fd214032a4 | |
|
|
3bc810dcd4 | |
|
|
2a4526c8be | |
|
|
851affb63c | |
|
|
845358bb61 | |
|
|
c1f189b124 | |
|
|
0ea6b340a4 | |
|
|
e6fe5df515 | |
|
|
0eea53a628 | |
|
|
e2d23726b9 | |
|
|
268657831b | |
|
|
98f443d3f1 | |
|
|
ee8fcd41f4 | |
|
|
08c2d0c5e8 | |
|
|
db2ad1354b | |
|
|
3c6ea77a12 | |
|
|
74d7644106 | |
|
|
cac45e3607 | |
|
|
e8a6b40432 | |
|
|
cc7dab0341 | |
|
|
fa75eedb36 | |
|
|
cf27387180 | |
|
|
abe51015c4 | |
|
|
4c5dfb5881 | |
|
|
fbd28814e7 | |
|
|
3d7f55495a | |
|
|
387826ba37 | |
|
|
87c70065d5 | |
|
|
6327175fde | |
|
|
ad8debe030 | |
|
|
93c80460cd | |
|
|
24be6ddc2e | |
|
|
7ec932a1e3 | |
|
|
bf0843f321 | |
|
|
7fa11c8505 | |
|
|
4fe021df97 | |
|
|
ca49180a95 | |
|
|
7a9a895f64 | |
|
|
65a55493da | |
|
|
75c3278a32 | |
|
|
c53eb5e0e4 | |
|
|
bab1a5f592 | |
|
|
382258eb97 | |
|
|
f14c6e1226 | |
|
|
ebb2db9303 | |
|
|
3e5307f081 | |
|
|
86b61ce2fc | |
|
|
2402978c3a | |
|
|
0d041834db | |
|
|
6a8826b379 | |
|
|
83ad53c53f | |
|
|
9fc36fe587 | |
|
|
8847c6155b | |
|
|
8c3e151561 | |
|
|
9f81f0e13e | |
|
|
dd3b48ade0 | |
|
|
9f5a3dd61d | |
|
|
c80e1a067e | |
|
|
8e67e52f96 | |
|
|
b04e179400 | |
|
|
8035beec4f | |
|
|
b3faa3103c | |
|
|
43aa8437ba | |
|
|
7406027c52 | |
|
|
b8a96bfd7d | |
|
|
ce5953aaff | |
|
|
5ce683bab2 | |
|
|
faf006268d | |
|
|
5bc2d62a1f | |
|
|
eb147bb1f3 | |
|
|
cf6ffb4399 | |
|
|
f9b1997283 | |
|
|
1b6e6a5f4e | |
|
|
46db867c41 | |
|
|
a9426cb44f | |
|
|
ac17371c10 | |
|
|
0ecdc7f3d1 | |
|
|
d771955ad3 | |
|
|
b7f045fd5e | |
|
|
0389d798d7 | |
|
|
480e6fe973 | |
|
|
ad1cea991f | |
|
|
b0d6da28f5 | |
|
|
23df06cdc9 | |
|
|
773e8bcd34 | |
|
|
9cad754411 | |
|
|
43cfa09e7e | |
|
|
699ae10458 | |
|
|
46669f8073 | |
|
|
eea508f930 | |
|
|
e4297a63c3 | |
|
|
a7c52f4d5d |
|
|
@ -0,0 +1,16 @@
|
||||||
|
tests/issue0228.d text eol=lf
|
||||||
|
tests/allman/issue0228.d.ref text eol=crlf
|
||||||
|
tests/knr/issue0228.d.ref text eol=crlf
|
||||||
|
tests/otbs/issue0228.d.ref text eol=crlf
|
||||||
|
tests/issue0552_lf.d text eol=lf
|
||||||
|
tests/allman/issue0552_lf.d.ref text eol=lf
|
||||||
|
tests/knr/issue0552_lf.d.ref text eol=lf
|
||||||
|
tests/otbs/issue0552_lf.d.ref text eol=lf
|
||||||
|
tests/issue0552_cr.d text eol=cr
|
||||||
|
tests/allman/issue0552_cr.d.ref text eol=cr
|
||||||
|
tests/knr/issue0552_cr.d.ref text eol=cr
|
||||||
|
tests/otbs/issue0552_cr.d.ref text eol=cr
|
||||||
|
tests/issue0552_crlf.d text eol=crlf
|
||||||
|
tests/allman/issue0552_crlf.d.ref text eol=crlf
|
||||||
|
tests/knr/issue0552_crlf.d.ref text eol=crlf
|
||||||
|
tests/otbs/issue0552_crlf.d.ref text eol=crlf
|
||||||
|
|
@ -0,0 +1,34 @@
|
||||||
|
# This workflow uses actions that are not certified by GitHub.
|
||||||
|
# They are provided by a third-party and are governed by
|
||||||
|
# separate terms of service, privacy policy, and support
|
||||||
|
# documentation.
|
||||||
|
name: D
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches: [ "master" ]
|
||||||
|
pull_request:
|
||||||
|
branches: [ "master" ]
|
||||||
|
|
||||||
|
permissions:
|
||||||
|
contents: read
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build:
|
||||||
|
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v3
|
||||||
|
- uses: dlang-community/setup-dlang@4c99aa991ce7d19dd3064de0a4f2f6b2f152e2d7
|
||||||
|
|
||||||
|
- name: 'Build & Test'
|
||||||
|
run: |
|
||||||
|
# Build the project, with its main file included, without unittests
|
||||||
|
dub build --compiler=$DC
|
||||||
|
# Build and run tests, as defined by `unittest` configuration
|
||||||
|
# In this mode, `mainSourceFile` is excluded and `version (unittest)` are included
|
||||||
|
# See https://dub.pm/package-format-json.html#configurations
|
||||||
|
dub test --compiler=$DC
|
||||||
|
# Run tests
|
||||||
|
cd tests && rdmd test
|
||||||
|
|
@ -3,3 +3,5 @@ bin
|
||||||
*.d.out
|
*.d.out
|
||||||
.dub
|
.dub
|
||||||
dub.selections.json
|
dub.selections.json
|
||||||
|
.gdb_history
|
||||||
|
bin/dfmt
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,9 @@
|
||||||
[submodule "libdparse"]
|
[submodule "libdparse"]
|
||||||
path = libdparse
|
path = libdparse
|
||||||
url = https://github.com/Hackerpilot/libdparse.git
|
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
|
||||||
|
|
|
||||||
|
|
@ -1,3 +0,0 @@
|
||||||
language: d
|
|
||||||
script:
|
|
||||||
- git submodule update --init --recursive && make test
|
|
||||||
123
README.md
123
README.md
|
|
@ -1,46 +1,66 @@
|
||||||
# dfmt [](https://travis-ci.org/Hackerpilot/dfmt)
|
# dfmt [](https://github.com/dlang-community/dfmt/actions?query=workflow%3A%22D%22)
|
||||||
|
|
||||||
**dfmt** is a formatter for D source code
|
**dfmt** is a formatter for D source code
|
||||||
|
|
||||||
## Status
|
## Status
|
||||||
**dfmt** is beta quality. Make backups of your files or use source control
|
**dfmt** is beta quality. Make backups of your files or use source control
|
||||||
when using the **--inplace** option.
|
when using the **--inplace** option.
|
||||||
|
|
||||||
## Building
|
## Installation
|
||||||
### Using Make
|
|
||||||
|
### Installing with DUB
|
||||||
|
|
||||||
|
```sh
|
||||||
|
> dub run dfmt -- -h
|
||||||
|
```
|
||||||
|
|
||||||
|
### Building from source using Make
|
||||||
* Clone the repository
|
* Clone the repository
|
||||||
* Run ```git submodule update --init``` in the dfmt directory
|
* Run ```git submodule update --init --recursive``` in the dfmt directory
|
||||||
* To compile with DMD, run ```make``` in the dfmt directory. To compile with
|
* 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/```.
|
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
|
## Using
|
||||||
By default, dfmt reads its input from **stdin** and writes to **stdout**.
|
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
|
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**.
|
file instead, and output will be written to **stdout**.
|
||||||
|
|
||||||
**dfmt** uses EditorConfig files for configuration. If you run **dfmt** on a
|
**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.
|
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
|
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
|
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
|
line options can be used instead of *.editorconfig* files, or to override options
|
||||||
found in .editorconfig files.
|
found there.
|
||||||
|
|
||||||
### Options
|
### Options
|
||||||
* **--help**: Display command line options
|
* `--help | -h`: Display command line options.
|
||||||
* **--inplace**: A file name is required and the file will be edited in-place.
|
* `--inplace | -i`: A file name is required and the file will be edited in-place.
|
||||||
* **--align_switch_statements**: See **dfmt_align_switch_statements** below
|
* `--align_switch_statements`: *see dfmt_align_switch_statements [below](#dfmt-specific-properties)*
|
||||||
* **--brace_style**: See **brace_style** below
|
* `--brace_style`: *see dfmt_brace_style [below](#dfmt-specific-properties)*
|
||||||
* **--end_of_line**: See **end_of_line** below
|
* `--compact_labeled_statements`: *see dfmt_compact_labeled_statements [below](#dfmt-specific-properties)*
|
||||||
* **--indent_size**: See **indent_size** below
|
* `--end_of_line`: *see end_of_line [below](#standard-editorconfig-properties)*
|
||||||
* **--indent_style**: See **indent_style** below
|
* `--indent_size`: *see indent_size [below](#standard-editorconfig-properties)*
|
||||||
* **--max_line_length**: See **max_line_length** below
|
* `--indent_style | -t`: *see indent_style [below](#standard-editorconfig-properties)*
|
||||||
* **--soft_max_line_length**: See **dfmt_soft_max_line_length** below
|
* `--max_line_length`: *see max_line_length [below](#standard-editorconfig-properties)*
|
||||||
* **--outdent_attributes**: See **dfmt_outdent_attributes** below
|
* `--outdent_attributes`: *see dfmt_outdent_attributes [below](#dfmt-specific-properties)*
|
||||||
* **--space_after_cast**: See **dfmt_space_after_cast** below
|
* `--selective_import_space`: *see dfmt_selective_import_space [below](#dfmt-specific-properties)*
|
||||||
* **--split_operator_at_line_end**: See **dfmt_split_operator_at_line_end** below
|
* `--single_template_constraint_indent`: *see dfmt_single_template_constraint_indent [below](#dfmt-specific-properties)*
|
||||||
* **--tab_width**: See **tab_width** below
|
* `--soft_max_line_length`: *see dfmt_soft_max_line_length [below](#dfmt-specific-properties)*
|
||||||
* **--selective_import_space**: See **dfmt_selective_import_space** below
|
* `--space_after_cast`: *see dfmt_space_after_cast [below](#dfmt-specific-properties)*
|
||||||
* **--compact_labeled_statements**: See **dfmt_compact_labeled_statements** below
|
* `--space_before_aa_colon`: *see dfmt_space_before_aa_colon [below](#dfmt-specific-properties)*
|
||||||
|
* `--space_before_named_arg_colon`: *see dfmt_space_before_named_arg_colon [below](#dfmt-specific-properties)*
|
||||||
|
* `--space_before_function_parameters`: *see dfmt_space_before_function_parameters [below](#dfmt-specific-properties)*
|
||||||
|
* `--split_operator_at_line_end`: *see dfmt_split_operator_at_line_end [below](#dfmt-specific-properties)*
|
||||||
|
* `--tab_width`: *see tab_width [below](#standard-editorconfig-properties)*
|
||||||
|
* `--template_constraint_style`: *see dfmt_template_constraint_style [below](#dfmt-specific-properties)*
|
||||||
|
* `--keep_line_breaks`: *see dfmt_keep_line_breaks [below](#dfmt-specific-properties)*
|
||||||
|
* `--single_indent`: *see dfmt_single_indent [below](#dfmt-specific-properties)*
|
||||||
|
* `--reflow_property_chains`: *see dfmt_property_chains [below](#dfmt-specific-properties)*
|
||||||
|
* `--space_after_keywords`: *see dfmt_space_after_keywords [below](#dfmt-specific-properties)*
|
||||||
|
|
||||||
### Example
|
### Example
|
||||||
```
|
```
|
||||||
|
|
@ -59,9 +79,9 @@ void main(string[] args)
|
||||||
|
|
||||||
// dfmt has no way of knowing that "getopt" is special, so it wraps the
|
// dfmt has no way of knowing that "getopt" is special, so it wraps the
|
||||||
// argument list normally
|
// argument list normally
|
||||||
getopt(args, "optionOne", &optionOne, "optionTwo", &optionTwo, "optionThree", &optionThree);
|
getopt(args, "optionOne", &optionOne, "optionTwo", &optionTwo, "optionThree", &optionThree);
|
||||||
|
|
||||||
// dfmt off
|
// dfmt off
|
||||||
getopt(args,
|
getopt(args,
|
||||||
"optionOne", &optionOne,
|
"optionOne", &optionOne,
|
||||||
"optionTwo", &optionTwo,
|
"optionTwo", &optionTwo,
|
||||||
|
|
@ -74,28 +94,37 @@ void main(string[] args)
|
||||||
**dfmt** uses [EditorConfig](http://editorconfig.org/) configuration files.
|
**dfmt** uses [EditorConfig](http://editorconfig.org/) configuration files.
|
||||||
**dfmt**-specific properties are prefixed with *dfmt_*.
|
**dfmt**-specific properties are prefixed with *dfmt_*.
|
||||||
### Standard EditorConfig properties
|
### Standard EditorConfig properties
|
||||||
Property Name | Allowed Values | Default Value | Description
|
Property Name | Allowed Values | Description
|
||||||
--------------|----------------|---------------|------------
|
--------------|----------------|------------
|
||||||
end_of_line | `cr`, `crlf` and `lf` | `lf` | [See EditorConfig documentation.](https://github.com/editorconfig/editorconfig/wiki/EditorConfig-Properties#end_of_line)
|
end_of_line | `cr`, `crlf` and `lf` | [See EditorConfig documentation.](https://github.com/editorconfig/editorconfig/wiki/EditorConfig-Properties#end_of_line) When not set, `dfmt` adopts the first line ending in the input.
|
||||||
insert_final_newline | | `true` | Not supported. `dfmt` always inserts a final newline.
|
insert_final_newline | **`true`** | Not supported. `dfmt` always inserts a final newline.
|
||||||
charset | | `UTf-8` | Not supported. `dfmt` only works correctly on UTF-8.
|
charset | **`UTF-8`** | Not supported. `dfmt` only works correctly on UTF-8.
|
||||||
indent_style | `tab`, `space` | `space` | [See EditorConfig documentation.](https://github.com/editorconfig/editorconfig/wiki/EditorConfig-Properties#indent_style)
|
indent_style | `tab`, **`space`** | [See EditorConfig documentation.](https://github.com/editorconfig/editorconfig/wiki/EditorConfig-Properties#indent_style)
|
||||||
indent_size | positive integers | `4` | [See EditorConfig documentation.](https://github.com/editorconfig/editorconfig/wiki/EditorConfig-Properties#indent_size)
|
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)
|
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.
|
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)
|
max_line_length | positive integers (**`120`**) | [See EditorConfig documentation.](https://github.com/editorconfig/editorconfig/wiki/EditorConfig-Properties#max_line_length)
|
||||||
### dfmt-specific properties
|
### dfmt-specific properties
|
||||||
Property Name | Allowed Values | Default Value | Description
|
Property Name | Allowed Values | Description
|
||||||
--------------|----------------|---------------|------------
|
--------------|----------------|------------
|
||||||
dfmt_brace_style | `allman`, `otbs`, or `stroustrup` | `allman` | [See Wikipedia](https://en.wikipedia.org/wiki/Brace_style)
|
dfmt_brace_style | **`allman`**, `otbs`, `stroustrup` or `knr` | [See Wikipedia](https://en.wikipedia.org/wiki/Brace_style)
|
||||||
dfmt_soft_max_line_length | positive integers | `80` | The formatting process will usually keep lines below this length, but they may be up to max_line_length columns long.
|
dfmt_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_align_switch_statements | **`true`**, `false` | 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_outdent_attributes (Not yet implemented) | **`true`**, `false`| 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_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` | `false` | Insert space after the closing paren of a `cast` expression
|
dfmt_space_after_cast | **`true`**, `false` | Insert space after the closing paren of a `cast` expression.
|
||||||
dfmt_space_after_keywords (Not yet implemented) | `true`, `false` | `true` | Insert space after `if`, `while`, `foreach`, etc, and before the `(`
|
dfmt_space_after_keywords (Not yet implemented) | **`true`**, `false` | 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_space_before_function_parameters | `true`, **`false`** | Insert space before the opening paren of a function parameter list.
|
||||||
dfmt_compact_labeled_statements | `true`, `false` | `true` | Place labels on the same line as the labeled `switch`, `for`, `foreach`, or `while` statement
|
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.).
|
||||||
|
|
||||||
## Terminology
|
## Terminology
|
||||||
* Braces - `{` and `}`
|
* Braces - `{` and `}`
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,67 @@
|
||||||
|
# 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
|
||||||
30
build.bat
30
build.bat
|
|
@ -1,15 +1,37 @@
|
||||||
@echo off
|
@echo off
|
||||||
setlocal enabledelayedexpansion
|
setlocal enabledelayedexpansion
|
||||||
|
|
||||||
|
IF "%DC%"=="" SET DC="dmd"
|
||||||
|
|
||||||
set DFLAGS=-g
|
set DFLAGS=-g
|
||||||
set CORE=
|
set CORE=
|
||||||
set STD=
|
set STD=
|
||||||
set STDD=
|
set STDD=
|
||||||
|
set STDXALLOCATOR=
|
||||||
|
set STDXALLOCATORBLOCKS=
|
||||||
|
set OBIN=bin\dfmt
|
||||||
|
|
||||||
for %%x in (src\*.d) do set CORE=!CORE! %%x
|
:: git might not be installed, so we provide 0.0.0 as a fallback or use
|
||||||
for %%x in (libdparse\src\std\*.d) do set STD=!STD! %%x
|
:: the existing githash file if existent
|
||||||
for %%x in (libdparse\src\std\d\*.d) do set STDD=!STDD! %%x
|
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
|
||||||
|
|
||||||
@echo on
|
@echo on
|
||||||
dmd %CORE% %STD% %STDD% %DFLAGS% -ofbin\dfmt.exe
|
%DC% %CORE% %STD% %STDD% %STDE% %STDXALLOCATOR% %STDXALLOCATORBLOCKS% -I"stdx-allocator\source" -I"libdparse\src" -Jbin %DFLAGS% -of%OBIN%.exe
|
||||||
|
|
||||||
|
if exist %OBIN%.obj del %OBIN%.obj
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
Subproject commit 206a2e6abd97b4462f3a320e4f2d23986fad3cff
|
||||||
18
dub.json
18
dub.json
|
|
@ -1,10 +1,20 @@
|
||||||
{
|
{
|
||||||
"name": "dfmt",
|
"name": "dfmt",
|
||||||
"description": "Dfmt is a formatter for D source code",
|
"description": "Dfmt is a formatter for D source code",
|
||||||
"version": "0.4.0-beta",
|
"targetType": "autodetect",
|
||||||
"targetType": "executable",
|
|
||||||
"license": "BSL-1.0",
|
"license": "BSL-1.0",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"libdparse": "~master"
|
"libdparse": ">=0.19.2 <1.0.0"
|
||||||
}
|
},
|
||||||
|
"targetPath" : "bin/",
|
||||||
|
"targetName" : "dfmt",
|
||||||
|
"stringImportPaths" : [
|
||||||
|
"bin"
|
||||||
|
],
|
||||||
|
"versions" : [
|
||||||
|
"built_with_dub"
|
||||||
|
],
|
||||||
|
"preBuildCommands" : [
|
||||||
|
"$DC -run \"$PACKAGE_DIR/dubhash.d\""
|
||||||
|
]
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,23 @@
|
||||||
|
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 b3303ab6fd15e9cbde50c6987b303b6ed296d493
|
Subproject commit fe6d1e38fb4fc04323170389cfec67ed7fd4e24a
|
||||||
70
makefile
70
makefile
|
|
@ -1,33 +1,63 @@
|
||||||
|
PREFIX = /usr/local
|
||||||
|
|
||||||
SRC := $(shell find src -name "*.d") \
|
SRC := $(shell find src -name "*.d") \
|
||||||
$(shell find libdparse/src -name "*.d") \
|
$(shell find libdparse/src -name "*.d")
|
||||||
$(shell find libdparse/experimental_allocator/src -name "*.d")
|
IMPORTS := -Ilibdparse/src -Isrc -Jbin
|
||||||
INCLUDE_PATHS := -Ilibdparse/src -Isrc -Ilibdparse/experimental_allocator/src
|
|
||||||
DMD_COMMON_FLAGS := -dip25 -w $(INCLUDE_PATHS)
|
DC ?= dmd
|
||||||
DMD_DEBUG_FLAGS := -g $(DMD_COMMON_FLAGS)
|
LDC ?= ldc2
|
||||||
|
GDC ?= gdc
|
||||||
|
|
||||||
|
DMD_COMMON_FLAGS := -w $(IMPORTS)
|
||||||
|
DMD_DEBUG_FLAGS := -debug -g $(DMD_COMMON_FLAGS)
|
||||||
DMD_FLAGS := -O -inline $(DMD_COMMON_FLAGS)
|
DMD_FLAGS := -O -inline $(DMD_COMMON_FLAGS)
|
||||||
DMD_TEST_FLAGS := -unittest -g $(DMD_COMMON_FLAGS)
|
DMD_TEST_FLAGS := -unittest -g $(DMD_COMMON_FLAGS)
|
||||||
LDC_FLAGS := -g -w -oq $(INCLUDE_PATHS)
|
LDC_FLAGS := -g -w -oq $(IMPORTS)
|
||||||
GDC_FLAGS := -g -w -oq $(INCLUDE_PATHS)
|
GDC_FLAGS := -g -w -oq $(IMPORTS)
|
||||||
|
override DMD_FLAGS += $(DFLAGS)
|
||||||
|
override LDC_FLAGS += $(DFLAGS)
|
||||||
|
override GDC_FLAGS += $(DFLAGS)
|
||||||
|
|
||||||
.PHONY: dmd ldc gdc test
|
.PHONY: all clean install debug dmd ldc gdc pkg release test
|
||||||
|
|
||||||
|
all: bin/dfmt
|
||||||
|
|
||||||
|
bin/githash.txt:
|
||||||
|
mkdir -p bin
|
||||||
|
git describe --tags > bin/githash.txt
|
||||||
|
|
||||||
dmd: bin/dfmt
|
dmd: bin/dfmt
|
||||||
|
|
||||||
ldc: $(SRC)
|
ldc: bin/githash.txt
|
||||||
ldc2 $(LDC_FLAGS) $^ -ofbin/dfmt
|
$(LDC) $(SRC) $(LDC_FLAGS) -ofbin/dfmt
|
||||||
-rm -f *.o
|
-rm -f *.o
|
||||||
|
|
||||||
gdc: $(SRC)
|
gdc: bin/githash.txt
|
||||||
gdc $(GDC_FLAGS) $^ -obin/dfmt
|
$(GDC) $(SRC) $(GDC_FLAGS) -obin/dfmt
|
||||||
|
|
||||||
test: bin/dfmt
|
test: debug
|
||||||
cd tests && ./test.sh
|
cd tests && ./test.d
|
||||||
|
|
||||||
bin/dfmt-test: $(SRC)
|
bin/dfmt-test: bin/githash.txt $(SRC)
|
||||||
dmd $(DMD_TEST_FLAGS) $^ -of$@
|
$(DC) $(DMD_TEST_FLAGS) $(filter %.d,$^) -of$@
|
||||||
|
|
||||||
bin/dfmt: $(SRC)
|
bin/dfmt: bin/githash.txt $(SRC)
|
||||||
dmd $(DMD_FLAGS) $^ -of$@
|
$(DC) $(DMD_FLAGS) $(filter %.d,$^) -of$@
|
||||||
|
|
||||||
debug: $(SRC)
|
debug: bin/githash.txt $(SRC)
|
||||||
dmd $(DMD_DEBUG_FLAGS) $^ -ofbin/dfmt
|
$(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
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,21 @@
|
||||||
|
#!/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"
|
||||||
|
|
@ -0,0 +1,23 @@
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
set -eux -o pipefail
|
||||||
|
VERSION=$(git describe --abbrev=0 --tags)
|
||||||
|
ARCH="${ARCH:-64}"
|
||||||
|
LDC_FLAGS=()
|
||||||
|
unameOut="$(uname -s)"
|
||||||
|
case "$unameOut" in
|
||||||
|
Linux*) OS=linux; LDC_FLAGS=("-flto=full" "-linker=gold" "-static") ;;
|
||||||
|
Darwin*) OS=osx; LDC_FLAGS+=("-L-macosx_version_min" "-L10.7" "-L-lcrt1.o"); ;;
|
||||||
|
*) echo "Unknown OS: $unameOut"; exit 1
|
||||||
|
esac
|
||||||
|
|
||||||
|
case "$ARCH" in
|
||||||
|
64) ARCH_SUFFIX="x86_64";;
|
||||||
|
32) ARCH_SUFFIX="x86";;
|
||||||
|
*) echo "Unknown ARCH: $ARCH"; exit 1
|
||||||
|
esac
|
||||||
|
|
||||||
|
archiveName="dfmt-$VERSION-$OS-$ARCH_SUFFIX.tar.gz"
|
||||||
|
|
||||||
|
echo "Building $archiveName"
|
||||||
|
${MAKE:-make} ldc LDC_FLAGS="${LDC_FLAGS[*]} -Jbin"
|
||||||
|
tar cvfz "bin/$archiveName" -C bin dfmt
|
||||||
|
|
@ -0,0 +1,70 @@
|
||||||
|
#!/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
|
||||||
|
|
||||||
|
|
@ -5,8 +5,29 @@
|
||||||
|
|
||||||
module dfmt.ast_info;
|
module dfmt.ast_info;
|
||||||
|
|
||||||
import std.d.lexer;
|
import dparse.lexer;
|
||||||
import std.d.ast;
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
/// AST information that is needed by the formatter.
|
/// AST information that is needed by the formatter.
|
||||||
struct ASTInformation
|
struct ASTInformation
|
||||||
|
|
@ -14,12 +35,14 @@ struct ASTInformation
|
||||||
/// Sorts the arrays so that binary search will work on them
|
/// Sorts the arrays so that binary search will work on them
|
||||||
void cleanup()
|
void cleanup()
|
||||||
{
|
{
|
||||||
import std.algorithm : sort;
|
import std.algorithm : sort, uniq;
|
||||||
|
import std.array : array;
|
||||||
|
|
||||||
sort(doubleNewlineLocations);
|
sort(doubleNewlineLocations);
|
||||||
sort(spaceAfterLocations);
|
sort(spaceAfterLocations);
|
||||||
sort(unaryLocations);
|
sort(unaryLocations);
|
||||||
sort(attributeDeclarationLines);
|
sort(attributeDeclarationLines);
|
||||||
|
sort(atAttributeStartLocations);
|
||||||
sort(caseEndLocations);
|
sort(caseEndLocations);
|
||||||
sort(structInitStartLocations);
|
sort(structInitStartLocations);
|
||||||
sort(structInitEndLocations);
|
sort(structInitEndLocations);
|
||||||
|
|
@ -28,7 +51,20 @@ struct ASTInformation
|
||||||
sort(conditionalWithElseLocations);
|
sort(conditionalWithElseLocations);
|
||||||
sort(conditionalStatementLocations);
|
sort(conditionalStatementLocations);
|
||||||
sort(arrayStartLocations);
|
sort(arrayStartLocations);
|
||||||
|
sort(assocArrayStartLocations);
|
||||||
sort(contractLocations);
|
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
|
/// Locations of end braces for struct bodies
|
||||||
|
|
@ -43,6 +79,9 @@ struct ASTInformation
|
||||||
/// Lines containing attribute declarations
|
/// Lines containing attribute declarations
|
||||||
size_t[] attributeDeclarationLines;
|
size_t[] attributeDeclarationLines;
|
||||||
|
|
||||||
|
/// Lines containing attribute declarations that can be followed by a new line
|
||||||
|
size_t[] atAttributeStartLocations;
|
||||||
|
|
||||||
/// Case statement colon locations
|
/// Case statement colon locations
|
||||||
size_t[] caseEndLocations;
|
size_t[] caseEndLocations;
|
||||||
|
|
||||||
|
|
@ -58,6 +97,12 @@ struct ASTInformation
|
||||||
/// Closing braces of function literals
|
/// Closing braces of function literals
|
||||||
size_t[] funLitEndLocations;
|
size_t[] funLitEndLocations;
|
||||||
|
|
||||||
|
/// Locations of aggregate bodies (struct, class, union)
|
||||||
|
size_t[] aggregateBodyLocations;
|
||||||
|
|
||||||
|
/// Locations of function bodies
|
||||||
|
size_t[] funBodyLocations;
|
||||||
|
|
||||||
/// Conditional statements that have matching "else" statements
|
/// Conditional statements that have matching "else" statements
|
||||||
size_t[] conditionalWithElseLocations;
|
size_t[] conditionalWithElseLocations;
|
||||||
|
|
||||||
|
|
@ -67,13 +112,44 @@ struct ASTInformation
|
||||||
/// Locations of start locations of array initializers
|
/// Locations of start locations of array initializers
|
||||||
size_t[] arrayStartLocations;
|
size_t[] arrayStartLocations;
|
||||||
|
|
||||||
|
/// Locations of start locations of associative array initializers
|
||||||
|
size_t[] assocArrayStartLocations;
|
||||||
|
|
||||||
/// Locations of "in" and "out" tokens that begin contracts
|
/// Locations of "in" and "out" tokens that begin contracts
|
||||||
size_t[] contractLocations;
|
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
|
/// Collects information from the AST that is useful for the formatter
|
||||||
final class FormatVisitor : ASTVisitor
|
final class FormatVisitor : ASTVisitor
|
||||||
{
|
{
|
||||||
|
alias visit = ASTVisitor.visit;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Params:
|
* Params:
|
||||||
* astInformation = the AST information that will be filled in
|
* astInformation = the AST information that will be filled in
|
||||||
|
|
@ -89,14 +165,76 @@ final class FormatVisitor : ASTVisitor
|
||||||
arrayInitializer.accept(this);
|
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)
|
override void visit(const ConditionalDeclaration dec)
|
||||||
{
|
{
|
||||||
if (dec.falseDeclaration !is null)
|
if (dec.hasElse)
|
||||||
{
|
{
|
||||||
auto condition = dec.compileCondition;
|
auto condition = dec.compileCondition;
|
||||||
if (condition.versionCondition !is null)
|
if (condition.versionCondition !is null)
|
||||||
{
|
{
|
||||||
astInformation.conditionalWithElseLocations ~= condition.versionCondition.versionIndex;
|
astInformation.conditionalWithElseLocations
|
||||||
|
~= condition.versionCondition.versionIndex;
|
||||||
}
|
}
|
||||||
else if (condition.debugCondition !is null)
|
else if (condition.debugCondition !is null)
|
||||||
{
|
{
|
||||||
|
|
@ -108,6 +246,12 @@ final class FormatVisitor : ASTVisitor
|
||||||
dec.accept(this);
|
dec.accept(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override void visit(const Constraint constraint)
|
||||||
|
{
|
||||||
|
astInformation.constraintLocations ~= constraint.location;
|
||||||
|
constraint.accept(this);
|
||||||
|
}
|
||||||
|
|
||||||
override void visit(const ConditionalStatement statement)
|
override void visit(const ConditionalStatement statement)
|
||||||
{
|
{
|
||||||
auto condition = statement.compileCondition;
|
auto condition = statement.compileCondition;
|
||||||
|
|
@ -124,8 +268,15 @@ final class FormatVisitor : ASTVisitor
|
||||||
|
|
||||||
override void visit(const FunctionLiteralExpression funcLit)
|
override void visit(const FunctionLiteralExpression funcLit)
|
||||||
{
|
{
|
||||||
astInformation.funLitStartLocations ~= funcLit.functionBody.blockStatement.startLocation;
|
if (funcLit.specifiedFunctionBody !is null)
|
||||||
astInformation.funLitEndLocations ~= funcLit.functionBody.blockStatement.endLocation;
|
{
|
||||||
|
const bs = funcLit.specifiedFunctionBody.blockStatement;
|
||||||
|
|
||||||
|
astInformation.funLitStartLocations ~= bs.startLocation;
|
||||||
|
astInformation.funLitEndLocations ~= bs.endLocation;
|
||||||
|
astInformation.indentInfoSortedByEndLocation ~=
|
||||||
|
BraceIndentInfo(bs.startLocation, bs.endLocation);
|
||||||
|
}
|
||||||
funcLit.accept(this);
|
funcLit.accept(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -147,19 +298,22 @@ final class FormatVisitor : ASTVisitor
|
||||||
caseRangeStatement.accept(this);
|
caseRangeStatement.accept(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
override void visit(const FunctionBody functionBody)
|
override void visit(const SpecifiedFunctionBody specifiedFunctionBody)
|
||||||
{
|
{
|
||||||
if (functionBody.blockStatement !is null)
|
if (specifiedFunctionBody.blockStatement !is null)
|
||||||
astInformation.doubleNewlineLocations ~= functionBody.blockStatement.endLocation;
|
astInformation.doubleNewlineLocations ~= specifiedFunctionBody.blockStatement.endLocation;
|
||||||
if (functionBody.bodyStatement !is null && functionBody.bodyStatement.blockStatement !is null)
|
specifiedFunctionBody.accept(this);
|
||||||
astInformation.doubleNewlineLocations ~= functionBody.bodyStatement.blockStatement.endLocation;
|
|
||||||
functionBody.accept(this);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override void visit(const StructInitializer structInitializer)
|
override void visit(const StructInitializer structInitializer)
|
||||||
{
|
{
|
||||||
astInformation.structInitStartLocations ~= structInitializer.startLocation;
|
astInformation.structInitStartLocations ~= structInitializer.startLocation;
|
||||||
astInformation.structInitEndLocations ~= structInitializer.endLocation;
|
astInformation.structInitEndLocations ~= structInitializer.endLocation;
|
||||||
|
astInformation.structInfoSortedByEndLocation ~=
|
||||||
|
StructInitializerInfo(structInitializer.startLocation, structInitializer.endLocation);
|
||||||
|
astInformation.indentInfoSortedByEndLocation ~=
|
||||||
|
BraceIndentInfo(structInitializer.startLocation, structInitializer.endLocation);
|
||||||
|
|
||||||
structInitializer.accept(this);
|
structInitializer.accept(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -177,12 +331,15 @@ final class FormatVisitor : ASTVisitor
|
||||||
|
|
||||||
override void visit(const Invariant invariant_)
|
override void visit(const Invariant invariant_)
|
||||||
{
|
{
|
||||||
astInformation.doubleNewlineLocations ~= invariant_.blockStatement.endLocation;
|
if (invariant_.blockStatement !is null)
|
||||||
|
astInformation.doubleNewlineLocations ~= invariant_.blockStatement.endLocation;
|
||||||
|
|
||||||
invariant_.accept(this);
|
invariant_.accept(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
override void visit(const StructBody structBody)
|
override void visit(const StructBody structBody)
|
||||||
{
|
{
|
||||||
|
astInformation.aggregateBodyLocations ~= structBody.startLocation;
|
||||||
astInformation.doubleNewlineLocations ~= structBody.endLocation;
|
astInformation.doubleNewlineLocations ~= structBody.endLocation;
|
||||||
structBody.accept(this);
|
structBody.accept(this);
|
||||||
}
|
}
|
||||||
|
|
@ -202,9 +359,29 @@ final class FormatVisitor : ASTVisitor
|
||||||
|
|
||||||
override void visit(const UnaryExpression unary)
|
override void visit(const UnaryExpression unary)
|
||||||
{
|
{
|
||||||
|
import std.typecons : rebindable;
|
||||||
|
|
||||||
|
int chainLength;
|
||||||
|
auto u = rebindable(unary);
|
||||||
|
while (u !is null)
|
||||||
|
{
|
||||||
|
if (u.identifierOrTemplateInstance !is null
|
||||||
|
&& u.identifierOrTemplateInstance.templateInstance !is null)
|
||||||
|
chainLength++;
|
||||||
|
u = u.unaryExpression;
|
||||||
|
}
|
||||||
|
if (chainLength > 1)
|
||||||
|
{
|
||||||
|
u = unary;
|
||||||
|
while (u.unaryExpression !is null)
|
||||||
|
{
|
||||||
|
astInformation.ufcsHintLocations ~= u.dotLocation;
|
||||||
|
u = u.unaryExpression;
|
||||||
|
}
|
||||||
|
}
|
||||||
if (unary.prefix.type == tok!"~" || unary.prefix.type == tok!"&"
|
if (unary.prefix.type == tok!"~" || unary.prefix.type == tok!"&"
|
||||||
|| unary.prefix.type == tok!"*" || unary.prefix.type == tok!"+"
|
|| unary.prefix.type == tok!"*"
|
||||||
|| unary.prefix.type == tok!"-")
|
|| unary.prefix.type == tok!"+" || unary.prefix.type == tok!"-")
|
||||||
{
|
{
|
||||||
astInformation.unaryLocations ~= unary.prefix.index;
|
astInformation.unaryLocations ~= unary.prefix.index;
|
||||||
}
|
}
|
||||||
|
|
@ -217,19 +394,110 @@ final class FormatVisitor : ASTVisitor
|
||||||
attributeDeclaration.accept(this);
|
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)
|
override void visit(const InStatement inStatement)
|
||||||
{
|
{
|
||||||
astInformation.contractLocations ~= inStatement.inTokenLocation;
|
astInformation.contractLocations ~= inStatement.inTokenLocation;
|
||||||
inStatement.accept(this);
|
inStatement.accept(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override void visit(const OutContractExpression outContractExpression)
|
||||||
|
{
|
||||||
|
astInformation.contractLocations ~= outContractExpression.outTokenLocation;
|
||||||
|
outContractExpression.accept(this);
|
||||||
|
}
|
||||||
|
|
||||||
override void visit(const OutStatement outStatement)
|
override void visit(const OutStatement outStatement)
|
||||||
{
|
{
|
||||||
astInformation.contractLocations ~= outStatement.outTokenLocation;
|
astInformation.contractLocations ~= outStatement.outTokenLocation;
|
||||||
outStatement.accept(this);
|
outStatement.accept(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override void visit(const TernaryExpression ternaryExpression)
|
||||||
|
{
|
||||||
|
astInformation.ternaryColonLocations ~= ternaryExpression.colon.index;
|
||||||
|
ternaryExpression.accept(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
override void visit(const FunctionCallExpression functionCall)
|
||||||
|
{
|
||||||
|
visit(functionCall.arguments);
|
||||||
|
functionCall.accept(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
override void visit(const NewExpression newCall)
|
||||||
|
{
|
||||||
|
visit(newCall.arguments);
|
||||||
|
newCall.accept(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
override void visit(const NewAnonClassExpression newAnonClassCall)
|
||||||
|
{
|
||||||
|
visit(newAnonClassCall.constructorArguments);
|
||||||
|
newAnonClassCall.accept(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void visit(const Arguments arguments)
|
||||||
|
{
|
||||||
|
// Check if call has any arguments.
|
||||||
|
if (!arguments || arguments.namedArgumentList is null)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (item; arguments.namedArgumentList.items)
|
||||||
|
{
|
||||||
|
// Do nothing if not a named argument.
|
||||||
|
if (item.name == tok!"")
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Find first colon if named argument.
|
||||||
|
foreach (t; item.tokens)
|
||||||
|
{
|
||||||
|
if (t.type == tok!":")
|
||||||
|
{
|
||||||
|
astInformation.namedArgumentColonLocations ~= t.index;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
ASTInformation* astInformation;
|
ASTInformation* astInformation;
|
||||||
alias visit = ASTVisitor.visit;
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -10,13 +10,24 @@ import dfmt.editorconfig;
|
||||||
/// Brace styles
|
/// Brace styles
|
||||||
enum BraceStyle
|
enum BraceStyle
|
||||||
{
|
{
|
||||||
unspecified,
|
_unspecified,
|
||||||
/// $(LINK https://en.wikipedia.org/wiki/Indent_style#Allman_style)
|
/// $(LINK https://en.wikipedia.org/wiki/Indent_style#Allman_style)
|
||||||
allman,
|
allman,
|
||||||
/// $(LINK https://en.wikipedia.org/wiki/Indent_style#Variant:_1TBS)
|
/// $(LINK https://en.wikipedia.org/wiki/Indent_style#Variant:_1TBS)
|
||||||
otbs,
|
otbs,
|
||||||
/// $(LINK https://en.wikipedia.org/wiki/Indent_style#Variant:_Stroustrup)
|
/// $(LINK https://en.wikipedia.org/wiki/Indent_style#Variant:_Stroustrup)
|
||||||
stroustrup
|
stroustrup,
|
||||||
|
/// $(LINK https://en.wikipedia.org/wiki/Indentation_style#K&R_style)
|
||||||
|
knr,
|
||||||
|
}
|
||||||
|
|
||||||
|
enum TemplateConstraintStyle
|
||||||
|
{
|
||||||
|
_unspecified,
|
||||||
|
conditional_newline_indent,
|
||||||
|
conditional_newline,
|
||||||
|
always_newline,
|
||||||
|
always_newline_indent
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Configuration options for formatting
|
/// Configuration options for formatting
|
||||||
|
|
@ -35,15 +46,32 @@ struct Config
|
||||||
///
|
///
|
||||||
OptionalBoolean dfmt_space_after_keywords;
|
OptionalBoolean dfmt_space_after_keywords;
|
||||||
///
|
///
|
||||||
|
OptionalBoolean dfmt_space_before_function_parameters;
|
||||||
|
///
|
||||||
OptionalBoolean dfmt_split_operator_at_line_end;
|
OptionalBoolean dfmt_split_operator_at_line_end;
|
||||||
///
|
///
|
||||||
OptionalBoolean dfmt_selective_import_space;
|
OptionalBoolean dfmt_selective_import_space;
|
||||||
///
|
///
|
||||||
OptionalBoolean dfmt_compact_labeled_statements;
|
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;
|
mixin StandardEditorConfigFields;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initializes the standard EditorConfig properties with default values that
|
* Initializes the standard EditorConfig properties with default values that
|
||||||
* make sense for D code.
|
* make sense for D code.
|
||||||
|
|
@ -51,7 +79,7 @@ struct Config
|
||||||
void initializeWithDefaults()
|
void initializeWithDefaults()
|
||||||
{
|
{
|
||||||
pattern = "*.d";
|
pattern = "*.d";
|
||||||
end_of_line = EOL.lf;
|
end_of_line = EOL._default;
|
||||||
indent_style = IndentStyle.space;
|
indent_style = IndentStyle.space;
|
||||||
indent_size = 4;
|
indent_size = 4;
|
||||||
tab_width = 4;
|
tab_width = 4;
|
||||||
|
|
@ -62,9 +90,17 @@ struct Config
|
||||||
dfmt_soft_max_line_length = 80;
|
dfmt_soft_max_line_length = 80;
|
||||||
dfmt_space_after_cast = OptionalBoolean.t;
|
dfmt_space_after_cast = OptionalBoolean.t;
|
||||||
dfmt_space_after_keywords = OptionalBoolean.t;
|
dfmt_space_after_keywords = OptionalBoolean.t;
|
||||||
|
dfmt_space_before_function_parameters = OptionalBoolean.f;
|
||||||
dfmt_split_operator_at_line_end = OptionalBoolean.f;
|
dfmt_split_operator_at_line_end = OptionalBoolean.f;
|
||||||
dfmt_selective_import_space = OptionalBoolean.t;
|
dfmt_selective_import_space = OptionalBoolean.t;
|
||||||
dfmt_compact_labeled_statements = OptionalBoolean.t;
|
dfmt_compact_labeled_statements = OptionalBoolean.t;
|
||||||
|
dfmt_template_constraint_style = TemplateConstraintStyle.conditional_newline_indent;
|
||||||
|
dfmt_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;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -78,7 +114,7 @@ struct Config
|
||||||
if (dfmt_soft_max_line_length > max_line_length)
|
if (dfmt_soft_max_line_length > max_line_length)
|
||||||
{
|
{
|
||||||
stderr.writefln("Column hard limit (%d) must be greater than or equal to column soft limit (%d)",
|
stderr.writefln("Column hard limit (%d) must be greater than or equal to column soft limit (%d)",
|
||||||
max_line_length, dfmt_soft_max_line_length);
|
max_line_length, dfmt_soft_max_line_length);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@ module dfmt.editorconfig;
|
||||||
import std.regex : ctRegex;
|
import std.regex : ctRegex;
|
||||||
|
|
||||||
static if (__VERSION__ >= 2067)
|
static if (__VERSION__ >= 2067)
|
||||||
import std.traits : FieldNameTuple;
|
public import std.traits : FieldNameTuple;
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
private enum NameOf(alias T) = T.stringof;
|
private enum NameOf(alias T) = T.stringof;
|
||||||
|
|
@ -26,21 +26,22 @@ private auto commentRe = ctRegex!(`^\s*[#;].*$`);
|
||||||
|
|
||||||
enum OptionalBoolean : ubyte
|
enum OptionalBoolean : ubyte
|
||||||
{
|
{
|
||||||
unspecified = 3,
|
_unspecified = 3,
|
||||||
t = 1,
|
t = 1,
|
||||||
f = 0
|
f = 0
|
||||||
}
|
}
|
||||||
|
|
||||||
enum IndentStyle : ubyte
|
enum IndentStyle : ubyte
|
||||||
{
|
{
|
||||||
unspecified,
|
_unspecified,
|
||||||
tab,
|
tab,
|
||||||
space
|
space
|
||||||
}
|
}
|
||||||
|
|
||||||
enum EOL : ubyte
|
enum EOL : ubyte
|
||||||
{
|
{
|
||||||
unspecified,
|
_unspecified,
|
||||||
|
_default,
|
||||||
lf,
|
lf,
|
||||||
cr,
|
cr,
|
||||||
crlf
|
crlf
|
||||||
|
|
@ -61,9 +62,10 @@ mixin template StandardEditorConfigFields()
|
||||||
|
|
||||||
void merge(ref const typeof(this) other, const string fileName)
|
void merge(ref const typeof(this) other, const string fileName)
|
||||||
{
|
{
|
||||||
import std.path : globMatch;
|
import dfmt.globmatch_editorconfig : globMatchEditorConfig;
|
||||||
|
import std.array : front, popFront, empty, save;
|
||||||
|
|
||||||
if (other.pattern is null || !fileName.globMatch(other.pattern))
|
if (other.pattern is null || !ecMatch(fileName, other.pattern))
|
||||||
return;
|
return;
|
||||||
foreach (N; FieldNameTuple!(typeof(this)))
|
foreach (N; FieldNameTuple!(typeof(this)))
|
||||||
{
|
{
|
||||||
|
|
@ -72,16 +74,43 @@ mixin template StandardEditorConfigFields()
|
||||||
auto thisN = &mixin("this." ~ N);
|
auto thisN = &mixin("this." ~ N);
|
||||||
static if (N == "pattern")
|
static if (N == "pattern")
|
||||||
continue;
|
continue;
|
||||||
else static if (is (T == enum))
|
else static if (is(T == enum))
|
||||||
*thisN = otherN != T.unspecified ? otherN : *thisN;
|
*thisN = otherN != T._unspecified ? otherN : *thisN;
|
||||||
else static if (is (T == int))
|
else static if (is(T == int))
|
||||||
*thisN = otherN != -1 ? otherN : *thisN;
|
*thisN = otherN != -1 ? otherN : *thisN;
|
||||||
else static if (is (T == string))
|
else static if (is(T == string))
|
||||||
*thisN = otherN !is null ? otherN : *thisN;
|
*thisN = otherN !is null ? otherN : *thisN;
|
||||||
else
|
else
|
||||||
static assert(false);
|
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);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -94,15 +123,19 @@ EC getConfigFor(EC)(string path)
|
||||||
{
|
{
|
||||||
import std.stdio : File;
|
import std.stdio : File;
|
||||||
import std.regex : regex, match;
|
import std.regex : regex, match;
|
||||||
import std.path : globMatch, dirName, baseName, pathSplitter, buildPath;
|
import std.path : globMatch, dirName, baseName, pathSplitter, buildPath,
|
||||||
|
absolutePath;
|
||||||
import std.algorithm : reverse, map, filter;
|
import std.algorithm : reverse, map, filter;
|
||||||
import std.array : array;
|
import std.array : array;
|
||||||
|
import std.file : isDir;
|
||||||
|
|
||||||
EC result;
|
EC result;
|
||||||
EC[][] configs;
|
EC[][] configs;
|
||||||
string dir = dirName(path);
|
immutable expanded = absolutePath(path);
|
||||||
immutable string fileName = baseName(path);
|
immutable bool id = isDir(expanded);
|
||||||
string[] pathParts = cast(string[]) pathSplitter(dir).array();
|
immutable string fileName = id ? "dummy.d" : baseName(expanded);
|
||||||
|
string[] pathParts = cast(string[]) pathSplitter(expanded).array();
|
||||||
|
|
||||||
for (size_t i = pathParts.length; i > 1; i--)
|
for (size_t i = pathParts.length; i > 1; i--)
|
||||||
{
|
{
|
||||||
EC[] sections = parseConfig!EC(buildPath(pathParts[0 .. i]));
|
EC[] sections = parseConfig!EC(buildPath(pathParts[0 .. i]));
|
||||||
|
|
@ -115,6 +148,7 @@ EC getConfigFor(EC)(string path)
|
||||||
static if (__VERSION__ >= 2067)
|
static if (__VERSION__ >= 2067)
|
||||||
{
|
{
|
||||||
import std.algorithm : each;
|
import std.algorithm : each;
|
||||||
|
|
||||||
configs.each!(a => a.each!(b => result.merge(b, fileName)))();
|
configs.each!(a => a.each!(b => result.merge(b, fileName)))();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
|
||||||
1447
src/dfmt/formatter.d
1447
src/dfmt/formatter.d
File diff suppressed because it is too large
Load Diff
|
|
@ -0,0 +1,239 @@
|
||||||
|
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"));
|
||||||
|
}
|
||||||
|
|
@ -5,23 +5,27 @@
|
||||||
|
|
||||||
module dfmt.indentation;
|
module dfmt.indentation;
|
||||||
|
|
||||||
import std.d.lexer;
|
import dfmt.config;
|
||||||
|
import dfmt.editorconfig;
|
||||||
|
import dparse.lexer;
|
||||||
|
|
||||||
|
import std.bitmanip : bitfields;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns: true if the given token type is a wrap indent type
|
* Returns: true if the given token type is a wrap indent type
|
||||||
*/
|
*/
|
||||||
bool isWrapIndent(IdType type) pure nothrow @nogc @safe
|
bool isWrapIndent(IdType type) pure nothrow @nogc @safe
|
||||||
{
|
{
|
||||||
return type != tok!"{" && type != tok!"case" && type != tok!"@"
|
return type != tok!"{" && type != tok!"case" && type != tok!"@"
|
||||||
&& type != tok!"]" && isOperator(type);
|
&& type != tok!"]" && type != tok!"(" && type != tok!")" && isOperator(type);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns: true if the given token type is a wrap indent type
|
* Returns: true if the given token type is a temporary indent type
|
||||||
*/
|
*/
|
||||||
bool isTempIndent(IdType type) pure nothrow @nogc @safe
|
bool isTempIndent(IdType type) pure nothrow @nogc @safe
|
||||||
{
|
{
|
||||||
return type != tok!"{" && type != tok!"case" && type != tok!"@";
|
return type != tok!")" && type != tok!"{" && type != tok!"case" && type != tok!"@";
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -29,9 +33,33 @@ bool isTempIndent(IdType type) pure nothrow @nogc @safe
|
||||||
*/
|
*/
|
||||||
struct IndentStack
|
struct IndentStack
|
||||||
{
|
{
|
||||||
|
/// Configuration
|
||||||
|
private const Config* config;
|
||||||
|
|
||||||
|
this(const Config* config)
|
||||||
|
{
|
||||||
|
this.config = config;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct Details
|
||||||
|
{
|
||||||
|
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));
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Modifies the indent stack to match the state that it had at the most
|
* Get the indent size at the most recent occurrence of the given indent type
|
||||||
* recent appearance of the given token type.
|
|
||||||
*/
|
*/
|
||||||
int indentToMostRecent(IdType item) const
|
int indentToMostRecent(IdType item) const
|
||||||
{
|
{
|
||||||
|
|
@ -56,7 +84,7 @@ struct IndentStack
|
||||||
int tempIndentCount = 0;
|
int tempIndentCount = 0;
|
||||||
for (size_t i = index; i > 0; i--)
|
for (size_t i = index; i > 0; i--)
|
||||||
{
|
{
|
||||||
if (!isWrapIndent(arr[i - 1]) && arr[i - 1] != tok!"]")
|
if (!details[i - 1].wrap && arr[i - 1] != tok!"]")
|
||||||
break;
|
break;
|
||||||
tempIndentCount++;
|
tempIndentCount++;
|
||||||
}
|
}
|
||||||
|
|
@ -67,9 +95,27 @@ struct IndentStack
|
||||||
* Pushes the given indent type on to the stack.
|
* Pushes the given indent type on to the stack.
|
||||||
*/
|
*/
|
||||||
void push(IdType item) pure nothrow
|
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;
|
arr[index] = item;
|
||||||
index = index + 1 == arr.length ? index : index + 1;
|
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++;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -77,7 +123,8 @@ struct IndentStack
|
||||||
*/
|
*/
|
||||||
void pop() pure nothrow
|
void pop() pure nothrow
|
||||||
{
|
{
|
||||||
index = index == 0 ? index : index - 1;
|
if (index)
|
||||||
|
index--;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -85,7 +132,7 @@ struct IndentStack
|
||||||
*/
|
*/
|
||||||
void popWrapIndents() pure nothrow @safe @nogc
|
void popWrapIndents() pure nothrow @safe @nogc
|
||||||
{
|
{
|
||||||
while (index > 0 && isWrapIndent(arr[index - 1]))
|
while (index > 0 && details[index - 1].wrap)
|
||||||
index--;
|
index--;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -94,10 +141,18 @@ struct IndentStack
|
||||||
*/
|
*/
|
||||||
void popTempIndents() pure nothrow @safe @nogc
|
void popTempIndents() pure nothrow @safe @nogc
|
||||||
{
|
{
|
||||||
while (index > 0 && isTempIndent(arr[index - 1]))
|
while (index > 0 && details[index - 1].temp)
|
||||||
index--;
|
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.
|
* Returns: `true` if the top of the indent stack is the given indent type.
|
||||||
*/
|
*/
|
||||||
|
|
@ -111,7 +166,15 @@ struct IndentStack
|
||||||
*/
|
*/
|
||||||
bool topIsTemp()
|
bool topIsTemp()
|
||||||
{
|
{
|
||||||
return index > 0 && index <= arr.length && isTempIndent(arr[index - 1]);
|
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -119,7 +182,15 @@ struct IndentStack
|
||||||
*/
|
*/
|
||||||
bool topIsWrap()
|
bool topIsWrap()
|
||||||
{
|
{
|
||||||
return index > 0 && index <= arr.length && isWrapIndent(arr[index - 1]);
|
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -142,6 +213,11 @@ struct IndentStack
|
||||||
return arr[index - 1];
|
return arr[index - 1];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Details topDetails() const pure nothrow @property @safe @nogc
|
||||||
|
{
|
||||||
|
return details[index - 1];
|
||||||
|
}
|
||||||
|
|
||||||
int indentLevel() const pure nothrow @property @safe @nogc
|
int indentLevel() const pure nothrow @property @safe @nogc
|
||||||
{
|
{
|
||||||
return indentSize();
|
return indentSize();
|
||||||
|
|
@ -152,34 +228,93 @@ struct IndentStack
|
||||||
return cast(int) index;
|
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:
|
private:
|
||||||
|
|
||||||
size_t index;
|
size_t index;
|
||||||
|
|
||||||
IdType[256] arr;
|
IdType[256] arr;
|
||||||
|
Details[arr.length] details;
|
||||||
|
|
||||||
int indentSize(const size_t k = size_t.max) const pure nothrow @safe @nogc
|
int indentSize(const size_t k = size_t.max) const pure nothrow @safe @nogc
|
||||||
{
|
{
|
||||||
|
import std.algorithm : among;
|
||||||
if (index == 0 || k == 0)
|
if (index == 0 || k == 0)
|
||||||
return 0;
|
return 0;
|
||||||
immutable size_t j = k == size_t.max ? index : k;
|
immutable size_t j = k == size_t.max ? index : k;
|
||||||
int size = 0;
|
int size = 0;
|
||||||
|
int parenCount;
|
||||||
foreach (i; 0 .. j)
|
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 (i + 1 < index)
|
||||||
{
|
{
|
||||||
if (arr[i] == tok!"]")
|
if (config.dfmt_single_indent == OptionalBoolean.t && skipDoubleIndent(i, parenCount))
|
||||||
|
{
|
||||||
|
parenCount = pc;
|
||||||
continue;
|
continue;
|
||||||
immutable bool currentIsTemp = isTempIndent(arr[i]);
|
}
|
||||||
immutable bool nextIsTemp = isTempIndent(arr[i + 1]);
|
|
||||||
immutable bool nextIsSwitch = arr[i + 1] == tok!"switch";
|
immutable currentIsNonWrapTemp = !details[i].wrap
|
||||||
if (currentIsTemp && (!nextIsTemp || nextIsSwitch))
|
&& details[i].temp && arr[i] != tok!")" && arr[i] != tok!"!";
|
||||||
|
|
||||||
|
if (currentIsNonWrapTemp && arr[i + 1] == tok!"]")
|
||||||
|
{
|
||||||
|
parenCount = pc;
|
||||||
continue;
|
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++;
|
size++;
|
||||||
}
|
}
|
||||||
return size;
|
return size;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool skipDoubleIndent(size_t i, int parenCount) const pure nothrow @safe @nogc
|
||||||
|
{
|
||||||
|
return (details[i + 1].wrap && arr[i] == tok!")")
|
||||||
|
|| (parenCount == 0 && arr[i + 1] == tok!"," && arr[i] == tok!"(");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
unittest
|
unittest
|
||||||
|
|
|
||||||
264
src/dfmt/main.d
264
src/dfmt/main.d
|
|
@ -5,18 +5,46 @@
|
||||||
|
|
||||||
module dfmt.main;
|
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)
|
version (NoMain)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
import std.array : front, popFront;
|
|
||||||
import std.stdio : stdout, stdin, stderr, writeln, File;
|
|
||||||
import dfmt.config : Config;
|
import dfmt.config : Config;
|
||||||
import dfmt.formatter : format;
|
|
||||||
import std.path : buildPath, expandTilde;
|
|
||||||
import dfmt.editorconfig : getConfigFor;
|
import dfmt.editorconfig : getConfigFor;
|
||||||
|
import dfmt.formatter : format;
|
||||||
|
import std.array : appender, front, popFront;
|
||||||
import std.getopt : getopt, GetOptException;
|
import std.getopt : getopt, GetOptException;
|
||||||
|
import std.path : buildPath, dirName, expandTilde;
|
||||||
|
import std.stdio : File, stderr, stdin, stdout, writeln;
|
||||||
|
|
||||||
int main(string[] args)
|
int main(string[] args)
|
||||||
{
|
{
|
||||||
|
|
@ -24,13 +52,17 @@ else
|
||||||
Config optConfig;
|
Config optConfig;
|
||||||
optConfig.pattern = "*.d";
|
optConfig.pattern = "*.d";
|
||||||
bool showHelp;
|
bool showHelp;
|
||||||
|
bool showVersion;
|
||||||
|
string explicitConfigDir;
|
||||||
|
|
||||||
void handleBooleans(string option, string value)
|
void handleBooleans(string option, string value)
|
||||||
{
|
{
|
||||||
import dfmt.editorconfig : OptionalBoolean;
|
import dfmt.editorconfig : OptionalBoolean;
|
||||||
import std.exception : enforceEx;
|
import std.exception : enforce;
|
||||||
enforceEx!GetOptException(value == "true" || value == "false", "Invalid argument");
|
|
||||||
immutable OptionalBoolean optVal = value == "true" ? OptionalBoolean.t : OptionalBoolean.f;
|
enforce!GetOptException(value == "true" || value == "false", "Invalid argument");
|
||||||
|
immutable OptionalBoolean optVal = value == "true" ? OptionalBoolean.t
|
||||||
|
: OptionalBoolean.f;
|
||||||
switch (option)
|
switch (option)
|
||||||
{
|
{
|
||||||
case "align_switch_statements":
|
case "align_switch_statements":
|
||||||
|
|
@ -42,6 +74,9 @@ else
|
||||||
case "space_after_cast":
|
case "space_after_cast":
|
||||||
optConfig.dfmt_space_after_cast = optVal;
|
optConfig.dfmt_space_after_cast = optVal;
|
||||||
break;
|
break;
|
||||||
|
case "space_before_function_parameters":
|
||||||
|
optConfig.dfmt_space_before_function_parameters = optVal;
|
||||||
|
break;
|
||||||
case "split_operator_at_line_end":
|
case "split_operator_at_line_end":
|
||||||
optConfig.dfmt_split_operator_at_line_end = optVal;
|
optConfig.dfmt_split_operator_at_line_end = optVal;
|
||||||
break;
|
break;
|
||||||
|
|
@ -51,28 +86,63 @@ else
|
||||||
case "compact_labeled_statements":
|
case "compact_labeled_statements":
|
||||||
optConfig.dfmt_compact_labeled_statements = optVal;
|
optConfig.dfmt_compact_labeled_statements = optVal;
|
||||||
break;
|
break;
|
||||||
default: assert(false, "Invalid command-line switch");
|
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");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
// dfmt off
|
||||||
getopt(args,
|
getopt(args,
|
||||||
|
"version", &showVersion,
|
||||||
"align_switch_statements", &handleBooleans,
|
"align_switch_statements", &handleBooleans,
|
||||||
"brace_style", &optConfig.dfmt_brace_style,
|
"brace_style", &optConfig.dfmt_brace_style,
|
||||||
|
"config|c", &explicitConfigDir,
|
||||||
"end_of_line", &optConfig.end_of_line,
|
"end_of_line", &optConfig.end_of_line,
|
||||||
"help|h", &showHelp,
|
"help|h", &showHelp,
|
||||||
"indent_size", &optConfig.indent_size,
|
"indent_size", &optConfig.indent_size,
|
||||||
"indent_style|t", &optConfig.indent_style,
|
"indent_style|t", &optConfig.indent_style,
|
||||||
"inplace", &inplace,
|
"inplace|i", &inplace,
|
||||||
"max_line_length", &optConfig.max_line_length,
|
"max_line_length", &optConfig.max_line_length,
|
||||||
"soft_max_line_length", &optConfig.dfmt_soft_max_line_length,
|
"soft_max_line_length", &optConfig.dfmt_soft_max_line_length,
|
||||||
"outdent_attributes", &handleBooleans,
|
"outdent_attributes", &handleBooleans,
|
||||||
"space_after_cast", &handleBooleans,
|
"space_after_cast", &handleBooleans,
|
||||||
|
"space_after_keywords", &handleBooleans,
|
||||||
"selective_import_space", &handleBooleans,
|
"selective_import_space", &handleBooleans,
|
||||||
|
"space_before_function_parameters", &handleBooleans,
|
||||||
"split_operator_at_line_end", &handleBooleans,
|
"split_operator_at_line_end", &handleBooleans,
|
||||||
"compact_labeled_statements", &handleBooleans,
|
"compact_labeled_statements", &handleBooleans,
|
||||||
"tab_width", &optConfig.tab_width);
|
"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
|
||||||
}
|
}
|
||||||
catch (GetOptException e)
|
catch (GetOptException e)
|
||||||
{
|
{
|
||||||
|
|
@ -80,6 +150,12 @@ else
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (showVersion)
|
||||||
|
{
|
||||||
|
writeln(VERSION);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
if (showHelp)
|
if (showHelp)
|
||||||
{
|
{
|
||||||
printHelp();
|
printHelp();
|
||||||
|
|
@ -88,22 +164,62 @@ else
|
||||||
|
|
||||||
args.popFront();
|
args.popFront();
|
||||||
immutable bool readFromStdin = args.length == 0;
|
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);
|
|
||||||
|
|
||||||
if (!config.isValid())
|
version (Windows)
|
||||||
return 1;
|
{
|
||||||
|
// 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
File output = stdout;
|
|
||||||
ubyte[] buffer;
|
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");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
explicitConfig = getConfigFor!Config(explicitConfigDir);
|
||||||
|
explicitConfig.pattern = "*.d";
|
||||||
|
}
|
||||||
|
|
||||||
if (readFromStdin)
|
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[4096] inputBuffer;
|
||||||
ubyte[] b;
|
ubyte[] b;
|
||||||
while (true)
|
while (true)
|
||||||
|
|
@ -114,7 +230,9 @@ else
|
||||||
else
|
else
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
dfmt.formatter.format("stdin", buffer, output.lockingTextWriter(), &config);
|
immutable bool formatSuccess = format("stdin", buffer,
|
||||||
|
stdout.lockingTextWriter(), &config);
|
||||||
|
return formatSuccess ? 0 : 1;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
@ -122,6 +240,7 @@ else
|
||||||
|
|
||||||
if (args.length >= 2)
|
if (args.length >= 2)
|
||||||
inplace = true;
|
inplace = true;
|
||||||
|
int retVal;
|
||||||
while (args.length > 0)
|
while (args.length > 0)
|
||||||
{
|
{
|
||||||
const path = args.front;
|
const path = args.front;
|
||||||
|
|
@ -130,46 +249,115 @@ else
|
||||||
{
|
{
|
||||||
inplace = true;
|
inplace = true;
|
||||||
foreach (string name; dirEntries(path, "*.d", SpanMode.depth))
|
foreach (string name; dirEntries(path, "*.d", SpanMode.depth))
|
||||||
{
|
|
||||||
args ~= name;
|
args ~= name;
|
||||||
}
|
|
||||||
continue;
|
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);
|
File f = File(path);
|
||||||
buffer = new ubyte[](cast(size_t) f.size);
|
// ignore empty files
|
||||||
f.rawRead(buffer);
|
if (f.size)
|
||||||
if (inplace)
|
{
|
||||||
output = File(path, "wb");
|
buffer = new ubyte[](cast(size_t) f.size);
|
||||||
dfmt.formatter.format(path, buffer, output.lockingTextWriter(), &config);
|
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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
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()
|
private void printHelp()
|
||||||
{
|
{
|
||||||
writeln(`dfmt 0.4.0-beta
|
writeln(`dfmt `, VERSION, `
|
||||||
|
https://github.com/dlang-community/dfmt
|
||||||
|
|
||||||
Options:
|
Options:
|
||||||
--help | -h Print this help message
|
--help, -h Print this help message
|
||||||
--inplace Edit files in place
|
--inplace, -i Edit files in place
|
||||||
|
--config, -c Path to directory to load .editorconfig file from.
|
||||||
|
--version Print the version number and then exit
|
||||||
|
|
||||||
Formatting Options:
|
Formatting Options:
|
||||||
--align_switch_statements
|
--align_switch_statements
|
||||||
--brace_style
|
--brace_style `, optionsToString!(typeof(Config.dfmt_brace_style)),
|
||||||
--end_of_line
|
`
|
||||||
--help|h
|
--end_of_line `, optionsToString!(typeof(Config.end_of_line)), `
|
||||||
--indent_size
|
--indent_size
|
||||||
--indent_style|t
|
--indent_style, -t `,
|
||||||
--inplace
|
optionsToString!(typeof(Config.indent_style)), `
|
||||||
|
--keep_line_breaks
|
||||||
--soft_max_line_length
|
--soft_max_line_length
|
||||||
--max_line_length
|
--max_line_length
|
||||||
--outdent_attributes
|
--outdent_attributes
|
||||||
--space_after_cast
|
--space_after_cast
|
||||||
|
--space_before_function_parameters
|
||||||
|
--space_after_keywords
|
||||||
--selective_import_space
|
--selective_import_space
|
||||||
|
--single_template_constraint_indent
|
||||||
--split_operator_at_line_end
|
--split_operator_at_line_end
|
||||||
--compact_labeled_statements`);
|
--compact_labeled_statements
|
||||||
|
--template_constraint_style
|
||||||
|
--space_before_aa_colon
|
||||||
|
--space_before_named_arg_colon
|
||||||
|
--single_indent
|
||||||
|
--reflow_property_chains
|
||||||
|
`,
|
||||||
|
optionsToString!(typeof(Config.dfmt_template_constraint_style)));
|
||||||
}
|
}
|
||||||
|
|
||||||
private string createFilePath(bool readFromStdin, string fileName)
|
private string createFilePath(bool readFromStdin, string fileName)
|
||||||
|
|
|
||||||
|
|
@ -5,15 +5,38 @@
|
||||||
|
|
||||||
module dfmt.tokens;
|
module dfmt.tokens;
|
||||||
|
|
||||||
import std.d.lexer;
|
import dparse.lexer;
|
||||||
|
|
||||||
/// Length of an invalid token
|
/// Length of an invalid token
|
||||||
enum int INVALID_TOKEN_LENGTH = -1;
|
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
|
int tokenLength(ref const Token t) pure @safe @nogc
|
||||||
{
|
{
|
||||||
import std.algorithm : countUntil;
|
import std.algorithm : countUntil;
|
||||||
|
|
||||||
|
int c;
|
||||||
switch (t.type)
|
switch (t.type)
|
||||||
{
|
{
|
||||||
case tok!"doubleLiteral":
|
case tok!"doubleLiteral":
|
||||||
|
|
@ -33,7 +56,7 @@ int tokenLength(ref const Token t) pure @safe @nogc
|
||||||
case tok!"wstringLiteral":
|
case tok!"wstringLiteral":
|
||||||
case tok!"dstringLiteral":
|
case tok!"dstringLiteral":
|
||||||
// TODO: Unicode line breaks and old-Mac line endings
|
// TODO: Unicode line breaks and old-Mac line endings
|
||||||
auto c = cast(int) t.text.countUntil('\n');
|
c = cast(int) t.text.countUntil('\n');
|
||||||
if (c == -1)
|
if (c == -1)
|
||||||
return cast(int) t.text.length;
|
return cast(int) t.text.length;
|
||||||
else
|
else
|
||||||
|
|
@ -89,6 +112,7 @@ bool isBreakToken(IdType t) 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!"%":
|
case tok!"%":
|
||||||
|
|
@ -103,19 +127,19 @@ bool isBreakToken(IdType t) pure nothrow @safe @nogc
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int breakCost(IdType t) pure nothrow @safe @nogc
|
int breakCost(IdType p, IdType c) pure nothrow @safe @nogc
|
||||||
{
|
{
|
||||||
switch (t)
|
switch (c)
|
||||||
{
|
{
|
||||||
case tok!"||":
|
case tok!"||":
|
||||||
case tok!"&&":
|
case tok!"&&":
|
||||||
case tok!",":
|
case tok!",":
|
||||||
|
case tok!"?":
|
||||||
return 0;
|
return 0;
|
||||||
case tok!"(":
|
case tok!"(":
|
||||||
return 60;
|
return 60;
|
||||||
case tok!"[":
|
case tok!"[":
|
||||||
return 400;
|
return 300;
|
||||||
case tok!":":
|
|
||||||
case tok!";":
|
case tok!";":
|
||||||
case tok!"^^":
|
case tok!"^^":
|
||||||
case tok!"^=":
|
case tok!"^=":
|
||||||
|
|
@ -146,11 +170,11 @@ int breakCost(IdType t) 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!"..":
|
case tok!"..":
|
||||||
case tok!"*=":
|
case tok!"*=":
|
||||||
|
case tok!"*":
|
||||||
case tok!"&=":
|
case tok!"&=":
|
||||||
case tok!"%=":
|
case tok!"%=":
|
||||||
case tok!"%":
|
case tok!"%":
|
||||||
|
|
@ -159,8 +183,12 @@ int breakCost(IdType t) pure nothrow @safe @nogc
|
||||||
case tok!"~":
|
case tok!"~":
|
||||||
case tok!"+=":
|
case tok!"+=":
|
||||||
return 200;
|
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!".":
|
case tok!".":
|
||||||
return 900;
|
return p == tok!")" ? 0 : 300;
|
||||||
default:
|
default:
|
||||||
return 1000;
|
return 1000;
|
||||||
}
|
}
|
||||||
|
|
@ -170,10 +198,9 @@ pure nothrow @safe @nogc unittest
|
||||||
{
|
{
|
||||||
foreach (ubyte u; 0 .. ubyte.max)
|
foreach (ubyte u; 0 .. ubyte.max)
|
||||||
if (isBreakToken(u))
|
if (isBreakToken(u))
|
||||||
assert(breakCost(u) != 1000);
|
assert(breakCost(tok!".", u) != 1000);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private string generateFixedLengthCases()
|
private string generateFixedLengthCases()
|
||||||
{
|
{
|
||||||
import std.algorithm : map;
|
import std.algorithm : map;
|
||||||
|
|
@ -183,36 +210,34 @@ private string generateFixedLengthCases()
|
||||||
assert(__ctfe);
|
assert(__ctfe);
|
||||||
|
|
||||||
string[] spacedOperatorTokens = [
|
string[] spacedOperatorTokens = [
|
||||||
",", "..", "...", "/", "/=", "!", "!<", "!<=", "!<>", "!<>=", "!=", "!>",
|
",", "..", "...", "/", "/=", "!", "!<", "!<=", "!<>", "!<>=", "!=",
|
||||||
"!>=", "%", "%=", "&", "&&", "&=", "*", "*=", "+", "+=", "-", "-=", ":",
|
"!>", "!>=", "%", "%=", "&", "&&", "&=", "*", "*=", "+", "+=", "-",
|
||||||
";", "<", "<<", "<<=", "<=", "<>", "<>=", "=", "==", "=>", ">", ">=",
|
"-=", ":", ";", "<", "<<", "<<=", "<=", "<>", "<>=", "=", "==", "=>",
|
||||||
">>", ">>=", ">>>", ">>>=", "?", "@", "^", "^=", "^^", "^^=", "|", "|=", "||",
|
">", ">=", ">>", ">>=", ">>>", ">>>=", "?", "@", "^", "^=", "^^",
|
||||||
"~", "~="
|
"^^=", "|", "|=", "||", "~", "~="
|
||||||
];
|
];
|
||||||
immutable spacedOperatorTokenCases = spacedOperatorTokens.map!(
|
immutable spacedOperatorTokenCases = spacedOperatorTokens.map!(
|
||||||
a => format(`case tok!"%s": return %d + 1;`, a, a.length)).join("\n\t");
|
a => format(`case tok!"%s": return %d + 1;`, a, a.length)).join("\n\t");
|
||||||
|
|
||||||
string[] identifierTokens = [
|
string[] identifierTokens = [
|
||||||
"abstract", "alias", "align", "asm", "assert", "auto", "body", "bool",
|
"abstract", "alias", "align", "asm", "assert", "auto", "bool",
|
||||||
"break", "byte", "case", "cast", "catch", "cdouble", "cent", "cfloat",
|
"break", "byte", "case", "cast", "catch", "cdouble", "cent", "cfloat", "char", "class",
|
||||||
"char", "class", "const", "continue", "creal", "dchar", "debug",
|
"const", "continue", "creal", "dchar", "debug", "default", "delegate", "delete", "deprecated",
|
||||||
"default", "delegate", "delete", "deprecated", "do", "double", "else",
|
"do", "double", "else", "enum", "export", "extern", "false", "final", "finally", "float",
|
||||||
"enum", "export", "extern", "false", "final", "finally", "float", "for",
|
"for", "foreach", "foreach_reverse", "function", "goto", "idouble", "if", "ifloat", "immutable",
|
||||||
"foreach", "foreach_reverse", "function", "goto", "idouble", "if",
|
"import", "in", "inout", "int", "interface", "invariant", "ireal", "is",
|
||||||
"ifloat", "immutable", "import", "in", "inout", "int", "interface",
|
"lazy", "long", "macro", "mixin", "module", "new", "nothrow", "null", "out", "override",
|
||||||
"invariant", "ireal", "is", "lazy", "long", "macro", "mixin", "module",
|
"package", "pragma", "private", "protected", "public", "pure", "real", "ref", "return", "scope",
|
||||||
"new", "nothrow", "null", "out", "override", "package", "pragma",
|
"shared", "short", "static", "struct", "super", "switch", "synchronized", "template", "this",
|
||||||
"private", "protected", "public", "pure", "real", "ref", "return",
|
"throw", "true", "try", "typedef", "typeid", "typeof", "ubyte", "ucent", "uint", "ulong",
|
||||||
"scope", "shared", "short", "static", "struct", "super", "switch",
|
"union", "unittest", "ushort", "version", "void", "wchar",
|
||||||
"synchronized", "template", "this", "throw", "true", "try", "typedef",
|
"while", "with", "__DATE__", "__EOF__", "__FILE__",
|
||||||
"typeid", "typeof", "ubyte", "ucent", "uint", "ulong", "union",
|
"__FUNCTION__", "__gshared", "__LINE__", "__MODULE__", "__parameters",
|
||||||
"unittest", "ushort", "version", "void", "volatile", "wchar", "while",
|
"__PRETTY_FUNCTION__", "__TIME__", "__TIMESTAMP__",
|
||||||
"with", "__DATE__", "__EOF__", "__FILE__", "__FUNCTION__", "__gshared",
|
"__traits", "__vector", "__VENDOR__", "__VERSION__", "$", "++", "--",
|
||||||
"__LINE__", "__MODULE__", "__parameters", "__PRETTY_FUNCTION__",
|
".", "[", "]", "(", ")", "{", "}"
|
||||||
"__TIME__", "__TIMESTAMP__", "__traits", "__vector", "__VENDOR__",
|
|
||||||
"__VERSION__", "$", "++", "--", ".", "[", "]", "(", ")", "{", "}"
|
|
||||||
];
|
];
|
||||||
immutable identifierTokenCases = identifierTokens.map!(
|
immutable identifierTokenCases = identifierTokens.map!(
|
||||||
a => format(`case tok!"%s": return %d;`, a, a.length)).join("\n\t");
|
a => format(`case tok!"%s": return %d;`, a, a.length)).join("\n\t");
|
||||||
return spacedOperatorTokenCases ~ identifierTokenCases;
|
return spacedOperatorTokenCases ~ identifierTokenCases;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -5,62 +5,63 @@
|
||||||
|
|
||||||
module dfmt.wrapping;
|
module dfmt.wrapping;
|
||||||
|
|
||||||
import std.d.lexer;
|
import dparse.lexer;
|
||||||
import dfmt.tokens;
|
import dfmt.tokens;
|
||||||
import dfmt.config;
|
import dfmt.config;
|
||||||
|
|
||||||
struct State
|
struct State
|
||||||
{
|
{
|
||||||
this(uint breaks, const Token[] tokens, immutable short[] depths,
|
this(uint breaks, const Token[] tokens, immutable short[] depths,
|
||||||
const Config* config, int currentLineLength, int indentLevel) pure @safe
|
const Config* config, int currentLineLength, int indentLevel) pure @safe
|
||||||
{
|
{
|
||||||
import std.math : abs;
|
import std.math : abs;
|
||||||
import core.bitop : popcnt, bsf;
|
import core.bitop : popcnt, bsf;
|
||||||
import std.algorithm : min, map, sum;
|
import std.algorithm : min, map, sum;
|
||||||
|
|
||||||
immutable int remainingCharsMultiplier = config.max_line_length - config.dfmt_soft_max_line_length;
|
immutable int remainingCharsMultiplier = 25;
|
||||||
immutable int newlinePenalty = remainingCharsMultiplier * 20;
|
immutable int newlinePenalty = 480;
|
||||||
|
|
||||||
this.breaks = breaks;
|
this.breaks = breaks;
|
||||||
this._cost = 0;
|
this._cost = 0;
|
||||||
this._solved = true;
|
this._solved = true;
|
||||||
int ll = currentLineLength;
|
|
||||||
|
|
||||||
if (breaks == 0)
|
if (breaks == 0)
|
||||||
{
|
{
|
||||||
immutable int l = currentLineLength + tokens.map!(a => tokenLength(a)).sum();
|
immutable int l = currentLineLength + tokens.map!(a => tokenLength(a)).sum();
|
||||||
if (l > config.dfmt_soft_max_line_length)
|
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._cost += longPenalty;
|
||||||
this._solved = longPenalty < newlinePenalty;
|
this._solved = longPenalty < newlinePenalty;
|
||||||
}
|
}
|
||||||
else
|
|
||||||
this._solved = true;
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
for (size_t i = 0; i != uint.sizeof * 8; ++i)
|
foreach (size_t i; 0 .. (uint.sizeof * 8))
|
||||||
{
|
{
|
||||||
if (((1 << i) & breaks) == 0)
|
if (((1 << i) & breaks) == 0)
|
||||||
continue;
|
continue;
|
||||||
immutable b = tokens[i].type;
|
immutable prevType = i > 0 ? tokens[i - 1].type : tok!"";
|
||||||
|
immutable currentType = tokens[i].type;
|
||||||
immutable p = abs(depths[i]);
|
immutable p = abs(depths[i]);
|
||||||
immutable bc = breakCost(b) * (p == 0 ? 1 : p * 2);
|
immutable bc = breakCost(prevType, currentType) * (p == 0 ? 1 : p * 2);
|
||||||
this._cost += bc;
|
this._cost += bc + newlinePenalty;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int ll = currentLineLength;
|
||||||
size_t i = 0;
|
size_t i = 0;
|
||||||
foreach (_; 0 .. uint.sizeof * 8)
|
foreach (_; 0 .. uint.sizeof * 8)
|
||||||
{
|
{
|
||||||
immutable uint k = breaks >>> i;
|
immutable uint k = breaks >>> i;
|
||||||
immutable bool b = k == 0;
|
immutable bool b = k == 0;
|
||||||
immutable uint bits = b ? 0 : bsf(k);
|
immutable uint bits = b ? ALGORITHMIC_COMPLEXITY_SUCKS : bsf(k);
|
||||||
immutable size_t j = min(i + bits + 1, tokens.length);
|
immutable size_t j = min(i + bits + 1, tokens.length);
|
||||||
ll += tokens[i .. j].map!(a => tokenLength(a)).sum();
|
ll += tokens[i .. j].map!(a => tokenLength(a)).sum();
|
||||||
if (ll > config.dfmt_soft_max_line_length)
|
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;
|
this._cost += longPenalty;
|
||||||
}
|
}
|
||||||
if (ll > config.max_line_length)
|
if (ll > config.max_line_length)
|
||||||
|
|
@ -69,12 +70,14 @@ struct State
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
i = j;
|
i = j;
|
||||||
ll = indentLevel * config.indent_size;
|
if (indentLevel < 0)
|
||||||
|
ll = (abs(indentLevel) + 1) * config.indent_size;
|
||||||
|
else
|
||||||
|
ll = (indentLevel + (i == 0 ? 0 : 1)) * config.indent_size;
|
||||||
if (b)
|
if (b)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
this._cost += popcnt(breaks) * newlinePenalty;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int cost() const pure nothrow @safe @property
|
int cost() const pure nothrow @safe @property
|
||||||
|
|
@ -91,13 +94,12 @@ struct State
|
||||||
{
|
{
|
||||||
import core.bitop : bsf, popcnt;
|
import core.bitop : bsf, popcnt;
|
||||||
|
|
||||||
if (_cost < other._cost || (_cost == other._cost && ((breaks != 0
|
if (_cost < other._cost)
|
||||||
&& other.breaks != 0 && bsf(breaks) > bsf(other.breaks))
|
|
||||||
|| (_solved && !other.solved))))
|
|
||||||
{
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
if (_cost == other._cost && (breaks != 0 && other.breaks != 0
|
||||||
return other._cost > _cost;
|
&& bsf(breaks) > bsf(other.breaks)))
|
||||||
|
return -1;
|
||||||
|
return _cost > other._cost;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool opEquals(ref const State other) const pure nothrow @safe
|
bool opEquals(ref const State other) const pure nothrow @safe
|
||||||
|
|
@ -117,8 +119,14 @@ private:
|
||||||
bool _solved;
|
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,
|
size_t[] chooseLineBreakTokens(size_t index, const Token[] tokens,
|
||||||
immutable short[] depths, const Config* config, int currentLineLength, int indentLevel)
|
immutable short[] depths, const Config* config, int currentLineLength, int indentLevel)
|
||||||
{
|
{
|
||||||
import std.container.rbtree : RedBlackTree;
|
import std.container.rbtree : RedBlackTree;
|
||||||
import std.algorithm : filter, min;
|
import std.algorithm : filter, min;
|
||||||
|
|
@ -134,39 +142,36 @@ size_t[] chooseLineBreakTokens(size_t index, const Token[] tokens,
|
||||||
return retVal;
|
return retVal;
|
||||||
}
|
}
|
||||||
|
|
||||||
enum ALGORITHMIC_COMPLEXITY_SUCKS = uint.sizeof * 8;
|
|
||||||
immutable size_t tokensEnd = min(tokens.length, ALGORITHMIC_COMPLEXITY_SUCKS);
|
immutable size_t tokensEnd = min(tokens.length, ALGORITHMIC_COMPLEXITY_SUCKS);
|
||||||
auto open = new RedBlackTree!State;
|
auto open = new RedBlackTree!State;
|
||||||
open.insert(State(0, tokens[0 .. tokensEnd], depths[0 .. tokensEnd], config,
|
open.insert(State(0, tokens[0 .. tokensEnd], depths[0 .. tokensEnd], config,
|
||||||
currentLineLength, indentLevel));
|
currentLineLength, indentLevel));
|
||||||
State lowest;
|
State lowest;
|
||||||
while (!open.empty)
|
lowest._solved = false;
|
||||||
|
int tries = 0;
|
||||||
|
while (!open.empty && tries < 10_00)
|
||||||
{
|
{
|
||||||
|
tries++;
|
||||||
State current = open.front();
|
State current = open.front();
|
||||||
if (current.cost < lowest.cost)
|
|
||||||
lowest = current;
|
|
||||||
open.removeFront();
|
open.removeFront();
|
||||||
if (current.solved)
|
if (current.solved)
|
||||||
{
|
|
||||||
return genRetVal(current.breaks, index);
|
return genRetVal(current.breaks, index);
|
||||||
}
|
if (current < lowest)
|
||||||
validMoves!(typeof(open))(open, tokens[0 .. tokensEnd],
|
lowest = current;
|
||||||
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))
|
foreach (r; open[].filter!(a => a.solved))
|
||||||
return genRetVal(r.breaks, index);
|
return genRetVal(r.breaks, index);
|
||||||
assert(false);
|
if (open[].front < lowest)
|
||||||
|
return genRetVal(open[].front.breaks, index);
|
||||||
|
else
|
||||||
|
return genRetVal(lowest.breaks, index);
|
||||||
}
|
}
|
||||||
|
|
||||||
void validMoves(OR)(auto ref OR output, const Token[] tokens,
|
void validMoves(OR)(auto ref OR output, const Token[] tokens, immutable short[] depths,
|
||||||
immutable short[] depths, uint current, const Config* config,
|
uint current, const Config* config, int currentLineLength, int indentLevel)
|
||||||
int currentLineLength, int indentLevel)
|
|
||||||
{
|
{
|
||||||
import std.algorithm : sort, canFind;
|
|
||||||
import std.array : insertInPlace;
|
|
||||||
|
|
||||||
foreach (i, token; tokens)
|
foreach (i, token; tokens)
|
||||||
{
|
{
|
||||||
if (!isBreakToken(token.type) || (((1 << i) & current) != 0))
|
if (!isBreakToken(token.type) || (((1 << i) & current) != 0))
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
Subproject commit ae237cabd1843774cc78aad0729c914a3dd579db
|
||||||
|
|
@ -0,0 +1,17 @@
|
||||||
|
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"]];
|
||||||
|
|
@ -0,0 +1,38 @@
|
||||||
|
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"]
|
||||||
|
];
|
||||||
|
|
@ -0,0 +1,23 @@
|
||||||
|
class C
|
||||||
|
{
|
||||||
|
void f()
|
||||||
|
{
|
||||||
|
if (true)
|
||||||
|
{
|
||||||
|
f(map.map.map.map.map.map.map.map.map.map.map.map.map.map.map.map
|
||||||
|
.map.map.map.map.map.map, __FILE__, __FILE__, __FILE__, __FILE__, __FILE__,
|
||||||
|
__FILE__, __FILE__, __FILE__, __FILE__, __FILE__, __FILE__,
|
||||||
|
__FILE__, __FILE__, __FILE__, __FILE__, __FILE__, __LINE__);
|
||||||
|
|
||||||
|
g(map && map && map && map && map && map && map && map && map && map && map
|
||||||
|
&& map, __FILE__, __FILE__, __FILE__, __FILE__, __FILE__,
|
||||||
|
__FILE__, __FILE__, __LINE__);
|
||||||
|
h(map || map || map || map || map || map || map || map || map || map || map
|
||||||
|
|| map, __FILE__, __FILE__, __FILE__, __FILE__, __FILE__,
|
||||||
|
__FILE__, __FILE__, __LINE__);
|
||||||
|
i(map + map + map + map + map + map + map + map + map + map + map + map + map
|
||||||
|
+ map + map + map + map + map, __FILE__, __FILE__, __FILE__,
|
||||||
|
__FILE__, __FILE__, __FILE__, __FILE__, __LINE__);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,31 @@
|
||||||
|
class C
|
||||||
|
{
|
||||||
|
void f()
|
||||||
|
{
|
||||||
|
if (true)
|
||||||
|
{
|
||||||
|
f(
|
||||||
|
array.map!(a => a.prop)
|
||||||
|
.array
|
||||||
|
.to!string,
|
||||||
|
__FILE__,
|
||||||
|
__LINE__);
|
||||||
|
|
||||||
|
g(
|
||||||
|
map &&
|
||||||
|
map,
|
||||||
|
__FILE__,
|
||||||
|
__LINE__);
|
||||||
|
h(
|
||||||
|
map ||
|
||||||
|
map,
|
||||||
|
__FILE__,
|
||||||
|
__LINE__);
|
||||||
|
i(
|
||||||
|
map
|
||||||
|
+ map,
|
||||||
|
__FILE__,
|
||||||
|
__LINE__);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,7 @@
|
||||||
|
unittest
|
||||||
|
{
|
||||||
|
foo([
|
||||||
|
target.value.region[1], target.value.region[1], target.value.region[1],
|
||||||
|
target.value.region[1], target.value.region[1]
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,8 @@
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
string key;
|
||||||
|
|
||||||
|
int[string] var = [
|
||||||
|
key: 5
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,26 @@
|
||||||
|
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
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,25 @@
|
||||||
|
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))
|
||||||
|
]
|
||||||
|
])
|
||||||
|
])
|
||||||
|
]
|
||||||
|
]
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,17 @@
|
||||||
|
struct SomeStructName
|
||||||
|
{
|
||||||
|
static struct InnerStruct
|
||||||
|
{
|
||||||
|
version (linux)
|
||||||
|
{
|
||||||
|
static if (condition)
|
||||||
|
{
|
||||||
|
void longFunctionName(AAAAAAAA)(AAAAAAAA a) @property
|
||||||
|
if (someThingsAreTrue!AAAAAAAA && long_condition
|
||||||
|
&& is(elaborate == expression))
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,15 @@
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -2,6 +2,6 @@ int /*sneaky*/ foo( /*comments*/ ) /*everywhere*/
|
||||||
{
|
{
|
||||||
// comment on its own line
|
// comment on its own line
|
||||||
foo() // comment on same line
|
foo() // comment on same line
|
||||||
.bar(); // also on same line
|
.bar(); // also on same line
|
||||||
/* again */ // same line
|
/* again */ // same line
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,9 @@
|
||||||
|
void foo()()
|
||||||
|
if (dogs && pigs && birds && ants && foxes && flies && cats && bugs && bees
|
||||||
|
&& cows && sheeps && monkeys && whales)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void foo()() if (dogs && pigs && birds)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,10 @@
|
||||||
|
void foo()()
|
||||||
|
if (dogs && pigs && birds && ants && foxes && flies && cats && bugs && bees
|
||||||
|
&& cows && sheeps && monkeys && whales)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void foo()()
|
||||||
|
if (dogs && pigs && birds)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,8 @@
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
if (true)
|
||||||
|
debug
|
||||||
|
{
|
||||||
|
foo();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,7 @@
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
debug (0)
|
||||||
|
foo();
|
||||||
|
else
|
||||||
|
bar();
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,21 @@
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,19 @@
|
||||||
|
import character.body;
|
||||||
|
|
||||||
|
void body() @nogc
|
||||||
|
in
|
||||||
|
{
|
||||||
|
}
|
||||||
|
body
|
||||||
|
{
|
||||||
|
body = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
void body()
|
||||||
|
in
|
||||||
|
{
|
||||||
|
}
|
||||||
|
do
|
||||||
|
{
|
||||||
|
body = null;
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,6 @@
|
||||||
|
enum Foo
|
||||||
|
{
|
||||||
|
|
||||||
|
deprecated member0,
|
||||||
|
@UDA(0) member1
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,54 @@
|
||||||
|
static foreach (x; [
|
||||||
|
1,
|
||||||
|
2,
|
||||||
|
3,
|
||||||
|
])
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
static foreach_reverse (x; [
|
||||||
|
1,
|
||||||
|
2,
|
||||||
|
3,
|
||||||
|
])
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void f()
|
||||||
|
{
|
||||||
|
foreach (x; [
|
||||||
|
1,
|
||||||
|
2,
|
||||||
|
3,
|
||||||
|
])
|
||||||
|
{
|
||||||
|
}
|
||||||
|
foreach_reverse (x; [
|
||||||
|
1,
|
||||||
|
2,
|
||||||
|
3,
|
||||||
|
])
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!SymbolTool.instance.workspacesFilesUris.canFind!sameFile(uri))
|
||||||
|
{
|
||||||
|
send(TextDocument.publishDiagnostics, new PublishDiagnosticsParams(uri, [
|
||||||
|
]));
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (x; map([
|
||||||
|
1,
|
||||||
|
2,
|
||||||
|
3,
|
||||||
|
]))
|
||||||
|
{
|
||||||
|
}
|
||||||
|
foreach (x; foo!(map!([
|
||||||
|
1,
|
||||||
|
2,
|
||||||
|
3,
|
||||||
|
])))
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
void foo(@UDA(0) @UDA(1) Bar bar);
|
||||||
|
|
@ -3,8 +3,7 @@ import std.stdio, std.random, std.typecons, std.conv, std.string, std.range;
|
||||||
void main()
|
void main()
|
||||||
{
|
{
|
||||||
immutable interval = tuple(1, 100);
|
immutable interval = tuple(1, 100);
|
||||||
writefln("Guess my target number that is between " ~ "%d and %d (inclusive).\n",
|
writefln("Guess my target number that is between " ~ "%d and %d (inclusive).\n", interval[]);
|
||||||
interval[]);
|
|
||||||
immutable target = uniform!"[]"(interval[]);
|
immutable target = uniform!"[]"(interval[]);
|
||||||
|
|
||||||
foreach (immutable i; sequence!q{n})
|
foreach (immutable i; sequence!q{n})
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
alias u8 = ubyte
|
||||||
|
|
@ -1,3 +1,4 @@
|
||||||
immutable NameId[] namesA = [{"Aacgr", 0x00386}, // GREEK CAPITAL LETTER ALPHA WITH TONOS
|
immutable NameId[] namesA = [
|
||||||
{"aacgr", 0x003AC}, // GREEK SMALL LETTER ALPHA WITH TONOS
|
{"Aacgr", 0x00386}, // GREEK CAPITAL LETTER ALPHA WITH TONOS
|
||||||
|
{"aacgr", 0x003AC}, // GREEK SMALL LETTER ALPHA WITH TONOS
|
||||||
];
|
];
|
||||||
|
|
|
||||||
|
|
@ -10,27 +10,27 @@ string generateFixedLengthCases()
|
||||||
string[] fixedLengthTokens = [
|
string[] fixedLengthTokens = [
|
||||||
"abstract", "alias", "align", "asm", "assert", "auto", "body", "bool",
|
"abstract", "alias", "align", "asm", "assert", "auto", "body", "bool",
|
||||||
"break", "byte", "case", "cast", "catch", "cdouble", "cent", "cfloat",
|
"break", "byte", "case", "cast", "catch", "cdouble", "cent", "cfloat",
|
||||||
"char", "class", "const", "continue", "creal", "dchar", "debug",
|
"char", "class", "const", "continue", "creal", "dchar", "debug", "default",
|
||||||
"default", "delegate", "delete", "deprecated", "do", "double", "else",
|
"delegate", "delete", "deprecated", "do", "double", "else", "enum",
|
||||||
"enum", "export", "extern", "false", "final", "finally", "float",
|
"export", "extern", "false", "final", "finally", "float", "for", "foreach",
|
||||||
"for", "foreach", "foreach_reverse", "function", "goto", "idouble",
|
"foreach_reverse", "function", "goto", "idouble", "if", "ifloat",
|
||||||
"if", "ifloat", "immutable", "import", "in", "inout", "int",
|
"immutable", "import", "in", "inout", "int", "interface", "invariant",
|
||||||
"interface", "invariant", "ireal", "is", "lazy", "long", "macro",
|
"ireal", "is", "lazy", "long", "macro", "mixin", "module", "new",
|
||||||
"mixin", "module", "new", "nothrow", "null", "out", "override",
|
"nothrow", "null", "out", "override", "package", "pragma", "private",
|
||||||
"package", "pragma", "private", "protected", "public", "pure", "real",
|
"protected", "public", "pure", "real", "ref", "return", "scope", "shared",
|
||||||
"ref", "return", "scope", "shared", "short", "static", "struct",
|
"short", "static", "struct", "super", "switch", "synchronized", "template",
|
||||||
"super", "switch", "synchronized", "template", "this", "throw", "true",
|
"this", "throw", "true", "try", "typedef", "typeid", "typeof", "ubyte",
|
||||||
"try", "typedef", "typeid", "typeof", "ubyte", "ucent", "uint",
|
"ucent", "uint", "ulong", "union", "unittest", "ushort", "version", "void",
|
||||||
"ulong", "union", "unittest", "ushort", "version", "void", "volatile",
|
"volatile", "wchar", "while", "with", "__DATE__", "__EOF__",
|
||||||
"wchar", "while", "with", "__DATE__", "__EOF__", "__FILE__",
|
"__FILE__", "__FUNCTION__", "__gshared", "__LINE__",
|
||||||
"__FUNCTION__", "__gshared", "__LINE__", "__MODULE__", "__parameters",
|
"__MODULE__", "__parameters", "__PRETTY_FUNCTION__", "__TIME__",
|
||||||
"__PRETTY_FUNCTION__", "__TIME__", "__TIMESTAMP__", "__traits",
|
"__TIMESTAMP__", "__traits", "__vector", "__VENDOR__", "__VERSION__",
|
||||||
"__vector", "__VENDOR__", "__VERSION__", ",", ".", "..", "...", "/",
|
",", ".", "..", "...", "/", "/=", "!", "!<", "!<=", "!<>", "!<>=",
|
||||||
"/=", "!", "!<", "!<=", "!<>", "!<>=", "!=", "!>", "!>=", "$", "%",
|
"!=", "!>", "!>=", "$", "%", "%=", "&", "&&", "&=", "(", ")", "*",
|
||||||
"%=", "&", "&&", "&=", "(", ")", "*", "*=", "+", "++", "+=", "-",
|
"*=", "+", "++", "+=", "-", "--", "-=", ":", ";", "<", "<<", "<<=",
|
||||||
"--", "-=", ":", ";", "<", "<<", "<<=", "<=", "<>", "<>=", "=", "==",
|
"<=", "<>", "<>=", "=", "==", "=>", ">", ">=", ">>", ">>=", ">>>",
|
||||||
"=>", ">", ">=", ">>", ">>=", ">>>", ">>>=", "?", "@", "[", "]", "^",
|
">>>=", "?", "@", "[", "]", "^", "^=", "^^", "^^=", "{", "|", "|=", "||",
|
||||||
"^=", "^^", "^^=", "{", "|", "|=", "||", "}", "~", "~="
|
"}", "~", "~="
|
||||||
];
|
];
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,7 @@ unittest
|
||||||
{
|
{
|
||||||
auto dd = new DtorDeclaration(declLoc, Loc(), stc, Identifier.idPool("__fieldDtor"));
|
auto dd = new DtorDeclaration(declLoc, Loc(), stc, Identifier.idPool("__fieldDtor"));
|
||||||
auto dd = new DtorDeclaration(declLoc, Loc(), stc, extraParam,
|
auto dd = new DtorDeclaration(declLoc, Loc(), stc, extraParam,
|
||||||
midLengthFun(param, param), longIdentifier, Identifier.idPool("__fieldDtor"));
|
midLengthFun(param, param), longIdentifier, Identifier.idPool("__fieldDtor"));
|
||||||
|
|
||||||
memcpy(&saved_idents, &rvl.saved_idents, (const(char)*).sizeof * VC_SAVED_IDENT_CNT);
|
memcpy(&saved_idents, &rvl.saved_idents, (const(char)*).sizeof * VC_SAVED_IDENT_CNT);
|
||||||
memcpy(&saved_types, &rvl.saved_types, (Type).sizeof * VC_SAVED_TYPE_CNT);
|
memcpy(&saved_types, &rvl.saved_types, (Type).sizeof * VC_SAVED_TYPE_CNT);
|
||||||
|
|
@ -16,8 +16,7 @@ unittest
|
||||||
}
|
}
|
||||||
|
|
||||||
void doStuff(const Token[] tokens, ref const State current,
|
void doStuff(const Token[] tokens, ref const State current,
|
||||||
const FormatterConfig* formatterConfig, int currentLineLength, int indentLevel,
|
const FormatterConfig* formatterConfig, int currentLineLength, int indentLevel, int depth)
|
||||||
int depth)
|
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
{
|
{
|
||||||
with (CXTypeKind)
|
with (CXTypeKind)
|
||||||
return kind == CXType_FunctionNoProto || kind == CXType_FunctionProto
|
return kind == CXType_FunctionNoProto || kind == CXType_FunctionProto
|
||||||
|| // FIXME: This "hack" shouldn't be needed.
|
|| // FIXME: This "hack" shouldn't be needed.
|
||||||
func.resultType.isValid;
|
func.resultType.isValid;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,8 @@
|
||||||
struct Test
|
struct Test
|
||||||
{
|
{
|
||||||
this(string name, string[] aliasList, string briefDescription, string examDesc,
|
this(string name, string[] aliasList, string briefDescription, string examDesc, string onOpenDesc,
|
||||||
string onOpenDesc, string openDesc, string onCloseDesc, string closeDesc,
|
string openDesc, string onCloseDesc, string closeDesc,
|
||||||
Flag!"canOpen" canOpen, Flag!"canClose" canClose, Flag!"isOpen" isOpen)
|
Flag!"canOpen" canOpen, Flag!"canClose" canClose, Flag!"isOpen" isOpen)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,15 @@
|
||||||
|
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();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,15 @@
|
||||||
|
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();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
auto fun = function() { };
|
auto fun = function() {};
|
||||||
auto fun = () { };
|
auto fun = () {};
|
||||||
auto fun = {};
|
auto fun = {};
|
||||||
|
|
||||||
auto fun = { int i; };
|
auto fun = { int i; };
|
||||||
|
|
@ -17,9 +17,8 @@ unittest
|
||||||
});
|
});
|
||||||
callFunc({
|
callFunc({
|
||||||
int i = 10;
|
int i = 10;
|
||||||
foo(alpha_longVarName, bravo_longVarName, charlie_longVarName,
|
foo(alpha_longVarName, bravo_longVarName, charlie_longVarName, delta_longVarName,
|
||||||
delta_longVarName, echo_longVarName, foxtrot_longVarName,
|
echo_longVarName, foxtrot_longVarName, golf_longVarName, echo_longVarName);
|
||||||
golf_longVarName, echo_longVarName);
|
|
||||||
doStuff(withThings, andOtherStuff);
|
doStuff(withThings, andOtherStuff);
|
||||||
return i;
|
return i;
|
||||||
}, more_stuff);
|
}, more_stuff);
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
struct State
|
struct State
|
||||||
{
|
{
|
||||||
this(uint breaks, const Token[] tokens, immutable short[] depths,
|
this(uint breaks, const Token[] tokens, immutable short[] depths,
|
||||||
const Config* config, int currentLineLength, int indentLevel) pure @safe
|
const Config* config, int currentLineLength, int indentLevel) pure @safe
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,15 @@
|
||||||
|
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";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
class Foo(T) : FirstInterfaceWithVeryLongName,
|
class Foo(T) : FirstInterfaceWithVeryLongName, SecondInterfaceWithVeryLongName
|
||||||
SecondInterfaceWithVeryLongName if (is(T : Bar))
|
if (is(T : Bar))
|
||||||
{
|
{
|
||||||
void foo()
|
void foo()
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
@Foo enum Bar
|
@Foo enum Bar
|
||||||
{
|
{
|
||||||
|
a
|
||||||
}
|
}
|
||||||
|
|
||||||
@foo class Baz
|
@foo class Baz
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,8 @@
|
||||||
void foo(int foobarbazqux1, /* */
|
void foo(int foobarbazqux1, /* */
|
||||||
int foobarbazqux2, /* */
|
int foobarbazqux2, /* */
|
||||||
int foobarbazqux3, /* */
|
int foobarbazqux3, /* */
|
||||||
int foobarbazqux4, /* */
|
int foobarbazqux4, /* */
|
||||||
int foobarbazqux5, /* */
|
int foobarbazqux5, /* */
|
||||||
int foobarbazqux6, /* */
|
int foobarbazqux6, /* */
|
||||||
int foobarbazqux7 /* */
|
int foobarbazqux7 /* */
|
||||||
);
|
);
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,7 @@
|
||||||
|
final class FormatVisitor : ASTVisitor
|
||||||
|
{
|
||||||
|
this(ASTInformation* astInformation)
|
||||||
|
{
|
||||||
|
this.astInformation = astInformation;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,5 @@
|
||||||
|
void merge()
|
||||||
|
{
|
||||||
|
static if (is(T == enum))
|
||||||
|
*thisN = x;
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,29 @@
|
||||||
|
unittest
|
||||||
|
{
|
||||||
|
{
|
||||||
|
}
|
||||||
|
//
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
unittest
|
||||||
|
{
|
||||||
|
{
|
||||||
|
}
|
||||||
|
//
|
||||||
|
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
unittest
|
||||||
|
{
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,15 @@
|
||||||
|
unittest
|
||||||
|
{
|
||||||
|
do
|
||||||
|
++a;
|
||||||
|
while (true);
|
||||||
|
}
|
||||||
|
|
||||||
|
unittest
|
||||||
|
{
|
||||||
|
do
|
||||||
|
{
|
||||||
|
++a;
|
||||||
|
}
|
||||||
|
while (true);
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,29 @@
|
||||||
|
void functionName()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
static if (true)
|
||||||
|
{
|
||||||
|
if (true && {
|
||||||
|
functionName();
|
||||||
|
functionName();
|
||||||
|
functionName();
|
||||||
|
functionName();
|
||||||
|
return true;
|
||||||
|
}())
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,3 @@
|
||||||
|
void doStuff(T)() @safe if (isNumeric!T)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,21 @@
|
||||||
|
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
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,8 @@
|
||||||
|
unittest
|
||||||
|
{
|
||||||
|
asm
|
||||||
|
{
|
||||||
|
dl 12345;
|
||||||
|
movdqu [R8], XMM0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,12 @@
|
||||||
|
module test;
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
test("stringLiteral") in
|
||||||
|
{
|
||||||
|
foreach (thing; things)
|
||||||
|
{
|
||||||
|
doStuff(thing);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,16 @@
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
auto myTid = runTask({
|
||||||
|
auto conn = connectTCP("localhost", 4222);
|
||||||
|
|
||||||
|
auto l = Lexer(conn);
|
||||||
|
foreach (t; l)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
conn.close();
|
||||||
|
});
|
||||||
|
|
||||||
|
// foo
|
||||||
|
runEventLoop();
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,13 @@
|
||||||
|
version (Foo)
|
||||||
|
{
|
||||||
|
version (D_Version2)
|
||||||
|
{
|
||||||
|
public import core.memory;
|
||||||
|
}
|
||||||
|
else:
|
||||||
|
}
|
||||||
|
|
||||||
|
version (Bar)
|
||||||
|
int foo();
|
||||||
|
else:
|
||||||
|
int foo(int);
|
||||||
|
|
@ -0,0 +1,8 @@
|
||||||
|
unittest
|
||||||
|
{
|
||||||
|
asm
|
||||||
|
{
|
||||||
|
}
|
||||||
|
d[] = a[];
|
||||||
|
c[] = d[];
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,8 @@
|
||||||
|
unittest
|
||||||
|
{
|
||||||
|
import std.stdio : stderr;
|
||||||
|
|
||||||
|
{
|
||||||
|
a = 10;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,11 @@
|
||||||
|
enum a
|
||||||
|
{
|
||||||
|
a,
|
||||||
|
b,
|
||||||
|
c,
|
||||||
|
d,
|
||||||
|
/* a comment */
|
||||||
|
e,
|
||||||
|
f,
|
||||||
|
g
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,7 @@
|
||||||
|
unittest
|
||||||
|
{
|
||||||
|
if (a && !is(b == q))
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,23 @@
|
||||||
|
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
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,2 @@
|
||||||
|
static assert(call(x) !is y);
|
||||||
|
static assert(call(x) is y);
|
||||||
|
|
@ -0,0 +1,4 @@
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
x = 3
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,6 @@
|
||||||
|
version (linux)
|
||||||
|
import core.sys.linux.elf;
|
||||||
|
else version (FreeBSD)
|
||||||
|
import core.sys.freebsd.sys.elf;
|
||||||
|
else version (Solaris)
|
||||||
|
import core.sys.solaris.elf;
|
||||||
|
|
@ -0,0 +1,18 @@
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,18 @@
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,19 @@
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,19 @@
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,7 @@
|
||||||
|
unittest
|
||||||
|
{
|
||||||
|
if (something || somethingElse || // I like putting comments here for no good reason
|
||||||
|
thirdThing)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,6 @@
|
||||||
|
@OneOf("group1")
|
||||||
|
{
|
||||||
|
JSONValue[string] fred;
|
||||||
|
bool mertz;
|
||||||
|
bool ethel;
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,68 @@
|
||||||
|
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;
|
||||||
|
|
@ -0,0 +1,5 @@
|
||||||
|
unittest
|
||||||
|
{
|
||||||
|
static if (stuff) // comment
|
||||||
|
things();
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,5 @@
|
||||||
|
unittest
|
||||||
|
{
|
||||||
|
return (complicated % expression) / //-------------------
|
||||||
|
(other * complicated + expression);
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,7 @@
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,6 @@
|
||||||
|
unittest
|
||||||
|
{
|
||||||
|
int a, /// comment
|
||||||
|
b, /// comment
|
||||||
|
c; /// comment
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,5 @@
|
||||||
|
static if (condition)
|
||||||
|
int declaration;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,15 @@
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,8 @@
|
||||||
|
/* This test relies on ../.gitattributes to contain these lines:
|
||||||
|
|
||||||
|
tests/issue0228.d text eol=lf
|
||||||
|
tests/allman/issue0228.d.ref text eol=crlf
|
||||||
|
tests/knr/issue0228.d.ref text eol=crlf
|
||||||
|
tests/otbs/issue0228.d.ref text eol=crlf
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
@ -0,0 +1,24 @@
|
||||||
|
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
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,40 @@
|
||||||
|
void fn()
|
||||||
|
{
|
||||||
|
{
|
||||||
|
{
|
||||||
|
{
|
||||||
|
auto file = {
|
||||||
|
"integrationtest/feed/etc/config.iniaasdfaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
|
||||||
|
"etc/config.ini"
|
||||||
|
};
|
||||||
|
{
|
||||||
|
int x;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct A
|
||||||
|
{
|
||||||
|
int x, y, z;
|
||||||
|
}
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
int fun()
|
||||||
|
{
|
||||||
|
import std.stdio : writeln;
|
||||||
|
import std.typecons : tuple;
|
||||||
|
|
||||||
|
A a = {
|
||||||
|
tuple(Variant(1))[0].get!int, tuple(Variant(2))[0].get!int,
|
||||||
|
tuple(Variant(3))[0].get!int
|
||||||
|
};
|
||||||
|
A b = {
|
||||||
|
tuple(Variant(1))[0].get!int, tuple(Variant(2))[0].get!int,
|
||||||
|
tuple(Variant(3))[0].get!int
|
||||||
|
};
|
||||||
|
writeln(a);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,4 @@
|
||||||
|
void round()
|
||||||
|
body
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,5 @@
|
||||||
|
enum Status : bool
|
||||||
|
{
|
||||||
|
abort = true,
|
||||||
|
ignore = false
|
||||||
|
}
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue