blob: 6e126da27b6f8be00aac3fa0a47ff445dc2a45b8 [file] [log] [blame] [view] [edit]
# Buildifier warnings
Warning categories supported by buildifier's linter:
* [`attr-cfg`](#attr-cfg)
* [`attr-license`](#attr-license)
* [`attr-non-empty`](#attr-non-empty)
* [`attr-output-default`](#attr-output-default)
* [`attr-single-file`](#attr-single-file)
* [`build-args-kwargs`](#build-args-kwargs)
* [`bzl-visibility`](#bzl-visibility)
* [`confusing-name`](#confusing-name)
* [`constant-glob`](#constant-glob)
* [`ctx-actions`](#ctx-actions)
* [`ctx-args`](#ctx-args)
* [`depset-iteration`](#depset-iteration)
* [`depset-union`](#depset-union)
* [`dict-concatenation`](#dict-concatenation)
* [`duplicated-name`](#duplicated-name)
* [`filetype`](#filetype)
* [`function-docstring`](#function-docstring)
* [`function-docstring-header`](#function-docstring-header)
* [`function-docstring-args`](#function-docstring-args)
* [`function-docstring-return`](#function-docstring-return)
* [`git-repository`](#git-repository)
* [`http-archive`](#http-archive)
* [`integer-division`](#integer-division)
* [`keyword-positional-params`](#keyword-positional-params)
* [`list-append`](#list-append)
* [`load`](#load)
* [`load-on-top`](#load-on-top)
* [`module-docstring`](#module-docstring)
* [`name-conventions`](#name-conventions)
* [`native-android`](#native-android)
* [`native-build`](#native-build)
* [`native-cc`](#native-cc)
* [`native-java`](#native-java)
* [`native-package`](#native-package)
* [`native-proto`](#native-proto)
* [`native-py`](#native-py)
* [`no-effect`](#no-effect)
* [`out-of-order-load`](#out-of-order-load)
* [`output-group`](#output-group)
* [`overly-nested-depset`](#overly-nested-depset)
* [`package-name`](#package-name)
* [`package-on-top`](#package-on-top)
* [`positional-args`](#positional-args)
* [`print`](#print)
* [`redefined-variable`](#redefined-variable)
* [`repository-name`](#repository-name)
* [`return-value`](#return-value)
* [`rule-impl-return`](#rule-impl-return)
* [`same-origin-load`](#same-origin-load)
* [`string-escape`](#string-escape)
* [`string-iteration`](#string-iteration)
* [`uninitialized`](#uninitialized)
* [`unreachable`](#unreachable)
* [`unsorted-dict-items`](#unsorted-dict-items)
* [`unused-variable`](#unused-variable)
### How to disable warnings
All warnings can be disabled / suppressed / ignored by adding a special comment `# buildifier: disable=<category_name>` to
the expression that causes the warning. Historically comments with `buildozer` instead of
`buildifier` are also supported, they are equivalent.
#### Examples
```python
# buildifier: disable=no-effect
"""
A multiline comment as a string literal.
Docstrings don't trigger the warning if they are first statements of a file or a function.
"""
if debug:
print("Debug information:", foo) # buildifier: disable=print
```
--------------------------------------------------------------------------------
## <a name="attr-cfg"></a>`cfg = "data"` for attr definitions has no effect
* Category name: `attr-cfg`
* Flag in Bazel: [`--incompatible_disallow_data_transition`](https://github.com/bazelbuild/bazel/issues/6153)
* Automatic fix: yes
The [Configuration](https://docs.bazel.build/versions/master/skylark/rules.html#configurations)
`cfg = "data"` is deprecated and has no effect. Consider removing it.
--------------------------------------------------------------------------------
## <a name="attr-license"></a>`attr.license()` is deprecated and shouldn't be used
* Category name: `attr-license`
* Flag in Bazel: `--incompatible_no_attr_license`
* Automatic fix: no
The `attr.license()` method is almost never used and being deprecated.
--------------------------------------------------------------------------------
## <a name="attr-non-empty"></a>`non_empty` attribute for attr definitions are deprecated
* Category name: `attr-non-empty`
* Flag in Bazel: `--incompatible_disable_deprecated_attr_params`
* Automatic fix: yes
The `non_empty` [attribute](https://docs.bazel.build/versions/master/skylark/lib/attr.html)
for attr definitions is deprecated, please use `allow_empty` with an opposite value instead.
--------------------------------------------------------------------------------
## <a name="attr-output-default"></a>The `default` parameter for `attr.output()`is deprecated
* Category name: `attr-output-default`
* Flag in Bazel: [`--incompatible_no_output_attr_default`](https://github.com/bazelbuild/bazel/issues/7950)
* Automatic fix: no
The `default` parameter of `attr.output()` is bug-prone, as two targets of the same rule would be
unable to exist in the same package under default behavior. Use Starlark macros to specify defaults
for these attributes instead.
--------------------------------------------------------------------------------
## <a name="attr-single-file"></a>`single_file` is deprecated
* Category name: `attr-single-file`
* Flag in Bazel: `--incompatible_disable_deprecated_attr_params`
* Automatic fix: yes
The `single_file` [attribute](https://docs.bazel.build/versions/master/skylark/lib/attr.html)
is deprecated, please use `allow_single_file` instead.
--------------------------------------------------------------------------------
## <a name="build-args-kwargs"></a>`*args` and `**kwargs` are not allowed in BUILD files
* Category name: `build-args-kwargs`
* Flag in Bazel: `--incompatible_no_kwargs_in_build_files`
* Automatic fix: no
Having `*args` or `**kwargs` makes BUILD files hard to read and manipulate. The list of
arguments should be explicit.
--------------------------------------------------------------------------------
## <a name="bzl-visibility"></a>Module shouldn't be used directly
* Category name: `bzl-visibility`
* Automatic fix: no
If a directory `foo` contains a subdirectory `internal` or `private`, only files located under `foo`
can access it.
For example, `dir/rules_mockascript/private/foo.bzl` can be loaded from
`dir/rules_mockascript/private/bar.bzl` or `dir/rules_mockascript/sub/public.bzl`,
but not from `dir/other_rule/file.bzl`.
--------------------------------------------------------------------------------
## <a name="confusing-name"></a>Never use `l`, `I`, or `O` as names
* Category name: `confusing-name`
* Automatic fix: no
The names `l`, `I`, or `O` can be easily confused with `I`, `l`, or `0` correspondingly.
--------------------------------------------------------------------------------
## <a name="constant-glob"></a>Glob pattern has no wildcard ('*')
* Category name: `constant-glob`
* Automatic fix: no
[Glob function](https://docs.bazel.build/versions/master/be/functions.html#glob)
is used to get a list of files from the depot. The patterns (the first argument)
typically include a wildcard (* character). A pattern without a wildcard is
often useless and sometimes harmful.
To fix the warning, move the string out of the glob:
```diff
- glob(["*.cc", "test.cpp"])
+ glob(["*.cc"]) + ["test.cpp"]
```
**There’s one important difference**: before the change, Bazel would silently
ignore test.cpp if file is missing; after the change, Bazel will throw an error
if file is missing.
If `test.cpp` doesn’t exist, the fix becomes:
```diff
- glob(["*.cc", "test.cpp"])
+ glob(["*.cc"])
```
which improves maintenance and readability.
If no pattern has a wildcard, just remove the glob. It will also improve build
performance (glob can be relatively slow):
```diff
- glob(["test.cpp"])
+ ["test.cpp"]
```
--------------------------------------------------------------------------------
## <a name="ctx-actions"></a>`ctx.{action_name}` is deprecated
* Category name: `ctx-actions`
* Flag in Bazel: [`--incompatible_new_actions_api`](https://github.com/bazelbuild/bazel/issues/5825)
* Automatic fix: yes
The following [actions](https://docs.bazel.build/versions/master/skylark/lib/actions.html)
are deprecated, please use the new API:
* [`ctx.new_file`](https://docs.bazel.build/versions/master/skylark/lib/ctx.html#new_file) → [`ctx.actions.declare_file`](https://docs.bazel.build/versions/master/skylark/lib/actions.html#declare_file)
* `ctx.experimental_new_directory` → [`ctx.actions.declare_directory`](https://docs.bazel.build/versions/master/skylark/lib/actions.html#declare_directory)
* [`ctx.file_action`](https://docs.bazel.build/versions/master/skylark/lib/ctx.html#file_action) → [`ctx.actions.write`](https://docs.bazel.build/versions/master/skylark/lib/actions.html#write)
* [`ctx.action(command = "...")`](https://docs.bazel.build/versions/master/skylark/lib/ctx.html#action) → [`ctx.actions.run_shell`](https://docs.bazel.build/versions/master/skylark/lib/actions.html#run_shell)
* [`ctx.action(executable = "...")`](https://docs.bazel.build/versions/master/skylark/lib/ctx.html#action) → [`ctx.actions.run`](https://docs.bazel.build/versions/master/skylark/lib/actions.html#run)
* [`ctx.empty_action`](https://docs.bazel.build/versions/master/skylark/lib/ctx.html#empty_action) → [`ctx.actions.do_nothing`](https://docs.bazel.build/versions/master/skylark/lib/actions.html#do_nothing)
* [`ctx.template_action`](https://docs.bazel.build/versions/master/skylark/lib/ctx.html#template_action) → [`ctx.actions.expand_template`](https://docs.bazel.build/versions/master/skylark/lib/actions.html#expand_template)
--------------------------------------------------------------------------------
## <a name="ctx-args"></a>`ctx.actions.args().add()` for multiple arguments is deprecated
* Category name: `ctx-args`
* Flag in Bazel: [`--incompatible_disallow_old_style_args_add`](https://github.com/bazelbuild/bazel/issues/5822)
* Automatic fix: yes
It's deprecated to use the [`add`](https://docs.bazel.build/versions/master/skylark/lib/Args.html#add)
method of `ctx.actions.args()` to add a list (or a depset) of variables. Please use either
[`add_all`](https://docs.bazel.build/versions/master/skylark/lib/Args.html#add_all) or
[`add_joined`](https://docs.bazel.build/versions/master/skylark/lib/Args.html#add_joined),
depending on the desired behavior.
--------------------------------------------------------------------------------
## <a name="depset-iteration"></a>Depset iteration is deprecated
* Category name: `depset-iteration`
* Flag in Bazel: [`--incompatible_depset_is_not_iterable`](https://github.com/bazelbuild/bazel/issues/5816)
* Automatic fix: yes
Depsets are complex structures, iterations over them and lookups require flattening them to
a list which may be a heavy operation. To make it more obvious it's now required to call
the `.to_list()` method on them in order to be able to iterate their items:
```python
deps = depset()
[x.path for x in deps] # deprecated
[x.path for x in deps.to_list()] # recommended
```
--------------------------------------------------------------------------------
## <a name="depset-union"></a>Depsets should be joined using the depset constructor
* Category name: `depset-union`
* Flag in Bazel: [`--incompatible_depset_union`](https://github.com/bazelbuild/bazel/issues/5817)
* Automatic fix: no
The following ways to merge two depsets are deprecated:
```python
depset1 + depset2
depset1 | depset2
depset1.union(depset2)
```
Please use the [depset](https://docs.bazel.build/versions/master/skylark/lib/depset.html) constructor
instead:
```python
depset(transitive = [depset1, depset2])
```
When fixing this issue, make sure you
[understand depsets](https://docs.bazel.build/versions/master/skylark/depsets.html)
and try to
[reduce the number of calls to depset](https://docs.bazel.build/versions/master/skylark/performance.html#reduce-the-number-of-calls-to-depset).
--------------------------------------------------------------------------------
## <a name="dict-concatenation"></a>Dictionary concatenation is deprecated
* Category name: `dict-concatenation`
* Flag in Bazel: [`--incompatible_disallow_dict_plus`](https://github.com/bazelbuild/bazel/issues/6461)
* Automatic fix: no
The `+` operator to concatenate dicts is deprecated. The operator used to create a new dict and
copy the data to it. There are several ways to avoid it, for example, instead of `d = d1 + d2 + d3`
you can use one of the following:
* Use [Skylib](https://github.com/bazelbuild/bazel-skylib):
```python
load("@bazel_skylib//lib:dicts.bzl", "dicts")
d = dicts.add(d1, d2, d3)
```
* The same if you don't want to use Skylib:
```python
d = dict(d1.items() + d2.items() + d3.items())
```
* The same in several steps:
```python
d = dict(d1) # If you don't want `d1` to be mutated
d.update(d2)
d.update(d3)
```
--------------------------------------------------------------------------------
## <a name="duplicated-name"></a>A rule with name `foo` was already found on line
* Category name: `duplicated-name`
* Automatic fix: no
### Background
Each label in Bazel has a unique name, and Bazel doesn’t allow two rules to have
the same name. With macros, this may be accepted by Bazel (if each macro
generates different rules):
```python
my_first_macro(name = "foo")
my_other_macro(name = "foo")
```
Although the build may work, this code can be very confusing. It can confuse
users reading a BUILD file (if they look for the rule “foo”, they may read see
only one of the macros). It will also confuse tools that edit BUILD files.
### How to fix it
Just change the name attribute of one rule/macro.
--------------------------------------------------------------------------------
## <a name="filetype"></a>The `FileType` function is deprecated
* Category name: `filetype`
* Flag in Bazel: [`--incompatible_disallow_filetype`](https://github.com/bazelbuild/bazel/issues/5831)
* Automatic fix: no
The function `FileType` is deprecated.
Instead of using it as an argument to the [`rule` function](https://docs.bazel.build/versions/master/skylark/lib/globals.html#rule)
just use a list of strings.
--------------------------------------------------------------------------------
## <a name="function-docstring"></a><a name="function-docstring-header"></a><a name="function-docstring-args"></a><a name="function-docstring-return"></a>Function docstring
* Category names:
* `function-docstring`
* `function-docstring-header`
* `function-docstring-args`
* `function-docstring-return`
* Automatic fix: no
Public functions should have docstrings describing functions and their signatures.
A docstring is a string literal (not a comment) which should be the first statement
of a function (it may follow comment lines). Function docstrings are expected to be
formatted in the following way:
```python
"""One-line summary: must be followed and may be preceded by a blank line.
Optional additional description like this.
If it's a function docstring and the function has more than one argument, the docstring has
to document these parameters as follows:
Args:
parameter1: description of the first parameter. Each parameter line
should be indented by one, preferably two, spaces (as here).
parameter2: description of the second
parameter that spans two lines. Each additional line should have a
hanging indentation of at least one, preferably two, additional spaces (as here).
another_parameter (unused, mutable): a parameter may be followed
by additional attributes in parentheses
Returns:
Description of the return value.
Should be indented by at least one, preferably two spaces (as here)
Can span multiple lines.
"""
```
Docstrings are required for all public functions with at least 5 statements. If a docstring exists
it should start with a one-line summary line followed by an empty line. If a docsrting is required
or it describe some of the arguments, it should describe all of them. If a docstring is required and
the function returns a value, it should be described.
--------------------------------------------------------------------------------
## <a name="git-repository"></a>Function `git_repository` is not global anymore
* Category name: `git-repository`
* Flag in Bazel: [`--incompatible_remove_native_git_repository`](https://github.com/bazelbuild/bazel/issues/6569)
* Automatic fix: yes
Native `git_repository` and `new_git_repository` functions are removed.
Please use the Starlark versions instead:
```python
load("@bazel_tools//tools/build_defs/repo:git.bzl", "git_repository", "new_git_repository")
```
--------------------------------------------------------------------------------
## <a name="http-archive"></a>Function `http_archive` is not global anymore
* Category name: `http-archive`
* Flag in Bazel: [`--incompatible_remove_native_http_archive`](https://github.com/bazelbuild/bazel/issues/6570)
* Automatic fix: yes
Native `http_archive` function are removed.
Please use the Starlark versions instead:
```python
load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")
```
--------------------------------------------------------------------------------
## <a name="integer-division"></a>The `/` operator for integer division is deprecated
* Category name: `integer-division`
* Flag in Bazel: [`--incompatible_disallow_slash_operator`](https://github.com/bazelbuild/bazel/issues/5823)
* Automatic fix: yes
The `/` operator is deprecated in favor of `//`, please use the latter for
integer division:
```python
a = b // c
d //= e
```
--------------------------------------------------------------------------------
## <a name="keyword-positional-params"></a>Keyword parameter should be positional
* Category_name: `keyword-positional-params`
* Automatic fix: yes
Some parameters for builtin functions in Starlark are keyword for legacy reasons;
their names are not meaningful (e.g. `x`). Making them positional-only will improve
the readability.
--------------------------------------------------------------------------------
## <a name="list-append"></a>Prefer using ".append()" to adding a single element list
* Category name: `list-append`
* Automatic fix: yes
Transforming `x += [expr]` to `x.append(expr)` avoids a list allocation.
--------------------------------------------------------------------------------
## <a name="load"></a>Loaded symbol is unused
* Category name: `load`
* Automatic fix: yes
### Background
[load](https://docs.bazel.build/versions/master/skylark/concepts.html#loading-an-extension)
is used to import definitions in a BUILD file. If the definition is not used in
the file, the load can be safely removed. If a symbol is loaded two times, you
will get a warning on the second occurrence.
### How to fix it
Delete the line. When load is used to import multiple symbols, you can remove
the unused symbols from the list. To fix your BUILD files automatically, try
this command:
```console
$ buildozer 'fix unusedLoads' path/to/BUILD
```
If you want to keep the load, you can disable the warning by adding a comment
`# @unused`.
--------------------------------------------------------------------------------
## <a name="load-on-top"></a>Load statements should be at the top of the file
* Category name: `load-on-top`
* Flag in Bazel: [`--incompatible_bzl_disallow_load_after_statement`](https://github.com/bazelbuild/bazel/issues/5815)
* Automatic fix: yes
Load statements should be first statements (with the exception of `WORKSPACE` files),
they can follow only comments and docstrings.
--------------------------------------------------------------------------------
## <a name="module-docstring"></a>The file has no module docstring
* Category name: `module-docstring`
* Automatic fix: no
`.bzl` files should have docstrings on top of them. A docstring is a string literal
(not a comment) which should be the first statement of the file (it may follow
comment lines). For example:
```python
"""
This module contains build rules for my project.
"""
...
```
--------------------------------------------------------------------------------
## <a name="name-conventions"></a>Name conventions
* Category name: `name-conventions`
* Automatic fix: no
By convention, all variables should be lower_snake_case, constant should be
UPPER_SNAKE_CASE, and providers should be UpperCamelCase ending with `Info`.
--------------------------------------------------------------------------------
## <a name="native-android"></a>All Android build rules should be loaded from Starlark
* Category name: `native-android`
* Automatic fix: yes
The Android build rules should be loaded from Starlark. The native rules [will be
disabled](https://github.com/bazelbuild/bazel/issues/8391).
--------------------------------------------------------------------------------
## <a name="native-build"></a>The `native` module shouldn't be used in BUILD files
* Category name: `native-build`
* Automatic fix: yes
There's no need in using `native.` in BUILD files, its members are available as global symbols
there.
--------------------------------------------------------------------------------
## <a name="native-cc"></a>All C++ build rules should be loaded from Starlark
* Category name: `native-cc`
* Flag in Bazel: [`--incompatible_load_cc_rules_from_bzl`](https://github.com/bazelbuild/bazel/issues/8743)
* Automatic fix: yes
The C++ build rules should be loaded from Starlark. The native rules [will be
disabled](https://github.com/bazelbuild/bazel/issues/8743).
--------------------------------------------------------------------------------
## <a name="native-java"></a>All Java build rules should be loaded from Starlark
* Category name: `native-java`
* Flag in Bazel: [`--incompatible_load_java_rules_from_bzl`](https://github.com/bazelbuild/bazel/issues/8746)
* Automatic fix: yes
The Java build rules should be loaded from Starlark. The native rules [will be
disabled](https://github.com/bazelbuild/bazel/issues/8746).
--------------------------------------------------------------------------------
## <a name="native-package"></a>`native.package()` shouldn't be used in .bzl files
* Category name: `native-package`
* Automatic fix: no
It's discouraged and will be disallowed to use `native.package()` in .bzl files. It can silently
modify the semantics of a BUILD file and makes it hard to maintain.
--------------------------------------------------------------------------------
## <a name="native-proto"></a>All Proto build rules and symbols should be loaded from Starlark
* Category name: `native-proto`
* Flag in Bazel: [`--incompatible_load_proto_rules_from_bzl`](https://github.com/bazelbuild/bazel/issues/8922)
* Automatic fix: yes
The Proto build rules and symbols should be loaded from Starlark. The native
rules [will be disabled](https://github.com/bazelbuild/bazel/issues/8922).
--------------------------------------------------------------------------------
## <a name="native-py"></a>All Python build rules should be loaded from Starlark
* Category name: `native-py`
* Flag in Bazel: [`--incompatible_load_python_rules_from_bzl`](https://github.com/bazelbuild/bazel/issues/9006)
* Automatic fix: yes
The Python build rules should be loaded from Starlark. The native rules [will be
disabled](https://github.com/bazelbuild/bazel/issues/9006).
--------------------------------------------------------------------------------
## <a name="no-effect"></a>Expression result is not used
* Category name: `no-effect`
* Automatic fix: no
The statement has no effect. Consider removing it or storing its result in a
variable.
--------------------------------------------------------------------------------
## <a name="out-of-order-load"></a>Load statements should be ordered by their labels
* Category name: `out-of-order-load`
* Automatic fix: yes
* [Disabled by default](buildifier/README.md#linter)
Load statements should be ordered by their first argument - extension file label.
This makes it easier to developers to locate loads of interest and reduces chances
for conflicts when performing large-scale automated refactoring.
When applying automated fixes, it's highly recommended to also use
[`load-on-top`](#load-on-top) fixes, since otherwise the relative order
of a symbol load and its usage can change resulting in runtime error.
--------------------------------------------------------------------------------
## <a name="output-group"></a>`ctx.attr.dep.output_group` is deprecated
* Category name: `output-group`
* Flag in Bazel: [`--incompatible_no_target_output_group`](https://github.com/bazelbuild/bazel/issues/7949)
* Automatic fix: yes
The `output_group` field of a target is deprecated in favor of the
[`OutputGroupInfo` provider](https://docs.bazel.build/versions/master/skylark/lib/OutputGroupInfo.html).
--------------------------------------------------------------------------------
## <a name="overly-nested-depset"></a>The depset is potentially overly nested
* Category name: `overly-nested-depset`
* Automatic fix: no
If a depset is iteratively chained in a for loop, e.g. the following pattern is used:
```python
for ...:
x = depset(..., transitive = [..., x, ...])
```
this can result in an overly nested depset with a long chain of transitive elements. Such patterns
can lead to performance problems, consider refactoring the code to create a flat list of transitive
elements and call the depset constructor just once:
```python
transitive = []
for ...:
transitive += ...
x = depset(..., transitive = transitive)
```
Or in simple cases you can use list comprehensions instead:
```python
x = depset(..., transitive = [y.deps for y in ...])
```
For more information, read Bazel documentation about
[depsets](https://docs.bazel.build/versions/master/skylark/depsets.html)
and
[reducing the number of calls to depset](https://docs.bazel.build/versions/master/skylark/performance.html#reduce-the-number-of-calls-to-depset).
--------------------------------------------------------------------------------
## <a name="package-name"></a>Global variable `PACKAGE_NAME` is deprecated
* Category name: `package-name`
* Flag in Bazel: [`--incompatible_package_name_is_a_function`](https://github.com/bazelbuild/bazel/issues/5827)
* Automatic fix: yes
The global variable `PACKAGE_NAME` is deprecated, please use
[`native.package_name()`](https://docs.bazel.build/versions/master/skylark/lib/native.html#package_name)
instead.
--------------------------------------------------------------------------------
## <a name="package-on-top"></a>Package declaration should be at the top of the file
* Category name: `package-on-top`
* Automatic fix: no
Here is a typical structure of a BUILD file:
* `load()` statements
* `package()`
* calls to rules, macros
Instantiating a rule and setting the package defaults later can be very
confusing, and has been a source of bugs (tools and humans sometimes believe
package applies to everything in a BUILD file). This might become an error in
the future (but it requires large-scale changes in google3).
### What can be used before package()?
The linter allows the following to be before `package()`:
* comments
* `load()`
* variable declarations
* `package_group()`
* `licenses()`
--------------------------------------------------------------------------------
## <a name="positional-args"></a>Keyword arguments should be used over positional arguments
* Category name: `positional-args`
* Automatic fix: no
All top level calls (except for some built-ins) should use keyword args over
positional arguments. Positional arguments can cause subtle errors if the order
is switched or if an argument is removed. Keyword args also greatly improve
readability.
```diff
- my_macro("foo", "bar")
+ my_macro(name = "foo", env = "bar")
```
The linter allows the following functions to be called with positional
arguments:
* `load()`
* `vardef()`
* `export_files()`
* `licenses()`
* `print()`
--------------------------------------------------------------------------------
## <a name="print"></a>`print()` is a debug function and shouldn't be submitted
* Category name: `print`
* Automatic fix: no
Using the `print()` function for warnings is discouraged: they are often spammy and
non actionable, the people who see the warning are usually not the people who can
fix the code to make the warning disappear, and the actual maintainers of the code
may never see the warning.
--------------------------------------------------------------------------------
## <a name="redefined-variable"></a>Variable has already been defined
* Category name: `redefined-variable`
* Automatic fix: no
### Background
In .bzl files, redefining a global variable is already forbidden. This helps
both humans and tools reason about the code. For consistency, we want to bring
this restriction also to BUILD files.
### How to fix it
Rename one of the variables.
Note that the content of lists and dictionaries can still be modified. We will
forbid reassignment, but not every side-effect.
--------------------------------------------------------------------------------
## <a name="repository-name"></a>Global variable `REPOSITORY_NAME` is deprecated
* Category name: `repository-name`
* Flag in Bazel: [`--incompatible_package_name_is_a_function`](https://github.com/bazelbuild/bazel/issues/5827)
* Automatic fix: yes
The global variable `REPOSITORY_NAME` is deprecated, please use
[`native.repository_name()`](https://docs.bazel.build/versions/master/skylark/lib/native.html#repository_name)
instead.
--------------------------------------------------------------------------------
## <a name="return-value"></a>Some but not all execution paths of a function return a value
* Category name: `return-value`
* Automatic fix: no
Some but not all execution paths of a function return a value. Either there's
an explicit empty `return` statement, or an implcit return in the end of a
function. If it is intentional, make it explicit using `return None`. If you
know certain parts of the code cannot be reached, add the statement
`fail("unreachable")` to them.
--------------------------------------------------------------------------------
## <a name="rule-impl-return"></a>Avoid using the legacy provider syntax
* Category name: `rule-impl-return`
* Automatic fix: no
Returning structs from rule implementation functions is
<a href="https://docs.bazel.build/versions/master/skylark/rules.html#migrating-from-legacy-providers">deprecated</a>,
consider using
<a href="https://docs.bazel.build/versions/master/skylark/rules.html#providers">providers</a>
or lists of providers instead.
--------------------------------------------------------------------------------
## <a name="same-origin-load"></a>Same label is used for multiple loads
* Category name: `same-origin-load`
* Automatic fix: yes
### Background
[load](https://docs.bazel.build/versions/master/skylark/concepts.html#loading-an-extension)
is used to import definitions in a BUILD file. If the same label is used for loading
symbols more the ones, all such loads can be merged into a single one.
### How to fix it
Merge all loads into a single one. For example,
```python
load(":f.bzl", "s1")
load(":f.bzl", "s2")
```
can be written more compactly as
```python
load(":f.bzl", "s1", "s2")
```
--------------------------------------------------------------------------------
## <a name="string-escape"></a>Invalid escape sequence
* Category name: `string-escape`
* Flag in Bazel: [`--incompatible_restrict_string_escapes`](https://github.com/bazelbuild/bazel/issues/8380)
* Automatic fix: yes
Unrecognized escape sequences in string literals (e.g. `"\a \b"` is error-prone and shouldn't
be used. If you need the backslash symbol, escape it explicitly: `"\\a \\b"`.
--------------------------------------------------------------------------------
## <a name="string-iteration"></a>String iteration is deprecated
* Category name: `string-iteration`
* Flag in Bazel: [`--incompatible_string_is_not_iterable`](https://github.com/bazelbuild/bazel/issues/5830)
* Automatic fix: no
Iteration over strings often leads to confusion with iteration over a sequence of strings,
therefore strings won't be recognized as sequences of 1-element strings (like in Python).
Use string indexing and `len` instead:
```python
my_string = "hello world"
for i in range(len(my_string)):
char = my_string[i]
# do something with char
```
--------------------------------------------------------------------------------
## <a name="uninitialized"></a>Variable may not have been initialized
* Category name: `uninitialized`
* Automatic fix: no
The local value can be not initialized at the time of execution. It may happen if it's
initialized in one of the if-else clauses but not in all of them, or in a for-loop which
can potentially be empty.
--------------------------------------------------------------------------------
## <a name="unreachable"></a>The statement is unreachable
* Category name: `unreachable`
* Automatic fix: no
The statement is unreachable because it follows a `return`, `break`, `continue`,
or `fail()` statement.
--------------------------------------------------------------------------------
## <a name="unsorted-dict-items"></a>Dictionary items should be ordered by their keys
* Category name: `unsorted-dict-items`
* Automatic fix: yes
* [Disabled by default](buildifier/README.md#linter)
Dictionary items should be sorted lexicagraphically by their keys. This makes
it easier to find the item of interest and reduces chances of conflicts when
performing large-scale automated refactoring.
The order is affected by `NamePriority` dictionary passed using `-tables` or
`-add_tables` flags.
If you want to preserve the original dictionary items order, you can disable
the warning by adding a comment `# @unsorted-dict-items` to the dictionary
expression or any of its enclosing expressins (binary, if etc). For example,
```python
# @unsorted-dict-items
d = {
"b": "bvalue",
"a": "avalue",
}
```
will not be reported as an issue because the assignment operation that uses
the dictionary with unsorted items has a comment disabling this warning.
--------------------------------------------------------------------------------
## <a name="unused-variable"></a>Variable is unused
* Category name: `unused-variable`
* Automatic fix: no
This happens when a variable is set but not used in the file, e.g.
```python
x = [1, 2]
```
The line can often be safely removed.
If you want to keep the variable, you can disable the warning by adding a
comment `# @unused`.
```python
x = [1, 2] # @unused
```