Change ScriptFnMetadata to hold references.

This commit is contained in:
Stephen Chung 2020-12-18 16:31:44 +08:00
parent 719f0babbf
commit 882b26d2a1
4 changed files with 44 additions and 35 deletions

View File

@ -83,8 +83,8 @@ pub struct ScriptFnDef {
/// Access to external variables. /// Access to external variables.
#[cfg(not(feature = "no_closure"))] #[cfg(not(feature = "no_closure"))]
pub externals: Vec<ImmutableString>, pub externals: Vec<ImmutableString>,
/// Comment block for function. /// Function doc-comments (if any).
pub fn_comments: Vec<String>, pub comments: Vec<String>,
} }
impl fmt::Display for ScriptFnDef { impl fmt::Display for ScriptFnDef {
@ -107,16 +107,29 @@ impl fmt::Display for ScriptFnDef {
} }
} }
/// A type containing a script-defined function's metadata. /// A type containing the metadata of a script-defined function.
#[derive(Debug, Clone, Hash)] ///
pub struct ScriptFnMetadata { /// Created by [`AST::iter_functions`].
pub comments: Vec<String>, #[derive(Debug, Eq, PartialEq, Clone, Hash)]
pub struct ScriptFnMetadata<'a> {
/// Function doc-comments (if any).
///
/// Block doc-comments are kept in a single string slice with line-breaks within.
///
/// Line doc-comments are kept in one string slice per line without the termination line-break.
///
/// Leading white-spaces are stripped, and each string slice always starts with the corresponding
/// doc-comment leader: `///` or `/**`.
pub comments: Vec<&'a str>,
/// Function access mode.
pub access: FnAccess, pub access: FnAccess,
pub fn_name: ImmutableString, /// Function name.
pub params: Vec<ImmutableString>, pub name: &'a str,
/// Function parameters (if any).
pub params: Vec<&'a str>,
} }
impl fmt::Display for ScriptFnMetadata { impl fmt::Display for ScriptFnMetadata<'_> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!( write!(
f, f,
@ -126,23 +139,19 @@ impl fmt::Display for ScriptFnMetadata {
} else { } else {
"" ""
}, },
self.fn_name, self.name,
self.params self.params.iter().cloned().collect::<Vec<_>>().join(", ")
.iter()
.map(|p| p.as_str())
.collect::<Vec<_>>()
.join(", ")
) )
} }
} }
impl Into<ScriptFnMetadata> for &ScriptFnDef { impl<'a> Into<ScriptFnMetadata<'a>> for &'a ScriptFnDef {
fn into(self) -> ScriptFnMetadata { fn into(self) -> ScriptFnMetadata<'a> {
ScriptFnMetadata { ScriptFnMetadata {
comments: self.fn_comments.clone(), comments: self.comments.iter().map(|s| s.as_str()).collect(),
access: self.access, access: self.access,
fn_name: self.name.clone(), name: &self.name,
params: self.params.iter().cloned().collect(), params: self.params.iter().map(|s| s.as_str()).collect(),
} }
} }
} }
@ -538,7 +547,7 @@ impl AST {
} }
self self
} }
/// Iterate through all functions /// Iterate through all function definitions.
#[cfg(not(feature = "no_function"))] #[cfg(not(feature = "no_function"))]
#[inline(always)] #[inline(always)]
pub fn iter_functions<'a>(&'a self) -> impl Iterator<Item = ScriptFnMetadata> + 'a { pub fn iter_functions<'a>(&'a self) -> impl Iterator<Item = ScriptFnMetadata> + 'a {

View File

@ -503,7 +503,7 @@ impl Clone for Dynamic {
/// ///
/// ## WARNING /// ## WARNING
/// ///
/// The cloned copy is marked [`AccessType::Normal`] even if the original is constant. /// The cloned copy is marked read-write even if the original is read-only.
fn clone(&self) -> Self { fn clone(&self) -> Self {
match self.0 { match self.0 {
Union::Unit(value, _) => Self(Union::Unit(value, AccessMode::ReadWrite)), Union::Unit(value, _) => Self(Union::Unit(value, AccessMode::ReadWrite)),

View File

@ -868,7 +868,7 @@ pub fn optimize_into_ast(
lib: None, lib: None,
#[cfg(not(feature = "no_module"))] #[cfg(not(feature = "no_module"))]
mods: Default::default(), mods: Default::default(),
fn_comments: Default::default(), comments: Default::default(),
}) })
.for_each(|fn_def| { .for_each(|fn_def| {
lib2.set_script_fn(fn_def); lib2.set_script_fn(fn_def);

View File

@ -2409,14 +2409,14 @@ fn parse_stmt(
) -> Result<Option<Stmt>, ParseError> { ) -> Result<Option<Stmt>, ParseError> {
use AccessMode::{ReadOnly, ReadWrite}; use AccessMode::{ReadOnly, ReadWrite};
let mut fn_comments: Vec<String> = Default::default(); let mut comments: Vec<String> = Default::default();
let mut fn_comments_pos = Position::NONE; let mut comments_pos = Position::NONE;
// Handle doc-comment. // Handle doc-comments.
#[cfg(not(feature = "no_function"))] #[cfg(not(feature = "no_function"))]
while let (Token::Comment(ref comment), comment_pos) = input.peek().unwrap() { while let (Token::Comment(ref comment), comment_pos) = input.peek().unwrap() {
if fn_comments_pos.is_none() { if comments_pos.is_none() {
fn_comments_pos = *comment_pos; comments_pos = *comment_pos;
} }
if !is_doc_comment(comment) { if !is_doc_comment(comment) {
@ -2424,16 +2424,16 @@ fn parse_stmt(
} }
if !settings.is_global { if !settings.is_global {
return Err(PERR::WrongDocComment.into_err(fn_comments_pos)); return Err(PERR::WrongDocComment.into_err(comments_pos));
} }
if let Token::Comment(comment) = input.next().unwrap().0 { if let Token::Comment(comment) = input.next().unwrap().0 {
fn_comments.push(comment); comments.push(comment);
match input.peek().unwrap() { match input.peek().unwrap() {
(Token::Fn, _) | (Token::Private, _) => break, (Token::Fn, _) | (Token::Private, _) => break,
(Token::Comment(_), _) => (), (Token::Comment(_), _) => (),
_ => return Err(PERR::WrongDocComment.into_err(fn_comments_pos)), _ => return Err(PERR::WrongDocComment.into_err(comments_pos)),
} }
} else { } else {
unreachable!(); unreachable!();
@ -2492,7 +2492,7 @@ fn parse_stmt(
pos: pos, pos: pos,
}; };
let func = parse_fn(input, &mut new_state, lib, access, settings, fn_comments)?; let func = parse_fn(input, &mut new_state, lib, access, settings, comments)?;
// Qualifiers (none) + function name + number of arguments. // Qualifiers (none) + function name + number of arguments.
let hash = calc_script_fn_hash(empty(), &func.name, func.params.len()); let hash = calc_script_fn_hash(empty(), &func.name, func.params.len());
@ -2651,7 +2651,7 @@ fn parse_fn(
lib: &mut FunctionsLib, lib: &mut FunctionsLib,
access: FnAccess, access: FnAccess,
mut settings: ParseSettings, mut settings: ParseSettings,
fn_comments: Vec<String>, comments: Vec<String>,
) -> Result<ScriptFnDef, ParseError> { ) -> Result<ScriptFnDef, ParseError> {
#[cfg(not(feature = "unchecked"))] #[cfg(not(feature = "unchecked"))]
settings.ensure_level_within_max_limit(state.max_expr_depth)?; settings.ensure_level_within_max_limit(state.max_expr_depth)?;
@ -2737,7 +2737,7 @@ fn parse_fn(
lib: None, lib: None,
#[cfg(not(feature = "no_module"))] #[cfg(not(feature = "no_module"))]
mods: Default::default(), mods: Default::default(),
fn_comments, comments,
}) })
} }
@ -2894,7 +2894,7 @@ fn parse_anon_fn(
lib: None, lib: None,
#[cfg(not(feature = "no_module"))] #[cfg(not(feature = "no_module"))]
mods: Default::default(), mods: Default::default(),
fn_comments: Default::default(), comments: Default::default(),
}; };
let expr = Expr::FnPointer(fn_name, settings.pos); let expr = Expr::FnPointer(fn_name, settings.pos);