Skip to content
Merged
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
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Luau: Added support for parsing attributes (`@native` / `@deprecated`) on functions
- Added support for CfxLua (FiveM) syntax formatting. This is available with `syntax = "cfxlua"` ([#855](https://github.com/JohnnyMorganz/StyLua/issues/855))
- Added a pre-built binary release for `stylua-linux-aarch64-musl.zip`
- Added error hints on parse failurse when a potential Lua syntax conflict is noticed (e.g., Lua 5.2 vs Luau syntax for labels `::` and generics `>>`) ([#960](https://github.com/JohnnyMorganz/StyLua/issues/960) / [#962](https://github.com/JohnnyMorganz/StyLua/issues/962))

### Changed

Expand Down
46 changes: 45 additions & 1 deletion src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
use context::Context;
use full_moon::ast::Ast;
#[cfg(all(feature = "luau", any(feature = "lua52", feature = "lua53")))]
use full_moon::tokenizer::{Symbol, TokenType};
use serde::Deserialize;
use thiserror::Error;
#[cfg(all(target_arch = "wasm32", feature = "wasm-bindgen"))]
Expand Down Expand Up @@ -299,6 +301,29 @@ pub enum OutputVerification {
None,
}

#[cfg(all(feature = "luau", feature = "lua53"))]
fn is_luau_and_lua53_conflict(error: &full_moon::Error) -> bool {
match error {
full_moon::Error::AstError(ast_error) => match ast_error.token().token_type() {
TokenType::Symbol {
symbol: Symbol::DoubleGreaterThan,
} => ast_error.error_message() == "expected '>' to close generic type parameter list",
_ => false,
},
_ => false,
}
}

#[cfg(all(feature = "luau", feature = "lua52"))]
fn is_luau_and_lua52_conflict(error: &full_moon::Error) -> bool {
match error {
full_moon::Error::AstError(ast_error) => {
ast_error.error_message() == "expected label name after `::`"
}
_ => false,
}
}

fn print_full_moon_error(error: &full_moon::Error) -> String {
match error {
full_moon::Error::AstError(ast_error) => format!(
Expand All @@ -315,14 +340,33 @@ fn print_full_moon_error(error: &full_moon::Error) -> String {
}

fn print_full_moon_errors(errors: &[full_moon::Error]) -> String {
if errors.len() == 1 {
#[allow(unused_mut)]
let mut error_message = if errors.len() == 1 {
print_full_moon_error(errors.first().unwrap())
} else {
errors
.iter()
.map(|err| "\n - ".to_string() + &print_full_moon_error(err))
.collect::<String>()
};

#[cfg(all(feature = "luau", feature = "lua53"))]
{
let recommend_luau_syntax = errors.iter().any(is_luau_and_lua53_conflict);
if recommend_luau_syntax {
error_message += "\nhint: this looks like a conflict with Lua 5.3 and Luau generics syntax, add `syntax = \"Luau\"` to stylua.toml to resolve";
}
}

#[cfg(all(feature = "luau", feature = "lua52"))]
{
let recommend_lua52_syntax = errors.iter().any(is_luau_and_lua52_conflict);
if recommend_lua52_syntax {
error_message += "\nhint: this looks like a conflict with Luau and Lua 5.2 label syntax, add `syntax = \"Lua52\"` to stylua.toml to resolve";
}
}

error_message
}

/// A formatting error
Expand Down
27 changes: 27 additions & 0 deletions tests/test_hint_syntax_config.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
#[cfg(all(feature = "luau", any(feature = "lua52", feature = "lua53")))]
use stylua_lib::{format_code, Config, OutputVerification};

#[test]
#[cfg(all(feature = "luau", feature = "lua53"))]
fn test_hint_syntax_luau_for_generic_parameter_list() {
let code = r#"
export type Foo = A<B<C>>
"#;
let result = format_code(code, Config::default(), None, OutputVerification::None);
let error = result.unwrap_err().to_string();
assert!(error.ends_with("hint: this looks like a conflict with Lua 5.3 and Luau generics syntax, add `syntax = \"Luau\"` to stylua.toml to resolve"));
}

#[test]
#[cfg(all(feature = "luau", feature = "lua52"))]
fn test_hint_syntax_lua52_for_labels() {
let code = r#"
do
local x = 1
::continue::
end
"#;
let result = format_code(code, Config::default(), None, OutputVerification::None);
let error = result.unwrap_err().to_string();
assert!(error.ends_with("hint: this looks like a conflict with Luau and Lua 5.2 label syntax, add `syntax = \"Lua52\"` to stylua.toml to resolve"));
}