Skip to content

Commit

Permalink
fix(types):prune unused and ToParts trait
Browse files Browse the repository at this point in the history
* do not emit unused types. Sometimes though, rustc doesn't seem to
  detect that attributses are actually used
* ToParts trait is used and implemented only when needed.

Linters are back to 'normal'.

Fixes #35
  • Loading branch information
Byron committed Mar 21, 2015
1 parent 0152138 commit 80161f7
Show file tree
Hide file tree
Showing 7 changed files with 249 additions and 111 deletions.
10 changes: 9 additions & 1 deletion gen/youtube3/src/cmn.rs
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,11 @@ pub trait NestedType: MarkerTrait {}
pub trait ReadSeek: Seek + Read {}
impl<T: Seek + Read> ReadSeek for T {}

/// A trait for all types that can convert themselves into a *parts* string
pub trait ToParts {
fn to_parts(&self) -> String;
}


/// A utility type which can decode a server response that indicates error
#[derive(Deserialize)]
Expand Down Expand Up @@ -98,7 +103,10 @@ pub trait Delegate {
/// Called whenever a server response could not be decoded from json.
/// It's for informational purposes only, the caller will return with an error
/// accordingly.
fn response_json_decode_error(&mut self, json_encoded_value: &str) {}
/// # Arguments
/// `&str` - The json-encoded value which failed to decode.
/// `Error` - The decoder error
fn response_json_decode_error(&mut self, _: &str, _: &serde::json::Error) {}

/// Called whenever the http request returns with a non-success status code.
/// This can involve authentication issues, or anything else that very much
Expand Down
258 changes: 181 additions & 77 deletions gen/youtube3/src/lib.rs

Large diffs are not rendered by default.

14 changes: 8 additions & 6 deletions src/mako/lib.rs.mako
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@
<%
from util import (new_context, rust_comment, rust_doc_comment, rust_module_doc_comment,
rb_type, hub_type, mangle_ident, hub_type_params_s, hub_type_bounds,
rb_type_params_s, find_fattest_resource, HUB_TYPE_PARAMETERS, METHODS_RESOURCE)
rb_type_params_s, find_fattest_resource, HUB_TYPE_PARAMETERS, METHODS_RESOURCE,
UNUSED_TYPE_MARKER, schema_markers)
c = new_context(schemas, resources, context.get('methods'))
hub_type = hub_type(c.schemas, util.canonical_name())
Expand All @@ -21,9 +22,8 @@
<%block filter="rust_module_doc_comment">\
${lib.docs(c)}
</%block>
#![feature(core,io, old_io)]
// DEBUG !! TODO: Remove this
#![allow(dead_code, deprecated)]
#![feature(core,io,thread_sleep)]
// Unused attributes happen thanks to defined, but unused structures
// We don't warn about this, as depending on the API, some data structures or facilities are never used.
// Instead of pre-determining this, we just disable the lint. It's manually tuned to not have any
// unused imports in fully featured APIs. Same with unused_mut ... .
Expand All @@ -49,9 +49,9 @@ use std::marker::PhantomData;
use serde::json;
use std::io;
use std::fs;
use std::old_io::timer::sleep;
use std::thread::sleep;

pub use cmn::{MultiPartReader, MethodInfo, Result, CallBuilder, Hub, ReadSeek, Part, ResponseResult, RequestValue, NestedType, Delegate, DefaultDelegate, UnusedType};
pub use cmn::{MultiPartReader, ToParts, MethodInfo, Result, CallBuilder, Hub, ReadSeek, Part, ResponseResult, RequestValue, NestedType, Delegate, DefaultDelegate};


// ##############
Expand Down Expand Up @@ -119,7 +119,9 @@ impl<'a, ${', '.join(HUB_TYPE_PARAMETERS)}> ${hub_type}${ht_params}
// SCHEMAS ###
// ##########
% for s in c.schemas.values():
% if UNUSED_TYPE_MARKER not in schema_markers(s, c, transitive=True):
${schema.new(s, c)}
% endif
% endfor
% endif

