Add more development info to README.md

master
Hugo Thunnissen 4 weeks ago
parent afb9a9e4ed
commit 95735e7b94

@ -125,6 +125,146 @@ Elapsed time: 0.013878 (0.000000 in 0 GCs)
```
## Development
The codebase of phpinspect is relatively large. As a new contributor, you'll
probably feel a bit lost in the many files, functions and datatypes of the
package. Let me tell you a bit about phpinspect's architecture.
### Domains
There are roughly four main domains under which code in phpinspect can fall:
parsing, indexation, interpetation and user-facing functions. Below is a short
explanation of each domain.
#### Parsing
The parser provides the underpinnings for almost all of phpinspect's
functionalities. It is implemented with specialized macros and supports two main
parsing modes: bare and incremental. The parser code is located in
`phpinspect-parser.el`.
##### Bare Parsing
The parser produces a parse result in the form of a basic list, where each
parsed token is a list itself. The car of each list contains a keyword,
describing its meaning in the parsed code. Below is a lisp form and its
resulting insertion to demonstrate the structure of a syntax tree produced by
the bare parser.
`(insert (pp-to-string (phpinspect-parse-string "function foo(Bar $bar) { return $bar->baz; }")))`
```elisp
(:root
(:function
(:declaration
(:word "function")
(:word "foo")
(:list
(:word "Bar")
(:variable "bar")))
(:block
(:word "return")
(:variable "bar")
(:object-attrib
(:word "baz"))
(:terminator ";"))))
```
##### Incremental Parsing
Bare parsing is fast, because it makes use of simple lisp datastructures and
keeps the parser logic simple. A downside of this parsing mode is that the
result lacks any extra metadata about the tokens, like what their start- and
endpoints are in a buffer. It also makes it hard to partially update the tree
after a buffer has been edited. As both are essential for a program that needs
to work efficiently in live-edited buffers, the incremental parser was
implemented. When parsing incrementally, the parser still produces the same
structure of nested lists as a result. But it also stores metadata about each
parsed token in an n-ary tree of `phpinspect-meta` objects (see
`phpinspect-meta.el`). The incremental parser is able to partially update an
existing tree after code has been edited, making it efficient for live buffers.
##### Parsers Summarised
The incremental parsing is efficient for use with live edited buffers. Due to
its higher complexity it is not as fast at parsing entire files as the bare
parser. For this reason, both the bare and the incremental parser are used for
what they are best at.
#### Indexation
Within phpinspect, indexation is referred to as the process of extracting
information from parsed code and project configuration files.
##### Code Indexation
The code in
`phpinspect-index.el` consumes bare syntax trees and extracts information about
PHP functions and types from them. Code in `phpinspect-buffer.el` implements the
same functionality, but for live buffers based on the data produced by the
incremental parser.
##### Project Indexation
Code in `phpinspect-autoload.el` implements logic for `psr-4`, `psr-0` and
`files` autoload strategies. It is able to read a composer.json file and
generate autoload information based on which a project's types and functions can
be found.
##### Caching
Code in `phpinspect-cache.el` and `phpinspect-class.el` allows phpinspect to
store the result of code indexations in memory, so that they can be accessed
instantly when a user requests information about their code.
##### Threading
Indexation takes time. Because emacs is single-threaded, you might think that
indexing a project would lock up your emacs for a while. Do not despair!
`phpinspect-worker.el` contains code for a worker with a job queue that uses
collaborative threads to do work when emacs is idle. When you start interacting
with emacs, it will back off and let you do your thing! `phpinspect-pipeline.el`
contains code for something similar to generators in PHP, combined with
collaborative threading. Pipelines are used for more intense processes that
should be completed with a bit more of a hurry. Emacs should remain responsive
while a pipeline is running, but there may be a slightly noticeable sluggishness
while they run. At the moment of writing, pipelines are mainly used to refresh a
projects autoloader.
#### Interpretation
Having parsing, indexation and caching infrastructure is all well and good, but
how to we determine what information is actually useful to show to a user? This
is where code interpretation plays a big role. The main goal of interpretation
in phpinspect is the determination of the PHP type to display information
about. Determining this type is referred to as "resolving" in phpinspect's
codebase. Resolving a type is built around the concept of a "resolvecontext". A
resolvecontext is an object that contains information about a location in a
buffer and its surroundings. Based on the informatoin in the resolvecontext, the
type that a statement is expected to evaluate to can be determined. The code for
resolving types is mostly contained in `phpinspect-type.el`,
`phpinspect-resolve.el` and `phpinspect-resolvecontext.el`. The main entrypoints
are the functions `phpinspect-get-resolvecontext` and
`phpinspect-resolve-type-from-context`.
#### User-facing Functions
User-facing functions in phpinspect are mostly integrations with existing
infrastructure within emacs. For completion there is
`completion-at-point-functions`, for tooltips there is `eldoc` and for
go-to-definition there is `xref`. Aside from these integrations, phpinspect aims
to provide functionalities for code formatting.
##### Completion
Completion is implemented in `phpinspect-completion.el` as a strategy pattern. A
completion strategy can be added by implementing the methods
`phpinspect-comp-strategy-supports` and
`phpinspect-comp-strategy-execute`. Completion strategies are high level
abstractions that build on top of the type resolving code and the code in
`phpinspect-suggest.el`.
##### Eldoc
Eldoc support is implemented in a strategy pattern similar to that of
completion. An eldoc strategy can be added by implementing the methods
`phpinspect-eld-strategy-supports` and `phpinspect-eld-strategy-execute`.
##### Code Formatting
`phpinspect-fix-imports` adds, removes and sorts use statements. At the time of
writing, this is the only code formatting functionality that phpinspect
provides. See `phpinspect-imports.el` for the implementation.
##### Really Want To But Not Implemented: Xref
A thing that would be possible to implement on top of phpinspect's
infrastructure, but not much time has been spent on yet, is an integration with
`xref`. Xref integration would enable functionalities like go-to-definition.
### Building

Loading…
Cancel
Save