1
0
mirror of https://github.com/danog/psalm.git synced 2024-12-13 17:57:37 +01:00
psalm/docs/contributing/philosophy.md

71 lines
4.3 KiB
Markdown
Raw Normal View History

2021-02-28 20:09:19 +01:00
# Philosophy
2021-02-28 19:58:32 +01:00
2021-02-28 20:09:19 +01:00
This is about why Psalm is the way it is. This is a living document!
2021-02-28 19:58:32 +01:00
2021-02-28 20:32:48 +01:00
## Psalm is a tool for PHP written in PHP
2021-02-28 19:58:32 +01:00
2021-02-28 20:49:53 +01:00
### Advantages
2021-02-28 19:58:32 +01:00
- PHP is fast enough for most use-cases
- Writing the tool in PHP guarantees that PHP community members can contribute to it without too much difficulty
### Drawbacks
2021-02-28 20:02:18 +01:00
- Psalm is slow in very large monorepos (over 5 million lines of checked-in code).
2021-08-05 22:39:01 +02:00
- Psalms language server is more limited in what it can provide than comparable compiled-language tools. For example, it's infeasible to find/change all occurrences of a symbol, in all files that use it, as you type.
2021-02-28 19:58:32 +01:00
2021-02-28 20:02:18 +01:00
### Comparison to other languages & tools
2021-02-28 19:58:32 +01:00
2021-02-28 20:46:02 +01:00
Many languages have typecheckers/compilers written in the same language. Popular examples include Go, Rust, and TypeScript. Python is a special case where the semi-official typechecker [MyPy](https://github.com/python/mypy) (written in Python) can also [compile to a C Python extension](https://github.com/python/mypy/blame/master/mypyc/README.md#L6-L10), which runs 4x faster than the interpreted equivalent.
2021-02-28 19:58:32 +01:00
2021-02-28 20:38:55 +01:00
Some interpreted languages have unofficial open-source typecheckers written in faster compiled languages. In all cases a single mid-to-large company is behind each effort, with a small number of contributors not employed by that company:
2021-02-28 19:58:32 +01:00
- PHP
2021-02-28 20:32:10 +01:00
- [NoVerify](https://github.com/VKCOM/noverify) written in Go. Runs much faster than Psalm (but does not support many modern PHP features)
2021-02-28 19:58:32 +01:00
- Ruby
2021-02-28 20:32:10 +01:00
- [Sorbet](https://sorbet.org/) - written in C
2021-02-28 19:58:32 +01:00
- Python
2021-02-28 20:32:10 +01:00
- [Pyre](https://github.com/facebook/pyre-check) - written in OCaml
- [Hack](https://github.com/facebook/hhvm) - the typechecker is written in OCaml and Rust
2021-02-28 19:58:32 +01:00
2021-02-28 20:32:48 +01:00
## Psalm's primary purpose is finding bugs
2021-02-28 19:58:32 +01:00
2021-02-28 20:43:55 +01:00
Psalm does a lot, but people mainly use it to find potential bugs in their code.
All other functionality the language server, security analysis, manipulating/fixing code is a secondary concern.
2021-02-28 19:58:32 +01:00
2021-02-28 20:57:49 +01:00
## It's designed to be run on syntactically-correct code
2021-02-28 19:58:32 +01:00
2021-02-28 20:57:49 +01:00
Psalm is almost always run on PHP code that parses a lint check (`php -l <filename>`) i.e. syntactically-correct code. Psalm is not a replacement for that syntax check.
2021-02-28 19:58:32 +01:00
2021-02-28 20:46:02 +01:00
Given Psalm is almost always used on syntatically-correct code it should use a parser built for that purpose, and `nikic/php-parser` is the gold-standard.
2021-02-28 19:58:32 +01:00
2022-08-20 23:29:03 +02:00
Where Psalm needs to run on syntactically-incorrect code (e.g. in language server mode) Psalm should still use the same parser (and work around any issues that it produces).
2021-02-28 20:57:49 +01:00
2021-03-01 06:14:24 +01:00
## Docblock annotations are better than type-providing plugins
2021-02-28 19:58:32 +01:00
Psalm offers a plugin API that allows you to tell it what about your program's property types, return types and parameter types.
Psalm aims to operate in a space with other static analysis tools. The more users rely on plugins, the less chance those other tools have to understand the user's intent.
2021-02-28 20:41:54 +01:00
Psalm should encourage developers to use docblock annotations rather than type-providing plugins. This was a driving force in the adoption of [Conditional Types](../annotating_code/type_syntax/conditional_types.md) which allowed Psalm to replace some of its own internal type-providing plugins.
The other benefit to docblock annotations is verifiability for the most part Psalm is able to verify that docblock annotations are correct, but it cannot provide many assurances when plugins are used.
2021-02-28 19:58:32 +01:00
2021-02-28 21:09:19 +01:00
This doesnt mean that plugins as a whole are bad, or that they cant provide useful types. A great adjacent use of plugins is to provide stubs with Psalm type annotations for libraries that dont have them. This helps the PHP ecosystem because those stubs may eventually make their way into the project currently being stubbed.
2021-03-01 06:14:24 +01:00
## Docblock annotations that can be verified are better than those that cannot
Psalm currently supports a number of function/class docblock annotations that it's unable to verify:
- `@psalm-assert`, `@psalm-assert-if-true`, `@psalm-assert-if-false`
- `@property`, `@method`, `@mixin`
Whenever new docblock annotations are added, effort should be made to allow Psalm to verify their correctness.
## In certain circumstances docblock annotations are better than PHP 8 attributes
2021-02-28 19:58:32 +01:00
For information that's just designed to be consumed by static analysis tools, docblocks are a better home than PHP 8 attributes.
A rationale is provided in [this article](https://psalm.dev/articles/php-8-attributes).