diff --git a/Luau.YAML-tmLanguage b/Luau.YAML-tmLanguage
index fcc6017..4006755 100644
--- a/Luau.YAML-tmLanguage
+++ b/Luau.YAML-tmLanguage
@@ -12,8 +12,15 @@ fileTypes: [luau]
variables:
matchingParentheses: (\(([^\(\)]|(\(([^\(\)]|\([^\(\)]*\))*\)))*\))
- lookAheadEndOfType: '(?=[),}\]](?!\s*[&|]))|(?=\s*;)|(?=\s*\b(?:break|const|continue|do|else|elseif|end|for|function|if|in|local|repeat|return|then|until|while)\b)|(?=^\s*$)|(?=^\s*(?:@|\b(?:export\s+)?type\b))|(?=^\s*{{identifier}}(?:\.{{identifier}})*\s*(?:(?:[+\-*/%^]|\.\.)?=(?!=)|\(|\[|:))'
identifier: "[a-zA-Z_][a-zA-Z0-9_]*"
+ # Arithmetic/comparison operators that are valid in expressions but cannot appear at the
+ # top level of a Luau type expression, so their presence signals the end of a type.
+ # Exclusions: -> (function return type arrow), -- (comment), ... (variadic pack)
+ nonTypeOperators: '[*+%^]|\/\/?|(?`])|~=|=='
+ # Keywords that are valid outside a type expression (as binary operators or statement
+ # starters) but cannot appear within one, so their presence signals the end of a type.
+ nonTypeKeywords: 'and|or|break|const|continue|do|else|elseif|end|for|function|if|in|local|repeat|return|then|until|while'
+ lookAheadEndOfType: '(?=[),}\]](?!\s*[&|]))|(?=\s*;)|(?=\s*(?:{{nonTypeOperators}}))|(?=\s*\b(?:{{nonTypeKeywords}})\b)|(?=^\s*$)|(?=^\s*(?:@|\b(?:export\s+)?type\b))|(?=^\s*{{identifier}}(?:\.{{identifier}})*\s*(?:(?:[+\-*/%^]|\.\.)?=(?!=)|\(|\[|:))'
patterns:
- include: "#function-definition"
diff --git a/Luau.tmLanguage b/Luau.tmLanguage
index 8f71ba7..6d799da 100644
--- a/Luau.tmLanguage
+++ b/Luau.tmLanguage
@@ -1114,7 +1114,7 @@
begin
(?<![^.]\.|:)\b(?:(export)\s+)?(type)\b(?=\s+(?!function\b)[a-zA-Z_][a-zA-Z0-9_]*)
end
- (?=[),}\]](?!\s*[&|]))|(?=\s*;)|(?=\s*\b(?:break|const|continue|do|else|elseif|end|for|function|if|in|local|repeat|return|then|until|while)\b)|(?=^\s*$)|(?=^\s*(?:@|\b(?:export\s+)?type\b))|(?=^\s*[a-zA-Z_][a-zA-Z0-9_]*(?:\.[a-zA-Z_][a-zA-Z0-9_]*)*\s*(?:(?:[+\-*/%^]|\.\.)?=(?!=)|\(|\[|:))
+ (?=[),}\]](?!\s*[&|]))|(?=\s*;)|(?=\s*(?:[*+%^]|\/\/?|(?<!\.)\.\.(?!\.)|-(?![->`])|~=|==))|(?=\s*\b(?:and|or|break|const|continue|do|else|elseif|end|for|function|if|in|local|repeat|return|then|until|while)\b)|(?=^\s*$)|(?=^\s*(?:@|\b(?:export\s+)?type\b))|(?=^\s*[a-zA-Z_][a-zA-Z0-9_]*(?:\.[a-zA-Z_][a-zA-Z0-9_]*)*\s*(?:(?:[+\-*/%^]|\.\.)?=(?!=)|\(|\[|:))
beginCaptures
1
@@ -1173,7 +1173,7 @@
end
- (?=[),}\]](?!\s*[&|]))|(?=\s*;)|(?=\s*\b(?:break|const|continue|do|else|elseif|end|for|function|if|in|local|repeat|return|then|until|while)\b)|(?=^\s*$)|(?=^\s*(?:@|\b(?:export\s+)?type\b))|(?=^\s*[a-zA-Z_][a-zA-Z0-9_]*(?:\.[a-zA-Z_][a-zA-Z0-9_]*)*\s*(?:(?:[+\-*/%^]|\.\.)?=(?!=)|\(|\[|:))
+ (?=[),}\]](?!\s*[&|]))|(?=\s*;)|(?=\s*(?:[*+%^]|\/\/?|(?<!\.)\.\.(?!\.)|-(?![->`])|~=|==))|(?=\s*\b(?:and|or|break|const|continue|do|else|elseif|end|for|function|if|in|local|repeat|return|then|until|while)\b)|(?=^\s*$)|(?=^\s*(?:@|\b(?:export\s+)?type\b))|(?=^\s*[a-zA-Z_][a-zA-Z0-9_]*(?:\.[a-zA-Z_][a-zA-Z0-9_]*)*\s*(?:(?:[+\-*/%^]|\.\.)?=(?!=)|\(|\[|:))
patterns
diff --git a/Luau.tmLanguage.json b/Luau.tmLanguage.json
index 50db9fb..5c00a84 100644
--- a/Luau.tmLanguage.json
+++ b/Luau.tmLanguage.json
@@ -733,7 +733,7 @@
},
"type-alias-declaration": {
"begin": "(?`])|~=|==))|(?=\\s*\\b(?:and|or|break|const|continue|do|else|elseif|end|for|function|if|in|local|repeat|return|then|until|while)\\b)|(?=^\\s*$)|(?=^\\s*(?:@|\\b(?:export\\s+)?type\\b))|(?=^\\s*[a-zA-Z_][a-zA-Z0-9_]*(?:\\.[a-zA-Z_][a-zA-Z0-9_]*)*\\s*(?:(?:[+\\-*/%^]|\\.\\.)?=(?!=)|\\(|\\[|:))",
"beginCaptures": {
"1": {
"name": "storage.modifier.visibility.luau"
@@ -771,7 +771,7 @@
"name": "keyword.operator.typecast.luau"
}
},
- "end": "(?=[),}\\]](?!\\s*[&|]))|(?=\\s*;)|(?=\\s*\\b(?:break|const|continue|do|else|elseif|end|for|function|if|in|local|repeat|return|then|until|while)\\b)|(?=^\\s*$)|(?=^\\s*(?:@|\\b(?:export\\s+)?type\\b))|(?=^\\s*[a-zA-Z_][a-zA-Z0-9_]*(?:\\.[a-zA-Z_][a-zA-Z0-9_]*)*\\s*(?:(?:[+\\-*/%^]|\\.\\.)?=(?!=)|\\(|\\[|:))",
+ "end": "(?=[),}\\]](?!\\s*[&|]))|(?=\\s*;)|(?=\\s*(?:[*+%^]|\\/\\/?|(?`])|~=|==))|(?=\\s*\\b(?:and|or|break|const|continue|do|else|elseif|end|for|function|if|in|local|repeat|return|then|until|while)\\b)|(?=^\\s*$)|(?=^\\s*(?:@|\\b(?:export\\s+)?type\\b))|(?=^\\s*[a-zA-Z_][a-zA-Z0-9_]*(?:\\.[a-zA-Z_][a-zA-Z0-9_]*)*\\s*(?:(?:[+\\-*/%^]|\\.\\.)?=(?!=)|\\(|\\[|:))",
"patterns": [
{
"include": "#type_literal"
diff --git a/tests/baselines/issue-24.baseline.txt b/tests/baselines/issue-24.baseline.txt
new file mode 100644
index 0000000..3346961
--- /dev/null
+++ b/tests/baselines/issue-24.baseline.txt
@@ -0,0 +1,46 @@
+original file
+-----------------------------------
+local a = tonumber("1")::number * 1000
+
+-----------------------------------
+
+>local a = tonumber("1")::number * 1000
+ ^^^^^
+ source.luau storage.modifier.local.luau
+ ^
+ source.luau
+ ^
+ source.luau variable.other.readwrite.luau
+ ^
+ source.luau
+ ^
+ source.luau keyword.operator.assignment.luau
+ ^
+ source.luau
+ ^^^^^^^^
+ source.luau support.function.luau
+ ^
+ source.luau punctuation.arguments.begin.luau
+ ^
+ source.luau string.quoted.double.luau
+ ^
+ source.luau string.quoted.double.luau
+ ^
+ source.luau string.quoted.double.luau
+ ^
+ source.luau punctuation.arguments.end.luau
+ ^^
+ source.luau keyword.operator.typecast.luau
+ ^^^^^^
+ source.luau support.type.primitive.luau
+ ^
+ source.luau
+ ^
+ source.luau keyword.operator.arithmetic.luau
+ ^
+ source.luau
+ ^^^^
+ source.luau constant.numeric.decimal.luau
+>
+ ^
+ source.luau
\ No newline at end of file
diff --git a/tests/baselines/stylua-luau-assignment-hang-1.lua.baseline.txt b/tests/baselines/stylua-luau-assignment-hang-1.lua.baseline.txt
index d04a4cf..d0fc0e6 100644
--- a/tests/baselines/stylua-luau-assignment-hang-1.lua.baseline.txt
+++ b/tests/baselines/stylua-luau-assignment-hang-1.lua.baseline.txt
@@ -450,10 +450,14 @@ exports.separateDisplayNameAndHOCs =
source.luau
^^^
source.luau support.type.primitive.luau
- ^^^^
+ ^
source.luau
+ ^^
+ source.luau keyword.operator.comparison.luau
+ ^
+ source.luau
^^^
- source.luau support.type.primitive.luau
+ source.luau constant.language.nil.luau
^
source.luau
^^
diff --git a/tests/cases/issue-24.luau b/tests/cases/issue-24.luau
new file mode 100644
index 0000000..62bb75d
--- /dev/null
+++ b/tests/cases/issue-24.luau
@@ -0,0 +1 @@
+local a = tonumber("1")::number * 1000