Configuration Reference
A DressCode configuration is a tree. At the top are a few reserved keys that say what is checked and under which conditions, and below them are the sections of decisions. Each key of a section names one thing in the code, and its value says how that thing is written. This page is a map of the whole tree; each section has its own page with all its keys, their values and examples.
use:
- perCs
- cleanup
paths:
- src
- tests
braces:
position:
class: nextLine
spacing:
concatenation: '$a.$b'
blankLines:
aroundMethods: 1
beforeStatement:
return: 1
qualification:
function:
global: bare
optimized: imported
The first five lines are reserved keys: what the configuration is based on and what is checked. The rest are decisions, and you
can read them aloud: the brace of a class goes on the next line, the dot is written without spaces, there is one blank line
between methods and one before return too, global functions stay bare names, and the ones PHP optimizes are imported.
You will see the whole path of a decision, such as blankLines.aroundMethods, next to every finding in the output, and
you write it into a dresscode:ignore comment, into fixRisky or after the --only option. The
Configuration page describes how a configuration is put together from
presets, overrides and the command line.
Reserved Keys
A reserved key is not a decision about how the code looks. It is a fact about the project, the scope of the run, or what the run does with what it finds.
| key | what it says |
|---|---|
use |
which presets the configuration is based on (the standard and the sets), and which plugins the project adds |
targets |
which PHP and package versions the code is
written for, when it should not follow composer.json |
typeAnalysis |
where the types of the code come from; the only value
is phpstan |
namespaces |
the functions and constants that the namespaces of the project declare |
nameResolution |
whether the lists in namespaces are complete: certain or uncertain |
paths, excludePaths, fileExtensions, skipWhen |
what is checked and what is skipped |
baseline |
the baseline file with violations that are not reported for now |
cacheDir |
where DressCode stores the list of files that passed clean |
rules, ruleUrl |
the project's own rules, named by class, and the URL of their pages |
analyses |
custom analyses for rules |
fixRisky |
the decisions whose risky fixes the project accepts |
severity |
how strictly violations are reported: a map of decisions, groups, sections or presets to warning
or error |
suppressionComments |
the project's own comments that silence a decision on their line |
overrides |
different values for a part of the project |
Not every key is allowed everywhere. A preset carries only decisions, use with presets,
suppressionComments and severity, because it knows the standard but not your project. An override for a
part of the project may also hold targets with the PHP version, namespaces, nameResolution
and fixRisky. The rest belongs only to the configuration of the whole project.
Sections of Decisions
Sections only sort the decisions so that you can find them: the space after a comma is where you would look for it. Nothing
else follows from the section. How strictly a violation is reported is set by the severity key. Whether DressCode may
make the fix on its own, or when a decision applies, depends on the value and the properties of the decision, not on the name of
the section.
| section | what it decides |
|---|---|
| file | the file as text: the opening tag, line endings, line length, declare(strict_types=1) |
| indentation | indentation: the unit, the tab width, the indentation of continuation lines |
| naming | letter case in names of classes, methods, constants and variables |
| casing | letter case in what belongs to PHP: keywords, true, null, built-in classes, functions
and types |
| qualification | how fully the name of a class, function or constant is written: bare, imported, or with a leading backslash |
| imports | use statements at the top of the file: shape, groups, order, unused imports |
| spacing | spaces within a line: around operators, after a comma, inside parentheses, after a keyword |
| multiline | constructs split onto lines and lines longer than the limit: the placement of the items and edges of parameters, arguments,
arrays, conditions, method chains, the ternary operator, for, operators and implements; the
trailing comma |
| braces | braces: where they stand, when they are required, the empty body |
| blankLines | blank lines in the file header, in a class, in a block and around statements |
| classes | classes and their members: order, visibility, modifiers, empty parentheses |
| types | types in declarations: required types, the ?int form, the order in a union |
| functions | functions and closures: arrow functions, static, a needless return |
| hygiene | code that can be written more simply with the same meaning: aliases, is_null(), intval(),
get_class(), call_user_func() |
| controlFlow | control structures: elseif, a needless else, fall-through in switch |
| expressions | operators and expressions: strict comparison, !=, the ternary operator, $a += 1 |
| literals | how strings, numbers and arrays are written: quotes, [], digit separators |
| comments | ordinary comments: // instead of #, empty comments |
| phpdoc | doc comments: annotations, the types in them, what does not belong in them |
| mistakes | what is most likely a bug, whatever the style |
| upgrading | upgrading to a newer PHP and to new versions of libraries |
A plugin that brings its own rules has its own section named after it: the decisions of the
dresscode/upgrade-nette package live under the nette key, for example nette.linkArguments.
The rules a project writes for itself put their decisions under the project key. Both are written into the
configuration the same way as the sections of the engine; dresscode catalogue lists what a plugin or the project has
in its section.
Values
The description of a key on the page of its section says what values the key takes, and
dresscode explain <path> prints it too. There are only a few kinds of values, and they repeat:
- Presence says whether a thing must or must not be in the code:
requiredorforbidden, for examplehygiene.is_null: forbiddenorfunctions.arrowFunction.oneExpression: required. The key names the thing, and the word says what to do with it:forbiddenremoves or rewrites it,requiredadds it. In theupgradingsection,requiredwrites a construct that a newer PHP brought, andforbiddenreplaces what PHP deprecated. Where a thing may be there or not, like the comma at the end of a multiline list, the key also takesoptional. - A word names a shape that has no single fixed form:
braces.position.class: nextLine,imports.order.names: alphabetical,literals.quotes: single. - A sample is a shape written as a piece of example code in single quotes:
spacing.call: 'foo($a, $b)',types.nullable: '?int'. The quotes are needed because NEON would readfoo($a, $b)as an entity. DressCode does not read a sample as code; it only compares it with the samples the key knows. An unknown sample is an error, and the message lists the known ones. - A count of blank lines, digits or length:
blankLines.aroundMethods: 2. Where the key allows it, also a range0-1and an open range1+. Some counts also take a word, for examplefile.lineLength: none. A list is never a count; DressCode rejects[0, 1]. - A list of names, patterns or an order:
classes.members.order: [traitUse, constant, property],phpdoc.forbiddenAnnotations: ['@author', '@package']. A list written in a higher layer replaces the whole list below it, the default included. To add to it, write...into the list, which stands for the list of the layer below:['...', '@package']. - A tolerance is a list of words or samples where a key accepts several shapes at once:
multiline.edges.condition: [apart, closingApart]lets both shapes pass, and rewrites a condition that matches neither into the first shape. - A map of names or kinds to a value:
blankLines.beforeStatement: {return: 1, throw: 1}, or the replacement maps inupgrading.api. A map is merged with the layer below it item by item. An item with the valuekeepremoves that name from all layers below it,keepin place of the whole map removes all of it, and an exclamation mark after the key (replacedClasses!:) replaces the maps of the lower layers with what you write. - A text is the only case where the value is a plain sentence: the text of the comment at a fall-through
case(controlFlow.switch.fallThroughComment: no break). A list of texts lets every one of them pass and writes the first. - Yes or no (
yes,no) is taken only by parameters whose question has no other answer, for exampleimports.order.caseSensitive: yes, and byupgrading.packages, which adds the data of packages beneath the maps of the project.
Decisions that belong together stand in a group, and the path then reads like a sentence: the section gives the area, the group
the question or the thing, and the last part the place. A group brings together either places that answer the same question, like
braces.position for the position of the brace at a class, a function or a closure, and
multiline.trailingComma for the comma at the end of an array, arguments or parameters, or questions about one thing,
like file.strictTypes for the declaration and the place where it stands. A decision that has no other name than the
thing it decides about does not form a group: it stands flat, and the keys that refine it stand next to it and carry its name.
file.lineLength is the longest allowed line, file.longLines says whether a longer line that could not be
split is reported, and file.lineLengthExcept says which constructs are not split because of the line width and which
lines are never reported. A group is written as a nested map, and the path to its keys has one more part. A word, count or list
written on a group applies to each of its keys that takes it, so multiline.operatorPosition: lineStart moves all
operators to the start of the line at once, and qualification.function: imported imports functions that are global,
optimized and from other namespaces alike. A key that does not take the word is skipped, and a value written directly for a
single place wins over the value of the group; a word that no key of the group takes is an error. A presence word written on a
group must be taken by every key of the group, and a group that names one thing with several questions, like
expressions.ternary, takes keep as its only presence word. In the multiline section, the
kinds of places lists and operators stand between the group and the place, as described on the page of the section.
And then there is keep. Every decision that requires something takes it, and so does a map, both per item
and as a whole: “nothing is enforced here, the code stays as it is”. It is the only word for “do not touch this”, and it
means no shape. keep written on a section or on a key with subkeys applies to everything under it, and a later layer
then brings back only the keys it names itself:
blankLines: keep # nothing decides about blank lines
The Default and the Fact
A decision that nobody writes has a default, and the page of the section shows it. For most decisions it is keep,
so they require nothing. A parameter, that is, a key that only refines another key, has a real default, does not take
keep and turns nothing on by itself: controlFlow.trailingIfMinStatements sets the number of statements
from which an if at the end of a function becomes an early return, but this is checked only once
controlFlow.trailingIf: forbidden is set. That is also why a list the project writes into
types.traversableClasses never turns on required types by itself.
A project fact is not a decision about how the code looks but a statement of what the project contains:
namespaces.functions and namespaces.constants list the functions and constants in namespaces. They are
written into the reserved key namespaces, and the check that reports a declaration missing from the list is turned on
by the key nameResolution: certain; the details are on the Functions
and Constants in Namespaces page.
Where to Learn More
dresscode explain spacing.callprints the description of the decision, the values with their meanings, the value in your project together with the layer that set it, and what each standard says.dresscode explain spacingdoes the same for the whole section.dresscode configprints the resolved configuration in the shape of the file, with a comment at each value saying where it came from.dresscode cataloguelists all decisions your installation knows, plugins included, and marks with an asterisk the ones the configuration sets; with--format jsonit gives the same as data.
The details of all three commands are on the Command Line page.