docs: enforce documentation on all public things

Signed-off-by: Charlotte Meyer <dev@buffet.sh>
This commit is contained in:
buffet 2023-01-16 15:33:52 +01:00
parent 009947fa29
commit cafd3cafe1
10 changed files with 83 additions and 2 deletions

View file

@ -1,4 +1,6 @@
//! Contains the proc macro used to define builtins.
#![deny(unreachable_pub)] #![deny(unreachable_pub)]
#![warn(missing_docs)]
use darling::FromMeta; use darling::FromMeta;
use proc_macro::TokenStream; use proc_macro::TokenStream;
@ -16,6 +18,20 @@ struct AttrArgs {
nofork: bool, nofork: bool,
} }
/// Define a built in with the given description and name.
///
/// ```rust
/// use oyster_builtin_proc::builtin;
///
/// #[builtin(
/// name = "greet", // optionally override name
/// description = "greets the user",
/// nofork = true, // optionally don't fork, required for cd and similar
/// )]
/// fn hello(_shell: &mut Shell, _args: &[Cow<OsStr>]) {
/// println!("Hello world!");
/// }
/// ```
#[proc_macro_attribute] #[proc_macro_attribute]
pub fn builtin(attr: TokenStream, item: TokenStream) -> TokenStream { pub fn builtin(attr: TokenStream, item: TokenStream) -> TokenStream {
let attrs = parse_macro_input!(attr as AttributeArgs); let attrs = parse_macro_input!(attr as AttributeArgs);
@ -49,7 +65,7 @@ pub fn builtin(attr: TokenStream, item: TokenStream) -> TokenStream {
}; };
TokenStream::from(quote! { TokenStream::from(quote! {
#[allow(non_upper_case_globals)] #[allow(non_upper_case_globals, missing_docs)]
#vis static #ident: #builtin = { #vis static #ident: #builtin = {
#fn_token #ident(#inputs) #block #fn_token #ident(#inputs) #block

View file

@ -1,7 +1,10 @@
//! Readline implementation used in oyster.
#![deny(unreachable_pub)] #![deny(unreachable_pub)]
#![warn(missing_docs)]
use std::io::{self, Write}; use std::io::{self, Write};
/// Read a line from stdin and return it.
pub fn readline(prompt: &str) -> Result<String, io::Error> { pub fn readline(prompt: &str) -> Result<String, io::Error> {
print!("{}", prompt); print!("{}", prompt);
io::stdout().flush()?; io::stdout().flush()?;

View file

@ -1,32 +1,46 @@
//! Defines the abstract syntax tree of a valid program.
use crate::{NodeKind, ParseError, ParseEvent, Parser}; use crate::{NodeKind, ParseError, ParseEvent, Parser};
/// Abtract, lossy representation of the syntax. /// Abtract, lossy representation of the syntax of an entire program.
#[derive(Debug)] #[derive(Debug)]
pub struct Code<'a>(pub Vec<Statement<'a>>); pub struct Code<'a>(pub Vec<Statement<'a>>);
/// A statement in a program.
#[derive(Debug)] #[derive(Debug)]
pub enum Statement<'a> { pub enum Statement<'a> {
/// See [Pipeline].
Pipeline(Pipeline<'a>), Pipeline(Pipeline<'a>),
} }
/// A pipeline consisting of multiple commands.
#[derive(Debug)] #[derive(Debug)]
pub struct Pipeline<'a>(pub Vec<Command<'a>>); pub struct Pipeline<'a>(pub Vec<Command<'a>>);
/// Redirects between commands in a [Pipeline].
#[derive(Debug, Clone, Copy)] #[derive(Debug, Clone, Copy)]
pub enum Redirect { pub enum Redirect {
/// No redirect.
None, None,
/// Stdout is getting redirected.
Stdout, Stdout,
} }
/// A command within a [Pipeline].
#[derive(Debug)] #[derive(Debug)]
pub struct Command<'a>(pub Vec<Word<'a>>, pub Redirect); pub struct Command<'a>(pub Vec<Word<'a>>, pub Redirect);
/// A word within a [Command].
#[derive(Debug)] #[derive(Debug)]
pub struct Word<'a>(pub Vec<WordPart<'a>>); pub struct Word<'a>(pub Vec<WordPart<'a>>);
/// Part of a [Word].
/// This can be anything from different parts of a quoted string, to escaped symbols, or even
/// subcommands.
#[derive(Debug)] #[derive(Debug)]
pub enum WordPart<'a> { pub enum WordPart<'a> {
/// Plain text.
Text(&'a str), Text(&'a str),
/// A command substitution that needs to be run first.
CommandSubstitution(Code<'a>), CommandSubstitution(Code<'a>),
} }

