2018-05-07 02:27:11 +00:00
#!/usr/bin/env bash
# For code formatting we have clang-format.
#
# But it's not sane to apply clang-format for whole code base,
# because it sometimes makes worse for properly formatted files.
#
# It's only reasonable to blindly apply clang-format only in cases
# when the code is likely to be out of style.
#
# For this purpose we have a script that will use very primitive heuristics
# (simple regexps) to check if the code is likely to have basic style violations.
# and then to run formatter only for the specified files.
ROOT_PATH=$(git rev-parse --show-toplevel)
2020-02-17 19:09:56 +00:00
EXCLUDE_DIRS='build/|integration/|widechar_width/|glibc-compatibility/|memcpy/|consistent-hashing'
2018-05-07 02:27:11 +00:00
2020-04-05 23:51:26 +00:00
find $ROOT_PATH/{src,base,programs,utils} -name '*.h' -or -name '*.cpp' 2>/dev/null |
2020-02-17 19:09:56 +00:00
grep -vP $EXCLUDE_DIRS |
2020-04-05 23:57:24 +00:00
xargs grep $@ -P '((class|struct|namespace|enum|if|for|while|else|throw|switch).*|\)(\s*const)?(\s*override)?\s*)\{$|\s$|^ {1,3}[^\* ]\S|\t|^\s*(if|else if|if constexpr|else if constexpr|for|while|catch|switch)\(|\( [^\s\\]|\S \)' |
# a curly brace not in a new line, but not for the case of C++11 init or agg. initialization | trailing whitespace | number of ws not a multiple of 4, but not in the case of comment continuation | missing whitespace after for/if/while... before opening brace | whitespaces inside braces
2018-11-24 01:48:06 +00:00
grep -v -P '(//|:\s+\*|\$\(\()| \)"'
2019-06-13 10:45:32 +00:00
# single-line comment | continuation of a multiline comment | a typical piece of embedded shell code | something like ending of raw string literal
2020-04-05 23:57:24 +00:00
# Tabs
find $ROOT_PATH/{src,base,programs,utils} -name '*.h' -or -name '*.cpp' 2>/dev/null |
grep -vP $EXCLUDE_DIRS |
xargs grep $@ -F $'\t'
2019-06-13 10:45:32 +00:00
# // namespace comments are unneeded
2020-04-05 23:51:26 +00:00
find $ROOT_PATH/{src,base,programs,utils} -name '*.h' -or -name '*.cpp' 2>/dev/null |
2020-02-17 19:09:56 +00:00
grep -vP $EXCLUDE_DIRS |
2019-06-13 10:45:32 +00:00
xargs grep $@ -P '}\s*//+\s*namespace\s*'
2019-08-23 15:10:33 +00:00
# Broken symlinks
2020-02-17 19:09:56 +00:00
find -L $ROOT_PATH -type l 2>/dev/null | grep -v contrib && echo "^ Broken symlinks found"
2019-08-23 18:30:04 +00:00
# Double whitespaces
2020-04-05 23:51:26 +00:00
find $ROOT_PATH/{src,base,programs,utils} -name '*.h' -or -name '*.cpp' 2>/dev/null | while read i; do $ROOT_PATH/utils/check-style/double-whitespaces.pl < $i || echo -e "^ File $i contains double whitespaces\n"; done
2020-02-25 14:35:37 +00:00
# Unused ErrorCodes
2020-02-25 18:20:08 +00:00
# NOTE: to fix automatically, replace echo with:
# sed -i "/extern const int $code/d" $file
2020-04-05 23:51:26 +00:00
find $ROOT_PATH/{src,base,programs,utils} -name '*.h' -or -name '*.cpp' | xargs grep -l -P 'extern const int [_A-Z]+' | while read file; do grep -P 'extern const int [_A-Z]+;' $file | sed -r -e 's/^.*?extern const int ([_A-Z]+);.*?$/\1/' | while read code; do grep -q "ErrorCodes::$code" $file || echo "ErrorCode $code is defined but not used in file $file"; done; done
2020-02-25 14:35:37 +00:00
# Undefined ErrorCodes
2020-02-25 18:20:08 +00:00
# NOTE: to fix automatically, replace echo with:
# ( grep -q -F 'namespace ErrorCodes' $file && sed -i -r "0,/(\s*)extern const int [_A-Z]+/s//\1extern const int $code;\n&/" $file || awk '{ print; if (ns == 1) { ns = 2 }; if (ns == 2) { ns = 0; print "namespace ErrorCodes\n{\n extern const int '$code';\n}" } }; /namespace DB/ { ns = 1; };' < $file > ${file}.tmp && mv ${file}.tmp $file )
2020-04-05 23:51:26 +00:00
find $ROOT_PATH/{src,base,programs,utils} -name '*.h' -or -name '*.cpp' | xargs grep -l -P 'ErrorCodes::[_A-Z]+' | while read file; do grep -P 'ErrorCodes::[_A-Z]+' $file | sed -r -e 's/^.*?ErrorCodes::([_A-Z]+).*?$/\1/' | while read code; do grep -q "extern const int $code" $file || echo "ErrorCode $code is used in file $file but not defined"; done; done
2020-02-25 14:35:37 +00:00
# Duplicate ErrorCodes
2020-04-05 23:51:26 +00:00
find $ROOT_PATH/{src,base,programs,utils} -name '*.h' -or -name '*.cpp' | xargs grep -l -P 'ErrorCodes::[_A-Z]+' | while read file; do grep -P 'extern const int [_A-Z]+;' $file | sort | uniq -c | grep -v -P ' +1 ' && echo "Duplicate ErrorCode in file $file"; done
2020-03-03 02:45:20 +00:00
# Three or more consecutive empty lines
2020-04-05 23:51:26 +00:00
find $ROOT_PATH/{src,base,programs,utils} -name '*.h' -or -name '*.cpp' | while read file; do awk '/^$/ { ++i; if (i > 2) { print "More than two consecutive empty lines in file '$file'" } } /./ { i = 0 }' $file; done
2020-03-07 03:28:03 +00:00
# Broken XML files (requires libxml2-utils)
2020-04-05 23:51:26 +00:00
find $ROOT_PATH/{src,base,programs,utils} -name '*.xml' | xargs xmllint --noout --nonet
2020-04-11 15:54:16 +00:00
# Machine translation to Russian is strictly prohibited
find $ROOT_PATH/docs/ru -name '*.md' | xargs grep -l -F 'machine_translated: true'
2020-06-20 06:28:19 +00:00
# Tests should not be named with "fail" in their names. It makes looking at the results less convenient.
find $ROOT_PATH/tests/queries -iname '*fail*' | grep . && echo 'Tests should not be named with "fail" in their names. It makes looking at the results less convenient when you search for "fail" substring in browser.'
2020-08-06 03:13:02 +00:00
# All the submodules should be from https://github.com/
find $ROOT_PATH -name '.gitmodules' | while read i; do grep -F 'url = ' $i | grep -v -F 'https://github.com/' && echo 'All the submodules should be from https://github.com/'; done
2020-08-08 02:08:36 +00:00
# There shouldn't be any code snippets under GPL or LGPL
find $ROOT_PATH/{src,base,programs} -name '*.h' -or -name '*.cpp' 2>/dev/null | xargs grep -i -F 'General Public License' && echo "There shouldn't be any code snippets under GPL or LGPL"
2020-08-08 01:42:00 +00:00
# Check for typos in code
CURDIR=$(dirname "${BASH_SOURCE[0]}")
"${CURDIR}"/check-typos
2020-08-16 11:57:21 +00:00
2020-08-08 23:26:59 +00:00
# Check sh tests with Shellcheck
(cd $ROOT_PATH/tests/queries/0_stateless/ && shellcheck --check-sourced --external-sources --severity info --exclude SC1071,SC2086 *.sh ../1_stateful/*.sh)
2020-08-15 16:49:22 +00:00
2020-08-14 14:41:03 +00:00
# There shouldn't be any docker containers outside docker directory
find $ROOT_PATH -not -path $ROOT_PATH'/docker*' -not -path $ROOT_PATH'/contrib*' -name Dockerfile -type f 2>/dev/null | xargs --no-run-if-empty -n1 echo "Please move Dockerfile to docker directory:"
# There shouldn't be any docker compose files outside docker directory
2020-08-15 04:23:23 +00:00
#find $ROOT_PATH -not -path $ROOT_PATH'/tests/testflows*' -not -path $ROOT_PATH'/docker*' -not -path $ROOT_PATH'/contrib*' -name '*compose*.yml' -type f 2>/dev/null | xargs --no-run-if-empty grep -l "version:" | xargs --no-run-if-empty -n1 echo "Please move docker compose to docker directory:"
2020-08-19 09:40:28 +00:00
# Check that ya.make files are auto-generated
"$ROOT_PATH"/utils/generate-ya-make/generate-ya-make.sh
git status -uno | grep ya.make && echo "ya.make files should be generated with utils/generate-ya-make/generate-ya-make.sh"