Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 22 additions & 0 deletions WARNINGS.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

Warning categories supported by buildifier's linter:

* [`allowed-symbol-load-locations`](#allowed-symbol-load-locations)
* [`attr-applicable_licenses`](#attr-applicable_licenses)
* [`attr-cfg`](#attr-cfg)
* [`attr-license`](#attr-license)
Expand Down Expand Up @@ -128,6 +129,27 @@ if debug:

--------------------------------------------------------------------------------

## <a name="allowed-symbol-load-locations"></a>Symbol must be loaded from a specific location

* Category name: `allowed-symbol-load-locations`
* Automatic fix: no
* [Suppress the warning](#suppress): `# buildifier: disable=allowed-symbol-load-locations`

Warns when a symbol is loaded from a location other than the expected ones.
Expected locations are specified in the tables file:

```json
{
"AllowedSymbolLoadLocations": {
"genrule": [
"//tools/bazel:genrule.bzl"
]
}
}
```

--------------------------------------------------------------------------------

## <a name="attr-applicable_licenses"></a>Do not use `applicable_licenses` as an attribute name.

* Category name: `attr-applicable_licenses`
Expand Down
7 changes: 5 additions & 2 deletions buildifier/config/config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ func ExampleExample() {
// "mode": "fix",
// "lint": "fix",
// "warningsList": [
// "allowed-symbol-load-locations",
// "attr-applicable_licenses",
// "attr-cfg",
// "attr-license",
Expand Down Expand Up @@ -263,6 +264,7 @@ func TestValidate(t *testing.T) {
"type auto": {options: "--type=auto"},
"type error": {options: "--type=foo", wantErr: fmt.Errorf("unrecognized input type foo; valid types are build, bzl, workspace, default, module, auto")},
"warnings all": {options: "--warnings=all", wantWarnings: []string{
"allowed-symbol-load-locations",
"attr-applicable_licenses",
"attr-cfg",
"attr-license",
Expand Down Expand Up @@ -364,6 +366,7 @@ func TestValidate(t *testing.T) {
"unused-variable",
}},
"warnings default": {options: "--warnings=default", wantWarnings: []string{
"allowed-symbol-load-locations",
"attr-applicable_licenses",
"attr-cfg",
"attr-license",
Expand Down Expand Up @@ -465,6 +468,7 @@ func TestValidate(t *testing.T) {
"unused-variable",
}},
"warnings plus/minus": {options: "--warnings=+unsorted-dict-items,-print,-deprecated-function", wantWarnings: []string{
"allowed-symbol-load-locations",
"attr-applicable_licenses",
"attr-cfg",
"attr-license",
Expand Down Expand Up @@ -556,7 +560,6 @@ func TestValidate(t *testing.T) {
"repository-name",
"return-value",
"rule-impl-return",

"skylark-comment",
"skylark-docstring",
"string-iteration",
Expand All @@ -567,6 +570,7 @@ func TestValidate(t *testing.T) {
"unused-variable",
}},
"warnings no duplicates": {options: "--warnings=+unused-variable", wantWarnings: []string{
"allowed-symbol-load-locations",
"attr-applicable_licenses",
"attr-cfg",
"attr-license",
Expand Down Expand Up @@ -658,7 +662,6 @@ func TestValidate(t *testing.T) {
"repository-name",
"return-value",
"rule-impl-return",

"skylark-comment",
"skylark-docstring",
"string-iteration",
Expand Down
34 changes: 34 additions & 0 deletions buildifier/integration_test.sh
Original file line number Diff line number Diff line change
Expand Up @@ -258,6 +258,7 @@ cat > golden/.buildifier.example.json <<EOF
"mode": "fix",
"lint": "fix",
"warningsList": [
"allowed-symbol-load-locations",
"attr-applicable_licenses",
"attr-cfg",
"attr-license",
Expand Down Expand Up @@ -691,3 +692,36 @@ EOF

$buildifier --lint=warn --warnings=deprecated-function BUILD 2> report || ret=$?
diff -u report_golden report || die "$1: wrong console output for multifile warnings (WORKSPACE exists)"

cd ..

# Test allowed symbol load locations

mkdir test_dir/allowed_locations
cd test_dir/allowed_locations

cat > BUILD <<EOF
load(":f.bzl", "s1", "s2")
load(":a.bzl", "s3")
load(":a.bzl", "s4")
EOF

cat > buildifier.tables <<EOF
{
"AllowedSymbolLoadLocations": {
"s1": [":z.bzl"],
"s3": [":y.bzl", ":x.bzl"],
"s4": [":a.bzl"]
}
}
EOF

cat > report_golden <<EOF
BUILD:1: allowed-symbol-load-locations: Symbol "s1" must be loaded from :z.bzl. (https://github.com/bazelbuild/buildtools/blob/main/WARNINGS.md#allowed-symbol-load-locations)
BUILD:2: allowed-symbol-load-locations: Symbol "s3" must be loaded from one of the allowed locations: :x.bzl, :y.bzl. (https://github.com/bazelbuild/buildtools/blob/main/WARNINGS.md#allowed-symbol-load-locations)
EOF

$buildifier --lint=warn --warnings=allowed-symbol-load-locations -tables=buildifier.tables BUILD 2> report || true
diff -u report_golden report || die "$1: wrong console output for allowed symbol load locations"

cd ../..
5 changes: 3 additions & 2 deletions tables/jsonparser.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ type Definitions struct {
NamePriority map[string]int
StripLabelLeadingSlashes bool
ShortenAbsoluteLabelsToRelative bool
AllowedSymbolLoadLocations map[string][]string
}

// ParseJSONDefinitions reads and parses JSON table definitions from file.
Expand All @@ -55,9 +56,9 @@ func ParseAndUpdateJSONDefinitions(file string, merge bool) error {
}

if merge {
MergeTables(definitions.IsLabelArg, definitions.LabelDenylist, definitions.IsListArg, definitions.IsSortableListArg, definitions.SortableDenylist, definitions.SortableAllowlist, definitions.NamePriority, definitions.StripLabelLeadingSlashes, definitions.ShortenAbsoluteLabelsToRelative)
MergeTables(definitions.IsLabelArg, definitions.LabelDenylist, definitions.IsListArg, definitions.IsSortableListArg, definitions.SortableDenylist, definitions.SortableAllowlist, definitions.NamePriority, definitions.StripLabelLeadingSlashes, definitions.ShortenAbsoluteLabelsToRelative, definitions.AllowedSymbolLoadLocations)
} else {
OverrideTables(definitions.IsLabelArg, definitions.LabelDenylist, definitions.IsListArg, definitions.IsSortableListArg, definitions.SortableDenylist, definitions.SortableAllowlist, definitions.NamePriority, definitions.StripLabelLeadingSlashes, definitions.ShortenAbsoluteLabelsToRelative)
OverrideTables(definitions.IsLabelArg, definitions.LabelDenylist, definitions.IsListArg, definitions.IsSortableListArg, definitions.SortableDenylist, definitions.SortableAllowlist, definitions.NamePriority, definitions.StripLabelLeadingSlashes, definitions.ShortenAbsoluteLabelsToRelative, definitions.AllowedSymbolLoadLocations)
}
return nil
}
15 changes: 8 additions & 7 deletions tables/jsonparser_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,13 +30,14 @@ func TestParseJSONDefinitions(t *testing.T) {
}

expected := Definitions{
IsLabelArg: map[string]bool{"srcs": true},
LabelDenylist: map[string]bool{},
IsSortableListArg: map[string]bool{"srcs": true, "visibility": true},
SortableDenylist: map[string]bool{"genrule.srcs": true},
SortableAllowlist: map[string]bool{},
NamePriority: map[string]int{"name": -1},
StripLabelLeadingSlashes: true,
IsLabelArg: map[string]bool{"srcs": true},
LabelDenylist: map[string]bool{},
IsSortableListArg: map[string]bool{"srcs": true, "visibility": true},
SortableDenylist: map[string]bool{"genrule.srcs": true},
SortableAllowlist: map[string]bool{},
NamePriority: map[string]int{"name": -1},
StripLabelLeadingSlashes: true,
AllowedSymbolLoadLocations: map[string][]string{"genrule": {"//tools/bazel:genrule.bzl"}},
}
if !reflect.DeepEqual(expected, definitions) {
t.Errorf("ParseJSONDefinitions(simple_tables.json) = %v; want %v", definitions, expected)
Expand Down
24 changes: 22 additions & 2 deletions tables/tables.go
Original file line number Diff line number Diff line change
Expand Up @@ -265,8 +265,11 @@ var IsModuleOverride = map[string]bool{
"single_version_override": true,
}

// AllowedSymbolLoadLocations contains locations for loading rules that are allowed to be used.
var AllowedSymbolLoadLocations = map[string]map[string]bool{}

// OverrideTables allows a user of the build package to override the special-case rules. The user-provided tables replace the built-in tables.
func OverrideTables(labelArg, denylist, listArg, sortableListArg, sortDenylist, sortAllowlist map[string]bool, namePriority map[string]int, stripLabelLeadingSlashes, shortenAbsoluteLabelsToRelative bool) {
func OverrideTables(labelArg, denylist, listArg, sortableListArg, sortDenylist, sortAllowlist map[string]bool, namePriority map[string]int, stripLabelLeadingSlashes, shortenAbsoluteLabelsToRelative bool, symbolLoadLocation map[string][]string) {
IsLabelArg = labelArg
LabelDenylist = denylist
IsListArg = listArg
Expand All @@ -276,10 +279,19 @@ func OverrideTables(labelArg, denylist, listArg, sortableListArg, sortDenylist,
NamePriority = namePriority
StripLabelLeadingSlashes = stripLabelLeadingSlashes
ShortenAbsoluteLabelsToRelative = shortenAbsoluteLabelsToRelative

AllowedSymbolLoadLocations = map[string]map[string]bool{}
for k, v := range symbolLoadLocation {
locations := map[string]bool{}
for _, l := range v {
locations[l] = true
}
AllowedSymbolLoadLocations[k] = locations
}
}

// MergeTables allows a user of the build package to override the special-case rules. The user-provided tables are merged into the built-in tables.
func MergeTables(labelArg, denylist, listArg, sortableListArg, sortDenylist, sortAllowlist map[string]bool, namePriority map[string]int, stripLabelLeadingSlashes, shortenAbsoluteLabelsToRelative bool) {
func MergeTables(labelArg, denylist, listArg, sortableListArg, sortDenylist, sortAllowlist map[string]bool, namePriority map[string]int, stripLabelLeadingSlashes, shortenAbsoluteLabelsToRelative bool, symbolLoadLocation map[string][]string) {
for k, v := range labelArg {
IsLabelArg[k] = v
}
Expand All @@ -303,4 +315,12 @@ func MergeTables(labelArg, denylist, listArg, sortableListArg, sortDenylist, sor
}
StripLabelLeadingSlashes = stripLabelLeadingSlashes || StripLabelLeadingSlashes
ShortenAbsoluteLabelsToRelative = shortenAbsoluteLabelsToRelative || ShortenAbsoluteLabelsToRelative

for k, v := range symbolLoadLocation {
locations := map[string]bool{}
for _, l := range v {
locations[l] = true
}
AllowedSymbolLoadLocations[k] = locations
}
}
7 changes: 6 additions & 1 deletion tables/testdata/simple_tables.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,5 +19,10 @@
"NamePriority": {
"name": -1
},
"StripLabelLeadingSlashes": true
"StripLabelLeadingSlashes": true,
"AllowedSymbolLoadLocations": {
"genrule": [
"//tools/bazel:genrule.bzl"
]
}
}
2 changes: 2 additions & 0 deletions warn/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ go_library(
"warn_cosmetic.go",
"warn_deprecated.go",
"warn_docstring.go",
"warn_load.go",
"warn_macro.go",
"warn_naming.go",
"warn_operation.go",
Expand Down Expand Up @@ -42,6 +43,7 @@ go_test(
"warn_cosmetic_test.go",
"warn_deprecated_test.go",
"warn_docstring_test.go",
"warn_load_test.go",
"warn_macro_test.go",
"warn_naming_test.go",
"warn_operation_test.go",
Expand Down
17 changes: 17 additions & 0 deletions warn/docs/warnings.textproto
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,23 @@
# proto-message: Warnings
# After modifying this file, run `bazel build //warn/docs:warnings_docs && cp bazel-bin/warn/docs/WARNINGS.md .`

warnings: {
name: "allowed-symbol-load-locations"
header: "Symbol must be loaded from a specific location"
description:
"Warns when a symbol is loaded from a location other than the expected ones.\n"
"Expected locations are specified in the tables file:\n\n"
"```json\n"
"{\n"
" \"AllowedSymbolLoadLocations\": {\n"
" \"genrule\": [\n"
" \"//tools/bazel:genrule.bzl\"\n"
" ]\n"
" }\n"
"}\n"
"```"
}

warnings: {
name: "attr-cfg"
header: "`cfg = \"data\"` for attr definitions has no effect"
Expand Down
103 changes: 52 additions & 51 deletions warn/warn.go
Original file line number Diff line number Diff line change
Expand Up @@ -116,57 +116,58 @@ var RuleWarningMap = map[string]func(call *build.CallExpr, pkg string) *LinterFi

// FileWarningMap lists the warnings that run on the whole file.
var FileWarningMap = map[string]func(f *build.File) []*LinterFinding{
"attr-applicable_licenses": attrApplicableLicensesWarning,
"attr-cfg": attrConfigurationWarning,
"attr-license": attrLicenseWarning,
"attr-licenses": attrLicensesWarning,
"attr-non-empty": attrNonEmptyWarning,
"attr-output-default": attrOutputDefaultWarning,
"attr-single-file": attrSingleFileWarning,
"build-args-kwargs": argsKwargsInBuildFilesWarning,
"canonical-repository": canonicalRepositoryWarning,
"confusing-name": confusingNameWarning,
"constant-glob": constantGlobWarning,
"ctx-actions": ctxActionsWarning,
"ctx-args": contextArgsAPIWarning,
"depset-items": depsetItemsWarning,
"depset-iteration": depsetIterationWarning,
"depset-union": depsetUnionWarning,
"dict-method-named-arg": dictMethodNamedArgWarning,
"dict-concatenation": dictionaryConcatenationWarning,
"duplicated-name": duplicatedNameWarning,
"external-path": externalPathWarning,
"filetype": fileTypeWarning,
"function-docstring": functionDocstringWarning,
"function-docstring-header": functionDocstringHeaderWarning,
"function-docstring-args": functionDocstringArgsWarning,
"function-docstring-return": functionDocstringReturnWarning,
"integer-division": integerDivisionWarning,
"keyword-positional-params": keywordPositionalParametersWarning,
"list-append": listAppendWarning,
"load": unusedLoadWarning,
"module-docstring": moduleDocstringWarning,
"name-conventions": nameConventionsWarning,
"native-build": nativeInBuildFilesWarning,
"native-package": nativePackageWarning,
"no-effect": noEffectWarning,
"output-group": outputGroupWarning,
"overly-nested-depset": overlyNestedDepsetWarning,
"package-name": packageNameWarning,
"package-on-top": packageOnTopWarning,
"print": printWarning,
"provider-params": providerParamsWarning,
"redefined-variable": redefinedVariableWarning,
"repository-name": repositoryNameWarning,
"rule-impl-return": ruleImplReturnWarning,
"return-value": missingReturnValueWarning,
"skylark-comment": skylarkCommentWarning,
"skylark-docstring": skylarkDocstringWarning,
"string-iteration": stringIterationWarning,
"uninitialized": uninitializedVariableWarning,
"unreachable": unreachableStatementWarning,
"unsorted-dict-items": unsortedDictItemsWarning,
"unused-variable": unusedVariableWarning,
"allowed-symbol-load-locations": symbolLoadLocationWarning,
"attr-applicable_licenses": attrApplicableLicensesWarning,
"attr-cfg": attrConfigurationWarning,
"attr-license": attrLicenseWarning,
"attr-licenses": attrLicensesWarning,
"attr-non-empty": attrNonEmptyWarning,
"attr-output-default": attrOutputDefaultWarning,
"attr-single-file": attrSingleFileWarning,
"build-args-kwargs": argsKwargsInBuildFilesWarning,
"canonical-repository": canonicalRepositoryWarning,
"confusing-name": confusingNameWarning,
"constant-glob": constantGlobWarning,
"ctx-actions": ctxActionsWarning,
"ctx-args": contextArgsAPIWarning,
"depset-items": depsetItemsWarning,
"depset-iteration": depsetIterationWarning,
"depset-union": depsetUnionWarning,
"dict-method-named-arg": dictMethodNamedArgWarning,
"dict-concatenation": dictionaryConcatenationWarning,
"duplicated-name": duplicatedNameWarning,
"external-path": externalPathWarning,
"filetype": fileTypeWarning,
"function-docstring": functionDocstringWarning,
"function-docstring-header": functionDocstringHeaderWarning,
"function-docstring-args": functionDocstringArgsWarning,
"function-docstring-return": functionDocstringReturnWarning,
"integer-division": integerDivisionWarning,
"keyword-positional-params": keywordPositionalParametersWarning,
"list-append": listAppendWarning,
"load": unusedLoadWarning,
"module-docstring": moduleDocstringWarning,
"name-conventions": nameConventionsWarning,
"native-build": nativeInBuildFilesWarning,
"native-package": nativePackageWarning,
"no-effect": noEffectWarning,
"output-group": outputGroupWarning,
"overly-nested-depset": overlyNestedDepsetWarning,
"package-name": packageNameWarning,
"package-on-top": packageOnTopWarning,
"print": printWarning,
"provider-params": providerParamsWarning,
"redefined-variable": redefinedVariableWarning,
"repository-name": repositoryNameWarning,
"rule-impl-return": ruleImplReturnWarning,
"return-value": missingReturnValueWarning,
"skylark-comment": skylarkCommentWarning,
"skylark-docstring": skylarkDocstringWarning,
"string-iteration": stringIterationWarning,
"uninitialized": uninitializedVariableWarning,
"unreachable": unreachableStatementWarning,
"unsorted-dict-items": unsortedDictItemsWarning,
"unused-variable": unusedVariableWarning,
}

// MultiFileWarningMap lists the warnings that run on the whole file, but may use other files.
Expand Down
Loading