Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

TypeScript package generator. #7

Draft
wants to merge 14 commits into
base: main
Choose a base branch
from
4 changes: 3 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ members = [
"core",
"syntax",
"cli",
"codegen",
"json-schema",
"json-ld-context"
"json-ld-context",
"typescript"
]
6 changes: 5 additions & 1 deletion cli/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,16 @@ description = "Schema definition language."
edition = "2021"

[features]
default = ["json-schema", "json-ld-context"]
default = ["json-schema", "json-ld-context", "typescript"]
json-schema = [
"treeldr-json-schema"
]
json-ld-context = [
"treeldr-json-ld-context"
]
typescript = [
"treeldr-typescript"
]

[dependencies]
treeldr = { path = "../core" }
Expand All @@ -28,6 +31,7 @@ clap = { version = "3.0", features = ["derive"] }
# Extensions.
treeldr-json-schema = { path = "../json-schema", version = "0.1", optional = true }
treeldr-json-ld-context = { path = "../json-ld-context", version = "0.1", optional = true }
treeldr-typescript = { path = "../typescript", version = "0.1", optional = true }

[[bin]]
name = "treeldr"
Expand Down
20 changes: 16 additions & 4 deletions cli/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ struct Args {
verbosity: usize,

#[clap(subcommand)]
command: Option<Command>,
command: Command,
}

#[derive(clap::Subcommand)]
Expand All @@ -33,6 +33,14 @@ pub enum Command {

#[cfg(feature = "json-ld-context")]
JsonLdContext(treeldr_json_ld_context::Command),

#[cfg(feature = "typescript")]
#[clap(name = "typescript")]
TypeScript(treeldr_typescript::Command),

#[cfg(feature = "typescript")]
#[clap(name = "typescript-package")]
TypeScriptPackage(treeldr_typescript::command::Package),
}

fn main() {
Expand All @@ -58,7 +66,7 @@ fn main() {
}

match args.command {
Some(Command::Dump) => {
Command::Dump => {
for quad in &quads {
use treeldr::vocab::RdfDisplay;
println!("{} .", quad.rdf_display(&vocab))
Expand All @@ -73,9 +81,13 @@ fn main() {
#[allow(unused_variables)]
Ok(model) => match command {
#[cfg(feature = "json-schema")]
Some(Command::JsonSchema(command)) => command.execute(&model),
Command::JsonSchema(command) => command.execute(&model),
#[cfg(feature = "json-ld-context")]
Some(Command::JsonLdContext(command)) => command.execute(&model),
Command::JsonLdContext(command) => command.execute(&model),
#[cfg(feature = "typescript")]
Command::TypeScript(command) => command.execute(&model),
#[cfg(feature = "typescript")]
Command::TypeScriptPackage(command) => command.execute(&model),
_ => (),
},
Err((e, vocab)) => {
Expand Down
2 changes: 2 additions & 0 deletions codegen/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
/target
Cargo.lock
1 change: 1 addition & 0 deletions codegen/.rustfmt.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
hard_tabs = true
7 changes: 7 additions & 0 deletions codegen/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
[package]
name = "treeldr-codegen"
version = "0.1.0"
edition = "2021"

[dependencies]
treeldr = { path = "../core" }
106 changes: 106 additions & 0 deletions codegen/src/doc.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
use crate::IndentBy;
use std::fmt;

pub enum CommentSyntax {
Single(&'static str),
Multi {
/// If true, two empty lines are added at the top and bottom.
pad: bool,
start: &'static str,
middle: &'static str,
end: &'static str,
},
}

pub enum CommentPosition {
Start,
Middle,
End,
}

impl CommentSyntax {
pub fn pad(&self) -> bool {
matches!(self, Self::Multi { pad: true, .. })
}

pub fn as_str(&self, pos: CommentPosition) -> &'static str {
match self {
Self::Single(s) => s,
Self::Multi {
start, middle, end, ..
} => match pos {
CommentPosition::Start => start,
CommentPosition::Middle => middle,
CommentPosition::End => end,
},
}
}
}

pub struct Comment<S> {
content: S,
syntax: CommentSyntax,
indent_by: IndentBy,
}

impl<S> Comment<S> {
pub fn new(content: S, syntax: CommentSyntax, indent_by: IndentBy) -> Self {
Self {
content,
syntax,
indent_by,
}
}
}

impl<S: AsRef<str>> fmt::Display for Comment<S> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let content = self.content.as_ref();
let line_count = content.lines().count();
let pad = self.syntax.pad();

if pad {
writeln!(
f,
"{}{}",
self.indent_by,
self.syntax.as_str(CommentPosition::Start)
)?;
}

for (i, line) in content.lines().enumerate() {
let pos = if !pad && i == 0 {
CommentPosition::Start
} else if !pad && i + 1 == line_count {
CommentPosition::End
} else {
CommentPosition::Middle
};

if i > 0 {
writeln!(f)?;
}

write!(f, "{}{}{}", self.indent_by, self.syntax.as_str(pos), line)?;

if !pad && i == 0 && i + 1 == line_count {
write!(f, "{}", self.syntax.as_str(CommentPosition::End))?;
}
}

if pad {
if !content.is_empty() {
writeln!(f)?;
}

write!(
f,
"{}{}",
self.indent_by,
self.syntax.as_str(CommentPosition::End)
)?;
}

Ok(())
}
}
48 changes: 48 additions & 0 deletions codegen/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
//! Common functions for code generation.
use std::fmt;

pub mod doc;

/// Indentation method.
#[derive(Clone, Copy)]
pub enum Indent {
/// Use a tab `\t` character.
Tab,

/// Use the given number of spaces.
Spaces(u8),
}

impl Indent {
pub fn by(&self, n: u32) -> IndentBy {
IndentBy(*self, n)
}
}

impl fmt::Display for Indent {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
Self::Tab => write!(f, "\t"),
Self::Spaces(n) => {
for _ in 0..*n {
write!(f, " ")?;
}

Ok(())
}
}
}
}

#[derive(Clone, Copy)]
pub struct IndentBy(Indent, u32);

impl fmt::Display for IndentBy {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
for _ in 0..self.1 {
self.0.fmt(f)?;
}

Ok(())
}
}
14 changes: 6 additions & 8 deletions core/src/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -106,17 +106,15 @@ impl<F: Clone + Ord> Context<F> {
}
},
Name::Rdfs(vocab::Rdfs::Label) => match object.as_literal() {
Some(label) => {
self.add_label(
id,
label.string_literal().value().as_str().to_owned(),
Some(loc),
)
}
Some(label) => self.add_label(
id,
label.string_literal().value().as_str().to_owned(),
Some(loc),
),
None => {
panic!("label is not a string literal")
}
}
},
Name::Rdfs(vocab::Rdfs::Comment) => match object.as_literal() {
Some(literal) => {
self.add_comment(
Expand Down
6 changes: 3 additions & 3 deletions core/src/doc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ impl Block {
}
}
}

if state == State::Short {
short_end = s.len();
long_start = s.len();
Expand Down Expand Up @@ -129,7 +129,7 @@ impl Documentation {
self.blocks.insert(Block::new(comment));
}

pub fn as_string(&self) -> Option<&str> {
pub fn as_str(&self) -> Option<&str> {
self.blocks.iter().next().map(Block::as_str)
}
}
}
Loading