referrerpolicy=no-referrer-when-downgrade

frame_support_procedural/pallet/expand/
warnings.rs

1// This file is part of Substrate.
2
3// Copyright (C) Parity Technologies (UK) Ltd.
4// SPDX-License-Identifier: Apache-2.0
5
6// Licensed under the Apache License, Version 2.0 (the "License");
7// you may not use this file except in compliance with the License.
8// You may obtain a copy of the License at
9//
10// 	http://www.apache.org/licenses/LICENSE-2.0
11//
12// Unless required by applicable law or agreed to in writing, software
13// distributed under the License is distributed on an "AS IS" BASIS,
14// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15// See the License for the specific language governing permissions and
16// limitations under the License.
17
18//! Generates warnings for undesirable pallet code.
19
20use crate::pallet::parse::call::{CallVariantDef, CallWeightDef};
21use proc_macro_warning::Warning;
22use syn::{
23	spanned::Spanned,
24	visit::{self, Visit},
25};
26
27/// Warn if any of the call arguments starts with a underscore and is used in a weight formula.
28pub(crate) fn weight_witness_warning(
29	method: &CallVariantDef,
30	dev_mode: bool,
31	warnings: &mut Vec<Warning>,
32) {
33	if dev_mode {
34		return
35	}
36	let CallWeightDef::Immediate(w) = &method.weight else { return };
37
38	let partial_warning = Warning::new_deprecated("UncheckedWeightWitness")
39		.old("not check weight witness data")
40		.new("ensure that all witness data for weight calculation is checked before usage")
41		.help_link("https://github.com/paritytech/polkadot-sdk/pull/1818");
42
43	for (_, arg_ident, _) in method.args.iter() {
44		if !arg_ident.to_string().starts_with('_') || !contains_ident(w.clone(), &arg_ident) {
45			continue
46		}
47
48		let warning = partial_warning
49			.clone()
50			.index(warnings.len())
51			.span(arg_ident.span())
52			.build_or_panic();
53
54		warnings.push(warning);
55	}
56}
57
58/// Warn if the weight is a constant and the pallet not in `dev_mode`.
59pub(crate) fn weight_constant_warning(
60	weight: &syn::Expr,
61	dev_mode: bool,
62	warnings: &mut Vec<Warning>,
63) {
64	if dev_mode {
65		return
66	}
67	let syn::Expr::Lit(lit) = weight else { return };
68
69	let warning = Warning::new_deprecated("ConstantWeight")
70		.index(warnings.len())
71		.old("use hard-coded constant as call weight")
72		.new("benchmark all calls or put the pallet into `dev` mode")
73		.help_link("https://github.com/paritytech/substrate/pull/13798")
74		.span(lit.span())
75		.build_or_panic();
76
77	warnings.push(warning);
78}
79
80/// Returns whether `expr` contains `ident`.
81fn contains_ident(mut expr: syn::Expr, ident: &syn::Ident) -> bool {
82	struct ContainsIdent {
83		ident: syn::Ident,
84		found: bool,
85	}
86
87	impl<'a> Visit<'a> for ContainsIdent {
88		fn visit_ident(&mut self, i: &syn::Ident) {
89			if *i == self.ident {
90				self.found = true;
91			}
92		}
93	}
94
95	let mut visitor = ContainsIdent { ident: ident.clone(), found: false };
96	visit::visit_expr(&mut visitor, &mut expr);
97	visitor.found
98}