2018-07-09 16:35:25 -07:00
|
|
|
use ast;
|
|
|
|
use proc_macro2::Ident;
|
|
|
|
use syn;
|
|
|
|
|
|
|
|
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
|
|
|
pub enum ImportedTypeKind {
|
|
|
|
/// The definition of an imported type.
|
|
|
|
Definition,
|
|
|
|
/// A reference to an imported type.
|
|
|
|
Reference,
|
|
|
|
}
|
|
|
|
|
2018-07-24 15:00:46 +01:00
|
|
|
impl<T> ImportedTypes for Option<T>
|
|
|
|
where
|
|
|
|
T: ImportedTypes,
|
|
|
|
{
|
|
|
|
fn imported_types<F>(&self, f: &mut F)
|
|
|
|
where
|
|
|
|
F: FnMut(&Ident, ImportedTypeKind),
|
|
|
|
{
|
|
|
|
if let Some(inner) = self {
|
|
|
|
inner.imported_types(f);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-07-09 16:35:25 -07:00
|
|
|
/// Iterate over definitions of and references to imported types in the AST.
|
|
|
|
pub trait ImportedTypes {
|
|
|
|
fn imported_types<F>(&self, f: &mut F)
|
|
|
|
where
|
|
|
|
F: FnMut(&Ident, ImportedTypeKind);
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Iterate over definitions of imported types in the AST.
|
|
|
|
pub trait ImportedTypeDefinitions {
|
|
|
|
fn imported_type_definitions<F>(&self, f: &mut F)
|
|
|
|
where
|
|
|
|
F: FnMut(&Ident);
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<T> ImportedTypeDefinitions for T
|
|
|
|
where
|
|
|
|
T: ImportedTypes,
|
|
|
|
{
|
|
|
|
fn imported_type_definitions<F>(&self, f: &mut F)
|
|
|
|
where
|
|
|
|
F: FnMut(&Ident),
|
|
|
|
{
|
|
|
|
self.imported_types(&mut |id, kind| {
|
|
|
|
if let ImportedTypeKind::Definition = kind {
|
|
|
|
f(id);
|
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Iterate over references to imported types in the AST.
|
|
|
|
pub trait ImportedTypeReferences {
|
|
|
|
fn imported_type_references<F>(&self, f: &mut F)
|
|
|
|
where
|
|
|
|
F: FnMut(&Ident);
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<T> ImportedTypeReferences for T
|
|
|
|
where
|
|
|
|
T: ImportedTypes,
|
|
|
|
{
|
|
|
|
fn imported_type_references<F>(&self, f: &mut F)
|
|
|
|
where
|
|
|
|
F: FnMut(&Ident),
|
|
|
|
{
|
|
|
|
self.imported_types(&mut |id, kind| {
|
|
|
|
if let ImportedTypeKind::Reference = kind {
|
|
|
|
f(id);
|
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-09-05 12:55:30 -07:00
|
|
|
impl<'a, T: ImportedTypes> ImportedTypes for &'a T {
|
|
|
|
fn imported_types<F>(&self, f: &mut F)
|
|
|
|
where
|
|
|
|
F: FnMut(&Ident, ImportedTypeKind),
|
|
|
|
{
|
|
|
|
(*self).imported_types(f)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-07-09 16:35:25 -07:00
|
|
|
impl ImportedTypes for ast::Program {
|
|
|
|
fn imported_types<F>(&self, f: &mut F)
|
|
|
|
where
|
|
|
|
F: FnMut(&Ident, ImportedTypeKind),
|
|
|
|
{
|
|
|
|
self.imports.imported_types(f);
|
2018-07-13 22:36:51 -07:00
|
|
|
self.consts.imported_types(f);
|
2018-08-14 10:16:18 -07:00
|
|
|
self.dictionaries.imported_types(f);
|
2018-07-09 16:35:25 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<T> ImportedTypes for Vec<T>
|
|
|
|
where
|
|
|
|
T: ImportedTypes,
|
|
|
|
{
|
|
|
|
fn imported_types<F>(&self, f: &mut F)
|
|
|
|
where
|
|
|
|
F: FnMut(&Ident, ImportedTypeKind),
|
|
|
|
{
|
|
|
|
for x in self {
|
|
|
|
x.imported_types(f);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl ImportedTypes for ast::Import {
|
|
|
|
fn imported_types<F>(&self, f: &mut F)
|
|
|
|
where
|
|
|
|
F: FnMut(&Ident, ImportedTypeKind),
|
|
|
|
{
|
|
|
|
self.kind.imported_types(f)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl ImportedTypes for ast::ImportKind {
|
|
|
|
fn imported_types<F>(&self, f: &mut F)
|
|
|
|
where
|
|
|
|
F: FnMut(&Ident, ImportedTypeKind),
|
|
|
|
{
|
|
|
|
match self {
|
|
|
|
ast::ImportKind::Static(s) => s.imported_types(f),
|
|
|
|
ast::ImportKind::Function(fun) => fun.imported_types(f),
|
|
|
|
ast::ImportKind::Type(ty) => ty.imported_types(f),
|
2018-07-08 22:09:00 -04:00
|
|
|
ast::ImportKind::Enum(enm) => enm.imported_types(f),
|
2018-07-09 16:35:25 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl ImportedTypes for ast::ImportStatic {
|
|
|
|
fn imported_types<F>(&self, f: &mut F)
|
|
|
|
where
|
|
|
|
F: FnMut(&Ident, ImportedTypeKind),
|
|
|
|
{
|
|
|
|
self.ty.imported_types(f);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl ImportedTypes for syn::Type {
|
|
|
|
fn imported_types<F>(&self, f: &mut F)
|
|
|
|
where
|
|
|
|
F: FnMut(&Ident, ImportedTypeKind),
|
|
|
|
{
|
|
|
|
match self {
|
|
|
|
syn::Type::Reference(ref r) => r.imported_types(f),
|
|
|
|
syn::Type::Path(ref p) => p.imported_types(f),
|
|
|
|
_ => {}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl ImportedTypes for syn::TypeReference {
|
|
|
|
fn imported_types<F>(&self, f: &mut F)
|
|
|
|
where
|
|
|
|
F: FnMut(&Ident, ImportedTypeKind),
|
|
|
|
{
|
|
|
|
self.elem.imported_types(f);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl ImportedTypes for syn::TypePath {
|
|
|
|
fn imported_types<F>(&self, f: &mut F)
|
|
|
|
where
|
|
|
|
F: FnMut(&Ident, ImportedTypeKind),
|
|
|
|
{
|
2018-07-24 15:00:46 +01:00
|
|
|
self.qself.imported_types(f);
|
|
|
|
self.path.imported_types(f);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl ImportedTypes for syn::QSelf {
|
|
|
|
fn imported_types<F>(&self, _: &mut F)
|
|
|
|
where
|
|
|
|
F: FnMut(&Ident, ImportedTypeKind),
|
|
|
|
{
|
|
|
|
// TODO
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl ImportedTypes for syn::Path {
|
|
|
|
fn imported_types<F>(&self, f: &mut F)
|
|
|
|
where
|
|
|
|
F: FnMut(&Ident, ImportedTypeKind),
|
|
|
|
{
|
|
|
|
for seg in self.segments.iter() {
|
|
|
|
seg.arguments.imported_types(f);
|
2018-07-09 16:35:25 -07:00
|
|
|
}
|
|
|
|
f(
|
2018-07-24 15:00:46 +01:00
|
|
|
&self.segments.last().unwrap().value().ident,
|
2018-07-09 16:35:25 -07:00
|
|
|
ImportedTypeKind::Reference,
|
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-07-24 15:00:46 +01:00
|
|
|
impl ImportedTypes for syn::PathArguments {
|
|
|
|
fn imported_types<F>(&self, f: &mut F)
|
|
|
|
where
|
|
|
|
F: FnMut(&Ident, ImportedTypeKind),
|
|
|
|
{
|
|
|
|
match self {
|
|
|
|
syn::PathArguments::AngleBracketed(data) => {
|
|
|
|
for arg in data.args.iter() {
|
|
|
|
arg.imported_types(f);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
//TOCHECK
|
|
|
|
syn::PathArguments::Parenthesized(data) => {
|
|
|
|
for input in data.inputs.iter() {
|
|
|
|
input.imported_types(f);
|
|
|
|
}
|
2018-08-07 16:09:38 -07:00
|
|
|
// TODO do we need to handle output here?
|
2018-07-24 15:00:46 +01:00
|
|
|
// https://docs.rs/syn/0.14.0/syn/struct.ParenthesizedGenericArguments.html
|
|
|
|
}
|
|
|
|
syn::PathArguments::None => {}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl ImportedTypes for syn::GenericArgument {
|
|
|
|
fn imported_types<F>(&self, f: &mut F)
|
|
|
|
where
|
|
|
|
F: FnMut(&Ident, ImportedTypeKind),
|
|
|
|
{
|
|
|
|
match self {
|
|
|
|
syn::GenericArgument::Lifetime(_) => {}
|
|
|
|
syn::GenericArgument::Type(ty) => ty.imported_types(f),
|
|
|
|
syn::GenericArgument::Binding(_) => {}, // TODO
|
|
|
|
syn::GenericArgument::Const(_) => {}, // TODO
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2018-07-09 16:35:25 -07:00
|
|
|
impl ImportedTypes for ast::ImportFunction {
|
|
|
|
fn imported_types<F>(&self, f: &mut F)
|
|
|
|
where
|
|
|
|
F: FnMut(&Ident, ImportedTypeKind),
|
|
|
|
{
|
|
|
|
self.function.imported_types(f);
|
|
|
|
self.kind.imported_types(f);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl ImportedTypes for ast::ImportFunctionKind {
|
|
|
|
fn imported_types<F>(&self, f: &mut F)
|
|
|
|
where
|
|
|
|
F: FnMut(&Ident, ImportedTypeKind),
|
|
|
|
{
|
|
|
|
match self {
|
|
|
|
ast::ImportFunctionKind::Method { ty, .. } => ty.imported_types(f),
|
2018-08-28 15:19:31 -07:00
|
|
|
ast::ImportFunctionKind::ScopedMethod { ty, .. } => ty.imported_types(f),
|
2018-07-09 16:35:25 -07:00
|
|
|
ast::ImportFunctionKind::Normal => {}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl ImportedTypes for ast::Function {
|
|
|
|
fn imported_types<F>(&self, f: &mut F)
|
|
|
|
where
|
|
|
|
F: FnMut(&Ident, ImportedTypeKind),
|
|
|
|
{
|
|
|
|
self.arguments.imported_types(f);
|
|
|
|
if let Some(ref r) = self.ret {
|
|
|
|
r.imported_types(f);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl ImportedTypes for syn::ArgCaptured {
|
|
|
|
fn imported_types<F>(&self, f: &mut F)
|
|
|
|
where
|
|
|
|
F: FnMut(&Ident, ImportedTypeKind),
|
|
|
|
{
|
|
|
|
self.ty.imported_types(f);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl ImportedTypes for ast::ImportType {
|
|
|
|
fn imported_types<F>(&self, f: &mut F)
|
|
|
|
where
|
|
|
|
F: FnMut(&Ident, ImportedTypeKind),
|
|
|
|
{
|
2018-08-07 16:09:38 -07:00
|
|
|
f(&self.rust_name, ImportedTypeKind::Definition);
|
2018-07-09 16:35:25 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-07-08 22:09:00 -04:00
|
|
|
impl ImportedTypes for ast::ImportEnum {
|
|
|
|
fn imported_types<F>(&self, f: &mut F)
|
|
|
|
where
|
|
|
|
F: FnMut(&Ident, ImportedTypeKind),
|
|
|
|
{
|
|
|
|
f(&self.name, ImportedTypeKind::Definition);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-07-13 04:16:19 +02:00
|
|
|
impl ImportedTypes for ast::Const {
|
|
|
|
fn imported_types<F>(&self, f: &mut F)
|
|
|
|
where
|
|
|
|
F: FnMut(&Ident, ImportedTypeKind),
|
|
|
|
{
|
|
|
|
self.ty.imported_types(f);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-08-14 10:16:18 -07:00
|
|
|
impl ImportedTypes for ast::Dictionary {
|
|
|
|
fn imported_types<F>(&self, f: &mut F)
|
|
|
|
where
|
|
|
|
F: FnMut(&Ident, ImportedTypeKind),
|
|
|
|
{
|
|
|
|
f(&self.name, ImportedTypeKind::Definition);
|
|
|
|
for field in self.fields.iter() {
|
|
|
|
field.imported_types(f);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl ImportedTypes for ast::DictionaryField {
|
|
|
|
fn imported_types<F>(&self, f: &mut F)
|
|
|
|
where
|
|
|
|
F: FnMut(&Ident, ImportedTypeKind),
|
|
|
|
{
|
|
|
|
self.ty.imported_types(f);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-07-09 16:35:25 -07:00
|
|
|
/// Remove any methods, statics, &c, that reference types that are *not*
|
|
|
|
/// defined.
|
|
|
|
pub trait RemoveUndefinedImports {
|
2018-08-14 10:16:18 -07:00
|
|
|
fn remove_undefined_imports<F>(&mut self, is_defined: &F) -> bool
|
2018-07-09 16:35:25 -07:00
|
|
|
where
|
|
|
|
F: Fn(&Ident) -> bool;
|
|
|
|
}
|
|
|
|
|
|
|
|
impl RemoveUndefinedImports for ast::Program {
|
2018-08-14 10:16:18 -07:00
|
|
|
fn remove_undefined_imports<F>(&mut self, is_defined: &F) -> bool
|
2018-07-09 16:35:25 -07:00
|
|
|
where
|
|
|
|
F: Fn(&Ident) -> bool,
|
|
|
|
{
|
2018-08-14 10:16:18 -07:00
|
|
|
let a = self.imports.remove_undefined_imports(is_defined);
|
|
|
|
let b = self.consts.remove_undefined_imports(is_defined);
|
|
|
|
let c = self.dictionaries.remove_undefined_imports(is_defined);
|
|
|
|
a || b || c
|
2018-07-09 16:35:25 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<T> RemoveUndefinedImports for Vec<T>
|
|
|
|
where
|
|
|
|
T: ImportedTypeReferences,
|
|
|
|
{
|
2018-08-14 10:16:18 -07:00
|
|
|
fn remove_undefined_imports<F>(&mut self, is_defined: &F) -> bool
|
2018-07-09 16:35:25 -07:00
|
|
|
where
|
|
|
|
F: Fn(&Ident) -> bool,
|
|
|
|
{
|
2018-08-14 10:16:18 -07:00
|
|
|
let before = self.len();
|
2018-07-09 16:35:25 -07:00
|
|
|
self.retain(|x| {
|
|
|
|
let mut all_defined = true;
|
|
|
|
x.imported_type_references(&mut |id| {
|
2018-07-18 17:59:24 -05:00
|
|
|
if all_defined {
|
|
|
|
if !is_defined(id) {
|
|
|
|
info!("removing due to {} not being defined", id);
|
|
|
|
all_defined = false;
|
|
|
|
}
|
|
|
|
}
|
2018-07-09 16:35:25 -07:00
|
|
|
});
|
|
|
|
all_defined
|
|
|
|
});
|
2018-08-14 10:16:18 -07:00
|
|
|
before != self.len()
|
2018-07-09 16:35:25 -07:00
|
|
|
}
|
|
|
|
}
|