Commit 59834db472101b3577f530c7fb3f991d28518b80
1 parent
ece6b6fe
Add documentation for code formatting and contribution guidelines
Showing
6 changed files
with
208 additions
and
55 deletions
README-maintainer
| @@ -119,6 +119,10 @@ GOOGLE OSS-FUZZ | @@ -119,6 +119,10 @@ GOOGLE OSS-FUZZ | ||
| 119 | 119 | ||
| 120 | CODING RULES | 120 | CODING RULES |
| 121 | 121 | ||
| 122 | +* Code is formatted with clang-format >= 15. See .clang-format and the | ||
| 123 | + "Code Formatting" section in manual/contributing.rst for details. | ||
| 124 | + See also "CODE FORMATTING" below. | ||
| 125 | + | ||
| 122 | * In a source file, include the header file that declares the source | 126 | * In a source file, include the header file that declares the source |
| 123 | class first followed by a blank line. If a config file is needed | 127 | class first followed by a blank line. If a config file is needed |
| 124 | first, put a blank line between that and the header followed by | 128 | first, put a blank line between that and the header followed by |
| @@ -562,3 +566,36 @@ The check_abi script is responsible for performing many of these | @@ -562,3 +566,36 @@ The check_abi script is responsible for performing many of these | ||
| 562 | steps. See comments in check_abi for additional notes. Running | 566 | steps. See comments in check_abi for additional notes. Running |
| 563 | "check_abi check-sizes" is run by ctest on Linux when CHECK_SIZES is | 567 | "check_abi check-sizes" is run by ctest on Linux when CHECK_SIZES is |
| 564 | on. | 568 | on. |
| 569 | + | ||
| 570 | + | ||
| 571 | +CODE FORMATTING | ||
| 572 | + | ||
| 573 | +* Emacs doesn't indent breaking strings concatenated with + over | ||
| 574 | + lines but clang-format does. It's clearer with clang-format. To | ||
| 575 | + get emacs and clang-format to agree, parenthesize the expression | ||
| 576 | + that builds the concatenated string. | ||
| 577 | + | ||
| 578 | +* With | ||
| 579 | + | ||
| 580 | + long_function(long_function( | ||
| 581 | + args) | ||
| 582 | + | ||
| 583 | + clang-format anchors relative to the first function, and emacs | ||
| 584 | + anchors relative to the second function. Use | ||
| 585 | + | ||
| 586 | + long_function( | ||
| 587 | + // line-break | ||
| 588 | + long_function( | ||
| 589 | + args) | ||
| 590 | + | ||
| 591 | + to resolve. | ||
| 592 | + | ||
| 593 | +In the revision control history, there is a commit around April 3, | ||
| 594 | +2022 with the title "Update some code manually to get better | ||
| 595 | +formatting results" that shows several examples of changing code so | ||
| 596 | +that clang-format produces several results. (In git this is commit | ||
| 597 | +77e889495f7c513ba8677df5fe662f08053709eb.) | ||
| 598 | + | ||
| 599 | +The commit that has the bulk of the automatic reformatting is | ||
| 600 | +12f1eb15ca3fed6310402847559a7c99d3c77847. This could go in a | ||
| 601 | +blame.ignoreRevsFile file for `git blame` if needed. |
TODO
| @@ -6,7 +6,6 @@ Next | @@ -6,7 +6,6 @@ Next | ||
| 6 | 6 | ||
| 7 | In order: | 7 | In order: |
| 8 | * cmake | 8 | * cmake |
| 9 | -* code formatting | ||
| 10 | * PointerHolder -> shared_ptr | 9 | * PointerHolder -> shared_ptr |
| 11 | * ABI including --json default is latest | 10 | * ABI including --json default is latest |
| 12 | * json v2 | 11 | * json v2 |
| @@ -38,60 +37,6 @@ Misc | @@ -38,60 +37,6 @@ Misc | ||
| 38 | 37 | ||
| 39 | Soon: Break ground on "Document-level work" | 38 | Soon: Break ground on "Document-level work" |
| 40 | 39 | ||
| 41 | -Code Formatting | ||
| 42 | -=============== | ||
| 43 | - | ||
| 44 | -Document about code formatting: | ||
| 45 | - | ||
| 46 | -* Use clang-format-15. | ||
| 47 | -* Update README-maintainer about formatting. Mention | ||
| 48 | - | ||
| 49 | - // clang-format off | ||
| 50 | - // clang-format on | ||
| 51 | - | ||
| 52 | - as well as the use of a comment to force a line break. Convention: | ||
| 53 | - // line-break | ||
| 54 | - | ||
| 55 | -* .dir-locals.el -- most of the time, emacs's formatting agrees with | ||
| 56 | - clang-format. When they differ, clang-format is authoritative. | ||
| 57 | - Significant differences: | ||
| 58 | - * clang-format-15 bug that when | ||
| 59 | - | ||
| 60 | - type function(args) | ||
| 61 | - | ||
| 62 | - is longer than 80 characters, the continuation line rule takes | ||
| 63 | - precedence over the break after type rule and the function ends | ||
| 64 | - getting intended. (Find an example and report.) | ||
| 65 | - * Emacs doesn't indent breaking strings concatenated with + over | ||
| 66 | - lines but clang-format does. It's clearer with clang-format. To | ||
| 67 | - get emacs and clang-format to agree, parenthesize the expression | ||
| 68 | - that builds the concatenated string. | ||
| 69 | - * With | ||
| 70 | - | ||
| 71 | - long_function(long_function( | ||
| 72 | - args) | ||
| 73 | - | ||
| 74 | - clang-format anchors relative to the first function, and emacs | ||
| 75 | - anchors relative to the second function. Use | ||
| 76 | - | ||
| 77 | - long_function( | ||
| 78 | - // line-break | ||
| 79 | - long_function( | ||
| 80 | - args) | ||
| 81 | - | ||
| 82 | - to resolve. | ||
| 83 | -* Consider blame.ignoreRevsFile if it seems to help | ||
| 84 | -* Add a script to format the code. | ||
| 85 | - | ||
| 86 | - for i in **/*.cc **/*.c **/*.h **/*.hh; do | ||
| 87 | - clang-format < $i >| $i.new && mv $i.new $i | ||
| 88 | - done | ||
| 89 | - | ||
| 90 | -* Consider a github action to check formatting. I don't want | ||
| 91 | - formatting failures to prevent all the tests from being run. | ||
| 92 | - Alternatively, add running the format script as a release | ||
| 93 | - preparation check like running the spell checker. | ||
| 94 | - | ||
| 95 | cmake | 40 | cmake |
| 96 | ===== | 41 | ===== |
| 97 | 42 |
libqpdf/sph/sph_types.h.new
0 โ 100644
manual/CMakeLists.txt
manual/contributing.rst
0 โ 100644
| 1 | +.. _contributing: | ||
| 2 | + | ||
| 3 | +Contributing to qpdf | ||
| 4 | +==================== | ||
| 5 | + | ||
| 6 | +.. _source-repository: | ||
| 7 | + | ||
| 8 | +Source Repository | ||
| 9 | +----------------- | ||
| 10 | + | ||
| 11 | +The qpdf source code lives at https://github.com/qpdf/qpdf. | ||
| 12 | + | ||
| 13 | +Create issues (bug reports, feature requests) at | ||
| 14 | +https://github.com/qpdf/qpdf/issues. If you have a general question or | ||
| 15 | +topic for discussion, you can create a discussion at | ||
| 16 | +https://github.com/qpdf/qpdf/discussions. | ||
| 17 | + | ||
| 18 | +.. _code-formatting: | ||
| 19 | + | ||
| 20 | +Code Formatting | ||
| 21 | +--------------- | ||
| 22 | + | ||
| 23 | +The qpdf source code is formatting using clang-format โฅ version 15 | ||
| 24 | +with a :file:`.clang-format` file at the top of the source tree. The | ||
| 25 | +:file:`format-code` script reformats all the source code in the | ||
| 26 | +repository. You must have ``clang-format`` in your path, and it must be | ||
| 27 | +at least version 15. | ||
| 28 | + | ||
| 29 | +For emacs users, the :file:`.dir-locals.el` file configures emacs | ||
| 30 | +``cc-mode`` for an indentation style that is similar to but not | ||
| 31 | +exactly like what ``clang-format`` produces. When there are | ||
| 32 | +differences, ``clang-format`` is authoritative. It is not possible to | ||
| 33 | +make ``cc-mode`` and ``clang-format`` exactly match since the syntax | ||
| 34 | +parser in emacs is not as sophisticated. | ||
| 35 | + | ||
| 36 | +Blocks of code that should not be formatted can be surrouned by the | ||
| 37 | +comments ``// clang-format off`` and ``// clang-format on``. Sometimes | ||
| 38 | +clang-format tries to combine lines in ways that are undesirable. In | ||
| 39 | +this case, we follow a convention of adding a comment ``// | ||
| 40 | +line-break`` on its own line. | ||
| 41 | + | ||
| 42 | +For exact details, consult :file:`.clang-format`. Here is a broad, | ||
| 43 | +partial summary of the formatting rules: | ||
| 44 | + | ||
| 45 | +- Use spaces, not tabs. | ||
| 46 | + | ||
| 47 | +- Keep lines to 80 columns when possible. | ||
| 48 | + | ||
| 49 | +- Braces are on their own lines after classes and functions (and | ||
| 50 | + similar top-level constructs) and are compact otherwise. | ||
| 51 | + | ||
| 52 | +- Closing parentheses are attached to the previous material, not not | ||
| 53 | + their own lines. | ||
| 54 | + | ||
| 55 | +The :file:`README-maintainer` file has a few additional notes that are | ||
| 56 | +probably not important to anyone who is not making deep changes to | ||
| 57 | +qpdf. | ||
| 58 | + | ||
| 59 | +.. _automated-testing: | ||
| 60 | + | ||
| 61 | +Automated Tests | ||
| 62 | +--------------- | ||
| 63 | + | ||
| 64 | +The testing style of qpdf has evolved over time. More recent tests | ||
| 65 | +call ``assert()``. Older tests print stuff to standard output and | ||
| 66 | +compare the output against reference files. Many tests are a mixture | ||
| 67 | +of these techniques. | ||
| 68 | + | ||
| 69 | +The `qtest <https://qtest.sourceforge.io>`__ style of testing is to | ||
| 70 | +test everything through the application. So effectively most testing | ||
| 71 | +is "integration testing" or "end-to-end testing". | ||
| 72 | + | ||
| 73 | +For details about ``qtest``, consult the `QTest Manual | ||
| 74 | +<https://qtest.sourceforge.io/doc/qtest-manual.html>`__. As you read | ||
| 75 | +it, keep in mind that, in spite of the recent date on the file, the | ||
| 76 | +vast majority of that documentation is from before 2007 and predates | ||
| 77 | +many test frameworks and approaches that are in use today. | ||
| 78 | + | ||
| 79 | +Notes on testing: | ||
| 80 | + | ||
| 81 | +- In most cases, things in the code are tested through integration | ||
| 82 | + tests, though the test suite is very thorough. Many tests are driven | ||
| 83 | + through the ``qpdf`` CLI. Others are driven through other files in | ||
| 84 | + the ``qpdf`` directory, especially ``test_driver.cc`` and | ||
| 85 | + ``qpdf-ctest.c``. These programs only use the public API. | ||
| 86 | + | ||
| 87 | +- In some cases, there are true "unit tests", but they are exercised | ||
| 88 | + through various stand-alone programs that exercise the library in | ||
| 89 | + particular ways, including some that have access to library | ||
| 90 | + internals. These are in the ``libtests`` directory. | ||
| 91 | + | ||
| 92 | +Coverage | ||
| 93 | +~~~~~~~~ | ||
| 94 | + | ||
| 95 | +You wil see calls to ``QTC::TC`` throughout the code. This is a | ||
| 96 | +"manual coverage" system described in depth in the qtest documentation | ||
| 97 | +linked above. It works by ensuring that ``QTC::TC`` is called sometime | ||
| 98 | +during the test in each configured way. In brief: | ||
| 99 | + | ||
| 100 | +- ``QTC::TC`` takes two mandatory options and an optional one: | ||
| 101 | + | ||
| 102 | + - The first two arguments must be *string literals*. This is because | ||
| 103 | + ``qtest`` finds coverage cases lexically. | ||
| 104 | + | ||
| 105 | + - The first argument is the scope name, usually ``qpdf``. This means | ||
| 106 | + there is a ``qpdf.testcov`` file in the source directory. | ||
| 107 | + | ||
| 108 | + - The second argument is a case name. Each case name appears in | ||
| 109 | + ``qpdf.testcov`` with a number after it, usually ``0``. | ||
| 110 | + | ||
| 111 | + - If the third argument is present, it is a number. ``qtest`` | ||
| 112 | + ensures that the ``QTC::TC`` is called for that scope and case at | ||
| 113 | + least once with the third argument set to every value from ``0`` | ||
| 114 | + to ``n`` inclusive, where ``n`` is the number after the coverage | ||
| 115 | + call. | ||
| 116 | + | ||
| 117 | +- ``QTC::TC`` does nothing unless certain environment variables are | ||
| 118 | + set. Therefore, ``QTC:TC`` calls should have no side effects. (In | ||
| 119 | + some languages, they may be disabled at compile-time, though qpdf | ||
| 120 | + does not actually do this.) | ||
| 121 | + | ||
| 122 | +So, for example, if you have this code: | ||
| 123 | + | ||
| 124 | +.. code-block:: C++ | ||
| 125 | + | ||
| 126 | + QTC::TC("qpdf", "QPDF eof skipping spaces before xref", | ||
| 127 | + skipped_space ? 0 : 1); | ||
| 128 | + | ||
| 129 | + | ||
| 130 | +and this line in `qpdf.testcov`: | ||
| 131 | + | ||
| 132 | +:: | ||
| 133 | + | ||
| 134 | + QPDF eof skipping spaces before xref 1 | ||
| 135 | + | ||
| 136 | +the test suite will only pass if that line of code was called at least | ||
| 137 | +once with ``skipped_space == 0`` and at least once with ``skipped_space | ||
| 138 | +== 1``. | ||
| 139 | + | ||
| 140 | +The manual coverage approach ensures the reader that certain | ||
| 141 | +conditions were covered in testing. Use of ``QTC::TC`` is only part of | ||
| 142 | +the overall strategy. | ||
| 143 | + | ||
| 144 | +I do not require testing on pull requests, but they are appreciated, | ||
| 145 | +and I will not merge any code that is not tested. Often someone will | ||
| 146 | +submit a pull request that is not adequately tested but is a good | ||
| 147 | +contribution. In those cases, I will often take the code, add it with | ||
| 148 | +tests, and accept the changes that way rather than merging the pull | ||
| 149 | +request as submitted. | ||
| 150 | + | ||
| 151 | +Personal Comments | ||
| 152 | +----------------- | ||
| 153 | + | ||
| 154 | +QPDF started as a work project in 2002. The first open source release | ||
| 155 | +was in 2008. While there have been a handful of contributors, the vast | ||
| 156 | +majority of the code was written by one person over many years as a | ||
| 157 | +side project. | ||
| 158 | + | ||
| 159 | +I maintain a very strong commitment to backward compatibility. As | ||
| 160 | +such, there are many aspects of the code that are showing their age. | ||
| 161 | +While I believe the codebase to have high quality, there are things | ||
| 162 | +that I would do differently if I were doing them from scratch today. | ||
| 163 | +Sometimes people will suggest changes that I like but can't accept for | ||
| 164 | +backward compatibility reasons. | ||
| 165 | + | ||
| 166 | +While I welcome contributions and am eager to collaborate with | ||
| 167 | +contributors, I have a high bar. I only accept things I'm willing to | ||
| 168 | +maintain over the long haul, and I am happy to help people get | ||
| 169 | +submissions into that state. |
manual/index.rst
| @@ -30,6 +30,7 @@ documentation, please visit `https://qpdf.readthedocs.io | @@ -30,6 +30,7 @@ documentation, please visit `https://qpdf.readthedocs.io | ||
| 30 | library | 30 | library |
| 31 | weak-crypto | 31 | weak-crypto |
| 32 | json | 32 | json |
| 33 | + contributing | ||
| 33 | design | 34 | design |
| 34 | qpdf-job | 35 | qpdf-job |
| 35 | linearization | 36 | linearization |