Code quality in TYPO3 projects
A while ago I wrote a small tool for analyzing code quality in TypoScript files (originally as part of a larger article for the t3n magazine) that since then has achieved a bit of popularity in the TYPO3 community. This article contains an updated write-up on the tool and a short guide on how to use it.
What is a linter?
The term “linting” dates back to the UNIX tool lint, which was originally intended find programming errors in C source code. By now, a “linter” is commonly understood as a tool to detect and report errors (including stylistic errors) in program source codes (source: Wikipedia). Linters help developers to keep a consistent coding style in projects and to find potential errors as early as possible using static code analysis.
There are linters for lots of different programming languages; web developers may have stumbled upon JSLint, CSSLint or HTMLLint. A new addition to this list is now TypoScript Lint that offers similar features for TypoScript, a language customarily used in TYPO3 projects. As a small example, let’s have a look at the following TypoScript snippet:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
page = PAGE
page {
10 = FLUIDTEMPLATE
10 {
templateName = Default
templateRootPaths.10 = fileadmin/templates
templateRootPaths.20 = EXT:mysite/Resources/Private/Templates
layoutRootPaths {
}
}
}
#page.includeJS.main = fileadmin/js/app.js
page.includeJS.main = fileadmin/js/app.min.js
page.10.templateRootPaths.10 = fileadmin/templates2
There are some obvious stylistic errors in this code snipped (ordered by severity):
- The property
page.10.templateRootPaths.10
is assigned in line 6. However, the exact same property is overwritten in line 17. This is a dangerous pitfall: an unsuspecting developer might now change line 6 in good faith, without this having any effect - an error that will cost a lot of valuable time to debug. - After the first assignment block to
page
has been closed, there are subsequent assignments to sub-properties ofpage
in lines 15 and 17. These might be surprising, since someone reading the source code might not expect these assignments after the initial assignment block. - The comment in line 14 apparently contains source code that was commented out. This obstructs readability and should be removed completely. This is what version control is for!
- Indentation is not consistent. The
10
s in lines 3 and 4 should be indented equally, but aren’t. Same goes for line 7. Especially in larger files, inconsistent indentation can reduce code readability hugely. - The assignments to
templateRootPaths
in lines 6 and 7 start with the same path segment. For better readability, these two assignments could be grouped in a single assignment block. - The assignment to
layoutRootPaths
in line 9 and 10 is completely empty.
And indeed, when passed an input file with the content seen above, the TypoScript linter generates the following output, that admonished all stated errors (and even a few more):
Completed with 8 issues
CHECKSTYLE REPORT
=> /Users/mhelmich/Git/Github/typo3-ci-example/test.typoscript.
2 Accessor should be followed by single space.
4 Expected indent of 2 spaces.
6 Value of object "page.10.templateRootPaths.10" is overwritten in line 17.
6 Common path prefix "templateRootPaths" with assignment to "templateRootPaths.20" in line 7. Consider merging them into a nested assignment.
7 Expected indent of 4 spaces.
7 Common path prefix "templateRootPaths" with assignment to "templateRootPaths.10" in line 6. Consider merging them into a nested assignment.
9 Empty assignment block
14 Found commented code (page.includeJS.main = fileadmin/js/app.js).
15 Assignment to value "page.includeJS.main", altough nested statement for path "page" exists at line 2.
17 Assignment to value "page.10.templateRootPaths.10", altough nested statement for path "page" exists at line 2.
17 Common path prefix "page" with assignment to "page.includeJS.main" in line 15. Consider merging them into a nested assignment.
SUMMARY
12 issues in total. (11 warnings, 1 infos)
A complete list of coding errors that are detected by the TypoScript linter can be found in the project’s README file.
Installation
The TypoScript linter is installed via Composer. Of course, this works best if the TYPO3 project in which the linter should be used is itself also managed with Composer (for setting up TYPO3 with Composer, I’ll just link to the respective README file). In this case, a simple composer require --dev
command in the project directory is sufficient:
The --dev
flag asserts that the linter is not installed when the project is deployed on a production system. After installation, the linter is available in the vendor/bin
directory and can be called with vendor/bin/typoscript-lint
.
If your TYPO3 project is not managed with Composer, you can use the composer global
command to install the linter globally. In this case, the linter is available not in your project directory, but in your user’s home directory; more precisely, $HOME/.composer/vendor/bin/typoscript-lint
(if you add the $HOME/.composer/vendor/bin
directory to your shell’s search path, a simple typoscript-lint
will be sufficient for calling the linter).
Usage
After the installation, typoscript-lint
can be called on arbitraty TypoScript files. These files will be analyzed and the linter will point out coding and style errors in the source code. The tool’s output might look as follows:
Using the options -f xml
and -o outputfile.xml
, you can create an XML output file that is compatible to the popular Checkstyle format. This way, you can easily integrate the TypoScript linter in Continuous Integration environments like Jenkins (for which there exists a plugin for Checkstyle).
Configuration
Style in programming languages is often subjective and a matter of personal taste (best example probably being the “Tabs or Spaces?” question). Of course, the TypoScript linter can be adjusted to these kinds of preferences. For this, a configuration file called typoscript-lint.yml
needs to be created in your project directory (earlier versions of the liter used tslint.yml
as file name, which lead to obvious problems). In this file, you can for example configure the indentation (here, for using tabs for indentation instead of spaces):
1
2
3
4
5
sniffs:
- class: Indentation
parameters:
useSpaces: false
indentPerLevel: 1
You can also deactivate individual checks. For example, if the recommendations for nesting assignments annoy you, they can be easily disabled:
1
2
3
sniffs:
- class: NestingConsistency
disabled: true
Questions & feedback?
The TypoScript linter is available on GitHub and licensed under the MIT license. If you should notice errors while using the linter, feel free to use the issue tracker on GitHub or open up a Pull Request if you want to fix a bug or make a change to the linter by yourself.