Compare commits
772 Commits
feature/io
...
master
| Author | SHA1 | Date |
|---|---|---|
|
|
dd85251813 | |
|
|
069396ecb8 | |
|
|
fce05b99ec | |
|
|
efa00ff67b | |
|
|
565279ef75 | |
|
|
66f4df9425 | |
|
|
5a663334f0 | |
|
|
ccd4df9314 | |
|
|
d900c5b9ad | |
|
|
1160ea6320 | |
|
|
e732e16d21 | |
|
|
abe62fca64 | |
|
|
7f7d535ca5 | |
|
|
e54d505272 | |
|
|
70c2899bf0 | |
|
|
434c4f4e6a | |
|
|
e44811d1b7 | |
|
|
eaad4027c6 | |
|
|
5be3987ea3 | |
|
|
f8865b3232 | |
|
|
4dfed1b2a8 | |
|
|
c841e48516 | |
|
|
3e249eae3d | |
|
|
318e0ce021 | |
|
|
f1fe35d298 | |
|
|
39109c6e60 | |
|
|
7d3f2794bc | |
|
|
b843196f3c | |
|
|
96f4d38bab | |
|
|
e3b688639f | |
|
|
16b6523742 | |
|
|
bf2ee40721 | |
|
|
cd8e8c60e4 | |
|
|
69928bb749 | |
|
|
d6c818370f | |
|
|
b50ced768e | |
|
|
7c5352e6c9 | |
|
|
23fb4371b1 | |
|
|
211020a30d | |
|
|
4716bdb131 | |
|
|
98bd66290e | |
|
|
4cdf0b8982 | |
|
|
9fe5348a98 | |
|
|
ba7f792f96 | |
|
|
3321f3bdfd | |
|
|
082f618425 | |
|
|
d83a3628e4 | |
|
|
0400dbe36d | |
|
|
216c228898 | |
|
|
84db8a0e09 | |
|
|
a58de7d461 | |
|
|
c5b7947526 | |
|
|
4d7182fd67 | |
|
|
302530f3c2 | |
|
|
4b5ee64737 | |
|
|
f0bbbb9929 | |
|
|
ce23c714e5 | |
|
|
34dcae1d5c | |
|
|
45fbc84578 | |
|
|
55ab60b6ea | |
|
|
99281d2105 | |
|
|
c4b340ec44 | |
|
|
a54982e482 | |
|
|
18cf87ea18 | |
|
|
8050647847 | |
|
|
1b8d06cb0d | |
|
|
7c22f6e4fc | |
|
|
d924c2a995 | |
|
|
1af248ea15 | |
|
|
3dfdb3de1e | |
|
|
b350383ae7 | |
|
|
120551da8f | |
|
|
65a5af2e31 | |
|
|
f389e6d806 | |
|
|
8e13458c7f | |
|
|
3f7c655c8e | |
|
|
732df3171f | |
|
|
e082796930 | |
|
|
44a7fd7f48 | |
|
|
47a67edfff | |
|
|
021e4f410e | |
|
|
fa8322b142 | |
|
|
8f4e64bc86 | |
|
|
76ac52accf | |
|
|
b908265a3e | |
|
|
fe8f581c48 | |
|
|
2e08a7c062 | |
|
|
2753812843 | |
|
|
c985b62bf0 | |
|
|
5ad312828c | |
|
|
68fdb3a815 | |
|
|
9babae50e5 | |
|
|
938d5bd332 | |
|
|
454ec643b3 | |
|
|
13e28f1b7f | |
|
|
cd82b034ed | |
|
|
57dbcee506 | |
|
|
2d98944976 | |
|
|
f30d6ec374 | |
|
|
3220b9a30c | |
|
|
31d621444c | |
|
|
51f0bd3ee7 | |
|
|
6282671df7 | |
|
|
f639e34579 | |
|
|
2799169e21 | |
|
|
9dad6d730c | |
|
|
082fc9a719 | |
|
|
3fd44c3bbd | |
|
|
6bc60ac0ab | |
|
|
8991f8c2b8 | |
|
|
d96c126fe2 | |
|
|
d7acbb0080 | |
|
|
5145245266 | |
|
|
2ec3289b5b | |
|
|
22abe5a792 | |
|
|
1db4cfc771 | |
|
|
6b21a9845a | |
|
|
5f009524a3 | |
|
|
d2ce219af4 | |
|
|
c94fb44966 | |
|
|
0fc2eb03c6 | |
|
|
81499749a1 | |
|
|
0df12c3b26 | |
|
|
c2259b12b2 | |
|
|
e1290036ff | |
|
|
b9b7dfe3f7 | |
|
|
e1e15d619e | |
|
|
7061bad2ec | |
|
|
b319b97522 | |
|
|
ecc34d227a | |
|
|
e975ff0ed0 | |
|
|
befc933117 | |
|
|
b9429f8aaf | |
|
|
ee5299c318 | |
|
|
1678af0116 | |
|
|
f98c1af719 | |
|
|
a455072e14 | |
|
|
44d4ff9f74 | |
|
|
494bc4886b | |
|
|
db99ec0009 | |
|
|
9e8d088017 | |
|
|
5a6dd866f7 | |
|
|
088114cb5c | |
|
|
40f6d12e15 | |
|
|
e725685a9e | |
|
|
8094a04ab3 | |
|
|
1e95815cce | |
|
|
54fdb267bc | |
|
|
501ff89f28 | |
|
|
51e9a3b190 | |
|
|
9ae6e92e66 | |
|
|
f5b21784fe | |
|
|
1545208c46 | |
|
|
5ac9fd8232 | |
|
|
cbf10f95f9 | |
|
|
c2104468bd | |
|
|
7c4149778c | |
|
|
6cdd30a872 | |
|
|
8d0449714b | |
|
|
6a032c324f | |
|
|
63ecad8042 | |
|
|
0d555bea19 | |
|
|
82a44c2a1c | |
|
|
cf2aa3f7ee | |
|
|
73abd1564f | |
|
|
ad2172cd27 | |
|
|
c302278751 | |
|
|
3c5135ea5e | |
|
|
efb5c8b60e | |
|
|
3f70495e4b | |
|
|
1b86887958 | |
|
|
e0913de8a3 | |
|
|
79105bf5f9 | |
|
|
045b57e72d | |
|
|
fa9ccef66b | |
|
|
a132bcd939 | |
|
|
908f69b1f8 | |
|
|
566bbe1801 | |
|
|
515e6ac5be | |
|
|
82154894c1 | |
|
|
8813dacd6f | |
|
|
27f69a2dcf | |
|
|
a83d6074b2 | |
|
|
257c8e966b | |
|
|
daf50493e6 | |
|
|
2ac36fbc1b | |
|
|
784f619166 | |
|
|
cd606ce17d | |
|
|
4f9aa52800 | |
|
|
bfad757f23 | |
|
|
8529a6f41f | |
|
|
ddf7e0228b | |
|
|
43485eb8f5 | |
|
|
f5d3b7e4ea | |
|
|
fc1c0ac74b | |
|
|
40db24db3c | |
|
|
e5c4db8c10 | |
|
|
621e46757d | |
|
|
2c0e89dbf5 | |
|
|
4a72255a79 | |
|
|
f62bc00b9c | |
|
|
88e8dbf2b7 | |
|
|
f0e0cb7e02 | |
|
|
69ec87dc47 | |
|
|
2c97109908 | |
|
|
fec78fd0bc | |
|
|
d0256372c1 | |
|
|
0546268696 | |
|
|
7c9680f4c9 | |
|
|
54fd9f1106 | |
|
|
039ddac90a | |
|
|
8794713900 | |
|
|
ca37784c57 | |
|
|
7819b0e4cd | |
|
|
a682c25dd5 | |
|
|
b27fa554fb | |
|
|
bd2138f58d | |
|
|
e2f85337c0 | |
|
|
bb432d4220 | |
|
|
be7e522f38 | |
|
|
e0300fcd07 | |
|
|
093f16a578 | |
|
|
2c5f978eeb | |
|
|
9c247bbf4a | |
|
|
454ae16cbe | |
|
|
659baf6ced | |
|
|
db8cd599b3 | |
|
|
687197d06d | |
|
|
f684dbc029 | |
|
|
175a97fc5f | |
|
|
a042e43450 | |
|
|
2af414680f | |
|
|
417ddaafba | |
|
|
9df5643e76 | |
|
|
07b0df8a46 | |
|
|
bd19a47a75 | |
|
|
b77b2288f2 | |
|
|
ec27c3bc81 | |
|
|
7a91383726 | |
|
|
688a828548 | |
|
|
7b5ba18dfa | |
|
|
1a344aeed7 | |
|
|
4777c0c597 | |
|
|
545f8d4c2f | |
|
|
52c61b3f2e | |
|
|
64c8f85298 | |
|
|
31cc96b6c6 | |
|
|
d7a571400d | |
|
|
149a4d2dcb | |
|
|
4564ffbd99 | |
|
|
e7574decbc | |
|
|
1f321c27c9 | |
|
|
b3751302a9 | |
|
|
95e915c003 | |
|
|
a5f2b49a51 | |
|
|
4cf2810533 | |
|
|
2712da9b89 | |
|
|
136beef976 | |
|
|
46be166a04 | |
|
|
67418eefc3 | |
|
|
a47f0b6218 | |
|
|
aa00fe13ca | |
|
|
dbfc6153ab | |
|
|
ea38c36478 | |
|
|
4dbdcfce7a | |
|
|
5669222c5c | |
|
|
1054ae4d3e | |
|
|
44d4e4175d | |
|
|
cb21c0ab03 | |
|
|
50499df38e | |
|
|
784063b996 | |
|
|
6c32607ef8 | |
|
|
fe5564da7b | |
|
|
d0f6f7d6a8 | |
|
|
e9dcba923c | |
|
|
bbe5e3a908 | |
|
|
ef6d0eb3cc | |
|
|
aa152a8fd4 | |
|
|
c11f3d4204 | |
|
|
9a4abfd68b | |
|
|
d99cf7cb03 | |
|
|
ef8a3b6cf5 | |
|
|
be9bbb971e | |
|
|
b022bfce95 | |
|
|
55e29f68a6 | |
|
|
7a590fd046 | |
|
|
7b92842a4b | |
|
|
c9ced95bce | |
|
|
697805638c | |
|
|
ab03600b0d | |
|
|
57a8c2f9db | |
|
|
1e2e8518a4 | |
|
|
427adefbc6 | |
|
|
20ee87615a | |
|
|
2f4628e5a7 | |
|
|
b73abe782c | |
|
|
2f65d801ec | |
|
|
80cc86b4f8 | |
|
|
94f1d45c7f | |
|
|
3546f980fd | |
|
|
bc240b7886 | |
|
|
adf2946881 | |
|
|
64e9c6182e | |
|
|
487291a54f | |
|
|
a8e55fc0e8 | |
|
|
21e21aca1d | |
|
|
3d73b2473f | |
|
|
b3bff24139 | |
|
|
7b54155ae1 | |
|
|
0f53df4bb4 | |
|
|
1b444a4582 | |
|
|
b6afc40941 | |
|
|
e1d0747fc3 | |
|
|
ca25128e9b | |
|
|
d70fc7f34d | |
|
|
0eb6a299d7 | |
|
|
04c863cc14 | |
|
|
dcf88a7be5 | |
|
|
c5cde472dd | |
|
|
e819248df2 | |
|
|
2285e1d18e | |
|
|
ce8f6746bf | |
|
|
613061d342 | |
|
|
f45357752a | |
|
|
85a994bdf5 | |
|
|
2647d6e41b | |
|
|
cc33a01bd0 | |
|
|
ae4462f5b7 | |
|
|
2265a153a2 | |
|
|
661e716d6c | |
|
|
08d11652ab | |
|
|
80eafad3fe | |
|
|
1e31172c76 | |
|
|
e3e730c762 | |
|
|
635fa8dc98 | |
|
|
77d5642b7a | |
|
|
6b299828f0 | |
|
|
2e64ab92d4 | |
|
|
7850b7f0cd | |
|
|
86702efd50 | |
|
|
1dd879f255 | |
|
|
9b75a0d09e | |
|
|
8b4b3878d3 | |
|
|
2bc26612ca | |
|
|
3458b0c166 | |
|
|
8e40c0a53f | |
|
|
bb81e9b8f4 | |
|
|
0f0c2c5c1b | |
|
|
867001ebd9 | |
|
|
a33f97b227 | |
|
|
343567c1c8 | |
|
|
36ff740139 | |
|
|
799a23adca | |
|
|
6c07003156 | |
|
|
1c6abf0146 | |
|
|
4ebcbadea2 | |
|
|
0b5f8ba670 | |
|
|
8711d20e72 | |
|
|
b45ac60a2a | |
|
|
03d1aa08a2 | |
|
|
ad099aa9c9 | |
|
|
7eeaf845ac | |
|
|
f7ef221e4f | |
|
|
068fdc2105 | |
|
|
3a46d7bba8 | |
|
|
baebe2da82 | |
|
|
0cfb8001e8 | |
|
|
e471637325 | |
|
|
4c3aea94a2 | |
|
|
777aaf9ea9 | |
|
|
a8c20aa760 | |
|
|
08481ba0d3 | |
|
|
f03660eb79 | |
|
|
0e0e66775e | |
|
|
d0dd319de2 | |
|
|
4770ee7f78 | |
|
|
5c277597f7 | |
|
|
e512ec339d | |
|
|
2ff3fb763a | |
|
|
c74fc8fa27 | |
|
|
0e5f9b67f6 | |
|
|
1eedb71209 | |
|
|
d6589c53a3 | |
|
|
74b5c1da91 | |
|
|
7979e8088b | |
|
|
05fd54ed8d | |
|
|
cc4647e3b4 | |
|
|
73f21b9cc4 | |
|
|
e9b619df87 | |
|
|
9d35018021 | |
|
|
e1726f0434 | |
|
|
ea14358a2e | |
|
|
8e13f2e025 | |
|
|
d1faa6cdfe | |
|
|
917ff13a0a | |
|
|
14cce365b8 | |
|
|
33851d484a | |
|
|
1181278091 | |
|
|
02f6f184a7 | |
|
|
a719bb5558 | |
|
|
b99d405e87 | |
|
|
d8fd6d4262 | |
|
|
6986100357 | |
|
|
e52308fc6c | |
|
|
e2399629c3 | |
|
|
5ede10f8d6 | |
|
|
0633d7c371 | |
|
|
0bc3cb3360 | |
|
|
861bb95a05 | |
|
|
c5b08186d0 | |
|
|
a6a9e8a523 | |
|
|
5ef4c23ae7 | |
|
|
0515e28828 | |
|
|
49ff743f31 | |
|
|
b5a77c09d1 | |
|
|
933c0049b9 | |
|
|
4f0ea050d3 | |
|
|
89c9b4d72e | |
|
|
75849acb9c | |
|
|
b285f6c86f | |
|
|
24a338d1b7 | |
|
|
5e4283a1ac | |
|
|
ee444d2700 | |
|
|
8ecb0c6892 | |
|
|
d57333f5d1 | |
|
|
c957a38784 | |
|
|
23789510b3 | |
|
|
9b759003ff | |
|
|
9dee92ef6f | |
|
|
882759b6fa | |
|
|
e42fd8f257 | |
|
|
b159715f6a | |
|
|
b2460f0683 | |
|
|
bc3f122966 | |
|
|
7ba32d59a8 | |
|
|
8eb9ab9887 | |
|
|
1a5abfc580 | |
|
|
a8284d136e | |
|
|
afdc7838fa | |
|
|
53a0c5fbee | |
|
|
2fbfcf3d59 | |
|
|
ab666b6a57 | |
|
|
097dd43301 | |
|
|
1d0ef76314 | |
|
|
7a29254c2e | |
|
|
55f503fc6f | |
|
|
0291efe8c9 | |
|
|
29debb2477 | |
|
|
1f6665086b | |
|
|
d96ae21abe | |
|
|
da6ba70750 | |
|
|
2a9d8e96e3 | |
|
|
b2e8152adb | |
|
|
5b7aca8317 | |
|
|
893ba57c26 | |
|
|
e1b5a37f27 | |
|
|
12693c0aee | |
|
|
4682878d00 | |
|
|
3a3c1cf4bb | |
|
|
9eceae2034 | |
|
|
afaa32863e | |
|
|
88cab67d73 | |
|
|
cc04600a68 | |
|
|
5686ab5d95 | |
|
|
fcf8a3fa5c | |
|
|
01570c55e5 | |
|
|
34751f808f | |
|
|
a88561ce7f | |
|
|
45e528c7f3 | |
|
|
ede5d3c902 | |
|
|
6d81c5630d | |
|
|
a919e84c6d | |
|
|
89a89e38c4 | |
|
|
205dba012e | |
|
|
8d60d0fd9b | |
|
|
51c48d5586 | |
|
|
35be552011 | |
|
|
6917053179 | |
|
|
4b601c981a | |
|
|
787af83f07 | |
|
|
45f17869d1 | |
|
|
71fb91ec3f | |
|
|
842ca4aab8 | |
|
|
86d0c8c661 | |
|
|
4206cba099 | |
|
|
6c1b2cb7a5 | |
|
|
85947a143e | |
|
|
d9d0a6034f | |
|
|
6e09948f9b | |
|
|
555c0f2e58 | |
|
|
b2a07d79c3 | |
|
|
1f83bf5d08 | |
|
|
de4b8102c6 | |
|
|
2b3852a21a | |
|
|
1a1381dd19 | |
|
|
16eeea5b55 | |
|
|
5bdccd47d6 | |
|
|
75bda07282 | |
|
|
566e165d3f | |
|
|
618547c080 | |
|
|
1205e6c5bb | |
|
|
94c179f666 | |
|
|
f86e9b653a | |
|
|
02b107e7a8 | |
|
|
12f908a01b | |
|
|
97391dd76f | |
|
|
df8e8f1efc | |
|
|
9747bc014a | |
|
|
6ed301663c | |
|
|
f0487ec52c | |
|
|
9e270928d5 | |
|
|
1d04958271 | |
|
|
b65ce9a93c | |
|
|
432bb8a67b | |
|
|
e31a200c41 | |
|
|
18f5a5b135 | |
|
|
e628d37039 | |
|
|
f1cbf04318 | |
|
|
ed993112ae | |
|
|
d73b9f8500 | |
|
|
39929518ea | |
|
|
f21d8ec594 | |
|
|
1a96d9ff5e | |
|
|
1a381bad79 | |
|
|
dea34e68e7 | |
|
|
20d4e50698 | |
|
|
9bf619a7fe | |
|
|
93e5f5a84c | |
|
|
b6ef418a07 | |
|
|
2f6ecb3199 | |
|
|
b0f9fbc69a | |
|
|
88622a8245 | |
|
|
6d01fefb6f | |
|
|
3bffb17ee6 | |
|
|
6a125006eb | |
|
|
94a72409e9 | |
|
|
2cd0b029d5 | |
|
|
1250921a31 | |
|
|
aad724b454 | |
|
|
cb59454a47 | |
|
|
b6d1851aef | |
|
|
f3999f601f | |
|
|
51ae3d4fd8 | |
|
|
82ca5cbbc0 | |
|
|
7e6a55d72f | |
|
|
9fe44e481e | |
|
|
2d6253973d | |
|
|
463eda96ec | |
|
|
921b87e797 | |
|
|
3d61e3db82 | |
|
|
b5d26d3d2b | |
|
|
66d2c4a885 | |
|
|
0ded563530 | |
|
|
c6b0b0d7bf | |
|
|
453284d37b | |
|
|
2c91968fdc | |
|
|
7a5ddf6243 | |
|
|
8c19fb411b | |
|
|
59b15d7db6 | |
|
|
373792222e | |
|
|
c4be015c0f | |
|
|
21f159b4f8 | |
|
|
1517c53611 | |
|
|
f2692e162c | |
|
|
cd61ff3398 | |
|
|
4d583007da | |
|
|
4460f594a4 | |
|
|
0c60a077e3 | |
|
|
a5bb4ad0cc | |
|
|
43496dc78d | |
|
|
90e9817503 | |
|
|
c373f6f148 | |
|
|
7acdb2037c | |
|
|
df9c885a31 | |
|
|
0f6423fd0a | |
|
|
5496b7cf49 | |
|
|
c9f31d9e3d | |
|
|
de3098db58 | |
|
|
1631d62bfe | |
|
|
f8e95262d2 | |
|
|
ee679410ea | |
|
|
acd1f2ea22 | |
|
|
745c70243e | |
|
|
38ec863753 | |
|
|
6431ddc873 | |
|
|
c0deed6673 | |
|
|
22252474bf | |
|
|
0bfac92fe1 | |
|
|
305e1a41dc | |
|
|
5d400f6be8 | |
|
|
1dafb3dec3 | |
|
|
90ad1399ad | |
|
|
0aac2976a7 | |
|
|
f50c1fef04 | |
|
|
d240fc3a2a | |
|
|
adde0b3480 | |
|
|
3f03e57a0a | |
|
|
597205e19c | |
|
|
27a29b573f | |
|
|
b0dff239f9 | |
|
|
1da691921b | |
|
|
508979d7b2 | |
|
|
15ef3d7332 | |
|
|
9238f55ebb | |
|
|
9e9a8ba11c | |
|
|
fbc71e057c | |
|
|
72f74326b1 | |
|
|
a4e1636b53 | |
|
|
f854e7b0a9 | |
|
|
05b62eb1b3 | |
|
|
9d5135098b | |
|
|
ce0326f21b | |
|
|
aece04b97b | |
|
|
959516a53b | |
|
|
fa49508457 | |
|
|
36d4770648 | |
|
|
612070a006 | |
|
|
b2ca884774 | |
|
|
15f5d73d4a | |
|
|
9ddcd41cdd | |
|
|
92508aff07 | |
|
|
3efb53a590 | |
|
|
6a7e4149ea | |
|
|
10e6b14199 | |
|
|
d64533410d | |
|
|
ff5cb4276a | |
|
|
631d186d50 | |
|
|
4b2075008f | |
|
|
4fa303f2c0 | |
|
|
014dba7afd | |
|
|
e6608abb28 | |
|
|
d4a7dce0d7 | |
|
|
041af69465 | |
|
|
05ed714e9f | |
|
|
63fe5b1ebc | |
|
|
412b1dafeb | |
|
|
a8f3a1c754 | |
|
|
70432c18f6 | |
|
|
641afa42f3 | |
|
|
1f2ed6f92b | |
|
|
ffa94a7a7f | |
|
|
889aa996de | |
|
|
a09f6a724a | |
|
|
3fb9988b9e | |
|
|
fb406b7940 | |
|
|
dd532f0aac | |
|
|
66ca5e2d4e | |
|
|
8bbbf9f01f | |
|
|
13bef27dbf | |
|
|
660067ed69 | |
|
|
dd5d6f3e69 | |
|
|
5efaf15990 | |
|
|
5e9b785962 | |
|
|
5038956f51 | |
|
|
5c7bf4d047 | |
|
|
55cc0c1f0a | |
|
|
9a9b420623 | |
|
|
b216095142 | |
|
|
2061a8cb36 | |
|
|
982532c200 | |
|
|
da9e84731b | |
|
|
b87aa69a4b | |
|
|
214ea3e5e2 | |
|
|
adb958d25c | |
|
|
94f0291c3a | |
|
|
97d8f0edcf | |
|
|
51271e8a2a | |
|
|
f629721026 | |
|
|
7bee714ada | |
|
|
a039f4b4c3 | |
|
|
c6a3b3a01b | |
|
|
2de0ff3897 | |
|
|
fd1b7d51a2 | |
|
|
6c3be07d83 | |
|
|
54935bbe26 | |
|
|
016f05fbc0 | |
|
|
f43aef1fe2 | |
|
|
a17eabbe42 | |
|
|
8d2ab6d3ea | |
|
|
15ca24b0ac | |
|
|
6126a73df3 | |
|
|
9088e17be8 | |
|
|
22c117ad65 | |
|
|
f80cc38c6a | |
|
|
71a39dc648 | |
|
|
57c83d2b9d | |
|
|
2d9cd4b12f | |
|
|
40048a1065 | |
|
|
2d72f3ad3f | |
|
|
0a91c3017a | |
|
|
b083b5995d | |
|
|
0cae26eee6 | |
|
|
779b0cabcb | |
|
|
2c915edc85 | |
|
|
78b242f85d | |
|
|
1d60b914dd | |
|
|
6190a8c8ce | |
|
|
ef2477e3d6 | |
|
|
fe233203b5 | |
|
|
6cec94e927 | |
|
|
c8e8b1f521 | |
|
|
29a8df61a9 | |
|
|
c3d2204e7d | |
|
|
e5aad8c828 | |
|
|
aac7e24674 | |
|
|
b04f37c702 | |
|
|
86ab1026b8 | |
|
|
ae35b548e5 | |
|
|
901f8a2d8a | |
|
|
ee12177ea8 | |
|
|
cde76d7d18 | |
|
|
e5ea7988c0 | |
|
|
8f198d724c | |
|
|
b9a390d1b9 | |
|
|
d5fb03c0aa | |
|
|
1c77b82aa6 | |
|
|
3b7f4684a1 | |
|
|
ea12763627 | |
|
|
485083d9df | |
|
|
0b2edf33f1 | |
|
|
86e5543fdb | |
|
|
f3f4155ace | |
|
|
9b93d96bd2 | |
|
|
cf8059f65e | |
|
|
ee05acf11d | |
|
|
ff326ff356 | |
|
|
4c280f9196 | |
|
|
6118fc8a66 | |
|
|
3fe4b2a1ae | |
|
|
64424e9197 | |
|
|
f8f1f2293c | |
|
|
3c80fe9d96 | |
|
|
4dc67fb694 | |
|
|
a2b815c76d | |
|
|
7ea4d5ada9 | |
|
|
ba2a9ed6b9 | |
|
|
46d78f3c46 | |
|
|
6fdf8400b3 | |
|
|
cfcd07b4fd | |
|
|
aa032efacf | |
|
|
ad01e169e5 | |
|
|
0851730ecb | |
|
|
9c06bb0b64 | |
|
|
622b2d3450 | |
|
|
fd49e41c55 | |
|
|
cb3061b43f | |
|
|
14fb2f40d4 | |
|
|
156a44153a | |
|
|
a98044321a | |
|
|
2444c8e1f3 | |
|
|
9890c73c56 | |
|
|
8a74be38b9 | |
|
|
05b5498873 | |
|
|
1dc141dbba | |
|
|
c097c93a53 | |
|
|
3e5f5efd19 | |
|
|
3da429101f | |
|
|
b24debdcf1 | |
|
|
11de558cdb | |
|
|
8569d8d17e | |
|
|
3004f0dde8 | |
|
|
43773a8a1f | |
|
|
adc90ad9af | |
|
|
b333de4512 | |
|
|
1650f64e2a | |
|
|
a190af1e0c | |
|
|
9bda77f33c | |
|
|
a22fa37ab0 | |
|
|
a0a281e725 | |
|
|
2390408192 | |
|
|
55170ce971 | |
|
|
57c54a1a3f |
|
|
@ -0,0 +1,3 @@
|
||||||
|
# macOS
|
||||||
|
|
||||||
|
.DS_Store
|
||||||
|
|
@ -0,0 +1,3 @@
|
||||||
|
[submodule "build_options_helper"]
|
||||||
|
path = xcode/config_generator/build_options_helper
|
||||||
|
url = https://github.com/petropavel13/build_options_helper
|
||||||
25
README.md
25
README.md
|
|
@ -1 +1,26 @@
|
||||||
# BuildScripts
|
# BuildScripts
|
||||||
|
|
||||||
|
## Настройки форматирования
|
||||||
|
|
||||||
|
Позволяют настроить одинаковое форматирования кода в Android Studio у всех, кто работает на проекте.
|
||||||
|
Настройки соответствуют
|
||||||
|
[Правилам оформления Kotlin кода](https://styleguide.docs.touchin.ru/Coding/KotlinCodestyle.html)
|
||||||
|
|
||||||
|
Есть два варианта использования: подключить к проекту или импортировать схему в Android Studio.
|
||||||
|
|
||||||
|
### Как подключить к проекту:
|
||||||
|
|
||||||
|
1. Скопировать директорию [`codeStyles`](./codeStyles) в директорию проекта `.idea`
|
||||||
|
2. Добавить в файл `.gitignore` строку `!.idea/codeStyles`
|
||||||
|
3. Перезапустить Android Studio, чтобы настройки применились
|
||||||
|
|
||||||
|
При таком варианте настройки будут применены у всех, кто работает на проекте.
|
||||||
|
И только для одного конкретного проекта.
|
||||||
|
|
||||||
|
### Как импортировать схему в Android Studio:
|
||||||
|
|
||||||
|
1. Скачать схему [`codeStyles/Project.xml`](./codeStyles/Project.xml)
|
||||||
|
2. В Android Studio перейти в `File` > `Settings` > `Editor` > `Code Style`
|
||||||
|
3. Нажать на шестеренку справа от выпадающего списка схем и выбрать `Import Scheme`
|
||||||
|
4. В открывшемся окне указать путь до сохраненной схемы и нажать `ОК`
|
||||||
|
5. В открывшемся окне ввести название новой схемы и нажать `ОК`
|
||||||
|
|
|
||||||
|
|
@ -1,210 +0,0 @@
|
||||||
<?xml version="1.0"?>
|
|
||||||
<!DOCTYPE module PUBLIC
|
|
||||||
"-//Puppy Crawl//DTD Check Configuration 1.3//EN"
|
|
||||||
"http://www.puppycrawl.com/dtds/configuration_1_3.dtd">
|
|
||||||
|
|
||||||
<!--
|
|
||||||
|
|
||||||
Checkstyle configuration that checks the Google coding conventions from:
|
|
||||||
|
|
||||||
- Google Java Style
|
|
||||||
https://google-styleguide.googlecode.com/svn-history/r130/trunk/javaguide.html
|
|
||||||
|
|
||||||
Checkstyle is very configurable. Be sure to read the documentation at
|
|
||||||
http://checkstyle.sf.net (or in your downloaded distribution).
|
|
||||||
|
|
||||||
Most Checks are configurable, be sure to consult the documentation.
|
|
||||||
|
|
||||||
To completely disable a check, just comment it out or delete it from the file.
|
|
||||||
|
|
||||||
Authors: Max Vetrenko, Ruslan Diachenko, Roman Ivanov.
|
|
||||||
|
|
||||||
-->
|
|
||||||
|
|
||||||
<module name = "Checker">
|
|
||||||
<property name="charset" value="UTF-8"/>
|
|
||||||
|
|
||||||
<property name="severity" value="warning"/>
|
|
||||||
|
|
||||||
<property name="fileExtensions" value="java, properties, xml"/>
|
|
||||||
<!-- Checks for whitespace -->
|
|
||||||
<!-- See http://checkstyle.sf.net/config_whitespace.html -->
|
|
||||||
<module name="FileTabCharacter">
|
|
||||||
<property name="eachLine" value="true"/>
|
|
||||||
</module>
|
|
||||||
|
|
||||||
<module name="TreeWalker">
|
|
||||||
<module name="MethodLength">
|
|
||||||
<property name="max" value="40"/>
|
|
||||||
</module>
|
|
||||||
<module name="FinalParameters">
|
|
||||||
<property name="tokens" value="METHOD_DEF, CTOR_DEF, LITERAL_CATCH, FOR_EACH_CLAUSE"/>
|
|
||||||
</module>
|
|
||||||
|
|
||||||
<module name="OuterTypeFilename"/>
|
|
||||||
<module name="IllegalTokenText">
|
|
||||||
<property name="tokens" value="STRING_LITERAL, CHAR_LITERAL"/>
|
|
||||||
<property name="format" value="\\u00(08|09|0(a|A)|0(c|C)|0(d|D)|22|27|5(C|c))|\\(0(10|11|12|14|15|42|47)|134)"/>
|
|
||||||
<property name="message" value="Avoid using corresponding octal or Unicode escape."/>
|
|
||||||
</module>
|
|
||||||
<module name="AvoidEscapedUnicodeCharacters">
|
|
||||||
<property name="allowEscapesForControlCharacters" value="true"/>
|
|
||||||
<property name="allowByTailComment" value="true"/>
|
|
||||||
<property name="allowNonPrintableEscapes" value="true"/>
|
|
||||||
</module>
|
|
||||||
<module name="LineLength">
|
|
||||||
<property name="max" value="150"/>
|
|
||||||
<property name="ignorePattern" value="^package.*|^import.*|a href|href|http://|https://|ftp://"/>
|
|
||||||
</module>
|
|
||||||
<module name="AvoidStarImport"/>
|
|
||||||
<module name="OneTopLevelClass"/>
|
|
||||||
<module name="NoLineWrap"/>
|
|
||||||
<module name="EmptyBlock">
|
|
||||||
<property name="option" value="TEXT"/>
|
|
||||||
<property name="tokens" value="LITERAL_TRY, LITERAL_FINALLY, LITERAL_IF, LITERAL_ELSE, LITERAL_SWITCH"/>
|
|
||||||
</module>
|
|
||||||
<module name="NeedBraces"/>
|
|
||||||
<module name="LeftCurly">
|
|
||||||
<property name="maxLineLength" value="150"/>
|
|
||||||
</module>
|
|
||||||
<module name="RightCurly"/>
|
|
||||||
<module name="RightCurly">
|
|
||||||
<property name="option" value="alone"/>
|
|
||||||
<property name="tokens" value="CLASS_DEF, METHOD_DEF, CTOR_DEF, LITERAL_FOR, LITERAL_WHILE, LITERAL_DO, STATIC_INIT, INSTANCE_INIT"/>
|
|
||||||
</module>
|
|
||||||
<module name="WhitespaceAround">
|
|
||||||
<property name="allowEmptyConstructors" value="true"/>
|
|
||||||
<property name="allowEmptyMethods" value="true"/>
|
|
||||||
<property name="allowEmptyTypes" value="true"/>
|
|
||||||
<property name="allowEmptyLoops" value="true"/>
|
|
||||||
<message key="ws.notFollowed"
|
|
||||||
value="WhitespaceAround: ''{0}'' is not followed by whitespace. Empty blocks may only be represented as '{}' when not part of a multi-block statement (4.1.3)"/>
|
|
||||||
<message key="ws.notPreceded"
|
|
||||||
value="WhitespaceAround: ''{0}'' is not preceded with whitespace."/>
|
|
||||||
</module>
|
|
||||||
<module name="OneStatementPerLine"/>
|
|
||||||
<module name="MultipleVariableDeclarations"/>
|
|
||||||
<module name="ArrayTypeStyle"/>
|
|
||||||
<module name="MissingSwitchDefault"/>
|
|
||||||
<module name="FallThrough"/>
|
|
||||||
<module name="UpperEll"/>
|
|
||||||
<module name="ModifierOrder"/>
|
|
||||||
<module name="EmptyLineSeparator">
|
|
||||||
<property name="allowNoEmptyLineBetweenFields" value="true"/>
|
|
||||||
</module>
|
|
||||||
<module name="SeparatorWrap">
|
|
||||||
<property name="tokens" value="DOT"/>
|
|
||||||
<property name="option" value="nl"/>
|
|
||||||
</module>
|
|
||||||
<module name="SeparatorWrap">
|
|
||||||
<property name="tokens" value="COMMA"/>
|
|
||||||
<property name="option" value="EOL"/>
|
|
||||||
</module>
|
|
||||||
<module name="PackageName">
|
|
||||||
<property name="format" value="^[a-z]+(\.[a-z][a-z0-9]*)*$"/>
|
|
||||||
<message key="name.invalidPattern"
|
|
||||||
value="Package name ''{0}'' must match pattern ''{1}''."/>
|
|
||||||
</module>
|
|
||||||
<module name="TypeName">
|
|
||||||
<message key="name.invalidPattern"
|
|
||||||
value="Type name ''{0}'' must match pattern ''{1}''."/>
|
|
||||||
</module>
|
|
||||||
<module name="MemberName">
|
|
||||||
<property name="format" value="^[a-z][a-z0-9][a-zA-Z0-9]*$"/>
|
|
||||||
<message key="name.invalidPattern"
|
|
||||||
value="Member name ''{0}'' must match pattern ''{1}''."/>
|
|
||||||
</module>
|
|
||||||
<module name="ParameterName">
|
|
||||||
<property name="format" value="^[a-z][a-z0-9][a-zA-Z0-9]*$"/>
|
|
||||||
<message key="name.invalidPattern"
|
|
||||||
value="Parameter name ''{0}'' must match pattern ''{1}''."/>
|
|
||||||
</module>
|
|
||||||
<module name="LocalVariableName">
|
|
||||||
<property name="tokens" value="VARIABLE_DEF"/>
|
|
||||||
<property name="format" value="^[a-z][a-z0-9][a-zA-Z0-9]*$"/>
|
|
||||||
<property name="allowOneCharVarInForLoop" value="true"/>
|
|
||||||
<message key="name.invalidPattern"
|
|
||||||
value="Local variable name ''{0}'' must match pattern ''{1}''."/>
|
|
||||||
</module>
|
|
||||||
<module name="ClassTypeParameterName">
|
|
||||||
<property name="format" value="^[T]([A-Z][a-zA-Z0-9]*)?$"/>
|
|
||||||
<message key="name.invalidPattern"
|
|
||||||
value="Class type name ''{0}'' must match pattern ''{1}''."/>
|
|
||||||
</module>
|
|
||||||
<module name="MethodTypeParameterName">
|
|
||||||
<property name="format" value="^[T]([A-Z][a-zA-Z0-9]*)?$"/>
|
|
||||||
<message key="name.invalidPattern"
|
|
||||||
value="Method type name ''{0}'' must match pattern ''{1}''."/>
|
|
||||||
</module>
|
|
||||||
<module name="NoFinalizer"/>
|
|
||||||
<module name="GenericWhitespace">
|
|
||||||
<message key="ws.followed"
|
|
||||||
value="GenericWhitespace ''{0}'' is followed by whitespace."/>
|
|
||||||
<message key="ws.preceded"
|
|
||||||
value="GenericWhitespace ''{0}'' is preceded with whitespace."/>
|
|
||||||
<message key="ws.illegalFollow"
|
|
||||||
value="GenericWhitespace ''{0}'' should followed by whitespace."/>
|
|
||||||
<message key="ws.notPreceded"
|
|
||||||
value="GenericWhitespace ''{0}'' is not preceded with whitespace."/>
|
|
||||||
</module>
|
|
||||||
<module name="Indentation">
|
|
||||||
<property name="basicOffset" value="4"/>
|
|
||||||
<property name="braceAdjustment" value="0"/>
|
|
||||||
<property name="caseIndent" value="4"/>
|
|
||||||
<property name="throwsIndent" value="4"/>
|
|
||||||
<property name="lineWrappingIndentation" value="4"/>
|
|
||||||
<property name="arrayInitIndent" value="4"/>
|
|
||||||
</module>
|
|
||||||
<module name="AbbreviationAsWordInName">
|
|
||||||
<property name="ignoreFinal" value="false"/>
|
|
||||||
<property name="allowedAbbreviationLength" value="1"/>
|
|
||||||
</module>
|
|
||||||
<module name="OverloadMethodsDeclarationOrder"/>
|
|
||||||
<module name="VariableDeclarationUsageDistance"/>
|
|
||||||
<module name="MethodParamPad"/>
|
|
||||||
<module name="OperatorWrap">
|
|
||||||
<property name="option" value="NL"/>
|
|
||||||
<property name="tokens" value="BAND, BOR, BSR, BXOR, DIV, EQUAL, GE, GT, LAND, LE, LITERAL_INSTANCEOF, LOR, LT, MINUS, MOD, NOT_EQUAL, PLUS, QUESTION, SL, SR, STAR "/>
|
|
||||||
</module>
|
|
||||||
<module name="AnnotationLocation">
|
|
||||||
<property name="tokens" value="CLASS_DEF, INTERFACE_DEF, ENUM_DEF, METHOD_DEF, CTOR_DEF"/>
|
|
||||||
</module>
|
|
||||||
<module name="AnnotationLocation">
|
|
||||||
<property name="tokens" value="VARIABLE_DEF"/>
|
|
||||||
<property name="allowSamelineMultipleAnnotations" value="true"/>
|
|
||||||
</module>
|
|
||||||
<module name="NonEmptyAtclauseDescription"/>
|
|
||||||
<module name="JavadocTagContinuationIndentation"/>
|
|
||||||
<module name="SummaryJavadocCheck">
|
|
||||||
<property name="forbiddenSummaryFragments" value="^@return the *|^This method returns |^A [{]@code [a-zA-Z0-9]+[}]( is a )"/>
|
|
||||||
</module>
|
|
||||||
<module name="JavadocParagraph"/>
|
|
||||||
<module name="AtclauseOrder">
|
|
||||||
<property name="tagOrder" value="@param, @return, @throws, @deprecated"/>
|
|
||||||
<property name="target" value="CLASS_DEF, INTERFACE_DEF, ENUM_DEF, METHOD_DEF, CTOR_DEF, VARIABLE_DEF"/>
|
|
||||||
</module>
|
|
||||||
<module name="JavadocMethod">
|
|
||||||
<property name="scope" value="nothing"/>
|
|
||||||
<property name="allowMissingParamTags" value="true"/>
|
|
||||||
<property name="allowMissingThrowsTags" value="true"/>
|
|
||||||
<property name="allowMissingReturnTag" value="true"/>
|
|
||||||
<property name="minLineCount" value="2"/>
|
|
||||||
<property name="allowedAnnotations" value="Override, Test"/>
|
|
||||||
<property name="allowThrowsTagsForSubclasses" value="true"/>
|
|
||||||
</module>
|
|
||||||
<module name="MethodName">
|
|
||||||
<property name="format" value="^[a-z][a-z0-9][a-zA-Z0-9_]*$"/>
|
|
||||||
<message key="name.invalidPattern"
|
|
||||||
value="Method name ''{0}'' must match pattern ''{1}''."/>
|
|
||||||
</module>
|
|
||||||
<module name="SingleLineJavadoc"/>
|
|
||||||
<module name="EmptyCatchBlock">
|
|
||||||
<property name="exceptionVariableName" value="expected"/>
|
|
||||||
</module>
|
|
||||||
<module name="SuppressWarningsHolder" />
|
|
||||||
</module>
|
|
||||||
<module name="SuppressWarningsFilter" />
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
</module>
|
|
||||||
|
|
@ -1,340 +0,0 @@
|
||||||
<?xml version="1.0"?>
|
|
||||||
<!DOCTYPE module PUBLIC
|
|
||||||
"-//Puppy Crawl//DTD Check Configuration 1.3//EN"
|
|
||||||
"http://www.puppycrawl.com/dtds/configuration_1_3.dtd">
|
|
||||||
|
|
||||||
<module name="Checker">
|
|
||||||
<property name="charset" value="UTF-8"/>
|
|
||||||
<property name="severity" value="warning"/>
|
|
||||||
<property name="fileExtensions" value="java, properties, xml"/>
|
|
||||||
|
|
||||||
<module name="FileTabCharacter">
|
|
||||||
<property name="eachLine" value="true"/>
|
|
||||||
</module>
|
|
||||||
|
|
||||||
<module name="TreeWalker">
|
|
||||||
<!-- CUSTOM CHECKS START-->
|
|
||||||
<module name="NullAnnotationsCheck"/>
|
|
||||||
<module name="CustomDeclarationOrder">
|
|
||||||
<property name="customDeclarationOrder"
|
|
||||||
value="Field(static final)
|
|
||||||
### Field(static)
|
|
||||||
### Ctor(static)
|
|
||||||
### Method(static)
|
|
||||||
### Field(.*)
|
|
||||||
### Ctor(.*)
|
|
||||||
### Method(.*)
|
|
||||||
### InnerEnum(.*)
|
|
||||||
### InnerInterface(.*)
|
|
||||||
### InnerClass(.*)"/>
|
|
||||||
</module>
|
|
||||||
<!-- CUSTOM CHECKS END-->
|
|
||||||
|
|
||||||
<module name="AbbreviationAsWordInName">
|
|
||||||
<property name="ignoreFinal" value="false"/>
|
|
||||||
<property name="allowedAbbreviationLength" value="1"/>
|
|
||||||
</module>
|
|
||||||
<!-- <module name="AbstractClassName"/> -->
|
|
||||||
<module name="AnnotationLocation">
|
|
||||||
<property name="tokens" value="CLASS_DEF, INTERFACE_DEF, ENUM_DEF, METHOD_DEF, CTOR_DEF"/>
|
|
||||||
<property name="allowSamelineSingleParameterlessAnnotation" value="false"/>
|
|
||||||
</module>
|
|
||||||
<module name="AnnotationLocation">
|
|
||||||
<property name="tokens"
|
|
||||||
value="VARIABLE_DEF, PARAMETER_DEF, ANNOTATION_DEF, TYPECAST, LITERAL_THROWS, IMPLEMENTS_CLAUSE, TYPE_ARGUMENT, LITERAL_NEW, DOT, ANNOTATION_FIELD_DEF"/>
|
|
||||||
<property name="allowSamelineMultipleAnnotations" value="true"/>
|
|
||||||
</module>
|
|
||||||
<!-- <module name="AnnotationUseStyle"/> -->
|
|
||||||
<!-- <module name="AnonInnerLength"/> -->
|
|
||||||
<!-- <module name="ArrayTrailingComma"/> -->
|
|
||||||
<module name="ArrayTypeStyle"/>
|
|
||||||
<module name="AtclauseOrder">
|
|
||||||
<property name="tagOrder" value="@param, @return, @throws, @deprecated"/>
|
|
||||||
<property name="target" value="CLASS_DEF, INTERFACE_DEF, ENUM_DEF, METHOD_DEF, CTOR_DEF, VARIABLE_DEF"/>
|
|
||||||
</module>
|
|
||||||
<module name="AvoidEscapedUnicodeCharacters">
|
|
||||||
<property name="allowEscapesForControlCharacters" value="true"/>
|
|
||||||
<property name="allowByTailComment" value="true"/>
|
|
||||||
<property name="allowNonPrintableEscapes" value="true"/>
|
|
||||||
</module>
|
|
||||||
<!-- <module name="AvoidInlineConditionals"/> -->
|
|
||||||
<module name="AvoidNestedBlocks">
|
|
||||||
<property name="allowInSwitchCase" value="true"/>
|
|
||||||
</module>
|
|
||||||
<module name="AvoidStarImport"/>
|
|
||||||
<module name="AvoidStaticImport"/>
|
|
||||||
<!-- <module name="BooleanExpressionComplexity"/> -->
|
|
||||||
<module name="CatchParameterName">
|
|
||||||
<property name="format" value="^[a-z][a-z0-9][a-zA-Z0-9]*$"/>
|
|
||||||
<message key="name.invalidPattern"
|
|
||||||
value="Catch parameter name ''{0}'' must match pattern ''{1}''."/>
|
|
||||||
</module>
|
|
||||||
<!-- <module name="ClassDataAbstractionCoupling"/> -->
|
|
||||||
<!-- <module name="ClassFanOutComplexity"/> -->
|
|
||||||
<module name="ClassTypeParameterName">
|
|
||||||
<property name="format" value="^[T]([A-Z][a-zA-Z0-9]*)?$"/>
|
|
||||||
<message key="name.invalidPattern"
|
|
||||||
value="Class type name ''{0}'' must match pattern ''{1}''."/>
|
|
||||||
</module>
|
|
||||||
<module name="CommentsIndentation"/>
|
|
||||||
<module name="ConstantName"/>
|
|
||||||
<!-- <module name="CovariantEquals"/> -->
|
|
||||||
<!-- <module name="CustomImportOrder"/> -->
|
|
||||||
<!-- <module name="CyclomaticComplexity"/> -->
|
|
||||||
<!-- <module name="DeclarationOrder"/> -->
|
|
||||||
<module name="DefaultComesLast"/>
|
|
||||||
<!-- <module name="DescendantToken"/> -->
|
|
||||||
<!-- <module name="DesignForExtension"/> -->
|
|
||||||
<module name="EmptyBlock">
|
|
||||||
<property name="option" value="TEXT"/>
|
|
||||||
<property name="tokens"
|
|
||||||
value="LITERAL_WHILE, LITERAL_TRY, LITERAL_CATCH, LITERAL_FINALLY, LITERAL_DO, LITERAL_IF, LITERAL_ELSE, LITERAL_FOR, INSTANCE_INIT, STATIC_INIT, LITERAL_SWITCH, LITERAL_SYNCHRONIZED, LITERAL_CASE, LITERAL_DEFAULT"/>
|
|
||||||
</module>
|
|
||||||
<module name="EmptyCatchBlock">
|
|
||||||
<property name="exceptionVariableName" value="expected"/>
|
|
||||||
</module>
|
|
||||||
<!-- <module name="EmptyForInitializerPad"/> -->
|
|
||||||
<!-- <module name="EmptyForIteratorPad"/> -->
|
|
||||||
<module name="EmptyLineSeparator">
|
|
||||||
<property name="allowNoEmptyLineBetweenFields" value="true"/>
|
|
||||||
</module>
|
|
||||||
<module name="EmptyStatement"/>
|
|
||||||
<!-- <module name="EqualsAvoidNull"/> -->
|
|
||||||
<module name="EqualsHashCode"/>
|
|
||||||
<!-- <module name="ExecutableStatementCount"/> -->
|
|
||||||
<!-- <module name="ExplicitInitialization"/> -->
|
|
||||||
<module name="FallThrough"/>
|
|
||||||
<!-- <module name="FileLength"/> -->
|
|
||||||
<!-- <module name="FinalClass"/> -->
|
|
||||||
<module name="FinalLocalVariable"/>
|
|
||||||
<module name="FinalParameters">
|
|
||||||
<property name="tokens" value="METHOD_DEF, CTOR_DEF, LITERAL_CATCH, FOR_EACH_CLAUSE"/>
|
|
||||||
</module>
|
|
||||||
<module name="GenericWhitespace">
|
|
||||||
<message key="ws.followed"
|
|
||||||
value="GenericWhitespace ''{0}'' is followed by whitespace."/>
|
|
||||||
<message key="ws.preceded"
|
|
||||||
value="GenericWhitespace ''{0}'' is preceded with whitespace."/>
|
|
||||||
<message key="ws.illegalFollow"
|
|
||||||
value="GenericWhitespace ''{0}'' should followed by whitespace."/>
|
|
||||||
<message key="ws.notPreceded"
|
|
||||||
value="GenericWhitespace ''{0}'' is not preceded with whitespace."/>
|
|
||||||
</module>
|
|
||||||
<!-- <module name="Header"/> -->
|
|
||||||
<!-- <module name="HiddenField"> -->
|
|
||||||
<!-- <module name="HideUtilityClassConstructor"/> -->
|
|
||||||
<!-- <module name="IllegalCatch"/> -->
|
|
||||||
<!-- <module name="IllegalImport"/> -->
|
|
||||||
<!-- <module name="IllegalInstantiation"/> -->
|
|
||||||
<!-- <module name="IllegalThrows"/> -->
|
|
||||||
<!-- <module name="IllegalToken"/> -->
|
|
||||||
<module name="IllegalTokenText">
|
|
||||||
<property name="tokens" value="STRING_LITERAL, CHAR_LITERAL"/>
|
|
||||||
<property name="format" value="\\u00(08|09|0(a|A)|0(c|C)|0(d|D)|22|27|5(C|c))|\\(0(10|11|12|14|15|42|47)|134)"/>
|
|
||||||
<property name="message" value="Avoid using corresponding octal or Unicode escape."/>
|
|
||||||
</module>
|
|
||||||
<!-- <module name="IllegalType"/> -->
|
|
||||||
<!-- <module name="ImportControl"/> -->
|
|
||||||
<!-- <module name="ImportOrder"/> -->
|
|
||||||
<module name="Indentation">
|
|
||||||
<property name="basicOffset" value="4"/>
|
|
||||||
<property name="braceAdjustment" value="0"/>
|
|
||||||
<property name="caseIndent" value="4"/>
|
|
||||||
<property name="throwsIndent" value="4"/>
|
|
||||||
<property name="lineWrappingIndentation" value="4"/>
|
|
||||||
<property name="arrayInitIndent" value="8"/>
|
|
||||||
</module>
|
|
||||||
<module name="InnerAssignment"/>
|
|
||||||
<module name="InnerTypeLast"/>
|
|
||||||
<module name="InterfaceIsType"/>
|
|
||||||
<module name="InterfaceTypeParameterName">
|
|
||||||
<property name="format" value="^[T]([A-Z][a-zA-Z0-9]*)?$"/>
|
|
||||||
<message key="name.invalidPattern"
|
|
||||||
value="Class type name ''{0}'' must match pattern ''{1}''."/>
|
|
||||||
</module>
|
|
||||||
<module name="JavadocMethod">
|
|
||||||
<property name="scope" value="nothing"/>
|
|
||||||
<property name="allowMissingParamTags" value="true"/>
|
|
||||||
<property name="allowMissingThrowsTags" value="true"/>
|
|
||||||
<property name="allowMissingReturnTag" value="true"/>
|
|
||||||
<property name="minLineCount" value="2"/>
|
|
||||||
<property name="allowedAnnotations" value="Override, Test"/>
|
|
||||||
<property name="allowThrowsTagsForSubclasses" value="true"/>
|
|
||||||
</module>
|
|
||||||
<!-- <module name="JavadocPackage"/> -->
|
|
||||||
<module name="JavadocParagraph"/>
|
|
||||||
<!-- <module name="JavadocStyle"/> -->
|
|
||||||
<!-- https://youtrack.jetbrains.com/issue/IDEA-121723 <module name="JavadocTagContinuationIndentation"/> -->
|
|
||||||
<!-- <module name="JavadocType"/> -->
|
|
||||||
<!-- <module name="JavadocVariable"/> -->
|
|
||||||
<!-- <module name="JavaNCSS"/> -->
|
|
||||||
<module name="LeftCurly">
|
|
||||||
<property name="maxLineLength" value="150"/>
|
|
||||||
</module>
|
|
||||||
<module name="LineLength">
|
|
||||||
<property name="max" value="150"/>
|
|
||||||
<property name="ignorePattern" value="^package.*|^import.*|a href|href|http://|https://|ftp://"/>
|
|
||||||
</module>
|
|
||||||
<module name="LocalFinalVariableName">
|
|
||||||
<property name="format" value="^[a-z][a-z0-9][a-zA-Z0-9]*$"/>
|
|
||||||
<message key="name.invalidPattern"
|
|
||||||
value="Final variable/parameter name ''{0}'' must match pattern ''{1}''."/>
|
|
||||||
</module>
|
|
||||||
<module name="LocalVariableName">
|
|
||||||
<property name="allowOneCharVarInForLoop" value="true"/>
|
|
||||||
<property name="format" value="^[a-z][a-z0-9][a-zA-Z0-9]*$"/>
|
|
||||||
<message key="name.invalidPattern"
|
|
||||||
value="Local variable name ''{0}'' must match pattern ''{1}''."/>
|
|
||||||
</module>
|
|
||||||
<!-- <module name="MagicNumber"/> -->
|
|
||||||
<module name="MemberName">
|
|
||||||
<property name="format" value="^[a-z][a-z0-9][a-zA-Z0-9]*$"/>
|
|
||||||
<message key="name.invalidPattern"
|
|
||||||
value="Member name ''{0}'' must match pattern ''{1}''."/>
|
|
||||||
</module>
|
|
||||||
<!-- <module name="MethodCount"/> -->
|
|
||||||
<module name="MethodLength">
|
|
||||||
<property name="max" value="40"/>
|
|
||||||
</module>
|
|
||||||
<module name="MethodName">
|
|
||||||
<property name="format" value="^[a-z][a-z0-9][a-zA-Z0-9_]*$"/>
|
|
||||||
<message key="name.invalidPattern"
|
|
||||||
value="Method name ''{0}'' must match pattern ''{1}''."/>
|
|
||||||
</module>
|
|
||||||
<module name="MethodParamPad"/>
|
|
||||||
<module name="MethodTypeParameterName">
|
|
||||||
<property name="format" value="^[T]([A-Z][a-zA-Z0-9]*)?$"/>
|
|
||||||
<message key="name.invalidPattern"
|
|
||||||
value="Method type name ''{0}'' must match pattern ''{1}''."/>
|
|
||||||
</module>
|
|
||||||
<!-- <module name="MissingCtor"/> -->
|
|
||||||
<!-- <module name="MissingDeprecated"/> -->
|
|
||||||
<module name="MissingOverride"/>
|
|
||||||
<module name="MissingSwitchDefault"/>
|
|
||||||
<!-- <module name="ModifiedControlVariable"/> -->
|
|
||||||
<module name="ModifierOrder"/>
|
|
||||||
<!-- <module name="MultipleStringLiterals"/> -->
|
|
||||||
<module name="MultipleVariableDeclarations"/>
|
|
||||||
<module name="MutableException"/>
|
|
||||||
<module name="NeedBraces"/>
|
|
||||||
<!-- <module name="NestedForDepth"/> -->
|
|
||||||
<!-- <module name="NestedIfDepth"/> -->
|
|
||||||
<!-- <module name="NestedTryDepth"/> -->
|
|
||||||
<!-- <module name="NewlineAtEndOfFile"/> -->
|
|
||||||
<module name="NoClone"/>
|
|
||||||
<module name="NoFinalizer"/>
|
|
||||||
<module name="NoLineWrap"/>
|
|
||||||
<module name="NonEmptyAtclauseDescription"/>
|
|
||||||
<module name="NoWhitespaceAfter">
|
|
||||||
<property name="allowLineBreaks" value="false"/>
|
|
||||||
<property name="tokens"
|
|
||||||
value="ARRAY_INIT, INC, DEC, UNARY_MINUS, UNARY_PLUS, BNOT, LNOT, DOT, ARRAY_DECLARATOR, INDEX_OP"/>
|
|
||||||
</module>
|
|
||||||
<module name="NoWhitespaceBefore">
|
|
||||||
<property name="tokens" value="COMMA, SEMI, POST_INC, POST_DEC, GENERIC_END"/>
|
|
||||||
</module>
|
|
||||||
<!-- <module name="NPathComplexity"/> -->
|
|
||||||
<module name="OneStatementPerLine"/>
|
|
||||||
<module name="OneTopLevelClass"/>
|
|
||||||
<module name="OperatorWrap">
|
|
||||||
<property name="option" value="NL"/>
|
|
||||||
<property name="tokens"
|
|
||||||
value="BAND, BOR, BSR, BXOR, DIV, EQUAL, GE, GT, LAND, LE, LITERAL_INSTANCEOF, LOR, LT, MINUS, MOD, NOT_EQUAL, PLUS, QUESTION, SL, SR, STAR "/>
|
|
||||||
</module>
|
|
||||||
<module name="OuterTypeFilename"/>
|
|
||||||
<!-- <module name="OuterTypeNumber"/> -->
|
|
||||||
<module name="OverloadMethodsDeclarationOrder"/>
|
|
||||||
<!-- <module name="PackageAnnotation"/> -->
|
|
||||||
<!-- <module name="PackageDeclaration"/> -->
|
|
||||||
<module name="PackageName">
|
|
||||||
<property name="format" value="^[a-z]+(\.[a-z][a-z0-9]*)*$"/>
|
|
||||||
<message key="name.invalidPattern"
|
|
||||||
value="Package name ''{0}'' must match pattern ''{1}''."/>
|
|
||||||
</module>
|
|
||||||
<module name="ParameterAssignment"/>
|
|
||||||
<module name="ParameterName">
|
|
||||||
<property name="format" value="^[a-z][a-z0-9][a-zA-Z0-9]*$"/>
|
|
||||||
<message key="name.invalidPattern"
|
|
||||||
value="Parameter name ''{0}'' must match pattern ''{1}''."/>
|
|
||||||
</module>
|
|
||||||
<!-- <module name="ParameterNumber"/> -->
|
|
||||||
<!-- <module name="ParenPad"/> -->
|
|
||||||
<module name="RedundantImport"/>
|
|
||||||
<!-- <module name="RedundantModifier"/> -->
|
|
||||||
<!-- <module name="Regexp"/> -->
|
|
||||||
<!-- <module name="RegexpHeader"/> -->
|
|
||||||
<!-- <module name="RegexpMultiline"/> -->
|
|
||||||
<!-- <module name="RegexpOnFilename"/> -->
|
|
||||||
<!-- <module name="RegexpSingleline"/> -->
|
|
||||||
<!-- <module name="RegexpSinglelineJava"/> -->
|
|
||||||
<!-- <module name="ReturnCount"/> -->
|
|
||||||
<module name="RequireThis">
|
|
||||||
<property name="checkMethods" value="false"/>
|
|
||||||
</module>
|
|
||||||
<module name="RightCurly"/>
|
|
||||||
<module name="RightCurly">
|
|
||||||
<property name="option" value="alone"/>
|
|
||||||
<property name="tokens" value="CLASS_DEF, METHOD_DEF, CTOR_DEF, LITERAL_FOR, LITERAL_WHILE, LITERAL_DO, STATIC_INIT, INSTANCE_INIT"/>
|
|
||||||
</module>
|
|
||||||
<module name="SeparatorWrap">
|
|
||||||
<property name="tokens" value="DOT"/>
|
|
||||||
<property name="option" value="nl"/>
|
|
||||||
</module>
|
|
||||||
<module name="SeparatorWrap">
|
|
||||||
<property name="tokens" value="COMMA"/>
|
|
||||||
<property name="option" value="EOL"/>
|
|
||||||
</module>
|
|
||||||
<module name="SimplifyBooleanExpression"/>
|
|
||||||
<module name="SimplifyBooleanReturn"/>
|
|
||||||
<module name="SingleLineJavadoc"/>
|
|
||||||
<module name="SingleSpaceSeparator"/>
|
|
||||||
<module name="StaticVariableName">
|
|
||||||
<property name="format" value="^[a-z][a-z0-9][a-zA-Z0-9]*$"/>
|
|
||||||
<message key="name.invalidPattern"
|
|
||||||
value="Static variable name ''{0}'' must match pattern ''{1}''."/>
|
|
||||||
</module>
|
|
||||||
<module name="StringLiteralEquality"/>
|
|
||||||
<module name="SummaryJavadoc">
|
|
||||||
<property name="forbiddenSummaryFragments" value="^@return the *|^This method returns |^A [{]@code [a-zA-Z0-9]+[}]( is a )"/>
|
|
||||||
</module>
|
|
||||||
<!-- <module name="SuperClone"/> -->
|
|
||||||
<!-- <module name="SuperFinalize"/> -->
|
|
||||||
<!-- <module name="SuppressWarnings"/> -->
|
|
||||||
<module name="SuppressWarningsHolder"/>
|
|
||||||
<!-- <module name="ThrowsCount"/> -->
|
|
||||||
<!-- <module name="TodoComment"/> -->
|
|
||||||
<!-- <module name="TrailingComment"/> -->
|
|
||||||
<!-- <module name="Translation"/> -->
|
|
||||||
<!-- <module name="TypecastParenPad"/> -->
|
|
||||||
<module name="TypeName">
|
|
||||||
<message key="name.invalidPattern"
|
|
||||||
value="Type name ''{0}'' must match pattern ''{1}''."/>
|
|
||||||
</module>
|
|
||||||
<!-- <module name="UncommentedMain"/> -->
|
|
||||||
<!-- <module name="UniqueProperties"/> -->
|
|
||||||
<module name="UnnecessaryParentheses">
|
|
||||||
<property name="tokens"
|
|
||||||
value=" EXPR, IDENT, NUM_DOUBLE, NUM_FLOAT, NUM_INT, NUM_LONG, STRING_LITERAL, LITERAL_NULL, LITERAL_FALSE, LITERAL_TRUE, ASSIGN, BAND_ASSIGN, BOR_ASSIGN, BSR_ASSIGN, BXOR_ASSIGN, DIV_ASSIGN, MINUS_ASSIGN, MOD_ASSIGN, PLUS_ASSIGN, SL_ASSIGN, SR_ASSIGN, STAR_ASSIGN"/>
|
|
||||||
</module>
|
|
||||||
<module name="UnusedImports"/>
|
|
||||||
<module name="UpperEll"/>
|
|
||||||
<module name="VariableDeclarationUsageDistance"/>
|
|
||||||
<!-- <module name="VisibilityModifier"/> -->
|
|
||||||
<!-- <module name="WhitespaceAfter"/> -->
|
|
||||||
<module name="WhitespaceAround">
|
|
||||||
<property name="allowEmptyConstructors" value="true"/>
|
|
||||||
<property name="allowEmptyMethods" value="true"/>
|
|
||||||
<property name="allowEmptyTypes" value="true"/>
|
|
||||||
<property name="allowEmptyLoops" value="true"/>
|
|
||||||
<message key="ws.notFollowed"
|
|
||||||
value="WhitespaceAround: ''{0}'' is not followed by whitespace. Empty blocks may only be represented as '{}' when not part of a multi-block statement (4.1.3)"/>
|
|
||||||
<message key="ws.notPreceded"
|
|
||||||
value="WhitespaceAround: ''{0}'' is not preceded with whitespace."/>
|
|
||||||
</module>
|
|
||||||
<!-- <module name="WriteTag"/> -->
|
|
||||||
</module>
|
|
||||||
|
|
||||||
<module name="SuppressWarningsFilter"/>
|
|
||||||
|
|
||||||
|
|
||||||
</module>
|
|
||||||
|
|
@ -1,8 +0,0 @@
|
||||||
<application>
|
|
||||||
<component name="CodeStyleSettingsManager">
|
|
||||||
<option name="PER_PROJECT_SETTINGS">
|
|
||||||
<value />
|
|
||||||
</option>
|
|
||||||
<option name="PREFERRED_PROJECT_CODE_STYLE" value="TouchInstinct" />
|
|
||||||
</component>
|
|
||||||
</application>
|
|
||||||
|
|
@ -1,5 +0,0 @@
|
||||||
<application>
|
|
||||||
<component name="CodeStyleSchemeSettings">
|
|
||||||
<option name="CURRENT_SCHEME_NAME" value="TouchInstinct" />
|
|
||||||
</component>
|
|
||||||
</application>
|
|
||||||
|
|
@ -0,0 +1,249 @@
|
||||||
|
<component name="ProjectCodeStyleConfiguration">
|
||||||
|
<code_scheme name="Project" version="173">
|
||||||
|
<option name="RIGHT_MARGIN" value="120" />
|
||||||
|
<option name="SOFT_MARGINS" value="100" />
|
||||||
|
<AndroidXmlCodeStyleSettings>
|
||||||
|
<option name="LAYOUT_SETTINGS">
|
||||||
|
<value>
|
||||||
|
<option name="INSERT_LINE_BREAK_BEFORE_NAMESPACE_DECLARATION" value="true" />
|
||||||
|
</value>
|
||||||
|
</option>
|
||||||
|
<option name="MANIFEST_SETTINGS">
|
||||||
|
<value>
|
||||||
|
<option name="INSERT_LINE_BREAK_BEFORE_NAMESPACE_DECLARATION" value="true" />
|
||||||
|
</value>
|
||||||
|
</option>
|
||||||
|
<option name="OTHER_SETTINGS">
|
||||||
|
<value>
|
||||||
|
<option name="INSERT_LINE_BREAK_BEFORE_NAMESPACE_DECLARATION" value="true" />
|
||||||
|
</value>
|
||||||
|
</option>
|
||||||
|
</AndroidXmlCodeStyleSettings>
|
||||||
|
<JavaCodeStyleSettings>
|
||||||
|
<option name="GENERATE_FINAL_LOCALS" value="true" />
|
||||||
|
<option name="GENERATE_FINAL_PARAMETERS" value="true" />
|
||||||
|
<option name="DO_NOT_WRAP_AFTER_SINGLE_ANNOTATION" value="true" />
|
||||||
|
<option name="ANNOTATION_PARAMETER_WRAP" value="1" />
|
||||||
|
<option name="ALIGN_MULTILINE_ANNOTATION_PARAMETERS" value="true" />
|
||||||
|
<option name="IMPORT_LAYOUT_TABLE">
|
||||||
|
<value>
|
||||||
|
<package name="android" static="false" withSubpackages="true" />
|
||||||
|
<emptyLine />
|
||||||
|
<package name="com" static="false" withSubpackages="true" />
|
||||||
|
<emptyLine />
|
||||||
|
<package name="junit" static="false" withSubpackages="true" />
|
||||||
|
<emptyLine />
|
||||||
|
<package name="net" static="false" withSubpackages="true" />
|
||||||
|
<emptyLine />
|
||||||
|
<package name="org" static="false" withSubpackages="true" />
|
||||||
|
<emptyLine />
|
||||||
|
<package name="java" static="false" withSubpackages="true" />
|
||||||
|
<emptyLine />
|
||||||
|
<package name="javax" static="false" withSubpackages="true" />
|
||||||
|
<emptyLine />
|
||||||
|
<package name="" static="false" withSubpackages="true" />
|
||||||
|
<emptyLine />
|
||||||
|
<package name="" static="true" withSubpackages="true" />
|
||||||
|
<emptyLine />
|
||||||
|
</value>
|
||||||
|
</option>
|
||||||
|
<option name="JD_P_AT_EMPTY_LINES" value="false" />
|
||||||
|
</JavaCodeStyleSettings>
|
||||||
|
<JetCodeStyleSettings>
|
||||||
|
<option name="PACKAGES_TO_USE_STAR_IMPORTS">
|
||||||
|
<value />
|
||||||
|
</option>
|
||||||
|
<option name="PACKAGES_IMPORT_LAYOUT">
|
||||||
|
<value>
|
||||||
|
<package name="" alias="false" withSubpackages="true" />
|
||||||
|
<package name="" alias="true" withSubpackages="true" />
|
||||||
|
</value>
|
||||||
|
</option>
|
||||||
|
<option name="NAME_COUNT_TO_USE_STAR_IMPORT" value="2147483647" />
|
||||||
|
<option name="NAME_COUNT_TO_USE_STAR_IMPORT_FOR_MEMBERS" value="2147483647" />
|
||||||
|
<option name="CONTINUATION_INDENT_IN_PARAMETER_LISTS" value="true" />
|
||||||
|
<option name="CONTINUATION_INDENT_IN_ARGUMENT_LISTS" value="true" />
|
||||||
|
<option name="CONTINUATION_INDENT_FOR_EXPRESSION_BODIES" value="true" />
|
||||||
|
<option name="CONTINUATION_INDENT_FOR_CHAINED_CALLS" value="true" />
|
||||||
|
<option name="CONTINUATION_INDENT_IN_ELVIS" value="true" />
|
||||||
|
<option name="ALLOW_TRAILING_COMMA" value="true" />
|
||||||
|
<option name="CODE_STYLE_DEFAULTS" value="KOTLIN_OFFICIAL" />
|
||||||
|
</JetCodeStyleSettings>
|
||||||
|
<Objective-C-extensions>
|
||||||
|
<file>
|
||||||
|
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Import" />
|
||||||
|
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Macro" />
|
||||||
|
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Typedef" />
|
||||||
|
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Enum" />
|
||||||
|
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Constant" />
|
||||||
|
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Global" />
|
||||||
|
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Struct" />
|
||||||
|
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="FunctionPredecl" />
|
||||||
|
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Function" />
|
||||||
|
</file>
|
||||||
|
<class>
|
||||||
|
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Property" />
|
||||||
|
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Synthesize" />
|
||||||
|
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="InitMethod" />
|
||||||
|
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="StaticMethod" />
|
||||||
|
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="InstanceMethod" />
|
||||||
|
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="DeallocMethod" />
|
||||||
|
</class>
|
||||||
|
<extensions>
|
||||||
|
<pair header="h" source="cpp" />
|
||||||
|
<pair header="h" source="c" />
|
||||||
|
</extensions>
|
||||||
|
</Objective-C-extensions>
|
||||||
|
<XML>
|
||||||
|
<option name="XML_KEEP_BLANK_LINES" value="1" />
|
||||||
|
</XML>
|
||||||
|
<codeStyleSettings language="JAVA">
|
||||||
|
<option name="ALIGN_MULTILINE_ARRAY_INITIALIZER_EXPRESSION" value="true" />
|
||||||
|
<option name="CALL_PARAMETERS_WRAP" value="1" />
|
||||||
|
<option name="METHOD_PARAMETERS_WRAP" value="1" />
|
||||||
|
<option name="RESOURCE_LIST_WRAP" value="1" />
|
||||||
|
<option name="EXTENDS_LIST_WRAP" value="1" />
|
||||||
|
<option name="THROWS_LIST_WRAP" value="1" />
|
||||||
|
<option name="EXTENDS_KEYWORD_WRAP" value="1" />
|
||||||
|
<option name="THROWS_KEYWORD_WRAP" value="1" />
|
||||||
|
<option name="METHOD_CALL_CHAIN_WRAP" value="1" />
|
||||||
|
<option name="BINARY_OPERATION_WRAP" value="1" />
|
||||||
|
<option name="BINARY_OPERATION_SIGN_ON_NEXT_LINE" value="true" />
|
||||||
|
<option name="TERNARY_OPERATION_WRAP" value="1" />
|
||||||
|
<option name="TERNARY_OPERATION_SIGNS_ON_NEXT_LINE" value="true" />
|
||||||
|
<option name="FOR_STATEMENT_WRAP" value="1" />
|
||||||
|
<option name="ARRAY_INITIALIZER_WRAP" value="1" />
|
||||||
|
<option name="ASSIGNMENT_WRAP" value="1" />
|
||||||
|
<option name="PLACE_ASSIGNMENT_SIGN_ON_NEXT_LINE" value="true" />
|
||||||
|
<option name="IF_BRACE_FORCE" value="3" />
|
||||||
|
<option name="DOWHILE_BRACE_FORCE" value="3" />
|
||||||
|
<option name="WHILE_BRACE_FORCE" value="3" />
|
||||||
|
<option name="FOR_BRACE_FORCE" value="3" />
|
||||||
|
<option name="WRAP_LONG_LINES" value="true" />
|
||||||
|
<option name="PARAMETER_ANNOTATION_WRAP" value="1" />
|
||||||
|
<option name="VARIABLE_ANNOTATION_WRAP" value="1" />
|
||||||
|
<option name="ENUM_CONSTANTS_WRAP" value="5" />
|
||||||
|
</codeStyleSettings>
|
||||||
|
<codeStyleSettings language="XML">
|
||||||
|
<option name="FORCE_REARRANGE_MODE" value="1" />
|
||||||
|
<indentOptions>
|
||||||
|
<option name="CONTINUATION_INDENT_SIZE" value="4" />
|
||||||
|
</indentOptions>
|
||||||
|
<arrangement>
|
||||||
|
<rules>
|
||||||
|
<section>
|
||||||
|
<rule>
|
||||||
|
<match>
|
||||||
|
<AND>
|
||||||
|
<NAME>xmlns:android</NAME>
|
||||||
|
<XML_ATTRIBUTE />
|
||||||
|
<XML_NAMESPACE>^$</XML_NAMESPACE>
|
||||||
|
</AND>
|
||||||
|
</match>
|
||||||
|
</rule>
|
||||||
|
</section>
|
||||||
|
<section>
|
||||||
|
<rule>
|
||||||
|
<match>
|
||||||
|
<AND>
|
||||||
|
<NAME>xmlns:.*</NAME>
|
||||||
|
<XML_ATTRIBUTE />
|
||||||
|
<XML_NAMESPACE>^$</XML_NAMESPACE>
|
||||||
|
</AND>
|
||||||
|
</match>
|
||||||
|
<order>BY_NAME</order>
|
||||||
|
</rule>
|
||||||
|
</section>
|
||||||
|
<section>
|
||||||
|
<rule>
|
||||||
|
<match>
|
||||||
|
<AND>
|
||||||
|
<NAME>.*:id</NAME>
|
||||||
|
<XML_ATTRIBUTE />
|
||||||
|
<XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE>
|
||||||
|
</AND>
|
||||||
|
</match>
|
||||||
|
</rule>
|
||||||
|
</section>
|
||||||
|
<section>
|
||||||
|
<rule>
|
||||||
|
<match>
|
||||||
|
<AND>
|
||||||
|
<NAME>.*:name</NAME>
|
||||||
|
<XML_ATTRIBUTE />
|
||||||
|
<XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE>
|
||||||
|
</AND>
|
||||||
|
</match>
|
||||||
|
</rule>
|
||||||
|
</section>
|
||||||
|
<section>
|
||||||
|
<rule>
|
||||||
|
<match>
|
||||||
|
<AND>
|
||||||
|
<NAME>name</NAME>
|
||||||
|
<XML_ATTRIBUTE />
|
||||||
|
<XML_NAMESPACE>^$</XML_NAMESPACE>
|
||||||
|
</AND>
|
||||||
|
</match>
|
||||||
|
</rule>
|
||||||
|
</section>
|
||||||
|
<section>
|
||||||
|
<rule>
|
||||||
|
<match>
|
||||||
|
<AND>
|
||||||
|
<NAME>style</NAME>
|
||||||
|
<XML_ATTRIBUTE />
|
||||||
|
<XML_NAMESPACE>^$</XML_NAMESPACE>
|
||||||
|
</AND>
|
||||||
|
</match>
|
||||||
|
</rule>
|
||||||
|
</section>
|
||||||
|
<section>
|
||||||
|
<rule>
|
||||||
|
<match>
|
||||||
|
<AND>
|
||||||
|
<NAME>.*</NAME>
|
||||||
|
<XML_ATTRIBUTE />
|
||||||
|
<XML_NAMESPACE>^$</XML_NAMESPACE>
|
||||||
|
</AND>
|
||||||
|
</match>
|
||||||
|
<order>BY_NAME</order>
|
||||||
|
</rule>
|
||||||
|
</section>
|
||||||
|
<section>
|
||||||
|
<rule>
|
||||||
|
<match>
|
||||||
|
<AND>
|
||||||
|
<NAME>.*</NAME>
|
||||||
|
<XML_ATTRIBUTE />
|
||||||
|
<XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE>
|
||||||
|
</AND>
|
||||||
|
</match>
|
||||||
|
<order>ANDROID_ATTRIBUTE_ORDER</order>
|
||||||
|
</rule>
|
||||||
|
</section>
|
||||||
|
<section>
|
||||||
|
<rule>
|
||||||
|
<match>
|
||||||
|
<AND>
|
||||||
|
<NAME>.*</NAME>
|
||||||
|
<XML_ATTRIBUTE />
|
||||||
|
<XML_NAMESPACE>.*</XML_NAMESPACE>
|
||||||
|
</AND>
|
||||||
|
</match>
|
||||||
|
<order>BY_NAME</order>
|
||||||
|
</rule>
|
||||||
|
</section>
|
||||||
|
</rules>
|
||||||
|
</arrangement>
|
||||||
|
</codeStyleSettings>
|
||||||
|
<codeStyleSettings language="kotlin">
|
||||||
|
<option name="CODE_STYLE_DEFAULTS" value="KOTLIN_OFFICIAL" />
|
||||||
|
<option name="KEEP_FIRST_COLUMN_COMMENT" value="false" />
|
||||||
|
<option name="KEEP_BLANK_LINES_IN_DECLARATIONS" value="1" />
|
||||||
|
<option name="KEEP_BLANK_LINES_IN_CODE" value="1" />
|
||||||
|
<option name="KEEP_BLANK_LINES_BEFORE_RBRACE" value="0" />
|
||||||
|
<option name="ENUM_CONSTANTS_WRAP" value="5" />
|
||||||
|
</codeStyleSettings>
|
||||||
|
</code_scheme>
|
||||||
|
</component>
|
||||||
|
|
@ -0,0 +1,5 @@
|
||||||
|
<component name="ProjectCodeStyleConfiguration">
|
||||||
|
<state>
|
||||||
|
<option name="USE_PER_PROJECT_SETTINGS" value="true" />
|
||||||
|
</state>
|
||||||
|
</component>
|
||||||
|
|
@ -1,254 +0,0 @@
|
||||||
<code_scheme name="TouchInstinct">
|
|
||||||
<option name="GENERATE_FINAL_LOCALS" value="true" />
|
|
||||||
<option name="GENERATE_FINAL_PARAMETERS" value="true" />
|
|
||||||
<option name="CLASS_COUNT_TO_USE_IMPORT_ON_DEMAND" value="99" />
|
|
||||||
<option name="NAMES_COUNT_TO_USE_IMPORT_ON_DEMAND" value="99" />
|
|
||||||
<option name="PACKAGES_TO_USE_IMPORT_ON_DEMAND">
|
|
||||||
<value />
|
|
||||||
</option>
|
|
||||||
<option name="IMPORT_LAYOUT_TABLE">
|
|
||||||
<value>
|
|
||||||
<package name="android" withSubpackages="true" static="false" />
|
|
||||||
<emptyLine />
|
|
||||||
<package name="com" withSubpackages="true" static="false" />
|
|
||||||
<emptyLine />
|
|
||||||
<package name="junit" withSubpackages="true" static="false" />
|
|
||||||
<emptyLine />
|
|
||||||
<package name="net" withSubpackages="true" static="false" />
|
|
||||||
<emptyLine />
|
|
||||||
<package name="org" withSubpackages="true" static="false" />
|
|
||||||
<emptyLine />
|
|
||||||
<package name="java" withSubpackages="true" static="false" />
|
|
||||||
<emptyLine />
|
|
||||||
<package name="javax" withSubpackages="true" static="false" />
|
|
||||||
<emptyLine />
|
|
||||||
<package name="" withSubpackages="true" static="false" />
|
|
||||||
<emptyLine />
|
|
||||||
<package name="" withSubpackages="true" static="true" />
|
|
||||||
<emptyLine />
|
|
||||||
</value>
|
|
||||||
</option>
|
|
||||||
<option name="RIGHT_MARGIN" value="150" />
|
|
||||||
<option name="JD_P_AT_EMPTY_LINES" value="false" />
|
|
||||||
<AndroidXmlCodeStyleSettings>
|
|
||||||
<option name="USE_CUSTOM_SETTINGS" value="true" />
|
|
||||||
</AndroidXmlCodeStyleSettings>
|
|
||||||
<JavaCodeStyleSettings>
|
|
||||||
<option name="DO_NOT_WRAP_AFTER_SINGLE_ANNOTATION" value="true" />
|
|
||||||
<option name="ANNOTATION_PARAMETER_WRAP" value="1" />
|
|
||||||
<option name="ALIGN_MULTILINE_ANNOTATION_PARAMETERS" value="true" />
|
|
||||||
</JavaCodeStyleSettings>
|
|
||||||
<Objective-C-extensions>
|
|
||||||
<file>
|
|
||||||
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Import" />
|
|
||||||
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Macro" />
|
|
||||||
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Typedef" />
|
|
||||||
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Enum" />
|
|
||||||
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Constant" />
|
|
||||||
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Global" />
|
|
||||||
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Struct" />
|
|
||||||
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="FunctionPredecl" />
|
|
||||||
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Function" />
|
|
||||||
</file>
|
|
||||||
<class>
|
|
||||||
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Property" />
|
|
||||||
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Synthesize" />
|
|
||||||
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="InitMethod" />
|
|
||||||
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="StaticMethod" />
|
|
||||||
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="InstanceMethod" />
|
|
||||||
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="DeallocMethod" />
|
|
||||||
</class>
|
|
||||||
<extensions>
|
|
||||||
<pair source="cpp" header="h" />
|
|
||||||
<pair source="c" header="h" />
|
|
||||||
</extensions>
|
|
||||||
</Objective-C-extensions>
|
|
||||||
<XML>
|
|
||||||
<option name="XML_LEGACY_SETTINGS_IMPORTED" value="true" />
|
|
||||||
</XML>
|
|
||||||
<codeStyleSettings language="JAVA">
|
|
||||||
<option name="RIGHT_MARGIN" value="150" />
|
|
||||||
<option name="ALIGN_MULTILINE_ARRAY_INITIALIZER_EXPRESSION" value="true" />
|
|
||||||
<option name="CALL_PARAMETERS_WRAP" value="1" />
|
|
||||||
<option name="METHOD_PARAMETERS_WRAP" value="1" />
|
|
||||||
<option name="RESOURCE_LIST_WRAP" value="1" />
|
|
||||||
<option name="EXTENDS_LIST_WRAP" value="1" />
|
|
||||||
<option name="THROWS_LIST_WRAP" value="1" />
|
|
||||||
<option name="EXTENDS_KEYWORD_WRAP" value="1" />
|
|
||||||
<option name="THROWS_KEYWORD_WRAP" value="1" />
|
|
||||||
<option name="METHOD_CALL_CHAIN_WRAP" value="1" />
|
|
||||||
<option name="BINARY_OPERATION_WRAP" value="1" />
|
|
||||||
<option name="BINARY_OPERATION_SIGN_ON_NEXT_LINE" value="true" />
|
|
||||||
<option name="TERNARY_OPERATION_WRAP" value="1" />
|
|
||||||
<option name="TERNARY_OPERATION_SIGNS_ON_NEXT_LINE" value="true" />
|
|
||||||
<option name="FOR_STATEMENT_WRAP" value="1" />
|
|
||||||
<option name="ARRAY_INITIALIZER_WRAP" value="1" />
|
|
||||||
<option name="ASSIGNMENT_WRAP" value="1" />
|
|
||||||
<option name="PLACE_ASSIGNMENT_SIGN_ON_NEXT_LINE" value="true" />
|
|
||||||
<option name="IF_BRACE_FORCE" value="3" />
|
|
||||||
<option name="DOWHILE_BRACE_FORCE" value="3" />
|
|
||||||
<option name="WHILE_BRACE_FORCE" value="3" />
|
|
||||||
<option name="FOR_BRACE_FORCE" value="3" />
|
|
||||||
<option name="WRAP_LONG_LINES" value="true" />
|
|
||||||
<option name="PARAMETER_ANNOTATION_WRAP" value="1" />
|
|
||||||
<option name="VARIABLE_ANNOTATION_WRAP" value="1" />
|
|
||||||
<option name="ENUM_CONSTANTS_WRAP" value="2" />
|
|
||||||
</codeStyleSettings>
|
|
||||||
<codeStyleSettings language="XML">
|
|
||||||
<option name="FORCE_REARRANGE_MODE" value="1" />
|
|
||||||
<indentOptions>
|
|
||||||
<option name="CONTINUATION_INDENT_SIZE" value="4" />
|
|
||||||
</indentOptions>
|
|
||||||
<arrangement>
|
|
||||||
<rules>
|
|
||||||
<section>
|
|
||||||
<rule>
|
|
||||||
<match>
|
|
||||||
<AND>
|
|
||||||
<NAME>xmlns:android</NAME>
|
|
||||||
<XML_NAMESPACE>^$</XML_NAMESPACE>
|
|
||||||
</AND>
|
|
||||||
</match>
|
|
||||||
</rule>
|
|
||||||
</section>
|
|
||||||
<section>
|
|
||||||
<rule>
|
|
||||||
<match>
|
|
||||||
<AND>
|
|
||||||
<NAME>xmlns:.*</NAME>
|
|
||||||
<XML_NAMESPACE>^$</XML_NAMESPACE>
|
|
||||||
</AND>
|
|
||||||
</match>
|
|
||||||
<order>BY_NAME</order>
|
|
||||||
</rule>
|
|
||||||
</section>
|
|
||||||
<section>
|
|
||||||
<rule>
|
|
||||||
<match>
|
|
||||||
<AND>
|
|
||||||
<NAME>.*:id</NAME>
|
|
||||||
<XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE>
|
|
||||||
</AND>
|
|
||||||
</match>
|
|
||||||
</rule>
|
|
||||||
</section>
|
|
||||||
<section>
|
|
||||||
<rule>
|
|
||||||
<match>
|
|
||||||
<AND>
|
|
||||||
<NAME>.*:name</NAME>
|
|
||||||
<XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE>
|
|
||||||
</AND>
|
|
||||||
</match>
|
|
||||||
</rule>
|
|
||||||
</section>
|
|
||||||
<section>
|
|
||||||
<rule>
|
|
||||||
<match>
|
|
||||||
<AND>
|
|
||||||
<NAME>name</NAME>
|
|
||||||
<XML_NAMESPACE>^$</XML_NAMESPACE>
|
|
||||||
</AND>
|
|
||||||
</match>
|
|
||||||
</rule>
|
|
||||||
</section>
|
|
||||||
<section>
|
|
||||||
<rule>
|
|
||||||
<match>
|
|
||||||
<AND>
|
|
||||||
<NAME>style</NAME>
|
|
||||||
<XML_NAMESPACE>^$</XML_NAMESPACE>
|
|
||||||
</AND>
|
|
||||||
</match>
|
|
||||||
</rule>
|
|
||||||
</section>
|
|
||||||
<section>
|
|
||||||
<rule>
|
|
||||||
<match>
|
|
||||||
<AND>
|
|
||||||
<NAME>.*</NAME>
|
|
||||||
<XML_NAMESPACE>^$</XML_NAMESPACE>
|
|
||||||
</AND>
|
|
||||||
</match>
|
|
||||||
<order>BY_NAME</order>
|
|
||||||
</rule>
|
|
||||||
</section>
|
|
||||||
<section>
|
|
||||||
<rule>
|
|
||||||
<match>
|
|
||||||
<AND>
|
|
||||||
<NAME>.*:layout_width</NAME>
|
|
||||||
<XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE>
|
|
||||||
</AND>
|
|
||||||
</match>
|
|
||||||
</rule>
|
|
||||||
</section>
|
|
||||||
<section>
|
|
||||||
<rule>
|
|
||||||
<match>
|
|
||||||
<AND>
|
|
||||||
<NAME>.*:layout_height</NAME>
|
|
||||||
<XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE>
|
|
||||||
</AND>
|
|
||||||
</match>
|
|
||||||
</rule>
|
|
||||||
</section>
|
|
||||||
<section>
|
|
||||||
<rule>
|
|
||||||
<match>
|
|
||||||
<AND>
|
|
||||||
<NAME>.*:layout_.*</NAME>
|
|
||||||
<XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE>
|
|
||||||
</AND>
|
|
||||||
</match>
|
|
||||||
<order>BY_NAME</order>
|
|
||||||
</rule>
|
|
||||||
</section>
|
|
||||||
<section>
|
|
||||||
<rule>
|
|
||||||
<match>
|
|
||||||
<AND>
|
|
||||||
<NAME>.*:width</NAME>
|
|
||||||
<XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE>
|
|
||||||
</AND>
|
|
||||||
</match>
|
|
||||||
<order>BY_NAME</order>
|
|
||||||
</rule>
|
|
||||||
</section>
|
|
||||||
<section>
|
|
||||||
<rule>
|
|
||||||
<match>
|
|
||||||
<AND>
|
|
||||||
<NAME>.*:height</NAME>
|
|
||||||
<XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE>
|
|
||||||
</AND>
|
|
||||||
</match>
|
|
||||||
<order>BY_NAME</order>
|
|
||||||
</rule>
|
|
||||||
</section>
|
|
||||||
<section>
|
|
||||||
<rule>
|
|
||||||
<match>
|
|
||||||
<AND>
|
|
||||||
<NAME>.*</NAME>
|
|
||||||
<XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE>
|
|
||||||
</AND>
|
|
||||||
</match>
|
|
||||||
<order>BY_NAME</order>
|
|
||||||
</rule>
|
|
||||||
</section>
|
|
||||||
<section>
|
|
||||||
<rule>
|
|
||||||
<match>
|
|
||||||
<AND>
|
|
||||||
<NAME>.*</NAME>
|
|
||||||
<XML_NAMESPACE>.*</XML_NAMESPACE>
|
|
||||||
</AND>
|
|
||||||
</match>
|
|
||||||
<order>BY_NAME</order>
|
|
||||||
</rule>
|
|
||||||
</section>
|
|
||||||
</rules>
|
|
||||||
</arrangement>
|
|
||||||
</codeStyleSettings>
|
|
||||||
</code_scheme>
|
|
||||||
|
|
@ -1,124 +0,0 @@
|
||||||
## Описание генератора JSON моделей
|
|
||||||
|
|
||||||
Генератор JSON моделей - это скрипт, который автоматически создает классы JSON моделей на основе описания их схемы в файле формата YAML.
|
|
||||||
|
|
||||||
Генерируется 2 типа классов:
|
|
||||||
- классы, описывающие enum;
|
|
||||||
- классы, описывающие модели.
|
|
||||||
|
|
||||||
Классы моделей размечаются для работы с библиотекой LoganSquare и наследуется от абстракного класса `ApiModel`, содержащего логику валидации.
|
|
||||||
|
|
||||||
Классы моделей содержат в себе:
|
|
||||||
- конструктор без параметров;
|
|
||||||
- конструктор со всеми возможными параметрами в случае, если модель не наследуется ни от какой другой модели;
|
|
||||||
- приватные поля, описывающие параметры модели;
|
|
||||||
- публичный `getter` и `setter` для каждого поля модели;
|
|
||||||
- метод `validate` для валидации модели;
|
|
||||||
- метод `equals` и `hashCode` на основе всех содержащихся полей;
|
|
||||||
- метод `writeObject` и `readObject` для стандартной сериализации объекта;
|
|
||||||
- метод `copy` для создания копии объекта. Создается только в случае, если модель не наследуется ни от какой другой модели.
|
|
||||||
|
|
||||||
**ВАЖНО!** Копирование через метод `copy` не гарантирует копирование всех объектов, содержащихся во всех полях.
|
|
||||||
|
|
||||||
## Подключение и использование генератора
|
|
||||||
|
|
||||||
Подключаем сабмодуль [BuildScripts](https://github.com/TouchInstinct/BuildScripts) в папку libraries.
|
|
||||||
|
|
||||||
Чтобы подключить скрипт, добавьте в конец файл `build.gradle` модуля следующую строку:
|
|
||||||
```gradle
|
|
||||||
apply from: "${rootDir}/libraries/BuildScripts/gradle/jsonModelsGeneration.gradle"
|
|
||||||
```
|
|
||||||
|
|
||||||
Чтобы зарегистрировать YAML файлы для генерации моделей, в секцию `android` надо добавить:
|
|
||||||
```gradle
|
|
||||||
android {
|
|
||||||
extensions.jsonModelsMapping = ["schemes/api_models.yaml -> ${defaulConfig.applicationId}.logic.api.model",
|
|
||||||
"schemes/internal_models.yaml -> ${defaulConfig.applicationId}.logic.model"]
|
|
||||||
}
|
|
||||||
```
|
|
||||||
- `schemes/api_models.yaml` - путь к файлу схемы. По умолчанию относительно папки модуля, но можно указать и абсолютный путь;
|
|
||||||
- `->` - разделитель;
|
|
||||||
- `${applicationId}.logic.api.model` - package-name моделей, которые будут сгенерированы на основе этого файла.
|
|
||||||
|
|
||||||
## Структура файла YAML
|
|
||||||
|
|
||||||
YAML файл может содержать 3 типа объектов: описание модели, описание enum, импортированные классы.
|
|
||||||
|
|
||||||
### Описание модели
|
|
||||||
Описание начинается с `class MyModel:`, где `MyModel` - это имя класса, который будет сгенерирован.
|
|
||||||
|
|
||||||
Затем для класса идет описание параметров класса:
|
|
||||||
- параметр `typeArguments: TResponse, TData` добавляет к классу указанные аргументы: `class MyModel<TResponse, TData>`;
|
|
||||||
- параметр `extends: BaseResponse<String>` наследует класс от указанного класса: `class MyModel extends BaseResponse<String>`;
|
|
||||||
- параметры, описывающие поля класса, например `name: string` добавляет поле типа `String` с названием `name`.
|
|
||||||
|
|
||||||
### Описание параметра поля класса
|
|
||||||
В простом виде поле добавляется, как `name: string`. То есть, указывается имя поля и его тип.
|
|
||||||
|
|
||||||
Вообще, поле может быть описано следующими параметрами:
|
|
||||||
1. Название параметра - это имя поля;
|
|
||||||
2. `jsonName`, необязательное - имя параметра в разметке JSON, соответсвующее полю. По умолчанию берется ;
|
|
||||||
3. `type`, обязательное - тип поля. Разрешенные типы:
|
|
||||||
- строки `string`, `String`;
|
|
||||||
- целые числа `int`, `Integer`, `long`, `Long`;
|
|
||||||
- дробные числа `float`, `Float`, `double`, `Double`;
|
|
||||||
- буленовские значения `boolean`, `Boolean`;
|
|
||||||
- дата/время `date`, `datetime`, `DateTime`;
|
|
||||||
- списки `List<*>`;
|
|
||||||
- мапы `Map<String, *>;
|
|
||||||
- описанные в этом же файле enum'ы;
|
|
||||||
- описанные в этом же файле импортированные классы;
|
|
||||||
4. `flags`, необязательное - флаги для валидации объекта. Перечисляются через запятую, могут быть:
|
|
||||||
- `nullable` - в поле может прийти null. По умолчанию все поля считаются `non-null`;
|
|
||||||
- `missable` - JSON может не содержать такого поля. По умолчанию все поля считаются `non-missable`;
|
|
||||||
- `solid` - если поле содержит коллекцию, то все элементы в ней обязаны быть валидными. По умолчанию не валидные элементы исключаются из коллекции на этапе валидации;
|
|
||||||
- `non-empty` - если поле содержит коллекцию, то она не должна быть пустой. По умолчанию пустые коллекции разрешены.
|
|
||||||
|
|
||||||
### Пример описания моделей:
|
|
||||||
```yaml
|
|
||||||
class SimpleModel:
|
|
||||||
name: string
|
|
||||||
age: int
|
|
||||||
birthDate: date
|
|
||||||
|
|
||||||
class ComplexModel:
|
|
||||||
id:
|
|
||||||
type: long
|
|
||||||
jsonName: object_id
|
|
||||||
usersList:
|
|
||||||
type: List<SimpleModel>
|
|
||||||
flags: solid, non-empty
|
|
||||||
hasSomeInfo:
|
|
||||||
type: boolean
|
|
||||||
jsonName: has_info
|
|
||||||
flags: nullable
|
|
||||||
```
|
|
||||||
|
|
||||||
### Описание enum'a
|
|
||||||
Описание начинается с `enum MyEnum:`, где `MyEnum` - это имя enum'a, который будет сгенерирован.
|
|
||||||
|
|
||||||
Затем идет перечисление всех возможных значений в формате `VALUE: json_value`, где `VALUE` - имя значения в enum'e, а `json_value` - соответствующая этому значению строка в JSON.
|
|
||||||
|
|
||||||
Пример:
|
|
||||||
```yaml
|
|
||||||
enum SimpleEnum:
|
|
||||||
MALE: male_gender
|
|
||||||
FEMALE: female_gender
|
|
||||||
```
|
|
||||||
|
|
||||||
### Описание импортированных классов
|
|
||||||
Импортированные классы добавляются списком в разделе `imports`. Все классы должны быть указаны полным именем.
|
|
||||||
|
|
||||||
Пример:
|
|
||||||
```yaml
|
|
||||||
imports:
|
|
||||||
- android.util.Pair
|
|
||||||
- com.myproject.model.UserExtension
|
|
||||||
|
|
||||||
class MyModel:
|
|
||||||
pair: Pair
|
|
||||||
users: List<UserExtension>
|
|
||||||
```
|
|
||||||
Импортированные классы нужно использовать в двух случаях:
|
|
||||||
1. Для них заргеистрированы конвертеры в LoganSquare;
|
|
||||||
2. Это расширенные или кастомные модели, описанные для LoganSquare вручную.
|
|
||||||
|
|
@ -1,23 +0,0 @@
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<FindBugsFilter>
|
|
||||||
<Match>
|
|
||||||
<!-- ignore all issues in resource generation -->
|
|
||||||
<Class name="~.*\.R\$.*"/>
|
|
||||||
</Match>
|
|
||||||
<Match>
|
|
||||||
<Class name="~.*\.Manifest\$.*"/>
|
|
||||||
</Match>
|
|
||||||
<Match>
|
|
||||||
<!-- ignore concrete check groups -->
|
|
||||||
<Bug code="DP"/>
|
|
||||||
</Match>
|
|
||||||
<Match>
|
|
||||||
<!-- ignore concrete checks -->
|
|
||||||
<Bug pattern="BC_UNCONFIRMED_CAST_OF_RETURN_VALUE, NP_UNWRITTEN_FIELD, UWF_NULL_FIELD, UWF_FIELD_NOT_INITIALIZED_IN_CONSTRUCTOR, PZLA_PREFER_ZERO_LENGTH_ARRAYS, EI_EXPOSE_REP, EI_EXPOSE_REP2, REC_CATCH_EXCEPTION, EQ_COMPARETO_USE_OBJECT_EQUALS, BC_UNCONFIRMED_CAST, EQ_DOESNT_OVERRIDE_EQUALS, BC_IMPOSSIBLE_CAST" />
|
|
||||||
</Match>
|
|
||||||
<Match>
|
|
||||||
<Bug code="UPM" />
|
|
||||||
<Class name="~.*\$\$Lambda\$.*"/>
|
|
||||||
</Match>
|
|
||||||
|
|
||||||
</FindBugsFilter>
|
|
||||||
|
|
@ -1,442 +0,0 @@
|
||||||
apply plugin: 'checkstyle'
|
|
||||||
apply plugin: 'pmd'
|
|
||||||
apply plugin: 'cpd'
|
|
||||||
|
|
||||||
def getCpdTask
|
|
||||||
def getPmdTask
|
|
||||||
def getCheckstyleTask
|
|
||||||
def getLintTasks
|
|
||||||
def getKotlinDetektTask
|
|
||||||
|
|
||||||
def appendError
|
|
||||||
def appendCpdErrors
|
|
||||||
def appendKotlinErrors
|
|
||||||
def appendCheckstyleErrors
|
|
||||||
def appendPmdErrors
|
|
||||||
def appendLintErrors
|
|
||||||
|
|
||||||
def normalizeFileUrl
|
|
||||||
|
|
||||||
repositories {
|
|
||||||
maven { url "http://dl.bintray.com/touchin/touchin-tools" }
|
|
||||||
}
|
|
||||||
|
|
||||||
configurations {
|
|
||||||
pngtastic
|
|
||||||
detekt
|
|
||||||
}
|
|
||||||
|
|
||||||
cpd {
|
|
||||||
skipLexicalErrors = true
|
|
||||||
}
|
|
||||||
|
|
||||||
import org.apache.tools.ant.taskdefs.condition.Os
|
|
||||||
|
|
||||||
ext.getIdeaFormatTask = { isAndroidProject, sources ->
|
|
||||||
def ideaPath = System.getenv("IDEA_HOME")
|
|
||||||
if (ideaPath == null) {
|
|
||||||
return tasks.create((isAndroidProject ? "android" : "server") + "do nothing")
|
|
||||||
}
|
|
||||||
return tasks.create((isAndroidProject ? "android" : "server") + "IdeaFormat_$project.name", Exec) {
|
|
||||||
def inspectionPath
|
|
||||||
def params = ["-r", "-mask", "*.java,*.kt,*.xml"]
|
|
||||||
for (String source : sources) {
|
|
||||||
params.add(source)
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Os.isFamily(Os.FAMILY_WINDOWS)) {
|
|
||||||
inspectionPath = ['cmd', '/c', "${ideaPath}\\bin\\format.bat ${params.join(" ")}"]
|
|
||||||
} else {
|
|
||||||
inspectionPath = ["$ideaPath/bin/format.sh"]
|
|
||||||
}
|
|
||||||
commandLine inspectionPath
|
|
||||||
if (!Os.isFamily(Os.FAMILY_WINDOWS)) {
|
|
||||||
args = params
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ext.getStaticAnalysisTaskNames = { isAndroidProject, sources ->
|
|
||||||
def tasksNames = new ArrayList<String>()
|
|
||||||
try {
|
|
||||||
tasksNames.add(getCpdTask(isAndroidProject, sources))
|
|
||||||
tasksNames.add(getKotlinDetektTask(isAndroidProject))
|
|
||||||
if (isAndroidProject) {
|
|
||||||
tasksNames.add(getCheckstyleTask(sources))
|
|
||||||
tasksNames.add(getPmdTask(sources))
|
|
||||||
tasksNames.addAll(getLintTasks())
|
|
||||||
}
|
|
||||||
} catch (Exception exception) {
|
|
||||||
println(exception.toString())
|
|
||||||
}
|
|
||||||
return tasksNames
|
|
||||||
}
|
|
||||||
|
|
||||||
ext.generateHtmlReport = { isAndroidProject ->
|
|
||||||
StringBuilder fullReport = new StringBuilder()
|
|
||||||
|
|
||||||
fullReport.append("<table cellpadding='10px' border='2px' cellspacing='0px' cols='4'>");
|
|
||||||
|
|
||||||
StringBuilder consoleReport = new StringBuilder()
|
|
||||||
consoleReport.append("STATIC ANALYSIS RESULTS:")
|
|
||||||
def count = 0
|
|
||||||
|
|
||||||
def previousCount = count
|
|
||||||
count = appendCpdErrors(fullReport, count, new File("${project.buildDir}/reports/cpd.xml"))
|
|
||||||
if (count - previousCount > 0) {
|
|
||||||
consoleReport.append("\n\u001B[31mCPD: FAILED (" + (count - previousCount) + " errors)\u001B[0m " +
|
|
||||||
normalizeFileUrl("file://${project.buildDir}/reports/cpd.xml"))
|
|
||||||
} else {
|
|
||||||
consoleReport.append("\n\u001B[32mCPD: PASSED\u001B[0m")
|
|
||||||
}
|
|
||||||
|
|
||||||
previousCount = count
|
|
||||||
count = appendKotlinErrors(fullReport, count, new File("${project.buildDir}/reports/kotlin-detekt.xml"))
|
|
||||||
if (count - previousCount > 0) {
|
|
||||||
consoleReport.append("\n\u001B[31mKotlin-detekt: FAILED (" + (count - previousCount) + " errors)\u001B[0m " +
|
|
||||||
normalizeFileUrl("file://${project.buildDir}/reports/kotlin-detekt.xml"))
|
|
||||||
} else {
|
|
||||||
consoleReport.append("\n\u001B[32mKotlin-detekt: PASSED\u001B[0m")
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isAndroidProject) {
|
|
||||||
previousCount = count
|
|
||||||
count = appendPmdErrors(fullReport, count, new File("${project.buildDir}/reports/pmd.xml"))
|
|
||||||
if (count - previousCount > 0) {
|
|
||||||
consoleReport.append("\n\u001B[31mPMD: FAILED (" + (count - previousCount) + " errors)\u001B[0m " +
|
|
||||||
normalizeFileUrl("file://${project.buildDir}/reports/pmd.html"))
|
|
||||||
} else {
|
|
||||||
consoleReport.append("\n\u001B[32mPMD: PASSED\u001B[0m")
|
|
||||||
}
|
|
||||||
|
|
||||||
previousCount = count
|
|
||||||
count = appendLintErrors(fullReport, count, new File("${project.buildDir}/reports/lint_report.xml"))
|
|
||||||
if (count - previousCount > 0) {
|
|
||||||
consoleReport.append("\n\u001B[31mLint: FAILED (" + (count - previousCount) + " errors)\u001B[0m " +
|
|
||||||
normalizeFileUrl("file://${project.buildDir}/reports/lint.html"))
|
|
||||||
} else {
|
|
||||||
consoleReport.append("\n\u001B[32mLint: PASSED\u001B[0m")
|
|
||||||
}
|
|
||||||
|
|
||||||
previousCount = count
|
|
||||||
count = appendCheckstyleErrors(fullReport, count, new File("${project.buildDir}/reports/checkstyle.xml"))
|
|
||||||
if (count - previousCount > 0) {
|
|
||||||
consoleReport.append("\n\u001B[31mCheckstyle: FAILED (" + (count - previousCount) + " errors)\u001B[0m " +
|
|
||||||
normalizeFileUrl("file://${project.buildDir}/reports/checkstyle.xml"))
|
|
||||||
} else {
|
|
||||||
consoleReport.append("\n\u001B[32mCheckstyle: PASSED\u001B[0m")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fullReport.append("\n</table>\n");
|
|
||||||
fullReport.append("<script>\n" +
|
|
||||||
"\tfunction visitPage(file, line) {\n" +
|
|
||||||
"\t\tfor (port = 63330; port < 63340; port++) {\n" +
|
|
||||||
"\t\t\tvar theUrl='http://127.0.0.1:' + port + '/file?file=' + file + '&line=' + line;\n" +
|
|
||||||
"\t\t\tvar xmlHttp = new XMLHttpRequest();\n" +
|
|
||||||
"\t\t\txmlHttp.open('GET', theUrl, true);\n" +
|
|
||||||
"\t\t\txmlHttp.send(null);\n" +
|
|
||||||
"\t\t}\n" +
|
|
||||||
"\t}\n" +
|
|
||||||
"</script>")
|
|
||||||
|
|
||||||
File fullReportFile = new File("${project.buildDir}/reports/full_report.html")
|
|
||||||
fullReportFile.write(fullReport.toString());
|
|
||||||
|
|
||||||
if (count > 0) {
|
|
||||||
consoleReport.append("\n\u001B[31mOverall: FAILED (" + count + " errors)\u001B[0m "
|
|
||||||
+ normalizeFileUrl("file://${project.buildDir}/reports/full_report.html"))
|
|
||||||
throw new Exception(consoleReport.toString())
|
|
||||||
} else {
|
|
||||||
consoleReport.append("\n\u001B[32mOverall: PASSED\u001B[0m")
|
|
||||||
println(consoleReport.toString())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
normalizeFileUrl = { url ->
|
|
||||||
return url.replace("\\", "/")
|
|
||||||
}
|
|
||||||
|
|
||||||
appendError = { report, number, analyzer, file, line, errorId, errorLink, description ->
|
|
||||||
report.append("\n\t<tr>")
|
|
||||||
|
|
||||||
report.append("\n\t\t<td>" + number + "</td>")
|
|
||||||
|
|
||||||
report.append("\n\t\t<td>" + analyzer + "</td>")
|
|
||||||
|
|
||||||
report.append("\n\t\t<td>")
|
|
||||||
if (analyzer == "Lint") {
|
|
||||||
report.append("\n\t\t\t<a href='javascript:alert(\"" + errorLink.replace("'", "'") + "\")'>" + description + " (" + errorId + ")</a>")
|
|
||||||
} else if (analyzer == "Detekt") {
|
|
||||||
report.append("\n\t\t\t" + description + " (" + errorId + ")")
|
|
||||||
} else {
|
|
||||||
report.append("\n\t\t\t<a target='_blank' href='" + errorLink + "'>" + description + " (" + errorId + ")</a>")
|
|
||||||
}
|
|
||||||
report.append("\n\t\t</td>")
|
|
||||||
|
|
||||||
def indexOfSrc = file.indexOf("src")
|
|
||||||
def deeplink = (indexOfSrc > 0 ? file.substring(indexOfSrc) : file).replace('\\', '/')
|
|
||||||
report.append("\n\t\t<td>")
|
|
||||||
report.append("\n\t\t\t<a href='javascript:visitPage(\"" + deeplink + "\", " + line + ")'>" + file + ":" + line + "</a>")
|
|
||||||
report.append("\n\t\t</td>")
|
|
||||||
|
|
||||||
report.append("\n\t</tr>")
|
|
||||||
println("\n\u001B[31m" + number + " " + analyzer + ": " + description + " (" + errorId + ")\n\tat " + file + ":" + line + "\u001B[0m")
|
|
||||||
}
|
|
||||||
|
|
||||||
appendKotlinErrors = { report, count, checkstyleFile ->
|
|
||||||
def rootNode = new XmlParser().parse(checkstyleFile)
|
|
||||||
for (def fileNode : rootNode.children()) {
|
|
||||||
if (!fileNode.name().equals("file")) {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
for (def errorNode : fileNode.children()) {
|
|
||||||
if (!errorNode.name().equals("error")) {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
count++
|
|
||||||
|
|
||||||
def error = errorNode.attribute("source")
|
|
||||||
appendError(report, count, "Detekt", fileNode.attribute("name"), errorNode.attribute("line"), error, "", errorNode.attribute("message"))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return count
|
|
||||||
}
|
|
||||||
|
|
||||||
appendCpdErrors = { report, count, cpdFile ->
|
|
||||||
def rootNode = new XmlParser().parse(cpdFile)
|
|
||||||
for (def duplicationNode : rootNode.children()) {
|
|
||||||
if (!duplicationNode.name().equals("duplication")) {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
count++
|
|
||||||
|
|
||||||
report.append("\n\t<tr>")
|
|
||||||
|
|
||||||
report.append("\n\t\t<td>" + count + "</td>")
|
|
||||||
|
|
||||||
report.append("\n\t\t<td>CPD</td>")
|
|
||||||
|
|
||||||
def fragment = "<b>Code duplication:</b></br></br>"
|
|
||||||
def links = ""
|
|
||||||
def duplicationIndex = 0
|
|
||||||
String duplicationPoints = ""
|
|
||||||
for (def filePointNode : duplicationNode.children()) {
|
|
||||||
if (filePointNode.name().equals("file")) {
|
|
||||||
def file = filePointNode.attribute("path")
|
|
||||||
def line = filePointNode.attribute("line");
|
|
||||||
def indexOfSrc = file.indexOf("src")
|
|
||||||
def deeplink = (indexOfSrc > 0 ? file.substring(indexOfSrc) : file).replace('\\', '/')
|
|
||||||
if (duplicationIndex > 0) {
|
|
||||||
links += "\n\t\t\t</br></br>"
|
|
||||||
}
|
|
||||||
links += "Code fragment " + (duplicationIndex + 1) + "</br>"
|
|
||||||
links += "\n\t\t\t<a href='javascript:visitPage(\"" + deeplink + "\", " + line + ")'>" + file + ":" + line + "</a>"
|
|
||||||
duplicationPoints += "\n\tat " + file + ":" + line
|
|
||||||
duplicationIndex++
|
|
||||||
} else if (filePointNode.name().equals("codefragment")) {
|
|
||||||
fragment += filePointNode.text().replace("\n", "</br>").replace(" ", " ")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
report.append("\n\t\t<td>" + fragment + "\n\t\t</td>")
|
|
||||||
|
|
||||||
report.append("\n\t\t<td>" + links + "\n\t\t</td>")
|
|
||||||
|
|
||||||
report.append("\n\t</tr>")
|
|
||||||
println("\u001B[31m" + count + " CPD: code duplication" + duplicationPoints + "\u001B[0m")
|
|
||||||
}
|
|
||||||
return count
|
|
||||||
}
|
|
||||||
|
|
||||||
appendCheckstyleErrors = { report, count, checkstyleFile ->
|
|
||||||
def rootNode = new XmlParser().parse(checkstyleFile)
|
|
||||||
for (def fileNode : rootNode.children()) {
|
|
||||||
if (!fileNode.name().equals("file")) {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
for (def errorNode : fileNode.children()) {
|
|
||||||
if (!errorNode.name().equals("error")) {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
count++
|
|
||||||
|
|
||||||
def error = errorNode.attribute("source")
|
|
||||||
def link = "http://checkstyle.sourceforge.net/apidocs/" + error.replace('.', '/') + ".html"
|
|
||||||
appendError(report, count, "Checkstyle", fileNode.attribute("name"), errorNode.attribute("line"), error, link, errorNode.attribute("message"))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return count
|
|
||||||
}
|
|
||||||
|
|
||||||
appendPmdErrors = { report, count, pmdFile ->
|
|
||||||
def rootNode = new XmlParser().parse(pmdFile)
|
|
||||||
for (def fileNode : rootNode.children()) {
|
|
||||||
if (!fileNode.name().equals("file")) {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
for (def errorNode : fileNode.children()) {
|
|
||||||
if (!errorNode.name().equals("violation")) {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
count++
|
|
||||||
|
|
||||||
appendError(report, count, "PMD", fileNode.attribute("name"), errorNode.attribute("beginline"),
|
|
||||||
errorNode.attribute("rule").trim(), errorNode.attribute("externalInfoUrl").trim(), errorNode.text().trim())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return count
|
|
||||||
}
|
|
||||||
|
|
||||||
appendLintErrors = { report, count, lintFile ->
|
|
||||||
def rootNode = new XmlParser().parse(lintFile)
|
|
||||||
for (def issueNode : rootNode.children()) {
|
|
||||||
if (!issueNode.name().equals("issue")
|
|
||||||
|| !issueNode.attribute("severity").equals("Error")) {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
for (def locationNode : issueNode.children()) {
|
|
||||||
if (!locationNode.name().equals("location")) {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
count++
|
|
||||||
appendError(report, count, "Lint", locationNode.attribute("file"), locationNode.attribute("line"),
|
|
||||||
issueNode.attribute("id"), issueNode.attribute("explanation"), issueNode.attribute("message"))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return count
|
|
||||||
}
|
|
||||||
|
|
||||||
getCpdTask = { isAndroidProject, sources ->
|
|
||||||
def taskName = (isAndroidProject ? "android" : "server") + "cpd_${project.name}"
|
|
||||||
tasks.create(taskName, tasks.findByName('cpdCheck').getClass().getSuperclass()) {
|
|
||||||
minimumTokenCount = 60
|
|
||||||
source = files(sources)
|
|
||||||
ignoreFailures = true
|
|
||||||
reports {
|
|
||||||
xml {
|
|
||||||
enabled = true
|
|
||||||
destination = file("${project.buildDir}/reports/cpd.xml")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return taskName
|
|
||||||
}
|
|
||||||
|
|
||||||
getPmdTask = { sources ->
|
|
||||||
def taskName = "pmd_${project.name}"
|
|
||||||
tasks.create(taskName, Pmd) {
|
|
||||||
pmdClasspath = configurations.pmd.asFileTree
|
|
||||||
ruleSetFiles = files("${rootDir}/libraries/BuildScripts/pmd/rulesets/java/android.xml")
|
|
||||||
ruleSets = []
|
|
||||||
source files(sources)
|
|
||||||
ignoreFailures = true
|
|
||||||
reports {
|
|
||||||
html {
|
|
||||||
enabled = true
|
|
||||||
destination file("${project.buildDir}/reports/pmd.html")
|
|
||||||
}
|
|
||||||
xml {
|
|
||||||
enabled = true
|
|
||||||
destination file("${project.buildDir}/reports/pmd.xml")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return taskName
|
|
||||||
}
|
|
||||||
|
|
||||||
getLintTasks = {
|
|
||||||
def lintTaskNames = new ArrayList<String>()
|
|
||||||
|
|
||||||
def lintReleaseTask = tasks.matching {
|
|
||||||
it.getName().contains("lint") && it.getName().contains("Release")
|
|
||||||
}.first()
|
|
||||||
//TODO return on jack lintReleaseTask.dependsOn.clear()
|
|
||||||
lintTaskNames.add(lintReleaseTask.getName())
|
|
||||||
|
|
||||||
def lintDebugTask = tasks.matching {
|
|
||||||
it.getName().contains("lint") && it.getName().contains("Debug")
|
|
||||||
}.first()
|
|
||||||
//TODO return on jack lintDebugTask.dependsOn.clear()
|
|
||||||
lintTaskNames.add(lintDebugTask.getName())
|
|
||||||
|
|
||||||
android.lintOptions.abortOnError = false
|
|
||||||
android.lintOptions.checkAllWarnings = true
|
|
||||||
android.lintOptions.warningsAsErrors = false
|
|
||||||
android.lintOptions.xmlReport = true
|
|
||||||
android.lintOptions.xmlOutput = file("${project.buildDir}/reports/lint_report.xml")
|
|
||||||
android.lintOptions.htmlReport = true
|
|
||||||
android.lintOptions.htmlOutput = file("${project.buildDir}/reports/lint_report.html")
|
|
||||||
android.lintOptions.lintConfig = file("${rootDir}/libraries/BuildScripts/lint/lint.xml")
|
|
||||||
return lintTaskNames
|
|
||||||
}
|
|
||||||
|
|
||||||
getCheckstyleTask = { sources ->
|
|
||||||
def taskName = "checkstyle_${project.name}"
|
|
||||||
def compileReleaseTask = tasks.matching {
|
|
||||||
it.getName().contains("compile") && it.getName().contains("Release") && it.getName().contains("Java") && !it.getName().contains("UnitTest")
|
|
||||||
}.last()
|
|
||||||
tasks.create(taskName, Checkstyle) {
|
|
||||||
ignoreFailures = true
|
|
||||||
showViolations = false
|
|
||||||
source files(sources)
|
|
||||||
configFile file("${rootDir}/libraries/BuildScripts/checkstyle/configuration/touchin_checkstyle.xml")
|
|
||||||
checkstyleClasspath = configurations.checkstyle.asFileTree
|
|
||||||
classpath = files(System.getenv("ANDROID_HOME") + "/platforms/" + android.compileSdkVersion + "/android.jar") +
|
|
||||||
files(System.properties.'java.home' + "/lib/rt.jar") +
|
|
||||||
compileReleaseTask.classpath
|
|
||||||
reports {
|
|
||||||
xml {
|
|
||||||
enabled = true
|
|
||||||
destination file("${project.buildDir}/reports/checkstyle.xml")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return taskName
|
|
||||||
}
|
|
||||||
|
|
||||||
getKotlinDetektTask = { isAndroidProject ->
|
|
||||||
def taskName = (isAndroidProject ? "android" : "server") + "detektCheck_${project.name}"
|
|
||||||
tasks.create(taskName, JavaExec) {
|
|
||||||
main = "io.gitlab.arturbosch.detekt.cli.Main"
|
|
||||||
classpath = configurations.detekt
|
|
||||||
def input = "${rootDir}"
|
|
||||||
def output = "${project.buildDir}/reports/kotlin-detekt.xml"
|
|
||||||
def config = "${rootDir}/libraries/BuildScripts/kotlin/detekt-config.yml"
|
|
||||||
|
|
||||||
// TODO add excludes from rootProject.extensions.findByName("staticAnalysisExcludes")
|
|
||||||
def filters = ".*src/test.*,.*/resources/.*,.*/tmp/.*"
|
|
||||||
def params = ['-i', input, '-o', output, '-c', config, '-f', filters]
|
|
||||||
args(params)
|
|
||||||
}
|
|
||||||
return taskName
|
|
||||||
}
|
|
||||||
|
|
||||||
task optimizePng {
|
|
||||||
doFirst {
|
|
||||||
def jarArgs = new ArrayList<String>()
|
|
||||||
jarArgs.add(configurations.pngtastic.asPath)
|
|
||||||
def relatedPathIndex = "${rootDir}".length() + 1
|
|
||||||
for (def file : fileTree(dir: "${rootDir}", include: '**/src/**/res/drawable**/*.png')) {
|
|
||||||
jarArgs.add(file.absolutePath.substring(relatedPathIndex))
|
|
||||||
}
|
|
||||||
for (def file : fileTree(dir: "${rootDir}", include: '**/src/**/res/mipmap**/*.png')) {
|
|
||||||
jarArgs.add(file.absolutePath.substring(relatedPathIndex))
|
|
||||||
}
|
|
||||||
javaexec { main = "-jar"; args = jarArgs; workingDir = file("${rootDir}") }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
dependencies {
|
|
||||||
pmd 'net.sourceforge.pmd:pmd-core:5.5.3'
|
|
||||||
pmd 'net.sourceforge.pmd:pmd-java:5.5.3'
|
|
||||||
|
|
||||||
checkstyle 'ru.touchin:checkstyle:7.6.2-fork'
|
|
||||||
|
|
||||||
pngtastic 'com.github.depsypher:pngtastic:1.2'
|
|
||||||
|
|
||||||
detekt 'io.gitlab.arturbosch.detekt:detekt-cli:1.0.0.M13.2'
|
|
||||||
detekt 'io.gitlab.arturbosch.detekt:detekt-formatting:1.0.0.M13.2'
|
|
||||||
}
|
|
||||||
File diff suppressed because it is too large
Load Diff
|
|
@ -0,0 +1,20 @@
|
||||||
|
# Generated files
|
||||||
|
bin/
|
||||||
|
gen/
|
||||||
|
|
||||||
|
# Gradle files
|
||||||
|
.gradle/
|
||||||
|
build/
|
||||||
|
/*/build/
|
||||||
|
|
||||||
|
# Local configuration file (sdk path, etc)
|
||||||
|
local.properties
|
||||||
|
|
||||||
|
# Log Files
|
||||||
|
*.log
|
||||||
|
|
||||||
|
.gradle
|
||||||
|
.idea
|
||||||
|
.DS_Store
|
||||||
|
/captures
|
||||||
|
*.iml
|
||||||
|
|
@ -0,0 +1,56 @@
|
||||||
|
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
|
||||||
|
|
||||||
|
plugins {
|
||||||
|
`java-gradle-plugin`
|
||||||
|
`kotlin-dsl`
|
||||||
|
}
|
||||||
|
|
||||||
|
// The kotlin-dsl plugin requires a repository to be declared
|
||||||
|
repositories {
|
||||||
|
mavenCentral()
|
||||||
|
google()
|
||||||
|
}
|
||||||
|
|
||||||
|
dependencies {
|
||||||
|
// android gradle plugin, required by custom plugin
|
||||||
|
implementation("com.android.tools.build:gradle:4.0.1")
|
||||||
|
|
||||||
|
implementation("io.gitlab.arturbosch.detekt:detekt-gradle-plugin:1.10.0")
|
||||||
|
implementation("de.aaschmid:gradle-cpd-plugin:3.1")
|
||||||
|
|
||||||
|
// kotlin plugin, required by custom plugin
|
||||||
|
implementation(kotlin("gradle-plugin", embeddedKotlinVersion))
|
||||||
|
|
||||||
|
gradleKotlinDsl()
|
||||||
|
implementation(kotlin("stdlib-jdk8"))
|
||||||
|
}
|
||||||
|
|
||||||
|
val compileKotlin: KotlinCompile by tasks
|
||||||
|
compileKotlin.kotlinOptions {
|
||||||
|
jvmTarget = "1.8"
|
||||||
|
}
|
||||||
|
|
||||||
|
gradlePlugin {
|
||||||
|
plugins {
|
||||||
|
create("api-generator-android") {
|
||||||
|
id = "api-generator-android"
|
||||||
|
implementationClass = "apigen.ApiGeneratorAndroidPlugin"
|
||||||
|
}
|
||||||
|
create("swagger-generator-android") {
|
||||||
|
id = "swagger-generator-android"
|
||||||
|
implementationClass = "apigen.SwaggerApiGeneratorAndroidPlugin"
|
||||||
|
}
|
||||||
|
create("api-generator-backend") {
|
||||||
|
id = "api-generator-backend"
|
||||||
|
implementationClass = "apigen.ApiGeneratorBackendPlugin"
|
||||||
|
}
|
||||||
|
create("static-analysis-android") {
|
||||||
|
id = "static-analysis-android"
|
||||||
|
implementationClass = "static_analysis.plugins.StaticAnalysisAndroidPlugin"
|
||||||
|
}
|
||||||
|
create("static-analysis-backend") {
|
||||||
|
id = "static-analysis-backend"
|
||||||
|
implementationClass = "static_analysis.plugins.StaticAnalysisBackendPlugin"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,46 @@
|
||||||
|
package apigen
|
||||||
|
|
||||||
|
import com.android.build.gradle.AppExtension
|
||||||
|
import com.android.build.gradle.LibraryExtension
|
||||||
|
import org.gradle.api.Project
|
||||||
|
import org.gradle.api.tasks.compile.JavaCompile
|
||||||
|
import org.gradle.kotlin.dsl.findByType
|
||||||
|
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
|
||||||
|
|
||||||
|
class ApiGeneratorAndroidPlugin : ApiGeneratorPlugin() {
|
||||||
|
|
||||||
|
override fun apply(target: Project) {
|
||||||
|
super.apply(target)
|
||||||
|
|
||||||
|
with(target) {
|
||||||
|
val extension = getExtension()
|
||||||
|
val outputDir = getDirectoryForGeneration()
|
||||||
|
|
||||||
|
extension.outputDirPath = outputDir.path
|
||||||
|
extension.recreateOutputDir = true
|
||||||
|
|
||||||
|
afterEvaluate {
|
||||||
|
extensions.findByType<LibraryExtension>()?.apply {
|
||||||
|
sourceSets.getByName("main")
|
||||||
|
.java
|
||||||
|
.srcDir(outputDir)
|
||||||
|
}
|
||||||
|
extensions.findByType<AppExtension>()?.apply {
|
||||||
|
sourceSets.getByName("main")
|
||||||
|
.java
|
||||||
|
.srcDir(outputDir)
|
||||||
|
}
|
||||||
|
tasks
|
||||||
|
.filterIsInstance<KotlinCompile>()
|
||||||
|
.forEach { it.source(outputDir) }
|
||||||
|
|
||||||
|
tasks
|
||||||
|
.filterIsInstance<JavaCompile>()
|
||||||
|
.forEach { it.source(outputDir) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun Project.getDirectoryForGeneration() = file("$buildDir/generated/api")
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,17 @@
|
||||||
|
package apigen
|
||||||
|
|
||||||
|
import org.gradle.api.Project
|
||||||
|
|
||||||
|
class ApiGeneratorBackendPlugin : ApiGeneratorPlugin() {
|
||||||
|
|
||||||
|
override fun apply(target: Project) {
|
||||||
|
super.apply(target)
|
||||||
|
|
||||||
|
val extension = target.getExtension()
|
||||||
|
|
||||||
|
extension.outputDirPath = target.file("src/main/kotlin").path
|
||||||
|
extension.recreateOutputDir = false
|
||||||
|
extension.outputLanguage = OutputLanguage.KotlinServer
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,22 @@
|
||||||
|
package apigen
|
||||||
|
|
||||||
|
open class ApiGeneratorExtension(
|
||||||
|
var pathToApiSchemes: String? = null,
|
||||||
|
var outputPackageName: String = "",
|
||||||
|
var outputDirPath: String = "",
|
||||||
|
var recreateOutputDir: Boolean = false,
|
||||||
|
var outputLanguage: OutputLanguage? = null
|
||||||
|
)
|
||||||
|
|
||||||
|
sealed class OutputLanguage(val argName: String, val methodOutputType: MethodOutputType? = null) {
|
||||||
|
object KotlinServer : OutputLanguage("KOTLIN_SERVER")
|
||||||
|
class KotlinAndroid(methodOutputType: MethodOutputType = MethodOutputType.Rx) : OutputLanguage("KOTLIN", methodOutputType)
|
||||||
|
object Java : OutputLanguage("JAVA")
|
||||||
|
object Swift : OutputLanguage("SWIFT")
|
||||||
|
}
|
||||||
|
|
||||||
|
sealed class MethodOutputType(val argName: String) {
|
||||||
|
object Rx : MethodOutputType("REACTIVE")
|
||||||
|
object RetrofitCall : MethodOutputType("CALL")
|
||||||
|
object Coroutine : MethodOutputType("COROUTINE")
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,76 @@
|
||||||
|
package apigen
|
||||||
|
|
||||||
|
import org.gradle.api.Plugin
|
||||||
|
import org.gradle.api.Project
|
||||||
|
import org.gradle.api.Task
|
||||||
|
import org.gradle.kotlin.dsl.create
|
||||||
|
import org.gradle.kotlin.dsl.dependencies
|
||||||
|
import org.gradle.kotlin.dsl.repositories
|
||||||
|
|
||||||
|
abstract class ApiGeneratorPlugin : Plugin<Project> {
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
const val API_GENERATOR_CONFIG = "apiGenerator"
|
||||||
|
const val API_GENERATOR_EXT_NAME = "apiGenerator"
|
||||||
|
const val API_GENERATOR_DEFAULT_VERSION = "1.4.0-beta10"
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun apply(target: Project) {
|
||||||
|
with(target) {
|
||||||
|
repositories {
|
||||||
|
maven {
|
||||||
|
url = uri("https://maven.dev.touchin.ru")
|
||||||
|
metadataSources {
|
||||||
|
artifact()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
configurations.create(API_GENERATOR_CONFIG)
|
||||||
|
|
||||||
|
dependencies {
|
||||||
|
add(API_GENERATOR_CONFIG, "ru.touchin:api-generator:$API_GENERATOR_DEFAULT_VERSION")
|
||||||
|
}
|
||||||
|
|
||||||
|
extensions.create<ApiGeneratorExtension>(API_GENERATOR_EXT_NAME)
|
||||||
|
|
||||||
|
val apiGenTask = createApiGeneratorTask()
|
||||||
|
|
||||||
|
gradle.projectsEvaluated {
|
||||||
|
tasks.getByName("preBuild").dependsOn(apiGenTask)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected fun Project.getExtension(): ApiGeneratorExtension = extensions.getByName(API_GENERATOR_EXT_NAME) as ApiGeneratorExtension
|
||||||
|
|
||||||
|
private fun Project.createApiGeneratorTask(): Task = tasks.create(API_GENERATOR_CONFIG).doLast {
|
||||||
|
|
||||||
|
val extension = getExtension()
|
||||||
|
|
||||||
|
val pathToApiSchemes = extension.pathToApiSchemes ?: throw IllegalStateException("Configure path to api schemes for api generator plugin")
|
||||||
|
val outputLanguage = extension.outputLanguage ?: throw IllegalStateException("Configure output language code for api generator plugin")
|
||||||
|
|
||||||
|
javaexec {
|
||||||
|
main = "-jar"
|
||||||
|
workingDir = rootDir
|
||||||
|
args = listOfNotNull(
|
||||||
|
configurations.getByName("apiGenerator").asPath,
|
||||||
|
"generate-client-code",
|
||||||
|
"--output-language",
|
||||||
|
outputLanguage.argName,
|
||||||
|
"--specification-path",
|
||||||
|
pathToApiSchemes,
|
||||||
|
"--kotlin-methods-generation-mode".takeIf { outputLanguage.methodOutputType != null },
|
||||||
|
outputLanguage.methodOutputType?.argName,
|
||||||
|
"--output-path",
|
||||||
|
extension.outputDirPath,
|
||||||
|
"--package-name",
|
||||||
|
extension.outputPackageName,
|
||||||
|
"--recreate_output_dirs",
|
||||||
|
extension.recreateOutputDir.toString()
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,91 @@
|
||||||
|
package apigen
|
||||||
|
|
||||||
|
import org.gradle.api.Action
|
||||||
|
import org.gradle.api.Plugin
|
||||||
|
import org.gradle.api.Project
|
||||||
|
import org.gradle.api.Task
|
||||||
|
import org.gradle.kotlin.dsl.create
|
||||||
|
import org.gradle.kotlin.dsl.dependencies
|
||||||
|
import org.gradle.kotlin.dsl.repositories
|
||||||
|
|
||||||
|
class SwaggerApiGeneratorAndroidPlugin : Plugin<Project> {
|
||||||
|
|
||||||
|
private companion object {
|
||||||
|
const val GENERATOR_CONFIG = "swaggerCodegen"
|
||||||
|
const val GENERATOR_VERSION = "3.0.34"
|
||||||
|
const val TI_GENERATOR_CONFIG = "TIKotlin-swagger-codegen"
|
||||||
|
const val TI_GENERATOR_VERSION = "1.0.0"
|
||||||
|
const val GENERATOR_EXT_NAME = "swaggerApiGenerator"
|
||||||
|
const val MAVEN_URL = "https://maven.dev.touchin.ru"
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun apply(target: Project) {
|
||||||
|
with(target) {
|
||||||
|
repositories {
|
||||||
|
maven {
|
||||||
|
url = uri(MAVEN_URL)
|
||||||
|
metadataSources {
|
||||||
|
artifact()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
configurations.create(GENERATOR_CONFIG)
|
||||||
|
configurations.create(TI_GENERATOR_CONFIG)
|
||||||
|
|
||||||
|
dependencies {
|
||||||
|
add(TI_GENERATOR_CONFIG, "ru.touchin:TIKotlin-swagger-codegen:$TI_GENERATOR_VERSION")
|
||||||
|
add(GENERATOR_CONFIG, "io.swagger.codegen.v3:swagger-codegen-cli:$GENERATOR_VERSION")
|
||||||
|
}
|
||||||
|
|
||||||
|
extensions.create<SwaggerApiGeneratorExtension>(GENERATOR_EXT_NAME)
|
||||||
|
|
||||||
|
val apiGenTask = createSwaggerApiGeneratorTask()
|
||||||
|
|
||||||
|
gradle.projectsEvaluated {
|
||||||
|
tasks.getByName("preBuild").dependsOn(apiGenTask)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected fun Project.getExtension(): SwaggerApiGeneratorExtension = extensions.getByName(GENERATOR_EXT_NAME) as SwaggerApiGeneratorExtension
|
||||||
|
|
||||||
|
private fun Project.createSwaggerApiGeneratorTask(): Task = tasks.create(GENERATOR_CONFIG).doLast {
|
||||||
|
|
||||||
|
val extension = getExtension()
|
||||||
|
|
||||||
|
val taskWorkingDir = extension.taskWorkingDir ?: throw IllegalStateException("Configure taskWorkingDir for swagger generator plugin")
|
||||||
|
val apiSchemesFilePath = extension.apiSchemesFilePath ?: throw IllegalStateException("Configure sourceFilePath for swagger generator plugin")
|
||||||
|
val outputDir = extension.outputDir ?: throw IllegalStateException("Configure outputDir for swagger generator plugin")
|
||||||
|
val projectName = extension.projectName ?: throw IllegalStateException("Configure projectName for swagger generator plugin")
|
||||||
|
|
||||||
|
javaexec {
|
||||||
|
workingDir = file(taskWorkingDir)
|
||||||
|
classpath = files(configurations.getByName(GENERATOR_CONFIG).asPath,
|
||||||
|
configurations.getByName(TI_GENERATOR_CONFIG).asPath)
|
||||||
|
main = "io.swagger.codegen.v3.cli.SwaggerCodegen"
|
||||||
|
args = listOfNotNull(
|
||||||
|
"generate",
|
||||||
|
"-i",
|
||||||
|
apiSchemesFilePath,
|
||||||
|
"-l",
|
||||||
|
"TIKotlinCodegen",
|
||||||
|
"-o",
|
||||||
|
outputDir,
|
||||||
|
"--additional-properties",
|
||||||
|
"projectName=$projectName"
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
open class SwaggerApiGeneratorExtension(
|
||||||
|
var taskWorkingDir: String? = null,
|
||||||
|
var apiSchemesFilePath: String? = null,
|
||||||
|
var outputDir: String? = null,
|
||||||
|
var projectName: String? = null
|
||||||
|
)
|
||||||
|
|
||||||
|
fun Project.swaggerApiGenerator(configure: Action<SwaggerApiGeneratorExtension>): Unit =
|
||||||
|
(this as org.gradle.api.plugins.ExtensionAware).extensions.configure("swaggerApiGenerator", configure)
|
||||||
|
|
@ -0,0 +1,15 @@
|
||||||
|
package static_analysis.errors
|
||||||
|
|
||||||
|
class AndroidLintError(
|
||||||
|
private val filePath: String,
|
||||||
|
private val fileLine: String?,
|
||||||
|
private val errorId: String,
|
||||||
|
private val description: String
|
||||||
|
) : StaticAnalysisError {
|
||||||
|
|
||||||
|
override fun print(count: Int): String = "\n$count. Android Lint. $description ($errorId)\n\tat [$filePath$fileLinePrefix]"
|
||||||
|
|
||||||
|
private val fileLinePrefix: String
|
||||||
|
get() = fileLine?.let { ":$it" }.orEmpty()
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,12 @@
|
||||||
|
package static_analysis.errors
|
||||||
|
|
||||||
|
class CpdError(
|
||||||
|
private val duplications: List<Pair<String, String>>,
|
||||||
|
private val codeFragment: String
|
||||||
|
) : StaticAnalysisError {
|
||||||
|
|
||||||
|
override fun print(count: Int): String = "\n$count. CPD. Code duplication in files: " +
|
||||||
|
duplications.joinToString(separator = "") { (file, line) -> "\n\t[$file:$line]" } +
|
||||||
|
"\n\n Duplicated code:\n\n$codeFragment\n"
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,12 @@
|
||||||
|
package static_analysis.errors
|
||||||
|
|
||||||
|
class DetektError(
|
||||||
|
private val filePath: String,
|
||||||
|
private val fileLine: String,
|
||||||
|
private val errorId: String,
|
||||||
|
private val description: String
|
||||||
|
) : StaticAnalysisError {
|
||||||
|
|
||||||
|
override fun print(count: Int): String = "\n$count. Detekt. $description ($errorId)\n\tat [$filePath:$fileLine]"
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,5 @@
|
||||||
|
package static_analysis.errors
|
||||||
|
|
||||||
|
interface StaticAnalysisError {
|
||||||
|
fun print(count: Int): String
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,72 @@
|
||||||
|
package static_analysis.linters
|
||||||
|
|
||||||
|
import com.android.build.gradle.AppExtension
|
||||||
|
import com.android.build.gradle.AppPlugin
|
||||||
|
import org.gradle.api.Project
|
||||||
|
import org.gradle.kotlin.dsl.findByType
|
||||||
|
import static_analysis.errors.AndroidLintError
|
||||||
|
import static_analysis.errors.StaticAnalysisError
|
||||||
|
import static_analysis.plugins.StaticAnalysisExtension
|
||||||
|
import static_analysis.utils.typedChildren
|
||||||
|
import static_analysis.utils.xmlParser
|
||||||
|
|
||||||
|
class AndroidLinter : Linter {
|
||||||
|
|
||||||
|
override val name: String = "Android lint"
|
||||||
|
|
||||||
|
override fun getErrors(project: Project): List<StaticAnalysisError> = xmlParser(project.getLintReportFile())
|
||||||
|
.typedChildren()
|
||||||
|
.filter { it.name() == "issue" && (it.attribute("severity") as String) == "Error" }
|
||||||
|
.map { errorNode ->
|
||||||
|
errorNode
|
||||||
|
.typedChildren()
|
||||||
|
.filter { it.name() == "location" }
|
||||||
|
.map { locationNode ->
|
||||||
|
AndroidLintError(
|
||||||
|
filePath = locationNode.attribute("file") as String,
|
||||||
|
fileLine = locationNode.attribute("line") as String?,
|
||||||
|
errorId = errorNode.attribute("id") as String,
|
||||||
|
description = errorNode.attribute("message") as String
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.flatten()
|
||||||
|
|
||||||
|
override fun setupForProject(project: Project, extension: StaticAnalysisExtension) {
|
||||||
|
project.beforeEvaluate {
|
||||||
|
subprojects
|
||||||
|
.mapNotNull { it.extensions.findByType<AppExtension>() }
|
||||||
|
.first()
|
||||||
|
.lintOptions.apply {
|
||||||
|
isAbortOnError = false
|
||||||
|
isCheckAllWarnings = true
|
||||||
|
isWarningsAsErrors = false
|
||||||
|
xmlReport = true
|
||||||
|
htmlReport = false
|
||||||
|
isCheckDependencies = true
|
||||||
|
disable("MissingConstraints", "VectorRaster")
|
||||||
|
xmlOutput = getLintReportFile()
|
||||||
|
lintConfig = file("${extension.buildScriptDir}/static_analysis_configs/lint.xml")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getTaskNames(project: Project, buildType: String?): List<String> {
|
||||||
|
if (buildType == null) {
|
||||||
|
throw IllegalStateException("Build type must not be null in android linter")
|
||||||
|
}
|
||||||
|
|
||||||
|
return project
|
||||||
|
.subprojects
|
||||||
|
.filter { it.plugins.hasPlugin(AppPlugin::class.java) }
|
||||||
|
.mapNotNull { subproject: Project ->
|
||||||
|
subproject
|
||||||
|
.tasks
|
||||||
|
.find { task -> task.name.contains(buildType, ignoreCase = true) && task.name.contains("lint") }
|
||||||
|
?.path
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun Project.getLintReportFile() = file("${rootProject.buildDir}/reports/lint-report.xml")
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,60 @@
|
||||||
|
package static_analysis.linters
|
||||||
|
|
||||||
|
import de.aaschmid.gradle.plugins.cpd.Cpd
|
||||||
|
import de.aaschmid.gradle.plugins.cpd.CpdExtension
|
||||||
|
import org.gradle.api.Project
|
||||||
|
import org.gradle.kotlin.dsl.findByType
|
||||||
|
import org.gradle.kotlin.dsl.withType
|
||||||
|
import static_analysis.errors.CpdError
|
||||||
|
import static_analysis.errors.StaticAnalysisError
|
||||||
|
import static_analysis.plugins.StaticAnalysisExtension
|
||||||
|
import static_analysis.utils.getSources
|
||||||
|
import static_analysis.utils.typedChildren
|
||||||
|
import static_analysis.utils.xmlParser
|
||||||
|
|
||||||
|
class CpdLinter : Linter {
|
||||||
|
|
||||||
|
override val name: String = "CPD"
|
||||||
|
|
||||||
|
override fun getErrors(project: Project): List<StaticAnalysisError> = xmlParser(project.getCpdReportFile())
|
||||||
|
.typedChildren()
|
||||||
|
.filter { it.name() == "duplication" }
|
||||||
|
.map { duplicationNode ->
|
||||||
|
|
||||||
|
val children = duplicationNode
|
||||||
|
.typedChildren()
|
||||||
|
|
||||||
|
CpdError(
|
||||||
|
duplications = children
|
||||||
|
.filter { it.name() == "file" }
|
||||||
|
.map { fileNode -> fileNode.attribute("path") as String to fileNode.attribute("line") as String },
|
||||||
|
codeFragment = children.findLast { it.name() == "codefragment" }!!.text()
|
||||||
|
)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun setupForProject(project: Project, extension: StaticAnalysisExtension) {
|
||||||
|
project.afterEvaluate {
|
||||||
|
extensions.findByType<CpdExtension>()!!.apply {
|
||||||
|
isSkipLexicalErrors = true
|
||||||
|
language = "kotlin"
|
||||||
|
minimumTokenCount = 60
|
||||||
|
}
|
||||||
|
tasks.withType<Cpd> {
|
||||||
|
reports.xml.required.set(true)
|
||||||
|
reports.xml.destination = getCpdReportFile()
|
||||||
|
ignoreFailures = true
|
||||||
|
source = getSources(extension.excludes)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getTaskNames(project: Project, buildType: String?): List<String> = project
|
||||||
|
.rootProject
|
||||||
|
.tasks
|
||||||
|
.withType<Cpd>()
|
||||||
|
.map(Cpd::getPath)
|
||||||
|
|
||||||
|
private fun Project.getCpdReportFile() = file("${rootProject.buildDir}/reports/cpd.xml")
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,62 @@
|
||||||
|
package static_analysis.linters
|
||||||
|
|
||||||
|
import io.gitlab.arturbosch.detekt.Detekt
|
||||||
|
import org.gradle.api.Project
|
||||||
|
import static_analysis.errors.DetektError
|
||||||
|
import static_analysis.errors.StaticAnalysisError
|
||||||
|
import static_analysis.plugins.StaticAnalysisExtension
|
||||||
|
import static_analysis.utils.getSources
|
||||||
|
import static_analysis.utils.typedChildren
|
||||||
|
import static_analysis.utils.xmlParser
|
||||||
|
|
||||||
|
class DetektLinter : Linter {
|
||||||
|
|
||||||
|
override val name: String = "Detekt"
|
||||||
|
|
||||||
|
override fun getErrors(project: Project): List<StaticAnalysisError> = xmlParser(project.getDetektReportFile())
|
||||||
|
.typedChildren()
|
||||||
|
.filter { fileNode -> fileNode.name() == "file" }
|
||||||
|
.map { fileNode ->
|
||||||
|
fileNode
|
||||||
|
.typedChildren()
|
||||||
|
.filter { it.name() == "error" }
|
||||||
|
.map { errorNode ->
|
||||||
|
DetektError(
|
||||||
|
filePath = fileNode.attribute("name") as String,
|
||||||
|
fileLine = errorNode.attribute("line") as String,
|
||||||
|
errorId = errorNode.attribute("source") as String,
|
||||||
|
description = errorNode.attribute("message") as String
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.flatten()
|
||||||
|
|
||||||
|
override fun setupForProject(project: Project, extension: StaticAnalysisExtension) {
|
||||||
|
project.afterEvaluate {
|
||||||
|
tasks.withType(Detekt::class.java) {
|
||||||
|
exclude("**/test/**")
|
||||||
|
exclude("resources/")
|
||||||
|
exclude("build/")
|
||||||
|
exclude("tmp/")
|
||||||
|
jvmTarget = "1.8"
|
||||||
|
|
||||||
|
config.setFrom(files("${extension.buildScriptDir!!}/static_analysis_configs/detekt-config.yml"))
|
||||||
|
reports {
|
||||||
|
txt.enabled = false
|
||||||
|
html.enabled = false
|
||||||
|
xml {
|
||||||
|
enabled = true
|
||||||
|
destination = getDetektReportFile()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
source = getSources(extension.excludes)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getTaskNames(project: Project, buildType: String?): List<String> = listOf(":detekt")
|
||||||
|
|
||||||
|
private fun Project.getDetektReportFile() = file("${rootProject.buildDir}/reports/detekt.xml")
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,12 @@
|
||||||
|
package static_analysis.linters
|
||||||
|
|
||||||
|
import org.gradle.api.Project
|
||||||
|
import static_analysis.errors.StaticAnalysisError
|
||||||
|
import static_analysis.plugins.StaticAnalysisExtension
|
||||||
|
|
||||||
|
interface Linter {
|
||||||
|
val name: String
|
||||||
|
fun getErrors(project: Project): List<StaticAnalysisError>
|
||||||
|
fun setupForProject(project: Project, extension: StaticAnalysisExtension)
|
||||||
|
fun getTaskNames(project: Project, buildType: String? = null): List<String>
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,41 @@
|
||||||
|
package static_analysis.plugins
|
||||||
|
|
||||||
|
import com.android.build.gradle.AppExtension
|
||||||
|
import org.gradle.api.Project
|
||||||
|
import org.gradle.kotlin.dsl.getByType
|
||||||
|
import static_analysis.linters.AndroidLinter
|
||||||
|
import static_analysis.linters.CpdLinter
|
||||||
|
import static_analysis.linters.DetektLinter
|
||||||
|
import static_analysis.linters.Linter
|
||||||
|
|
||||||
|
class StaticAnalysisAndroidPlugin : StaticAnalysisPlugin() {
|
||||||
|
|
||||||
|
override fun createStaticAnalysisTasks(project: Project, linters: List<Linter>) {
|
||||||
|
project.subprojects {
|
||||||
|
if (plugins.hasPlugin("com.android.application")) {
|
||||||
|
|
||||||
|
extensions.getByType<AppExtension>().apply {
|
||||||
|
applicationVariants.forEach { variant ->
|
||||||
|
project.tasks.register("staticAnalysis${variant.name.capitalize()}") {
|
||||||
|
setupStaticAnalysisTask(linters, variant.name)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
project.tasks.register("staticAnalysis") {
|
||||||
|
setupStaticAnalysisTask(
|
||||||
|
linters = linters,
|
||||||
|
buildVariant = applicationVariants.first { it.name.contains("Debug") }.name
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun createLinters(): List<Linter> = listOf(
|
||||||
|
DetektLinter(),
|
||||||
|
CpdLinter(),
|
||||||
|
AndroidLinter()
|
||||||
|
)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,21 @@
|
||||||
|
package static_analysis.plugins
|
||||||
|
|
||||||
|
import org.gradle.api.Project
|
||||||
|
import static_analysis.linters.CpdLinter
|
||||||
|
import static_analysis.linters.DetektLinter
|
||||||
|
import static_analysis.linters.Linter
|
||||||
|
|
||||||
|
class StaticAnalysisBackendPlugin : StaticAnalysisPlugin() {
|
||||||
|
|
||||||
|
override fun createStaticAnalysisTasks(project: Project, linters: List<Linter>) {
|
||||||
|
project.tasks.register("staticAnalysis") {
|
||||||
|
setupStaticAnalysisTask(linters)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun createLinters(): List<Linter> = listOf(
|
||||||
|
CpdLinter(),
|
||||||
|
DetektLinter()
|
||||||
|
)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,6 @@
|
||||||
|
package static_analysis.plugins
|
||||||
|
|
||||||
|
open class StaticAnalysisExtension(
|
||||||
|
var excludes: String = "",
|
||||||
|
var buildScriptDir: String? = null
|
||||||
|
)
|
||||||
|
|
@ -0,0 +1,45 @@
|
||||||
|
package static_analysis.plugins
|
||||||
|
|
||||||
|
import org.gradle.api.Plugin
|
||||||
|
import org.gradle.api.Project
|
||||||
|
import org.gradle.api.Task
|
||||||
|
import org.gradle.kotlin.dsl.create
|
||||||
|
import org.gradle.kotlin.dsl.getByType
|
||||||
|
import static_analysis.linters.Linter
|
||||||
|
import static_analysis.utils.ReportGenerator
|
||||||
|
|
||||||
|
abstract class StaticAnalysisPlugin : Plugin<Project> {
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
const val DETEKT_ID = "io.gitlab.arturbosch.detekt"
|
||||||
|
const val CPD_ID = "de.aaschmid.cpd"
|
||||||
|
const val STATIC_ANALYSIS_EXT_NAME = "staticAnalysis"
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun apply(target: Project) {
|
||||||
|
|
||||||
|
with(target) {
|
||||||
|
pluginManager.apply(CPD_ID)
|
||||||
|
pluginManager.apply(DETEKT_ID)
|
||||||
|
|
||||||
|
extensions.create<StaticAnalysisExtension>(STATIC_ANALYSIS_EXT_NAME)
|
||||||
|
|
||||||
|
val linters = createLinters()
|
||||||
|
|
||||||
|
linters.forEach { it.setupForProject(target, extensions.getByType()) }
|
||||||
|
|
||||||
|
gradle.projectsEvaluated {
|
||||||
|
createStaticAnalysisTasks(target, linters)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun Task.setupStaticAnalysisTask(linters: List<Linter>, buildVariant: String? = null) {
|
||||||
|
doFirst { ReportGenerator.generate(linters, project) }
|
||||||
|
dependsOn(*(linters.map { it.getTaskNames(project, buildVariant) }.flatten().toTypedArray()))
|
||||||
|
}
|
||||||
|
|
||||||
|
abstract fun createLinters(): List<Linter>
|
||||||
|
abstract fun createStaticAnalysisTasks(project: Project, linters: List<Linter>)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,5 @@
|
||||||
|
package static_analysis.utils
|
||||||
|
|
||||||
|
import groovy.util.Node
|
||||||
|
|
||||||
|
fun Node.typedChildren() = children() as List<Node>
|
||||||
|
|
@ -0,0 +1,27 @@
|
||||||
|
package static_analysis.utils
|
||||||
|
|
||||||
|
import org.gradle.api.Project
|
||||||
|
import org.gradle.api.file.FileTree
|
||||||
|
import java.io.File
|
||||||
|
|
||||||
|
fun Project.getSources(excludes: String): FileTree = files(
|
||||||
|
project
|
||||||
|
.rootProject
|
||||||
|
.subprojects
|
||||||
|
.filter { subproject -> subproject.subprojects.isEmpty() && !excludes.contains(subproject.path) }
|
||||||
|
.map { subproject -> subproject.file("${subproject.projectDir.path}/src/main") }
|
||||||
|
.filter { it.exists() && it.isDirectory }
|
||||||
|
.flatMap { srcDir ->
|
||||||
|
srcDir
|
||||||
|
.listFiles()
|
||||||
|
.orEmpty()
|
||||||
|
.flatMap {
|
||||||
|
listOf(
|
||||||
|
File(srcDir.path, "java"),
|
||||||
|
File(srcDir.path, "kotlin")
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.filter { it.exists() && it.isDirectory }
|
||||||
|
.map { it.path }
|
||||||
|
).asFileTree
|
||||||
|
|
@ -0,0 +1,52 @@
|
||||||
|
package static_analysis.utils
|
||||||
|
|
||||||
|
import org.gradle.api.Project
|
||||||
|
import static_analysis.errors.StaticAnalysisError
|
||||||
|
import static_analysis.linters.Linter
|
||||||
|
|
||||||
|
object ReportGenerator {
|
||||||
|
|
||||||
|
fun generate(linters: List<Linter>, project: Project) {
|
||||||
|
|
||||||
|
val groupedErrors = linters
|
||||||
|
.map { linter -> linter to linter.getErrors(project) }
|
||||||
|
|
||||||
|
val lintersResults = groupedErrors
|
||||||
|
.map { (linter, linterErrors) -> linter.name to linterErrors.size }
|
||||||
|
|
||||||
|
val allErrors = groupedErrors
|
||||||
|
.map(Pair<Linter, List<StaticAnalysisError>>::second)
|
||||||
|
.flatten()
|
||||||
|
|
||||||
|
val consoleReport = StringBuilder("\nSTATIC ANALYSIS ERRORS:").apply {
|
||||||
|
appendAllErrors(allErrors)
|
||||||
|
append("\nREPORT:\n")
|
||||||
|
appendReportsSummary(lintersResults)
|
||||||
|
appendOverallSummary(allErrors)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (allErrors.isEmpty()) {
|
||||||
|
println(consoleReport)
|
||||||
|
} else {
|
||||||
|
throw Exception(consoleReport.toString())
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun StringBuilder.appendAllErrors(errors: List<StaticAnalysisError>) = errors
|
||||||
|
.mapIndexed { index, staticAnalysisError -> staticAnalysisError.print(index + 1) }
|
||||||
|
.forEach { error -> append(error) }
|
||||||
|
|
||||||
|
private fun StringBuilder.appendReportsSummary(lintersResults: List<Pair<String, Int>>) = lintersResults
|
||||||
|
.forEach { this.appendSummary(it.first, it.second) }
|
||||||
|
|
||||||
|
private fun StringBuilder.appendOverallSummary(errors: List<StaticAnalysisError>) = appendSummary("Overall", errors.size)
|
||||||
|
|
||||||
|
private fun StringBuilder.appendSummary(header: String, quantityOfErrors: Int) {
|
||||||
|
assert(quantityOfErrors < 0)
|
||||||
|
|
||||||
|
append("\n$header: ")
|
||||||
|
append(if (quantityOfErrors == 0) "PASSED" else "FAILED ($quantityOfErrors errors)")
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,6 @@
|
||||||
|
package static_analysis.utils
|
||||||
|
|
||||||
|
import groovy.util.XmlParser
|
||||||
|
import java.io.File
|
||||||
|
|
||||||
|
fun xmlParser(file: File) = XmlParser().parse(file)
|
||||||
|
|
@ -0,0 +1,12 @@
|
||||||
|
android {
|
||||||
|
defaultConfig {
|
||||||
|
setProperty(
|
||||||
|
"archivesBaseName",
|
||||||
|
"${project.android.defaultConfig.applicationId}" +
|
||||||
|
"-" +
|
||||||
|
"${project.android.defaultConfig.versionName}" +
|
||||||
|
"-" +
|
||||||
|
"${project.android.defaultConfig.versionCode}"
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,92 @@
|
||||||
|
import groovy.json.JsonSlurper
|
||||||
|
import groovy.xml.MarkupBuilder
|
||||||
|
|
||||||
|
task stringGenerator {
|
||||||
|
generate(android.languageMap, project)
|
||||||
|
println("Strings generated!")
|
||||||
|
}
|
||||||
|
|
||||||
|
private def generate(Map<String, String> sources, Project project) {
|
||||||
|
if (sources == null || sources.isEmpty()) {
|
||||||
|
throw new IOException("languageMap can't be null or empty")
|
||||||
|
}
|
||||||
|
Map jsonMap = getJsonsMap(sources)
|
||||||
|
def diffs = calcDiffs(jsonMap)
|
||||||
|
if (!diffs.isEmpty()) {
|
||||||
|
printDiffs(diffs)
|
||||||
|
throw new IllegalStateException("Strings source can't be different")
|
||||||
|
}
|
||||||
|
def defaultLang = getDefaultLangKey(sources)
|
||||||
|
jsonMap.forEach { key, json ->
|
||||||
|
|
||||||
|
def sw = new StringWriter()
|
||||||
|
def xml = new MarkupBuilder(sw)
|
||||||
|
|
||||||
|
xml.setDoubleQuotes(true)
|
||||||
|
xml.mkp.xmlDeclaration(version: "1.0", encoding: "utf-8")
|
||||||
|
xml.resources() {
|
||||||
|
json.each {
|
||||||
|
k, v ->
|
||||||
|
string(name: "${k}", formatted: "false", "${v}".replace('\n', '\\n'))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
def stringsFile = getFile(key, key == defaultLang, project)
|
||||||
|
stringsFile.write(sw.toString(), "UTF-8")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private printDiffs(Map<?, ?> diffs) {
|
||||||
|
def diffLog = new StringBuilder()
|
||||||
|
diffs.forEach { k, v ->
|
||||||
|
if (v.size() > 0) {
|
||||||
|
diffLog.append("For $k was missed string keys: ${v.size()}\n")
|
||||||
|
v.forEach {
|
||||||
|
diffLog.append("\tString key: $it\n")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
println(diffLog.toString())
|
||||||
|
}
|
||||||
|
|
||||||
|
private static def calcDiffs(Map<String, Object> jsonsMap) {
|
||||||
|
if (jsonsMap.size() == 1) {
|
||||||
|
return [:]
|
||||||
|
}
|
||||||
|
def keys = jsonsMap.collectEntries {
|
||||||
|
[(it.key): (it.value).keySet() as List]
|
||||||
|
}
|
||||||
|
def inclusive = keys.get(keys.keySet().first())
|
||||||
|
def diffs = keys.collectEntries {
|
||||||
|
[(it.key): inclusive - it.value.intersect(inclusive)]
|
||||||
|
}.findAll { it.value.size() > 0 }
|
||||||
|
return diffs
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Map<String, Object> getJsonsMap(Map sources) {
|
||||||
|
return sources.collectEntries {
|
||||||
|
[(it.key): new JsonSlurper().parseText(new File(it.value).text)]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static File getFile(String key, boolean defaultLang, Project project) {
|
||||||
|
if (defaultLang) {
|
||||||
|
return project.file("src/main/res/values/strings.xml")
|
||||||
|
} else {
|
||||||
|
def directory = project.file("src/main/res/values-$key")
|
||||||
|
if (!directory.exists()) {
|
||||||
|
directory.mkdir()
|
||||||
|
}
|
||||||
|
return project.file("src/main/res/values-$key/strings.xml")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String getDefaultLangKey(Map<String, String> sources) {
|
||||||
|
def defaultLanguage = sources.find { it.value.contains("default") }
|
||||||
|
if (defaultLanguage != null) {
|
||||||
|
return defaultLanguage.key
|
||||||
|
} else {
|
||||||
|
throw new IOException("Can't find default language")
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -1,107 +0,0 @@
|
||||||
def getServerProjectSources
|
|
||||||
def getAndroidProjectSources
|
|
||||||
|
|
||||||
apply from: "${rootDir}/libraries/BuildScripts/gradle/commonStaticAnalysis.gradle"
|
|
||||||
|
|
||||||
gradle.projectsEvaluated {
|
|
||||||
|
|
||||||
tasks.withType(JavaCompile) {
|
|
||||||
options.compilerArgs <<
|
|
||||||
"-Xlint:cast" <<
|
|
||||||
"-Xlint:divzero" <<
|
|
||||||
"-Xlint:empty" <<
|
|
||||||
"-Xlint:deprecation" <<
|
|
||||||
"-Xlint:finally" <<
|
|
||||||
"-Xlint:overrides" <<
|
|
||||||
"-Xlint:path"
|
|
||||||
}
|
|
||||||
|
|
||||||
def excludes = rootProject.extensions.findByName("staticAnalysisExcludes")
|
|
||||||
|
|
||||||
def androidStaticAnalysisTasks = getStaticAnalysisTaskNames(true, getAndroidProjectSources(excludes))
|
|
||||||
def androidIdeaFormatTask = getIdeaFormatTask(true, getAndroidProjectSources(excludes))
|
|
||||||
task staticAnalysis {
|
|
||||||
androidStaticAnalysisTasks.each { task ->
|
|
||||||
tasks.findByName(task).mustRunAfter(androidIdeaFormatTask)
|
|
||||||
}
|
|
||||||
dependsOn androidIdeaFormatTask
|
|
||||||
dependsOn androidStaticAnalysisTasks
|
|
||||||
doFirst {
|
|
||||||
generateHtmlReport(true)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
task staticAnalysisWithoutFormatting {
|
|
||||||
dependsOn androidStaticAnalysisTasks
|
|
||||||
doFirst {
|
|
||||||
generateHtmlReport(true)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
def serverStaticAnalysisTasks = getStaticAnalysisTaskNames(false, getServerProjectSources(excludes))
|
|
||||||
def serverIdeaFormatTask = getIdeaFormatTask(false, getServerProjectSources(excludes))
|
|
||||||
task serverStaticAnalysis {
|
|
||||||
serverStaticAnalysisTasks.each { task ->
|
|
||||||
tasks.findByName(task).mustRunAfter(serverIdeaFormatTask)
|
|
||||||
}
|
|
||||||
dependsOn serverIdeaFormatTask
|
|
||||||
dependsOn serverStaticAnalysisTasks
|
|
||||||
doFirst {
|
|
||||||
generateHtmlReport(false)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
task serverStaticAnalysisWithoutFormatting {
|
|
||||||
dependsOn serverStaticAnalysisTasks
|
|
||||||
doFirst {
|
|
||||||
generateHtmlReport(false)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
getServerProjectSources = { excludes ->
|
|
||||||
def sources = new ArrayList<String>()
|
|
||||||
def sourcesDirectory = new File(project.projectDir.path, 'src')
|
|
||||||
|
|
||||||
for (def sourceFlavorDirectory : sourcesDirectory.listFiles()) {
|
|
||||||
def javaSourceDirectory = new File(sourceFlavorDirectory.path, 'java')
|
|
||||||
def kotlinSourceDirectory = new File(sourceFlavorDirectory.path, 'kotlin')
|
|
||||||
|
|
||||||
if (javaSourceDirectory.exists() && javaSourceDirectory.isDirectory()) {
|
|
||||||
sources.add(javaSourceDirectory.absolutePath)
|
|
||||||
}
|
|
||||||
if (kotlinSourceDirectory.exists() && kotlinSourceDirectory.isDirectory()) {
|
|
||||||
sources.add(kotlinSourceDirectory.absolutePath)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return sources
|
|
||||||
}
|
|
||||||
|
|
||||||
getAndroidProjectSources = { excludes ->
|
|
||||||
def sources = new ArrayList<String>()
|
|
||||||
for (def project : rootProject.subprojects) {
|
|
||||||
if (!project.subprojects.isEmpty() || (excludes != null && excludes.contains(project.path))) {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
def sourcesDirectory = new File(project.projectDir.path, 'src')
|
|
||||||
if (!sourcesDirectory.exists() || !sourcesDirectory.isDirectory()) {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
for (def sourceFlavorDirectory : sourcesDirectory.listFiles()) {
|
|
||||||
def javaSourceDirectory = new File(sourceFlavorDirectory.path, 'java')
|
|
||||||
def kotlinSourceDirectory = new File(sourceFlavorDirectory.path, 'kotlin')
|
|
||||||
|
|
||||||
if (javaSourceDirectory.exists() && javaSourceDirectory.isDirectory()) {
|
|
||||||
sources.add(javaSourceDirectory.absolutePath)
|
|
||||||
}
|
|
||||||
if (kotlinSourceDirectory.exists() && kotlinSourceDirectory.isDirectory()) {
|
|
||||||
sources.add(kotlinSourceDirectory.absolutePath)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return sources
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -1,142 +0,0 @@
|
||||||
autoCorrect: true
|
|
||||||
|
|
||||||
build:
|
|
||||||
warningThreshold: 1
|
|
||||||
failThreshold: 100500
|
|
||||||
weights:
|
|
||||||
complexity: 2
|
|
||||||
formatting: 0
|
|
||||||
LongParameterList: 1
|
|
||||||
comments: 0.5
|
|
||||||
|
|
||||||
potential-bugs:
|
|
||||||
active: true
|
|
||||||
DuplicateCaseInWhenExpression:
|
|
||||||
active: true
|
|
||||||
EqualsWithHashCodeExist:
|
|
||||||
active: true
|
|
||||||
ExplicitGarbageCollectionCall:
|
|
||||||
active: true
|
|
||||||
LateinitUsage:
|
|
||||||
active: false
|
|
||||||
UnsafeCallOnNullableType:
|
|
||||||
active: false
|
|
||||||
UnsafeCast:
|
|
||||||
active: false
|
|
||||||
|
|
||||||
performance:
|
|
||||||
active: true
|
|
||||||
ForEachOnRange:
|
|
||||||
active: true
|
|
||||||
SpreadOperator:
|
|
||||||
active: true
|
|
||||||
|
|
||||||
exceptions:
|
|
||||||
active: false
|
|
||||||
|
|
||||||
empty-blocks:
|
|
||||||
active: true
|
|
||||||
|
|
||||||
complexity:
|
|
||||||
active: true
|
|
||||||
LongMethod:
|
|
||||||
threshold: 40
|
|
||||||
LongParameterList:
|
|
||||||
threshold: 10
|
|
||||||
LargeClass:
|
|
||||||
threshold: 800
|
|
||||||
ComplexMethod:
|
|
||||||
threshold: 10
|
|
||||||
TooManyFunctions:
|
|
||||||
threshold: 20
|
|
||||||
ComplexCondition:
|
|
||||||
threshold: 6
|
|
||||||
|
|
||||||
code-smell:
|
|
||||||
active: true
|
|
||||||
FeatureEnvy:
|
|
||||||
threshold: 0.5
|
|
||||||
weight: 0.45
|
|
||||||
base: 0.5
|
|
||||||
|
|
||||||
formatting:
|
|
||||||
active: true
|
|
||||||
useTabs: true
|
|
||||||
Indentation:
|
|
||||||
active: false
|
|
||||||
indentSize: 4
|
|
||||||
ConsecutiveBlankLines:
|
|
||||||
active: true
|
|
||||||
autoCorrect: false
|
|
||||||
MultipleSpaces:
|
|
||||||
active: true
|
|
||||||
autoCorrect: true
|
|
||||||
SpacingAfterComma:
|
|
||||||
active: true
|
|
||||||
autoCorrect: true
|
|
||||||
SpacingAfterKeyword:
|
|
||||||
active: true
|
|
||||||
autoCorrect: true
|
|
||||||
SpacingAroundColon:
|
|
||||||
active: true
|
|
||||||
autoCorrect: true
|
|
||||||
SpacingAroundCurlyBraces:
|
|
||||||
active: true
|
|
||||||
autoCorrect: true
|
|
||||||
SpacingAroundOperator:
|
|
||||||
active: true
|
|
||||||
autoCorrect: true
|
|
||||||
TrailingSpaces:
|
|
||||||
active: true
|
|
||||||
autoCorrect: true
|
|
||||||
UnusedImports:
|
|
||||||
active: true
|
|
||||||
autoCorrect: true
|
|
||||||
OptionalSemicolon:
|
|
||||||
active: true
|
|
||||||
autoCorrect: true
|
|
||||||
OptionalUnit:
|
|
||||||
active: true
|
|
||||||
autoCorrect: true
|
|
||||||
ExpressionBodySyntax:
|
|
||||||
active: true
|
|
||||||
autoCorrect: false
|
|
||||||
ExpressionBodySyntaxLineBreaks:
|
|
||||||
active: true
|
|
||||||
autoCorrect: false
|
|
||||||
OptionalReturnKeyword:
|
|
||||||
active: true
|
|
||||||
autoCorrect: false
|
|
||||||
|
|
||||||
style:
|
|
||||||
active: true
|
|
||||||
NewLineAtEndOfFile:
|
|
||||||
active: false
|
|
||||||
ForbiddenComment:
|
|
||||||
active: true
|
|
||||||
values: 'STOPSHIP:'
|
|
||||||
WildcardImport:
|
|
||||||
active: true
|
|
||||||
MaxLineLength:
|
|
||||||
active: true
|
|
||||||
maxLineLength: 150
|
|
||||||
excludePackageStatements: false
|
|
||||||
excludeImportStatements: false
|
|
||||||
NamingConventionViolation:
|
|
||||||
active: true
|
|
||||||
variablePattern: '^[a-z][a-z0-9][a-zA-Z0-9]*$'
|
|
||||||
constantPattern: '^[A-Z][A-Z0-9]*(_[A-Z0-9]+)*$'
|
|
||||||
methodPattern: '^[a-z][a-z0-9][a-zA-Z0-9_]*$'
|
|
||||||
classPattern: '^[A-Z][a-zA-Z0-9]*$'
|
|
||||||
enumEntryPattern: '^[A-Z][a-zA-Z0-9_]*$'
|
|
||||||
|
|
||||||
comments:
|
|
||||||
active: false
|
|
||||||
CommentOverPrivateMethod:
|
|
||||||
active: false
|
|
||||||
CommentOverPrivateProperty:
|
|
||||||
active: false
|
|
||||||
UndocumentedPublicClass:
|
|
||||||
active: false
|
|
||||||
UndocumentedPublicFunction:
|
|
||||||
active: false
|
|
||||||
275
lint/lint.xml
275
lint/lint.xml
|
|
@ -1,275 +0,0 @@
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<lint>
|
|
||||||
|
|
||||||
<issue id="InvalidPackage" severity="error">
|
|
||||||
<ignore regexp="Invalid package reference in library.*not included in Android.*java.*"/>
|
|
||||||
</issue>
|
|
||||||
<issue id="NewerVersionAvailable" severity="error">
|
|
||||||
<ignore regexp="A newer version of de.ruedigermoeller:fst than .+ is available: .+"/>
|
|
||||||
</issue>
|
|
||||||
<issue id="GradleCompatible" severity="error">
|
|
||||||
<ignore regexp="All com.android.support libraries must use the exact same version specification (mixing versions can lead to runtime crashes). Found versions *. Examples include *"/>
|
|
||||||
</issue>
|
|
||||||
<!-- todo: lint bug? -->
|
|
||||||
<issue id="MissingRegistered" severity="ignore"/>
|
|
||||||
<!-- todo: lint bug? -->
|
|
||||||
<issue id="MissingPermission" severity="ignore"/>
|
|
||||||
<!-- todo: lint bug? -->
|
|
||||||
<issue id="MissingSuperCall" severity="ignore"/>
|
|
||||||
|
|
||||||
<issue id="AllowAllHostnameVerifier" severity="error"/>
|
|
||||||
<issue id="InvalidUsesTagAttribute" severity="error"/>
|
|
||||||
<issue id="MissingIntentFilterForMediaSearch" severity="error"/>
|
|
||||||
<issue id="MissingMediaBrowserServiceIntentFilter" severity="error"/>
|
|
||||||
<issue id="MissingOnPlayFromSearch" severity="error"/>
|
|
||||||
<issue id="ShiftFlags" severity="error"/>
|
|
||||||
<issue id="LocalSuppress" severity="error"/>
|
|
||||||
<issue id="SwitchIntDef" severity="error"/>
|
|
||||||
<issue id="UniqueConstants" severity="error"/>
|
|
||||||
<issue id="InlinedApi" severity="error"/>
|
|
||||||
<issue id="Override" severity="error"/>
|
|
||||||
<issue id="UnusedAttribute" severity="warning"/>
|
|
||||||
<issue id="AppCompatResource" severity="error"/>
|
|
||||||
<issue id="BadHostnameVerifier" severity="error"/>
|
|
||||||
<issue id="EnforceUTF8" severity="error"/>
|
|
||||||
<issue id="ByteOrderMark" severity="error"/>
|
|
||||||
<issue id="StopShip" severity="error"/>
|
|
||||||
<issue id="MissingPrefix" severity="error"/>
|
|
||||||
<issue id="MangledCRLF" severity="error"/>
|
|
||||||
<issue id="DuplicateIds" severity="error"/>
|
|
||||||
<issue id="DuplicateDefinition" severity="error"/>
|
|
||||||
<issue id="ReferenceType" severity="error"/>
|
|
||||||
<issue id="UnsafeDynamicallyLoadedCode" severity="error"/>
|
|
||||||
<issue id="UnsafeNativeCodeLocation" severity="error"/>
|
|
||||||
<issue id="FullBackupContent" severity="error"/>
|
|
||||||
<issue id="ValidFragment" severity="error"/>
|
|
||||||
<issue id="GradleCompatible" severity="error"/>
|
|
||||||
<issue id="GradlePluginVersion" severity="error"/>
|
|
||||||
<issue id="GradleGetter" severity="error"/>
|
|
||||||
<issue id="GradleIdeError" severity="error"/>
|
|
||||||
<issue id="NotInterpolated" severity="error"/>
|
|
||||||
<issue id="StringShouldBeInt" severity="error"/>
|
|
||||||
<issue id="AccidentalOctal" severity="error"/>
|
|
||||||
<issue id="GridLayout" severity="error"/>
|
|
||||||
<issue id="HardcodedDebugMode" severity="error"/>
|
|
||||||
<issue id="IconExpectedSize" severity="error"/>
|
|
||||||
<issue id="IncludeLayoutParam" severity="error"/>
|
|
||||||
<issue id="TrustAllX509TrustManager" severity="warning"/>
|
|
||||||
<issue id="DefaultLocale" severity="error"/>
|
|
||||||
<issue id="InvalidResourceFolder" severity="error"/>
|
|
||||||
<issue id="LongLogTag" severity="error"/>
|
|
||||||
<issue id="LogTagMismatch" severity="error"/>
|
|
||||||
<issue id="DuplicateActivity" severity="error"/>
|
|
||||||
<issue id="MockLocation" severity="error"/>
|
|
||||||
<issue id="MultipleUsesSdk" severity="error"/>
|
|
||||||
<issue id="UniquePermission" severity="error"/>
|
|
||||||
<issue id="WrongManifestParent" severity="error"/>
|
|
||||||
<issue id="ManifestResource" severity="error"/>
|
|
||||||
<issue id="ManifestTypo" severity="error"/>
|
|
||||||
<issue id="FloatMath" severity="error"/>
|
|
||||||
<issue id="Instantiatable" severity="error"/>
|
|
||||||
<issue id="LibraryCustomView" severity="error"/>
|
|
||||||
<issue id="ResAuto" severity="error"/>
|
|
||||||
<issue id="NamespaceTypo" severity="error"/>
|
|
||||||
<issue id="UnusedNamespace" severity="error"/>
|
|
||||||
<issue id="NfcTechWhitespace" severity="error"/>
|
|
||||||
<issue id="OnClick" severity="error"/>
|
|
||||||
<issue id="DalvikOverride" severity="error"/>
|
|
||||||
<issue id="OverrideAbstract" severity="error"/>
|
|
||||||
<issue id="ParcelCreator" severity="error"/>
|
|
||||||
<issue id="PackagedPrivateKey" severity="error"/>
|
|
||||||
<issue id="Proguard" severity="error"/>
|
|
||||||
<issue id="PropertyEscape" severity="error"/>
|
|
||||||
<issue id="ParcelClassLoader" severity="error"/>
|
|
||||||
<issue id="RecyclerView" severity="error"/>
|
|
||||||
<issue id="RequiredSize" severity="error"/>
|
|
||||||
<issue id="AaptCrash" severity="error"/>
|
|
||||||
<issue id="ResourceCycle" severity="error"/>
|
|
||||||
<issue id="ResourceName" severity="error"/>
|
|
||||||
<issue id="ValidRestrictions" severity="error"/>
|
|
||||||
<issue id="RtlCompat" severity="error"/>
|
|
||||||
<issue id="ScrollViewSize" severity="error"/>
|
|
||||||
<issue id="SecureRandom" severity="error"/>
|
|
||||||
<issue id="SetWorldReadable" severity="error"/>
|
|
||||||
<issue id="SetWorldWritable" severity="error"/>
|
|
||||||
<issue id="ServiceCast" severity="error"/>
|
|
||||||
<issue id="SSLCertificateSocketFactoryCreateSocket" severity="error"/>
|
|
||||||
<issue id="SSLCertificateSocketFactoryGetInsecure" severity="error"/>
|
|
||||||
<issue id="StringFormatMatches" severity="error"/>
|
|
||||||
<issue id="StringFormatInvalid" severity="error"/>
|
|
||||||
<issue id="UseCheckPermission" severity="error"/>
|
|
||||||
<issue id="CheckResult" severity="warning"/>
|
|
||||||
<issue id="ResourceAsColor" severity="error"/>
|
|
||||||
<issue id="Range" severity="error"/>
|
|
||||||
<issue id="ResourceType" severity="error"/>
|
|
||||||
<issue id="WrongThread" severity="error"/>
|
|
||||||
<issue id="WrongConstant" severity="error"/>
|
|
||||||
<issue id="ProtectedPermissions" severity="error"/>
|
|
||||||
<issue id="MenuTitle" severity="error"/>
|
|
||||||
<issue id="ExtraTranslation" severity="error"/>
|
|
||||||
<issue id="MissingLeanbackLauncher" severity="error"/>
|
|
||||||
<issue id="MissingLeanbackSupport" severity="error"/>
|
|
||||||
<issue id="PermissionImpliesUnsupportedHardware" severity="error"/>
|
|
||||||
<issue id="UnsupportedTvHardware" severity="error"/>
|
|
||||||
<issue id="MissingTvBanner" severity="error"/>
|
|
||||||
<issue id="TypographyOther" severity="error"/>
|
|
||||||
<issue id="TypographyQuotes" severity="warning"/>
|
|
||||||
<issue id="UnsafeProtectedBroadcastReceiver" severity="error"/>
|
|
||||||
<issue id="UnprotectedSMSBroadcastReceiver" severity="error"/>
|
|
||||||
<issue id="VectorRaster" severity="error"/>
|
|
||||||
<issue id="ViewTag" severity="error"/>
|
|
||||||
<issue id="WrongViewCast" severity="error"/>
|
|
||||||
<issue id="Wakelock" severity="error"/>
|
|
||||||
<issue id="WrongCall" severity="error"/>
|
|
||||||
<issue id="WrongCase" severity="error"/>
|
|
||||||
<issue id="InvalidId" severity="error"/>
|
|
||||||
<issue id="NotSibling" severity="error"/>
|
|
||||||
<issue id="UnknownIdInLayout" severity="error"/>
|
|
||||||
<issue id="WrongFolder" severity="error"/>
|
|
||||||
<issue id="AdapterViewChildren" severity="error"/>
|
|
||||||
<issue id="SetJavaScriptEnabled" severity="warning"/>
|
|
||||||
<issue id="AddJavascriptInterface" severity="warning"/>
|
|
||||||
<issue id="AllowBackup" severity="error"/>
|
|
||||||
<issue id="AlwaysShowAction" severity="error"/>
|
|
||||||
<issue id="AppCompatMethod" severity="error"/>
|
|
||||||
<issue id="AppIndexingApiWarning" severity="error"/>
|
|
||||||
<issue id="Assert" severity="error"/>
|
|
||||||
<issue id="CommitPrefEdits" severity="error"/>
|
|
||||||
<issue id="CommitTransaction" severity="error"/>
|
|
||||||
<issue id="CustomViewStyleable" severity="error"/>
|
|
||||||
<issue id="CutPasteId" severity="error"/>
|
|
||||||
<issue id="Deprecated" severity="error"/>
|
|
||||||
<issue id="DeviceAdmin" severity="error"/>
|
|
||||||
<issue id="DisableBaselineAlignment" severity="error"/>
|
|
||||||
<issue id="DrawAllocation" severity="warning"/>
|
|
||||||
<issue id="DuplicateIncludedIds" severity="error"/>
|
|
||||||
<issue id="DuplicateUsesFeature" severity="error"/>
|
|
||||||
<issue id="ExportedContentProvider" severity="error"/>
|
|
||||||
<issue id="ExportedReceiver" severity="error"/>
|
|
||||||
<issue id="ExportedService" severity="error"/>
|
|
||||||
<issue id="ExtraText" severity="error"/>
|
|
||||||
<issue id="GetInstance" severity="error"/>
|
|
||||||
<issue id="GifUsage" severity="error"/>
|
|
||||||
<issue id="GradleDependency" severity="error"/>
|
|
||||||
<issue id="GradleDeprecated" severity="error"/>
|
|
||||||
<issue id="GradleDynamicVersion" severity="error"/>
|
|
||||||
<issue id="GradleOverrides" severity="error"/>
|
|
||||||
<issue id="GradlePath" severity="warning"/>
|
|
||||||
<issue id="GrantAllUris" severity="error"/>
|
|
||||||
<issue id="HandlerLeak" severity="error"/>
|
|
||||||
<issue id="HardcodedText" severity="error"/>
|
|
||||||
<issue id="IconColors" severity="warning"/>
|
|
||||||
<issue id="IconDensities" severity="warning"/>
|
|
||||||
<issue id="IconDipSize" severity="error"/>
|
|
||||||
<issue id="IconDuplicates" severity="error"/>
|
|
||||||
<issue id="IconDuplicatesConfig" severity="error"/>
|
|
||||||
<issue id="IconExtension" severity="error"/>
|
|
||||||
<issue id="IconLocation" severity="error"/>
|
|
||||||
<issue id="IconMixedNinePatch" severity="error"/>
|
|
||||||
<issue id="IconNoDpi" severity="error"/>
|
|
||||||
<issue id="IconXmlAndPng" severity="error"/>
|
|
||||||
<issue id="IllegalResourceRef" severity="error"/>
|
|
||||||
<issue id="InOrMmUsage" severity="error"/>
|
|
||||||
<issue id="InconsistentArrays" severity="error"/>
|
|
||||||
<issue id="InefficientWeight" severity="warning"/>
|
|
||||||
<issue id="InflateParams" severity="warning"/>
|
|
||||||
<issue id="InnerclassSeparator" severity="error"/>
|
|
||||||
<issue id="LocaleFolder" severity="error"/>
|
|
||||||
<issue id="LogConditional" severity="error"/>
|
|
||||||
<issue id="ManifestOrder" severity="error"/>
|
|
||||||
<issue id="MipmapIcons" severity="error"/>
|
|
||||||
<issue id="MissingApplicationIcon" severity="error"/>
|
|
||||||
<issue id="MissingId" severity="error"/>
|
|
||||||
<issue id="MissingVersion" severity="error"/>
|
|
||||||
<issue id="NestedWeights" severity="warning"/>
|
|
||||||
<issue id="ObsoleteLayoutParam" severity="error"/>
|
|
||||||
<issue id="OldTargetApi" severity="error"/>
|
|
||||||
<issue id="PackageManagerGetSignatures" severity="error"/>
|
|
||||||
<issue id="PrivateResource" severity="error"/>
|
|
||||||
<issue id="ProguardSplit" severity="error"/>
|
|
||||||
<issue id="PxUsage" severity="error"/>
|
|
||||||
<issue id="Recycle" severity="error"/>
|
|
||||||
<issue id="Registered" severity="error"/>
|
|
||||||
<issue id="RtlEnabled" severity="error"/>
|
|
||||||
<issue id="SQLiteString" severity="error"/>
|
|
||||||
<issue id="ScrollViewCount" severity="error"/>
|
|
||||||
<issue id="ScrollViewSize" severity="error"/>
|
|
||||||
<issue id="SdCardPath" severity="error"/>
|
|
||||||
<issue id="ShortAlarm" severity="warning"/>
|
|
||||||
<issue id="ShowToast" severity="error"/>
|
|
||||||
<issue id="SignatureOrSystemPermissions" severity="error"/>
|
|
||||||
<issue id="SimpleDateFormat" severity="error"/>
|
|
||||||
<issue id="SpUsage" severity="error"/>
|
|
||||||
<issue id="StateListReachable" severity="error"/>
|
|
||||||
<issue id="SuspiciousImport" severity="error"/>
|
|
||||||
<issue id="TextFields" severity="error"/>
|
|
||||||
<issue id="TextViewEdits" severity="error"/>
|
|
||||||
<issue id="TooDeepLayout" severity="warning"/>
|
|
||||||
<issue id="TooManyViews" severity="warning"/>
|
|
||||||
<issue id="TypographyDashes" severity="warning"/>
|
|
||||||
<issue id="UnknownIdInLayout" severity="error"/>
|
|
||||||
<issue id="UnlocalizedSms" severity="error"/>
|
|
||||||
<issue id="UnusedIds" severity="error"/>
|
|
||||||
<issue id="UseAlpha2" severity="error"/>
|
|
||||||
<issue id="UseSparseArrays" severity="warning"/>
|
|
||||||
<issue id="UseValueOf" severity="error"/>
|
|
||||||
<issue id="UsesMinSdkAttributes" severity="error"/>
|
|
||||||
<issue id="UsingHttp" severity="warning"/>
|
|
||||||
<issue id="WorldReadableFiles" severity="warning"/>
|
|
||||||
<issue id="WorldWriteableFiles" severity="warning"/>
|
|
||||||
<issue id="WrongRegion" severity="warning"/>
|
|
||||||
|
|
||||||
<!-- DISABLE RULES BELOW -->
|
|
||||||
<issue id="GoogleAppIndexingApiWarning" severity="ignore"/>
|
|
||||||
<issue id="GoogleAppIndexingUrlError" severity="ignore"/>
|
|
||||||
<issue id="GoogleAppIndexingWarning" severity="ignore"/>
|
|
||||||
<issue id="AppLinksAutoVerifyError" severity="ignore"/>
|
|
||||||
<issue id="AppLinksAutoVerifyWarning" severity="ignore"/>
|
|
||||||
<issue id="ClickableViewAccessibility" severity="ignore"/>
|
|
||||||
<issue id="SetTextI18n" severity="ignore"/>
|
|
||||||
<issue id="EasterEgg" severity="ignore"/>
|
|
||||||
<issue id="BackButton" severity="ignore"/>
|
|
||||||
<issue id="FieldGetter" severity="ignore"/>
|
|
||||||
<issue id="Orientation" severity="ignore"/>
|
|
||||||
<issue id="Suspicious0dp" severity="ignore"/>
|
|
||||||
<issue id="NegativeMargin" severity="ignore"/>
|
|
||||||
<issue id="MissingQuantity" severity="ignore"/>
|
|
||||||
<issue id="ImpliedQuantity" severity="ignore"/>
|
|
||||||
<issue id="TrulyRandom" severity="ignore"/>
|
|
||||||
<issue id="SelectableText" severity="ignore"/>
|
|
||||||
<issue id="UnusedIds" severity="ignore"/>
|
|
||||||
<issue id="ButtonCase" severity="ignore"/>
|
|
||||||
<issue id="ButtonOrder" severity="ignore"/>
|
|
||||||
<issue id="ButtonStyle" severity="ignore"/>
|
|
||||||
<issue id="ContentDescription" severity="ignore"/>
|
|
||||||
<issue id="ExportedPreferenceActivity" severity="ignore"/>
|
|
||||||
<!-- remove when facebook will update support library in sdk -->
|
|
||||||
<issue id="GradleCompatible" severity="ignore"/>
|
|
||||||
<issue id="IconLauncherShape" severity="ignore"/>
|
|
||||||
<issue id="IconMissingDensityFolder" severity="ignore"/>
|
|
||||||
<issue id="InconsistentLayout" severity="ignore"/>
|
|
||||||
<issue id="LabelFor" severity="ignore"/>
|
|
||||||
<issue id="MissingTranslation" severity="ignore"/>
|
|
||||||
<issue id="NestedScrolling" severity="ignore"/>
|
|
||||||
<issue id="MergeRootFrame" severity="ignore"/>
|
|
||||||
<issue id="NewApi" severity="ignore"/>
|
|
||||||
<issue id="Overdraw" severity="ignore"/>
|
|
||||||
<issue id="PluralsCandidate" severity="ignore"/>
|
|
||||||
<issue id="RelativeOverlap" severity="ignore"/>
|
|
||||||
<issue id="RtlHardcoded" severity="ignore"/>
|
|
||||||
<issue id="RtlSymmetry" severity="ignore"/>
|
|
||||||
<issue id="SmallSp" severity="ignore"/>
|
|
||||||
<issue id="StringFormatCount" severity="ignore"/>
|
|
||||||
<issue id="TypographyFractions" severity="ignore"/>
|
|
||||||
<issue id="Typos" severity="ignore"/>
|
|
||||||
<issue id="UnusedQuantity" severity="ignore"/>
|
|
||||||
<issue id="UnusedResources" severity="ignore"/>
|
|
||||||
<issue id="UseCompoundDrawables" severity="ignore"/>
|
|
||||||
<issue id="UselessLeaf" severity="ignore"/>
|
|
||||||
<issue id="UselessParent" severity="ignore"/>
|
|
||||||
<issue id="ViewConstructor" severity="ignore"/>
|
|
||||||
<issue id="ViewHolder" severity="ignore"/>
|
|
||||||
<issue id="WebViewLayout" severity="ignore"/>
|
|
||||||
<issue id="TypographyEllipsis" severity="ignore"/>
|
|
||||||
|
|
||||||
</lint>
|
|
||||||
|
|
@ -1,131 +0,0 @@
|
||||||
<?xml version="1.0"?>
|
|
||||||
|
|
||||||
<ruleset name="All Java Rules"
|
|
||||||
xmlns="http://pmd.sourceforge.net/ruleset/2.0.0"
|
|
||||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
|
||||||
xsi:schemaLocation="http://pmd.sourceforge.net/ruleset/2.0.0 http://pmd.sourceforge.net/ruleset_2_0_0.xsd">
|
|
||||||
<description>Every Java Rule in PMD</description>
|
|
||||||
|
|
||||||
<rule ref="rulesets/java/android.xml"/>
|
|
||||||
<rule ref="rulesets/java/basic.xml">
|
|
||||||
<exclude name="SimplifiedTernary"/>
|
|
||||||
</rule>
|
|
||||||
<rule ref="rulesets/java/braces.xml"/>
|
|
||||||
<rule ref="rulesets/java/clone.xml"/>
|
|
||||||
<rule ref="rulesets/java/codesize.xml"/>
|
|
||||||
<rule ref="rulesets/java/codesize.xml/TooManyMethods">
|
|
||||||
<properties>
|
|
||||||
<property name="maxmethods" value="20"/>
|
|
||||||
</properties>
|
|
||||||
</rule>
|
|
||||||
<rule ref="rulesets/java/codesize.xml/CyclomaticComplexity">
|
|
||||||
<properties>
|
|
||||||
<property name="showClassesComplexity" value="false"/>
|
|
||||||
<property name="violationSuppressXPath" value="./MethodDeclarator[@Image='hashCode' or @Image='equals']"/>
|
|
||||||
</properties>
|
|
||||||
</rule>
|
|
||||||
<rule ref="rulesets/java/codesize.xml/StdCyclomaticComplexity">
|
|
||||||
<properties>
|
|
||||||
<property name="showClassesComplexity" value="false"/>
|
|
||||||
<property name="violationSuppressXPath" value="./MethodDeclarator[@Image='hashCode' or @Image='equals']"/>
|
|
||||||
</properties>
|
|
||||||
</rule>
|
|
||||||
<rule ref="rulesets/java/codesize.xml/ModifiedCyclomaticComplexity">
|
|
||||||
<properties>
|
|
||||||
<property name="showClassesComplexity" value="false"/>
|
|
||||||
<property name="violationSuppressXPath" value="./MethodDeclarator[@Image='hashCode' or @Image='equals']"/>
|
|
||||||
</properties>
|
|
||||||
</rule>
|
|
||||||
<rule ref="rulesets/java/codesize.xml/NPathComplexity">
|
|
||||||
<properties>
|
|
||||||
<property name="violationSuppressXPath" value="./MethodDeclarator[@Image='hashCode' or @Image='equals']"/>
|
|
||||||
</properties>
|
|
||||||
</rule>
|
|
||||||
<rule ref="rulesets/java/comments.xml">
|
|
||||||
<exclude name="CommentSize"/>
|
|
||||||
<exclude name="CommentRequired"/>
|
|
||||||
<exclude name="CommentDefaultAccessModifier"/>
|
|
||||||
</rule>
|
|
||||||
<rule ref="rulesets/java/controversial.xml">
|
|
||||||
<exclude name="AtLeastOneConstructor"/>
|
|
||||||
<exclude name="OnlyOneReturn"/>
|
|
||||||
<exclude name="UseConcurrentHashMap"/>
|
|
||||||
<exclude name="NullAssignment"/>
|
|
||||||
<exclude name="DataflowAnomalyAnalysis"/>
|
|
||||||
<exclude name="AvoidFinalLocalVariable"/>
|
|
||||||
</rule>
|
|
||||||
<rule ref="rulesets/java/controversial.xml/AvoidLiteralsInIfCondition">
|
|
||||||
<properties>
|
|
||||||
<property name="ignoreMagicNumbers" value="-1,0,1"/>
|
|
||||||
</properties>
|
|
||||||
</rule>
|
|
||||||
<rule ref="rulesets/java/coupling.xml">
|
|
||||||
<exclude name="LoosePackageCoupling"/>
|
|
||||||
<exclude name="LawOfDemeter"/>
|
|
||||||
<exclude name="LooseCoupling"/>
|
|
||||||
</rule>
|
|
||||||
<rule ref="rulesets/java/coupling.xml/ExcessiveImports">
|
|
||||||
<properties>
|
|
||||||
<property name="minimum" value="50"/>
|
|
||||||
</properties>
|
|
||||||
</rule>
|
|
||||||
<rule ref="rulesets/java/design.xml">
|
|
||||||
<exclude name="GodClass"/>
|
|
||||||
<exclude name="ConfusingTernary"/>
|
|
||||||
<exclude name="ReturnEmptyArrayRatherThanNull"/>
|
|
||||||
<exclude name="FieldDeclarationsShouldBeAtStartOfClass"/>
|
|
||||||
<exclude name="EmptyMethodInAbstractClassShouldBeAbstract"/>
|
|
||||||
</rule>
|
|
||||||
<rule ref="rulesets/java/empty.xml"/>
|
|
||||||
<rule ref="rulesets/java/empty.xml/EmptyCatchBlock">
|
|
||||||
<properties>
|
|
||||||
<property name="allowCommentedBlocks" value="true"/>
|
|
||||||
</properties>
|
|
||||||
</rule>
|
|
||||||
<rule ref="rulesets/java/finalizers.xml"/>
|
|
||||||
<rule ref="rulesets/java/imports.xml"/>
|
|
||||||
<rule ref="rulesets/java/j2ee.xml">
|
|
||||||
<exclude name="DoNotUseThreads"/>
|
|
||||||
</rule>
|
|
||||||
<rule ref="rulesets/java/javabeans.xml">
|
|
||||||
<exclude name="BeanMembersShouldSerialize"/>
|
|
||||||
</rule>
|
|
||||||
<rule ref="rulesets/java/junit.xml"/>
|
|
||||||
<rule ref="rulesets/java/logging-jakarta-commons.xml">
|
|
||||||
<exclude name="GuardLogStatement"/>
|
|
||||||
</rule>
|
|
||||||
<rule ref="rulesets/java/logging-java.xml"/>
|
|
||||||
<rule ref="rulesets/java/migrating.xml"/>
|
|
||||||
<rule ref="rulesets/java/naming.xml">
|
|
||||||
<exclude name="SuspiciousEqualsMethodName"/>
|
|
||||||
<exclude name="AbstractNaming"/>
|
|
||||||
<exclude name="ShortVariable"/>
|
|
||||||
<exclude name="LongVariable"/>
|
|
||||||
<exclude name="GenericsNaming"/>
|
|
||||||
</rule>
|
|
||||||
<rule ref="rulesets/java/naming.xml/ShortClassName">
|
|
||||||
<properties>
|
|
||||||
<property name="minimum" value="4"/>
|
|
||||||
</properties>
|
|
||||||
</rule>
|
|
||||||
<rule ref="rulesets/java/optimizations.xml">
|
|
||||||
<exclude name="AvoidInstantiatingObjectsInLoops"/>
|
|
||||||
</rule>
|
|
||||||
<rule ref="rulesets/java/strictexception.xml">
|
|
||||||
<exclude name="AvoidCatchingGenericException"/>
|
|
||||||
<exclude name="SignatureDeclareThrowsException"/>
|
|
||||||
</rule>
|
|
||||||
<rule ref="rulesets/java/strings.xml"/>
|
|
||||||
<rule ref="rulesets/java/sunsecure.xml">
|
|
||||||
<exclude name="MethodReturnsInternalArray"/>
|
|
||||||
<exclude name="ArrayIsStoredDirectly"/>
|
|
||||||
</rule>
|
|
||||||
<rule ref="rulesets/java/typeresolution.xml">
|
|
||||||
<exclude name="SignatureDeclareThrowsException"/>
|
|
||||||
<exclude name="LooseCoupling"/>
|
|
||||||
</rule>
|
|
||||||
<rule ref="rulesets/java/unnecessary.xml">
|
|
||||||
<exclude name="UselessParentheses"/>
|
|
||||||
</rule>
|
|
||||||
<rule ref="rulesets/java/unusedcode.xml"/>
|
|
||||||
</ruleset>
|
|
||||||
|
|
@ -0,0 +1,9 @@
|
||||||
|
-include rules/components.pro
|
||||||
|
-include rules/okhttp.pro
|
||||||
|
-include rules/retrofit.pro
|
||||||
|
-include rules/logansquare.pro
|
||||||
|
-include rules/crashlytics.pro
|
||||||
|
-include rules/glide.pro
|
||||||
|
-include rules/kaspersky.pro
|
||||||
|
-include rules/appsflyer.pro
|
||||||
|
-include rules/moshi.pro
|
||||||
|
|
@ -0,0 +1,3 @@
|
||||||
|
-dontobfuscate
|
||||||
|
|
||||||
|
-include common.pro
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
-include common.pro
|
||||||
|
|
@ -0,0 +1,3 @@
|
||||||
|
-keepclassmembers class * extends com.google.crypto.tink.shaded.protobuf.GeneratedMessageLite {
|
||||||
|
<fields>;
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,5 @@
|
||||||
|
-dontwarn com.google.android.gms.iid.**
|
||||||
|
-keep class com.appsflyer.** { *; }
|
||||||
|
-dontwarn android.app.job.JobParameters
|
||||||
|
-dontwarn com.android.installreferrer.**
|
||||||
|
-dontwarn com.appsflyer.**
|
||||||
|
|
@ -0,0 +1,2 @@
|
||||||
|
# View controllers are created through reflection.
|
||||||
|
-keep class ** extends ru.touchin.roboswag.navigation_viewcontroller.viewcontrollers.ViewController { *; }
|
||||||
|
|
@ -0,0 +1,8 @@
|
||||||
|
# https://docs.fabric.io/android/crashlytics/dex-and-proguard.html
|
||||||
|
|
||||||
|
-keepattributes *Annotation*
|
||||||
|
-keepattributes SourceFile,LineNumberTable
|
||||||
|
-keep public class * extends java.lang.Exception
|
||||||
|
|
||||||
|
-keep class com.crashlytics.** { *; }
|
||||||
|
-dontwarn com.crashlytics.**
|
||||||
|
|
@ -0,0 +1,11 @@
|
||||||
|
# https://github.com/bumptech/glide/blob/master/library/proguard-rules.txt
|
||||||
|
|
||||||
|
-keep public class * implements com.bumptech.glide.module.GlideModule
|
||||||
|
-keep public class * extends com.bumptech.glide.module.AppGlideModule
|
||||||
|
-keep public enum com.bumptech.glide.load.ImageHeaderParser$** {
|
||||||
|
**[] $VALUES;
|
||||||
|
public *;
|
||||||
|
}
|
||||||
|
|
||||||
|
# Uncomment for DexGuard only
|
||||||
|
#-keepresourcexmlelements manifest/application/meta-data@value=GlideModule
|
||||||
|
|
@ -0,0 +1,8 @@
|
||||||
|
-dontwarn com.kavsdk.*
|
||||||
|
-keep class com.kavsdk.** { *; }
|
||||||
|
|
||||||
|
-dontwarn com.kaspersky.*
|
||||||
|
-keep class com.kaspersky.** { *; }
|
||||||
|
|
||||||
|
-dontwarn com.kms.*
|
||||||
|
-keep class com.kms.** { *; }
|
||||||
|
|
@ -0,0 +1,5 @@
|
||||||
|
-keep class com.bluelinelabs.logansquare.** { *; }
|
||||||
|
-keep @com.bluelinelabs.logansquare.annotation.JsonObject class *
|
||||||
|
-keep @com.bluelinelabs.logansquare.annotation.JsonEnum class *
|
||||||
|
-keep class **$$JsonObjectMapper { *; }
|
||||||
|
-keep class **$$JsonTypeConverter { *; }
|
||||||
|
|
@ -0,0 +1,23 @@
|
||||||
|
# JSR 305 annotations are for embedding nullability information.
|
||||||
|
-dontwarn javax.annotation.**
|
||||||
|
|
||||||
|
-keepclasseswithmembers class * {
|
||||||
|
@com.squareup.moshi.* <methods>;
|
||||||
|
}
|
||||||
|
|
||||||
|
-keep @com.squareup.moshi.JsonQualifier interface *
|
||||||
|
-keep @com.squareup.moshi.JsonQualifier class *
|
||||||
|
|
||||||
|
# Enum field names are used by the integrated EnumJsonAdapter.
|
||||||
|
# values() is synthesized by the Kotlin compiler and is used by EnumJsonAdapter indirectly
|
||||||
|
# Annotate enums with @JsonClass(generateAdapter = false) to use them with Moshi.
|
||||||
|
-keepclassmembers @com.squareup.moshi.JsonClass class * extends java.lang.Enum {
|
||||||
|
<fields>;
|
||||||
|
**[] values();
|
||||||
|
}
|
||||||
|
|
||||||
|
-keep class kotlin.reflect.jvm.internal.impl.builtins.BuiltInsLoaderImpl
|
||||||
|
|
||||||
|
-keepclassmembers class kotlin.Metadata {
|
||||||
|
public <methods>;
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,13 @@
|
||||||
|
# https://github.com/square/okhttp/blob/master/okhttp/src/main/resources/META-INF/proguard/okhttp3.pro
|
||||||
|
|
||||||
|
# JSR 305 annotations are for embedding nullability information.
|
||||||
|
-dontwarn javax.annotation.**
|
||||||
|
|
||||||
|
# A resource is loaded with a relative path so the package of this class must be preserved.
|
||||||
|
-keepnames class okhttp3.internal.publicsuffix.PublicSuffixDatabase
|
||||||
|
|
||||||
|
# Animal Sniffer compileOnly dependency to ensure APIs are compatible with older versions of Java.
|
||||||
|
-dontwarn org.codehaus.mojo.animal_sniffer.*
|
||||||
|
|
||||||
|
# OkHttp platform used only on JVM and when Conscrypt dependency is available.
|
||||||
|
-dontwarn okhttp3.internal.platform.ConscryptPlatform
|
||||||
|
|
@ -0,0 +1,22 @@
|
||||||
|
# https://github.com/square/retrofit/blob/master/retrofit/src/main/resources/META-INF/proguard/retrofit2.pro
|
||||||
|
|
||||||
|
# Retrofit does reflection on generic parameters. InnerClasses is required to use Signature and
|
||||||
|
# EnclosingMethod is required to use InnerClasses.
|
||||||
|
-keepattributes Signature, InnerClasses, EnclosingMethod
|
||||||
|
|
||||||
|
# Retain service method parameters when optimizing.
|
||||||
|
-keepclassmembers,allowshrinking,allowobfuscation interface * {
|
||||||
|
@retrofit2.http.* <methods>;
|
||||||
|
}
|
||||||
|
|
||||||
|
# Ignore annotation used for build tooling.
|
||||||
|
-dontwarn org.codehaus.mojo.animal_sniffer.IgnoreJRERequirement
|
||||||
|
|
||||||
|
# Ignore JSR 305 annotations for embedding nullability information.
|
||||||
|
-dontwarn javax.annotation.**
|
||||||
|
|
||||||
|
# Guarded by a NoClassDefFoundError try/catch and only used when on the classpath.
|
||||||
|
-dontwarn kotlin.Unit
|
||||||
|
|
||||||
|
# Top-level functions that can only be used by Kotlin.
|
||||||
|
-dontwarn retrofit2.-KotlinExtensions
|
||||||
|
|
@ -0,0 +1,71 @@
|
||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
# Description:
|
||||||
|
# Creates archive with source code of multiple repositories.
|
||||||
|
#
|
||||||
|
# Parameters:
|
||||||
|
# $1 - github repository name without suffix (project name).
|
||||||
|
# $2, $3, ..., $n - repository suffixes (platforms).
|
||||||
|
#
|
||||||
|
# Optional environment variables:
|
||||||
|
# GIT_BRANCH - branch to use. Default - master.
|
||||||
|
#
|
||||||
|
# Example of usage:
|
||||||
|
# export_src.sh TestProject ios android backend
|
||||||
|
# GIT_BRANCH="develop" ./export_src.sh TestProject ios web
|
||||||
|
#
|
||||||
|
|
||||||
|
if [ -z "${GIT_BRANCH}" ]; then
|
||||||
|
GIT_BRANCH="master"
|
||||||
|
fi
|
||||||
|
|
||||||
|
LAST_COMMIT_DATE=""
|
||||||
|
PROJECT_NAME=$1
|
||||||
|
SRC_FOLDER_NAME="${PROJECT_NAME}-src"
|
||||||
|
SRC_DIR="./${SRC_FOLDER_NAME}"
|
||||||
|
|
||||||
|
COMMAND_LINE_ARGUMENTS=$@
|
||||||
|
|
||||||
|
clone_platform() {
|
||||||
|
PROJECT_NAME=$1
|
||||||
|
PLATFORM=$2
|
||||||
|
|
||||||
|
if git clone --recurse-submodules -j8 "ssh://git@git.ti:7999/touchinstinct/${PROJECT_NAME}-${PLATFORM}.git" --branch "${GIT_BRANCH}"; then
|
||||||
|
cd ${PROJECT_NAME}-${PLATFORM}
|
||||||
|
|
||||||
|
COMMIT_DATE=`git log -1 --pretty='format:%cd' --date=format:'%Y-%m-%d'`
|
||||||
|
if [[ $LAST_COMMIT_DATE < $COMMIT_DATE ]]; then
|
||||||
|
LAST_COMMIT_DATE="${COMMIT_DATE}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
cd ..
|
||||||
|
else
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
mkdir -p "${SRC_DIR}"
|
||||||
|
cd "${SRC_DIR}"
|
||||||
|
|
||||||
|
for argument in ${COMMAND_LINE_ARGUMENTS}
|
||||||
|
do
|
||||||
|
if [ $argument != $PROJECT_NAME ]; then
|
||||||
|
platform=${argument} # all arguments after project name treated as platforms
|
||||||
|
clone_platform ${PROJECT_NAME} ${platform}
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
ERR_PATHS=$(find . -name "*[<>:\\|?*]*" | xargs -I %s echo "- %s")
|
||||||
|
if [ "$ERR_PATHS" ]; then
|
||||||
|
echo "Export aborted! Invalid characters found in file or directories name(s):\n$ERR_PATHS"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -z "${EXPORT_DATE}" ]; then
|
||||||
|
EXPORT_DATE="${LAST_COMMIT_DATE}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
find . -name ".git*" -print0 | xargs -0 rm -rf
|
||||||
|
zip -r -q "${SRC_FOLDER_NAME}-${EXPORT_DATE}".zip .
|
||||||
|
|
||||||
|
open .
|
||||||
|
|
@ -0,0 +1,396 @@
|
||||||
|
build:
|
||||||
|
# maxIssues: 10
|
||||||
|
weights:
|
||||||
|
# complexity: 2
|
||||||
|
# LongParameterList: 1
|
||||||
|
# style: 1
|
||||||
|
# comments: 1
|
||||||
|
|
||||||
|
processors:
|
||||||
|
active: true
|
||||||
|
exclude:
|
||||||
|
# - 'FunctionCountProcessor'
|
||||||
|
# - 'PropertyCountProcessor'
|
||||||
|
# - 'ClassCountProcessor'
|
||||||
|
# - 'PackageCountProcessor'
|
||||||
|
# - 'KtFileCountProcessor'
|
||||||
|
|
||||||
|
formatting:
|
||||||
|
active: true
|
||||||
|
android: true
|
||||||
|
autoCorrect: true
|
||||||
|
MaximumLineLength:
|
||||||
|
active: true
|
||||||
|
|
||||||
|
console-reports:
|
||||||
|
active: false
|
||||||
|
exclude:
|
||||||
|
# - 'ProjectStatisticsReport'
|
||||||
|
# - 'ComplexityReport'
|
||||||
|
# - 'NotificationReport'
|
||||||
|
# - 'FindingsReport'
|
||||||
|
# - 'BuildFailureReport'
|
||||||
|
|
||||||
|
comments:
|
||||||
|
active: false
|
||||||
|
CommentOverPrivateFunction:
|
||||||
|
active: false
|
||||||
|
CommentOverPrivateProperty:
|
||||||
|
active: false
|
||||||
|
EndOfSentenceFormat:
|
||||||
|
active: false
|
||||||
|
endOfSentenceFormat: ([.?!][ \t\n\r\f<])|([.?!]$)
|
||||||
|
UndocumentedPublicClass:
|
||||||
|
active: false
|
||||||
|
searchInNestedClass: true
|
||||||
|
searchInInnerClass: true
|
||||||
|
searchInInnerObject: true
|
||||||
|
searchInInnerInterface: true
|
||||||
|
UndocumentedPublicFunction:
|
||||||
|
active: false
|
||||||
|
|
||||||
|
complexity:
|
||||||
|
active: true
|
||||||
|
ComplexCondition:
|
||||||
|
active: true
|
||||||
|
threshold: 5
|
||||||
|
ComplexInterface:
|
||||||
|
active: false
|
||||||
|
threshold: 10
|
||||||
|
includeStaticDeclarations: false
|
||||||
|
ComplexMethod:
|
||||||
|
active: true
|
||||||
|
threshold: 10
|
||||||
|
ignoreSingleWhenExpression: true
|
||||||
|
ignoreSimpleWhenEntries: true
|
||||||
|
LabeledExpression:
|
||||||
|
active: true
|
||||||
|
LargeClass:
|
||||||
|
active: true
|
||||||
|
threshold: 800
|
||||||
|
LongMethod:
|
||||||
|
active: true
|
||||||
|
threshold: 40
|
||||||
|
LongParameterList:
|
||||||
|
active: true
|
||||||
|
threshold: 10
|
||||||
|
ignoreDefaultParameters: false
|
||||||
|
MethodOverloading:
|
||||||
|
active: false
|
||||||
|
threshold: 5
|
||||||
|
NestedBlockDepth:
|
||||||
|
active: true
|
||||||
|
threshold: 4
|
||||||
|
StringLiteralDuplication:
|
||||||
|
active: true
|
||||||
|
threshold: 3
|
||||||
|
ignoreAnnotation: true
|
||||||
|
excludeStringsWithLessThan5Characters: true
|
||||||
|
ignoreStringsRegex: '$^'
|
||||||
|
TooManyFunctions:
|
||||||
|
active: true
|
||||||
|
thresholdInFiles: 20
|
||||||
|
thresholdInClasses: 20
|
||||||
|
thresholdInInterfaces: 20
|
||||||
|
thresholdInObjects: 20
|
||||||
|
thresholdInEnums: 20
|
||||||
|
ignoreDeprecated: false
|
||||||
|
ignorePrivate: false
|
||||||
|
|
||||||
|
empty-blocks:
|
||||||
|
active: true
|
||||||
|
EmptyCatchBlock:
|
||||||
|
active: true
|
||||||
|
allowedExceptionNameRegex: "^(_|(ignore|expected).*)"
|
||||||
|
EmptyClassBlock:
|
||||||
|
active: true
|
||||||
|
EmptyDefaultConstructor:
|
||||||
|
active: false
|
||||||
|
EmptyDoWhileBlock:
|
||||||
|
active: true
|
||||||
|
EmptyElseBlock:
|
||||||
|
active: true
|
||||||
|
EmptyFinallyBlock:
|
||||||
|
active: true
|
||||||
|
EmptyForBlock:
|
||||||
|
active: true
|
||||||
|
EmptyFunctionBlock:
|
||||||
|
active: true
|
||||||
|
ignoreOverridden: false
|
||||||
|
EmptyIfBlock:
|
||||||
|
active: true
|
||||||
|
EmptyInitBlock:
|
||||||
|
active: true
|
||||||
|
EmptyKtFile:
|
||||||
|
active: true
|
||||||
|
EmptySecondaryConstructor:
|
||||||
|
active: true
|
||||||
|
EmptyWhenBlock:
|
||||||
|
active: true
|
||||||
|
EmptyWhileBlock:
|
||||||
|
active: true
|
||||||
|
|
||||||
|
exceptions:
|
||||||
|
active: true
|
||||||
|
ExceptionRaisedInUnexpectedLocation:
|
||||||
|
active: true
|
||||||
|
methodNames: 'toString,hashCode,equals,finalize'
|
||||||
|
InstanceOfCheckForException:
|
||||||
|
active: false
|
||||||
|
NotImplementedDeclaration:
|
||||||
|
active: true
|
||||||
|
PrintStackTrace:
|
||||||
|
active: true
|
||||||
|
RethrowCaughtException:
|
||||||
|
active: false
|
||||||
|
ReturnFromFinally:
|
||||||
|
active: false
|
||||||
|
SwallowedException:
|
||||||
|
active: false
|
||||||
|
ThrowingExceptionFromFinally:
|
||||||
|
active: false
|
||||||
|
ThrowingExceptionInMain:
|
||||||
|
active: false
|
||||||
|
ThrowingExceptionsWithoutMessageOrCause:
|
||||||
|
active: true
|
||||||
|
exceptions: 'IllegalArgumentException,IllegalStateException,IOException'
|
||||||
|
ThrowingNewInstanceOfSameException:
|
||||||
|
active: false
|
||||||
|
TooGenericExceptionCaught:
|
||||||
|
active: true
|
||||||
|
exceptionNames:
|
||||||
|
- ArrayIndexOutOfBoundsException
|
||||||
|
- Error
|
||||||
|
- Exception
|
||||||
|
- IllegalMonitorStateException
|
||||||
|
- NullPointerException
|
||||||
|
- IndexOutOfBoundsException
|
||||||
|
- RuntimeException
|
||||||
|
- Throwable
|
||||||
|
allowedExceptionNameRegex: "^(_|(ignore|expected).*)"
|
||||||
|
TooGenericExceptionThrown:
|
||||||
|
active: true
|
||||||
|
exceptionNames:
|
||||||
|
- Error
|
||||||
|
- Exception
|
||||||
|
- Throwable
|
||||||
|
- RuntimeException
|
||||||
|
|
||||||
|
naming:
|
||||||
|
active: true
|
||||||
|
ClassNaming:
|
||||||
|
active: true
|
||||||
|
classPattern: '[A-Z$][a-zA-Z0-9$]*'
|
||||||
|
ConstructorParameterNaming:
|
||||||
|
active: true
|
||||||
|
parameterPattern: '[a-z][A-Za-z0-9]*'
|
||||||
|
privateParameterPattern: '[a-z][A-Za-z0-9]*'
|
||||||
|
excludeClassPattern: '$^'
|
||||||
|
EnumNaming:
|
||||||
|
active: true
|
||||||
|
enumEntryPattern: '^[A-Z][_a-zA-Z0-9]*'
|
||||||
|
ForbiddenClassName:
|
||||||
|
active: false
|
||||||
|
forbiddenName: ''
|
||||||
|
FunctionMaxLength:
|
||||||
|
active: false
|
||||||
|
maximumFunctionNameLength: 30
|
||||||
|
FunctionMinLength:
|
||||||
|
active: false
|
||||||
|
minimumFunctionNameLength: 3
|
||||||
|
FunctionNaming:
|
||||||
|
active: true
|
||||||
|
functionPattern: '^([a-z$][a-zA-Z$0-9]*)|(`.*`)$'
|
||||||
|
excludeClassPattern: '$^'
|
||||||
|
ignoreOverridden: true
|
||||||
|
FunctionParameterNaming:
|
||||||
|
active: true
|
||||||
|
parameterPattern: '[a-z][A-Za-z0-9]*'
|
||||||
|
excludeClassPattern: '$^'
|
||||||
|
ignoreOverridden: true
|
||||||
|
MatchingDeclarationName:
|
||||||
|
active: true
|
||||||
|
MemberNameEqualsClassName:
|
||||||
|
active: false
|
||||||
|
ignoreOverridden: true
|
||||||
|
ObjectPropertyNaming:
|
||||||
|
active: true
|
||||||
|
constantPattern: '[A-Za-z][_A-Za-z0-9]*'
|
||||||
|
propertyPattern: '[A-Za-z][_A-Za-z0-9]*'
|
||||||
|
privatePropertyPattern: '[A-Za-z][_A-Za-z0-9]*'
|
||||||
|
PackageNaming:
|
||||||
|
active: false
|
||||||
|
packagePattern: '^[a-z]+(\.[a-z][a-z0-9]*)*$'
|
||||||
|
TopLevelPropertyNaming:
|
||||||
|
active: true
|
||||||
|
constantPattern: '[A-Z][_A-Z0-9]*'
|
||||||
|
propertyPattern: '[A-Za-z][_A-Za-z0-9]*'
|
||||||
|
privatePropertyPattern: '[A-Za-z][_A-Za-z0-9]*'
|
||||||
|
VariableMaxLength:
|
||||||
|
active: false
|
||||||
|
maximumVariableNameLength: 64
|
||||||
|
VariableMinLength:
|
||||||
|
active: false
|
||||||
|
minimumVariableNameLength: 1
|
||||||
|
VariableNaming:
|
||||||
|
active: true
|
||||||
|
variablePattern: '[a-z][A-Za-z0-9]*'
|
||||||
|
privateVariablePattern: '(_)?[a-z][A-Za-z0-9]*'
|
||||||
|
excludeClassPattern: '$^'
|
||||||
|
ignoreOverridden: true
|
||||||
|
|
||||||
|
performance:
|
||||||
|
active: true
|
||||||
|
ArrayPrimitive:
|
||||||
|
active: false
|
||||||
|
ForEachOnRange:
|
||||||
|
active: true
|
||||||
|
SpreadOperator:
|
||||||
|
active: false
|
||||||
|
UnnecessaryTemporaryInstantiation:
|
||||||
|
active: true
|
||||||
|
|
||||||
|
potential-bugs:
|
||||||
|
active: true
|
||||||
|
DuplicateCaseInWhenExpression:
|
||||||
|
active: true
|
||||||
|
EqualsAlwaysReturnsTrueOrFalse:
|
||||||
|
active: false
|
||||||
|
EqualsWithHashCodeExist:
|
||||||
|
active: true
|
||||||
|
ExplicitGarbageCollectionCall:
|
||||||
|
active: true
|
||||||
|
InvalidRange:
|
||||||
|
active: true
|
||||||
|
IteratorHasNextCallsNextMethod:
|
||||||
|
active: false
|
||||||
|
IteratorNotThrowingNoSuchElementException:
|
||||||
|
active: false
|
||||||
|
LateinitUsage:
|
||||||
|
active: false
|
||||||
|
excludeAnnotatedProperties: ""
|
||||||
|
ignoreOnClassesPattern: ""
|
||||||
|
UnconditionalJumpStatementInLoop:
|
||||||
|
active: false
|
||||||
|
UnreachableCode:
|
||||||
|
active: true
|
||||||
|
UnsafeCallOnNullableType:
|
||||||
|
active: false
|
||||||
|
UnsafeCast:
|
||||||
|
active: false
|
||||||
|
UselessPostfixExpression:
|
||||||
|
active: false
|
||||||
|
WrongEqualsTypeParameter:
|
||||||
|
active: false
|
||||||
|
|
||||||
|
style:
|
||||||
|
active: true
|
||||||
|
CollapsibleIfStatements:
|
||||||
|
active: false
|
||||||
|
DataClassContainsFunctions:
|
||||||
|
active: false
|
||||||
|
conversionFunctionPrefix: 'to'
|
||||||
|
EqualsNullCall:
|
||||||
|
active: true
|
||||||
|
ExplicitItLambdaParameter:
|
||||||
|
active: true
|
||||||
|
ExpressionBodySyntax:
|
||||||
|
active: true
|
||||||
|
includeLineWrapping: false
|
||||||
|
ForbiddenComment:
|
||||||
|
active: true
|
||||||
|
values: 'STOPSHIP:'
|
||||||
|
ForbiddenImport:
|
||||||
|
active: false
|
||||||
|
imports: ''
|
||||||
|
ForbiddenVoid:
|
||||||
|
active: false
|
||||||
|
FunctionOnlyReturningConstant:
|
||||||
|
active: false
|
||||||
|
ignoreOverridableFunction: true
|
||||||
|
excludedFunctions: 'describeContents'
|
||||||
|
LoopWithTooManyJumpStatements:
|
||||||
|
active: false
|
||||||
|
maxJumpCount: 1
|
||||||
|
MagicNumber:
|
||||||
|
active: false
|
||||||
|
ignoreNumbers: '-1,0,1,2'
|
||||||
|
ignoreHashCodeFunction: true
|
||||||
|
ignorePropertyDeclaration: false
|
||||||
|
ignoreConstantDeclaration: true
|
||||||
|
ignoreCompanionObjectPropertyDeclaration: true
|
||||||
|
ignoreAnnotation: false
|
||||||
|
ignoreNamedArgument: true
|
||||||
|
ignoreEnums: false
|
||||||
|
MandatoryBracesIfStatements:
|
||||||
|
active: true
|
||||||
|
MaxLineLength:
|
||||||
|
active: true
|
||||||
|
maxLineLength: 150
|
||||||
|
excludePackageStatements: true
|
||||||
|
excludeImportStatements: true
|
||||||
|
excludeCommentStatements: false
|
||||||
|
MayBeConst:
|
||||||
|
active: true
|
||||||
|
ModifierOrder:
|
||||||
|
active: true
|
||||||
|
NestedClassesVisibility:
|
||||||
|
active: false
|
||||||
|
NewLineAtEndOfFile:
|
||||||
|
active: true
|
||||||
|
NoTabs:
|
||||||
|
active: true
|
||||||
|
OptionalAbstractKeyword:
|
||||||
|
active: true
|
||||||
|
OptionalUnit:
|
||||||
|
active: false
|
||||||
|
OptionalWhenBraces:
|
||||||
|
active: false
|
||||||
|
PreferToOverPairSyntax:
|
||||||
|
active: true
|
||||||
|
ProtectedMemberInFinalClass:
|
||||||
|
active: true
|
||||||
|
RedundantVisibilityModifierRule:
|
||||||
|
active: true
|
||||||
|
ReturnCount:
|
||||||
|
active: true
|
||||||
|
max: 3
|
||||||
|
excludedFunctions: "equals"
|
||||||
|
SafeCast:
|
||||||
|
active: true
|
||||||
|
SerialVersionUIDInSerializableClass:
|
||||||
|
active: false
|
||||||
|
SpacingBetweenPackageAndImports:
|
||||||
|
active: true
|
||||||
|
ThrowsCount:
|
||||||
|
active: true
|
||||||
|
max: 3
|
||||||
|
TrailingWhitespace:
|
||||||
|
active: true
|
||||||
|
UnnecessaryAbstractClass:
|
||||||
|
active: false
|
||||||
|
excludeAnnotatedClasses: "dagger.Module"
|
||||||
|
UnnecessaryApply:
|
||||||
|
active: true
|
||||||
|
UnnecessaryInheritance:
|
||||||
|
active: true
|
||||||
|
UnnecessaryLet:
|
||||||
|
active: true
|
||||||
|
UnnecessaryParentheses:
|
||||||
|
active: true
|
||||||
|
UntilInsteadOfRangeTo:
|
||||||
|
active: true
|
||||||
|
UnusedImports:
|
||||||
|
active: true
|
||||||
|
UnusedPrivateClass:
|
||||||
|
active: true
|
||||||
|
UnusedPrivateMember:
|
||||||
|
active: true
|
||||||
|
allowedNames: "(_|ignored|expected|serialVersionUID)"
|
||||||
|
UtilityClassWithPublicConstructor:
|
||||||
|
active: false
|
||||||
|
VarCouldBeVal:
|
||||||
|
active: true
|
||||||
|
WildcardImport:
|
||||||
|
active: true
|
||||||
|
excludeImports: 'java.util.*,kotlinx.android.synthetic.*'
|
||||||
|
|
@ -0,0 +1,273 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<lint>
|
||||||
|
|
||||||
|
<issue id="InvalidPackage" severity="error">
|
||||||
|
<ignore regexp="Invalid package reference in library.*not included in Android.*java.*" />
|
||||||
|
</issue>
|
||||||
|
<issue id="GradleCompatible" severity="error">
|
||||||
|
<ignore
|
||||||
|
regexp="All com.android.support libraries must use the exact same version specification (mixing versions can lead to runtime crashes). Found versions *. Examples include *" />
|
||||||
|
</issue>
|
||||||
|
<!-- todo: lint bug? -->
|
||||||
|
<issue id="MissingPermission" severity="ignore" />
|
||||||
|
<!-- todo: lint bug? -->
|
||||||
|
<issue id="MissingSuperCall" severity="ignore" />
|
||||||
|
|
||||||
|
<!--All activities should have locked orientation-->
|
||||||
|
<issue id="LockedOrientationActivity" severity="ignore" />
|
||||||
|
|
||||||
|
<issue id="AllowAllHostnameVerifier" severity="error" />
|
||||||
|
<issue id="InvalidUsesTagAttribute" severity="error" />
|
||||||
|
<issue id="MissingIntentFilterForMediaSearch" severity="error" />
|
||||||
|
<issue id="MissingMediaBrowserServiceIntentFilter" severity="error" />
|
||||||
|
<issue id="MissingOnPlayFromSearch" severity="error" />
|
||||||
|
<issue id="ShiftFlags" severity="error" />
|
||||||
|
<issue id="LocalSuppress" severity="error" />
|
||||||
|
<issue id="SwitchIntDef" severity="error" />
|
||||||
|
<issue id="UniqueConstants" severity="error" />
|
||||||
|
<issue id="InlinedApi" severity="error" />
|
||||||
|
<issue id="Override" severity="error" />
|
||||||
|
<issue id="UnusedAttribute" severity="warning" />
|
||||||
|
<issue id="AppCompatResource" severity="error" />
|
||||||
|
<issue id="BadHostnameVerifier" severity="error" />
|
||||||
|
<issue id="EnforceUTF8" severity="error" />
|
||||||
|
<issue id="ByteOrderMark" severity="error" />
|
||||||
|
<issue id="StopShip" severity="error" />
|
||||||
|
<issue id="MissingPrefix" severity="error" />
|
||||||
|
<issue id="MangledCRLF" severity="error" />
|
||||||
|
<issue id="DuplicateIds" severity="error" />
|
||||||
|
<issue id="DuplicateDefinition" severity="error" />
|
||||||
|
<issue id="ReferenceType" severity="error" />
|
||||||
|
<issue id="UnsafeDynamicallyLoadedCode" severity="error" />
|
||||||
|
<issue id="UnsafeNativeCodeLocation" severity="error" />
|
||||||
|
<issue id="FullBackupContent" severity="error" />
|
||||||
|
<issue id="ValidFragment" severity="error" />
|
||||||
|
<issue id="GradleCompatible" severity="error" />
|
||||||
|
<issue id="GradlePluginVersion" severity="error" />
|
||||||
|
<issue id="GradleGetter" severity="error" />
|
||||||
|
<issue id="GradleIdeError" severity="error" />
|
||||||
|
<issue id="NotInterpolated" severity="error" />
|
||||||
|
<issue id="StringShouldBeInt" severity="error" />
|
||||||
|
<issue id="AccidentalOctal" severity="error" />
|
||||||
|
<issue id="GridLayout" severity="error" />
|
||||||
|
<issue id="HardcodedDebugMode" severity="error" />
|
||||||
|
<issue id="IconExpectedSize" severity="error" />
|
||||||
|
<issue id="IncludeLayoutParam" severity="error" />
|
||||||
|
<issue id="TrustAllX509TrustManager" severity="warning" />
|
||||||
|
<issue id="DefaultLocale" severity="error" />
|
||||||
|
<issue id="InvalidResourceFolder" severity="error" />
|
||||||
|
<issue id="LongLogTag" severity="error" />
|
||||||
|
<issue id="LogTagMismatch" severity="error" />
|
||||||
|
<issue id="DuplicateActivity" severity="error" />
|
||||||
|
<issue id="MockLocation" severity="error" />
|
||||||
|
<issue id="MultipleUsesSdk" severity="error" />
|
||||||
|
<issue id="UniquePermission" severity="error" />
|
||||||
|
<issue id="WrongManifestParent" severity="error" />
|
||||||
|
<issue id="ManifestResource" severity="error" />
|
||||||
|
<issue id="ManifestTypo" severity="error" />
|
||||||
|
<issue id="Instantiatable" severity="error" />
|
||||||
|
<issue id="LibraryCustomView" severity="error" />
|
||||||
|
<issue id="ResAuto" severity="error" />
|
||||||
|
<issue id="NamespaceTypo" severity="error" />
|
||||||
|
<issue id="UnusedNamespace" severity="error" />
|
||||||
|
<issue id="NfcTechWhitespace" severity="error" />
|
||||||
|
<issue id="OnClick" severity="error" />
|
||||||
|
<issue id="DalvikOverride" severity="error" />
|
||||||
|
<issue id="OverrideAbstract" severity="error" />
|
||||||
|
<issue id="ParcelCreator" severity="error" />
|
||||||
|
<issue id="PackagedPrivateKey" severity="error" />
|
||||||
|
<issue id="Proguard" severity="error" />
|
||||||
|
<issue id="PropertyEscape" severity="error" />
|
||||||
|
<issue id="ParcelClassLoader" severity="error" />
|
||||||
|
<issue id="RecyclerView" severity="error" />
|
||||||
|
<issue id="RequiredSize" severity="error" />
|
||||||
|
<issue id="AaptCrash" severity="error" />
|
||||||
|
<issue id="ResourceCycle" severity="error" />
|
||||||
|
<issue id="ResourceName" severity="error" />
|
||||||
|
<issue id="ValidRestrictions" severity="error" />
|
||||||
|
<issue id="RtlCompat" severity="error" />
|
||||||
|
<issue id="ScrollViewSize" severity="error" />
|
||||||
|
<issue id="SecureRandom" severity="error" />
|
||||||
|
<issue id="SetWorldReadable" severity="error" />
|
||||||
|
<issue id="SetWorldWritable" severity="error" />
|
||||||
|
<issue id="ServiceCast" severity="error" />
|
||||||
|
<issue id="SSLCertificateSocketFactoryCreateSocket" severity="error" />
|
||||||
|
<issue id="SSLCertificateSocketFactoryGetInsecure" severity="error" />
|
||||||
|
<issue id="StringFormatMatches" severity="error" />
|
||||||
|
<issue id="StringFormatInvalid" severity="error" />
|
||||||
|
<issue id="UseCheckPermission" severity="error" />
|
||||||
|
<issue id="CheckResult" severity="warning" />
|
||||||
|
<issue id="ResourceAsColor" severity="error" />
|
||||||
|
<issue id="Range" severity="error" />
|
||||||
|
<issue id="ResourceType" severity="warning" />
|
||||||
|
<issue id="WrongThread" severity="error" />
|
||||||
|
<issue id="WrongConstant" severity="error" />
|
||||||
|
<issue id="ProtectedPermissions" severity="error" />
|
||||||
|
<issue id="MenuTitle" severity="error" />
|
||||||
|
<issue id="ExtraTranslation" severity="error" />
|
||||||
|
<issue id="MissingLeanbackLauncher" severity="error" />
|
||||||
|
<issue id="MissingLeanbackSupport" severity="error" />
|
||||||
|
<issue id="PermissionImpliesUnsupportedHardware" severity="error" />
|
||||||
|
<issue id="UnsupportedTvHardware" severity="error" />
|
||||||
|
<issue id="MissingTvBanner" severity="error" />
|
||||||
|
<issue id="TypographyOther" severity="error" />
|
||||||
|
<issue id="TypographyQuotes" severity="warning" />
|
||||||
|
<issue id="UnsafeProtectedBroadcastReceiver" severity="error" />
|
||||||
|
<issue id="UnprotectedSMSBroadcastReceiver" severity="error" />
|
||||||
|
<issue id="VectorRaster" severity="error" />
|
||||||
|
<issue id="ViewTag" severity="error" />
|
||||||
|
<issue id="WrongViewCast" severity="error" />
|
||||||
|
<issue id="Wakelock" severity="error" />
|
||||||
|
<issue id="WrongCall" severity="error" />
|
||||||
|
<issue id="WrongCase" severity="error" />
|
||||||
|
<issue id="InvalidId" severity="error" />
|
||||||
|
<issue id="NotSibling" severity="error" />
|
||||||
|
<issue id="UnknownIdInLayout" severity="error" />
|
||||||
|
<issue id="WrongFolder" severity="error" />
|
||||||
|
<issue id="AdapterViewChildren" severity="error" />
|
||||||
|
<issue id="SetJavaScriptEnabled" severity="warning" />
|
||||||
|
<issue id="AddJavascriptInterface" severity="warning" />
|
||||||
|
<issue id="AllowBackup" severity="error" />
|
||||||
|
<issue id="AlwaysShowAction" severity="error" />
|
||||||
|
<issue id="AppCompatMethod" severity="error" />
|
||||||
|
<issue id="Assert" severity="error" />
|
||||||
|
<issue id="CommitPrefEdits" severity="error" />
|
||||||
|
<issue id="CommitTransaction" severity="error" />
|
||||||
|
<issue id="CustomViewStyleable" severity="error" />
|
||||||
|
<issue id="CutPasteId" severity="error" />
|
||||||
|
<issue id="Deprecated" severity="error" />
|
||||||
|
<issue id="DeviceAdmin" severity="error" />
|
||||||
|
<issue id="DisableBaselineAlignment" severity="error" />
|
||||||
|
<issue id="DrawAllocation" severity="warning" />
|
||||||
|
<issue id="DuplicateIncludedIds" severity="error" />
|
||||||
|
<issue id="DuplicateUsesFeature" severity="error" />
|
||||||
|
<issue id="ExportedContentProvider" severity="error" />
|
||||||
|
<issue id="ExportedReceiver" severity="error" />
|
||||||
|
<issue id="ExportedService" severity="error" />
|
||||||
|
<issue id="ExtraText" severity="error" />
|
||||||
|
<issue id="GetInstance" severity="error" />
|
||||||
|
<issue id="GifUsage" severity="warning" />
|
||||||
|
<issue id="GradleDependency" severity="warning" />
|
||||||
|
<issue id="GradleDeprecated" severity="error" />
|
||||||
|
<issue id="GradleDynamicVersion" severity="error" />
|
||||||
|
<issue id="GradleOverrides" severity="error" />
|
||||||
|
<issue id="GradlePath" severity="warning" />
|
||||||
|
<issue id="GrantAllUris" severity="error" />
|
||||||
|
<issue id="HandlerLeak" severity="error" />
|
||||||
|
<issue id="HardcodedText" severity="error" />
|
||||||
|
<issue id="IconColors" severity="warning" />
|
||||||
|
<issue id="IconDensities" severity="warning" />
|
||||||
|
<issue id="IconDipSize" severity="error" />
|
||||||
|
<issue id="IconDuplicates" severity="error" />
|
||||||
|
<issue id="IconDuplicatesConfig" severity="error" />
|
||||||
|
<issue id="IconExtension" severity="error" />
|
||||||
|
<issue id="IconLocation" severity="error" />
|
||||||
|
<issue id="IconMixedNinePatch" severity="error" />
|
||||||
|
<issue id="IconNoDpi" severity="error" />
|
||||||
|
<issue id="IconXmlAndPng" severity="error" />
|
||||||
|
<issue id="IllegalResourceRef" severity="error" />
|
||||||
|
<issue id="InOrMmUsage" severity="error" />
|
||||||
|
<issue id="InconsistentArrays" severity="error" />
|
||||||
|
<issue id="InefficientWeight" severity="warning" />
|
||||||
|
<issue id="InflateParams" severity="warning" />
|
||||||
|
<issue id="InnerclassSeparator" severity="error" />
|
||||||
|
<issue id="LocaleFolder" severity="error" />
|
||||||
|
<issue id="LogConditional" severity="error" />
|
||||||
|
<issue id="ManifestOrder" severity="error" />
|
||||||
|
<issue id="MipmapIcons" severity="error" />
|
||||||
|
<issue id="MissingApplicationIcon" severity="error" />
|
||||||
|
<issue id="MissingId" severity="error" />
|
||||||
|
<issue id="MissingVersion" severity="error" />
|
||||||
|
<issue id="NestedWeights" severity="warning" />
|
||||||
|
<issue id="NewerVersionAvailable" severity="warning" />
|
||||||
|
<issue id="ObsoleteLayoutParam" severity="error" />
|
||||||
|
<issue id="OldTargetApi" severity="error" />
|
||||||
|
<issue id="PackageManagerGetSignatures" severity="error" />
|
||||||
|
<issue id="PrivateResource" severity="error" />
|
||||||
|
<issue id="ProguardSplit" severity="error" />
|
||||||
|
<issue id="PxUsage" severity="error" />
|
||||||
|
<issue id="Recycle" severity="error" />
|
||||||
|
<issue id="Registered" severity="error" />
|
||||||
|
<issue id="RtlEnabled" severity="error" />
|
||||||
|
<issue id="SQLiteString" severity="error" />
|
||||||
|
<issue id="ScrollViewCount" severity="error" />
|
||||||
|
<issue id="ScrollViewSize" severity="error" />
|
||||||
|
<issue id="SdCardPath" severity="error" />
|
||||||
|
<issue id="ShortAlarm" severity="warning" />
|
||||||
|
<issue id="ShowToast" severity="error" />
|
||||||
|
<issue id="SignatureOrSystemPermissions" severity="error" />
|
||||||
|
<issue id="SimpleDateFormat" severity="error" />
|
||||||
|
<issue id="SpUsage" severity="error" />
|
||||||
|
<issue id="StateListReachable" severity="error" />
|
||||||
|
<issue id="SuspiciousImport" severity="error" />
|
||||||
|
<issue id="TextFields" severity="error" />
|
||||||
|
<issue id="TextViewEdits" severity="error" />
|
||||||
|
<issue id="TooDeepLayout" severity="warning" />
|
||||||
|
<issue id="TooManyViews" severity="warning" />
|
||||||
|
<issue id="TypographyDashes" severity="warning" />
|
||||||
|
<issue id="UnknownIdInLayout" severity="error" />
|
||||||
|
<issue id="UnlocalizedSms" severity="error" />
|
||||||
|
<issue id="UnusedIds" severity="error" />
|
||||||
|
<issue id="UseAlpha2" severity="error" />
|
||||||
|
<issue id="UseSparseArrays" severity="warning" />
|
||||||
|
<issue id="UseValueOf" severity="error" />
|
||||||
|
<issue id="UsesMinSdkAttributes" severity="error" />
|
||||||
|
<issue id="UsingHttp" severity="warning" />
|
||||||
|
<issue id="WorldReadableFiles" severity="warning" />
|
||||||
|
<issue id="WorldWriteableFiles" severity="warning" />
|
||||||
|
<issue id="WrongRegion" severity="warning" />
|
||||||
|
|
||||||
|
<!-- DISABLE RULES BELOW -->
|
||||||
|
<issue id="GoogleAppIndexingApiWarning" severity="ignore" />
|
||||||
|
<issue id="GoogleAppIndexingWarning" severity="ignore" />
|
||||||
|
<issue id="AppLinksAutoVerifyError" severity="ignore" />
|
||||||
|
<issue id="AppLinksAutoVerifyWarning" severity="ignore" />
|
||||||
|
<issue id="ClickableViewAccessibility" severity="ignore" />
|
||||||
|
<issue id="SetTextI18n" severity="ignore" />
|
||||||
|
<issue id="EasterEgg" severity="ignore" />
|
||||||
|
<issue id="BackButton" severity="ignore" />
|
||||||
|
<issue id="FieldGetter" severity="ignore" />
|
||||||
|
<issue id="Orientation" severity="ignore" />
|
||||||
|
<issue id="Suspicious0dp" severity="ignore" />
|
||||||
|
<issue id="NegativeMargin" severity="ignore" />
|
||||||
|
<issue id="MissingQuantity" severity="ignore" />
|
||||||
|
<issue id="ImpliedQuantity" severity="ignore" />
|
||||||
|
<issue id="TrulyRandom" severity="ignore" />
|
||||||
|
<issue id="SelectableText" severity="ignore" />
|
||||||
|
<issue id="UnusedIds" severity="ignore" />
|
||||||
|
<issue id="ButtonCase" severity="ignore" />
|
||||||
|
<issue id="ButtonOrder" severity="ignore" />
|
||||||
|
<issue id="ButtonStyle" severity="ignore" />
|
||||||
|
<issue id="ContentDescription" severity="ignore" />
|
||||||
|
<issue id="ExportedPreferenceActivity" severity="ignore" />
|
||||||
|
<!-- remove when facebook will update support library in sdk -->
|
||||||
|
<issue id="GradleCompatible" severity="ignore" />
|
||||||
|
<issue id="IconLauncherShape" severity="ignore" />
|
||||||
|
<issue id="IconMissingDensityFolder" severity="ignore" />
|
||||||
|
<issue id="InconsistentLayout" severity="ignore" />
|
||||||
|
<issue id="LabelFor" severity="ignore" />
|
||||||
|
<issue id="MissingTranslation" severity="ignore" />
|
||||||
|
<issue id="NestedScrolling" severity="ignore" />
|
||||||
|
<issue id="MergeRootFrame" severity="ignore" />
|
||||||
|
<issue id="NewApi" severity="ignore" />
|
||||||
|
<issue id="Overdraw" severity="ignore" />
|
||||||
|
<issue id="PluralsCandidate" severity="ignore" />
|
||||||
|
<issue id="RelativeOverlap" severity="ignore" />
|
||||||
|
<issue id="RtlHardcoded" severity="ignore" />
|
||||||
|
<issue id="RtlSymmetry" severity="ignore" />
|
||||||
|
<issue id="SmallSp" severity="ignore" />
|
||||||
|
<issue id="StringFormatCount" severity="ignore" />
|
||||||
|
<issue id="TypographyFractions" severity="ignore" />
|
||||||
|
<issue id="Typos" severity="ignore" />
|
||||||
|
<issue id="UnusedQuantity" severity="ignore" />
|
||||||
|
<issue id="UnusedResources" severity="ignore" />
|
||||||
|
<issue id="UseCompoundDrawables" severity="ignore" />
|
||||||
|
<issue id="UselessLeaf" severity="ignore" />
|
||||||
|
<issue id="UselessParent" severity="ignore" />
|
||||||
|
<issue id="ViewConstructor" severity="ignore" />
|
||||||
|
<issue id="ViewHolder" severity="ignore" />
|
||||||
|
<issue id="WebViewLayout" severity="ignore" />
|
||||||
|
<issue id="TypographyEllipsis" severity="ignore" />
|
||||||
|
<issue id="PermissionImpliesUnsupportedChromeOsHardware" severity="ignore" />
|
||||||
|
|
||||||
|
</lint>
|
||||||
|
|
@ -0,0 +1,285 @@
|
||||||
|
opt_in_rules:
|
||||||
|
|
||||||
|
# performance
|
||||||
|
|
||||||
|
- first_where
|
||||||
|
- last_where
|
||||||
|
- empty_string
|
||||||
|
- empty_count
|
||||||
|
- contains_over_filter_count
|
||||||
|
- contains_over_filter_is_empty
|
||||||
|
- empty_collection_literal
|
||||||
|
- contains_over_range_nil_comparison
|
||||||
|
- contains_over_first_not_nil
|
||||||
|
- flatmap_over_map_reduce
|
||||||
|
|
||||||
|
# idiomatic
|
||||||
|
|
||||||
|
- legacy_multiple
|
||||||
|
- pattern_matching_keywords
|
||||||
|
- redundant_nil_coalescing
|
||||||
|
- redundant_type_annotation
|
||||||
|
- static_operator
|
||||||
|
- toggle_bool
|
||||||
|
- joined_default_parameter
|
||||||
|
- implicitly_unwrapped_optional
|
||||||
|
- convenience_type
|
||||||
|
- object_literal
|
||||||
|
- force_unwrapping
|
||||||
|
- force_cast
|
||||||
|
- force_try
|
||||||
|
- fatal_error_message
|
||||||
|
- extension_access_modifier
|
||||||
|
- explicit_init
|
||||||
|
- fallthrough
|
||||||
|
- unavailable_function
|
||||||
|
- prefer_zero_over_explicit_init
|
||||||
|
- discouraged_assert
|
||||||
|
- discouraged_none_name
|
||||||
|
- shorthand_optional_binding
|
||||||
|
|
||||||
|
# style
|
||||||
|
|
||||||
|
- literal_expression_end_indentation
|
||||||
|
- multiline_function_chains
|
||||||
|
- multiline_literal_brackets
|
||||||
|
- multiline_parameters
|
||||||
|
- operator_usage_whitespace
|
||||||
|
- switch_case_on_newline
|
||||||
|
- unneeded_parentheses_in_closure_argument
|
||||||
|
- vertical_parameter_alignment_on_call
|
||||||
|
- vertical_whitespace_between_cases
|
||||||
|
- vertical_whitespace_closing_braces
|
||||||
|
- yoda_condition
|
||||||
|
- number_separator
|
||||||
|
- let_var_whitespace
|
||||||
|
- implicit_return
|
||||||
|
- conditional_returns_on_newline
|
||||||
|
- closure_spacing
|
||||||
|
- closure_end_indentation
|
||||||
|
- prefer_self_type_over_type_of_self
|
||||||
|
- closure_parameter_position
|
||||||
|
- comma_inheritance
|
||||||
|
- self_binding
|
||||||
|
- prefer_self_in_static_references
|
||||||
|
- direct_return
|
||||||
|
- period_spacing
|
||||||
|
|
||||||
|
# lint
|
||||||
|
|
||||||
|
- private_action
|
||||||
|
- private_outlet
|
||||||
|
- prohibited_super_call
|
||||||
|
- identical_operands
|
||||||
|
- overridden_super_call
|
||||||
|
- unowned_variable_capture
|
||||||
|
- strong_iboutlet
|
||||||
|
- lower_acl_than_parent
|
||||||
|
- comment_spacing
|
||||||
|
- ibinspectable_in_extension
|
||||||
|
- private_subject
|
||||||
|
- unhandled_throwing_task
|
||||||
|
|
||||||
|
# metrics
|
||||||
|
|
||||||
|
- enum_case_associated_values_count
|
||||||
|
|
||||||
|
analyzer_rules:
|
||||||
|
- capture_variable
|
||||||
|
- typesafe_array_init
|
||||||
|
- unused_declaration
|
||||||
|
- unused_import
|
||||||
|
|
||||||
|
excluded:
|
||||||
|
- Carthage
|
||||||
|
- Pods
|
||||||
|
- Generated
|
||||||
|
- "**/Generated"
|
||||||
|
- "**/Resources"
|
||||||
|
- ".gem"
|
||||||
|
- "**/*.app"
|
||||||
|
|
||||||
|
line_length:
|
||||||
|
warning: 128
|
||||||
|
ignores_urls: true
|
||||||
|
|
||||||
|
cyclomatic_complexity:
|
||||||
|
ignores_case_statements: true
|
||||||
|
|
||||||
|
type_body_length:
|
||||||
|
- 500 # warning
|
||||||
|
- 700 # error
|
||||||
|
|
||||||
|
file_length:
|
||||||
|
warning: 500
|
||||||
|
error: 1200
|
||||||
|
|
||||||
|
function_parameter_count:
|
||||||
|
error: 5
|
||||||
|
|
||||||
|
colon:
|
||||||
|
flexible_right_spacing: true
|
||||||
|
|
||||||
|
enum_case_associated_values_count:
|
||||||
|
warning: 4
|
||||||
|
error: 5
|
||||||
|
|
||||||
|
identifier_name:
|
||||||
|
excluded:
|
||||||
|
- id
|
||||||
|
- ok
|
||||||
|
- URL
|
||||||
|
- qr
|
||||||
|
- x
|
||||||
|
- y
|
||||||
|
- z
|
||||||
|
|
||||||
|
warning_threshold: 1
|
||||||
|
|
||||||
|
allow_zero_lintable_files: true
|
||||||
|
|
||||||
|
custom_rules:
|
||||||
|
|
||||||
|
# General
|
||||||
|
|
||||||
|
unsecure_logging:
|
||||||
|
name: "Unsecure logging"
|
||||||
|
regex: '\s(print|debugPrint|NSLog)\('
|
||||||
|
message: "Please use os_log or remove this debug statement"
|
||||||
|
severity: error
|
||||||
|
excluded_match_kinds:
|
||||||
|
- comment
|
||||||
|
- comment.mark
|
||||||
|
- comment.url
|
||||||
|
- doccomment
|
||||||
|
- doccomment.field
|
||||||
|
|
||||||
|
marks_style:
|
||||||
|
name: "Marks"
|
||||||
|
regex: '// MARK: -?[a-zA-Z0-9]'
|
||||||
|
message: "Marks should follow the following structure: // MARK: - Comment."
|
||||||
|
severity: warning
|
||||||
|
|
||||||
|
no_header_comments:
|
||||||
|
name: "Header Comments"
|
||||||
|
regex: '//\s*Created by.*\s*//\s*Copyright'
|
||||||
|
match_kinds:
|
||||||
|
- comment
|
||||||
|
message: "Template header comments should be removed."
|
||||||
|
|
||||||
|
unnecessary_type:
|
||||||
|
name: "Unnecessary Type"
|
||||||
|
regex: '[ @a-zA-Z]*(?:let|var)\s\w*: ([a-zA-Z0-9]*)\?? = \1'
|
||||||
|
message: "Type definition not needed"
|
||||||
|
severity: error
|
||||||
|
|
||||||
|
unsafe_unowned:
|
||||||
|
name: "Unsafe unowned usage"
|
||||||
|
regex: 'unowned'
|
||||||
|
message: "Please use `weak` instead."
|
||||||
|
severity: error
|
||||||
|
|
||||||
|
cyrillic_strings:
|
||||||
|
name: "Cyrillic strings"
|
||||||
|
regex: '[а-яА-Я]+'
|
||||||
|
message: "Localize or translate"
|
||||||
|
severity: error
|
||||||
|
match_kinds:
|
||||||
|
- identifier
|
||||||
|
- string
|
||||||
|
|
||||||
|
too_many_empty_spaces:
|
||||||
|
name: "Too many empty spaces"
|
||||||
|
regex: '(?!\n)[^ \n]+ {2,}.+'
|
||||||
|
message: "Remove excess empty spaces"
|
||||||
|
severity: warning
|
||||||
|
excluded_match_kinds:
|
||||||
|
- comment
|
||||||
|
- comment.mark
|
||||||
|
- comment.url
|
||||||
|
- doccomment
|
||||||
|
- doccomment.field
|
||||||
|
|
||||||
|
getter_setter_style:
|
||||||
|
name: "Wrong getter/setter code style"
|
||||||
|
regex: "(get|set|willSet|didSet) \\{ [.]*"
|
||||||
|
match_kinds:
|
||||||
|
- keyword
|
||||||
|
message: "Make a new line break when use getter or setter"
|
||||||
|
severity: warning
|
||||||
|
|
||||||
|
redundant_boolean_condition:
|
||||||
|
name: "Redundant Boolean Condition"
|
||||||
|
regex: "(== true)|(== false)|(!= true)|(!= false)"
|
||||||
|
message: "Comparing a boolean to true is redundant (use `?? false` for optionals), and `!`-syntax is preferred over comparing to false."
|
||||||
|
severity: warning
|
||||||
|
excluded_match_kinds:
|
||||||
|
- comment
|
||||||
|
- comment.mark
|
||||||
|
- comment.url
|
||||||
|
- doccomment
|
||||||
|
- doccomment.field
|
||||||
|
|
||||||
|
redundant_ternary_operator:
|
||||||
|
name: "Redundant Ternary Operator"
|
||||||
|
regex: "(\\? true \\: false)|(\\? false \\: true)"
|
||||||
|
message: "Returning a boolean as true is redundant, and `!`-syntax is preferred over returning as false."
|
||||||
|
severity: warning
|
||||||
|
|
||||||
|
single_line_closure:
|
||||||
|
name: "Single line closure"
|
||||||
|
regex: '\{([^\n\/]*\[[^\]]+\][^\n\/]*)?([^\n\/]*[a-zA-Z]\w*(, \w+)*)? in [^\n\/]+'
|
||||||
|
message: "Too complex expression for single line closure. Improve readability by making it multiline."
|
||||||
|
severity: warning
|
||||||
|
|
||||||
|
addSubview_in_cell:
|
||||||
|
name: "Usage addSubview in cell"
|
||||||
|
regex: '(extension|class)\s*\w+Cell(:| )(?s).*(self\.|\s{2,})add(Subv|V)iews?\(\w'
|
||||||
|
message: "Use сontentView instead of self for addSubview or addSubviews methods in cell."
|
||||||
|
severity: warning
|
||||||
|
|
||||||
|
parameter_repetition:
|
||||||
|
name: "Parameter repetition"
|
||||||
|
regex: 'func ((\w+([A-Z]\w+))|(\w+)) *(<[^>]+>)? *\( *(?i)(\3|\4):'
|
||||||
|
message: "The parameter name is actually used in the function name. Use _ instead."
|
||||||
|
severity: warning
|
||||||
|
|
||||||
|
parameter_closure:
|
||||||
|
name: "Parameter closure"
|
||||||
|
regex: '\w*Closure<[^\r\n\t\f\v]*, Void[^\r\n\t\f\v]*>'
|
||||||
|
message: "Use `ParameterClosure` instead of declaring an explicit return value of `Void`."
|
||||||
|
severity: warning
|
||||||
|
|
||||||
|
strong_self:
|
||||||
|
name: "Strong self"
|
||||||
|
regex: '(if|guard)\s+let\s+self\s+=\s+self'
|
||||||
|
message: "Use a local function instead of capture strong self"
|
||||||
|
severity: warning
|
||||||
|
|
||||||
|
pattern_matching:
|
||||||
|
name: "Pattern matching"
|
||||||
|
regex: 'case[^\n\(]+\([^\)]*(let|var)\s'
|
||||||
|
message: "Use a let|var keyword behind parentheses"
|
||||||
|
severity: warning
|
||||||
|
|
||||||
|
# Rx
|
||||||
|
|
||||||
|
unused_map_parameter:
|
||||||
|
name: "Unused map parameter"
|
||||||
|
regex: '.map\s*\{\s*_\s*in'
|
||||||
|
message: "Replace Rx.map operator with replace(with:) or asVoid(). For Sequence.map consider using forEach."
|
||||||
|
severity: warning
|
||||||
|
|
||||||
|
disposable_nil:
|
||||||
|
name: "Disposable nil"
|
||||||
|
regex: ' *\S*(d|D)isposable\?? *= *nil'
|
||||||
|
message: "nil assigning doesn't dispose subscription. Call `dispose()` instead."
|
||||||
|
severity: error
|
||||||
|
|
||||||
|
# LeadKit
|
||||||
|
|
||||||
|
multiple_add_subview:
|
||||||
|
name: "Multiple addSubview calls"
|
||||||
|
regex: '(^\s*\w*\.?)(addSubview)\([\w]+\)\n\1\2'
|
||||||
|
message: "Replace multiple addSubview calls with single addSubviews."
|
||||||
|
severity: warning
|
||||||
|
|
@ -0,0 +1,6 @@
|
||||||
|
excluded-resources:
|
||||||
|
- Generated/
|
||||||
|
- Resources/Localization
|
||||||
|
- Carthage/
|
||||||
|
- Pods/
|
||||||
|
- FormattingService.swift
|
||||||
|
|
@ -0,0 +1,57 @@
|
||||||
|
CERTS_PATH="${PROJECT_DIR}/Certificates"
|
||||||
|
|
||||||
|
for config_folder in $CERTS_PATH/*/; do
|
||||||
|
CONFIG_FOLDER_NAME="$(basename "$config_folder")"
|
||||||
|
|
||||||
|
echo "# ${CONFIG_FOLDER_NAME}"
|
||||||
|
|
||||||
|
for type_folder in $CERTS_PATH/$CONFIG_FOLDER_NAME/*/; do
|
||||||
|
TYPE_FOLDER_NAME="$(basename "$type_folder")"
|
||||||
|
|
||||||
|
echo "### ${TYPE_FOLDER_NAME}"
|
||||||
|
echo "|Target|Description|"
|
||||||
|
echo "|-|-|"
|
||||||
|
|
||||||
|
for target_folder in $CERTS_PATH/$CONFIG_FOLDER_NAME/$TYPE_FOLDER_NAME/*/; do
|
||||||
|
TARGET_FOLDER_NAME="$(basename "$target_folder")"
|
||||||
|
|
||||||
|
DESCRIPTION_FILE_NAME="description.txt"
|
||||||
|
|
||||||
|
TARGET_FOLDER_PATH="${CERTS_PATH}/${CONFIG_FOLDER_NAME}/${TYPE_FOLDER_NAME}/${TARGET_FOLDER_NAME}"
|
||||||
|
DESCRIPTION_FILE_PATH="${TARGET_FOLDER_PATH}/${DESCRIPTION_FILE_NAME}"
|
||||||
|
|
||||||
|
if [ -e "$DESCRIPTION_FILE_PATH" ]
|
||||||
|
then
|
||||||
|
DESCRIPTION="$(cat $DESCRIPTION_FILE_PATH)"
|
||||||
|
else
|
||||||
|
DESCRIPTION="-"
|
||||||
|
fi
|
||||||
|
|
||||||
|
for file in $CERTS_PATH/$CONFIG_FOLDER_NAME/$TYPE_FOLDER_NAME/$TARGET_FOLDER_NAME/*; do
|
||||||
|
FILE_NAME="$(basename "$file")"
|
||||||
|
|
||||||
|
if ! [ "$FILE_NAME" == "$DESCRIPTION_FILE_NAME" ]
|
||||||
|
then
|
||||||
|
FILE_PATH="${TARGET_FOLDER_PATH}/${FILE_NAME}"
|
||||||
|
EXTENSION="${FILE_NAME##*.}"
|
||||||
|
PROPER_FILE_PREFIX="${PROJECT_NAME}${TARGET_FOLDER_NAME}${CONFIG_FOLDER_NAME}"
|
||||||
|
|
||||||
|
if [ "$EXTENSION" == "mobileprovision" ]; then
|
||||||
|
FILE_TYPE="Profile"
|
||||||
|
elif [ "$EXTENSION" == "p12" ]; then
|
||||||
|
FILE_TYPE="Cert"
|
||||||
|
elif [ ]; then
|
||||||
|
echo "Unknown type of file has been found. Not a profile or a certificate."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
PROPER_FILE_NAME="${PROPER_FILE_PREFIX}${FILE_TYPE}"
|
||||||
|
|
||||||
|
mv $FILE_PATH "${TARGET_FOLDER_PATH}/${PROPER_FILE_NAME}.${EXTENSION}"
|
||||||
|
|
||||||
|
echo "|[${TARGET_FOLDER_NAME}](${CONFIG_FOLDER_NAME}/${TYPE_FOLDER_NAME}/${TARGET_FOLDER_NAME}/${PROPER_FILE_NAME}.${EXTENSION})|${DESCRIPTION}|"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
done
|
||||||
|
done
|
||||||
|
done
|
||||||
|
|
@ -0,0 +1,12 @@
|
||||||
|
<?php
|
||||||
|
$CPD_XML_PATH = $argv[1];
|
||||||
|
|
||||||
|
foreach (simplexml_load_file($CPD_XML_PATH)->duplication as $duplication) {
|
||||||
|
$files = $duplication->xpath('file');
|
||||||
|
foreach ($files as $file) {
|
||||||
|
echo $file['path'].':'.$file['line'].':1: warning: '.$duplication['lines'].' copy-pasted lines from: '
|
||||||
|
.implode(', ', array_map(function ($otherFile) { return $otherFile['path'].':'.$otherFile['line']; },
|
||||||
|
array_filter($files, function ($f) use (&$file) { return $f != $file; }))).PHP_EOL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
?>
|
||||||
|
|
@ -0,0 +1,32 @@
|
||||||
|
file_name=$1
|
||||||
|
file_link=$2
|
||||||
|
folder=$3
|
||||||
|
flag_of_delete=$4
|
||||||
|
|
||||||
|
key_of_delete="--remove-cached"
|
||||||
|
default_folder="./Downloads"
|
||||||
|
|
||||||
|
if [[ ${folder} = ${key_of_delete} ]]; then
|
||||||
|
folder="${default_folder}"
|
||||||
|
flag_of_delete="${key_of_delete}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if ! [ -n "$folder" ]; then
|
||||||
|
folder="${default_folder}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
file_path="${folder}/${file_name}"
|
||||||
|
|
||||||
|
if [[ ${flag_of_delete} = ${key_of_delete} ]]; then
|
||||||
|
rm ${file_path}
|
||||||
|
fi
|
||||||
|
|
||||||
|
# make folder if not exist
|
||||||
|
if ! [ -e ${folder} ]; then
|
||||||
|
mkdir -p ${folder}
|
||||||
|
fi
|
||||||
|
|
||||||
|
# download file if not downloaded
|
||||||
|
if ! [ -e ${file_path} ]; then
|
||||||
|
curl -L ${file_link} -o ${file_path}
|
||||||
|
fi
|
||||||
|
|
@ -0,0 +1,55 @@
|
||||||
|
<?php
|
||||||
|
$LOCALIZATION_PATH = $argv[1];
|
||||||
|
$COMMON_STRINGS_PATH = $argv[2];
|
||||||
|
$BUNDLE = $argv[3];
|
||||||
|
|
||||||
|
function createFolder($path) {
|
||||||
|
if (!file_exists($path)) {
|
||||||
|
mkdir($path, 0777, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$baseFile = file_get_contents(array_pop(glob($COMMON_STRINGS_PATH.'/default*.json')));
|
||||||
|
$baseJson = json_decode($baseFile, true);
|
||||||
|
|
||||||
|
foreach (glob($COMMON_STRINGS_PATH.'/*.json') as $file) {
|
||||||
|
$languageName = array_pop(explode('_', basename($file, '.json')));
|
||||||
|
$isBase = strpos($file, 'default') !== false;
|
||||||
|
|
||||||
|
$jsonFile = file_get_contents($file);
|
||||||
|
$json = array_merge($baseJson, json_decode($jsonFile, true));
|
||||||
|
|
||||||
|
if ($json == null) {
|
||||||
|
echo "Invalid JSON format\n";
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
$ios_strings = "";
|
||||||
|
foreach ($json as $key=>$value) {
|
||||||
|
$ios_strings.='"'.$key.'" = "'.str_replace('%s', '%@', str_replace('"','\"', str_replace("\n", '\n', $value))).'";'.PHP_EOL;
|
||||||
|
}
|
||||||
|
$ios_strings = preg_replace('/(\\\\)(u)([0-9a-fA-F]{4})/', '$1U$3', $ios_strings);
|
||||||
|
|
||||||
|
$lproj = $LOCALIZATION_PATH.$languageName.'.lproj/';
|
||||||
|
createFolder($lproj);
|
||||||
|
file_put_contents($lproj.'Localizable.strings', $ios_strings);
|
||||||
|
|
||||||
|
if($isBase) {
|
||||||
|
createFolder($LOCALIZATION_PATH.'Base.lproj/');
|
||||||
|
file_put_contents($LOCALIZATION_PATH.'Base.lproj/Localizable.strings', $ios_strings);
|
||||||
|
$ios_swift_strings = 'import Foundation'.PHP_EOL.PHP_EOL.
|
||||||
|
'// swiftlint:disable superfluous_disable_command'.PHP_EOL.
|
||||||
|
'// swiftlint:disable line_length'.PHP_EOL.
|
||||||
|
'// swiftlint:disable file_length'.PHP_EOL.
|
||||||
|
'// swiftlint:disable cyrillic_strings'.PHP_EOL.
|
||||||
|
'// swiftlint:disable identifier_name'.PHP_EOL.PHP_EOL.
|
||||||
|
'public extension String {'.PHP_EOL;
|
||||||
|
foreach ($json as $key=>$value) {
|
||||||
|
$value_without_linefeed = preg_replace("/\r|\n/", " ", $value);
|
||||||
|
$ios_swift_strings .= "\t/// ".$value_without_linefeed."\n\t".'static let '.preg_replace_callback('/_(.?)/', function ($m) { return strtoupper($m[1]); }, $key).' = NSLocalizedString("'.$key.'", bundle: '.$BUNDLE.', comment: "'.addslashes($value_without_linefeed).'")'."\n".PHP_EOL;
|
||||||
|
}
|
||||||
|
$ios_swift_strings .= '}'.PHP_EOL;
|
||||||
|
file_put_contents($LOCALIZATION_PATH.'String+Localization.swift', $ios_swift_strings);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
?>
|
||||||
|
|
@ -0,0 +1,39 @@
|
||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
# Description:
|
||||||
|
# Add user defined enviroment if programm not found
|
||||||
|
#
|
||||||
|
# Parameters:
|
||||||
|
# $1 - programm
|
||||||
|
#
|
||||||
|
# Examples of usage:
|
||||||
|
# . install_env.sh pmd
|
||||||
|
#
|
||||||
|
|
||||||
|
# When you run Git from the command line, it runs in the environment as set up by your Shell.
|
||||||
|
# GUI OS X apps, however, have no knowledge about your shell - and the PATH environment can be changed in many different places.
|
||||||
|
# Export our profile with path by ourselves
|
||||||
|
|
||||||
|
function source_home_file {
|
||||||
|
file="$HOME/$1"
|
||||||
|
|
||||||
|
if [[ -f "${file}" ]]; then
|
||||||
|
if ! source "${file}"; then
|
||||||
|
export_commands="$(cat "${file}" | grep "^export PATH=")"
|
||||||
|
|
||||||
|
while read export_command
|
||||||
|
do
|
||||||
|
eval "$export_command"
|
||||||
|
done <<< "$export_commands"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
|
# Use specific exec due to Xcode has custom value of $PATH
|
||||||
|
if [ -z "$(which $1)" ]; then
|
||||||
|
source_home_file ".bash_profile" || source_home_file ".zshrc" || source_home_file ".zprofile" || true
|
||||||
|
|
||||||
|
echo "User defined enviroment has been set for ${1}"
|
||||||
|
fi
|
||||||
|
|
@ -0,0 +1,44 @@
|
||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
PROJECT_PATH=$1
|
||||||
|
|
||||||
|
cd ${PROJECT_PATH}
|
||||||
|
|
||||||
|
# Install ruby dependencies (cocoapods, fastlane, etc.)
|
||||||
|
|
||||||
|
bundle install
|
||||||
|
|
||||||
|
# Install Homebrew
|
||||||
|
|
||||||
|
if [[ $(command -v brew) == "" ]]; then
|
||||||
|
|
||||||
|
# Prevent "Press RETURN to continue or any other key to abort" message when installing Homebrew
|
||||||
|
|
||||||
|
export CI=true
|
||||||
|
|
||||||
|
/usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Install brew dependencies (carthage, etc.)
|
||||||
|
|
||||||
|
brew bundle
|
||||||
|
|
||||||
|
# Install pods dependencies
|
||||||
|
|
||||||
|
bundle exec pod repo update
|
||||||
|
bundle exec pod install
|
||||||
|
|
||||||
|
# Install carthage dependencies
|
||||||
|
|
||||||
|
carthage bootstrap --platform iOS
|
||||||
|
|
||||||
|
case $2 in
|
||||||
|
--InstallDevelopmentCodeSigning)
|
||||||
|
# Install certificates & provision profiles for development
|
||||||
|
|
||||||
|
cd ${PROJECT_PATH}/fastlane
|
||||||
|
|
||||||
|
bundle exec fastlane SyncCodeSigning
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
|
@ -0,0 +1,14 @@
|
||||||
|
# Working environment
|
||||||
|
brew "rbenv" # ruby + bundler
|
||||||
|
brew "gettext"
|
||||||
|
|
||||||
|
# Code, configs and project generation
|
||||||
|
brew "php"
|
||||||
|
brew "python"
|
||||||
|
brew "xcodegen"
|
||||||
|
|
||||||
|
# code quality
|
||||||
|
brew "pmd"
|
||||||
|
|
||||||
|
# CI badge
|
||||||
|
# brew "imagemagick"
|
||||||
|
|
@ -0,0 +1,9 @@
|
||||||
|
source "https://rubygems.org"
|
||||||
|
|
||||||
|
gem "cocoapods"
|
||||||
|
gem "fastlane"
|
||||||
|
gem 'mustache' # for config generator
|
||||||
|
gem 'xcode-install'
|
||||||
|
|
||||||
|
plugins_path = File.join(File.dirname(__FILE__), 'fastlane', 'Pluginfile')
|
||||||
|
eval_gemfile(plugins_path) if File.exist?(plugins_path)
|
||||||
|
|
@ -0,0 +1,91 @@
|
||||||
|
GREEN := $(shell tput -Txterm setaf 2)
|
||||||
|
YELLOW := $(shell tput -Txterm setaf 3)
|
||||||
|
WHITE := $(shell tput -Txterm setaf 7)
|
||||||
|
RESET := $(shell tput -Txterm sgr0)
|
||||||
|
|
||||||
|
RUBY_VERSION="2.7.6"
|
||||||
|
|
||||||
|
open_project=(open *.xcworkspace)
|
||||||
|
install_dev_certs=(bundle exec fastlane InstallDevelopmentSigningIdentities)
|
||||||
|
install_pods=(bundle exec pod install || bundle exec pod install --repo-update)
|
||||||
|
init_rbenv=(if command -v rbenv &> /dev/null; then eval "$$(rbenv init -)"; fi)
|
||||||
|
|
||||||
|
TARGET_MAX_CHAR_NUM=20
|
||||||
|
## Show help
|
||||||
|
help:
|
||||||
|
@echo ''
|
||||||
|
@echo 'Использование:'
|
||||||
|
@echo ' ${YELLOW}make${RESET} ${GREEN}<target>${RESET}'
|
||||||
|
@echo ''
|
||||||
|
@echo 'Команды:'
|
||||||
|
@awk '/^[a-zA-Z\-\_0-9]+:/ { \
|
||||||
|
helpMessage = match(lastLine, /^## (.*)/); \
|
||||||
|
if (helpMessage) { \
|
||||||
|
helpCommand = substr($$1, 0, index($$1, ":")-1); \
|
||||||
|
helpMessage = substr(lastLine, RSTART + 3, RLENGTH); \
|
||||||
|
printf " ${YELLOW}%-$(TARGET_MAX_CHAR_NUM)s${RESET} ${GREEN}%s${RESET}\n", helpCommand, helpMessage; \
|
||||||
|
} \
|
||||||
|
} \
|
||||||
|
{ lastLine = $$0 }' $(MAKEFILE_LIST)
|
||||||
|
|
||||||
|
## Инициализирует проект и устанавливает системные утилиты
|
||||||
|
init:
|
||||||
|
brew bundle
|
||||||
|
|
||||||
|
$(call init_rbenv)
|
||||||
|
|
||||||
|
rbenv install -s ${RUBY_VERSION}
|
||||||
|
rbenv global ${RUBY_VERSION}
|
||||||
|
|
||||||
|
if ! gem spec bundler > /dev/null 2>&1; then\
|
||||||
|
echo "bundler gem is not installed!";\
|
||||||
|
-sudo gem install bundler;\
|
||||||
|
fi
|
||||||
|
|
||||||
|
bundle install
|
||||||
|
|
||||||
|
xcodegen
|
||||||
|
|
||||||
|
$(call install_pods)
|
||||||
|
|
||||||
|
bundle exec fastlane install_plugins
|
||||||
|
|
||||||
|
$(call install_dev_certs)
|
||||||
|
|
||||||
|
$(call open_project)
|
||||||
|
|
||||||
|
git config --local core.hooksPath .githooks
|
||||||
|
|
||||||
|
## Устанавливает поды
|
||||||
|
pod:
|
||||||
|
$(call install_pods)
|
||||||
|
|
||||||
|
## Запускает генерацию файла проекта
|
||||||
|
gen:
|
||||||
|
xcodegen
|
||||||
|
|
||||||
|
## Устанавливает сертификат и профили для запуска на девайсе
|
||||||
|
dev_certs:
|
||||||
|
$(call install_dev_certs)
|
||||||
|
|
||||||
|
## Открывает папку для ручного редактирования сертификатов и профайлов
|
||||||
|
update_certs:
|
||||||
|
bundle exec fastlane ManuallyUpdateCodeSigning
|
||||||
|
|
||||||
|
## Поднимает версию приложения (параметр "X.Y.Z")
|
||||||
|
bumpAppVersion:
|
||||||
|
ifeq ($(version),undefined)
|
||||||
|
@echo "Version parameter is missing (ex: x.y.z)" $(target)
|
||||||
|
else
|
||||||
|
bundle exec fastlane run increment_version_number version_number:$(version)
|
||||||
|
endif
|
||||||
|
|
||||||
|
## Позволяет быстро открыть workspace проекта
|
||||||
|
start:
|
||||||
|
$(call open_project)
|
||||||
|
|
||||||
|
## Очищает содержимое папки DerivedData
|
||||||
|
clean:
|
||||||
|
rm -rf ~/Library/Developer/Xcode/DerivedData/*
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -0,0 +1,25 @@
|
||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
# Description:
|
||||||
|
# Runs full linting and copy-paste-detection for project
|
||||||
|
#
|
||||||
|
# Required environment variables:
|
||||||
|
# SRCROOT - project directory.
|
||||||
|
# SCRIPT_DIR - directory of current script.
|
||||||
|
#
|
||||||
|
# Optional environment variables:
|
||||||
|
# See swiftlint.sh and copy_paste_detection.sh for complete list of available variables
|
||||||
|
#
|
||||||
|
# Example of usage:
|
||||||
|
# ./full_code_lint.sh
|
||||||
|
#
|
||||||
|
|
||||||
|
if [ -z "${SCRIPT_DIR}" ]; then
|
||||||
|
SCRIPT_DIR=${SRCROOT}/build-scripts/xcode/build_phases
|
||||||
|
fi
|
||||||
|
|
||||||
|
. ${SRCROOT}/build-scripts/xcode/aux_scripts/install_env.sh swiftlint
|
||||||
|
FORCE_LINT=true; . ${SCRIPT_DIR}/swiftlint.sh
|
||||||
|
|
||||||
|
. ${SRCROOT}/build-scripts/xcode/aux_scripts/install_env.sh cpd
|
||||||
|
. ${SCRIPT_DIR}/copy_paste_detection.sh Localization Generated Pods
|
||||||
|
|
@ -0,0 +1,22 @@
|
||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
# Description:
|
||||||
|
# Runs incremental linting for project
|
||||||
|
#
|
||||||
|
# Required environment variables:
|
||||||
|
# SRCROOT - project directory.
|
||||||
|
# SCRIPT_DIR - directory of current script.
|
||||||
|
#
|
||||||
|
# Optional environment variables:
|
||||||
|
# See swiftlint.sh for complete list of available variables
|
||||||
|
#
|
||||||
|
# Example of usage:
|
||||||
|
# ./incremetal_code_lint.sh
|
||||||
|
#
|
||||||
|
|
||||||
|
if [ -z "${SCRIPT_DIR}" ]; then
|
||||||
|
SCRIPT_DIR=${SRCROOT}/build-scripts/xcode/build_phases
|
||||||
|
fi
|
||||||
|
|
||||||
|
. ${SRCROOT}/build-scripts/xcode/aux_scripts/install_env.sh swiftlint
|
||||||
|
. ${SCRIPT_DIR}/swiftlint.sh
|
||||||
|
|
@ -0,0 +1,6 @@
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
|
||||||
|
PROJECT_DIR="${DIR}/../../../"
|
||||||
|
|
||||||
|
make init -C ${PROJECT_DIR}
|
||||||
|
|
@ -0,0 +1,190 @@
|
||||||
|
# source: https://github.com/PaulTaykalo/swift-scripts/blob/master/unused.rb
|
||||||
|
#!/usr/bin/ruby
|
||||||
|
#encoding: utf-8
|
||||||
|
require 'yaml'
|
||||||
|
require 'optparse'
|
||||||
|
|
||||||
|
Encoding.default_external = Encoding::UTF_8
|
||||||
|
Encoding.default_internal = Encoding::UTF_8
|
||||||
|
|
||||||
|
class Item
|
||||||
|
def initialize(file, line, at)
|
||||||
|
@file = file
|
||||||
|
@line = line
|
||||||
|
@at = at + 1
|
||||||
|
if match = line.match(/(func|let|var|class|enum|struct|protocol)\s+(\w+)/)
|
||||||
|
@type = match.captures[0]
|
||||||
|
@name = match.captures[1]
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def modifiers
|
||||||
|
return @modifiers if @modifiers
|
||||||
|
@modifiers = []
|
||||||
|
if match = @line.match(/(.*?)#{@type}/)
|
||||||
|
@modifiers = match.captures[0].split(" ")
|
||||||
|
end
|
||||||
|
return @modifiers
|
||||||
|
end
|
||||||
|
|
||||||
|
def name
|
||||||
|
@name
|
||||||
|
end
|
||||||
|
|
||||||
|
def file
|
||||||
|
@file
|
||||||
|
end
|
||||||
|
|
||||||
|
def to_s
|
||||||
|
serialize
|
||||||
|
end
|
||||||
|
def to_str
|
||||||
|
serialize
|
||||||
|
end
|
||||||
|
|
||||||
|
def full_file_path
|
||||||
|
Dir.pwd + '/' + @file
|
||||||
|
end
|
||||||
|
|
||||||
|
def serialize
|
||||||
|
"#{@file} has unused \"#{@type.to_s} #{@name.to_s}\""
|
||||||
|
end
|
||||||
|
def to_xcode
|
||||||
|
"#{full_file_path}:#{@at}:0: warning: #{@type.to_s} #{@name.to_s} is unused"
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
end
|
||||||
|
class Unused
|
||||||
|
def find
|
||||||
|
items = []
|
||||||
|
unused_warnings = []
|
||||||
|
|
||||||
|
regexps = parse_arguments
|
||||||
|
|
||||||
|
all_files = Dir.glob("**/*.swift").reject do |path|
|
||||||
|
File.directory?(path)
|
||||||
|
end
|
||||||
|
|
||||||
|
all_files.each { |my_text_file|
|
||||||
|
file_items = grab_items(my_text_file)
|
||||||
|
file_items = filter_items(file_items)
|
||||||
|
|
||||||
|
non_private_items, private_items = file_items.partition { |f| !f.modifiers.include?("private") && !f.modifiers.include?("fileprivate") }
|
||||||
|
items += non_private_items
|
||||||
|
|
||||||
|
# Usage within the file
|
||||||
|
if private_items.length > 0
|
||||||
|
unused_warnings += find_usages_in_files([my_text_file], [], private_items, regexps)
|
||||||
|
end
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
xibs = Dir.glob("**/*.xib")
|
||||||
|
storyboards = Dir.glob("**/*.storyboard")
|
||||||
|
|
||||||
|
unused_warnings += find_usages_in_files(all_files, xibs + storyboards, items, regexps)
|
||||||
|
|
||||||
|
if unused_warnings.length > 0
|
||||||
|
# show warning
|
||||||
|
puts "Unused Code Warning!: warning: Total Count #{unused_warnings.length}"
|
||||||
|
puts "#{unused_warnings.map { |e| e.to_xcode}.join("\n")}"
|
||||||
|
# write log
|
||||||
|
Dir.mkdir(directory_name) unless File.exists?("code-quality-reports")
|
||||||
|
File.open("code-quality-reports/UnusedLog.txt", "w") do |file|
|
||||||
|
file.write("Unused code warnings count: #{unused_warnings.length}\n\n")
|
||||||
|
file.write("#{unused_warnings.map { |e| e.serialize }.join("\n")}")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def parse_arguments
|
||||||
|
resources = []
|
||||||
|
|
||||||
|
options = {}
|
||||||
|
OptionParser.new do |opts|
|
||||||
|
options[:exclude] = []
|
||||||
|
|
||||||
|
opts.on("-c", "--config=FileName") { |c| options[:config] = c }
|
||||||
|
opts.on("-i", "--exclude [a, b, c]", Array) { |i| options[:exclude] += i if !i.nil? }
|
||||||
|
|
||||||
|
end.parse!
|
||||||
|
|
||||||
|
# find --config file
|
||||||
|
if !options[:config].nil?
|
||||||
|
fileName = options[:config]
|
||||||
|
resources += YAML.load_file(fileName).fetch("excluded-resources")
|
||||||
|
elsif
|
||||||
|
puts "---------\n Warning: Config file is not provided \n---------"
|
||||||
|
end
|
||||||
|
|
||||||
|
# find --exclude files
|
||||||
|
if !options[:exclude].nil?
|
||||||
|
resources += options[:exclude]
|
||||||
|
end
|
||||||
|
|
||||||
|
# create and return Regexp
|
||||||
|
resources.map { |r| Regexp.new(r) }
|
||||||
|
end
|
||||||
|
|
||||||
|
def grab_items(file)
|
||||||
|
lines = File.readlines(file).map {|line| line.gsub(/^\s*\/\/.*/, "") }
|
||||||
|
items = lines.each_with_index.select { |line, i| line[/(func|let|var|class|enum|struct|protocol)\s+\w+/] }.map { |line, i| Item.new(file, line, i)}
|
||||||
|
end
|
||||||
|
|
||||||
|
def filter_items(items)
|
||||||
|
items.select { |f|
|
||||||
|
!f.name.start_with?("test") && !f.modifiers.include?("@IBAction") && !f.modifiers.include?("override") && !f.modifiers.include?("@objc") && !f.modifiers.include?("@IBInspectable")
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
# remove files, that maches excluded Regexps array
|
||||||
|
def ignore_files_with_regexps(files, regexps)
|
||||||
|
files.select { |f| regexps.all? { |r| r.match(f.file).nil? } }
|
||||||
|
end
|
||||||
|
|
||||||
|
def find_usages_in_files(files, xibs, items_in, regexps)
|
||||||
|
items = items_in
|
||||||
|
usages = items.map { |f| 0 }
|
||||||
|
files.each { |file|
|
||||||
|
lines = File.readlines(file).map {|line| line.gsub(/^[^\/]*\/\/.*/, "") }
|
||||||
|
words = lines.join("\n").split(/\W+/)
|
||||||
|
words_arrray = words.group_by { |w| w }.map { |w, ws| [w, ws.length] }.flatten
|
||||||
|
|
||||||
|
wf = Hash[*words_arrray]
|
||||||
|
|
||||||
|
items.each_with_index { |f, i|
|
||||||
|
usages[i] += (wf[f.name] || 0)
|
||||||
|
}
|
||||||
|
# Remove all items which has usage 2+
|
||||||
|
indexes = usages.each_with_index.select { |u, i| u >= 2 }.map { |f, i| i }
|
||||||
|
|
||||||
|
# reduce usage array if we found some functions already
|
||||||
|
indexes.reverse.each { |i| usages.delete_at(i) && items.delete_at(i) }
|
||||||
|
}
|
||||||
|
|
||||||
|
xibs.each { |xib|
|
||||||
|
lines = File.readlines(xib).map {|line| line.gsub(/^\s*\/\/.*/, "") }
|
||||||
|
full_xml = lines.join(" ")
|
||||||
|
classes = full_xml.scan(/(class|customClass)="([^"]+)"/).map { |cd| cd[1] }
|
||||||
|
classes_array = classes.group_by { |w| w }.map { |w, ws| [w, ws.length] }.flatten
|
||||||
|
|
||||||
|
wf = Hash[*classes_array]
|
||||||
|
|
||||||
|
items.each_with_index { |f, i|
|
||||||
|
usages[i] += (wf[f.name] || 0)
|
||||||
|
}
|
||||||
|
# Remove all items which has usage 2+
|
||||||
|
indexes = usages.each_with_index.select { |u, i| u >= 2 }.map { |f, i| i }
|
||||||
|
|
||||||
|
# reduce usage array if we found some functions already
|
||||||
|
indexes.reverse.each { |i| usages.delete_at(i) && items.delete_at(i) }
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
items = ignore_files_with_regexps(items, regexps)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
Unused.new.find
|
||||||
|
|
@ -0,0 +1,350 @@
|
||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
# Description:
|
||||||
|
# Generates API models & methods.
|
||||||
|
#
|
||||||
|
# Parameters:
|
||||||
|
# $1 - api generator version.
|
||||||
|
# $2 - path to generated code directory
|
||||||
|
#
|
||||||
|
# Required environment variables:
|
||||||
|
# SRCROOT - path to project folder.
|
||||||
|
#
|
||||||
|
# Optional environment variables:
|
||||||
|
# OUTPUT_PATH - path to Generated folder.
|
||||||
|
# API_SPEC_DIR - path to api specification folder
|
||||||
|
# VERBOSE - print debug messages
|
||||||
|
# API_NAME - project name that will be used by generator (example: OUTPUT_PATH/API_NAME/Classes )
|
||||||
|
#
|
||||||
|
# Examples of usage:
|
||||||
|
# . api_generator.sh 1.4.0-beta1
|
||||||
|
# . api_generator.sh 1.4.0-beta1 ${TARGET_NAME}/Generated
|
||||||
|
#
|
||||||
|
|
||||||
|
readonly EXIT_SUCCESS=0
|
||||||
|
readonly EXIT_FAILURE=1
|
||||||
|
|
||||||
|
readonly TRUE=1
|
||||||
|
readonly FALSE=0
|
||||||
|
|
||||||
|
readonly LOG_TAG="API-GENERATOR"
|
||||||
|
|
||||||
|
notice()
|
||||||
|
{
|
||||||
|
echo "${LOG_TAG}:NOTICE: ${1}" >&2
|
||||||
|
}
|
||||||
|
|
||||||
|
debug()
|
||||||
|
{
|
||||||
|
if [ ! -z "${VERBOSE}" ]; then
|
||||||
|
echo "${LOG_TAG}:DEBUG: ${1}" >&2
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
exit_on_failure()
|
||||||
|
{
|
||||||
|
eval ${1}
|
||||||
|
|
||||||
|
local -r EXIT_CODE=$?
|
||||||
|
|
||||||
|
if [ ${EXIT_CODE} -ne 0 ]; then
|
||||||
|
echo "Recent command: \`${1}\` failed with code ${EXIT_CODE}"
|
||||||
|
|
||||||
|
exit ${EXIT_CODE}
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
is_force_run()
|
||||||
|
{
|
||||||
|
if [ -z "${FORCE_RUN}" ]; then
|
||||||
|
echo ${FALSE}
|
||||||
|
return
|
||||||
|
fi
|
||||||
|
|
||||||
|
local -r STR_MODE=`tr "[:upper:]" "[:lower:]" <<< ${FORCE_RUN}`
|
||||||
|
|
||||||
|
if [ ${STR_MODE} == "yes" ] || [ ${STR_MODE} == "true" ] || [ ${STR_MODE} == "1" ]; then
|
||||||
|
echo ${TRUE}
|
||||||
|
else
|
||||||
|
echo ${FALSE}
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
is_single_file()
|
||||||
|
{
|
||||||
|
if [ -z "${SINGLE_FILE}" ]; then
|
||||||
|
echo "true"
|
||||||
|
return
|
||||||
|
fi
|
||||||
|
|
||||||
|
local -r STR_MODE=`tr "[:upper:]" "[:lower:]" <<< ${SINGLE_FILE}`
|
||||||
|
|
||||||
|
if [ ${STR_MODE} == "no" ] || [ ${STR_MODE} == "false" ] || [ ${STR_MODE} == "0" ]; then
|
||||||
|
echo "false"
|
||||||
|
else
|
||||||
|
echo "true"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
get_api_spec_current_commit()
|
||||||
|
{
|
||||||
|
if [ -z "${API_SPEC_DIR}" ]; then
|
||||||
|
if [ ! -z "${1}" ]; then
|
||||||
|
echo `git -C ${1} rev-parse --verify HEAD`
|
||||||
|
else
|
||||||
|
echo `git rev-parse --verify HEAD`
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
echo `git -C ${API_SPEC_DIR} rev-parse --verify HEAD`
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
get_api_spec_status()
|
||||||
|
{
|
||||||
|
if [ -z "${API_SPEC_DIR}" ]; then
|
||||||
|
if [ ! -z "${1}" ]; then
|
||||||
|
echo `git -C ${1} status -s`
|
||||||
|
else
|
||||||
|
echo `git status -s`
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
echo `git -C ${API_SPEC_DIR} status -s`
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
is_api_spec_under_source_control()
|
||||||
|
{
|
||||||
|
local IS_UNDER_SOURCE_CONTROL_CHECK
|
||||||
|
|
||||||
|
if [ -z "${API_SPEC_DIR}" ]; then
|
||||||
|
if [ ! -z "${1}" ]; then
|
||||||
|
IS_UNDER_SOURCE_CONTROL_CHECK=`git -C ${1} rev-parse --is-inside-work-tree 2>/dev/null`
|
||||||
|
else
|
||||||
|
IS_UNDER_SOURCE_CONTROL_CHECK=`git rev-parse --is-inside-work-tree 2>/dev/null`
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
IS_UNDER_SOURCE_CONTROL_CHECK=`git -C ${API_SPEC_DIR} rev-parse --is-inside-work-tree 2>/dev/null`
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ "${IS_UNDER_SOURCE_CONTROL_CHECK}" = "true" ]; then
|
||||||
|
echo ${TRUE}
|
||||||
|
else
|
||||||
|
echo ${FALSE}
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
is_api_spec_has_uncommited_changes()
|
||||||
|
{
|
||||||
|
if [ `is_api_spec_under_source_control` -eq ${TRUE} ]; then
|
||||||
|
local -r API_SPEC_STATUS=`get_api_spec_status`
|
||||||
|
|
||||||
|
if [ -z "${API_SPEC_STATUS}" ]; then
|
||||||
|
echo ${FALSE}
|
||||||
|
else
|
||||||
|
echo ${TRUE}
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
echo ${FALSE}
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
is_nothing_changed_since_last_check()
|
||||||
|
{
|
||||||
|
if [ `is_force_run` -eq ${TRUE} ]; then
|
||||||
|
notice "Force run detected. Skipping commits comparison."
|
||||||
|
echo ${TRUE}
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -z "${COMMIT_FILE_PATH}" ]; then
|
||||||
|
if [ ! -z "${1}" ]; then
|
||||||
|
local -r COMMIT_FILE_PATH=${1}
|
||||||
|
else
|
||||||
|
debug "COMMIT_FILE_PATH should be defined or passed as first argument!"
|
||||||
|
echo ${FALSE}
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ `is_api_spec_under_source_control` -eq ${TRUE} ]; then
|
||||||
|
local -r CURRENT_COMMIT=`get_api_spec_current_commit`
|
||||||
|
|
||||||
|
local -r LAST_CHECKED_COMMIT=`cat ${COMMIT_FILE_PATH} 2> /dev/null || echo ""`
|
||||||
|
|
||||||
|
if [ ${CURRENT_COMMIT} = "${LAST_CHECKED_COMMIT}" ]; then
|
||||||
|
if [ `is_api_spec_has_uncommited_changes` -eq ${TRUE} ]; then
|
||||||
|
notice "API spec has uncomitted changes."
|
||||||
|
echo ${FALSE}
|
||||||
|
else
|
||||||
|
echo ${TRUE}
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
echo ${FALSE}
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
echo ${FALSE}
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
record_current_commit()
|
||||||
|
{
|
||||||
|
if [ `is_force_run` -eq ${TRUE} ]; then
|
||||||
|
notice "Force run detected. Commit won't be recorder."
|
||||||
|
exit ${EXIT_SUCCESS}
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -z "${COMMIT_FILE_PATH}" ]; then
|
||||||
|
if [ ! -v "${1}" ]; then
|
||||||
|
local -r COMMIT_FILE_PATH=${1}
|
||||||
|
else
|
||||||
|
debug "COMMIT_FILE_PATH should be defined or passed as second argument!"
|
||||||
|
return ${EXIT_FAILURE}
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
local -r CURRENT_COMMIT=`get_api_spec_current_commit`
|
||||||
|
|
||||||
|
echo ${CURRENT_COMMIT} > ${COMMIT_FILE_PATH}
|
||||||
|
}
|
||||||
|
|
||||||
|
openapi_codegen()
|
||||||
|
{
|
||||||
|
if [ -z "${OPEN_API_SPEC_PATH}" ]; then
|
||||||
|
if [ ! -v "${1}" ]; then
|
||||||
|
local -r OPEN_API_SPEC_PATH=${1}
|
||||||
|
else
|
||||||
|
debug "OPEN_API_SPEC_PATH should be defined or passed as first argument!"
|
||||||
|
return ${EXIT_FAILURE}
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -z "${OUTPUT_PATH}" ]; then
|
||||||
|
if [ ! -v "${2}" ]; then
|
||||||
|
local -r OUTPUT_PATH=${2}
|
||||||
|
else
|
||||||
|
debug "OUTPUT_PATH should be defined or passed as second argument!"
|
||||||
|
return ${EXIT_FAILURE}
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -z "${VERSION}" ]; then
|
||||||
|
if [ ! -v "${3}" ]; then
|
||||||
|
local -r VERSION=${3}
|
||||||
|
else
|
||||||
|
debug "VERSION should be defined or passed as third argument!"
|
||||||
|
return ${EXIT_FAILURE}
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -z "${API_NAME}" ]; then
|
||||||
|
local -r API_NAME="${PROJECT_NAME}API"
|
||||||
|
fi
|
||||||
|
|
||||||
|
notice "OpenAPI spec generation for ${OPEN_API_SPEC_PATH}"
|
||||||
|
|
||||||
|
local -r CODEGEN_VERSION="3.0.34"
|
||||||
|
|
||||||
|
local -r CODEGEN_FILE_NAME="swagger-codegen-cli-${CODEGEN_VERSION}.jar"
|
||||||
|
local -r CODEGEN_DOWNLOAD_URL="https://repo1.maven.org/maven2/io/swagger/codegen/v3/swagger-codegen-cli/${CODEGEN_VERSION}/${CODEGEN_FILE_NAME}"
|
||||||
|
|
||||||
|
. build-scripts/xcode/aux_scripts/download_file.sh ${CODEGEN_FILE_NAME} ${CODEGEN_DOWNLOAD_URL}
|
||||||
|
|
||||||
|
local -r TINETWORKING_CODEGEN_FILE_NAME="codegen-${VERSION}.jar"
|
||||||
|
|
||||||
|
local -r DOWNLOAD_URL="https://maven.dev.touchin.ru/ru/touchin/codegen/${VERSION}/${TINETWORKING_CODEGEN_FILE_NAME}"
|
||||||
|
|
||||||
|
. build-scripts/xcode/aux_scripts/download_file.sh ${TINETWORKING_CODEGEN_FILE_NAME} ${DOWNLOAD_URL}
|
||||||
|
|
||||||
|
rm -rf ${OUTPUT_PATH}/${API_NAME} # remove previously generated API (if exists)
|
||||||
|
|
||||||
|
local -r OPENAPI_COMMAND="java -cp "Downloads/${CODEGEN_FILE_NAME}:Downloads/${TINETWORKING_CODEGEN_FILE_NAME}" io.swagger.codegen.v3.cli.SwaggerCodegen generate -l TINetworking -i ${OPEN_API_SPEC_PATH} -o ${OUTPUT_PATH} --additional-properties projectName=${API_NAME}"
|
||||||
|
|
||||||
|
exit_on_failure "${OPENAPI_COMMAND}"
|
||||||
|
|
||||||
|
# flatten folders hierarchy
|
||||||
|
|
||||||
|
mv ${OUTPUT_PATH}/${API_NAME}/Classes/Swaggers/* ${OUTPUT_PATH}/${API_NAME}/
|
||||||
|
|
||||||
|
rm -rf ${OUTPUT_PATH}/${API_NAME}/Classes
|
||||||
|
}
|
||||||
|
|
||||||
|
api_generator_codegen()
|
||||||
|
{
|
||||||
|
if [ -z "${API_SPEC_DIR}" ]; then
|
||||||
|
if [ ! -v "${1}" ]; then
|
||||||
|
local -r API_SPEC_DIR=${1}
|
||||||
|
else
|
||||||
|
debug "API_SPEC_DIR should be defined or passed as first argument!"
|
||||||
|
return ${EXIT_FAILURE}
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -z "${OUTPUT_PATH}" ]; then
|
||||||
|
if [ ! -v "${2}" ]; then
|
||||||
|
local -r OUTPUT_PATH=${2}
|
||||||
|
else
|
||||||
|
debug "OUTPUT_PATH should be defined or passed as second argument!"
|
||||||
|
return ${EXIT_FAILURE}
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -z "${VERSION}" ]; then
|
||||||
|
if [ ! -v "${3}" ]; then
|
||||||
|
local -r VERSION=${3}
|
||||||
|
else
|
||||||
|
debug "VERSION should be defined or passed as third argument!"
|
||||||
|
return ${EXIT_FAILURE}
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
notice "api-generator spec generation for ${API_SPEC_DIR}/main.json"
|
||||||
|
|
||||||
|
local -r FILE_NAME="api-generator-${VERSION}.jar"
|
||||||
|
local -r DOWNLOAD_URL="https://maven.dev.touchin.ru/ru/touchin/api-generator/${VERSION}/${FILE_NAME}"
|
||||||
|
|
||||||
|
. build-scripts/xcode/aux_scripts/download_file.sh ${FILE_NAME} ${DOWNLOAD_URL}
|
||||||
|
|
||||||
|
local -r API_GENERATOR_COMMAND="java -Xmx12g -jar Downloads/${FILE_NAME} generate-client-code --output-language SWIFT --specification-path ${API_SPEC_DIR} --output-path ${OUTPUT_PATH} --single-file $(is_single_file)"
|
||||||
|
|
||||||
|
exit_on_failure "${API_GENERATOR_COMMAND}"
|
||||||
|
}
|
||||||
|
|
||||||
|
readonly BUILD_PHASES_DIR=${SRCROOT}/build_phases
|
||||||
|
|
||||||
|
mkdir -p ${BUILD_PHASES_DIR}
|
||||||
|
|
||||||
|
readonly COMMIT_FILE_PATH=${BUILD_PHASES_DIR}/api-generator-commit
|
||||||
|
|
||||||
|
if [ `is_nothing_changed_since_last_check` -eq ${TRUE} ]; then
|
||||||
|
notice "Nothing was changed. API generation skipped."
|
||||||
|
exit ${EXIT_SUCCESS}
|
||||||
|
fi
|
||||||
|
|
||||||
|
readonly VERSION=$1
|
||||||
|
|
||||||
|
if [ -z "${OUTPUT_PATH}" ]; then
|
||||||
|
if [ ! -z "${2}" ]; then
|
||||||
|
readonly OUTPUT_PATH=${2}
|
||||||
|
else
|
||||||
|
readonly OUTPUT_PATH="Generated"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -z "${API_SPEC_DIR}" ]; then
|
||||||
|
readonly API_SPEC_DIR="common/api"
|
||||||
|
fi
|
||||||
|
|
||||||
|
mkdir -p ${OUTPUT_PATH}
|
||||||
|
|
||||||
|
readonly OPEN_API_SPEC_PATH=`find ${API_SPEC_DIR} -maxdepth 1 -name '*.yaml' -o -name '*.yml' | head -n 1`
|
||||||
|
|
||||||
|
if [ -f "${OPEN_API_SPEC_PATH}" ]; then
|
||||||
|
openapi_codegen
|
||||||
|
elif [ -f "${API_SPEC_DIR}/main.json" ]; then
|
||||||
|
api_generator_codegen
|
||||||
|
else
|
||||||
|
notice "No api spec found!"
|
||||||
|
exit ${EXIT_FAILURE}
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ $? -ne ${EXIT_FAILURE} ]; then
|
||||||
|
record_current_commit
|
||||||
|
fi
|
||||||
Binary file not shown.
|
|
@ -0,0 +1,89 @@
|
||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
# Description:
|
||||||
|
# Converts SCRIPT_INPUT_FILE_{N} or SCRIPT_INPUT_FILE_LIST_{N} variables to string that contains
|
||||||
|
# list of file names splitted by given separator.
|
||||||
|
#
|
||||||
|
# Parameters:
|
||||||
|
# $1 - separator to use.
|
||||||
|
# $2 - default value to return if SCRIPT_INPUT_FILE_COUNT or SCRIPT_INPUT_FILE_LIST_COUNT is zero.
|
||||||
|
#
|
||||||
|
# Optional environment variables:
|
||||||
|
# FILE_NAMES_SEPARATOR - separator to use.
|
||||||
|
# DEFAULT_FILE_NAMES - default value if was found in environment variables.
|
||||||
|
# SCRIPT_INPUT_FILE_COUNT - number of files listed in "Input files" section of build phase.
|
||||||
|
# SCRIPT_INPUT_FILE_{N} - file path of specific input file at index.
|
||||||
|
# SCRIPT_INPUT_FILE_LIST_COUNT - number of files listed in "Input File Lists" section of build phase.
|
||||||
|
# SCRIPT_INPUT_FILE_LIST_{N} - file path to specifis xcfilelist file at index.
|
||||||
|
#
|
||||||
|
# Examples of usage:
|
||||||
|
# read_input_file_names
|
||||||
|
# read_input_file_names.sh " " path/to/project
|
||||||
|
#
|
||||||
|
|
||||||
|
has_input_files()
|
||||||
|
{
|
||||||
|
[ ! -z "${SCRIPT_INPUT_FILE_COUNT}" ] && [ ${SCRIPT_INPUT_FILE_COUNT} -gt 0 ]
|
||||||
|
}
|
||||||
|
|
||||||
|
has_input_file_lists()
|
||||||
|
{
|
||||||
|
[ ! -z "${SCRIPT_INPUT_FILE_LIST_COUNT}" ] && [ ${SCRIPT_INPUT_FILE_LIST_COUNT} -gt 0 ]
|
||||||
|
}
|
||||||
|
|
||||||
|
if [ -z "${FILE_NAMES_SEPARATOR}" ]; then
|
||||||
|
if [ ! -z "${1}" ]; then
|
||||||
|
FILE_NAMES_SEPARATOR=${1}
|
||||||
|
else
|
||||||
|
FILE_NAMES_SEPARATOR=" "
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -z "${DEFAULT_FILE_NAMES}" ]; then
|
||||||
|
if [ ! -z "${2}" ]; then
|
||||||
|
DEFAULT_FILE_NAMES=${2}
|
||||||
|
else
|
||||||
|
DEFAULT_FILE_NAMES=""
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
INPUT_FILE_NAMES=""
|
||||||
|
|
||||||
|
if has_input_files && has_input_file_lists; then
|
||||||
|
>&2 echo "Passing Input Files and Input Files Lists is not supported!\nOnly Input Files will be used."
|
||||||
|
fi
|
||||||
|
|
||||||
|
if has_input_files && \
|
||||||
|
[ ${SCRIPT_INPUT_FILE_COUNT} -gt 0 ]; then
|
||||||
|
|
||||||
|
for i in `seq 0 $((${SCRIPT_INPUT_FILE_COUNT}-1))`
|
||||||
|
do
|
||||||
|
SCRIPT_INPUT_FILE_VARIABLE_NAME="SCRIPT_INPUT_FILE_${i}"
|
||||||
|
SHELL_VARIABLE="\${${SCRIPT_INPUT_FILE_VARIABLE_NAME}}"
|
||||||
|
RESOLVED_FILE_NAME=`envsubst <<< ${SHELL_VARIABLE}`
|
||||||
|
|
||||||
|
if [ ! -z ${INPUT_FILE_NAMES} ]; then
|
||||||
|
INPUT_FILE_NAMES=${INPUT_FILE_NAMES}${FILE_NAMES_SEPARATOR}
|
||||||
|
else
|
||||||
|
INPUT_FILE_NAMES=${INPUT_FILE_NAMES}${FILE_NAMES_SEPARATOR}${RESOLVED_FILE_NAME}
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
elif has_input_file_lists; then
|
||||||
|
for i in `seq 0 $((${SCRIPT_INPUT_FILE_LIST_COUNT}-1))`
|
||||||
|
do
|
||||||
|
SCRIPT_INPUT_FILE_LIST_VARIABLE_NAME="SCRIPT_INPUT_FILE_LIST_${i}"
|
||||||
|
SHELL_VARIABLE="\${${SCRIPT_INPUT_FILE_LIST_VARIABLE_NAME}}"
|
||||||
|
FILE_NAME=`envsubst <<< ${SHELL_VARIABLE}`
|
||||||
|
RESOLVED_FILE_NAMES=`envsubst < ${FILE_NAME}`
|
||||||
|
|
||||||
|
for INPUT_FILE_NAME in ${RESOLVED_FILE_NAMES}; do
|
||||||
|
INPUT_FILE_NAMES=${INPUT_FILE_NAMES}${INPUT_FILE_NAME}${FILE_NAMES_SEPARATOR}
|
||||||
|
done
|
||||||
|
done
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -z "${INPUT_FILE_NAMES}" ]; then
|
||||||
|
echo ${DEFAULT_FILE_NAMES}
|
||||||
|
else
|
||||||
|
echo ${INPUT_FILE_NAMES}
|
||||||
|
fi
|
||||||
Binary file not shown.
|
|
@ -0,0 +1,65 @@
|
||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
# Description:
|
||||||
|
# Validates code for copy-paste, prints results to standard output and report file.
|
||||||
|
#
|
||||||
|
# Parameters:
|
||||||
|
# $1 $2 $3 $n - folders to exclude from code checking.
|
||||||
|
#
|
||||||
|
# Required environment variables:
|
||||||
|
# SRCROOT - project directory.
|
||||||
|
# SCRIPT_DIR - directory of current script.
|
||||||
|
#
|
||||||
|
# Optional environment variables:
|
||||||
|
# SCRIPT_INPUT_FILE_COUNT - number of files listed in "Input files" of build phase.
|
||||||
|
# SCRIPT_INPUT_FILE_{N} - file path to directory that should be checked.
|
||||||
|
#
|
||||||
|
# Modified files:
|
||||||
|
# ${SRCROOT}/code-quality-reports/CPDLog.txt - check report.
|
||||||
|
#
|
||||||
|
# Example of usage:
|
||||||
|
# copy_paste_detection.sh Generated Localization Pods
|
||||||
|
#
|
||||||
|
|
||||||
|
EXIT_SUCCESS=0
|
||||||
|
EXIT_FAILURE=1
|
||||||
|
|
||||||
|
if which pmd >/dev/null; then
|
||||||
|
REPORTS_DIR="${SRCROOT}/code-quality-reports"
|
||||||
|
|
||||||
|
SOURCES_DIRS=`. ${SCRIPT_DIR}/common/read_input_file_names.sh " " ${SRCROOT}`
|
||||||
|
|
||||||
|
COMMAND_LINE_ARGUMENTS=$@
|
||||||
|
|
||||||
|
FOLDERS_TO_EXCLUDE=""
|
||||||
|
|
||||||
|
for argument in ${COMMAND_LINE_ARGUMENTS}
|
||||||
|
do
|
||||||
|
FOLDERS_TO_EXCLUDE=${FOLDERS_TO_EXCLUDE}"-or -name ${argument} "
|
||||||
|
done
|
||||||
|
|
||||||
|
FOLDERS_TO_EXCLUDE=`echo ${FOLDERS_TO_EXCLUDE} | cut -c5-` # remove first "-or"
|
||||||
|
|
||||||
|
FILES_TO_EXCLUDE=`find ${SRCROOT} -type d ${FOLDERS_TO_EXCLUDE} | paste -sd " " -`
|
||||||
|
|
||||||
|
mkdir -p ${REPORTS_DIR}
|
||||||
|
|
||||||
|
DIRS_ARGUMENTS=""
|
||||||
|
|
||||||
|
for SOURCE_DIR in ${SOURCES_DIRS}; do
|
||||||
|
DIRS_ARGUMENTS=${DIRS_ARGUMENTS}" --dir "${SOURCE_DIR}
|
||||||
|
done
|
||||||
|
|
||||||
|
pmd cpd ${DIRS_ARGUMENTS} --exclude ${FILES_TO_EXCLUDE} --minimum-tokens 50 --language swift --encoding UTF-8 --format net.sourceforge.pmd.cpd.XMLRenderer --skip-lexical-errors true > ${REPORTS_DIR}/cpd-output.xml
|
||||||
|
|
||||||
|
php ${SCRIPT_DIR}/../aux_scripts/cpd_script.php ${REPORTS_DIR}/cpd-output.xml | tee ${REPORTS_DIR}/CPDLog.txt
|
||||||
|
|
||||||
|
# Make paths relative to SRCROOT, so different developers won't rewrite entire file
|
||||||
|
SED_REPLACEMENT_STRING=$(echo ${SRCROOT} | sed "s/\//\\\\\//g")
|
||||||
|
|
||||||
|
sed -i '' "s/${SED_REPLACEMENT_STRING}//g" "${REPORTS_DIR}/CPDLog.txt"
|
||||||
|
else
|
||||||
|
echo "warning: pmd not installed, install using 'brew install pmd'"
|
||||||
|
|
||||||
|
exit ${EXIT_FAILURE}
|
||||||
|
fi
|
||||||
|
|
@ -0,0 +1,2 @@
|
||||||
|
readonly BUILD_SCRIPTS_DIR=${1:-${PROJECT_DIR}} # first argument or PROJECT_DIR
|
||||||
|
. $BUILD_SCRIPTS_DIR/build-scripts/xcode/aux_scripts/certificates_readme_generator.sh > $PROJECT_DIR/Certificates/README.md
|
||||||
|
|
@ -0,0 +1,22 @@
|
||||||
|
require 'yaml'
|
||||||
|
|
||||||
|
require_relative '../../managers/managers'
|
||||||
|
require_relative '../../templates/templates'
|
||||||
|
|
||||||
|
# Input files paths
|
||||||
|
build_settings_file_path = ARGV[0]
|
||||||
|
generated_features_enum_file_path = ARGV[1]
|
||||||
|
|
||||||
|
build_settings_features_list = Managers::FileManager.load_from_file_YAML(build_settings_file_path)["features"]
|
||||||
|
|
||||||
|
if build_settings_features_list.nil? or build_settings_features_list.empty?
|
||||||
|
raise "There are no features in " + build_settings_file_path
|
||||||
|
end
|
||||||
|
|
||||||
|
# Generate enum Feature Toggles
|
||||||
|
features_enum_template = Templates::FeatureTemplates.features_enum
|
||||||
|
utils = Managers::TemplateManager.new(build_settings_features_list)
|
||||||
|
|
||||||
|
rendered_enum = utils.render(features_enum_template).strip
|
||||||
|
|
||||||
|
Managers::FileManager.save_data_to_file(generated_features_enum_file_path, rendered_enum)
|
||||||
|
|
@ -0,0 +1,19 @@
|
||||||
|
# Input paths
|
||||||
|
readonly BUILD_SETTINGS_FILE_PATH=${1:-${PROJECT_DIR}/common/build_settings.yaml}
|
||||||
|
readonly FEATURES_ENUM_FILE_PATH=${2:-${PROJECT_DIR}/${PRODUCT_NAME}/Resources/Features/Feature.swift}
|
||||||
|
|
||||||
|
# Features enunm generator script
|
||||||
|
readonly CURRENT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )"
|
||||||
|
readonly GENERATOR_SCRIPT=${CURRENT_DIR}/features_generator.rb
|
||||||
|
|
||||||
|
if ! [ -e ${BUILD_SETTINGS_FILE_PATH} ]; then
|
||||||
|
echo "File ${BUILD_SETTINGS_FILE_PATH} does not exist. Add this file and try again."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if ! [ -e ${FEATURES_ENUM_FILE_PATH} ]; then
|
||||||
|
echo "File ${FEATURES_ENUM_FILE_PATH} does not exist. Add this file and try again."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
ruby ${GENERATOR_SCRIPT} ${BUILD_SETTINGS_FILE_PATH} ${FEATURES_ENUM_FILE_PATH}
|
||||||
|
|
@ -0,0 +1,47 @@
|
||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
# Description:
|
||||||
|
# Generates Localizeable.strings and String+Localization.swift files.
|
||||||
|
#
|
||||||
|
# Parameters:
|
||||||
|
# $1 - path to strings folder containing json files.
|
||||||
|
# $2 - path to Localization folder (output).
|
||||||
|
# $3 - Bundle for localization. Default is `.main`.
|
||||||
|
#
|
||||||
|
# Required environment variables:
|
||||||
|
# SCRIPT_DIR - directory of current script.
|
||||||
|
#
|
||||||
|
# Optional environment variables:
|
||||||
|
# PRODUCT_NAME - product name to produce path to localization folder (output).
|
||||||
|
#
|
||||||
|
# Examples of usage:
|
||||||
|
# . localization.sh
|
||||||
|
# . localization.sh common/strings Resources/Localization/ .main
|
||||||
|
#
|
||||||
|
|
||||||
|
readonly EXIT_SUCCESS=0
|
||||||
|
readonly EXIT_FAILURE=1
|
||||||
|
|
||||||
|
. ${SCRIPT_DIR}/../aux_scripts/install_env.sh php
|
||||||
|
|
||||||
|
STRINGS_FOLDER=${1:-"common/strings"}
|
||||||
|
LOCALIZATION_PATH=${2:-"${PRODUCT_NAME}/Resources/Localization/"}
|
||||||
|
BUNDLE=${3:-".main"}
|
||||||
|
|
||||||
|
if ! [ -e ${LOCALIZATION_PATH} ]; then
|
||||||
|
echo "${LOCALIZATION_PATH} path does not exist. Add these folders and try again."
|
||||||
|
exit ${EXIT_FAILURE}
|
||||||
|
fi
|
||||||
|
|
||||||
|
if ! [ -e "${STRINGS_FOLDER}" ]; then
|
||||||
|
echo "${STRINGS_FOLDER} path does not exist. Submodule with strings should be named common and contain strings folder."
|
||||||
|
exit ${EXIT_FAILURE}
|
||||||
|
fi
|
||||||
|
|
||||||
|
if which php >/dev/null; then
|
||||||
|
php ${SCRIPT_DIR}/../aux_scripts/import_strings.php ${LOCALIZATION_PATH} ${STRINGS_FOLDER} ${BUNDLE}
|
||||||
|
else
|
||||||
|
echo "warning: php not installed, install using 'brew install php'"
|
||||||
|
|
||||||
|
exit ${EXIT_FAILURE}
|
||||||
|
fi
|
||||||
|
|
@ -0,0 +1,9 @@
|
||||||
|
# source: https://github.com/iKenndac/verify-string-files
|
||||||
|
|
||||||
|
# first argument set base localization strings path
|
||||||
|
readonly LOCALIZATION_PATH=${1:-${PRODUCT_NAME}/Resources/Localization/Base.lproj/Localizable.strings}
|
||||||
|
|
||||||
|
# second argument set check script path
|
||||||
|
readonly CHECK_SCRIPT=${2:-${PROJECT_DIR}/build-scripts/xcode/build_phases/common/localization_check}
|
||||||
|
|
||||||
|
${CHECK_SCRIPT} -master ${LOCALIZATION_PATH}
|
||||||
|
|
@ -0,0 +1,5 @@
|
||||||
|
class Array
|
||||||
|
def nilOrEmpty?
|
||||||
|
self.nil? or self.empty?
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
@ -0,0 +1,6 @@
|
||||||
|
class CommandUtils
|
||||||
|
def self.make_command(command)
|
||||||
|
command = command.to_s
|
||||||
|
return `#{command}`
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
@ -0,0 +1,35 @@
|
||||||
|
require_relative 'array_extension.rb'
|
||||||
|
require_relative 'command_utils.rb'
|
||||||
|
require_relative 'string_extension.rb'
|
||||||
|
|
||||||
|
class GitСaretaker < CommandUtils
|
||||||
|
def self.get_modified_files
|
||||||
|
non_indexed_files = get_files_from('git diff --name-only | sed s/.*/"&,"/ ')
|
||||||
|
indexed_files = get_files_from('git diff --cached --name-only | sed s/.*/"&,"/ ')
|
||||||
|
|
||||||
|
modified_files = non_indexed_files + indexed_files
|
||||||
|
unique_modified_files = modified_files.uniq
|
||||||
|
|
||||||
|
unique_modified_swift_files = []
|
||||||
|
if not unique_modified_files.nilOrEmpty?
|
||||||
|
unique_modified_swift_files = unique_modified_files.select { |file_path|
|
||||||
|
file_path.to_s.filter_allowed_symbol_into_path
|
||||||
|
file_path.to_s.include? '.swift'
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
return unique_modified_swift_files
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.get_creation_date(file_path)
|
||||||
|
git_command = 'git log --follow --format=%cD --reverse -- ' + file_path + ' | head -1'
|
||||||
|
return make_command(git_command)
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def self.get_files_from(command)
|
||||||
|
files_as_string = make_command(command)
|
||||||
|
return files_as_string.split(',')
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
@ -0,0 +1,78 @@
|
||||||
|
require 'optparse'
|
||||||
|
require 'ostruct'
|
||||||
|
|
||||||
|
require_relative 'array_extension.rb'
|
||||||
|
|
||||||
|
class SettingOption
|
||||||
|
def initialize
|
||||||
|
@options = OpenStruct.new
|
||||||
|
OptionParser.new do |opt|
|
||||||
|
opt.on('-p',
|
||||||
|
'--project_root_path STRING',
|
||||||
|
'The path of project directory and contains *.xcodeproj file always. ' +
|
||||||
|
'Example: project_root_path=~/Projects/MyProject/Source/..') { |option|
|
||||||
|
@options.project_root_path = option
|
||||||
|
}
|
||||||
|
opt.on('-r',
|
||||||
|
'--source_root_path STRING',
|
||||||
|
'The path of source directory and may not contains *.xcodeproj file in some cases. ' +
|
||||||
|
'Example: source_root_path=~/Projects/MyProject/') { |option|
|
||||||
|
@options.source_root_path = option
|
||||||
|
}
|
||||||
|
opt.on('-s',
|
||||||
|
'--swiftlint_executable_path STRING',
|
||||||
|
'The executable path of swiftlint') { |option|
|
||||||
|
@options.swiftlint_executable_path = option
|
||||||
|
}
|
||||||
|
opt.on('-c',
|
||||||
|
'--check_mode MODE',
|
||||||
|
'The mode of check is "fully" or "simplified"') { |option|
|
||||||
|
@options.check_mode = option
|
||||||
|
}
|
||||||
|
opt.on('-u',
|
||||||
|
'--use_multiple BOOL',
|
||||||
|
'The flag indicates the use of multiple yaml swiftlint configurations') { |option|
|
||||||
|
@options.use_multiple = option
|
||||||
|
}
|
||||||
|
opt.on('-d',
|
||||||
|
'--source_date DATE',
|
||||||
|
'The date of grouping files according touchin and old swiftlint rules') { |option|
|
||||||
|
@options.source_date = option
|
||||||
|
}
|
||||||
|
opt.on('-tc',
|
||||||
|
'--touchin_swiftlint_yaml_path STRING',
|
||||||
|
'The path to the touchin swiftlint yaml relative to the source directory') { |option|
|
||||||
|
@options.touchin_swiftlint_yaml_path = option
|
||||||
|
}
|
||||||
|
opt.on('-oc',
|
||||||
|
'--old_swiftlint_yaml_path STRING',
|
||||||
|
'The path to the old swiftlint yaml relative to the source directory') { |option|
|
||||||
|
@options.old_swiftlint_yaml_path = option
|
||||||
|
}
|
||||||
|
end.parse!
|
||||||
|
|
||||||
|
if @options.check_mode.to_s.nilOrEmpty?
|
||||||
|
@options.check_mode = 'fully'
|
||||||
|
end
|
||||||
|
|
||||||
|
if @options.use_multiple.to_s.nilOrEmpty?
|
||||||
|
@options.use_multiple = 'false'
|
||||||
|
end
|
||||||
|
|
||||||
|
if @options.source_root_path.to_s.nilOrEmpty?
|
||||||
|
@options.source_root_path = @options.project_root_path
|
||||||
|
end
|
||||||
|
|
||||||
|
if @options.touchin_swiftlint_yaml_path.to_s.nilOrEmpty?
|
||||||
|
@options.touchin_swiftlint_yaml_path = File.join(project_root_path, 'build-scripts/xcode/.swiftlint.yml')
|
||||||
|
end
|
||||||
|
|
||||||
|
if @options.old_swiftlint_yaml_path.to_s.nilOrEmpty?
|
||||||
|
@options.old_swiftlint_yaml_path = File.join(project_root_path, '.swiftlint.yml')
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def method_missing(method, *args, &block)
|
||||||
|
@options.send(method, *args, &block)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
@ -0,0 +1,161 @@
|
||||||
|
require 'fileutils'
|
||||||
|
require 'tmpdir'
|
||||||
|
|
||||||
|
require_relative 'array_extension.rb'
|
||||||
|
require_relative 'git_caretaker.rb'
|
||||||
|
require_relative 'string_extension.rb'
|
||||||
|
require_relative 'swift_file_manager.rb'
|
||||||
|
require_relative 'yaml_manager.rb'
|
||||||
|
|
||||||
|
class StrategyMaker
|
||||||
|
def initialize(project_root_path, swiftlint_executable_path, touchin_swiftlint_yaml_path, old_swiftlint_yaml_path)
|
||||||
|
@project_root_path = project_root_path
|
||||||
|
@touchin_swiftlint_yaml_path = touchin_swiftlint_yaml_path
|
||||||
|
@old_swiftlint_yaml_path = old_swiftlint_yaml_path
|
||||||
|
|
||||||
|
@temporary_swiftlint_folder_name = Dir.mktmpdir
|
||||||
|
@touchin_swiftlint_yaml_temporary_path = File.join(@temporary_swiftlint_folder_name, '.touchin_swiftlint.yml')
|
||||||
|
@old_swiftlint_yaml_temporary_path = File.join(@temporary_swiftlint_folder_name, '.old_swiftlint.yml')
|
||||||
|
|
||||||
|
@swiftlint_autocorrect_command = swiftlint_executable_path + ' autocorrect --path ' + @project_root_path + ' --config '
|
||||||
|
@swiftlint_lint_command = swiftlint_executable_path + ' --path ' + @project_root_path + ' --config '
|
||||||
|
end
|
||||||
|
|
||||||
|
def run_fully_multiple_strategy(source_date)
|
||||||
|
create_yaml_managers_and_copy_temporary_files
|
||||||
|
|
||||||
|
exclude_files = unique_exclude_files(@touchin_swiftlint_yaml_manager, @old_swiftlint_yaml_manager)
|
||||||
|
|
||||||
|
swift_files = SwiftFileManager.new(exclude_files, source_date)
|
||||||
|
swift_files.find_list_file_paths(@project_root_path)
|
||||||
|
|
||||||
|
total_touchin_excluded_files = exclude_files + swift_files.old_files
|
||||||
|
total_old_excluded_files = exclude_files + swift_files.new_files
|
||||||
|
|
||||||
|
@touchin_swiftlint_yaml_manager.update('excluded', total_touchin_excluded_files)
|
||||||
|
@old_swiftlint_yaml_manager.update('excluded', total_old_excluded_files)
|
||||||
|
|
||||||
|
run_multiple_strategy(@touchin_swiftlint_yaml_temporary_path, @old_swiftlint_yaml_temporary_path)
|
||||||
|
end
|
||||||
|
|
||||||
|
def run_simplified_multiple_strategy(source_date, source_root_path)
|
||||||
|
included_files = GitСaretaker.get_modified_files
|
||||||
|
|
||||||
|
if included_files.nilOrEmpty?
|
||||||
|
puts 'Git did not found swift files to check'
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
create_yaml_managers_and_copy_temporary_files
|
||||||
|
|
||||||
|
exclude_files = unique_exclude_files(@touchin_swiftlint_yaml_manager, @old_swiftlint_yaml_manager)
|
||||||
|
included_files = included_files.map { |file_path| source_root_path + file_path }
|
||||||
|
|
||||||
|
swift_file_manager = SwiftFileManager.new(exclude_files, source_date)
|
||||||
|
swift_file_manager.find_list_file_paths_from(included_files)
|
||||||
|
|
||||||
|
total_touchin_included_files = swift_file_manager.new_files
|
||||||
|
total_old_included_files = swift_file_manager.old_files
|
||||||
|
|
||||||
|
@touchin_swiftlint_yaml_manager.update('excluded', [])
|
||||||
|
@old_swiftlint_yaml_manager.update('excluded', [])
|
||||||
|
|
||||||
|
@touchin_swiftlint_yaml_manager.update('included', total_touchin_included_files)
|
||||||
|
@old_swiftlint_yaml_manager.update('included', total_old_included_files)
|
||||||
|
|
||||||
|
is_exist_total_touchin_included_files = (not total_touchin_included_files.nilOrEmpty?)
|
||||||
|
is_exist_total_old_included_files = (not total_old_included_files.nilOrEmpty?)
|
||||||
|
|
||||||
|
if is_exist_total_touchin_included_files and is_exist_total_old_included_files
|
||||||
|
run_multiple_strategy(@touchin_swiftlint_yaml_temporary_path, @old_swiftlint_yaml_temporary_path)
|
||||||
|
elsif is_exist_total_touchin_included_files and not is_exist_total_old_included_files
|
||||||
|
run_single_strategy(@touchin_swiftlint_yaml_temporary_path)
|
||||||
|
elsif not is_exist_total_touchin_included_files and is_exist_total_old_included_files
|
||||||
|
run_single_strategy(@old_swiftlint_yaml_temporary_path)
|
||||||
|
else
|
||||||
|
puts 'Git did not found swift files to check'
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def run_fully_single_strategy
|
||||||
|
run_single_strategy(@touchin_swiftlint_yaml_path)
|
||||||
|
end
|
||||||
|
|
||||||
|
def run_simplified_single_strategy(source_root_path)
|
||||||
|
included_files = GitСaretaker.get_modified_files
|
||||||
|
|
||||||
|
if included_files.nilOrEmpty?
|
||||||
|
puts 'Git did not found swift files to check'
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
create_copy_temporary_touchin_files
|
||||||
|
|
||||||
|
touchin_swiftlint_yaml_manager = YamlManager.new(@touchin_swiftlint_yaml_temporary_path)
|
||||||
|
touchin_excluded_files = touchin_swiftlint_yaml_manager.get_configuration('excluded')
|
||||||
|
swift_files = SwiftFileManager.new(touchin_excluded_files, '')
|
||||||
|
|
||||||
|
included_files = included_files.select { |file_name| not swift_files.is_excluded_file(file_name) }
|
||||||
|
included_files = included_files.map { |file_path| source_root_path + file_path }
|
||||||
|
|
||||||
|
touchin_swiftlint_yaml_manager.update('excluded', [])
|
||||||
|
touchin_swiftlint_yaml_manager.update('included', included_files)
|
||||||
|
|
||||||
|
if not included_files.nilOrEmpty?
|
||||||
|
run_single_strategy(@touchin_swiftlint_yaml_temporary_path)
|
||||||
|
else
|
||||||
|
puts 'Git found the swift files to check, but they are excluded in yaml'
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def run_single_strategy(swiftlint_yaml_path)
|
||||||
|
result_swiftlint_command = get_swiftlint_command(swiftlint_yaml_path)
|
||||||
|
puts result_swiftlint_command
|
||||||
|
run_bash_command(result_swiftlint_command)
|
||||||
|
end
|
||||||
|
|
||||||
|
def run_multiple_strategy(touchin_swiftlint_yaml_temporary_path, old_swiftlint_yaml_temporary_path)
|
||||||
|
touchin_swiftlint_command = get_swiftlint_command(touchin_swiftlint_yaml_temporary_path)
|
||||||
|
old_swiftlint_command = get_swiftlint_command(old_swiftlint_yaml_temporary_path)
|
||||||
|
result_swiftlint_command = touchin_swiftlint_command + ' && ' + old_swiftlint_command
|
||||||
|
puts result_swiftlint_command
|
||||||
|
run_bash_command(result_swiftlint_command)
|
||||||
|
end
|
||||||
|
|
||||||
|
def get_swiftlint_command(swiftlint_yaml_path)
|
||||||
|
autocorrect_command = @swiftlint_autocorrect_command + swiftlint_yaml_path
|
||||||
|
lint_command = @swiftlint_lint_command + swiftlint_yaml_path
|
||||||
|
return autocorrect_command + ' && ' + lint_command
|
||||||
|
end
|
||||||
|
|
||||||
|
def run_bash_command(bash_command)
|
||||||
|
exit (exec bash_command)
|
||||||
|
end
|
||||||
|
|
||||||
|
def create_yaml_managers_and_copy_temporary_files
|
||||||
|
create_copy_temporary_files
|
||||||
|
|
||||||
|
@touchin_swiftlint_yaml_manager = YamlManager.new(@touchin_swiftlint_yaml_temporary_path)
|
||||||
|
@old_swiftlint_yaml_manager = YamlManager.new(@old_swiftlint_yaml_temporary_path)
|
||||||
|
end
|
||||||
|
|
||||||
|
def create_copy_temporary_files
|
||||||
|
create_copy_temporary_touchin_files
|
||||||
|
FileUtils.cp @old_swiftlint_yaml_path, @old_swiftlint_yaml_temporary_path
|
||||||
|
end
|
||||||
|
|
||||||
|
def create_copy_temporary_touchin_files
|
||||||
|
Dir.mkdir(@temporary_swiftlint_folder_name) unless Dir.exist?(@temporary_swiftlint_folder_name)
|
||||||
|
FileUtils.cp @touchin_swiftlint_yaml_path, @touchin_swiftlint_yaml_temporary_path
|
||||||
|
end
|
||||||
|
|
||||||
|
def unique_exclude_files(touchin_swiftlint_yaml_manager, old_swiftlint_yaml_manager)
|
||||||
|
touchin_excluded_files = touchin_swiftlint_yaml_manager.get_configuration('excluded')
|
||||||
|
old_excluded_files = old_swiftlint_yaml_manager.get_configuration('excluded')
|
||||||
|
common_exclude_files = touchin_excluded_files + old_excluded_files
|
||||||
|
unique_exclude_files = common_exclude_files.uniq
|
||||||
|
return unique_exclude_files
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
@ -0,0 +1,17 @@
|
||||||
|
class String
|
||||||
|
def with_wrapped_whitespace
|
||||||
|
self.gsub(/\s+/, '\ ')
|
||||||
|
end
|
||||||
|
|
||||||
|
def filter_allowed_symbol_into_path
|
||||||
|
self.gsub!(/[^0-9A-Za-z \-+.\/]/, '')
|
||||||
|
end
|
||||||
|
|
||||||
|
def true?
|
||||||
|
self.to_s.downcase == "true"
|
||||||
|
end
|
||||||
|
|
||||||
|
def nilOrEmpty?
|
||||||
|
self.nil? or self.empty?
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
@ -0,0 +1,68 @@
|
||||||
|
require 'fileutils'
|
||||||
|
require 'date'
|
||||||
|
|
||||||
|
require_relative 'git_caretaker.rb'
|
||||||
|
|
||||||
|
class SwiftFileManager
|
||||||
|
def initialize(excluded_files, source_date)
|
||||||
|
if not source_date.nilOrEmpty?
|
||||||
|
@source_date = Date.parse(source_date)
|
||||||
|
end
|
||||||
|
@excluded_files = excluded_files
|
||||||
|
@new_files = []
|
||||||
|
@old_files = []
|
||||||
|
end
|
||||||
|
|
||||||
|
def old_files
|
||||||
|
@old_files
|
||||||
|
end
|
||||||
|
|
||||||
|
def new_files
|
||||||
|
@new_files
|
||||||
|
end
|
||||||
|
|
||||||
|
def find_list_file_paths(start_folder)
|
||||||
|
swift_files = File.join('**', '*.swift')
|
||||||
|
Dir.glob(swift_files, base: start_folder) { |file_path|
|
||||||
|
if not is_excluded_file(file_path)
|
||||||
|
compare_timestamp(file_path)
|
||||||
|
end
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
def find_list_file_paths_from(files_path)
|
||||||
|
files_path.each { |file_path|
|
||||||
|
if not is_excluded_file(file_path)
|
||||||
|
compare_timestamp(file_path)
|
||||||
|
end
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
def is_excluded_file(file_path)
|
||||||
|
@excluded_files.each do |exclude_file_path|
|
||||||
|
if file_path.include? exclude_file_path
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def compare_timestamp(file_path)
|
||||||
|
wrapped_whitespace_file_path = file_path.with_wrapped_whitespace
|
||||||
|
creation_date_string = GitСaretaker.get_creation_date(wrapped_whitespace_file_path)
|
||||||
|
if creation_date_string.nilOrEmpty?
|
||||||
|
@old_files.push(file_path)
|
||||||
|
puts ('Creation date of ' + file_path + ' was not found')
|
||||||
|
else
|
||||||
|
creation_date = Date.parse(creation_date_string)
|
||||||
|
puts ('Creation date of ' + file_path + ' is ' + creation_date.to_s)
|
||||||
|
if @source_date < creation_date
|
||||||
|
@new_files.push(file_path)
|
||||||
|
else
|
||||||
|
@old_files.push(file_path)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
@ -0,0 +1,19 @@
|
||||||
|
#https://github.com/TouchInstinct/Styleguide/blob/multiple_swiftlint/IOS/Guides/BuildScripts/Multiple_Swiftlint_Guide.md
|
||||||
|
require_relative 'setting_option.rb'
|
||||||
|
require_relative 'strategy_maker.rb'
|
||||||
|
|
||||||
|
setting = SettingOption.new
|
||||||
|
strategy_maker = StrategyMaker.new(setting.project_root_path,
|
||||||
|
setting.swiftlint_executable_path,
|
||||||
|
setting.touchin_swiftlint_yaml_path,
|
||||||
|
setting.old_swiftlint_yaml_path)
|
||||||
|
|
||||||
|
if setting.check_mode.eql? 'fully' and setting.use_multiple.true?
|
||||||
|
strategy_maker.run_fully_multiple_strategy(setting.source_date)
|
||||||
|
elsif setting.check_mode.eql? 'fully' and not setting.use_multiple.true?
|
||||||
|
strategy_maker.run_fully_single_strategy
|
||||||
|
elsif setting.check_mode.eql? 'simplified' and setting.use_multiple.true?
|
||||||
|
strategy_maker.run_simplified_multiple_strategy(setting.source_date, setting.source_root_path)
|
||||||
|
elsif setting.check_mode.eql? 'simplified' and not setting.use_multiple.true?
|
||||||
|
strategy_maker.run_simplified_single_strategy(setting.source_root_path)
|
||||||
|
end
|
||||||
|
|
@ -0,0 +1,24 @@
|
||||||
|
require 'yaml'
|
||||||
|
require 'fileutils'
|
||||||
|
|
||||||
|
class YamlManager
|
||||||
|
def initialize(swiftlint_yaml_path)
|
||||||
|
@swiftlint_yaml_path = swiftlint_yaml_path
|
||||||
|
@configuration ||= YAML.load(File.read(@swiftlint_yaml_path))
|
||||||
|
end
|
||||||
|
|
||||||
|
def get_configuration(key)
|
||||||
|
@configuration[key]
|
||||||
|
end
|
||||||
|
|
||||||
|
def update(key, new_configuration_values)
|
||||||
|
@configuration[key] = new_configuration_values
|
||||||
|
save_settings(@configuration)
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def save_settings(settings)
|
||||||
|
File.write(@swiftlint_yaml_path, settings.to_yaml)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
@ -0,0 +1,98 @@
|
||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
# Description:
|
||||||
|
# Runs swiftlint with selected or default config file.
|
||||||
|
# By default it runs only for modified files.
|
||||||
|
#
|
||||||
|
# Parameters:
|
||||||
|
# $1 - path to swiftlint executable.
|
||||||
|
# $2 - path to swiftlint config.
|
||||||
|
#
|
||||||
|
# Required environment variables:
|
||||||
|
# SCRIPT_DIR - directory of current script.
|
||||||
|
# SRCROOT - project directory.
|
||||||
|
#
|
||||||
|
# Optional environment variables:
|
||||||
|
# SWIFTLINT_EXECUTABLE - path to swiftlint executable.
|
||||||
|
# SWIFTLINT_CONFIG_PATH - path to swiftlint config.
|
||||||
|
# PODS_ROOT - cocoapods installation directory (eg. ${SRCROOT}/Pods) if SWIFTLINT_EXECUTABLE or ${1} is missing
|
||||||
|
# SCRIPT_INPUT_FILE_COUNT - number of files listed in "Input files" of build phase.
|
||||||
|
# SCRIPT_INPUT_FILE_{N} - file path to directory that should be checked.
|
||||||
|
# FORCE_LINT - don't exclude not modified files.
|
||||||
|
# AUTOCORRECT - format and fix code before lint.
|
||||||
|
#
|
||||||
|
# Example of usage:
|
||||||
|
# swiftlint.sh
|
||||||
|
# FORCE_LINT=true; swiftlint.sh
|
||||||
|
# swiftlint.sh Pods/Swiftlint/swiftlint build-scripts/xcode/.swiftlint.yml
|
||||||
|
#
|
||||||
|
|
||||||
|
readonly SOURCES_DIRS=`. ${SCRIPT_DIR}/common/read_input_file_names.sh "\n" ${SRCROOT}`
|
||||||
|
|
||||||
|
if [ -z "${SWIFTLINT_EXECUTABLE}" ]; then
|
||||||
|
if [ ! -z "${1}" ]; then
|
||||||
|
readonly SWIFTLINT_EXECUTABLE=${1}
|
||||||
|
elif [ ! -z "${PODS_ROOT}" ]; then
|
||||||
|
readonly SWIFTLINT_EXECUTABLE=${PODS_ROOT}/SwiftLint/swiftlint
|
||||||
|
else
|
||||||
|
readonly SWIFTLINT_EXECUTABLE=${SRCROOT}/Pods/SwiftLint/swiftlint
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -z "${SWIFTLINT_CONFIG_PATH}" ]; then
|
||||||
|
if [ ! -z "${2}" ]; then
|
||||||
|
readonly SWIFTLINT_CONFIG_PATH=${2}
|
||||||
|
else
|
||||||
|
readonly SWIFTLINT_CONFIG_PATH=${SCRIPT_DIR}/../.swiftlint.yml
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ ! -z "${FORCE_LINT}" ]; then
|
||||||
|
# Если задана переменная FORCE_LINT, то проверяем все файлы проекта
|
||||||
|
for SOURCE_DIR in ${SOURCES_DIRS}; do
|
||||||
|
if [ ! -z "${AUTOCORRECT}" ]; then
|
||||||
|
${SWIFTLINT_EXECUTABLE} lint --config ${SWIFTLINT_CONFIG_PATH} --fix --format "${SRCROOT}/${SOURCE_DIR}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
${SWIFTLINT_EXECUTABLE} lint --config ${SWIFTLINT_CONFIG_PATH} "${SRCROOT}/${SOURCE_DIR}"
|
||||||
|
done
|
||||||
|
else
|
||||||
|
# Xcode упадет, если будем использовать большое количество Script Input Files,
|
||||||
|
# так как просто переполнится стек - https://unix.stackexchange.com/questions/357843/setting-a-long-environment-variable-breaks-a-lot-of-commands
|
||||||
|
# Поэтому воспользуемся "скрытым" параметром Swiflint - https://github.com/realm/SwiftLint/pull/3313
|
||||||
|
# Создадим временный файл swiftlint_files с префиксом @ и в нем уже определим список файлов
|
||||||
|
# необходимых для линтовки :)
|
||||||
|
|
||||||
|
lint_files_path=`mktemp`
|
||||||
|
|
||||||
|
# Проходимся по папкам, которые требуют линтовки
|
||||||
|
for SOURCE_DIR in ${SOURCES_DIRS}; do
|
||||||
|
LINE_PREFIX="${SRCROOT}/"
|
||||||
|
|
||||||
|
pushd .
|
||||||
|
|
||||||
|
cd ${SRCROOT} # in case of runing script outside project folder (SPM)
|
||||||
|
|
||||||
|
# Отбираем файлы, которые были изменены или созданы
|
||||||
|
source_unstaged_files=$(git diff --diff-filter=d --name-only --line-prefix=${LINE_PREFIX} ${SOURCE_DIR} | grep "\.swift$")
|
||||||
|
source_staged_files=$(git diff --diff-filter=d --name-only --line-prefix=${LINE_PREFIX} --cached ${SOURCE_DIR} | grep "\.swift$")
|
||||||
|
|
||||||
|
popd
|
||||||
|
|
||||||
|
if [ ! -z "${source_unstaged_files}" ]; then
|
||||||
|
echo "${source_unstaged_files}" >> ${lint_files_path}
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ ! -z "${source_staged_files}" ]; then
|
||||||
|
echo "${source_staged_files}" >> ${lint_files_path}
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
swiftlint_files_path="@${lint_files_path}"
|
||||||
|
|
||||||
|
if [ ! -z "${AUTOCORRECT}" ]; then
|
||||||
|
${SWIFTLINT_EXECUTABLE} lint --config ${SWIFTLINT_CONFIG_PATH} --fix --format --force-exclude --use-alternative-excluding ${swiftlint_files_path}
|
||||||
|
fi
|
||||||
|
|
||||||
|
${SWIFTLINT_EXECUTABLE} lint --config ${SWIFTLINT_CONFIG_PATH} --force-exclude --use-alternative-excluding ${swiftlint_files_path}
|
||||||
|
fi
|
||||||
|
|
@ -0,0 +1,5 @@
|
||||||
|
readonly ARGUMENTS=("$@")
|
||||||
|
readonly IGNORED_FILES=$(IFS=, ; echo "${ARGUMENTS[*]}")
|
||||||
|
readonly SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )"
|
||||||
|
|
||||||
|
ruby ${SCRIPT_DIR}/Unused.rb --config ${SCRIPT_DIR}/../UnusedConfig.yml --exclude ${IGNORED_FILES}
|
||||||
|
|
@ -0,0 +1,8 @@
|
||||||
|
readonly SOURCES_DIR=${1:-${PROJECT_DIR}/${PRODUCT_NAME}} # first argument set product dir
|
||||||
|
readonly UNUSED_RESOURCES_SCRIPT=${2:-${PROJECT_DIR}/build-scripts/xcode/build_phases/common/unused_resources} # second argument set script path
|
||||||
|
readonly REPORTS_DIR=${PROJECT_DIR}/code-quality-reports
|
||||||
|
readonly FILES_TO_EXCLUDE=`find ${SOURCES_DIR} -type d -name Localization -or -name Generated | paste -sd " " -`
|
||||||
|
|
||||||
|
mkdir ${REPORTS_DIR}
|
||||||
|
|
||||||
|
${UNUSED_RESOURCES_SCRIPT} --project ${SOURCES_DIR} --exclude ${FILES_TO_EXCLUDE} --action "l" > ${REPORTS_DIR}/Unused_resources_log.txt
|
||||||
|
|
@ -1,7 +1,9 @@
|
||||||
$appName = File.basename(Dir['../*.xcworkspace'].first, '.*')
|
$appName = File.basename(Dir['../*.xcworkspace'].first, '.*')
|
||||||
|
|
||||||
before_all do |lane, options|
|
require_relative 'fastlane/touchlane/lib/touchlane'
|
||||||
appName = options[:appName] || $appName
|
|
||||||
|
|
||||||
|
private_lane :installDependencies do |options|
|
||||||
podsReposPath = File.expand_path "~/.cocoapods/repos/master/"
|
podsReposPath = File.expand_path "~/.cocoapods/repos/master/"
|
||||||
lockFilePath = "#{podsReposPath}/.git/index.lock"
|
lockFilePath = "#{podsReposPath}/.git/index.lock"
|
||||||
|
|
||||||
|
|
@ -11,61 +13,371 @@ before_all do |lane, options|
|
||||||
end
|
end
|
||||||
|
|
||||||
cocoapods(
|
cocoapods(
|
||||||
clean: true,
|
try_repo_update_on_error: true
|
||||||
repo_update: true
|
|
||||||
)
|
|
||||||
|
|
||||||
set_info_plist_value(
|
|
||||||
path: "./#{appName}/Info.plist",
|
|
||||||
key: "CFBundleVersion",
|
|
||||||
value: options[:buildNumber] || 10000
|
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
|
|
||||||
after_all do |lane, options|
|
private_lane :uploadToFirebase do |options|
|
||||||
if options[:uploadToFabric]
|
releaseNotesFile = "release-notes.txt"
|
||||||
appName = options[:appName] || $appName
|
sh("touch ../#{releaseNotesFile}")
|
||||||
token = sh("cat ../#{appName}.xcodeproj/project.pbxproj | grep 'Fabric/run' | awk '{print $4}' | tr -d '\n'")
|
|
||||||
secret = sh("cat ../#{appName}.xcodeproj/project.pbxproj | grep 'Fabric/run' | awk '{print $5}' | sed 's/..$//' | tr -d '\n'")
|
|
||||||
|
|
||||||
releaseNotesFile = "release-notes.txt"
|
app_target_folder_name = options[:appName] || $appName
|
||||||
sh("touch ../#{releaseNotesFile}")
|
configuration_type = Touchlane::ConfigurationType.from_type(options[:type])
|
||||||
|
|
||||||
crashlytics(
|
gsp_plist_path = get_google_services_plist_path(app_target_folder_name, configuration_type)
|
||||||
ipa_path: "./#{appName}.ipa",
|
|
||||||
crashlytics_path: "./Pods/Crashlytics/",
|
google_app_id = get_info_plist_value(path: gsp_plist_path, key: "GOOGLE_APP_ID")
|
||||||
api_token: token,
|
|
||||||
build_secret: secret,
|
firebase_app_distibution_groups_path = File.expand_path "../firebase_app_distribution_groups"
|
||||||
notes_path: releaseNotesFile,
|
|
||||||
groups: "touch-instinct"
|
# Select groups_file or groups parameter depending on groups file existence
|
||||||
|
if File.exists? firebase_app_distibution_groups_path
|
||||||
|
firebase_app_distribution(
|
||||||
|
app: google_app_id,
|
||||||
|
ipa_path: options[:ipa_path],
|
||||||
|
groups_file: firebase_app_distibution_groups_path,
|
||||||
|
release_notes_file: releaseNotesFile
|
||||||
)
|
)
|
||||||
|
else
|
||||||
upload_symbols_to_crashlytics(
|
firebase_app_distribution(
|
||||||
dsym_path: "./#{appName}.app.dSYM.zip",
|
app: google_app_id,
|
||||||
api_token: token
|
ipa_path: options[:ipa_path],
|
||||||
|
groups: "touch-instinct",
|
||||||
|
release_notes_file: releaseNotesFile
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def upload_to_app_store_using_options(options, submit_for_review = false)
|
||||||
|
upload_to_app_store(
|
||||||
|
username: options[:username] || options[:apple_id],
|
||||||
|
api_key_path: options[:api_key_path],
|
||||||
|
api_key: options[:api_key],
|
||||||
|
ipa: options[:ipa_path],
|
||||||
|
build_number: options[:ipa_path].nil? ? options[:buildNumber] : nil,
|
||||||
|
skip_binary_upload: options[:ipa_path].nil?,
|
||||||
|
skip_screenshots: true,
|
||||||
|
force: true, # skip metainfo prompt
|
||||||
|
submit_for_review: submit_for_review,
|
||||||
|
submission_information: options[:submission_information],
|
||||||
|
skip_metadata: true,
|
||||||
|
team_id: options[:itc_team_id],
|
||||||
|
dev_portal_team_id: options[:team_id],
|
||||||
|
precheck_include_in_app_purchases: false
|
||||||
|
)
|
||||||
|
end
|
||||||
|
|
||||||
|
private_lane :addShield do |options|
|
||||||
|
buildNumber = options[:buildNumber]
|
||||||
|
buildDescription = options[:lane_name] # EnterpriseCustomerDev1WithoutSSLPinningRelease
|
||||||
|
.split(/(?=[A-Z])/) # -> ["Enterprise", "Customer", "Dev1", "Without", "S", "S", "L", "Pinning", "Release"]
|
||||||
|
.map { |v| v.gsub(/[[:lower:]]+/, "") }[1..2] # -> ["E", "C", "D1", "W", "S", "S", "L", "P", "R"] -> ["C", "D1"]
|
||||||
|
.join # -> "CD1"
|
||||||
|
|
||||||
|
begin
|
||||||
|
add_badge(
|
||||||
|
shield: "#{buildDescription}-#{buildNumber}-green",
|
||||||
|
no_badge: true
|
||||||
|
)
|
||||||
|
rescue => error
|
||||||
|
UI.error(error)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
private_lane :buildConfiguration do |options|
|
private_lane :buildConfiguration do |options|
|
||||||
configuration = lane_context[SharedValues::LANE_NAME]
|
options[:appName] = options[:appName] || $appName
|
||||||
method = configuration.start_with?("Enterprise") ? "enterprise" : "development"
|
|
||||||
appName = options[:appName] || $appName
|
lane_name = options[:lane_name] || lane_context[SharedValues::LANE_NAME]
|
||||||
uploadToFabric = options[:uploadToFabric]
|
|
||||||
|
options[:scheme] = options[:scheme] || options[:appName]
|
||||||
|
options[:lane_name] = lane_name
|
||||||
|
|
||||||
|
ipa_name = "#{options[:appName]}.ipa"
|
||||||
|
options[:output_name] = ipa_name
|
||||||
|
|
||||||
|
options[:ipa_path] = "./#{ipa_name}"
|
||||||
|
options[:dsym_path] = "./#{options[:appName]}.app.dSYM.zip"
|
||||||
|
|
||||||
|
options[:xcodeproj_path] = options[:xcodeproj_path] || "../#{options[:appName]}.xcodeproj"
|
||||||
|
options[:workspace] = options[:workspace] || File.expand_path("../#{options[:appName]}.xcworkspace")
|
||||||
|
|
||||||
|
configuration_type = Touchlane::ConfigurationType.from_lane_name(lane_name)
|
||||||
|
options = fill_up_options_using_configuration_type(options, configuration_type, true)
|
||||||
|
|
||||||
|
generate_xcodeproj_if_needed(options)
|
||||||
|
|
||||||
|
openKeychain(options)
|
||||||
|
|
||||||
|
if !options[:buildNumber].nil?
|
||||||
|
increment_build_number(
|
||||||
|
build_number: options[:buildNumber]
|
||||||
|
)
|
||||||
|
end
|
||||||
|
|
||||||
|
installDependencies(options)
|
||||||
|
|
||||||
|
run_code_generation_phase_if_needed(options)
|
||||||
|
|
||||||
|
if !(options[:uploadToFabric] || options[:uploadToAppStore])
|
||||||
|
options[:skip_package_ipa] = true
|
||||||
|
|
||||||
|
install_signing_identities(options)
|
||||||
|
|
||||||
|
buildArchive(options) # check build failures and static analysis
|
||||||
|
end
|
||||||
|
|
||||||
|
if options[:uploadToFabric]
|
||||||
|
install_signing_identities(options)
|
||||||
|
addShield(options)
|
||||||
|
buildArchive(options)
|
||||||
|
uploadToFirebase(options)
|
||||||
|
end
|
||||||
|
|
||||||
|
if options[:uploadToAppStore]
|
||||||
|
options[:include_symbols] = options[:include_symbols].nil? ? true : options[:include_symbols]
|
||||||
|
|
||||||
|
install_signing_identities(options)
|
||||||
|
buildArchive(options)
|
||||||
|
upload_to_app_store_using_options(options, false)
|
||||||
|
end
|
||||||
|
|
||||||
|
upload_symbols_to_crashlytics(
|
||||||
|
gsp_path: get_google_services_plist_path(options[:appName], configuration_type)
|
||||||
|
)
|
||||||
|
end
|
||||||
|
|
||||||
|
private_lane :buildArchive do |options|
|
||||||
|
|
||||||
|
require 'json'
|
||||||
|
|
||||||
icloudEnvironment = options[:iCloudContainerEnvironment] || ""
|
icloudEnvironment = options[:iCloudContainerEnvironment] || ""
|
||||||
exportOptions = icloudEnvironment.to_s.empty? ? {} : {iCloudContainerEnvironment: icloudEnvironment}
|
exportOptions = icloudEnvironment.to_s.empty? ? {} : {iCloudContainerEnvironment: icloudEnvironment}
|
||||||
exportOptions[:compileBitcode] = options[:compileBitcode] || false
|
|
||||||
|
lane_name = options[:lane_name]
|
||||||
|
configuration = options[:configuration]
|
||||||
|
xcodeproj_path = options[:xcodeproj_path]
|
||||||
|
|
||||||
|
xcodes(select_for_current_build_only: true)
|
||||||
|
|
||||||
|
if configuration != "AppStore" # AppStore uses xcconfig choosen in Xcode
|
||||||
|
set_xcconfig_for_configuration_of_project(lane_name, configuration, xcodeproj_path)
|
||||||
|
end
|
||||||
|
|
||||||
gym(
|
gym(
|
||||||
clean: true,
|
clean: true,
|
||||||
workspace: "./#{appName}.xcworkspace",
|
workspace: options[:workspace],
|
||||||
scheme: appName,
|
scheme: options[:scheme],
|
||||||
archive_path: "./",
|
archive_path: "./#{$appName}.xcarchive",
|
||||||
output_directory: "./",
|
buildlog_path: "./",
|
||||||
output_name: "#{appName}.ipa",
|
output_name: options[:output_name],
|
||||||
configuration: configuration,
|
configuration: configuration,
|
||||||
export_method: method,
|
export_method: options[:export_method],
|
||||||
export_options: exportOptions,
|
export_options: exportOptions,
|
||||||
skip_package_ipa: !uploadToFabric
|
skip_package_ipa: options[:skip_package_ipa],
|
||||||
|
include_symbols: options[:include_symbols] || false
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
lane :SubmitForReview do |options|
|
||||||
|
configuration_type = Touchlane::ConfigurationType.from_type("appstore")
|
||||||
|
options = fill_up_options_using_configuration_type(options, configuration_type, false)
|
||||||
|
|
||||||
|
upload_to_app_store_using_options(options, true)
|
||||||
|
end
|
||||||
|
|
||||||
|
lane :InstallDevelopmentSigningIdentities do |options|
|
||||||
|
configuration_type = Touchlane::ConfigurationType.from_type("development")
|
||||||
|
options = fill_up_options_using_configuration_type(options, configuration_type)
|
||||||
|
|
||||||
|
install_signing_identities(options)
|
||||||
|
end
|
||||||
|
|
||||||
|
lane :RefreshProfiles do |options|
|
||||||
|
type = options[:type] || "development"
|
||||||
|
|
||||||
|
configuration_type = Touchlane::ConfigurationType.from_type(type)
|
||||||
|
options = fill_up_options_using_configuration_type(options, configuration_type)
|
||||||
|
|
||||||
|
refresh_profiles(options)
|
||||||
|
end
|
||||||
|
|
||||||
|
lane :ReplaceDevelopmentCertificate do |options|
|
||||||
|
configuration_type = Touchlane::ConfigurationType.from_type("development")
|
||||||
|
options = fill_up_options_using_configuration_type(options, configuration_type, true)
|
||||||
|
|
||||||
|
replace_development_certificate(options)
|
||||||
|
end
|
||||||
|
|
||||||
|
lane :SyncAppStoreIdentities do |options|
|
||||||
|
configuration_type = Touchlane::ConfigurationType.from_type("appstore")
|
||||||
|
options = fill_up_options_using_configuration_type(options, configuration_type, true)
|
||||||
|
|
||||||
|
options[:readonly] = false
|
||||||
|
sync_signing_identities(options)
|
||||||
|
end
|
||||||
|
|
||||||
|
lane :ManuallyUpdateCodeSigning do |options|
|
||||||
|
manually_update_code_signing(get_default_options.merge(options))
|
||||||
|
end
|
||||||
|
|
||||||
|
private_lane :openKeychain do |options|
|
||||||
|
if is_ci?
|
||||||
|
# workaround to avoid duplication problem
|
||||||
|
# https://apple.stackexchange.com/questions/350633/multiple-duplicate-keychain-dbs-that-dont-get-cleaned-up
|
||||||
|
keychain_path = File.expand_path("~/Library/Keychains/#{options[:keychain_name]}")
|
||||||
|
keychain_exists = File.exist?("#{keychain_path}-db") || File.exist?(keychain_path)
|
||||||
|
|
||||||
|
create_keychain(
|
||||||
|
name: options[:keychain_name],
|
||||||
|
password: options[:keychain_password],
|
||||||
|
unlock: true,
|
||||||
|
timeout: 0,
|
||||||
|
add_to_search_list: !keychain_exists
|
||||||
|
)
|
||||||
|
else
|
||||||
|
unlock_keychain(
|
||||||
|
path: options[:keychain_name],
|
||||||
|
password: options[:keychain_password]
|
||||||
|
)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def get_default_options
|
||||||
|
{
|
||||||
|
:git_url => get_signing_identities_path(),
|
||||||
|
:signing_identities_path => get_signing_identities_path(),
|
||||||
|
:storage_mode => Touchlane::LocalStorage::STORAGE_TYPE
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
def get_signing_identities_path
|
||||||
|
File.expand_path "../EncryptedSigningIdentities"
|
||||||
|
end
|
||||||
|
|
||||||
|
def fill_up_options_using_configuration_type(options, configuration_type, keychain_password_required = false)
|
||||||
|
configuration = get_configuration_for_type(configuration_type.type)
|
||||||
|
|
||||||
|
api_key_path = File.expand_path "../fastlane/#{configuration_type.prefix}_api_key.json"
|
||||||
|
is_api_key_file_exists = File.exists?(api_key_path)
|
||||||
|
|
||||||
|
# default_options required to be empty due to the possibility of skipping the configuration type check below
|
||||||
|
|
||||||
|
default_options = get_default_options
|
||||||
|
|
||||||
|
# Check whether configuration type is required to configure one of api key parameters or not
|
||||||
|
|
||||||
|
if configuration_type.is_app_store || configuration_type.is_development
|
||||||
|
|
||||||
|
# Check whether API key JSON file exists or not
|
||||||
|
|
||||||
|
if is_api_key_file_exists
|
||||||
|
|
||||||
|
# If exists then fill in all required information through api_key_path parameter
|
||||||
|
# and set a value to an options` parameter respectively
|
||||||
|
|
||||||
|
default_options[:api_key_path] = api_key_path
|
||||||
|
else
|
||||||
|
|
||||||
|
# If doesn't exist then build api_key parameter through app_store_connect_api_key action
|
||||||
|
# and set a value to an options` parameter respectively also
|
||||||
|
|
||||||
|
default_options[:api_key] = get_app_store_connect_api_key()
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
default_options
|
||||||
|
.merge(configuration.to_options)
|
||||||
|
.merge(get_keychain_options(options, keychain_password_required))
|
||||||
|
.merge(options)
|
||||||
|
end
|
||||||
|
|
||||||
|
def get_app_store_connect_api_key()
|
||||||
|
require 'json'
|
||||||
|
|
||||||
|
api_key_parameters = JSON.parse(ENV['API_KEY_JSON'])
|
||||||
|
|
||||||
|
return app_store_connect_api_key(
|
||||||
|
key_id: api_key_parameters['key_id'],
|
||||||
|
issuer_id: api_key_parameters['issuer_id'],
|
||||||
|
key_content: api_key_parameters['key'],
|
||||||
|
duration: api_key_parameters['duration'],
|
||||||
|
in_house: api_key_parameters['in_house']
|
||||||
|
)
|
||||||
|
end
|
||||||
|
|
||||||
|
def get_keychain_options(options, keychain_password_required = false)
|
||||||
|
keychain_name = options[:keychain_name]
|
||||||
|
keychain_password = options[:keychain_password]
|
||||||
|
|
||||||
|
if is_ci?
|
||||||
|
keychain_name = keychain_name || "ci.keychain"
|
||||||
|
keychain_password = keychain_password || ""
|
||||||
|
elsif keychain_password_required && keychain_password.nil?
|
||||||
|
keychain_password = prompt(
|
||||||
|
text: "Please enter your keychain password (account password): ",
|
||||||
|
secure_text: true
|
||||||
|
)
|
||||||
|
end
|
||||||
|
|
||||||
|
return {:keychain_name => keychain_name, :keychain_password => keychain_password}
|
||||||
|
end
|
||||||
|
|
||||||
|
def get_configuration_for_type(type)
|
||||||
|
config_path = File.expand_path "configurations.yaml"
|
||||||
|
|
||||||
|
configuration = Touchlane::Configuration.from_file(config_path, type)
|
||||||
|
end
|
||||||
|
|
||||||
|
def get_google_services_plist_path(app_target_folder_name, configuration_type)
|
||||||
|
File.expand_path "../#{app_target_folder_name}/Resources/GoogleService-Info.plist"
|
||||||
|
end
|
||||||
|
|
||||||
|
def set_xcconfig_for_configuration_of_project(lane_name, configuration, xcodeproj_path)
|
||||||
|
require 'xcodeproj'
|
||||||
|
|
||||||
|
project = Xcodeproj::Project.open(xcodeproj_path)
|
||||||
|
|
||||||
|
target_to_modify_selector = lambda do |t|
|
||||||
|
supported_product_types = [
|
||||||
|
Xcodeproj::Constants::PRODUCT_TYPE_UTI[:application],
|
||||||
|
Xcodeproj::Constants::PRODUCT_TYPE_UTI[:app_extension],
|
||||||
|
Xcodeproj::Constants::PRODUCT_TYPE_UTI[:framework]
|
||||||
|
]
|
||||||
|
return !t.test_target_type? && supported_product_types.include?(t.product_type)
|
||||||
|
end
|
||||||
|
|
||||||
|
application_targets = project.native_targets.select(&target_to_modify_selector)
|
||||||
|
|
||||||
|
application_targets.each do |target|
|
||||||
|
config_name = target.name + lane_name
|
||||||
|
build_configuration_reference = project.files.select { |f| f.path.start_with?(config_name) }.first
|
||||||
|
|
||||||
|
if !build_configuration_reference.nil? # target has custom xcconfig
|
||||||
|
build_configuration = target.build_configuration_list[configuration]
|
||||||
|
build_configuration.base_configuration_reference = build_configuration_reference
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
project.save()
|
||||||
|
end
|
||||||
|
|
||||||
|
def generate_xcodeproj_if_needed(options)
|
||||||
|
project_yml_path = File.expand_path "../project.yml"
|
||||||
|
|
||||||
|
if !File.exists?(options[:xcodeproj_path]) && File.exists?(project_yml_path)
|
||||||
|
xcodegen(
|
||||||
|
spec: project_yml_path
|
||||||
|
)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
# Build phases
|
||||||
|
|
||||||
|
def run_code_generation_phase_if_needed(options)
|
||||||
|
code_generation_script_path = File.expand_path "../.githooks/scripts/CodeGen.sh"
|
||||||
|
|
||||||
|
if File.exists? code_generation_script_path
|
||||||
|
sh(code_generation_script_path, options[:workspace])
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
Subproject commit a8f072f216684bd7f5563c0211f71d6637a5f92d
|
||||||
|
|
@ -0,0 +1,132 @@
|
||||||
|
require 'json'
|
||||||
|
require 'mustache'
|
||||||
|
require 'yaml'
|
||||||
|
|
||||||
|
require_relative '../fastlane/touchlane/lib/touchlane/configuration_type'
|
||||||
|
|
||||||
|
class String
|
||||||
|
def in_current_dir
|
||||||
|
"#{__dir__}/#{self}"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
class ConfigRenderer
|
||||||
|
class XCConfigKeys
|
||||||
|
DEVELOPMENT_TEAM = "DEVELOPMENT_TEAM"
|
||||||
|
PRODUCT_BUNDLE_IDENTIFIER = "PRODUCT_BUNDLE_IDENTIFIER"
|
||||||
|
CODE_SIGN_STYLE = "CODE_SIGN_STYLE"
|
||||||
|
end
|
||||||
|
|
||||||
|
INHERITED_PREFIX = "$(inherited)"
|
||||||
|
|
||||||
|
private_constant :INHERITED_PREFIX
|
||||||
|
|
||||||
|
def initialize(configurations_file_path, build_parameters_path, configs_folder_name)
|
||||||
|
@configurations_file_path = configurations_file_path
|
||||||
|
@build_parameters_path = build_parameters_path
|
||||||
|
@configs_folder_name = configs_folder_name
|
||||||
|
end
|
||||||
|
|
||||||
|
def render_xconfigs
|
||||||
|
temp_configs_data_file_path = "configs_data.json".in_current_dir
|
||||||
|
generator_path = "build_options_helper/helper.py".in_current_dir
|
||||||
|
template_path = "target_xcconfig.mustache".in_current_dir
|
||||||
|
|
||||||
|
# Create config directory if needed
|
||||||
|
Dir.mkdir(@configs_folder_name) unless Dir.exist?(@configs_folder_name)
|
||||||
|
|
||||||
|
# Call python script and generate configs to config file
|
||||||
|
system("python #{generator_path} -bp #{@build_parameters_path} -o #{__dir__} -r ios_build_settings -p ios")
|
||||||
|
|
||||||
|
# Open settings, configurations and template files
|
||||||
|
target_xcconfig_tempate = File.read(template_path)
|
||||||
|
$configurations = YAML.load(File.open(@configurations_file_path))
|
||||||
|
$config_types = $configurations["types"]
|
||||||
|
|
||||||
|
targets = $configurations["targets"]
|
||||||
|
|
||||||
|
# Run through all target in project
|
||||||
|
targets.each do |target_name, target|
|
||||||
|
|
||||||
|
# Need open everytime, because script make some changes only for this target
|
||||||
|
configs = JSON.load(File.open(temp_configs_data_file_path))
|
||||||
|
|
||||||
|
# Run through all configs
|
||||||
|
configs.each do |config|
|
||||||
|
|
||||||
|
# Take default values
|
||||||
|
distribution_type = Touchlane::ConfigurationType.from_account_type(config["account_type"]).type
|
||||||
|
properties = target[distribution_type]
|
||||||
|
|
||||||
|
# Add properties from settings file
|
||||||
|
properties.each do |key, value|
|
||||||
|
if config["xcconfig_options"].any? { |option| key == option["key"] }
|
||||||
|
config["xcconfig_options"].map! { |option| key == option["key"] ? merge_config_data(key, option["value"], value) : option }
|
||||||
|
else
|
||||||
|
config["xcconfig_options"].append(config_option(key, value))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
# Add missing properties if needed
|
||||||
|
config["xcconfig_options"].concat(generate_missing_properties(target_name, properties, distribution_type))
|
||||||
|
|
||||||
|
# Create settings pack
|
||||||
|
config_data = {
|
||||||
|
"target_name": target_name,
|
||||||
|
"abstract_targets_prefix": target["abstract_targets_prefix"],
|
||||||
|
"configuration": config
|
||||||
|
}
|
||||||
|
|
||||||
|
# Create file for every setting in loop
|
||||||
|
File.open(@configs_folder_name + "/" + target_name + config["name"] + ".xcconfig", 'w') { |file|
|
||||||
|
file.puts(Mustache.render(target_xcconfig_tempate, config_data))
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
# Remove config file, it's trash
|
||||||
|
File.delete(temp_configs_data_file_path) if File.exist?(temp_configs_data_file_path)
|
||||||
|
end
|
||||||
|
|
||||||
|
# Make tuple of key and value become mustache template element
|
||||||
|
def config_option(key, value)
|
||||||
|
return { "key" => key, "value" => value }
|
||||||
|
end
|
||||||
|
|
||||||
|
def merge_config_data(key, config_value, settings_value)
|
||||||
|
if settings_value.start_with?(INHERITED_PREFIX)
|
||||||
|
new_value = settings_value.split(INHERITED_PREFIX).last
|
||||||
|
return config_option(key, config_value + new_value)
|
||||||
|
else
|
||||||
|
return config_option(key, settings_value)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
# Fetch development team from build configuration
|
||||||
|
def fetch_development_team(development_team_key, distribution_type)
|
||||||
|
current_config = $config_types[distribution_type]
|
||||||
|
team_value = current_config["team_id"]
|
||||||
|
return config_option(development_team_key, team_value)
|
||||||
|
end
|
||||||
|
|
||||||
|
# Generate missing properties if needed
|
||||||
|
def generate_missing_properties(target_name, properties, distribution_type)
|
||||||
|
result = []
|
||||||
|
|
||||||
|
# Bundle_id_key should be among the properties (required by fastlane)
|
||||||
|
unless properties.key?(XCConfigKeys::PRODUCT_BUNDLE_IDENTIFIER)
|
||||||
|
raise "#{target_name}: Could not find #{XCConfigKeys::PRODUCT_BUNDLE_IDENTIFIER} for #{distribution_type}"
|
||||||
|
end
|
||||||
|
|
||||||
|
unless properties.key?(XCConfigKeys::DEVELOPMENT_TEAM)
|
||||||
|
result.append(fetch_development_team(XCConfigKeys::DEVELOPMENT_TEAM, distribution_type))
|
||||||
|
end
|
||||||
|
|
||||||
|
unless properties.key?(XCConfigKeys::CODE_SIGN_STYLE)
|
||||||
|
result.append(config_option(XCConfigKeys::CODE_SIGN_STYLE, "Manual"))
|
||||||
|
end
|
||||||
|
|
||||||
|
return result
|
||||||
|
end
|
||||||
|
end
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue