xref: /aosp_15_r20/build/soong/rust/config/lints.go (revision 333d2b3687b3a337dbcca9d65000bca186795e39)
1*333d2b36SAndroid Build Coastguard Worker// Copyright 2020 The Android Open Source Project
2*333d2b36SAndroid Build Coastguard Worker//
3*333d2b36SAndroid Build Coastguard Worker// Licensed under the Apache License, Version 2.0 (the "License");
4*333d2b36SAndroid Build Coastguard Worker// you may not use this file except in compliance with the License.
5*333d2b36SAndroid Build Coastguard Worker// You may obtain a copy of the License at
6*333d2b36SAndroid Build Coastguard Worker//
7*333d2b36SAndroid Build Coastguard Worker//     http://www.apache.org/licenses/LICENSE-2.0
8*333d2b36SAndroid Build Coastguard Worker//
9*333d2b36SAndroid Build Coastguard Worker// Unless required by applicable law or agreed to in writing, software
10*333d2b36SAndroid Build Coastguard Worker// distributed under the License is distributed on an "AS IS" BASIS,
11*333d2b36SAndroid Build Coastguard Worker// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12*333d2b36SAndroid Build Coastguard Worker// See the License for the specific language governing permissions and
13*333d2b36SAndroid Build Coastguard Worker// limitations under the License.
14*333d2b36SAndroid Build Coastguard Worker
15*333d2b36SAndroid Build Coastguard Workerpackage config
16*333d2b36SAndroid Build Coastguard Worker
17*333d2b36SAndroid Build Coastguard Workerimport (
18*333d2b36SAndroid Build Coastguard Worker	"fmt"
19*333d2b36SAndroid Build Coastguard Worker	"strings"
20*333d2b36SAndroid Build Coastguard Worker
21*333d2b36SAndroid Build Coastguard Worker	"android/soong/android"
22*333d2b36SAndroid Build Coastguard Worker)
23*333d2b36SAndroid Build Coastguard Worker
24*333d2b36SAndroid Build Coastguard Worker// Overarching principles for Rust lints on Android:
25*333d2b36SAndroid Build Coastguard Worker// The Android build system tries to avoid reporting warnings during the build.
26*333d2b36SAndroid Build Coastguard Worker// Therefore, by default, we upgrade warnings to denials. For some of these
27*333d2b36SAndroid Build Coastguard Worker// lints, an allow exception is setup, using the variables below.
28*333d2b36SAndroid Build Coastguard Worker//
29*333d2b36SAndroid Build Coastguard Worker// The lints are split into two categories. The first one contains the built-in
30*333d2b36SAndroid Build Coastguard Worker// lints (https://doc.rust-lang.org/rustc/lints/index.html). The second is
31*333d2b36SAndroid Build Coastguard Worker// specific to Clippy lints (https://rust-lang.github.io/rust-clippy/master/).
32*333d2b36SAndroid Build Coastguard Worker//
33*333d2b36SAndroid Build Coastguard Worker// For both categories, there are 3 levels of linting possible:
34*333d2b36SAndroid Build Coastguard Worker// - "android", for the strictest lints that applies to all Android platform code.
35*333d2b36SAndroid Build Coastguard Worker// - "vendor", for relaxed rules.
36*333d2b36SAndroid Build Coastguard Worker// - "none", to disable the linting.
37*333d2b36SAndroid Build Coastguard Worker// There is a fourth option ("default") which automatically selects the linting level
38*333d2b36SAndroid Build Coastguard Worker// based on the module's location. See defaultLintSetForPath.
39*333d2b36SAndroid Build Coastguard Worker//
40*333d2b36SAndroid Build Coastguard Worker// When developing a module, you may set `lints = "none"` and `clippy_lints =
41*333d2b36SAndroid Build Coastguard Worker// "none"` to disable all the linting. Expect some questioning during code review
42*333d2b36SAndroid Build Coastguard Worker// if you enable one of these options.
43*333d2b36SAndroid Build Coastguard Workervar (
44*333d2b36SAndroid Build Coastguard Worker	// Default Rust lints that applies to Google-authored modules.
45*333d2b36SAndroid Build Coastguard Worker	defaultRustcLints = []string{
46*333d2b36SAndroid Build Coastguard Worker		"-A deprecated",
47*333d2b36SAndroid Build Coastguard Worker		"-A unknown_lints",
48*333d2b36SAndroid Build Coastguard Worker		"-D missing-docs",
49*333d2b36SAndroid Build Coastguard Worker		"-D warnings",
50*333d2b36SAndroid Build Coastguard Worker		"-D unsafe_op_in_unsafe_fn",
51*333d2b36SAndroid Build Coastguard Worker	}
52*333d2b36SAndroid Build Coastguard Worker	// Default Clippy lints. These are applied on top of defaultRustcLints.
53*333d2b36SAndroid Build Coastguard Worker	// It should be assumed that any warning lint will be promoted to a
54*333d2b36SAndroid Build Coastguard Worker	// deny.
55*333d2b36SAndroid Build Coastguard Worker	defaultClippyLints = []string{
56*333d2b36SAndroid Build Coastguard Worker		// Let people hack in peace. ;)
57*333d2b36SAndroid Build Coastguard Worker		"-A clippy::disallowed_names",
58*333d2b36SAndroid Build Coastguard Worker		"-A clippy::type-complexity",
59*333d2b36SAndroid Build Coastguard Worker		"-A clippy::unnecessary_fallible_conversions",
60*333d2b36SAndroid Build Coastguard Worker		"-A clippy::unnecessary-wraps",
61*333d2b36SAndroid Build Coastguard Worker		"-A clippy::unusual-byte-groupings",
62*333d2b36SAndroid Build Coastguard Worker		"-A clippy::upper-case-acronyms",
63*333d2b36SAndroid Build Coastguard Worker		"-D clippy::undocumented_unsafe_blocks",
64*333d2b36SAndroid Build Coastguard Worker	}
65*333d2b36SAndroid Build Coastguard Worker
66*333d2b36SAndroid Build Coastguard Worker	// Rust lints for vendor code.
67*333d2b36SAndroid Build Coastguard Worker	defaultRustcVendorLints = []string{
68*333d2b36SAndroid Build Coastguard Worker		"-A deprecated",
69*333d2b36SAndroid Build Coastguard Worker		"-D warnings",
70*333d2b36SAndroid Build Coastguard Worker	}
71*333d2b36SAndroid Build Coastguard Worker	// Clippy lints for vendor source. These are applied on top of
72*333d2b36SAndroid Build Coastguard Worker	// defaultRustcVendorLints.  It should be assumed that any warning lint
73*333d2b36SAndroid Build Coastguard Worker	// will be promoted to a deny.
74*333d2b36SAndroid Build Coastguard Worker	defaultClippyVendorLints = []string{
75*333d2b36SAndroid Build Coastguard Worker		"-A clippy::complexity",
76*333d2b36SAndroid Build Coastguard Worker		"-A clippy::perf",
77*333d2b36SAndroid Build Coastguard Worker		"-A clippy::style",
78*333d2b36SAndroid Build Coastguard Worker	}
79*333d2b36SAndroid Build Coastguard Worker
80*333d2b36SAndroid Build Coastguard Worker	// For prebuilts/ and external/, no linting is expected. If a warning
81*333d2b36SAndroid Build Coastguard Worker	// or a deny is reported, it should be fixed upstream.
82*333d2b36SAndroid Build Coastguard Worker	allowAllLints = []string{
83*333d2b36SAndroid Build Coastguard Worker		"--cap-lints allow",
84*333d2b36SAndroid Build Coastguard Worker	}
85*333d2b36SAndroid Build Coastguard Worker)
86*333d2b36SAndroid Build Coastguard Worker
87*333d2b36SAndroid Build Coastguard Workerfunc init() {
88*333d2b36SAndroid Build Coastguard Worker	// Default Rust lints. These apply to all Google-authored modules.
89*333d2b36SAndroid Build Coastguard Worker	pctx.VariableFunc("RustDefaultLints", func(ctx android.PackageVarContext) string {
90*333d2b36SAndroid Build Coastguard Worker		if override := ctx.Config().Getenv("RUST_DEFAULT_LINTS"); override != "" {
91*333d2b36SAndroid Build Coastguard Worker			return override
92*333d2b36SAndroid Build Coastguard Worker		}
93*333d2b36SAndroid Build Coastguard Worker		return strings.Join(defaultRustcLints, " ")
94*333d2b36SAndroid Build Coastguard Worker	})
95*333d2b36SAndroid Build Coastguard Worker	pctx.VariableFunc("ClippyDefaultLints", func(ctx android.PackageVarContext) string {
96*333d2b36SAndroid Build Coastguard Worker		if override := ctx.Config().Getenv("CLIPPY_DEFAULT_LINTS"); override != "" {
97*333d2b36SAndroid Build Coastguard Worker			return override
98*333d2b36SAndroid Build Coastguard Worker		}
99*333d2b36SAndroid Build Coastguard Worker		return strings.Join(defaultClippyLints, " ")
100*333d2b36SAndroid Build Coastguard Worker	})
101*333d2b36SAndroid Build Coastguard Worker
102*333d2b36SAndroid Build Coastguard Worker	// Rust lints that only applies to external code.
103*333d2b36SAndroid Build Coastguard Worker	pctx.VariableFunc("RustVendorLints", func(ctx android.PackageVarContext) string {
104*333d2b36SAndroid Build Coastguard Worker		if override := ctx.Config().Getenv("RUST_VENDOR_LINTS"); override != "" {
105*333d2b36SAndroid Build Coastguard Worker			return override
106*333d2b36SAndroid Build Coastguard Worker		}
107*333d2b36SAndroid Build Coastguard Worker		return strings.Join(defaultRustcVendorLints, " ")
108*333d2b36SAndroid Build Coastguard Worker	})
109*333d2b36SAndroid Build Coastguard Worker	pctx.VariableFunc("ClippyVendorLints", func(ctx android.PackageVarContext) string {
110*333d2b36SAndroid Build Coastguard Worker		if override := ctx.Config().Getenv("CLIPPY_VENDOR_LINTS"); override != "" {
111*333d2b36SAndroid Build Coastguard Worker			return override
112*333d2b36SAndroid Build Coastguard Worker		}
113*333d2b36SAndroid Build Coastguard Worker		return strings.Join(defaultClippyVendorLints, " ")
114*333d2b36SAndroid Build Coastguard Worker	})
115*333d2b36SAndroid Build Coastguard Worker	pctx.StaticVariable("RustAllowAllLints", strings.Join(allowAllLints, " "))
116*333d2b36SAndroid Build Coastguard Worker}
117*333d2b36SAndroid Build Coastguard Worker
118*333d2b36SAndroid Build Coastguard Workerconst noLint = ""
119*333d2b36SAndroid Build Coastguard Workerconst rustcDefault = "${config.RustDefaultLints}"
120*333d2b36SAndroid Build Coastguard Workerconst rustcVendor = "${config.RustVendorLints}"
121*333d2b36SAndroid Build Coastguard Workerconst rustcAllowAll = "${config.RustAllowAllLints}"
122*333d2b36SAndroid Build Coastguard Workerconst clippyDefault = "${config.ClippyDefaultLints}"
123*333d2b36SAndroid Build Coastguard Workerconst clippyVendor = "${config.ClippyVendorLints}"
124*333d2b36SAndroid Build Coastguard Worker
125*333d2b36SAndroid Build Coastguard Worker// lintConfig defines a set of lints and clippy configuration.
126*333d2b36SAndroid Build Coastguard Workertype lintConfig struct {
127*333d2b36SAndroid Build Coastguard Worker	rustcConfig   string // for the lints to apply to rustc.
128*333d2b36SAndroid Build Coastguard Worker	clippyEnabled bool   // to indicate if clippy should be executed.
129*333d2b36SAndroid Build Coastguard Worker	clippyConfig  string // for the lints to apply to clippy.
130*333d2b36SAndroid Build Coastguard Worker}
131*333d2b36SAndroid Build Coastguard Worker
132*333d2b36SAndroid Build Coastguard Workerconst (
133*333d2b36SAndroid Build Coastguard Worker	androidLints = "android"
134*333d2b36SAndroid Build Coastguard Worker	vendorLints  = "vendor"
135*333d2b36SAndroid Build Coastguard Worker	noneLints    = "none"
136*333d2b36SAndroid Build Coastguard Worker)
137*333d2b36SAndroid Build Coastguard Worker
138*333d2b36SAndroid Build Coastguard Worker// lintSets defines the categories of linting for Android and their mapping to lintConfigs.
139*333d2b36SAndroid Build Coastguard Workervar lintSets = map[string]lintConfig{
140*333d2b36SAndroid Build Coastguard Worker	androidLints: {rustcDefault, true, clippyDefault},
141*333d2b36SAndroid Build Coastguard Worker	vendorLints:  {rustcVendor, true, clippyVendor},
142*333d2b36SAndroid Build Coastguard Worker	noneLints:    {rustcAllowAll, false, noLint},
143*333d2b36SAndroid Build Coastguard Worker}
144*333d2b36SAndroid Build Coastguard Worker
145*333d2b36SAndroid Build Coastguard Workertype pathLintSet struct {
146*333d2b36SAndroid Build Coastguard Worker	prefix string
147*333d2b36SAndroid Build Coastguard Worker	set    string
148*333d2b36SAndroid Build Coastguard Worker}
149*333d2b36SAndroid Build Coastguard Worker
150*333d2b36SAndroid Build Coastguard Worker// This is a map of local path prefixes to a lint set.  The first entry
151*333d2b36SAndroid Build Coastguard Worker// matching will be used. If no entry matches, androidLints ("android") will be
152*333d2b36SAndroid Build Coastguard Worker// used.
153*333d2b36SAndroid Build Coastguard Workervar defaultLintSetForPath = []pathLintSet{
154*333d2b36SAndroid Build Coastguard Worker	{"external", noneLints},
155*333d2b36SAndroid Build Coastguard Worker	{"hardware", vendorLints},
156*333d2b36SAndroid Build Coastguard Worker	{"prebuilts", noneLints},
157*333d2b36SAndroid Build Coastguard Worker	{"vendor/google", androidLints},
158*333d2b36SAndroid Build Coastguard Worker	{"vendor", vendorLints},
159*333d2b36SAndroid Build Coastguard Worker}
160*333d2b36SAndroid Build Coastguard Worker
161*333d2b36SAndroid Build Coastguard Worker// ClippyLintsForDir returns a boolean if Clippy should be executed and if so, the lints to be used.
162*333d2b36SAndroid Build Coastguard Workerfunc ClippyLintsForDir(dir string, clippyLintsProperty *string) (bool, string, error) {
163*333d2b36SAndroid Build Coastguard Worker	if clippyLintsProperty != nil {
164*333d2b36SAndroid Build Coastguard Worker		set, ok := lintSets[*clippyLintsProperty]
165*333d2b36SAndroid Build Coastguard Worker		if ok {
166*333d2b36SAndroid Build Coastguard Worker			return set.clippyEnabled, set.clippyConfig, nil
167*333d2b36SAndroid Build Coastguard Worker		}
168*333d2b36SAndroid Build Coastguard Worker		if *clippyLintsProperty != "default" {
169*333d2b36SAndroid Build Coastguard Worker			return false, "", fmt.Errorf("unknown value for `clippy_lints`: %v, valid options are: default, android, vendor or none", *clippyLintsProperty)
170*333d2b36SAndroid Build Coastguard Worker		}
171*333d2b36SAndroid Build Coastguard Worker	}
172*333d2b36SAndroid Build Coastguard Worker	for _, p := range defaultLintSetForPath {
173*333d2b36SAndroid Build Coastguard Worker		if strings.HasPrefix(dir, p.prefix) {
174*333d2b36SAndroid Build Coastguard Worker			setConfig := lintSets[p.set]
175*333d2b36SAndroid Build Coastguard Worker			return setConfig.clippyEnabled, setConfig.clippyConfig, nil
176*333d2b36SAndroid Build Coastguard Worker		}
177*333d2b36SAndroid Build Coastguard Worker	}
178*333d2b36SAndroid Build Coastguard Worker	return true, clippyDefault, nil
179*333d2b36SAndroid Build Coastguard Worker}
180*333d2b36SAndroid Build Coastguard Worker
181*333d2b36SAndroid Build Coastguard Worker// RustcLintsForDir returns the standard lints to be used for a repository.
182*333d2b36SAndroid Build Coastguard Workerfunc RustcLintsForDir(dir string, lintProperty *string) (string, error) {
183*333d2b36SAndroid Build Coastguard Worker	if lintProperty != nil {
184*333d2b36SAndroid Build Coastguard Worker		set, ok := lintSets[*lintProperty]
185*333d2b36SAndroid Build Coastguard Worker		if ok {
186*333d2b36SAndroid Build Coastguard Worker			return set.rustcConfig, nil
187*333d2b36SAndroid Build Coastguard Worker		}
188*333d2b36SAndroid Build Coastguard Worker		if *lintProperty != "default" {
189*333d2b36SAndroid Build Coastguard Worker			return "", fmt.Errorf("unknown value for `lints`: %v, valid options are: default, android, vendor or none", *lintProperty)
190*333d2b36SAndroid Build Coastguard Worker		}
191*333d2b36SAndroid Build Coastguard Worker
192*333d2b36SAndroid Build Coastguard Worker	}
193*333d2b36SAndroid Build Coastguard Worker	for _, p := range defaultLintSetForPath {
194*333d2b36SAndroid Build Coastguard Worker		if strings.HasPrefix(dir, p.prefix) {
195*333d2b36SAndroid Build Coastguard Worker			return lintSets[p.set].rustcConfig, nil
196*333d2b36SAndroid Build Coastguard Worker		}
197*333d2b36SAndroid Build Coastguard Worker	}
198*333d2b36SAndroid Build Coastguard Worker	return rustcDefault, nil
199*333d2b36SAndroid Build Coastguard Worker}
200