diesel_derives/deprecated/
mod.rs
1use syn::parse::{ParseStream, Result};
2
3#[cfg(all(not(feature = "without-deprecated"), feature = "with-deprecated"))]
4mod belongs_to;
5#[cfg(all(not(feature = "without-deprecated"), feature = "with-deprecated"))]
6mod changeset_options;
7#[cfg(all(not(feature = "without-deprecated"), feature = "with-deprecated"))]
8mod postgres_type;
9#[cfg(all(not(feature = "without-deprecated"), feature = "with-deprecated"))]
10mod primary_key;
11#[cfg(all(not(feature = "without-deprecated"), feature = "with-deprecated"))]
12mod utils;
13
14pub trait ParseDeprecated: Sized {
15 fn parse_deprecated(input: ParseStream) -> Result<Option<Self>>;
16}
17
18#[cfg(any(feature = "without-deprecated", not(feature = "with-deprecated")))]
19mod not_deprecated {
20 use super::{ParseDeprecated, ParseStream, Result};
21 use crate::attrs::{FieldAttr, StructAttr};
22
23 impl ParseDeprecated for StructAttr {
24 fn parse_deprecated(_input: ParseStream) -> Result<Option<Self>> {
25 unimplemented!()
26 }
27 }
28
29 impl ParseDeprecated for FieldAttr {
30 fn parse_deprecated(_input: ParseStream) -> Result<Option<Self>> {
31 unimplemented!()
32 }
33 }
34}
35
36#[cfg(all(not(feature = "without-deprecated"), feature = "with-deprecated"))]
37mod impl_deprecated {
38 use super::{ParseDeprecated, ParseStream, Result};
39 use crate::attrs::{FieldAttr, StructAttr};
40 use crate::deprecated::belongs_to::parse_belongs_to;
41 use crate::deprecated::changeset_options::parse_changeset_options;
42 use crate::deprecated::postgres_type::parse_postgres_type;
43 use crate::deprecated::primary_key::parse_primary_key;
44 use crate::deprecated::utils::parse_eq_and_lit_str;
45 use crate::parsers::{MysqlType, PostgresType, SqliteType};
46 use crate::util::{
47 COLUMN_NAME_NOTE, MYSQL_TYPE_NOTE, SQLITE_TYPE_NOTE, SQL_TYPE_NOTE, TABLE_NAME_NOTE,
48 };
49 use proc_macro2::Span;
50 use syn::Ident;
51
52 macro_rules! warn {
53 ($ident: expr, $help: expr) => {
54 warn(
55 $ident.span(),
56 &format!("#[{}] attribute form is deprecated", $ident),
57 $help,
58 );
59 };
60 }
61
62 impl ParseDeprecated for StructAttr {
63 fn parse_deprecated(input: ParseStream) -> Result<Option<Self>> {
64 let name: Ident = input.parse()?;
65 let name_str = name.to_string();
66
67 match &*name_str {
68 "table_name" => {
69 let lit_str = parse_eq_and_lit_str(name.clone(), input, TABLE_NAME_NOTE)?;
70 warn!(
71 name,
72 &format!("use `#[diesel(table_name = {})]` instead", lit_str.value())
73 );
74 Ok(Some(StructAttr::TableName(name, lit_str.parse()?)))
75 }
76 "changeset_options" => {
77 let (ident, value) = parse_changeset_options(name.clone(), input)?;
78 warn!(
79 name,
80 &format!(
81 "use `#[diesel(treat_none_as_null = {})]` instead",
82 value.value
83 )
84 );
85 Ok(Some(StructAttr::TreatNoneAsNull(ident, value)))
86 }
87 "sql_type" => {
88 let lit_str = parse_eq_and_lit_str(name.clone(), input, SQL_TYPE_NOTE)?;
89 warn!(
90 name,
91 &format!("use `#[diesel(sql_type = {})]` instead", lit_str.value())
92 );
93 Ok(Some(StructAttr::SqlType(name, lit_str.parse()?)))
94 }
95 "primary_key" => {
96 let keys = parse_primary_key(name.clone(), input)?;
97 let hint = keys
98 .iter()
99 .map(|i| i.to_string())
100 .collect::<Vec<_>>()
101 .join(", ");
102 warn!(
103 name,
104 &format!("use `#[diesel(primary_key({hint}))]` instead")
105 );
106 Ok(Some(StructAttr::PrimaryKey(name, keys)))
107 }
108 "belongs_to" => {
109 let belongs_to = parse_belongs_to(name.clone(), input)?;
110 let parent = belongs_to
111 .parent
112 .path
113 .segments
114 .iter()
115 .map(|s| s.ident.to_string())
116 .collect::<Vec<_>>()
117 .join("::");
118 if let Some(ref key) = belongs_to.foreign_key {
119 warn!(
120 name,
121 &format!(
122 "use `#[diesel(belongs_to({parent}, foreign_key = {key}))]` instead"
123 )
124 );
125 } else {
126 warn!(
127 name,
128 &format!("use `#[diesel(belongs_to({parent}))]` instead")
129 );
130 }
131 Ok(Some(StructAttr::BelongsTo(name, belongs_to)))
132 }
133 "sqlite_type" => {
134 let name_value = parse_eq_and_lit_str(name.clone(), input, SQLITE_TYPE_NOTE)?;
135 warn!(
136 name,
137 &format!(
138 "use `#[diesel(sqlite_type(name = \"{}\"))]` instead",
139 name_value.value()
140 )
141 );
142 Ok(Some(StructAttr::SqliteType(
143 name,
144 SqliteType { name: name_value },
145 )))
146 }
147 "mysql_type" => {
148 let name_value = parse_eq_and_lit_str(name.clone(), input, MYSQL_TYPE_NOTE)?;
149 warn!(
150 name,
151 &format!(
152 "use `#[diesel(mysql_type(name = \"{}\"))]` instead",
153 name_value.value()
154 )
155 );
156 Ok(Some(StructAttr::MysqlType(
157 name,
158 MysqlType { name: name_value },
159 )))
160 }
161 "postgres" => {
162 let pg_type = parse_postgres_type(name.clone(), input)?;
163 let msg = match &pg_type {
164 PostgresType::Fixed(oid, array_oid) => format!(
165 "use `#[diesel(postgres_type(oid = {}, array_oid = {}))]` instead",
166 oid.base10_parse::<u32>()?,
167 array_oid.base10_parse::<u32>()?
168 ),
169 PostgresType::Lookup(name, Some(schema)) => format!(
170 "use `#[diesel(postgres_type(name = \"{}\", schema = \"{}\"))]` instead",
171 name.value(),
172 schema.value()
173 ),
174 PostgresType::Lookup(name, None) => format!(
175 "use `#[diesel(postgres_type(name = \"{}\"))]` instead",
176 name.value(),
177 ),
178 };
179
180 warn!(name, &msg);
181 Ok(Some(StructAttr::PostgresType(name, pg_type)))
182 }
183 _ => Ok(None),
184 }
185 }
186 }
187
188 #[cfg(all(not(feature = "without-deprecated"), feature = "with-deprecated"))]
189 impl ParseDeprecated for FieldAttr {
190 fn parse_deprecated(input: ParseStream) -> Result<Option<Self>> {
191 let name: Ident = input.parse()?;
192 let name_str = name.to_string();
193
194 match &*name_str {
195 "column_name" => {
196 let lit_str = parse_eq_and_lit_str(name.clone(), input, COLUMN_NAME_NOTE)?;
197 warn!(
198 name,
199 &format!("use `#[diesel(column_name = {})]` instead", lit_str.value())
200 );
201 Ok(Some(FieldAttr::ColumnName(name, lit_str.parse()?)))
202 }
203 "sql_type" => {
204 let lit_str = parse_eq_and_lit_str(name.clone(), input, SQL_TYPE_NOTE)?;
205 warn!(
206 name,
207 &format!("use `#[diesel(sql_type = {})]` instead", lit_str.value())
208 );
209 Ok(Some(FieldAttr::SqlType(name, lit_str.parse()?)))
210 }
211
212 _ => Ok(None),
213 }
214 }
215 }
216
217 #[cfg(feature = "nightly")]
218 fn warn(span: Span, message: &str, help: &str) {
219 proc_macro::Diagnostic::spanned(span.unwrap(), proc_macro::Level::Warning, message)
220 .help(help)
221 .emit()
222 }
223
224 #[cfg(not(feature = "nightly"))]
225 fn warn(_span: Span, message: &str, help: &str) {
226 eprintln!("warning: {message}\n = help: {help}\n");
227 }
228}