|
| 1 | +# Contributing to Doxide |
| 2 | + |
| 3 | +Contributions to Doxide are welcome via a pull request to the [GitHub repository](https://github.com/lawmurray/doxide). Similarly, bug reports and feature suggestions can be made by [opening an issue](https://github.com/lawmurray/doxide/issues), and questions asked by [starting a discussion](https://github.com/lawmurray/doxide/discussions). |
| 4 | + |
| 5 | +There are many ways to contribute code to Doxide. To do so you will need knowledge of C++, and may need to learn how to use [Tree-sitter](https://tree-sitter.github.io/tree-sitter/) to parse and query a C++ source files. A brief how-to on the latter is given here . |
| 6 | + |
| 7 | +When developing Doxide, you will need to build it from source, and rebuild it from source after making any changes. See the [README.md](https://github.com/lawmurray/doxide?tab=readme-ov-file#installation) file for instructions on working from source. |
| 8 | + |
| 9 | +## Using Tree-sitter |
| 10 | + |
| 11 | +Install the `tree-sitter` command-line interface. This will depend on your operating system. It is widely available in Linux distributions. Once installed you may need to configure it for the first time: |
| 12 | +``` |
| 13 | +tree-sitter init-config |
| 14 | +``` |
| 15 | + |
| 16 | +There may not be a C++ parser installed by default, and at any rate Doxide is written to a specific version of a specific parser. That parser can be found in the `contrib/tree-sitter-cuda` directory, which is a submodule tracking the [tree-sitter-cuda](https://github.com/tree-sitter-grammars/tree-sitter-cuda) CUDA parser, which is based on the [tree-sitter-cpp](https://github.com/tree-sitter/tree-sitter-cpp) C++ parser, which is based on the [tree-sitter-c](https://github.com/tree-sitter/tree-sitter-c) C parser. CUDA is a superset of C++ is sort-of-a-superset of C and so Doxide currently uses the CUDA parser. |
| 17 | + |
| 18 | +From within the `contrib/tree-sitter-cuda` directory, run, for example: |
| 19 | +``` |
| 20 | +tree-sitter parse ../../demo/parsing.hpp |
| 21 | +``` |
| 22 | +This will parse the given file and output the parse tree to the terminal. |
| 23 | + |
| 24 | +## Fixing an issue: a walkthrough |
| 25 | + |
| 26 | +This is a walkthrough of fixing issue [#50](https://github.com/lawmurray/doxide/issues/50) reported on the Doxide GitHub repository. The issue was that Doxide would miss variables that had an array type: |
| 27 | +```cpp |
| 28 | +/** |
| 29 | + * Test member variable of array type. |
| 30 | + */ |
| 31 | +int arr[10]; |
| 32 | +``` |
| 33 | +They would not be included in the documentation, and their documentation comment would be attributed to the next entity. |
| 34 | + |
| 35 | +To reproduce the issue: |
| 36 | + |
| 37 | +1. Add code such as the above to `demo/parsing.hpp` as a test case. |
| 38 | + |
| 39 | +2. From the root directory of the code repository, build the Doxide documentation and publish it with MkDocs: |
| 40 | +``` |
| 41 | +doxide build |
| 42 | +mkdocs serve |
| 43 | +``` |
| 44 | + |
| 45 | +3. Point your browser to `localhost:8000`. This is actually the whole Doxide website that you see at [doxide.org](https://doxide.org). Confirm that the bug is apparent by navigating to the *Demo > Parsing* section. (Of course you won't see issue [#50](https://github.com/lawmurray/doxide/issues/50) anymore---it has been fixed!) |
| 46 | + |
| 47 | +To fix the problem, we can start by seeing how Tree-sitter parses the code. Back in the `contrib/tree-sitter-cuda` directory, put the above code in a file called `test.cpp` and run: |
| 48 | +``` |
| 49 | +tree-sitter parse test.cpp |
| 50 | +``` |
| 51 | +The output is: |
| 52 | +``` |
| 53 | +(translation_unit [0, 0] - [4, 0] |
| 54 | + (comment [0, 0] - [2, 3]) |
| 55 | + (declaration [3, 0] - [3, 12] |
| 56 | + type: (primitive_type [3, 0] - [3, 3]) |
| 57 | + declarator: (array_declarator [3, 4] - [3, 11] |
| 58 | + declarator: (identifier [3, 4] - [3, 7]) |
| 59 | + size: (number_literal [3, 8] - [3, 10])))) |
| 60 | +``` |
| 61 | + |
| 62 | +!!! tip |
| 63 | + We could run `tree-sitter parse ../../demo/parsing.hpp` instead, but the parse tree is much larger, and it may be difficult to track down the specific problem that way. |
| 64 | + |
| 65 | +Now, bring up the source file `src/doxide.cpp`, where Doxide's Tree-sitter queries are given as hard-coded strings in the `query_cpp` variable. These are patterns that match parse trees to select entities (e.g. types, variables, functions, macros, etc) from the source code to document. This section in particular plucks out variables and member variables: |
| 66 | +``` |
| 67 | +;; variable |
| 68 | +((declaration |
| 69 | + declarator: [ |
| 70 | + (identifier) @name |
| 71 | + (reference_declarator (identifier) @name) |
| 72 | + (pointer_declarator (identifier) @name) |
| 73 | + (init_declarator |
| 74 | + declarator: [ |
| 75 | + (identifier) @name |
| 76 | + (reference_declarator (identifier) @name) |
| 77 | + (pointer_declarator (identifier) @name) |
| 78 | + ] |
| 79 | + value: (_) @value) |
| 80 | + ] |
| 81 | + default_value: (_)? @value |
| 82 | + ) @variable) |
| 83 | +
|
| 84 | +;; member variable |
| 85 | +((field_declaration |
| 86 | + declarator: [ |
| 87 | + (field_identifier) @name |
| 88 | + (reference_declarator (field_identifier) @name) |
| 89 | + (pointer_declarator (field_identifier) @name) |
| 90 | + (init_declarator |
| 91 | + declarator: [ |
| 92 | + (identifier) @name |
| 93 | + (field_identifier) @name |
| 94 | + (reference_declarator (identifier) @name) |
| 95 | + (reference_declarator (field_identifier) @name) |
| 96 | + (pointer_declarator (identifier) @name) |
| 97 | + (pointer_declarator (field_identifier) @name) |
| 98 | + ] |
| 99 | + value: (_) @value) |
| 100 | + ] |
| 101 | + default_value: (_)? @value |
| 102 | + ) @variable) |
| 103 | +``` |
| 104 | + |
| 105 | +!!! tip |
| 106 | + For more information on writing queries, see the Tree-sitter documentation for [Pattern Matching with Queries](https://tree-sitter.github.io/tree-sitter/using-parsers#pattern-matching-with-queries). |
| 107 | + |
| 108 | +The query handles, among other things, `reference_declarator` and `pointer_declarator`, but we saw `array_declarator` in the parse tree above, and it does not seem to handle that. This looks like it might be the problem. So let's augment the query to handle `array_declarator`, following the same patterns as for `reference_declarator` and `pointer_declarator`: |
| 109 | +``` |
| 110 | +;; variable |
| 111 | +((declaration |
| 112 | + declarator: [ |
| 113 | + (identifier) @name |
| 114 | + (array_declarator (identifier) @name) |
| 115 | + (reference_declarator (identifier) @name) |
| 116 | + (pointer_declarator (identifier) @name) |
| 117 | + (init_declarator |
| 118 | + declarator: [ |
| 119 | + (identifier) @name |
| 120 | + (array_declarator (identifier) @name) |
| 121 | + (reference_declarator (identifier) @name) |
| 122 | + (pointer_declarator (identifier) @name) |
| 123 | + ] |
| 124 | + value: (_) @value) |
| 125 | + ] |
| 126 | + default_value: (_)? @value |
| 127 | + ) @variable) |
| 128 | +
|
| 129 | +;; member variable |
| 130 | +((field_declaration |
| 131 | + declarator: [ |
| 132 | + (field_identifier) @name |
| 133 | + (array_declarator (field_identifier) @name) |
| 134 | + (reference_declarator (field_identifier) @name) |
| 135 | + (pointer_declarator (field_identifier) @name) |
| 136 | + (init_declarator |
| 137 | + declarator: [ |
| 138 | + (identifier) @name |
| 139 | + (field_identifier) @name |
| 140 | + (array_declarator (identifier) @name) |
| 141 | + (array_declarator (field_identifier) @name) |
| 142 | + (reference_declarator (identifier) @name) |
| 143 | + (reference_declarator (field_identifier) @name) |
| 144 | + (pointer_declarator (identifier) @name) |
| 145 | + (pointer_declarator (field_identifier) @name) |
| 146 | + ] |
| 147 | + value: (_) @value) |
| 148 | + ] |
| 149 | + default_value: (_)? @value |
| 150 | + ) @variable) |
| 151 | +``` |
| 152 | +Now rebuild and reinstall Doxide, rerun the test above (`doxide build`, `mkdocs serve`, inspect `localhost:8000`), and verify that the bug is now fixed. |
| 153 | + |
| 154 | +You can now commit the fix, including the test case added to `parsing.hpp` as a regression test for future, and submit a pull request on the [GitHub repository](https://github.com/lawmurray/doxide). |
0 commit comments