Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions .devcontainer/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# See here for image contents: https://github.com/microsoft/vscode-dev-containers/tree/v0.217.4/containers/rust/.devcontainer/base.Dockerfile

# [Choice] Debian OS version (use bullseye on local arm64/Apple Silicon): buster, bullseye
ARG VARIANT="buster"
FROM mcr.microsoft.com/vscode/devcontainers/rust:0-${VARIANT}

# [Optional] Uncomment this section to install additional packages.
# RUN apt-get update && export DEBIAN_FRONTEND=noninteractive \
# && apt-get -y install --no-install-recommends <your-package-list-here>
46 changes: 46 additions & 0 deletions .devcontainer/devcontainer.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
// For format details, see https://aka.ms/devcontainer.json. For config options, see the README at:
// https://github.com/microsoft/vscode-dev-containers/tree/v0.217.4/containers/rust
{
"name": "Rust",
"build": {
"dockerfile": "Dockerfile",
"args": {
// Use the VARIANT arg to pick a Debian OS version: buster, bullseye
// Use bullseye when on local on arm64/Apple Silicon.
"VARIANT": "buster"
}
},
"runArgs": [
"--cap-add=SYS_PTRACE",
"--security-opt",
"seccomp=unconfined"
],

// Set *default* container specific settings.json values on container create.
"settings": {
"lldb.executable": "/usr/bin/lldb",
// VS Code don't watch files under ./target
"files.watcherExclude": {
"**/target/**": true
},
"rust-analyzer.checkOnSave.command": "clippy"
},

// Add the IDs of extensions you want installed when the container is created.
"extensions": [
"vadimcn.vscode-lldb",
"mutantdino.resourcemonitor",
"matklad.rust-analyzer",
"tamasfe.even-better-toml",
"serayuzgur.crates"
],

// Use 'forwardPorts' to make a list of ports inside the container available locally.
// "forwardPorts": [],

// Use 'postCreateCommand' to run commands after the container is created.
// "postCreateCommand": "rustc --version",

// Comment out to connect as root instead. More info: https://aka.ms/vscode-remote/containers/non-root.
"remoteUser": "vscode"
}
2 changes: 2 additions & 0 deletions src/item.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ use crate::r#enum::Enum;
use crate::r#impl::Impl;
use crate::r#struct::Struct;
use crate::r#trait::Trait;
use crate::type_alias::TypeAlias;

