1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
// This file is part of Substrate.

// Copyright (C) 2020-2021 Parity Technologies (UK) Ltd.
// SPDX-License-Identifier: Apache-2.0

// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// 	http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

use super::helper;
use syn::spanned::Spanned;

/// List of additional token to be used for parsing.
mod keyword {
	syn::custom_keyword!(DispatchResultWithPostInfo);
	syn::custom_keyword!(Call);
	syn::custom_keyword!(OriginFor);
	syn::custom_keyword!(weight);
	syn::custom_keyword!(compact);
	syn::custom_keyword!(T);
	syn::custom_keyword!(pallet);
}

/// Definition of extra constants typically `impl<T: Config> Pallet<T> { ... }`
pub struct ExtraConstantsDef {
	/// The where_clause used.
	pub where_clause: Option<syn::WhereClause>,
	/// A set of usage of instance, must be check for consistency with trait.
	pub instances: Vec<helper::InstanceUsage>,
	/// The index of call item in pallet module.
	pub index: usize,
	/// The extra constant defined.
	pub extra_constants: Vec<ExtraConstantDef>,
}

/// Input definition for an constant in pallet.
pub struct ExtraConstantDef {
	/// Name of the function
	pub ident: syn::Ident,
	/// The type returned by the function
	pub type_: syn::Type,
	/// The doc associated
	pub doc: Vec<syn::Lit>,
}

impl ExtraConstantsDef {
	pub fn try_from(index: usize, item: &mut syn::Item) -> syn::Result<Self> {
		let item = if let syn::Item::Impl(item) = item {
			item
		} else {
			return Err(syn::Error::new(item.span(), "Invalid pallet::call, expected item impl"))
		};

		let mut instances = vec![];
		instances.push(helper::check_impl_gen(&item.generics, item.impl_token.span())?);
		instances.push(helper::check_pallet_struct_usage(&item.self_ty)?);

		if let Some((_, _, for_)) = item.trait_ {
			let msg = "Invalid pallet::call, expected no trait ident as in \
				`impl<..> Pallet<..> { .. }`";
			return Err(syn::Error::new(for_.span(), msg))
		}

		let mut extra_constants = vec![];
		for impl_item in &mut item.items {
			let method = if let syn::ImplItem::Method(method) = impl_item {
				method
			} else {
				let msg = "Invalid pallet::call, only method accepted";
				return Err(syn::Error::new(impl_item.span(), msg))
			};

			if !method.sig.inputs.is_empty() {
				let msg = "Invalid pallet::extra_constants, method must have 0 args";
				return Err(syn::Error::new(method.sig.span(), msg))
			}

			if !method.sig.generics.params.is_empty() {
				let msg = "Invalid pallet::extra_constants, method must have 0 generics";
				return Err(syn::Error::new(method.sig.generics.params[0].span(), msg))
			}

			if method.sig.generics.where_clause.is_some() {
				let msg = "Invalid pallet::extra_constants, method must have no where clause";
				return Err(syn::Error::new(method.sig.generics.where_clause.span(), msg))
			}

			let type_ = match &method.sig.output {
				syn::ReturnType::Default => {
					let msg = "Invalid pallet::extra_constants, method must have a return type";
					return Err(syn::Error::new(method.span(), msg))
				},
				syn::ReturnType::Type(_, type_) => *type_.clone(),
			};

			extra_constants.push(ExtraConstantDef {
				ident: method.sig.ident.clone(),
				type_,
				doc: helper::get_doc_literals(&method.attrs),
			});
		}

		Ok(Self {
			index,
			instances,
			where_clause: item.generics.where_clause.clone(),
			extra_constants,
		})
	}
}