1 use crate::ast; 2 use proc_macro2::Ident; 3 use syn; 4 5 #[derive(Debug, Clone, Copy, PartialEq, Eq)] 6 pub enum ImportedTypeKind { 7 /// The definition of an imported type. 8 Definition, 9 /// A reference to an imported type. 10 Reference, 11 } 12 13 impl<T> ImportedTypes for Option<T> 14 where 15 T: ImportedTypes, 16 { imported_types<F>(&self, f: &mut F) where F: FnMut(&Ident, ImportedTypeKind),17 fn imported_types<F>(&self, f: &mut F) 18 where 19 F: FnMut(&Ident, ImportedTypeKind), 20 { 21 if let Some(inner) = self { 22 inner.imported_types(f); 23 } 24 } 25 } 26 27 /// Iterate over definitions of and references to imported types in the AST. 28 pub trait ImportedTypes { imported_types<F>(&self, f: &mut F) where F: FnMut(&Ident, ImportedTypeKind)29 fn imported_types<F>(&self, f: &mut F) 30 where 31 F: FnMut(&Ident, ImportedTypeKind); 32 } 33 34 /// Iterate over definitions of imported types in the AST. 35 pub trait ImportedTypeDefinitions { imported_type_definitions<F>(&self, f: &mut F) where F: FnMut(&Ident)36 fn imported_type_definitions<F>(&self, f: &mut F) 37 where 38 F: FnMut(&Ident); 39 } 40 41 impl<T> ImportedTypeDefinitions for T 42 where 43 T: ImportedTypes, 44 { imported_type_definitions<F>(&self, f: &mut F) where F: FnMut(&Ident),45 fn imported_type_definitions<F>(&self, f: &mut F) 46 where 47 F: FnMut(&Ident), 48 { 49 self.imported_types(&mut |id, kind| { 50 if let ImportedTypeKind::Definition = kind { 51 f(id); 52 } 53 }); 54 } 55 } 56 57 /// Iterate over references to imported types in the AST. 58 pub trait ImportedTypeReferences { imported_type_references<F>(&self, f: &mut F) where F: FnMut(&Ident)59 fn imported_type_references<F>(&self, f: &mut F) 60 where 61 F: FnMut(&Ident); 62 } 63 64 impl<T> ImportedTypeReferences for T 65 where 66 T: ImportedTypes, 67 { imported_type_references<F>(&self, f: &mut F) where F: FnMut(&Ident),68 fn imported_type_references<F>(&self, f: &mut F) 69 where 70 F: FnMut(&Ident), 71 { 72 self.imported_types(&mut |id, kind| { 73 if let ImportedTypeKind::Reference = kind { 74 f(id); 75 } 76 }); 77 } 78 } 79 80 impl<'a, T: ImportedTypes> ImportedTypes for &'a T { imported_types<F>(&self, f: &mut F) where F: FnMut(&Ident, ImportedTypeKind),81 fn imported_types<F>(&self, f: &mut F) 82 where 83 F: FnMut(&Ident, ImportedTypeKind), 84 { 85 (*self).imported_types(f) 86 } 87 } 88 89 impl ImportedTypes for ast::Program { imported_types<F>(&self, f: &mut F) where F: FnMut(&Ident, ImportedTypeKind),90 fn imported_types<F>(&self, f: &mut F) 91 where 92 F: FnMut(&Ident, ImportedTypeKind), 93 { 94 self.imports.imported_types(f); 95 self.consts.imported_types(f); 96 self.dictionaries.imported_types(f); 97 } 98 } 99 100 impl<T> ImportedTypes for Vec<T> 101 where 102 T: ImportedTypes, 103 { imported_types<F>(&self, f: &mut F) where F: FnMut(&Ident, ImportedTypeKind),104 fn imported_types<F>(&self, f: &mut F) 105 where 106 F: FnMut(&Ident, ImportedTypeKind), 107 { 108 for x in self { 109 x.imported_types(f); 110 } 111 } 112 } 113 114 impl ImportedTypes for ast::Import { imported_types<F>(&self, f: &mut F) where F: FnMut(&Ident, ImportedTypeKind),115 fn imported_types<F>(&self, f: &mut F) 116 where 117 F: FnMut(&Ident, ImportedTypeKind), 118 { 119 self.kind.imported_types(f) 120 } 121 } 122 123 impl ImportedTypes for ast::ImportKind { imported_types<F>(&self, f: &mut F) where F: FnMut(&Ident, ImportedTypeKind),124 fn imported_types<F>(&self, f: &mut F) 125 where 126 F: FnMut(&Ident, ImportedTypeKind), 127 { 128 match self { 129 ast::ImportKind::Static(s) => s.imported_types(f), 130 ast::ImportKind::Function(fun) => fun.imported_types(f), 131 ast::ImportKind::Type(ty) => ty.imported_types(f), 132 ast::ImportKind::Enum(enm) => enm.imported_types(f), 133 } 134 } 135 } 136 137 impl ImportedTypes for ast::ImportStatic { imported_types<F>(&self, f: &mut F) where F: FnMut(&Ident, ImportedTypeKind),138 fn imported_types<F>(&self, f: &mut F) 139 where 140 F: FnMut(&Ident, ImportedTypeKind), 141 { 142 self.ty.imported_types(f); 143 } 144 } 145 146 impl ImportedTypes for syn::Type { imported_types<F>(&self, f: &mut F) where F: FnMut(&Ident, ImportedTypeKind),147 fn imported_types<F>(&self, f: &mut F) 148 where 149 F: FnMut(&Ident, ImportedTypeKind), 150 { 151 match self { 152 syn::Type::Reference(ref r) => r.imported_types(f), 153 syn::Type::Path(ref p) => p.imported_types(f), 154 _ => {} 155 } 156 } 157 } 158 159 impl ImportedTypes for syn::TypeReference { imported_types<F>(&self, f: &mut F) where F: FnMut(&Ident, ImportedTypeKind),160 fn imported_types<F>(&self, f: &mut F) 161 where 162 F: FnMut(&Ident, ImportedTypeKind), 163 { 164 self.elem.imported_types(f); 165 } 166 } 167 168 impl ImportedTypes for syn::TypePath { imported_types<F>(&self, f: &mut F) where F: FnMut(&Ident, ImportedTypeKind),169 fn imported_types<F>(&self, f: &mut F) 170 where 171 F: FnMut(&Ident, ImportedTypeKind), 172 { 173 self.qself.imported_types(f); 174 self.path.imported_types(f); 175 } 176 } 177 178 impl ImportedTypes for syn::QSelf { imported_types<F>(&self, _: &mut F) where F: FnMut(&Ident, ImportedTypeKind),179 fn imported_types<F>(&self, _: &mut F) 180 where 181 F: FnMut(&Ident, ImportedTypeKind), 182 { 183 // TODO 184 } 185 } 186 187 impl ImportedTypes for syn::Path { imported_types<F>(&self, f: &mut F) where F: FnMut(&Ident, ImportedTypeKind),188 fn imported_types<F>(&self, f: &mut F) 189 where 190 F: FnMut(&Ident, ImportedTypeKind), 191 { 192 for seg in self.segments.iter() { 193 seg.arguments.imported_types(f); 194 } 195 f( 196 &self.segments.last().unwrap().ident, 197 ImportedTypeKind::Reference, 198 ); 199 } 200 } 201 202 impl ImportedTypes for syn::PathArguments { imported_types<F>(&self, f: &mut F) where F: FnMut(&Ident, ImportedTypeKind),203 fn imported_types<F>(&self, f: &mut F) 204 where 205 F: FnMut(&Ident, ImportedTypeKind), 206 { 207 match self { 208 syn::PathArguments::AngleBracketed(data) => { 209 for arg in data.args.iter() { 210 arg.imported_types(f); 211 } 212 } 213 //TOCHECK 214 syn::PathArguments::Parenthesized(data) => { 215 for input in data.inputs.iter() { 216 input.imported_types(f); 217 } 218 // TODO do we need to handle output here? 219 // https://docs.rs/syn/0.14.0/syn/struct.ParenthesizedGenericArguments.html 220 } 221 syn::PathArguments::None => {} 222 } 223 } 224 } 225 226 impl ImportedTypes for syn::GenericArgument { imported_types<F>(&self, f: &mut F) where F: FnMut(&Ident, ImportedTypeKind),227 fn imported_types<F>(&self, f: &mut F) 228 where 229 F: FnMut(&Ident, ImportedTypeKind), 230 { 231 match self { 232 syn::GenericArgument::Lifetime(_) => {} 233 syn::GenericArgument::Type(ty) => ty.imported_types(f), 234 syn::GenericArgument::Binding(_) => {} // TODO 235 syn::GenericArgument::Const(_) => {} // TODO 236 syn::GenericArgument::Constraint(_) => {} // TODO 237 } 238 } 239 } 240 241 impl ImportedTypes for ast::ImportFunction { imported_types<F>(&self, f: &mut F) where F: FnMut(&Ident, ImportedTypeKind),242 fn imported_types<F>(&self, f: &mut F) 243 where 244 F: FnMut(&Ident, ImportedTypeKind), 245 { 246 self.function.imported_types(f); 247 self.kind.imported_types(f); 248 } 249 } 250 251 impl ImportedTypes for ast::ImportFunctionKind { imported_types<F>(&self, f: &mut F) where F: FnMut(&Ident, ImportedTypeKind),252 fn imported_types<F>(&self, f: &mut F) 253 where 254 F: FnMut(&Ident, ImportedTypeKind), 255 { 256 match self { 257 ast::ImportFunctionKind::Method { ty, .. } => ty.imported_types(f), 258 ast::ImportFunctionKind::Normal => {} 259 } 260 } 261 } 262 263 impl ImportedTypes for ast::Function { imported_types<F>(&self, f: &mut F) where F: FnMut(&Ident, ImportedTypeKind),264 fn imported_types<F>(&self, f: &mut F) 265 where 266 F: FnMut(&Ident, ImportedTypeKind), 267 { 268 self.arguments.imported_types(f); 269 if let Some(ref r) = self.ret { 270 r.imported_types(f); 271 } 272 } 273 } 274 275 impl ImportedTypes for syn::FnArg { imported_types<F>(&self, f: &mut F) where F: FnMut(&Ident, ImportedTypeKind),276 fn imported_types<F>(&self, f: &mut F) 277 where 278 F: FnMut(&Ident, ImportedTypeKind), 279 { 280 match self { 281 syn::FnArg::Receiver(_) => {} 282 syn::FnArg::Typed(p) => p.imported_types(f), 283 } 284 } 285 } 286 287 impl ImportedTypes for syn::PatType { imported_types<F>(&self, f: &mut F) where F: FnMut(&Ident, ImportedTypeKind),288 fn imported_types<F>(&self, f: &mut F) 289 where 290 F: FnMut(&Ident, ImportedTypeKind), 291 { 292 self.ty.imported_types(f) 293 } 294 } 295 296 impl ImportedTypes for ast::ImportType { imported_types<F>(&self, f: &mut F) where F: FnMut(&Ident, ImportedTypeKind),297 fn imported_types<F>(&self, f: &mut F) 298 where 299 F: FnMut(&Ident, ImportedTypeKind), 300 { 301 f(&self.rust_name, ImportedTypeKind::Definition); 302 for class in self.extends.iter() { 303 class.imported_types(f); 304 } 305 } 306 } 307 308 impl ImportedTypes for ast::ImportEnum { imported_types<F>(&self, f: &mut F) where F: FnMut(&Ident, ImportedTypeKind),309 fn imported_types<F>(&self, f: &mut F) 310 where 311 F: FnMut(&Ident, ImportedTypeKind), 312 { 313 f(&self.name, ImportedTypeKind::Definition); 314 } 315 } 316 317 impl ImportedTypes for ast::Const { imported_types<F>(&self, f: &mut F) where F: FnMut(&Ident, ImportedTypeKind),318 fn imported_types<F>(&self, f: &mut F) 319 where 320 F: FnMut(&Ident, ImportedTypeKind), 321 { 322 self.ty.imported_types(f); 323 } 324 } 325 326 impl ImportedTypes for ast::Dictionary { imported_types<F>(&self, f: &mut F) where F: FnMut(&Ident, ImportedTypeKind),327 fn imported_types<F>(&self, f: &mut F) 328 where 329 F: FnMut(&Ident, ImportedTypeKind), 330 { 331 f(&self.name, ImportedTypeKind::Definition); 332 for field in self.fields.iter() { 333 field.imported_types(f); 334 } 335 } 336 } 337 338 impl ImportedTypes for ast::DictionaryField { imported_types<F>(&self, f: &mut F) where F: FnMut(&Ident, ImportedTypeKind),339 fn imported_types<F>(&self, f: &mut F) 340 where 341 F: FnMut(&Ident, ImportedTypeKind), 342 { 343 self.ty.imported_types(f); 344 } 345 } 346 347 /// Remove any methods, statics, &c, that reference types that are *not* 348 /// defined. 349 pub trait RemoveUndefinedImports { remove_undefined_imports<F>(&mut self, is_defined: &F) -> bool where F: Fn(&Ident) -> bool350 fn remove_undefined_imports<F>(&mut self, is_defined: &F) -> bool 351 where 352 F: Fn(&Ident) -> bool; 353 } 354 355 impl RemoveUndefinedImports for ast::Program { remove_undefined_imports<F>(&mut self, is_defined: &F) -> bool where F: Fn(&Ident) -> bool,356 fn remove_undefined_imports<F>(&mut self, is_defined: &F) -> bool 357 where 358 F: Fn(&Ident) -> bool, 359 { 360 let mut changed = self.imports.remove_undefined_imports(is_defined); 361 changed = self.consts.remove_undefined_imports(is_defined) || changed; 362 363 for dictionary in self.dictionaries.iter_mut() { 364 let num_required = 365 |dict: &ast::Dictionary| dict.fields.iter().filter(|f| f.required).count(); 366 let before = num_required(dictionary); 367 changed = dictionary.fields.remove_undefined_imports(is_defined) || changed; 368 369 // If a required field was removed we can no longer construct this 370 // dictionary so disable the constructor. 371 if before != num_required(dictionary) { 372 dictionary.ctor = false; 373 } 374 } 375 376 changed 377 } 378 } 379 380 impl<T> RemoveUndefinedImports for Vec<T> 381 where 382 T: ImportedTypeReferences, 383 { remove_undefined_imports<F>(&mut self, is_defined: &F) -> bool where F: Fn(&Ident) -> bool,384 fn remove_undefined_imports<F>(&mut self, is_defined: &F) -> bool 385 where 386 F: Fn(&Ident) -> bool, 387 { 388 let before = self.len(); 389 self.retain(|x| { 390 let mut all_defined = true; 391 x.imported_type_references(&mut |id| { 392 if all_defined { 393 if !is_defined(id) { 394 log::info!("removing due to {} not being defined", id); 395 all_defined = false; 396 } 397 } 398 }); 399 all_defined 400 }); 401 before != self.len() 402 } 403 } 404