|
| 1 | +## Intro |
| 2 | + |
1 | 3 | This project follows the contributing recommendations outlined by [saamwerk](https://lorenzwalthert.github.io/saamwerk/).
|
2 |
| -In particular, issues labelled with `Status: Postponed` are closed even if they are not resolved. |
| 4 | +In particular, issues labelled with `Status: Postponed` are closed even if they |
| 5 | +are not resolved. |
| 6 | + |
| 7 | +## How to dive in and understanding the source code |
| 8 | + |
| 9 | +Read the vignettes. If you are done, come back here. |
| 10 | + |
| 11 | +`devtools::load_all()` |
| 12 | + |
| 13 | +`debug(style_text)` |
| 14 | + |
| 15 | +`style_text("call(1, 2 + 1)")` |
| 16 | + |
| 17 | +Go broad before you go deep. Before going into the very deep layers of function |
| 18 | +calls of `style_text()`, try to understand that `style_text()` consists of a few |
| 19 | +function calls only. |
| 20 | +Go into each of them and try to understand one layer deep. That is, try to |
| 21 | +understand what `make_transformer()` does by reading the names of the functions |
| 22 | +that get called, the name of the objects that are created by assigning the output of |
| 23 | +these function calls. Before looking into a functions source code, look at the |
| 24 | +documentation for that function. All internal important functions |
| 25 | +are documented and documentation is available also for unexported objects via |
| 26 | +`?` (if you did `devtools::load_all()`. |
| 27 | +Then, go into `parse_transform_serialize()` and so on. |
| 28 | + |
| 29 | +To understand the most fundamental operation in styler, the manipulation of the |
| 30 | +columns related to spacing and line break information, pick a rule from |
| 31 | +`R/rules-*.R`, e.g. `R/rules-spacing`, add a break point to a rule and style a |
| 32 | +string where you think this rule will be active. Then, see what happens and how |
| 33 | +this rule is applied on each level of nesting. |
| 34 | + |
| 35 | +## Static code analysis |
| 36 | + |
| 37 | +There are multiple packages that can be used to analyze a code base: |
| 38 | + |
| 39 | +* [gitsum](https://github.com/lorenzwalthert/gitsum): Parses and summarises git |
| 40 | + repository history. |
| 41 | +* [parsesum](https://github.com/lorenzwalthert/parsesum): Analyses source code |
| 42 | + through parsing. |
| 43 | + |
| 44 | +Check out the links above to see how the tools listed could help you |
| 45 | +understanding styler. |
| 46 | + |
| 47 | +## Project setup |
| 48 | + |
| 49 | +* The package is developed with the devtools suite, which includes roxgen2 for |
| 50 | + documentation, testthat for unit testing, pkgdown for html documentation. |
| 51 | +* Continuous integration is done with the tic (tasks integrating continuously) |
| 52 | + package. |
| 53 | +* A key development principle of styler is to separate infrastructure from |
| 54 | + style guide. Hence, whenever possible, transformer functions should be |
| 55 | + adapted, not the infrastructure should be changed for a specific style guide. |
| 56 | +* styler was created in 2017 by Kirill Müller, then turned from a |
| 57 | + proof-of-concept into a ready-for-production tool as part of GSOC 2017 with |
| 58 | + Kirill Müller and Yihui Xie as mentors and Lorenz Walthert as student. |
| 59 | + |
| 60 | + |
| 61 | +## File Structure |
| 62 | + |
| 63 | +The source code is organized as follows: |
| 64 | + |
| 65 | +| File | Description | |
| 66 | +| -------------: |:-----------------------------------------------------------| |
| 67 | +| addins.R | ui and helpers for the Addins of styler. | |
| 68 | +| communicate.R | function to communicate to the user via the console. | |
| 69 | +| compat-dplyr.R | compatibility functions. Since styler does not depend on dplyr, we define the dplyr functions ourself.| |
| 70 | +| compat-tidyr.R | compatibility functions. Since styler does not depend on tidy, we define the tidyr functions ourself.| |
| 71 | +| expr-is.R | Functions to check whether an expression matches a predicate (e.g. whether it *is* a function call, a curly brace expression etc.). | |
| 72 | +| indent.R | Computation of whether indention is needed (needs_indention()), if so which indices are indented and how indention is it is triggered. | |
| 73 | +| initialize.R | initializer called with the visitor at each nest. | |
| 74 | +| nest.R | converting from a text representation into a flat and then into a nested parse table representation. | |
| 75 | +| nested-to-tree.R | utilities to create a tree representation from text (after text was converted into a nested parse table). | |
| 76 | +| parse.R | parse text into parse table, minor token manipulation, verification of parsed objects. | |
| 77 | +| reindent.R | Deals with token-dependent indention and re-indention, opposed to indent.R where all indention is token independent (i.e. a brace just adds one level of indention, whereas in function declaration headers (if mutli-line), indention depends on token position of "function"). | |
| 78 | +| relevel.R | Reorganizing the nested parse table, namely relocates expressions on both sides of "%>%" to the same nest. | |
| 79 | +| rules-line-break.R, rules-other.R, rules-replacement.R, rules-spacing.R | transformer rules | |
| 80 | +| serialize.R | converts flattened parse table into text representation. Complement operation to the functions in nest.R | |
| 81 | +| set-assert-args.R | Assertion and setting of arguments. | |
| 82 | +| style-guides.R | How to create style guide objects from transformers. | |
| 83 | +|styler.R | General package information. | |
| 84 | +| testing.R | function used for testing. | |
| 85 | +| token-create.R | Utilities for creating tokens, mostly to insert braces around mutli-line if statements. | |
| 86 | +| token-define.R | Defines which tokens belong to which group. | |
| 87 | +| transform-code.R, transform-files.R | Transformation of code for APIs that manipulate files (e.g. style_file()). | |
| 88 | +| ui.R | User interaces. Top-level functions for styling. | |
| 89 | +| unindent.R | Certain tokens cause unindention, e.g. closing braces. | |
| 90 | +| utils.R | low-level general purpose utilities. | |
| 91 | +| vertical.R | S3 class for pretty printing of styled code. | |
| 92 | +| visit.R | Functions that apply functions to each level of nesting, either inside out or outside in. | |
| 93 | +| zzz.R | backport imports. | |
| 94 | + |
| 95 | + |
| 96 | +## High-level conventions |
| 97 | + |
| 98 | +* The project follows a highly functional approach. This means that |
| 99 | + functionality should be capsuled into functions, even if they are only called |
| 100 | + once. This makes abstraction from the code easier, reduces the number of lines |
| 101 | + for each function declaration considerably and makes it easier for people not |
| 102 | + familiar with the code base to dive into it. |
| 103 | +* All internal functions (except if they are 100% self-explanatory) are to be |
| 104 | + documented. |
| 105 | +* New functionality (e.g. in terms of styling rules) needs to be unit tested. If |
| 106 | + the new functionality changes how code is to be styled, the infrastructure |
| 107 | + with `test_collection()` should be used. |
| 108 | +* Cases that are not yet formatted correctly can be labelled with a `FIXME`. |
| 109 | +* GitHub is the platform where communication about source code happens. We |
| 110 | + refrain from adding extensive in-line code comments. One can use `git blame` |
| 111 | + to track when changes were introduced and find the corresponding pull request |
| 112 | + and associated issues to understand the thought process that lead to a change |
| 113 | + in the source code. This also implies that issues and / or pull request |
| 114 | + contain verbose explanation of problems and solutions provided. |
| 115 | + |
| 116 | +## Low-level coventions |
| 117 | + |
| 118 | +This project follows the [tidyverse style guide](http://style.tidyverse.org). |
| 119 | +If we refer to specific variables / values etc. in the following sections, you |
| 120 | +can use RStudio's full text search to find where |
| 121 | +`remove_line_break_before_round_closing_after_curly()` is declared or called. |
| 122 | + |
| 123 | + |
| 124 | +### Files |
| 125 | + |
| 126 | +* File names only contain alphanumeric characters and dashes. |
| 127 | +* Files are named according to topics / contexts, not according to functions |
| 128 | + that live in these files. |
| 129 | + |
| 130 | +### Functions |
| 131 | + |
| 132 | +* Function names should be verbs. No abbreviations should be used, we don't |
| 133 | + care if function names are particularly long. For example, there is a |
| 134 | + function with the name `remove_line_break_before_round_closing_after_curly()`. |
| 135 | +* only very low-level functions or functions that don't fit in any other file |
| 136 | + go to `utils.R`. |
| 137 | + |
| 138 | +### Boolean Values |
| 139 | + |
| 140 | +Functions that return Boolean values or variables that hold Boolean values are |
| 141 | +often prefixed with `is` or `has`. For example, `is_rmd_file(path)` is a |
| 142 | +function that returns `TRUE` if `path` is the path to a `.Rmd` file and `FALSE` |
| 143 | +otherwise. |
| 144 | + |
| 145 | +### Vectors with indices |
| 146 | + |
| 147 | +Vectors that hold indices are often suffixed with `idx`. `else_idx` for example |
| 148 | +indicates for every row in a parse table whether it contains an `else` token. |
0 commit comments