View file

@ -1,18 +1,30 @@
use crate::{NodeKind, ParseError, ParseEvent, Parser}; use crate::{NodeKind, ParseError, ParseEvent, Parser};
/// A concrete, loss-less representation of the parsed program. /// A concrete, loss-less representation of the parsed program.
/// Only leafs contain actual code.
#[derive(Debug)] #[derive(Debug)]
pub enum ParseTree { pub enum ParseTree {
/// A sub-tree in the program.
/// These do not contain data.
Tree { Tree {
/// What kind of node are we dealing with.
kind: NodeKind, kind: NodeKind,
/// The children of this tree.
children: Vec<ParseTree>, children: Vec<ParseTree>,
}, },
/// A leaf node.
/// This contains all the code snippets.
Leaf { Leaf {
/// What kind of node we are dealing with.
kind: NodeKind, kind: NodeKind,
/// The length of the code referred to by this node.
len: usize, len: usize,
}, },
/// A parse error occured.
Error { Error {
/// Which error occured.
kind: ParseError, kind: ParseError,
/// How much code to skip until recovery?
len: usize, len: usize,
}, },
} }

View file

@ -34,7 +34,10 @@ pub enum TokenKind {
/// The parser is responsible for getting that information, if required. /// The parser is responsible for getting that information, if required.
#[derive(Debug)] #[derive(Debug)]
pub struct Token { pub struct Token {
/// The [TokenKind] of the token.
pub kind: TokenKind, pub kind: TokenKind,
/// How long the token is.
/// To actually get the code, you need to keep count yourself.
pub len: usize, pub len: usize,
} }

View file

@ -1,4 +1,5 @@
#![deny(unreachable_pub)] #![deny(unreachable_pub)]
#![warn(missing_docs)]
//! Parser for the oyster shell, the grammar is outlined below, `extras` are allowed everywhere, //! Parser for the oyster shell, the grammar is outlined below, `extras` are allowed everywhere,
//! *except* inside `word`. //! *except* inside `word`.

View file

@ -4,6 +4,7 @@ use crate::{lexer::Lexer, Token, TokenKind};
/// Errors that might occur during parsing. /// Errors that might occur during parsing.
#[derive(Debug, Error)] #[derive(Debug, Error)]
#[allow(missing_docs)]
pub enum ParseError { pub enum ParseError {
#[error("unexpected pipe")] #[error("unexpected pipe")]
UnexpectedPipe, UnexpectedPipe,
@ -16,8 +17,12 @@ pub enum ParseError {
} }
/// Type of the node. /// Type of the node.
/// For specific information refer to [TokenKind].
#[derive(Debug)] #[derive(Debug)]
#[allow(missing_docs)]
pub enum NodeKind { pub enum NodeKind {
// TokenKinds
Whitespace, Whitespace,
Newlines, Newlines,
Semicolon, Semicolon,
@ -29,6 +34,8 @@ pub enum NodeKind {
EscapedChar, EscapedChar,
Comment, Comment,
// Nodes in the tree, that appear in the cst.
Program, Program,
CommandSubstitution, CommandSubstitution,
Pipeline, Pipeline,
@ -36,6 +43,8 @@ pub enum NodeKind {
Word, Word,
DQuotedString, DQuotedString,
// Nodes in the tree, that don't appear in the cst.
/// Read a pipe but didn't start word yet. /// Read a pipe but didn't start word yet.
PipelineCont, PipelineCont,
} }
@ -43,9 +52,14 @@ pub enum NodeKind {
/// Events required to build a syntax tree. /// Events required to build a syntax tree.
#[derive(Debug)] #[derive(Debug)]
pub enum ParseEvent { pub enum ParseEvent {
/// An error occured.
Error(ParseError, usize), Error(ParseError, usize),
/// Start a new tree node.
/// From now on, all nodes are child notes.
StartNode(NodeKind), StartNode(NodeKind),
/// End the most recently started tree node.
EndNode, EndNode,
/// A new leaf note.
NewLeaf(NodeKind, usize), NewLeaf(NodeKind, usize),
} }

View file

@ -1,3 +1,4 @@
//! Standard math builtins.
use std::{ use std::{
borrow::Cow, borrow::Cow,
ffi::OsStr, ffi::OsStr,

View file

@ -1,3 +1,4 @@
//! Definition of all the builtin builtins, and the general framework managing builtins.
pub mod math; pub mod math;
use std::{borrow::Cow, collections::HashMap, ffi::OsStr}; use std::{borrow::Cow, collections::HashMap, ffi::OsStr};
@ -6,11 +7,18 @@ use oyster_builtin_proc::builtin;
use crate::Shell; use crate::Shell;
/// Definition of a builtin.
/// See [oyster_builtin_proc::builtin] for an easier way to generate them.
#[derive(Clone, Copy)] #[derive(Clone, Copy)]
pub struct Builtin { pub struct Builtin {
/// Name of the builtin.
pub name: &'static str, pub name: &'static str,
/// Description of the builtin, used in `help`.
pub description: &'static str, pub description: &'static str,
/// Whether the builtin should fork when executed.
/// Should be false for most builtins.
pub nofork: bool, pub nofork: bool,
/// The actual function to call when the builtin runs.
pub fun: fn(shell: &mut Shell, args: &[Cow<OsStr>]), pub fun: fn(shell: &mut Shell, args: &[Cow<OsStr>]),
} }

View file

@ -1,4 +1,7 @@
//! The runtime of the shell.
//! This contains all the code related to actually running the program.
#![deny(unreachable_pub)] #![deny(unreachable_pub)]
#![warn(missing_docs)]
//! The runtime for executing oyster programs. //! The runtime for executing oyster programs.
//! Panics when an invalid ast gets passed. //! Panics when an invalid ast gets passed.
@ -33,14 +36,19 @@ use thiserror::Error;
pub struct Status(pub i32); pub struct Status(pub i32);
impl Status { impl Status {
/// The command succeeded.
pub const SUCCESS: Status = Status(0); pub const SUCCESS: Status = Status(0);
/// The command failed to execute (most likely permissions).
pub const COULD_NOT_EXEC: Status = Status(126); pub const COULD_NOT_EXEC: Status = Status(126);
/// The command could not be found.
pub const COMMAND_NOT_FOUND: Status = Status(127); pub const COMMAND_NOT_FOUND: Status = Status(127);
/// The base whch signals get added onto, i.e. SIGINT (2) results in 130.
pub const SIG_BASE: Status = Status(128); pub const SIG_BASE: Status = Status(128);
} }
/// Errors that occur during runtime. /// Errors that occur during runtime.
#[derive(Debug, Error)] #[derive(Debug, Error)]
#[allow(missing_docs)]
pub enum RuntimeError { pub enum RuntimeError {
#[error("failed to create pipe: {0}")] #[error("failed to create pipe: {0}")]
PipeCreationFailed(#[source] nix::Error), PipeCreationFailed(#[source] nix::Error),
@ -67,6 +75,7 @@ pub enum RuntimeError {
IOError(#[source] io::Error), IOError(#[source] io::Error),
} }
/// The main "app struct", containing all the data related to the current shell instance.
pub struct Shell { pub struct Shell {
is_running: bool, is_running: bool,
builtins: BuiltinMap, builtins: BuiltinMap,