Skip to content

Commit

Permalink
Add Annotation enum
Browse files Browse the repository at this point in the history
  • Loading branch information
milesgranger committed Nov 2, 2019
1 parent 9e79768 commit 42d42f9
Show file tree
Hide file tree
Showing 12 changed files with 288 additions and 70 deletions.
65 changes: 65 additions & 0 deletions src/gen/annotation.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
//!
//! Create `enum` objects
//!
//!
//! Example
//! -------
//! ```
//! use proffer::*;
//!
//! let a = Annotation::from("#![be_cool]");
//!
//! let src_code = a.generate();
//! let expected = "#![be_cool]";
//! assert_eq!(norm_whitespace(expected), norm_whitespace(&src_code))
//! ```
use crate::SrcCode;
use serde::{Deserialize, Serialize};

/// Represents a single Rust annotation to a module, function, etc.
#[derive(Debug, Clone, Serialize, Deserialize)]
pub enum Annotation {
/// Annotation representing an attribute for type. ie. `#[foo(bar)]`
Attr(String),
/// Annotation representing a comment. ie. `// foo`
Comment(String),
/// Annotation representing a doc string. ie. `/// documentation`
Doc(String),
/// Annotation representing a module attribute. ie. `#![warn(...)]`
ModuleAttr(String),
/// Annotation representing a module level doc string. ie. `//! module documentation`
ModuleDoc(String),
}

impl<S: ToString> From<S> for Annotation {
fn from(annotation: S) -> Self {
let annotation = annotation.to_string();

if annotation.starts_with("//!") {
Annotation::ModuleDoc(annotation)
} else if annotation.starts_with("///") {
Annotation::Doc(annotation)
} else if annotation.starts_with("//") {
Annotation::Comment(annotation)
} else if annotation.starts_with("#!") {
Annotation::ModuleAttr(annotation)
} else if annotation.starts_with('#') {
Annotation::Attr(annotation)
} else {
panic!("No Annotation match for '{}'", annotation)
}
}
}

impl SrcCode for Annotation {
fn generate(&self) -> String {
match self {
Annotation::Attr(s)
| Annotation::Comment(s)
| Annotation::Doc(s)
| Annotation::ModuleAttr(s)
| Annotation::ModuleDoc(s) => s.to_owned(),
}
}
}
38 changes: 27 additions & 11 deletions src/gen/associated_types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,15 @@
use serde::{Deserialize, Serialize};
use tera::{Context, Tera};

use crate::internal;
use crate::traits::SrcCode;
use crate::{internal, Annotation};

/// Represent the declaration of a associated type in a trait
#[derive(Serialize, Deserialize, Default, Clone)]
pub struct AssociatedTypeDeclaration {
pub(crate) name: String,
pub(crate) traits: Vec<String>,
annotations: Vec<String>,
annotations: Vec<Annotation>,
}

