Architecture

This section documents the most important architectural elements of gherlint.

Main Concept

The linting process is coordinated by GherkinLinter. It constructs abstract syntax trees for each file and passes them to ASTWalker, together with a list of checkers which where discovered by the CheckerRegistry. The checker classes implement a Visitor pattern: each checker can implement visit_nodetype() and leave_nodetype() methods for the elements it is interested. The ASTWalker calls those methods on the checkers for each node while it traverses the tree. The checkers themselves define one or several Message which are registered in a central MessageStore and can be emitted through a class that inherits from Reporter (or defines the necessary methods).

../_images/static_representation.png

Startup Phase

The user invokes gherlint through the command line, where he can specify additional options like the Reporter class to use or what additional checkers to load. The main() function constructs a Config object which is passed to GherkinLinter. According to the configuration the GherkinLinter creates the reporter, checker instances and the walker which will be necessary for running the linting operation. The linting itself is described in the next section.

../_images/startup_phase.png

The linting process is started by calling the run() method on GherkinLinter. For each file in the directory which was passed to the __init__() of GherkinLinter, it will construct a Document object which contains the full abstract syntax tree (AST) of the file. This root node is passed to the ASTWalker’s walk() method. The ASTWalker will first call the visit_nodetype() method (where nodetype is the lowertype class name of the node) on all checkers that implement them, before it recursively calls walk(child_node)() for all the node’s children (if any) on itself. Afterwards the leave_nodetype() method is called analogous to the enter_nodetype() method.

../_images/linting_phase.png

Message Handling

Each checker has a number of messages it can emit. Message instances are stored in a central MessageStore. The individual vist_ and leave_ methods are responsible to determine whether a specific message shall be emitted. They use the Reporter to add a message to emit by passing the name or id of the message. The Reporter looks up the message instance through the MessageStore.

../_images/message_handling_static.png ../_images/message_handling_dynamic.png