Expand Down
5 changes: 4 additions & 1 deletion src/mako/lib/mbuild.mako
Original file line number Diff line number Diff line change
Expand Up @@ -747,7 +747,10 @@ if enable_resource_parsing \
res.read_to_string(&mut json_response).unwrap();
match json::from_str(&json_response) {
Ok(decoded) => (res, decoded),
Err(err) => return Result::JsonDecodeError(err),
Err(err) => {
dlg.response_json_decode_error(&json_response, &err);
return Result::JsonDecodeError(err);
}
}
}\
% if supports_download:
Expand Down
12 changes: 7 additions & 5 deletions src/mako/lib/schema.mako
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
from util import (schema_markers, rust_doc_comment, mangle_ident, to_rust_type, put_and,
IO_TYPES, activity_split, enclose_in, REQUEST_MARKER_TRAIT, mb_type, indent_all_but_first_by,
NESTED_TYPE_SUFFIX, RESPONSE_MARKER_TRAIT, split_camelcase_s, METHODS_RESOURCE, unique_type_name,
PART_MARKER_TRAIT, canonical_type_name)
PART_MARKER_TRAIT, canonical_type_name, TO_PARTS_MARKER, UNUSED_TYPE_MARKER)
default_traits = ('RustcEncodable', 'Clone', 'Default')
%>\
Expand All @@ -27,7 +27,7 @@ ${struct}(${to_rust_type(schemas, s.id, NESTED_TYPE_SUFFIX, s, allow_optionals=a
<%
et = unique_type_name(s.id)
variant_type = lambda p: canonical_type_name(p.type_value)
%>
%>\
pub enum ${et} {
% for p in s.variant.map:
${p.get('description', 'no description provided') | rust_doc_comment, indent_all_but_first_by(1)}
Expand Down Expand Up @@ -73,7 +73,7 @@ ${struct};
allow_optionals = False
# use optionals only when needed
## waiting for Default: https://github.com/rust-lang/rustc-serialize/issues/71
# waiting for Default: https://github.com/rust-lang/rustc-serialize/issues/71
if s.type == 'any':
traits.remove('Default')
Expand Down Expand Up @@ -105,11 +105,13 @@ impl Default for ${s_type} {
% endif ## type == ?
% for marker_trait in nt_markers:
% if marker_trait not in (TO_PARTS_MARKER, UNUSED_TYPE_MARKER):
impl ${marker_trait} for ${s_type} {}
% endif
% endfor
% if REQUEST_MARKER_TRAIT in nt_markers and 'properties' in s:
impl ${s_type} {
% if TO_PARTS_MARKER in nt_markers and allow_optionals:
impl ${TO_PARTS_MARKER} for ${s_type} {
/// Return a comma separated list of members that are currently set, i.e. for which `self.member.is_some()`.
/// The produced string is suitable for use as a parts list that indicates the parts you are sending, and/or
/// the parts you want to see in the server response.
Expand Down
51 changes: 31 additions & 20 deletions src/mako/lib/util.py
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,8 @@
NESTED_MARKER_TRAIT = 'NestedType'
REQUEST_VALUE_PROPERTY_NAME = 'request'
DELEGATE_PROPERTY_NAME = 'delegate'
TO_PARTS_MARKER = 'ToParts'
UNUSED_TYPE_MARKER = 'UnusedType'

PROTOCOL_TYPE_INFO = {
'simple' : {
Expand Down Expand Up @@ -365,39 +367,48 @@ def activity_input_type(schemas, p):
def is_pod_property(p):
return 'format' in p or p.get('type','') == 'boolean'


def _traverse_schema_ids(s, c):
ids = [s.id]
used_by = s.used_by + s.parents

seen = set() # protect against loops, just to be sure ...
while used_by:
id = used_by.pop()
if id in seen:
continue
seen.add(id)
ids.append(id)

oid = c.schemas[id]
used_by.extend(oid.used_by)
used_by.extend(oid.parents)
# end gather usages
return ids

# Return sorted type names of all markers applicable to the given schema
# This list is transitive. Thus, if the schema is used as child of someone with a trait, it
# inherits this trait
def schema_markers(s, c, transitive=True):
res = set()
ids = [s.id]

if transitive:
used_by = s.used_by + s.parents

seen = set() # protect against loops, just to be sure ...
while used_by:
id = used_by.pop()
if id in seen:
continue
seen.add(id)
ids.append(id)

oid = c.schemas[id]
used_by.extend(oid.used_by)
used_by.extend(oid.parents)
# end gather usages
# end is transitive
ids = transitive and _traverse_schema_ids(s, c) or [s.id]

has_activity = False
for sid in ids:
activities = c.sta_map.get(sid, dict())
if len(activities) == 0:
continue
has_activity = True
# it should have at least one activity that matches it's type to qualify for the Resource trait
for fqan, iot in activities.iteritems():
_, resource, _ = activity_split(fqan)
if resource and activity_name_to_type_name(resource).lower() == sid.lower():
res.add('cmn::%s' % RESOURCE_MARKER_TRAIT)
m = c.fqan_map[fqan]
params, _ = build_all_params(c, m)
part_prop, _ = parts_from_params(params)
if part_prop is not None and 'properties' in s:
res.add(TO_PARTS_MARKER)
if IO_RESPONSE in iot:
res.add(RESPONSE_MARKER_TRAIT)
if IO_REQUEST in iot:
Expand All @@ -412,8 +423,8 @@ def schema_markers(s, c, transitive=True):
if len(c.sta_map.get(s.id, dict())) == 0:
res.add(PART_MARKER_TRAIT)

if len(res) == 1 and PART_MARKER_TRAIT in res and len(s.used_by) == 0:
res.add('UnusedType')
if not has_activity:
res.add(UNUSED_TYPE_MARKER)

return sorted(res)

Expand Down
10 changes: 9 additions & 1 deletion src/rust/cmn.rs
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,11 @@ pub trait NestedType: MarkerTrait {}
pub trait ReadSeek: Seek + Read {}
impl<T: Seek + Read> ReadSeek for T {}

/// A trait for all types that can convert themselves into a *parts* string
pub trait ToParts {
fn to_parts(&self) -> String;
}


/// A utility type which can decode a server response that indicates error
#[derive(Deserialize)]
Expand Down Expand Up @@ -96,7 +101,10 @@ pub trait Delegate {
/// Called whenever a server response could not be decoded from json.
/// It's for informational purposes only, the caller will return with an error
/// accordingly.
fn response_json_decode_error(&mut self, json_encoded_value: &str) {}
/// # Arguments
/// `&str` - The json-encoded value which failed to decode.
/// `Error` - The decoder error
fn response_json_decode_error(&mut self, _: &str, _: &serde::json::Error) {}

/// Called whenever the http request returns with a non-success status code.
/// This can involve authentication issues, or anything else that very much
Expand Down

0 comments on commit 80161f7

Please sign in to comment.