impl AssociatedTypeDeclaration {
Expand All @@ -28,7 +28,7 @@ impl AssociatedTypeDeclaration {
}

impl internal::Annotations for AssociatedTypeDeclaration {
fn annotations(&mut self) -> &mut Vec<String> {
fn annotations(&mut self) -> &mut Vec<Annotation> {
&mut self.annotations
}
}
Expand All @@ -41,14 +41,22 @@ impl internal::TraitBounds for AssociatedTypeDeclaration {

impl SrcCode for AssociatedTypeDeclaration {
fn generate(&self) -> String {
let template = r#"{% if has_annotations %}{{ self.annotations | join(sep="
let template = r#"
{{ annotations | join(sep="
") }}
{% endif %}type {{ self.name }}{% if has_traits %}: {{ self.traits | join(sep=" + ") }}{% endif %};
type {{ self.name }}{% if has_traits %}: {{ self.traits | join(sep=" + ") }}{% endif %};
"#;
let mut context = Context::new();
context.insert("self", &self);
context.insert("has_traits", &!self.traits.is_empty());
context.insert("has_annotations", &!self.annotations.is_empty());
context.insert(
"annotations",
&self
.annotations
.iter()
.map(|a| a.generate())
.collect::<Vec<String>>(),
);
Tera::one_off(template, &context, false).unwrap()
}
}
Expand All @@ -58,7 +66,7 @@ impl SrcCode for AssociatedTypeDeclaration {
pub struct AssociatedTypeDefinition {
pub(crate) name: String,
pub(crate) implementer: String,
annotations: Vec<String>,
annotations: Vec<Annotation>,
}

impl AssociatedTypeDefinition {
Expand All @@ -73,20 +81,28 @@ impl AssociatedTypeDefinition {
}

impl internal::Annotations for AssociatedTypeDefinition {
fn annotations(&mut self) -> &mut Vec<String> {
fn annotations(&mut self) -> &mut Vec<Annotation> {
&mut self.annotations
}
}

impl SrcCode for AssociatedTypeDefinition {
fn generate(&self) -> String {
let template = r#"{% if has_annotations %}{{ self.annotations | join(sep="
let template = r#"
{{ annotations | join(sep="
") }}
{% endif %}type {{ self.name }} = {{ self.implementer }};
type {{ self.name }} = {{ self.implementer }};
"#;
let mut context = Context::new();
context.insert("self", &self);
context.insert("has_annotations", &!self.annotations.is_empty());
context.insert(
"annotations",
&self
.annotations
.iter()
.map(|v| v.generate())
.collect::<Vec<String>>(),
);
Tera::one_off(template, &context, false).unwrap()
}
}
28 changes: 22 additions & 6 deletions src/gen/field.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,8 @@ pub struct Field {
name: String,
is_pub: bool,
ty: String,
annotations: Vec<String>,
docs: Vec<String>,
annotations: Vec<Annotation>,
docs: Vec<Annotation>,
}

impl Field {
Expand All @@ -48,27 +48,43 @@ impl Field {
}

impl internal::Annotations for Field {
fn annotations(&mut self) -> &mut Vec<String> {
fn annotations(&mut self) -> &mut Vec<Annotation> {
&mut self.annotations
}
}

impl internal::Docs for Field {
fn docs(&mut self) -> &mut Vec<String> {
fn docs(&mut self) -> &mut Vec<Annotation> {
&mut self.docs
}
}

impl SrcCode for Field {
fn generate(&self) -> String {
let template = r#"
{{ field.docs | join(sep="
{{ docs | join(sep="
") }}
{% for annotation in field.annotations %}{{ annotation }}{% endfor %}
{% for annotation in annotations %}{{ annotation }}{% endfor %}
{% if field.is_pub %}pub{% endif %} {{ field.name }}: {{ field.ty }},
"#;
let mut context = Context::new();
context.insert("field", &self);
context.insert(
"docs",
&self
.docs
.iter()
.map(|d| d.generate())
.collect::<Vec<String>>(),
);
context.insert(
"annotations",
&self
.annotations
.iter()
.map(|a| a.generate())
.collect::<Vec<String>>(),
);
Tera::one_off(template, &context, false).unwrap()
}
}
48 changes: 36 additions & 12 deletions src/gen/function.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ use tera::{Context, Tera};

use crate::internal::Annotations;
use crate::traits::SrcCode;
use crate::{internal, Generic, Generics};
use crate::{internal, Annotation, Generic, Generics};

/// Represents a function or method. Determined if any `Parameter` contains `self`
#[derive(Default, Serialize, Clone)]
Expand All @@ -29,7 +29,7 @@ pub struct FunctionSignature {
parameters: Vec<Parameter>,
generics: Generics,
return_ty: Option<String>,
annotations: Vec<String>,
annotations: Vec<Annotation>,
}

impl FunctionSignature {
Expand Down Expand Up @@ -73,7 +73,7 @@ impl FunctionSignature {
}

impl internal::Annotations for FunctionSignature {
fn annotations(&mut self) -> &mut Vec<String> {
fn annotations(&mut self) -> &mut Vec<Annotation> {
&mut self.annotations
}
}
Expand All @@ -87,7 +87,7 @@ impl internal::Generics for FunctionSignature {
impl SrcCode for FunctionSignature {
fn generate(&self) -> String {
let template = r#"
{{ self.annotations | join(sep="
{{ annotations | join(sep="
") }}
{% if self.is_pub %}pub {% endif %}{% if self.is_async %}async {% endif %}fn {{ self.name }}{% if has_generics %}<{{ generic_keys | join(sep=", ") }}>{% endif %}({{ parameters | join(sep=", ") }}) -> {{ return_ty }}{% if has_generics %}
where
Expand Down Expand Up @@ -118,6 +118,14 @@ impl SrcCode for FunctionSignature {
.map(|param| param.generate())
.collect::<Vec<String>>(),
);
context.insert(
"annotations",
&self
.annotations
.iter()
.map(|a| a.generate())
.collect::<Vec<String>>(),
);
Tera::one_off(template, &context, false).unwrap()
}
}
Expand All @@ -126,24 +134,32 @@ impl SrcCode for FunctionSignature {
#[derive(Default, Serialize, Clone)]
pub struct FunctionBody {
body: String,
annotations: Vec<String>,
annotations: Vec<Annotation>,
}

impl internal::Annotations for FunctionBody {
fn annotations(&mut self) -> &mut Vec<String> {
fn annotations(&mut self) -> &mut Vec<Annotation> {
&mut self.annotations
}
}

impl SrcCode for FunctionBody {
fn generate(&self) -> String {
let template = r#"
{{ self.annotations | join(sep="
{{ annotations | join(sep="
") }}
{{ self.body }}
"#;
let mut ctx = Context::new();
ctx.insert("self", &self);
ctx.insert(
"annotations",
&self
.annotations
.iter()
.map(|a| a.generate())
.collect::<Vec<String>>(),
);
Tera::one_off(template, &ctx, false).unwrap()
}
}
Expand Down Expand Up @@ -185,11 +201,11 @@ impl Function {
}

impl internal::InnerAndOuterAnnotations for Function {
fn inner_annotations(&mut self) -> &mut Vec<String> {
fn inner_annotations(&mut self) -> &mut Vec<Annotation> {
self.body.annotations()
}

fn outer_annotations(&mut self) -> &mut Vec<String> {
fn outer_annotations(&mut self) -> &mut Vec<Annotation> {
self.signature.annotations()
}
}
Expand All @@ -205,7 +221,7 @@ impl internal::Generics for Function {
pub struct Parameter {
name: String,
ty: String,
annotations: Vec<String>,
annotations: Vec<Annotation>,
}
impl Parameter {
/// Create a new parameter
Expand All @@ -230,16 +246,24 @@ impl Parameter {
}

impl internal::Annotations for Parameter {
fn annotations(&mut self) -> &mut Vec<String> {
fn annotations(&mut self) -> &mut Vec<Annotation> {
&mut self.annotations
}
}

impl SrcCode for Parameter {
fn generate(&self) -> String {
let template = "{% for annotation in self.annotations %}{{ annotation }} {% endfor %}{{ self.name }}: {{ self.ty }}";
let template = "{% for annotation in annotations %}{{ annotation }} {% endfor %}{{ self.name }}: {{ self.ty }}";
let mut ctx = Context::new();
ctx.insert("self", &self);
ctx.insert(
"annotations",
&self
.annotations
.iter()
.map(|a| a.generate())
.collect::<Vec<String>>(),
);
Tera::one_off(template, &ctx, false).unwrap()
}
}
Expand Down
3 changes: 3 additions & 0 deletions src/gen/mod.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
//! Re-exports from the `gen` submodules.

pub mod annotation;
pub mod associated_types;
pub mod r#enum;
pub mod field;
Expand All @@ -10,6 +12,7 @@ pub mod module;
pub mod r#struct;
pub mod r#trait;

pub use annotation::*;
pub use associated_types::*;
pub use field::*;
pub use function::*;
Expand Down
Loading

0 comments on commit 42d42f9

Please sign in to comment.