-
-
Notifications
You must be signed in to change notification settings - Fork 72
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_case
or_private_snake_case
. -
class-load-variable-name
- validates if class load variable (var variable = load(...)
) name conforms toPascalCase
,snake_case
orprivate_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_case
or_private_snake_case
. -
loop-variable-name
- validates if loop variable name conforms tosnake_case
or_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_case
orprivate_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 + 1
which is not used in any way. To fix, simply remove that expression. -
unnecessary-pass
-pass
which is not the only expression on class or function body. To fix, simple remove thatpass
statement. -
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 == x
which 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:tool
classname
extends
- signals
- enums
- constants
- exports
- public variables
- private variables (prefixed with underscore
_
) -
onready
public variables -
onready
private 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 unnecessaryelif
is present in caseif
body was ended withreturn
. -
no-else-return
- validates if unnecessaryelse
is present in caseif
(and eachelif
) body was ended withreturn
.