Add linting and formatting#1198
Open
cj-young wants to merge 11 commits into
Open
Conversation
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Formatting and Linting System Configuration
Resolves #1197
This PR is intended to set up the rules for linting and formatting for both the frontend and the backend. Neither formatting issues nor linting issues have been fixed here. Ideally, developers can merge these rules into their own branches so that when a future PR modifies almost every file, they can just run the formatting command themselves to avoid merge conflicts.
Running the Formatters and Linters
The following Make commands are available to format and lint:
frontend-fmt: Format all frontend (or frontend-adjacent file-type, like YAML, JSON, etc.) codefrontend-lint: Lint all frontend codebackend-fmt: Format all backend codebackend-lint: Lint all backend codeformat: Format both frontend and backendlint: Lint both frontend and backendRule and tool choices
Prettier
Prettier is the industry-standard formatter for frontend applications. Because it is opinionated, few rule choices had to be made. Only two options were used:
experimentalTernariestrueexperimentalOperatorPositiontrueOther options were kept as defaults. Here are some brief justifications for some of those decisions:
semitruetrailingComma"all""es5"is another options, but since ES6 features are used anyway, there is no reason to limit trailing commas to be ES5-compatible.ESLint
ESLint is the industry-standard linter for JS. It has by far the most support and largest ecosystem of all linters. A few plugins are used, namely
eslint-plugin-react(rules prefixed withreact/),eslin-plugin-react-hooks(rules prefixed withreact-hooks/), andeslint-config-prettier(prevents rule conflicts with Prettier). Many of the rules have been given a severity ofwarnbecause there are currently so many errors in the codebase, and changes will have to be adopted relatively gradually. Once the lint errors start to be cleared up, most of thewarnseverities will be updated toerror.A brief justification of each changed rule is as follows:
no-unused-varswarn, ignore pattern of^_react/prop-typesoffreact/react-in-jsx-scopeoffReactdoes not need to be imported because webpack does not require it.react/function-component-definitionerror,namedComponents:function-declaration,unnamedComponents:arrow-functionwarnbecause there are so few instances of the violation and they are extremely easy to fix.react/jsx-keywarn,checkFragmentShorthand:true,warnOnDuplicates:truereact/no-array-index-keywarnreact/jsx-keyapplies here. This should have a severity oferrorin the future, but it is so common in the code currently that it is awarnfor now.react/checked-requires-onchange-or-readonlywarn<input>withtype="checkbox"either has areadonlyattribute or anonChangefunction if it is controlled. It is mostly to suppress React warnings.react-hooks/set-state-in-effectwarnerror. However, there are likely cases where a state setter in auseEffectis necessary, so it has been reduced to awarn. There are many violations in the codebase that should be changed, and there likely will be in the future, so it is not omitted entirely.PHP CS Fixer
PHP CS Fixer is a PHP formatter created and maintained by the same team that maintains Symfony. Because of this, it integrates easily with Symfony and has lots of integrations and support.
The only rule that is configured separately from the defaults is
phpdoc_summarywhich has been set tofalse. By default, it adds a period to the end of the first line of PHPDocs, which is somewhat invasive.PHPStan
PHPStan is the most popular choice for static analysis tools in Symfony applications. It easily integrates with Symfony through an extension and allows easy incremental adoption through its level system and its baseline feature. The standard PHP linter only tracks syntax errors. PHPStan introduces type checking. While types in this codebase are somewhat underused, it is still helpful in tracking possible nullable types, invalid method calls, and type checking where types are implemented. Moving forward, it will encourage the adoption of explicit typing throughout the entire codebase, which will make the app less prone to bugs.
The only major parameter that has been changed is the level, which has been set to 5 (on a 0 to 10 scale, 10 being the most strict). This has been chosen somewhat arbitrarily. There are roughly 150 errors at level 5, and at level 6 that shoots up to around 850 errors, almost all of which are due to missing types. Lowering the level much more wouldn't reduce the amount of errors by a substantial amount when considering the tradeoff of having very loose checks.
No baseline has been created. The baseline should be created once a PR to fix most linting errors is created to reduce the size of the baseline. Gradually, as the codebase becomes more type safe and up to standard, the level can be increased.
Adopting the Formatter
If we take the approach of adopting the correct formatting by incrementally formatting each file only when they are modified and pushed, the git blame on any formatted line will point to whoever ran the formatter and not to whoever originally changed the line, which isn't super useful. Instead, if a single commit (or a handful of commits) dedicated only to formatting are created, a
.git-blame-ignore-revsfile can be created to ignore these commits in the git blame. While this won't be perfect (since some line additions and line swaps can't be ignored correctly through this method), it will preserve a large majority of the blame.Eventually, CI checks should be added to ensure formatting and linting are up to the standard of the rest of the codebase. Ideally, this would be implemented right after the PRs that format and lint the entire codebase.
Adopting the Linter
Because lint issues typically change the functionality of the app, the
git blameshould not ignore lint changes. The commits in the PR that fixes the bulk of the lint issues, therefore, shouldn't be in the.git-blame-ignore-revs. Because lint changes aren't just stylistic in nature, merge conflicts are essentially inevitable. The only ones that could be fixed ahead of time would be through automatically fixable errors. If a process like this is run, it would be helpful to be listed in the PR where they are fixed so other developers know to run the command to reduce the likelihood of merge conflicts.