File indexing completed on 2024-05-12 04:44:28

0001 #!/bin/bash
0002 
0003 # SPDX-FileCopyrightText: Lukas Sommer <sommerluk@gmail.com>
0004 # SPDX-License-Identifier: BSD-2-Clause OR MIT
0005 
0006 
0007 
0008 
0009 
0010 ################# Configure #################
0011 # The “.” command will execute the given script within the context of
0012 # the current script, which is necessary in order to preserve the
0013 # environment variables that are set by the given script.
0014 . scripts/export-environment.sh
0015 
0016 
0017 
0018 
0019 
0020 ################# Static code check #################
0021 # NOTE Keep the following list synchronized
0022 # between scripts/static-codecheck.sh and src/CMakeLists.txt
0023 PUBLIC_HEADERS="
0024     src/abstractdiagram.h
0025     src/chromahuediagram.h
0026     src/colordialog.h
0027     src/colorpatch.h
0028     src/colorwheel.h
0029     src/constpropagatinguniquepointer.h
0030     src/gradientslider.h
0031     src/importexport.h
0032     src/lchadouble.h
0033     src/lchdouble.h
0034     src/multispinbox.h
0035     src/multispinboxsection.h
0036     src/rgbcolorspacefactory.h
0037     src/settranslation.h
0038     src/wheelcolorpicker.h
0039     src/version.in.hpp
0040     "
0041 CODE_WITHOUT_UNIT_TESTS="src/* tests utils examples"
0042 UNIT_TESTS="autotests/*"
0043 ALL_CODE="$CODE_WITHOUT_UNIT_TESTS $UNIT_TESTS"
0044 
0045 EXCLUDE_PUBLIC_HEADER_FROM_GREP="--exclude=$(echo $PUBLIC_HEADERS | sed 's/ / --exclude=/g')"
0046 
0047 # TODO Test for qDebug() which should not be used never in production
0048 # code. Exception: Unit tests.
0049 
0050 # Search for files that do not start with a byte-order-mark (BOM).
0051 # We do this because Microsoft’s compiler does require a BOM at the start
0052 # of the file in order to interpret it as UTF-8.
0053 grep \
0054     --recursive --exclude-dir=testbed \
0055     --files-without-match $'\xEF\xBB\xBF' \
0056     $ALL_CODE \
0057     | grep \
0058         --perl-regexp "\.(license|txt|icc|qrc|qph|ts|cmake\.in|sh)$" \
0059         --invert-match \
0060     | sed 's/^/Missing byte-order-mark: /'
0061 
0062 # All header files in src/ should have an “@internal” in
0063 # the Doxygen documentation, because when it would be public,
0064 # the header file would not be in src/
0065 grep \
0066     --recursive --exclude-dir=testbed \
0067     $EXCLUDE_PUBLIC_HEADER_FROM_GREP \
0068     --files-without-match $'@internal' \
0069     src/*.h \
0070          | sed 's/^/Missing “@internal” statement in non-public header: /'
0071 
0072 # The public header files should not use “final” because it cannot be removed
0073 # without breaking binary compatibility.
0074 grep \
0075     --recursive --exclude-dir=testbed \
0076     --files-with-matches $'final' \
0077     $PUBLIC_HEADERS \
0078          | sed 's/^/“final” should not show up in public headers: /'
0079 
0080 # All public header files should use
0081 # the PERCEPTUALCOLOR_IMPORTEXPORT macro.
0082 grep \
0083     --recursive --exclude-dir=testbed \
0084     --files-without-match $'PERCEPTUALCOLOR_IMPORTEXPORT' \
0085     $PUBLIC_HEADERS \
0086          | sed 's/^/Missing PERCEPTUALCOLOR_IMPORTEXPORT macro in public header: /'
0087 
0088 # All non-public code should not use the PERCEPTUALCOLOR_IMPORTEXPORT macro.
0089 grep \
0090     --recursive --exclude-dir={testbed,include} \
0091     $EXCLUDE_PUBLIC_HEADER_FROM_GREP \
0092     --files-with-matches $'PERCEPTUALCOLOR_IMPORTEXPORT' \
0093     $CODE_WITHOUT_UNIT_TESTS \
0094          | sed 's/^/Internal files may not use PERCEPTUALCOLOR_IMPORTEXPORT macro: /'
0095 
0096 # Do not use constexpr in public headers as when we change the value
0097 # later, compile time value and run time value might be different, and
0098 # that might be dangerous.
0099 grep \
0100     --recursive --exclude-dir=testbed \
0101     --fixed-strings "constexpr" \
0102     $PUBLIC_HEADERS \
0103          | sed 's/^/Public headers may not use constexpr: /'
0104 
0105 # Search for some patterns that should not be used in the source code. If
0106 # these patterns are found, a message is displayed. Otherwise, nothing is
0107 # displayed.
0108 
0109 # We do not include LittleCMS headers like lcms2.h in the public API of our
0110 # library. But it is only be an internal dependency; library users should
0111 # not need to care about that. Therefore, we grab all lines that contain
0112 # identifiers starting with “cms” (except when in lines starting with
0113 # “using”). This search is not done for all code directories, but only
0114 # for files within the include directory (public API).
0115 grep \
0116     --recursive --exclude-dir=testbed \
0117     --perl-regexp "^cms" \
0118     $PUBLIC_HEADERS \
0119          | sed 's/^/Do not expose LittleCMS’ API in our public API: /'
0120 grep \
0121     --recursive --exclude-dir=testbed \
0122     --perl-regexp "[^a-zA-Z]cms[a-zA-Z0-9]" \
0123     $PUBLIC_HEADERS \
0124     | grep \
0125         --perl-regexp "\<tt\>cms" \
0126         --invert-match \
0127          | sed 's/^/Do not expose LittleCMS’ API in our public API: /'
0128 grep \
0129     --recursive --exclude-dir=testbed \
0130     --fixed-strings "lcms2.h" \
0131     $PUBLIC_HEADERS \
0132          | sed 's/^/Do not expose LittleCMS’ API in our public API: /'
0133 
0134 # -> Do not use the “code” and “endcode” tags for Doxygen documentation. Use
0135 #    @snippet instead! That allows that the example code is actually compiled
0136 #    and that helps detecting errors.
0137 grep \
0138     --recursive --exclude-dir=testbed \
0139     --perl-regexp "(@|\\\\)code(?!\{\.unparsed\})" \
0140     $ALL_CODE \
0141          | sed 's/^/Use snippets instead of “code” or “endcode”. (Exception: @code{.unparsed} is allowed.): /'
0142 
0143 # -> Doxygen style: Do not use “@em xyz”. Prefer instead “<em>xyz</em>” which
0144 #    might be longer, but has a clearer start point and end point, which is
0145 #    better when non-letter characters are involved. The @ is reserved
0146 #    for @ref with semantically tested references.
0147 # -> Same thing for “@c xyz”: Prefer instead “<tt>xyz</tt>”.
0148 grep \
0149     --recursive --exclude-dir=testbed \
0150     --fixed-strings "\\em" \
0151     $ALL_CODE \
0152          | sed 's/^/Use HTML tags instead of Doxygen commands for “em”: /'
0153 grep \
0154     --recursive --exclude-dir=testbed \
0155     --fixed-strings "@em" \
0156     $ALL_CODE \
0157          | sed 's/^/Use HTML tags instead of Doxygen commands for “em”: /'
0158 grep \
0159     --recursive --exclude-dir=testbed \
0160     --fixed-strings "\\c" \
0161     $ALL_CODE \
0162          | sed 's/^/Use HTML tags instead of Doxygen commands for “em”: /'
0163 grep \
0164    --recursive --exclude-dir=testbed  \
0165     --perl-regexp "@c(?=([^a-zA-Z]|$))" \
0166     $ALL_CODE \
0167          | sed 's/^/Use HTML tags instead of Doxygen commands for “em”: /'
0168 
0169 # -> Coding style: Do not use the “NULL” macro, but its counterpart “nullptr”
0170 #    which is more type save.
0171 grep \
0172     --recursive --exclude-dir=testbed \
0173     --fixed-strings "NULL" \
0174     $ALL_CODE \
0175          | sed 's/^/Do not use the NULL macro: /'
0176 
0177 # -> Coding style: Do not use inline functions. If used in a header,
0178 #    once exposed, they cannot be changed without breaking binary
0179 #    compatibility, because applications linking against the library
0180 #    will always execute the inline function version against they where
0181 #    compiled, and never the inline function of the library version
0182 #    against they are linking at run-time. This make maintaining binary
0183 #    compatibility much harder, for little benefit.
0184 #
0185 #    However, “static inline” variables are good for the headers or
0186 #    private PIMPL classes, because differently to “simple” “static”
0187 #    variables they allow the definition within the very same header,
0188 #    which is not only easier to read, but also protects against
0189 #    a double definition in different compiler units.
0190 grep \
0191     --recursive --exclude-dir=testbed \
0192     --perl-regexp "(^|[^a-zA-Z0-9\-])inline(?![^()\/;]*=.*;)" \
0193     $ALL_CODE \
0194          | sed 's/^/Do not use inline functions respectively define inline variables at the same line.: /'
0195 
0196 # -> In some Qt classes, devicePixelRatio() returns in integer.
0197 #    Don’t do that and use floating point precision instead. Often,
0198 #    devicePixelRatioF() is an alternative that provides
0199 #    a qreal return value.
0200 grep \
0201     --recursive --exclude-dir=testbed \
0202     --perl-regexp "devicePixelRatio(?!F)" \
0203     $CODE_WITHOUT_UNIT_TESTS \
0204          | sed 's/^/Use devicePixelRatioF instead of devicePixelRatio: /'
0205 
0206 # Qt’s documentation about QImage::Format says: For optimal performance only
0207 # use the format types QImage::Format_ARGB32_Premultiplied,
0208 # QImage::Format_RGB32 or QImage::Format_RGB16. Any other format, including
0209 # QImage::Format_ARGB32, has significantly worse performance.
0210 grep \
0211     --recursive --exclude-dir=testbed \
0212     --perl-regexp "QImage::Format_(?!(ARGB32_Premultiplied|RGB32|RGB16))" \
0213     $ALL_CODE \
0214          | sed 's/^/Use exclusively ARGB32_Premultiplied or RGB32 or RGB16 as QImage formats: /'
0215 
0216 # -> QLatin1String and QLatin1Char dates from the pre-Unicode epoch. It should
0217 #    not be used anymore at all, yet to avoid confusion. Though the Clazy
0218 #    codecheck suggests to use QLatin1String() instead of an empty
0219 #    QStringLiteral because of a slight performance gain, this might not
0220 #    compensate for the less readable code. Alternatively, QString() might be
0221 #    used to avoid Clazy warnings.
0222 grep \
0223     --recursive --exclude-dir=testbed \
0224     --fixed-strings "QLatin1" \
0225     $ALL_CODE \
0226          | sed 's/^/QLatin1String or QLatin1Char: If emtpy, use substitute by QString(), otherwise by QStringLiteral.: /'
0227 
0228 # When using Doxygen snippets, don’t do this within a namespace. As they are
0229 # meant for documentation, they should always contain fully-qualified
0230 # names to make sure that they always work.
0231 #
0232 # As it is complicate to know if the snippet is actually within a namespace
0233 # (namespaces can be opened, but also be closed again), instead we do a
0234 # simplified check: We simply check if there are Doxygen snippets after the
0235 # very first usage of the “namespace” keyword.
0236 #
0237 # 1) Display all the files that are unit tests (adding “/*” to the UNIT_TESTS
0238 #    variable to make sure to get a file list that “cat” will understand.
0239 # 2) For each file, get all lines starting from the first occurrence
0240 #    of “namespace”, using sed.
0241 # 3) Now, filter only those who actually contain snippet definitions
0242 #    starting with “//!”, using grep.
0243 for FILE in $UNIT_TESTS
0244 do
0245     cat $FILE 2>/dev/null \
0246         | sed -n -e '/\([^a-zA-Z]namespace\)\|\(^namespace\)/,$p' \
0247         | grep --fixed-strings "//!" \
0248         | sed 's/^/When using snippets, don’t do this after having used the “namespace” keyword: /'
0249 done