-
-
Notifications
You must be signed in to change notification settings - Fork 97
3. Linter
gdlint is a static code analysis tool used to find potential problems in GDScript code.
For each provided file, this tool executes two phases in order:
- It parses the file thus checking if the code conforms to GDScript syntax
- It runs various predefined checks against the code
To run a linter, just execute the gdlint command with some files as arguments e.g.:
$ gdlint misc/MarkovianPCG.gd
The command's exit code is 0 if both - parsing succeeded and checks were successful. Any lines in stdout mean that there were some problems found like e.g.:
misc/MarkovianPCG.gd:96: Error: Function argument name "aOrigin" is not valid (function-argument-name)
misc/MarkovianPCG.gd:96: Error: Function argument name "aPos" is not valid (function-argument-name)
In case of gdlint bugs or work-in-progress code it may be necessary to disable some checks. Each check can be disabled single time using gdlint:ignore comment:
# gdlint:ignore = function-name , function-argument-name
func SomeWrongName(someArg):
assert(someArg > 0)
In case some checks must be disabled in larger file area, the gdlint: disable (with optional gdlint: enable) comment may be used:
# gdlint: disable=function-name
func SomeWrongName():
pass
# gdlint: enable=function-name
To tweak the default check settings, you can dump the default config to a file:
$ gdlint -d
$ cat gdlintrc
class-load-variable-name: (([A-Z][a-z0-9]*)+|_?[a-z][a-z0-9]*(_[a-z0-9]+)*)
class-name: ([A-Z][a-z0-9]*)+
class-variable-name: _?[a-z][a-z0-9]*(_[a-z0-9]+)*
constant-name: '[A-Z][A-Z0-9]*(_[A-Z0-9]+)*'
disable: []
enum-element-name: '[A-Z][A-Z0-9]*(_[A-Z0-9]+)*'
enum-name: ([A-Z][a-z0-9]*)+
function-argument-name: _?[a-z][a-z0-9]*(_[a-z0-9]+)*
function-arguments-number: 10
function-preload-variable-name: ([A-Z][a-z0-9]*)+
function-name: (_on_([A-Z][a-z0-9]*)+(_[a-z0-9]+)*|_?[a-z][a-z0-9]*(_[a-z0-9]+)*)
function-variable-name: '[a-z][a-z0-9]*(_[a-z0-9]+)*'
load-constant-name: (([A-Z][a-z0-9]*)+|[A-Z][A-Z0-9]*(_[A-Z0-9]+)*)
loop-variable-name: _?[a-z][a-z0-9]*(_[a-z0-9]+)*
signal-name: '[a-z][a-z0-9]*(_[a-z0-9]+)*'
sub-class-name: _?([A-Z][a-z0-9]*)+
Once the dump is performed, you can modify the gdlintrc file and optionally rename it to .gdlintrc.
From now on, linter will use this config file to override the default config.
The linter checks are divided into categories:
- name checks - the checks which are checking the naming conventions as per GDScript style guide
- basic checks - checks for very basic problems
- class checks - checks for problems related to classes
- design checks - checks for problems related to classes/functions design
- format checks - checks for file structure problems
- misc checks - other checks
-
function-name- validates if function name conforms tosnake_case,_private_snake_case, or_on_PascalCase_snake_case. -
class-name- validates if class name conforms toPascalCase. -
sub-class-name- validates if class name conforms to_PrivatePascalCase. -
signal-name- validates if signal name conforms toPascalCase. -
class-variable-name- validates if class variable name conforms tosnake_caseor_private_snake_case. -
class-load-variable-name- validates if class load variable (var variable = load(...)) name conforms toPascalCase,snake_caseorprivate_snake_case. -
function-variable-name- validates if function variable name conforms tosnake_case. -
function-preload-variable-name- validates if function preload variable (var Variable = preload(...)) name conforms toPascalCase. -
function-argument-name- validates if function argument (formal parameter) name conforms tosnake_caseor_private_snake_case. -
loop-variable-name- validates if loop variable name conforms tosnake_caseor_private_snake_case. -
enum-name- validates if enum name conforms toPascalCase. -
enum-element-name- validates if enum element name conforms toUPPER_SNAKE_CASE. -
constant-name- validates if constant name conforms toUPPER_SNAKE_CASE. -
load-constant-name- validates if load constant (const constant = load(...)) name conforms toPascalCase,snake_caseorprivate_snake_case.
-
duplicated-load- copy-pastedload(...)for the same path e.g.load("res://asdf.tscn")in multiple places. To fix, simply extract string to constant. -
expression-not-assigned- standalone expression like1 + 1which is not used in any way. To fix, simply remove that expression. -
unnecessary-pass-passwhich is not the only expression on class or function body. To fix, simple remove thatpassstatement. -
unused-argument- unused funtion argument. To fix, simply remove it or mark as explicitly unused by prefixing with underscore_e.g._unused_arg. -
comparison-with-itself- redundant comparison like e.g.x == xwhich is always true. To fix, simply remove that expression.
-
private-method-call- private (prefixed with underscore_) function was called. E.g.player._private_func(). To fix, redesign your approach so that private function is not being called. -
class-definitions-order- class statements are not in order. The order should be:toolclassnameextends- signals
- enums
- constants
- exports
- public variables
- private variables (prefixed with underscore
_) -
onreadypublic variables -
onreadyprivate variables (prefixed with underscore_) - other statements
-
max-public-methods- validates maximum number of public methods (class-level functions). -
function-arguments-number- validates number of function arguments.
-
max-file-lines- validates maximum number of file lines. -
trailing-whitespace- validates if any trailing whitespaces are present. -
max-line-length- validates maxium line length for each line. -
mixed-tabs-and-spaces- validates if either only tabs or only spaces are used for indentation.
-
no-elif-return- validates if unnecessaryelifis present in caseifbody was ended withreturn. -
no-else-return- validates if unnecessaryelseis present in caseif(and eachelif) body was ended withreturn.