Commit 59834db472101b3577f530c7fb3f991d28518b80

Authored by Jay Berkenbilt
1 parent ece6b6fe

Add documentation for code formatting and contribution guidelines

README-maintainer
... ... @@ -119,6 +119,10 @@ GOOGLE OSS-FUZZ
119 119  
120 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 126 * In a source file, include the header file that declares the source
123 127 class first followed by a blank line. If a config file is needed
124 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 566 steps. See comments in check_abi for additional notes. Running
563 567 "check_abi check-sizes" is run by ctest on Linux when CHECK_SIZES is
564 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.
... ...
... ... @@ -6,7 +6,6 @@ Next
6 6  
7 7 In order:
8 8 * cmake
9   -* code formatting
10 9 * PointerHolder -> shared_ptr
11 10 * ABI including --json default is latest
12 11 * json v2
... ... @@ -38,60 +37,6 @@ Misc
38 37  
39 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 40 cmake
96 41 =====
97 42  
... ...
libqpdf/sph/sph_types.h.new 0 โ†’ 100644
manual/CMakeLists.txt
... ... @@ -40,6 +40,7 @@ SET(MANUAL_DEPS
40 40 index.rst
41 41 installation.rst
42 42 json.rst
  43 + contributing.rst
43 44 library.rst
44 45 license.rst
45 46 linearization.rst
... ...
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 30 library
31 31 weak-crypto
32 32 json
  33 + contributing
33 34 design
34 35 qpdf-job
35 36 linearization
... ...