From b29118b8c33c0c1f28483848d20cd40fdb10110c Mon Sep 17 00:00:00 2001 From: Kampfkarren Date: Sat, 6 Jul 2024 13:39:28 -0700 Subject: [PATCH 01/10] full-moon 1.0.0 --- Cargo.lock | 34 +--- Cargo.toml | 2 +- selene-lib/Cargo.toml | 7 +- selene-lib/default_std/lua52.yml | 2 + selene-lib/default_std/lua53.yml | 2 + selene-lib/default_std/luau.yml | 2 + selene-lib/src/ast_util/mod.rs | 2 +- selene-lib/src/ast_util/scopes.rs | 16 +- selene-lib/src/ast_util/visit_nodes.rs | 2 +- selene-lib/src/lints/bad_string_escape.rs | 4 +- .../src/lints/high_cyclomatic_complexity.rs | 3 +- selene-lib/src/lints/mismatched_arg_count.rs | 8 +- selene-lib/src/lints/standard_library.rs | 4 +- .../src/lints/unbalanced_assignments.rs | 2 +- .../src/standard_library/lua_versions.rs | 89 ++++++++++ selene-lib/src/standard_library/mod.rs | 26 +++ selene/src/main.rs | 165 +++++++++++------- 17 files changed, 251 insertions(+), 119 deletions(-) create mode 100644 selene-lib/src/standard_library/lua_versions.rs diff --git a/Cargo.lock b/Cargo.lock index 3b8a6f39..4fa2f1a2 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -82,12 +82,6 @@ version = "0.21.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9d297deb1925b89f2ccc13d7635fa0714f12c87adce1c75356b39ca9b7178567" -[[package]] -name = "beef" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3a8241f3ebb85c056b509d4327ad0358fbbba6ffb340bf388f26350aeda225b1" - [[package]] name = "bitflags" version = "1.3.2" @@ -357,15 +351,14 @@ dependencies = [ [[package]] name = "full_moon" -version = "0.19.0" +version = "1.0.0-rc.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "24ef4f8ad0689d3a86bb483650422d72e6f79a37fdc83ed5426cafe96b776ce1" +checksum = "1c23cbff7830f7a5370221b5c073bafc74b5d9e8555873b1f153a41416837e4e" dependencies = [ "bytecount", "cfg-if", "derive_more", "full_moon_derive", - "logos", "paste", "serde", "smol_str", @@ -572,29 +565,6 @@ dependencies = [ "cfg-if", ] -[[package]] -name = "logos" -version = "0.12.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bf8b031682c67a8e3d5446840f9573eb7fe26efe7ec8d195c9ac4c0647c502f1" -dependencies = [ - "logos-derive", -] - -[[package]] -name = "logos-derive" -version = "0.12.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1d849148dbaf9661a6151d1ca82b13bb4c4c128146a88d05253b38d4e2f496c" -dependencies = [ - "beef", - "fnv", - "proc-macro2", - "quote", - "regex-syntax", - "syn", -] - [[package]] name = "loom" version = "0.5.6" diff --git a/Cargo.toml b/Cargo.toml index caf6734f..87304bb2 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -11,7 +11,7 @@ license = "MPL-2.0" repository = "https://github.com/Kampfkarren/selene" [workspace.dependencies] -full_moon = "0.19.0" +full_moon = "1.0.0-rc.5" toml = "0.7.2" # Do not update this without confirming profiling uses the same version of tracy-client as selene diff --git a/selene-lib/Cargo.toml b/selene-lib/Cargo.toml index 96f8ce6e..9dce1936 100644 --- a/selene-lib/Cargo.toml +++ b/selene-lib/Cargo.toml @@ -30,6 +30,11 @@ pretty_assertions = "1.3" termcolor = "1.2" [features] -default = ["roblox"] +default = ["lua52", "lua53", "lua54", "luajit", "roblox"] force_exhaustive_checks = [] + +lua52 = ["full_moon/lua52"] +lua53 = ["full_moon/lua53"] +lua54 = ["full_moon/lua54"] +luajit = ["full_moon/luajit"] roblox = ["full_moon/roblox"] diff --git a/selene-lib/default_std/lua52.yml b/selene-lib/default_std/lua52.yml index 8fae55e8..73eee76c 100644 --- a/selene-lib/default_std/lua52.yml +++ b/selene-lib/default_std/lua52.yml @@ -1,5 +1,7 @@ --- base: lua51 +lua_versions: + - lua52 globals: bit32.arshift: args: diff --git a/selene-lib/default_std/lua53.yml b/selene-lib/default_std/lua53.yml index 528dd2cd..581d3957 100644 --- a/selene-lib/default_std/lua53.yml +++ b/selene-lib/default_std/lua53.yml @@ -1,5 +1,7 @@ --- base: lua52 +lua_versions: + - lua53 globals: math.tointeger: args: diff --git a/selene-lib/default_std/luau.yml b/selene-lib/default_std/luau.yml index 0243c110..2f22d8e9 100644 --- a/selene-lib/default_std/luau.yml +++ b/selene-lib/default_std/luau.yml @@ -3,6 +3,8 @@ # Invalid (put in selene-lib/default_std/roblox_base.yml instead): CFrame.new(), Instance.new(), task.spawn() --- base: lua51 +lua_versions: + - luau globals: bit32.arshift: args: diff --git a/selene-lib/src/ast_util/mod.rs b/selene-lib/src/ast_util/mod.rs index 98690f26..bdaa6e76 100644 --- a/selene-lib/src/ast_util/mod.rs +++ b/selene-lib/src/ast_util/mod.rs @@ -51,7 +51,7 @@ pub fn is_vararg(expression: &ast::Expression) -> bool { if_chain::if_chain! { if let ast::Expression::Symbol(token) = expression; if let tokenizer::TokenType::Symbol { - symbol: tokenizer::Symbol::Ellipse, + symbol: tokenizer::Symbol::Ellipsis, } = token.token().token_type(); then { diff --git a/selene-lib/src/ast_util/scopes.rs b/selene-lib/src/ast_util/scopes.rs index dadcd47e..a0b3f742 100644 --- a/selene-lib/src/ast_util/scopes.rs +++ b/selene-lib/src/ast_util/scopes.rs @@ -339,8 +339,8 @@ impl ScopeVisitor { self.read_expression(rhs); } - ast::Expression::Function((name, _)) => { - self.read_name(name); + ast::Expression::Function(function_box) => { + self.read_name(&function_box.0); } ast::Expression::FunctionCall(call) => { @@ -357,7 +357,7 @@ impl ScopeVisitor { ast::Expression::Symbol(symbol) => { if *symbol.token_type() == (TokenType::Symbol { - symbol: Symbol::Ellipse, + symbol: Symbol::Ellipsis, }) { self.read_name(symbol); @@ -433,7 +433,7 @@ impl ScopeVisitor { if token.token_kind() == TokenKind::Identifier || *token.token_type() == (TokenType::Symbol { - symbol: Symbol::Ellipse, + symbol: Symbol::Ellipsis, }) { self.captured_references.insert(identifier); @@ -878,7 +878,7 @@ impl Visitor for ScopeVisitor { } #[cfg(feature = "roblox")] - fn visit_compound_assignment(&mut self, compound_assignment: &ast::types::CompoundAssignment) { + fn visit_compound_assignment(&mut self, compound_assignment: &ast::luau::CompoundAssignment) { self.read_var(compound_assignment.lhs()); self.read_expression(compound_assignment.rhs()); } @@ -911,7 +911,7 @@ impl Visitor for ScopeVisitor { self.current_scope().blocked.push(Cow::Borrowed("...")); for parameter in body.parameters() { - if let ast::Parameter::Ellipse(token) | ast::Parameter::Name(token) = parameter { + if let ast::Parameter::Ellipsis(token) | ast::Parameter::Name(token) = parameter { self.define_name(token, range(token)); } } @@ -1092,8 +1092,8 @@ impl Visitor for ScopeVisitor { } #[cfg(feature = "roblox")] - fn visit_type_info(&mut self, type_info: &ast::types::TypeInfo) { - if let ast::types::TypeInfo::Module { module, .. } = type_info { + fn visit_type_info(&mut self, type_info: &ast::luau::TypeInfo) { + if let ast::luau::TypeInfo::Module { module, .. } = type_info { self.read_name(module); } } diff --git a/selene-lib/src/ast_util/visit_nodes.rs b/selene-lib/src/ast_util/visit_nodes.rs index 163365ae..d993c15e 100644 --- a/selene-lib/src/ast_util/visit_nodes.rs +++ b/selene-lib/src/ast_util/visit_nodes.rs @@ -1,7 +1,7 @@ use full_moon::{ast::*, node::Node, tokenizer::TokenReference, visitors::Visitor}; #[cfg(feature = "roblox")] -use full_moon::ast::types::*; +use full_moon::ast::luau::*; pub(crate) trait NodeVisitor { fn visit_node(&mut self, node: &dyn Node, visitor_type: VisitorType); diff --git a/selene-lib/src/lints/bad_string_escape.rs b/selene-lib/src/lints/bad_string_escape.rs index dc4284ea..c9226210 100644 --- a/selene-lib/src/lints/bad_string_escape.rs +++ b/selene-lib/src/lints/bad_string_escape.rs @@ -107,8 +107,8 @@ impl Visitor for BadStringEscapeVisitor { fn visit_expression(&mut self, node: &ast::Expression) { if_chain::if_chain! { if let ast::Expression::String(token) = node; - if let tokenizer::TokenType::StringLiteral { literal, multi_line, quote_type } = token.token_type(); - if multi_line.is_none(); + if let tokenizer::TokenType::StringLiteral { literal, quote_type, .. } = token.token_type(); + if *quote_type != tokenizer::StringLiteralQuoteType::Brackets; then { let quote_type = *quote_type; let value_start = node.range().unwrap().0.bytes(); diff --git a/selene-lib/src/lints/high_cyclomatic_complexity.rs b/selene-lib/src/lints/high_cyclomatic_complexity.rs index adee8e28..695fb98a 100644 --- a/selene-lib/src/lints/high_cyclomatic_complexity.rs +++ b/selene-lib/src/lints/high_cyclomatic_complexity.rs @@ -400,7 +400,8 @@ impl Visitor for HighCyclomaticComplexityVisitor { } fn visit_expression(&mut self, expression: &ast::Expression) { - if let ast::Expression::Function((_, function_body)) = expression { + if let ast::Expression::Function(function_box) = expression { + let function_body = &function_box.1; let complexity = count_block_complexity(function_body.block(), 1); if complexity > self.config.maximum_complexity { self.positions.push(( diff --git a/selene-lib/src/lints/mismatched_arg_count.rs b/selene-lib/src/lints/mismatched_arg_count.rs index a22f0c88..a7a606f5 100644 --- a/selene-lib/src/lints/mismatched_arg_count.rs +++ b/selene-lib/src/lints/mismatched_arg_count.rs @@ -107,7 +107,7 @@ impl ParameterCount { )] match parameter { ast::Parameter::Name(_) => necessary_params += 1, - ast::Parameter::Ellipse(_) => { + ast::Parameter::Ellipsis(_) => { if necessary_params == 0 { return Self::Variable; } else { @@ -331,7 +331,8 @@ impl Visitor for MapFunctionDefinitionVisitor<'_> { .zip(local_assignment.expressions()); for (name_token, expression) in assignment_expressions { - if let ast::Expression::Function((_, function_body)) = expression { + if let ast::Expression::Function(function_box) = expression { + let function_body = &function_box.1; let identifier = range(name_token); if let Some(id) = self.find_variable(identifier) { @@ -346,7 +347,8 @@ impl Visitor for MapFunctionDefinitionVisitor<'_> { let assignment_expressions = assignment.variables().iter().zip(assignment.expressions()); for (var, expression) in assignment_expressions { - if let ast::Expression::Function((_, function_body)) = expression { + if let ast::Expression::Function(function_box) = expression { + let function_body = &function_box.1; let identifier = range(var); if let Some(reference) = self.find_reference(identifier) { diff --git a/selene-lib/src/lints/standard_library.rs b/selene-lib/src/lints/standard_library.rs index 6c4942c6..4ccdc2ac 100644 --- a/selene-lib/src/lints/standard_library.rs +++ b/selene-lib/src/lints/standard_library.rs @@ -76,7 +76,7 @@ fn get_argument_type(expression: &ast::Expression) -> Option Symbol::False => Some(ArgumentType::Bool.into()), Symbol::True => Some(ArgumentType::Bool.into()), Symbol::Nil => Some(ArgumentType::Nil.into()), - Symbol::Ellipse => Some(ArgumentType::Vararg.into()), + Symbol::Ellipsis => Some(ArgumentType::Vararg.into()), ref other => { unreachable!("TokenType::Symbol was not expected ({:?})", other) } @@ -532,7 +532,7 @@ impl Visitor for StandardLibraryVisitor<'_> { ast::Expression::Symbol(token_ref) => { if let TokenType::Symbol { symbol } = token_ref.token().token_type() { - if symbol == &full_moon::tokenizer::Symbol::Ellipse { + if symbol == &full_moon::tokenizer::Symbol::Ellipsis { maybe_more_arguments = true; } } diff --git a/selene-lib/src/lints/unbalanced_assignments.rs b/selene-lib/src/lints/unbalanced_assignments.rs index df1db4b2..e88f046a 100644 --- a/selene-lib/src/lints/unbalanced_assignments.rs +++ b/selene-lib/src/lints/unbalanced_assignments.rs @@ -94,7 +94,7 @@ fn expression_is_ellipsis(expression: &ast::Expression) -> bool { if let ast::Expression::Symbol(symbol) = expression { return *symbol.token_type() == TokenType::Symbol { - symbol: Symbol::Ellipse, + symbol: Symbol::Ellipsis, }; } diff --git a/selene-lib/src/standard_library/lua_versions.rs b/selene-lib/src/standard_library/lua_versions.rs new file mode 100644 index 00000000..6b1a6c5c --- /dev/null +++ b/selene-lib/src/standard_library/lua_versions.rs @@ -0,0 +1,89 @@ +use serde::{Deserialize, Serialize}; + +#[derive(Clone, Debug, PartialEq, Eq)] +pub enum LuaVersion { + Lua51, + Lua52, + Lua53, + Lua54, + Luau, + LuaJIT, + + Unknown(String), +} + +impl LuaVersion { + pub fn from_str(value: &str) -> Self { + match value { + "lua51" => Self::Lua51, + "lua52" => Self::Lua52, + "lua53" => Self::Lua53, + "lua54" => Self::Lua54, + "luau" => Self::Luau, + "luajit" => Self::LuaJIT, + _ => Self::Unknown(value.to_string()), + } + } + + pub fn to_str(&self) -> &str { + match self { + Self::Lua51 => "lua51", + Self::Lua52 => "lua52", + Self::Lua53 => "lua53", + Self::Lua54 => "lua54", + Self::Luau => "luau", + Self::LuaJIT => "luajit", + Self::Unknown(value) => value, + } + } + + pub fn to_lua_version(&self) -> Result { + match self { + Self::Lua51 => Ok(full_moon::ast::LuaVersion::lua51()), + + #[cfg(feature = "lua52")] + Self::Lua52 => Ok(full_moon::ast::LuaVersion::lua52()), + + #[cfg(feature = "lua53")] + Self::Lua53 => Ok(full_moon::ast::LuaVersion::lua53()), + + #[cfg(feature = "lua54")] + Self::Lua54 => Ok(full_moon::ast::LuaVersion::lua54()), + + #[cfg(feature = "roblox")] + Self::Luau => Ok(full_moon::ast::LuaVersion::luau()), + + #[cfg(feature = "luajit")] + Self::LuaJIT => Ok(full_moon::ast::LuaVersion::luajit()), + + Self::Unknown(value) => Err(LuaVersionError::Unknown(value)), + + #[allow(unreachable_patterns)] + _ => Err(LuaVersionError::FeatureNotEnabled(self.to_str())), + } + } +} + +pub enum LuaVersionError<'a> { + FeatureNotEnabled(&'a str), + Unknown(&'a str), +} + +impl Serialize for LuaVersion { + fn serialize(&self, serializer: S) -> Result + where + S: serde::Serializer, + { + serializer.serialize_str(self.to_str()) + } +} + +impl<'de> Deserialize<'de> for LuaVersion { + fn deserialize(deserializer: D) -> Result + where + D: serde::Deserializer<'de>, + { + let value = String::deserialize(deserializer)?; + Ok(Self::from_str(&value)) + } +} diff --git a/selene-lib/src/standard_library/mod.rs b/selene-lib/src/standard_library/mod.rs index 79ff08f5..1ad9cee5 100644 --- a/selene-lib/src/standard_library/mod.rs +++ b/selene-lib/src/standard_library/mod.rs @@ -1,3 +1,4 @@ +mod lua_versions; pub mod v1; mod v1_upgrade; @@ -15,6 +16,8 @@ use serde::{ Deserialize, Serialize, }; +pub use lua_versions::*; + lazy_static::lazy_static! { static ref ANY_TABLE: BTreeMap = { let mut map = BTreeMap::new(); @@ -117,6 +120,9 @@ pub struct StandardLibrary { #[serde(skip_serializing_if = "BTreeMap::is_empty")] pub structs: BTreeMap>, + #[serde(default)] + pub lua_versions: Vec, + /// Internal, used for the Roblox standard library #[serde(default)] #[serde(skip_serializing_if = "Option::is_none")] @@ -314,6 +320,11 @@ impl StandardLibrary { }), ); + // Intentionally not a merge, didn't seem valuable + if !other.lua_versions.is_empty() { + self.lua_versions = other.lua_versions; + } + self.globals = globals; } @@ -339,6 +350,21 @@ impl StandardLibrary { Some(std) } + + pub fn lua_version(&self) -> (full_moon::LuaVersion, Vec) { + let mut errors = Vec::new(); + + let mut lua_version = full_moon::LuaVersion::lua51(); + + for version in &self.lua_versions { + match version.to_lua_version() { + Ok(version) => lua_version |= version, + Err(error) => errors.push(error), + } + } + + (lua_version, errors) + } } macro_rules! names { diff --git a/selene/src/main.rs b/selene/src/main.rs index 610aeb8a..3e67e471 100644 --- a/selene/src/main.rs +++ b/selene/src/main.rs @@ -15,7 +15,8 @@ use codespan_reporting::{ }, term::DisplayStyle as CodespanDisplayStyle, }; -use selene_lib::{lints::Severity, *}; +use full_moon::LuaVersion; +use selene_lib::{lints::Severity, standard_library::LuaVersionError, *}; use structopt::{clap, StructOpt}; use termcolor::{Color, ColorChoice, ColorSpec, StandardStream, WriteColor}; use threadpool::ThreadPool; @@ -52,6 +53,7 @@ lazy_static::lazy_static! { static LINT_ERRORS: AtomicUsize = AtomicUsize::new(0); static LINT_WARNINGS: AtomicUsize = AtomicUsize::new(0); static PARSE_ERRORS: AtomicUsize = AtomicUsize::new(0); +static STANDARD_LIBRARY_ERRORS: AtomicUsize = AtomicUsize::new(0); fn get_color() -> ColorChoice { let lock = OPTIONS.read().unwrap(); @@ -178,7 +180,12 @@ fn emit_codespan_locked( emit_codespan(&mut stdout, files, diagnostic); } -fn read(checker: &Checker, filename: &Path, mut reader: R) { +fn read( + checker: &Checker, + filename: &Path, + lua_version: LuaVersion, + mut reader: R, +) { let mut buffer = Vec::new(); if let Err(error) = reader.read_to_end(&mut buffer) { error!( @@ -202,67 +209,75 @@ fn read(checker: &Checker, filename: &Path, mut rea let ast = { profiling::scope!("full_moon::parse"); - match full_moon::parse(&contents) { + match full_moon::parse_fallible(&contents, lua_version).into_result() { Ok(ast) => ast, - Err(error) => { - PARSE_ERRORS.fetch_add(1, Ordering::SeqCst); - - match error { - full_moon::Error::AstError(full_moon::ast::AstError::UnexpectedToken { - token, - additional, - }) => emit_codespan_locked( - &files, - &CodespanDiagnostic { - severity: CodespanSeverity::Error, - code: Some("parse_error".to_owned()), - message: format!("unexpected token `{token}`"), - labels: vec![CodespanLabel::primary( - source_id, - codespan::Span::new( - token.start_position().bytes() as u32, - token.end_position().bytes() as u32, - ), + Err(errors) => { + for error in errors { + PARSE_ERRORS.fetch_add(1, Ordering::SeqCst); + match error { + full_moon::Error::AstError(ast_error) => { + let token = ast_error.token(); + + emit_codespan_locked( + &files, + &CodespanDiagnostic { + severity: CodespanSeverity::Error, + code: Some("parse_error".to_owned()), + message: format!("unexpected token `{token}`"), + labels: vec![CodespanLabel::primary( + source_id, + codespan::Span::new( + token.start_position().bytes() as u32, + token.end_position().bytes() as u32, + ), + ) + .with_message(ast_error.error_message())], + notes: Vec::new(), + }, ) - .with_message(additional.unwrap_or_default())], - notes: Vec::new(), - }, - ), - full_moon::Error::TokenizerError(error) => emit_codespan_locked( - &files, - &CodespanDiagnostic { - severity: CodespanSeverity::Error, - code: Some("parse_error".to_owned()), - message: match error.error() { - full_moon::tokenizer::TokenizerErrorType::UnclosedComment => { - "unclosed comment".to_string() - } - full_moon::tokenizer::TokenizerErrorType::UnclosedString => { - "unclosed string".to_string() - } - full_moon::tokenizer::TokenizerErrorType::UnexpectedShebang => { - "unexpected shebang".to_string() - } - full_moon::tokenizer::TokenizerErrorType::UnexpectedToken( - character, - ) => { - format!("unexpected character {character}") - } - full_moon::tokenizer::TokenizerErrorType::InvalidSymbol(symbol) => { - format!("invalid symbol {symbol}") - } + } + + full_moon::Error::TokenizerError(error) => emit_codespan_locked( + &files, + &CodespanDiagnostic { + severity: CodespanSeverity::Error, + code: Some("parse_error".to_owned()), + message: match error.error() { + full_moon::tokenizer::TokenizerErrorType::UnclosedComment => { + "unclosed comment".to_string() + } + + full_moon::tokenizer::TokenizerErrorType::UnclosedString => { + "unclosed string".to_string() + } + + full_moon::tokenizer::TokenizerErrorType::UnexpectedToken( + character, + ) => { + format!("unexpected character {character}") + } + + full_moon::tokenizer::TokenizerErrorType::InvalidNumber => { + "invalid number".to_string() + } + + full_moon::tokenizer::TokenizerErrorType::InvalidSymbol( + symbol, + ) => { + format!("invalid symbol {symbol}") + } + }, + labels: vec![CodespanLabel::primary( + source_id, + codespan::Span::new( + error.position().bytes() as u32, + error.position().bytes() as u32, + ), + )], + notes: Vec::new(), }, - labels: vec![CodespanLabel::primary( - source_id, - codespan::Span::new( - error.position().bytes() as u32, - error.position().bytes() as u32, - ), - )], - notes: Vec::new(), - }, - ), - _ => error!("Error parsing {}: {}", filename.display(), error), + ), + } } return; @@ -376,10 +391,11 @@ fn read(checker: &Checker, filename: &Path, mut rea } } -fn read_file(checker: &Checker, filename: &Path) { +fn read_file(checker: &Checker, lua_version: LuaVersion, filename: &Path) { read( checker, filename, + lua_version, match fs::File::open(filename) { Ok(file) => file, Err(error) => { @@ -595,6 +611,21 @@ fn start(mut options: opts::Options) { } }; + let (lua_version, problems) = standard_library.lua_version(); + if !problems.is_empty() { + for problem in problems { + match problem { + LuaVersionError::FeatureNotEnabled(feature) => { + error!("lua version {feature} in standard library, but feature for it is not enabled"); + } + + LuaVersionError::Unknown(version) => { + error!("unknown lua version {version} in standard library"); + } + } + } + } + let checker = Arc::new(match Checker::new(config, standard_library) { Ok(checker) => checker, Err(error) => { @@ -608,7 +639,7 @@ fn start(mut options: opts::Options) { for filename in &options.files { if filename == "-" { let checker = Arc::clone(&checker); - pool.execute(move || read(&checker, Path::new("-"), io::stdin().lock())); + pool.execute(move || read(&checker, Path::new("-"), lua_version, io::stdin().lock())); continue; } @@ -622,7 +653,7 @@ fn start(mut options: opts::Options) { continue; } - pool.execute(move || read_file(&checker, Path::new(&filename))); + pool.execute(move || read_file(&checker, lua_version, Path::new(&filename))); } else if metadata.is_dir() { for pattern in &options.pattern { let glob = match glob::glob(&format!( @@ -646,7 +677,7 @@ fn start(mut options: opts::Options) { let checker = Arc::clone(&checker); - pool.execute(move || read_file(&checker, &path)); + pool.execute(move || read_file(&checker, lua_version, &path)); } Err(error) => { @@ -678,17 +709,19 @@ fn start(mut options: opts::Options) { pool.join(); - let (parse_errors, lint_errors, lint_warnings) = ( + let (parse_errors, lint_errors, lint_warnings, standard_library_errors) = ( PARSE_ERRORS.load(Ordering::SeqCst), LINT_ERRORS.load(Ordering::SeqCst), LINT_WARNINGS.load(Ordering::SeqCst), + STANDARD_LIBRARY_ERRORS.load(Ordering::SeqCst), ); if !options.luacheck && !options.no_summary { log_total(parse_errors, lint_errors, lint_warnings).ok(); } - let error_count = parse_errors + lint_errors + lint_warnings + pool.panic_count(); + let error_count = + parse_errors + lint_errors + lint_warnings + standard_library_errors + pool.panic_count(); if error_count > 0 { let lock = OPTIONS.read().unwrap(); let opts = lock.as_ref().unwrap(); From 18f23bb2d52e310946a134cdb81160cd2d7ece7f Mon Sep 17 00:00:00 2001 From: Kampfkarren Date: Sat, 6 Jul 2024 14:11:09 -0700 Subject: [PATCH 02/10] Update invalid_std_yaml --- selene/tests/validate_config/invalid_std_yaml/rich_output.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/selene/tests/validate_config/invalid_std_yaml/rich_output.txt b/selene/tests/validate_config/invalid_std_yaml/rich_output.txt index 571e3e62..abe87130 100644 --- a/selene/tests/validate_config/invalid_std_yaml/rich_output.txt +++ b/selene/tests/validate_config/invalid_std_yaml/rich_output.txt @@ -1,4 +1,4 @@ -error: failed to parse yml file `./tests/validate_config/invalid_std_yaml/std.yml`: unknown field `bad`, expected one of `base`, `name`, `globals`, `structs`, `last_updated`, `last_selene_version`, `roblox_classes` +error: failed to parse yml file `./tests/validate_config/invalid_std_yaml/std.yml`: unknown field `bad`, expected one of `base`, `name`, `globals`, `structs`, `lua_versions`, `last_updated`, `last_selene_version`, `roblox_classes` ┌─ std.yml:1:1 │ 1 │ bad: true From 9a5979c961ce1b6ed3a16575e3d381f39e13f231 Mon Sep 17 00:00:00 2001 From: Kampfkarren Date: Sat, 6 Jul 2024 15:18:09 -0700 Subject: [PATCH 03/10] Fix exhaustives --- selene-lib/src/lints/deprecated.rs | 21 ++++++----- selene-lib/src/lints/standard_library.rs | 48 ++++++++++++------------ 2 files changed, 37 insertions(+), 32 deletions(-) diff --git a/selene-lib/src/lints/deprecated.rs b/selene-lib/src/lints/deprecated.rs index 262557d3..86658c38 100644 --- a/selene-lib/src/lints/deprecated.rs +++ b/selene-lib/src/lints/deprecated.rs @@ -209,15 +209,18 @@ impl Visitor for DeprecatedVisitor<'_> { let call_suffix = suffixes.pop().unwrap(); let function_args = match call_suffix { - #[cfg_attr( - feature = "force_exhaustive_checks", - deny(non_exhaustive_omitted_patterns) - )] - ast::Suffix::Call(call) => match call { - ast::Call::AnonymousCall(args) => args, - ast::Call::MethodCall(method_call) => method_call.args(), - _ => return, - }, + ast::Suffix::Call(call) => + { + #[cfg_attr( + feature = "force_exhaustive_checks", + deny(non_exhaustive_omitted_patterns) + )] + match call { + ast::Call::AnonymousCall(args) => args, + ast::Call::MethodCall(method_call) => method_call.args(), + _ => return, + } + } _ => unreachable!("function_call.call_suffix != ast::Suffix::Call"), }; diff --git a/selene-lib/src/lints/standard_library.rs b/selene-lib/src/lints/standard_library.rs index 4ccdc2ac..703f278c 100644 --- a/selene-lib/src/lints/standard_library.rs +++ b/selene-lib/src/lints/standard_library.rs @@ -6,7 +6,7 @@ use crate::{ use std::convert::Infallible; use full_moon::{ - ast::{self, Ast}, + ast::{self, Ast, Expression}, node::Node, tokenizer::{Position, Symbol, TokenType}, visitors::Visitor, @@ -39,6 +39,17 @@ impl Lint for StandardLibraryLint { } } +fn same_type_if_equal(lhs: &Expression, rhs: &Expression) -> Option { + let lhs_type = get_argument_type(lhs); + let rhs_type = get_argument_type(rhs); + + if lhs_type == rhs_type { + lhs_type + } else { + None + } +} + // Returns the argument type of the expression if it can be constantly resolved // Otherwise, returns None // Only attempts to resolve constants @@ -57,6 +68,8 @@ fn get_argument_type(expression: &ast::Expression) -> Option ast::UnOp::Hash(_) => Some(ArgumentType::Number.into()), ast::UnOp::Minus(_) => get_argument_type(expression), ast::UnOp::Not(_) => Some(ArgumentType::Bool.into()), + #[cfg(feature = "lua53")] + ast::UnOp::Tilde(_) => get_argument_type(expression), _ => None, } } @@ -155,16 +168,17 @@ fn get_argument_type(expression: &ast::Expression) -> Option ast::BinOp::Plus(_) | ast::BinOp::Minus(_) | ast::BinOp::Star(_) - | ast::BinOp::Slash(_) => { - let lhs_type = get_argument_type(lhs); - let rhs_type = get_argument_type(rhs); - - if lhs_type == rhs_type { - lhs_type - } else { - None - } - } + | ast::BinOp::Slash(_) => same_type_if_equal(lhs, rhs), + + #[cfg(feature = "lua53")] + ast::BinOp::DoubleLessThan(_) + | ast::BinOp::DoubleGreaterThan(_) + | ast::BinOp::Ampersand(_) + | ast::BinOp::Tilde(_) + | ast::BinOp::Pipe(_) => same_type_if_equal(lhs, rhs), + + #[cfg(any(feature = "lua53", feature = "roblox"))] + ast::BinOp::DoubleSlash(_) => same_type_if_equal(lhs, rhs), ast::BinOp::Percent(_) => Some(ArgumentType::Number.into()), @@ -177,18 +191,6 @@ fn get_argument_type(expression: &ast::Expression) -> Option None } - #[cfg(feature = "roblox")] - ast::BinOp::DoubleSlash(_) => { - let lhs_type = get_argument_type(lhs); - let rhs_type = get_argument_type(rhs); - - if lhs_type == rhs_type { - lhs_type - } else { - None - } - } - _ => None, } } From 472ba69d1ad0940c414dd028418ef8eab41fe96c Mon Sep 17 00:00:00 2001 From: Kampfkarren Date: Sat, 6 Jul 2024 15:32:17 -0700 Subject: [PATCH 04/10] Fix from_str lint --- .../src/standard_library/lua_versions.rs | 36 ++++++++++++------- 1 file changed, 23 insertions(+), 13 deletions(-) diff --git a/selene-lib/src/standard_library/lua_versions.rs b/selene-lib/src/standard_library/lua_versions.rs index 6b1a6c5c..91f79a6a 100644 --- a/selene-lib/src/standard_library/lua_versions.rs +++ b/selene-lib/src/standard_library/lua_versions.rs @@ -1,3 +1,5 @@ +use std::str::FromStr; + use serde::{Deserialize, Serialize}; #[derive(Clone, Debug, PartialEq, Eq)] @@ -13,18 +15,6 @@ pub enum LuaVersion { } impl LuaVersion { - pub fn from_str(value: &str) -> Self { - match value { - "lua51" => Self::Lua51, - "lua52" => Self::Lua52, - "lua53" => Self::Lua53, - "lua54" => Self::Lua54, - "luau" => Self::Luau, - "luajit" => Self::LuaJIT, - _ => Self::Unknown(value.to_string()), - } - } - pub fn to_str(&self) -> &str { match self { Self::Lua51 => "lua51", @@ -64,6 +54,22 @@ impl LuaVersion { } } +impl FromStr for LuaVersion { + type Err = (); + + fn from_str(value: &str) -> Result { + match value { + "lua51" => Ok(Self::Lua51), + "lua52" => Ok(Self::Lua52), + "lua53" => Ok(Self::Lua53), + "lua54" => Ok(Self::Lua54), + "luau" => Ok(Self::Luau), + "luajit" => Ok(Self::LuaJIT), + _ => Err(()), + } + } +} + pub enum LuaVersionError<'a> { FeatureNotEnabled(&'a str), Unknown(&'a str), @@ -84,6 +90,10 @@ impl<'de> Deserialize<'de> for LuaVersion { D: serde::Deserializer<'de>, { let value = String::deserialize(deserializer)?; - Ok(Self::from_str(&value)) + if let Ok(version) = Self::from_str(&value) { + Ok(version) + } else { + Ok(Self::Unknown(value)) + } } } From bd4b410e2f93bce9f86bdbccaf6f8b3ec8ee6e56 Mon Sep 17 00:00:00 2001 From: Kampfkarren Date: Sat, 6 Jul 2024 15:38:28 -0700 Subject: [PATCH 05/10] Fix unused lints --- selene/src/roblox/api.rs | 25 +++++-------------------- selene/src/standard_library.rs | 4 ++-- 2 files changed, 7 insertions(+), 22 deletions(-) diff --git a/selene/src/roblox/api.rs b/selene/src/roblox/api.rs index ea55a880..937677b3 100644 --- a/selene/src/roblox/api.rs +++ b/selene/src/roblox/api.rs @@ -65,20 +65,13 @@ pub enum ApiMember { } #[derive(Deserialize)] -#[serde(rename_all = "PascalCase")] -pub struct ApiParameter { - pub default: Option, - #[serde(rename = "Type")] - pub parameter_type: ApiValueType, -} +pub struct ApiParameter {} #[derive(Debug)] pub enum ApiValueType { Class { name: String }, DataType { value: ApiDataType }, - Group { value: ApiGroupType }, - Primitive { value: ApiPrimitiveType }, - Other { name: String }, + Other, } impl<'de> Deserialize<'de> for ApiValueType { @@ -118,15 +111,7 @@ impl<'de> Visitor<'de> for ApiValueTypeVisitor { value: ApiDataType::deserialize(name.into_deserializer())?, }, - "Group" => ApiValueType::Group { - value: ApiGroupType::deserialize(name.into_deserializer())?, - }, - - "Primitive" => ApiValueType::Primitive { - value: ApiPrimitiveType::deserialize(name.into_deserializer())?, - }, - - _ => ApiValueType::Other { name }, + _ => ApiValueType::Other, }) } } @@ -167,7 +152,7 @@ pub enum ApiDataType { UDim, UDim2, - Other(String), + Other, } impl ApiDataType { @@ -198,7 +183,7 @@ impl<'de> Deserialize<'de> for ApiDataType { "UDim2" => ApiDataType::UDim2, "Vector2" => ApiDataType::Vector2, "Vector3" => ApiDataType::Vector3, - _ => ApiDataType::Other(string), + _ => ApiDataType::Other, }) } } diff --git a/selene/src/standard_library.rs b/selene/src/standard_library.rs index 3c455cf2..298f160e 100644 --- a/selene/src/standard_library.rs +++ b/selene/src/standard_library.rs @@ -41,10 +41,10 @@ pub enum StandardLibraryError { impl Display for StandardLibraryError { fn fmt(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { match self { - StandardLibraryError::BaseStd { name, .. } => { + StandardLibraryError::BaseStd { name, source } => { write!( formatter, - "failed to collect base standard library `{name}`", + "failed to collect base standard library `{name}`: {source}", ) } From 5993b7dbf2283b3bc464fa57539ea6f2f97bf4e3 Mon Sep 17 00:00:00 2001 From: Kampfkarren Date: Sat, 6 Jul 2024 16:00:35 -0700 Subject: [PATCH 06/10] Guess that's why I didn't have it --- selene/src/standard_library.rs | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/selene/src/standard_library.rs b/selene/src/standard_library.rs index 298f160e..005c6c25 100644 --- a/selene/src/standard_library.rs +++ b/selene/src/standard_library.rs @@ -12,7 +12,6 @@ use selene_lib::{ #[derive(Debug)] pub enum StandardLibraryError { BaseStd { - source: Box, name: String, }, @@ -41,10 +40,10 @@ pub enum StandardLibraryError { impl Display for StandardLibraryError { fn fmt(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { match self { - StandardLibraryError::BaseStd { name, source } => { + StandardLibraryError::BaseStd { name } => { write!( formatter, - "failed to collect base standard library `{name}`: {source}", + "failed to collect base standard library `{name}`", ) } @@ -201,7 +200,6 @@ fn from_name( if let Some(base) = collect_standard_library(config, base_name, directory, config_directory) .map_err(|error| StandardLibraryError::BaseStd { - source: Box::new(error), name: base_name.clone(), })? { From 49712b518f320bd266170ab46f31d1e27d5d68d3 Mon Sep 17 00:00:00 2001 From: Kampfkarren Date: Sat, 6 Jul 2024 16:00:58 -0700 Subject: [PATCH 07/10] Remove unused --- selene/src/standard_library.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/selene/src/standard_library.rs b/selene/src/standard_library.rs index 005c6c25..e91726b8 100644 --- a/selene/src/standard_library.rs +++ b/selene/src/standard_library.rs @@ -199,7 +199,7 @@ fn from_name( if let Some(base_name) = &library.base { if let Some(base) = collect_standard_library(config, base_name, directory, config_directory) - .map_err(|error| StandardLibraryError::BaseStd { + .map_err(|_| StandardLibraryError::BaseStd { name: base_name.clone(), })? { From 503161937b924adb7d841ba2696baa61f9d9ae52 Mon Sep 17 00:00:00 2001 From: Kampfkarren Date: Tue, 8 Oct 2024 19:59:38 -0700 Subject: [PATCH 08/10] Update to 1.0.0 --- Cargo.lock | 112 +++++++++++++++++++++++++++++++---------------------- Cargo.toml | 2 +- 2 files changed, 67 insertions(+), 47 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 4fa2f1a2..3fd0ec0a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -88,6 +88,15 @@ version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" +[[package]] +name = "borsh" +version = "1.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a6362ed55def622cddc70a4746a68554d7b687713770de539e59a739b249f8ed" +dependencies = [ + "cfg_aliases", +] + [[package]] name = "bstr" version = "1.1.0" @@ -122,6 +131,12 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" +[[package]] +name = "cfg_aliases" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724" + [[package]] name = "chrono" version = "0.4.23" @@ -200,12 +215,6 @@ dependencies = [ "tracing-error", ] -[[package]] -name = "convert_case" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6245d59a3e82a7fc217c5828a6692dbc6dfb63a0c8c90495621f7b9d79704a0e" - [[package]] name = "core-foundation-sys" version = "0.8.3" @@ -228,7 +237,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6d2301688392eb071b0bf1a37be05c469d3cc4dbbd95df672fe28ab021e6a096" dependencies = [ "quote", - "syn", + "syn 1.0.107", ] [[package]] @@ -255,7 +264,7 @@ dependencies = [ "proc-macro2", "quote", "scratch", - "syn", + "syn 1.0.107", ] [[package]] @@ -272,20 +281,28 @@ checksum = "39e61fda7e62115119469c7b3591fd913ecca96fb766cfd3f2e2502ab7bc87a5" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 1.0.107", ] [[package]] name = "derive_more" -version = "0.99.17" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4fb810d30a7c1953f91334de7244731fc3f3c10d7fe163338a35b9f640960321" +checksum = "4a9b99b9cbbe49445b21764dc0625032a89b145a2642e67603e1c936f5458d05" +dependencies = [ + "derive_more-impl", +] + +[[package]] +name = "derive_more-impl" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb7330aeadfbe296029522e6c40f315320aba36fc43a5b3632f3795348f3bd22" dependencies = [ - "convert_case", "proc-macro2", "quote", - "rustc_version", - "syn", + "syn 2.0.79", + "unicode-xid", ] [[package]] @@ -351,9 +368,9 @@ dependencies = [ [[package]] name = "full_moon" -version = "1.0.0-rc.5" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1c23cbff7830f7a5370221b5c073bafc74b5d9e8555873b1f153a41416837e4e" +checksum = "f0ed413ca670d8ec6c08d8a823975c8e14f2ada4d947f96bf7654312a72e114d" dependencies = [ "bytecount", "cfg-if", @@ -373,7 +390,7 @@ dependencies = [ "indexmap", "proc-macro2", "quote", - "syn", + "syn 1.0.107", ] [[package]] @@ -725,7 +742,7 @@ dependencies = [ "proc-macro-error-attr", "proc-macro2", "quote", - "syn", + "syn 1.0.107", "version_check", ] @@ -742,9 +759,9 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.66" +version = "1.0.87" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "18fb31db3f9bddb2ea821cde30a9f70117e3f119938b5ee630b7403aa6e2ead9" +checksum = "b3e4daa0dcf6feba26f985457cdf104d4b4256fc5a09547140f3631bb076b19a" dependencies = [ "unicode-ident", ] @@ -766,14 +783,14 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7a1e2417ef905b8ad94215f8a607bd2d0f5d13d416d18dca4a530811e8a0674c" dependencies = [ "quote", - "syn", + "syn 1.0.107", ] [[package]] name = "quote" -version = "1.0.23" +version = "1.0.37" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8856d8364d252a14d474036ea1358d63c9e6965c8e5c1885c18f73d70bff9c7b" +checksum = "b5b9d34b8991d19d98081b46eacdd8eb58c6f2b201139f7c5f643cc155a633af" dependencies = [ "proc-macro2", ] @@ -844,15 +861,6 @@ version = "0.1.21" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7ef03e0a2b150c7a90d01faf6254c9c48a41e95fb2a8c2ac1c6f0d2b9aefc342" -[[package]] -name = "rustc_version" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366" -dependencies = [ - "semver", -] - [[package]] name = "rustls" version = "0.21.10" @@ -961,12 +969,6 @@ dependencies = [ "toml", ] -[[package]] -name = "semver" -version = "1.0.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "58bc9567378fc7690d6b2addae4e60ac2eeea07becb2c64b9f218b53865cba2a" - [[package]] name = "serde" version = "1.0.152" @@ -984,7 +986,7 @@ checksum = "af487d118eecd09402d70a5d72551860e788df87b464af30e5ea6a38c75c541e" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 1.0.107", ] [[package]] @@ -1037,10 +1039,11 @@ checksum = "a507befe795404456341dfab10cef66ead4c041f62b8b11bbb92bffe5d0953e0" [[package]] name = "smol_str" -version = "0.1.23" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7475118a28b7e3a2e157ce0131ba8c5526ea96e90ee601d9f6bb2e286a35ab44" +checksum = "66eaf762c5af19db3108300515c8aa7a50efc90ff745f4c62288052ebf9fdd25" dependencies = [ + "borsh", "serde", ] @@ -1077,7 +1080,7 @@ dependencies = [ "proc-macro-error", "proc-macro2", "quote", - "syn", + "syn 1.0.107", ] [[package]] @@ -1091,6 +1094,17 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "syn" +version = "2.0.79" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "89132cd0bf050864e1d38dc3bbc07a0eb8e7530af26344d3d2bbbef83499f590" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + [[package]] name = "termcolor" version = "1.2.0" @@ -1126,7 +1140,7 @@ checksum = "1fb327af4685e4d03fa8cbcf1716380da910eeb2bb8be417e7f9fd3fb164f36f" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 1.0.107", ] [[package]] @@ -1227,7 +1241,7 @@ checksum = "4017f8f45139870ca7e672686113917c71c7a6e02d4924eda67186083c03081a" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 1.0.107", ] [[package]] @@ -1332,6 +1346,12 @@ version = "0.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c0edd1e5b14653f783770bce4a4dabb4a5108a5370a5f5d8cfe8710c361f6c8b" +[[package]] +name = "unicode-xid" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853" + [[package]] name = "unsafe-libyaml" version = "0.2.5" @@ -1424,7 +1444,7 @@ dependencies = [ "once_cell", "proc-macro2", "quote", - "syn", + "syn 1.0.107", "wasm-bindgen-shared", ] @@ -1446,7 +1466,7 @@ checksum = "07bc0c051dc5f23e307b13285f9d75df86bfdf816c5721e573dec1f9b8aa193c" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 1.0.107", "wasm-bindgen-backend", "wasm-bindgen-shared", ] diff --git a/Cargo.toml b/Cargo.toml index 87304bb2..9a1a5699 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -11,7 +11,7 @@ license = "MPL-2.0" repository = "https://github.com/Kampfkarren/selene" [workspace.dependencies] -full_moon = "1.0.0-rc.5" +full_moon = "1.0.0" toml = "0.7.2" # Do not update this without confirming profiling uses the same version of tracy-client as selene From e2fb91980f31fc010d11adfa90a93c4e847f9443 Mon Sep 17 00:00:00 2001 From: Kampfkarren Date: Tue, 8 Oct 2024 20:03:56 -0700 Subject: [PATCH 09/10] Update to v4 of actions --- .github/workflows/build.yml | 32 +++++++++++------------ .github/workflows/generate-roblox-std.yml | 4 +-- 2 files changed, 18 insertions(+), 18 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 760b6692..03c2a1a1 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -10,33 +10,33 @@ jobs: build_windows: runs-on: windows-latest steps: - - uses: actions/checkout@v1 + - uses: actions/checkout@v4 - name: Build (Default features) run: | cd selene cargo build --locked --release - name: Upload selene - uses: actions/upload-artifact@v1 + uses: actions/upload-artifact@v4 with: name: selene-windows path: ./target/release/selene.exe build_windows_light: runs-on: windows-latest steps: - - uses: actions/checkout@v1 + - uses: actions/checkout@v4 - name: Build (Lightweight) run: | cd selene cargo build --locked --release --verbose --no-default-features - name: Upload selene-light - uses: actions/upload-artifact@v1 + uses: actions/upload-artifact@v4 with: name: selene-light-windows path: ./target/release/selene.exe build_mac: runs-on: macos-latest steps: - - uses: actions/checkout@v1 + - uses: actions/checkout@v4 - name: Install Rust run: curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y - name: Build (Default features) @@ -45,14 +45,14 @@ jobs: cd selene cargo build --locked --release - name: Upload selene - uses: actions/upload-artifact@v1 + uses: actions/upload-artifact@v4 with: name: selene-macos path: ./target/release/selene build_mac_light: runs-on: macos-latest steps: - - uses: actions/checkout@v1 + - uses: actions/checkout@v4 - name: Install Rust run: curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y - name: Build (Lightweight) @@ -61,20 +61,20 @@ jobs: cd selene cargo build --locked --release --verbose --no-default-features - name: Upload selene-light - uses: actions/upload-artifact@v1 + uses: actions/upload-artifact@v4 with: name: selene-light-macos path: ./target/release/selene build_linux: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v1 + - uses: actions/checkout@v4 - name: Build (Default features) run: | cd selene cargo build --locked --release - name: Upload selene - uses: actions/upload-artifact@v1 + uses: actions/upload-artifact@v4 with: name: selene-linux path: ./target/release/selene @@ -86,20 +86,20 @@ jobs: command: build args: --locked --release --target aarch64-unknown-linux-gnu - name: Upload selene arm64 - uses: actions/upload-artifact@v1 + uses: actions/upload-artifact@v4 with: name: selene-linux-aarch64 path: ./target/aarch64-unknown-linux-gnu/release/selene build_linux_light: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v1 + - uses: actions/checkout@v4 - name: Build (Lightweight) run: | cd selene cargo build --locked --release --verbose --no-default-features - name: Upload selene-light - uses: actions/upload-artifact@v1 + uses: actions/upload-artifact@v4 with: name: selene-light-linux path: ./target/release/selene @@ -111,7 +111,7 @@ jobs: command: build args: --locked --release --verbose --no-default-features --target aarch64-unknown-linux-gnu - name: Upload selene-light arm64 - uses: actions/upload-artifact@v1 + uses: actions/upload-artifact@v4 with: name: selene-light-linux-aarch64 path: ./target/aarch64-unknown-linux-gnu/release/selene @@ -120,7 +120,7 @@ jobs: needs: ['build_windows_light', 'build_windows', 'build_mac', 'build_mac_light', 'build_linux', 'build_linux_light'] if: contains(github.event.head_commit.message, '[release]') steps: - - uses: actions/checkout@v1 + - uses: actions/checkout@v4 - name: Download artifacts uses: actions/download-artifact@v2 with: @@ -208,7 +208,7 @@ jobs: asset_path: ./selene-light-macos.zip asset_name: selene-light-${{ env.VERSION }}-macos.zip asset_content_type: application/zip - - uses: actions/checkout@v1 + - uses: actions/checkout@v4 - name: Log in to Docker Hub uses: docker/login-action@v1 with: diff --git a/.github/workflows/generate-roblox-std.yml b/.github/workflows/generate-roblox-std.yml index ad12177e..f9e1c1db 100644 --- a/.github/workflows/generate-roblox-std.yml +++ b/.github/workflows/generate-roblox-std.yml @@ -4,11 +4,11 @@ jobs: generate: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v1 + - uses: actions/checkout@v4 - name: Generate run: cargo run --bin selene --verbose -- generate-roblox-std - name: Upload - uses: actions/upload-artifact@v1 + uses: actions/upload-artifact@v4 with: name: roblox path: roblox.yml \ No newline at end of file From a24f949da85d1af7973b04d89414955b2791ce5d Mon Sep 17 00:00:00 2001 From: Kampfkarren Date: Tue, 8 Oct 2024 20:19:59 -0700 Subject: [PATCH 10/10] Docs and changelog --- CHANGELOG.md | 4 ++++ docs/src/usage/std.md | 23 ++++++++++++++++++++++- 2 files changed, 26 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0e6a62ce..8184176e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,10 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm ## [Unreleased](https://github.com/Kampfkarren/selene/compare/0.27.1...HEAD) ### Added - Added `Path2DControlPoint.new` to the Roblox standard library +- [Adds `lua_versions` to standard library definitions](https://kampfkarren.github.io/selene/usage/std.html#lua_versions). Specifying this will only allow the syntax used by those languages. The default standard libraries now specify these, meaning that invalid syntax for that language will no longer be supported. + +### Changed +- Upgrades to [full-moon 1.0.0](https://github.com/Kampfkarren/full-moon/blob/main/CHANGELOG.md#100---2024-10-08), which should provide faster parse speeds, support for multiple parsing errors at the same time, and support for some new Luau syntax. ## [0.27.1](https://github.com/Kampfkarren/selene/releases/tag/0.27.1) - 2024-04-28 ### Fixed diff --git a/docs/src/usage/std.md b/docs/src/usage/std.md index 70f21a80..7a23ed99 100644 --- a/docs/src/usage/std.md +++ b/docs/src/usage/std.md @@ -9,13 +9,34 @@ For examples of the standard library format, see: ## base -Used for specifying what standard library to be based off of. This supports both builtin libraries (lua51, lua52, lua53, roblox), as well as any standard libraries that can be found in the current directory. +Used for specifying what standard library to be based off of. This supports both builtin libraries (lua51, lua52, lua53, lua54, roblox), as well as any standard libraries that can be found in the current directory. ```yaml --- # This begins a YAML file base: lua51 # We will be extending off of Lua 5.1. ``` +## lua_versions + +Used for specifying the versions of Lua you support for the purpose of supporting the syntax of those dialects. If empty, will default to 5.1. + +Supports the following options: +- `lua51` - Lua 5.1 +- `lua52` - Lua 5.2 +- `lua53` - Lua 5.3 +- `lua54` - Lua 5.4 +- `luau` - [Luau](https://luau-lang.org) +- `luajit` - LuaJIT + +Usually you only need to specify one--for example, `lua54` will give Lua 5.4 syntax and all versions prior. That means that if you specify it, it will look something like: + +```yml +lua_versions: +- luajit +``` + +If you are extending off a library that specifies it (like `lua51`, etc) then you do not need this. If you specify it while overriding a library, it will override it. + ## globals This is where the magic happens. The `globals` field is a dictionary where the keys are the globals you want to define. The value you give tells selene what the value can be, do, and provide.