#[derive(Debug, Clone)]
pub enum Item {
Expand All @@ -15,4 +16,5 @@ pub enum Item {
Enum(Enum),
Impl(Impl),
Raw(String),
TypeAlias(TypeAlias),
}
73 changes: 73 additions & 0 deletions src/keywords.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
const KW_AS: &str = "as";
const KW_BREAK: &str = "break";
const KW_CONST: &str = "const";
const KW_CONTINUE: &str = "continue";
const KW_CRATE: &str = "crate";
const KW_ELSE: &str = "else";
const KW_ENUM: &str = "enum";
const KW_EXTERN: &str = "extern";
const KW_FALSE: &str = "false";
const KW_FN: &str = "fn";
const KW_FOR: &str = "for";
const KW_IF: &str = "if";
const KW_IMPL: &str = "impl";
const KW_IN: &str = "in";
const KW_LET: &str = "let";
const KW_LOOP: &str = "loop";
const KW_MATCH: &str = "match";
const KW_MOD: &str = "mod";
const KW_MOVE: &str = "move";
const KW_MUT: &str = "mut";
const KW_PUB: &str = "pub";
const KW_REF: &str = "ref";
const KW_RETURN: &str = "return";
const KW_SELFVALUE: &str = "self";
const KW_SELFTYPE: &str = "Self";
const KW_STATIC: &str = "static";
const KW_STRUCT: &str = "struct";
const KW_SUPER: &str = "super";
const KW_TRAIT: &str = "trait";
const KW_TRUE: &str = "true";
const KW_TYPE: &str = "type";
const KW_UNSAFE: &str = "unsafe";
const KW_USE: &str = "use";
const KW_WHERE: &str = "where";
const KW_WHILE: &str = "while";

const KEYWORDS_STRICT: [&str] = [
KW_AS,
KW_BREAK,
KW_CONST,
KW_CONTINUE,
KW_CRATE,
KW_ELSE,
KW_ENUM,
KW_EXTERN,
KW_FALSE,
KW_FN,
KW_FOR,
KW_IF,
KW_IMPL,
KW_IN,
KW_LET,
KW_LOOP,
KW_MATCH,
KW_MOD,
KW_MOVE,
KW_MUT,
KW_PUB,
KW_REF,
KW_RETURN,
KW_SELFVALUE,
KW_SELFTYPE,
KW_STATIC,
KW_STRUCT,
KW_SUPER,
KW_TRAIT,
KW_TRUE,
KW_TYPE,
KW_UNSAFE,
KW_USE,
KW_WHERE,
KW_WHILE,
];
2 changes: 1 addition & 1 deletion src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ mod r#impl;
mod r#struct;
mod r#trait;
mod r#type;

mod type_alias;

pub use associated_type::*;
pub use block::*;
Expand Down
20 changes: 19 additions & 1 deletion src/scope.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use std::fmt::{self, Write};
use std::fmt::{self, Debug, Write};

use indexmap::IndexMap;

Expand All @@ -13,6 +13,7 @@ use crate::r#enum::Enum;
use crate::r#impl::Impl;
use crate::r#struct::Struct;
use crate::r#trait::Trait;
use crate::type_alias::TypeAlias;

/// Defines a scope.
///
Expand Down Expand Up @@ -219,6 +220,22 @@ impl Scope {
self
}

/// Push a new `TypeAlias`, returning a mutable reference to it.
pub fn new_type_alias(&mut self, name: &str, target: &str) -> &mut TypeAlias {
self.push_type_alias(TypeAlias::new(name, target));

match *self.items.last_mut().unwrap() {
Item::TypeAlias(ref mut v) => v,
_ => unreachable!(),
}
}

/// Push an `TypeAlias`.
pub fn push_type_alias(&mut self, item: TypeAlias) -> &mut Self {
self.items.push(Item::TypeAlias(item));
self
}

/// Return a string representation of the scope.
pub fn to_string(&self) -> String {
let mut ret = String::new();
Expand Down Expand Up @@ -256,6 +273,7 @@ impl Scope {
Item::Raw(ref v) => {
write!(fmt, "{}\n", v)?;
}
Item::TypeAlias(ref v) => v.fmt(fmt)?,
}
}

Expand Down
87 changes: 87 additions & 0 deletions src/type_alias.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
use core::fmt;
use std::fmt::Write;

use crate::{type_def::TypeDef, Formatter, Type};

/// https://rust-lang.github.io/chalk/book/types/rust_types/alias.html#alias-types
#[derive(Debug, Clone)]
pub struct TypeAlias {
type_def: TypeDef,
ty: Type,
}

impl TypeAlias {
pub fn new(name: &str, ty: &str) -> Self {
Self {
type_def: TypeDef::new(name),
ty: Type::new(ty),
}
}
pub fn fmt(&self, fmt: &mut Formatter<'_>) -> fmt::Result {
self.type_def.fmt_head("type", &[], fmt)?;
write!(fmt, " = ")?;
self.ty.fmt(fmt)?;
write!(fmt, ";")?;
Ok(())
}

/// Returns a reference to the type
pub fn type_def(&self) -> &Type {
&self.type_def.ty
}

/// Set the TypeAliasure visibility.
pub fn vis(&mut self, vis: &str) -> &mut Self {
self.type_def.vis(vis);
self
}

/// Add a generic to the TypeAlias.
pub fn generic(&mut self, name: &str) -> &mut Self {
self.type_def.ty.generic(name);
self
}

/// Add a `where` bound to the TypeAlias.
pub fn bound<T>(&mut self, name: &str, ty: T) -> &mut Self
where
T: Into<Type>,
{
self.type_def.bound(name, ty);
self
}

/// Set the TypeAliasure documentation.
pub fn doc(&mut self, docs: &str) -> &mut Self {
self.type_def.doc(docs);
self
}

/// Add a new type that the TypeAlias should derive.
pub fn derive(&mut self, name: &str) -> &mut Self {
self.type_def.derive(name);
self
}

/// Specify lint attribute to supress a warning or error.
pub fn allow(&mut self, allow: &str) -> &mut Self {
self.type_def.allow(allow);
self
}

/// Specify representation.
pub fn repr(&mut self, repr: &str) -> &mut Self {
self.type_def.repr(repr);
self
}

/// Set the type alias's ty.
pub fn set_ty(&mut self, ty: Type) {
self.ty = ty;
}

/// Get a reference to the type alias's ty.
pub fn ty(&self) -> &Type {
&self.ty
}
}
13 changes: 13 additions & 0 deletions tests/codegen.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,19 @@ struct Foo {

assert_eq!(scope.to_string(), &expect[1..]);
}
#[test]
fn type_alias() {
let mut scope = Scope::new();

scope
.new_type_alias("hello", "world").vis("pub");

let expect = r#"
pub type hello = world;"#;

assert_eq!(scope.to_string(), &expect[1..]);
}


#[test]
fn struct_with_pushed_field() {
Expand Down