-
Notifications
You must be signed in to change notification settings - Fork 16
RBI Internals
STEP 1
All plugins mutate the
instance of RbiGenerator
They generate a tree
structure of RbiObjects
+--------+ +--------+
|Plugin 1| |Plugin 2|
+----+---+ +----+---+ STEP 2
^ ^ ConflictResolver
| | mutates the structure
+-------------------+ | | to fix conflicts
| | | |
| One instance of +-------------+ +----------------+
| RbiGenerator +--------------------->+ConflictResolver|
| | +----------------+
+---------+---------+
|
|
| +-------+ STEP 3
+--------->+ File | The final RBI is written
+-------+ to a file
Everything that can generate lines of the RBI implements the
RbiGenerator::RbiObject
abstract class. The function generate_rbi
accepts the current indentation level and a set of formatting options.
(Each object is responsible for generating its own indentation; that is, the
lines generated by a child object should not then be indented by its parent.)
Plugins are automatically detected when they subclass Plugin
. Plugins can then
be run by passing an array of them, along with an RbiGenerator
, to
Plugin.run_plugins
. Once done, the generator will be populated with a tree of
(possibly conflicting) RbiObjects
- the conflict resolver (detailed below)
will clear up any conflicts.
This is a key part of the plugin/build system. The ConflictResolver
takes
a namespace from the RbiGenerator
and merges duplicate items in it together.
This means that many plugins can generate their own signatures which are all
bundled into one, conflict-free output RBI.
It is able to do the following merges automatically:
- If many methods are identical, delete all but one.
- If many classes are defined with the same name, merge their methods, includes and extends. (But only if they are all abstract or all not, and only if they don't define more than one superclass together.)
- If many modules are defined with the same name, merge their methods, includes and extends. (But only if they are all interfaces or all not.)
If a merge can't be performed automatically, then the #resolve_conflicts
method takes a block. This block is passed all the conflicting objects, and one
should be selected and returned - all others will be deleted. (Alternatively,
the block can return nil, and all will be deleted.) This allows the CLI to
prompt the user asking them what they'd like to do, in the case of conflicts
between each plugin's signatures which can't automatically be resolved.