1// Copyright 2020 The Android Open Source Project 2// 3// Licensed under the Apache License, Version 2.0 (the "License"); 4// you may not use this file except in compliance with the License. 5// You may obtain a copy of the License at 6// 7// http://www.apache.org/licenses/LICENSE-2.0 8// 9// Unless required by applicable law or agreed to in writing, software 10// distributed under the License is distributed on an "AS IS" BASIS, 11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12// See the License for the specific language governing permissions and 13// limitations under the License. 14 15package config 16 17import ( 18 "strings" 19 20 "android/soong/android" 21) 22 23// Overarching principles for Rust lints on Android: 24// The Android build system tries to avoid reporting warnings during the build. 25// Therefore, by default, we upgrade warnings to denials. For some of these 26// lints, an allow exception is setup, using the variables below. 27// There are different default lints depending on the repository location (see 28// DefaultLocalClippyChecks). 29// The lints are split into two categories. The first one contains the built-in 30// lints (https://doc.rust-lang.org/rustc/lints/index.html). The second is 31// specific to Clippy lints (https://rust-lang.github.io/rust-clippy/master/). 32// 33// When developing a module, it is possible to use the `no_lint` property to 34// disable the built-in lints configuration. It is also possible to set 35// `clippy` to false to disable the clippy verification. Expect some 36// questioning during review if you enable one of these options. For external/ 37// code, if you need to use them, it is likely a bug. Otherwise, it may be 38// useful to add an exception (that is, move a lint from deny to allow). 39var ( 40 // Default Rust lints that applies to Google-authored modules. 41 defaultRustcLints = []string{ 42 "-A deprecated", 43 "-D missing-docs", 44 "-D warnings", 45 } 46 // Default Clippy lints. These are applied on top of defaultRustcLints. 47 // It should be assumed that any warning lint will be promoted to a 48 // deny. 49 defaultClippyLints = []string{ 50 "-A clippy::type-complexity", 51 } 52 53 // Rust lints for vendor code. 54 defaultRustcVendorLints = []string{ 55 "-A deprecated", 56 "-D warnings", 57 } 58 // Clippy lints for vendor source. These are applied on top of 59 // defaultRustcVendorLints. It should be assumed that any warning lint 60 // will be promoted to a deny. 61 defaultClippyVendorLints = []string{ 62 "-A clippy::complexity", 63 "-A clippy::perf", 64 "-A clippy::style", 65 } 66 67 // For prebuilts/ and external/, no linting is expected. If a warning 68 // or a deny is reported, it should be fixed upstream. 69 allowAllLints = []string{ 70 "--cap-lints allow", 71 } 72) 73 74func init() { 75 // Default Rust lints. These apply to all Google-authored modules. 76 pctx.VariableFunc("RustDefaultLints", func(ctx android.PackageVarContext) string { 77 if override := ctx.Config().Getenv("RUST_DEFAULT_LINTS"); override != "" { 78 return override 79 } 80 return strings.Join(defaultRustcLints, " ") 81 }) 82 pctx.VariableFunc("ClippyDefaultLints", func(ctx android.PackageVarContext) string { 83 if override := ctx.Config().Getenv("CLIPPY_DEFAULT_LINTS"); override != "" { 84 return override 85 } 86 return strings.Join(defaultClippyLints, " ") 87 }) 88 89 // Rust lints that only applies to external code. 90 pctx.VariableFunc("RustVendorLints", func(ctx android.PackageVarContext) string { 91 if override := ctx.Config().Getenv("RUST_VENDOR_LINTS"); override != "" { 92 return override 93 } 94 return strings.Join(defaultRustcVendorLints, " ") 95 }) 96 pctx.VariableFunc("ClippyVendorLints", func(ctx android.PackageVarContext) string { 97 if override := ctx.Config().Getenv("CLIPPY_VENDOR_LINTS"); override != "" { 98 return override 99 } 100 return strings.Join(defaultClippyVendorLints, " ") 101 }) 102 pctx.StaticVariable("RustAllowAllLints", strings.Join(allowAllLints, " ")) 103} 104 105type PathBasedClippyConfig struct { 106 PathPrefix string 107 RustcConfig string 108 ClippyEnabled bool 109 ClippyConfig string 110} 111 112const noLint = "" 113const rustcDefault = "${config.RustDefaultLints}" 114const rustcVendor = "${config.RustVendorLints}" 115const rustcAllowAll = "${config.RustAllowAllLints}" 116const clippyDefault = "${config.ClippyDefaultLints}" 117const clippyVendor = "${config.ClippyVendorLints}" 118 119// This is a map of local path prefixes to a set of parameters for the linting: 120// - a string for the lints to apply to rustc. 121// - a boolean to indicate if clippy should be executed. 122// - a string for the lints to apply to clippy. 123// The first entry matching will be used. 124var DefaultLocalClippyChecks = []PathBasedClippyConfig{ 125 {"external/", rustcAllowAll, false, noLint}, 126 {"hardware/", rustcVendor, true, clippyVendor}, 127 {"prebuilts/", rustcAllowAll, false, noLint}, 128 {"vendor/google", rustcDefault, true, clippyDefault}, 129 {"vendor/", rustcVendor, true, clippyVendor}, 130} 131 132// ClippyLintsForDir returns a boolean if Clippy should be executed and if so, the lints to be used. 133func ClippyLintsForDir(dir string) (bool, string) { 134 for _, pathCheck := range DefaultLocalClippyChecks { 135 if strings.HasPrefix(dir, pathCheck.PathPrefix) { 136 return pathCheck.ClippyEnabled, pathCheck.ClippyConfig 137 } 138 } 139 return true, clippyDefault 140} 141 142// RustcLintsForDir returns the standard lints to be used for a repository. 143func RustcLintsForDir(dir string) string { 144 for _, pathCheck := range DefaultLocalClippyChecks { 145 if strings.HasPrefix(dir, pathCheck.PathPrefix) { 146 return pathCheck.RustcConfig 147 } 148 } 149 return rustcDefault 150} 151