diff --git a/gitgalaxy/standards/language_standards.py b/gitgalaxy/standards/language_standards.py
index d3b8a623..3edf9a0f 100644
--- a/gitgalaxy/standards/language_standards.py
+++ b/gitgalaxy/standards/language_standards.py
@@ -9742,7 +9742,7 @@ class PrismConfigSchema(TypedDict):
),
# 2. args: Parameters / Coupling. Captures parameters in handlers (on, command, function).
"args": re.compile(
- r"(?:on|command|function|getprop|setprop)\s+[a-zA-Z0-9_-]+\s+([^\n]+)",
+ r"(?:on|command|function|getprop|setprop)\s+[a-zA-Z0-9_-]+\s+((?:(?!--|//|#|/\*)[^\n])+?)(?=[ \t]*(?:--|//|#|/\*|\n|$))",
re.I,
),
# 3. linear: Sequential I/O & Network Boundaries. Structural boundaries and state transformation verbs.
@@ -9755,7 +9755,7 @@ class PrismConfigSchema(TypedDict):
),
# 4. func_start: Executable Logic Anchors. Anchors executable logic blocks (handlers).
"func_start": re.compile(
- r"^[ \t]*(?:private\s+|public[ \t]+)?(?:on|command|function|getprop|setprop)\s+([a-zA-Z0-9_-]+)(?=[ \t\n]|$)",
+ r"^[ \t]*(?:private[ \t]+|public[ \t]+)?(?:on|command|function|getprop|setprop)[ \t]+([a-zA-Z0-9_-]+)(?=[ \t\n]|--|//|#|/\*|$)",
re.I | re.M,
),
# 5. class_start: Object / Entity Declarations. Defines structural entities (Stacks, Behaviors, Widgets).
@@ -9772,7 +9772,7 @@ class PrismConfigSchema(TypedDict):
# after would break the same lookahead, so it never actually
# matched anything either).
"class_start": re.compile(
- r"^[ \t]*(?:script|behavior|widget|module|library)\s+([a-zA-Z_]\w*(?:\.[a-zA-Z_]\w*){0,10})(?=[ \t\n]|$)",
+ r"^[ \t]*(?:script|behavior|widget|module|library)[ \t]+([a-zA-Z_]\w*(?:\.[a-zA-Z_]\w*){0,10})(?=[ \t]*(?:--|//|#|/\*|$))",
re.I | re.M,
),
# --- PHASE 2: RISK & STRUCTURAL INTEGRITY ---
@@ -9817,7 +9817,7 @@ class PrismConfigSchema(TypedDict):
),
# 10. api: Public Surface Area. Exposed surface area (Any non-private handler).
"api": re.compile(
- r"^[ \t]*(?:public[ \t]+)?(?!(?:private)\s+)(?:on|command|function|getprop|setprop)\s+[a-zA-Z0-9_-]+",
+ r"^[ \t]*(?:public[ \t]+)?(?!(?:private)[ \t]+)(?:on|command|function|getprop|setprop)[ \t]+[a-zA-Z0-9_-]+",
re.I | re.M,
),
# 11. flux: State Mutation. State mutation (The 'put into' core of xTalk).
@@ -9925,7 +9925,7 @@ class PrismConfigSchema(TypedDict):
# 24. import: Dependency Inclusions. Library and stack loading.
"import": re.compile(r"\b(start\s+using\s+(?:stack|behavior)|require|include|module)\b", re.I),
"_dependency_capture": re.compile(
- r"^[ \t]*(?:start[ \t\n]+using[ \t\n]+(?:stack[ \t\n]+|behavior[ \t\n]+)?|require[ \t\n]+|include[ \t\n]+|module[ \t\n]+)(?:['\"]([^'\"]+)['\"]|([^'\"\s]+))",
+ r"^[ \t]*(?:start[ \t]+using[ \t]+(?:stack[ \t]+|behavior[ \t]+)?|require[ \t]+|include[ \t]+|module[ \t]+)(?:['\"]([^'\"]+)['\"]|([^'\"\s]+))",
re.I | re.M,
),
# 25. ownership: Authorship metadata in comments.
diff --git a/tests/extraction/languages/test_livecode.py b/tests/extraction/languages/test_livecode.py
new file mode 100644
index 00000000..80b7d3a0
--- /dev/null
+++ b/tests/extraction/languages/test_livecode.py
@@ -0,0 +1,184 @@
+import sys
+from pathlib import Path
+
+_EXTRACTION_DIR = str(Path(__file__).resolve().parent.parent)
+if _EXTRACTION_DIR not in sys.path:
+ sys.path.insert(0, _EXTRACTION_DIR)
+
+import pytest # noqa: E402
+from _extraction_harness import ( # noqa: E402 # type: ignore
+ assert_invalid_no_match,
+ assert_pathological_dependency_match,
+ assert_pathological_match,
+ assert_valid_dependency_match,
+ assert_valid_match,
+)
+
+from gitgalaxy.standards.language_standards import LANGUAGE_DEFINITIONS # noqa: E402
+
+LIVECODE_RULES = LANGUAGE_DEFINITIONS["livecode"]["rules"]
+
+
+def test_livecode_func_start():
+ valid = [
+ ("on TargetFunc", "TargetFunc"),
+ ("command TargetFunc", "TargetFunc"),
+ ("function TargetFunc", "TargetFunc"),
+ ("getprop TargetFunc", "TargetFunc"),
+ ("setprop TargetFunc", "TargetFunc"),
+ ("private function TargetFunc", "TargetFunc"),
+ ("public command TargetFunc", "TargetFunc"),
+ ("private on TargetFunc", "TargetFunc"),
+ ("public on TargetFunc", "TargetFunc"),
+ ("private getprop TargetFunc", "TargetFunc"),
+ ]
+
+ invalid = [
+ ("script TargetFunc", None),
+ ("put TargetFunc into x", None),
+ ("repeat with TargetFunc", None),
+ ("function_not_start = 1", None),
+ ("command_name", None),
+ ('put "on TargetFunc" into x', None),
+ ("on", None),
+ ("function TargetFunc()", None),
+ ]
+
+ pathological = [
+ ("private \t command \t TargetFunc \t ", "TargetFunc"),
+ ("public \t function \t TargetFunc", "TargetFunc"),
+ ("public \t function \t TargetFunc", "TargetFunc"),
+ ("on \tTargetFunc\t", "TargetFunc"),
+ ("private\t\tcommand\t\tTargetFunc", "TargetFunc"),
+ ("on TargetFunc--comment", "TargetFunc"),
+ ("command TargetFunc//comment", "TargetFunc"),
+ ("function TargetFunc#comment", "TargetFunc"),
+ ("getprop TargetFunc/*comment*/", "TargetFunc"),
+ ]
+
+ for payload, expected in valid:
+ assert_valid_match(LIVECODE_RULES["func_start"], payload, expected, "livecode.func_start")
+
+ for payload, _ in invalid:
+ assert_invalid_no_match(LIVECODE_RULES["func_start"], payload, "livecode.func_start")
+
+ for payload, expected in pathological:
+ assert_pathological_match(LIVECODE_RULES["func_start"], payload, expected, "livecode.func_start")
+
+
+def test_livecode_class_start():
+ valid = [
+ ("script TargetScript", "TargetScript"),
+ ("behavior TargetBehavior", "TargetBehavior"),
+ ("widget TargetWidget", "TargetWidget"),
+ ("module com.livecode.library", "com.livecode.library"),
+ ("library TargetLibrary", "TargetLibrary"),
+ ]
+
+ invalid = [
+ ("on script", None),
+ ("put behavior into x", None),
+ ("widget_not_start = 1", None),
+ ('put "script TargetScript" into x', None),
+ ("module ", None),
+ ("script TargetScript pArg", None),
+ ]
+
+ pathological = [
+ ("script \t TargetScript", "TargetScript"),
+ ("module \t com.livecode.library", "com.livecode.library"),
+ ("widget \t TargetWidget \t ", "TargetWidget"),
+ ("behavior\t\tTargetBehavior", "TargetBehavior"),
+ ("script TargetScript--comment", "TargetScript"),
+ ("widget TargetWidget//comment", "TargetWidget"),
+ ]
+
+ for payload, expected in valid:
+ assert_valid_match(LIVECODE_RULES["class_start"], payload, expected, "livecode.class_start")
+
+ for payload, _ in invalid:
+ assert_invalid_no_match(LIVECODE_RULES["class_start"], payload, "livecode.class_start")
+
+ for payload, expected in pathological:
+ assert_pathological_match(LIVECODE_RULES["class_start"], payload, expected, "livecode.class_start")
+
+
+def test_livecode_args():
+ valid = [
+ ("on TargetFunc pArg1", "pArg1"),
+ ("command TargetFunc pArg1, pArg2", "pArg1, pArg2"),
+ ("function TargetFunc pArg1, pArg2, pArg3", "pArg1, pArg2, pArg3"),
+ ("setprop TargetFunc pArg1", "pArg1"),
+ ("on TargetFunc @pArray", "@pArray"),
+ ]
+
+ invalid = [
+ ("on TargetFunc", None),
+ ("command TargetFunc\n", None),
+ ("script TargetScript pArg", None),
+ ("on TargetFunc -- comment", None),
+ ("on TargetFunc // comment", None),
+ ("on TargetFunc # comment", None),
+ ]
+
+ pathological = [
+ ("on TargetFunc \t pArg1, pArg2", "pArg1, pArg2"),
+ ("command TargetFunc pArg1, pArg2 -- comment", "pArg1, pArg2"),
+ ("function TargetFunc pArg1 // comment", "pArg1"),
+ ("setprop TargetFunc pArg # comment", "pArg"),
+ ("on TargetFunc pArg /* comment */", "pArg"),
+ ]
+
+ for payload, expected in valid:
+ assert_valid_match(LIVECODE_RULES["args"], payload, expected, "livecode.args")
+
+ for payload, _ in invalid:
+ assert_invalid_no_match(LIVECODE_RULES["args"], payload, "livecode.args")
+
+ for payload, expected in pathological:
+ assert_pathological_match(LIVECODE_RULES["args"], payload, expected, "livecode.args")
+
+
+def test_livecode_dependency_capture():
+ valid = [
+ ('start using stack "lib"', "lib"),
+ ('require "database"', "database"),
+ ('include "my_lib"', "my_lib"),
+ ('module "com.livecode.math"', "com.livecode.math"),
+ ("start using behavior my_behavior", "my_behavior"),
+ ('start using "stack_name"', "stack_name"),
+ ("start using stack my_stack", "my_stack"),
+ ]
+
+ invalid = [
+ ("put empty into requirePath", None),
+ ("require_login", None),
+ ]
+
+ xfail_invalid = [
+ ('/*\nstart using stack "fake"\n*/', None),
+ ('put "\nstart using stack \\"fake\\"\n" into x', None),
+ ]
+
+ pathological = [
+ ('start \t using \t behavior \t "btnBehavior"', "btnBehavior"),
+ ('start \t using \t stack \t "lib"', "lib"),
+ ('require \t "database"', "database"),
+ ('module \t "com.livecode.math"', "com.livecode.math"),
+ ]
+
+ for payload, expected in valid:
+ assert_valid_dependency_match(
+ LIVECODE_RULES["_dependency_capture"], payload, expected, "livecode._dependency_capture"
+ )
+
+ for payload, _ in invalid:
+ assert_invalid_no_match(LIVECODE_RULES["_dependency_capture"], payload, "livecode._dependency_capture")
+
+ for payload, _ in xfail_invalid:
+ pytest.param(payload, None, marks=pytest.mark.xfail(reason="No block shielding"))
+
+ for payload, expected in pathological:
+ assert_pathological_dependency_match(
+ LIVECODE_RULES["_dependency_capture"], payload, expected, "livecode._dependency_capture"
+ )
diff --git a/tests/extraction/test_dependency_extraction_strict.py b/tests/extraction/test_dependency_extraction_strict.py
index 904a9374..ca69ada3 100644
--- a/tests/extraction/test_dependency_extraction_strict.py
+++ b/tests/extraction/test_dependency_extraction_strict.py
@@ -1,4 +1,5 @@
import pytest
+
from gitgalaxy.standards.language_standards import LANGUAGE_DEFINITIONS
# =======================================================================# THE GRAVITY LINK GAUNTLET
@@ -40,7 +41,6 @@
)
],
},
-
"html": {
"valid": [
('', "app.js"),
@@ -65,9 +65,6 @@
"invalid": ["CHARACTER(LEN=10) :: INCLUDE_FILE"],
"pathological": [("USE \n , \n INTRINSIC \n :: \n omp_lib", "omp_lib")],
},
-
-
-
"dart": {
"valid": [
("import 'dart:io';", "dart:io"),
@@ -92,15 +89,6 @@
"invalid": ["ENV FROM_PATH=/app"],
"pathological": [("FROM \n --platform=linux/amd64 \n alpine:3.18", "alpine:3.18")],
},
-
- "livecode": {
- "valid": [
- ('start using stack "lib"', "lib"),
- ('require "database"', "database"),
- ],
- "invalid": ["put empty into requirePath"],
- "pathological": [('start \n using \n behavior \n "btnBehavior"', "btnBehavior")],
- },
"objective-c": {
"valid": [
("#import ", "Foundation/Foundation.h"),
diff --git a/tests/extraction/test_function_extraction_strict.py b/tests/extraction/test_function_extraction_strict.py
index bcc1b23d..61c6b1f8 100644
--- a/tests/extraction/test_function_extraction_strict.py
+++ b/tests/extraction/test_function_extraction_strict.py
@@ -96,17 +96,6 @@
],
},
- "livecode": {
- "valid": [
- ("on TargetFunc", "TargetFunc"),
- ("command TargetFunc", "TargetFunc"),
- ("private function TargetFunc", "TargetFunc"),
- ],
- "invalid": ["script TargetFunc", "put TargetFunc", "repeat with TargetFunc"],
- "pathological": [("private \n command \n TargetFunc \n ", "TargetFunc")],
- },
-
-
"dockerfile": {
"valid": [
("RUN apt-get update", "RUN"),
@@ -130,8 +119,6 @@
"invalid": ["//TargetFunc DD DSN=", "//* TargetFunc EXEC"],
"pathological": [("//TargetFunc \t EXEC ", "TargetFunc")],
},
-
-
"css": {
"valid": [("@media (max-width: 600px) {", "@media"), ("@keyframes TargetFunc {", "@keyframes")],
"invalid": [".TargetFunc {", "#TargetFunc {"],