REFACTOR END

This commit is contained in:
2025-09-28 10:10:01 +03:00
parent 394e0040de
commit 9b914b2904
117 changed files with 3070 additions and 5447 deletions

View File

@@ -5,6 +5,7 @@
import re
import sys
import logging
import argparse
from pathlib import Path
# Configure logging
@@ -20,7 +21,7 @@ SEMANTIC_TAXONOMY = {
"entity", "activity", "application", "nav_host", "controller", "navigation_drawer",
"scaffold", "dashboard", "item", "label", "location", "setup", "theme", "dependencies",
"custom_field", "statistics", "image", "attachment", "item_creation", "item_detailed",
"item_summary", "item_update", "summary", "update"
"item_summary", "item_update", "summary", "update", "feature_module"
],
"Concern": [
"networking", "database", "caching", "authentication", "validation", "parsing",
@@ -74,9 +75,11 @@ class SemanticValidator:
self.check_file_header()
self.check_semantic_taxonomy()
self.check_anchors()
self.check_function_anchors()
self.check_file_termination()
self.check_no_stray_comments()
self.check_contracts_and_implementation()
self.check_relation_triplets()
self.check_ai_friendly_logging()
if not self.errors:
logging.info("[INFO][SemanticValidator.validate][SUCCESS] Validation passed.")
@@ -102,8 +105,8 @@ class SemanticValidator:
# [POST] Errors are added to self.errors if the header is incorrect.
# [END_CONTRACT:SemanticValidator.check_file_header]
def check_file_header(self):
if not self.lines[0].startswith(f"// [FILE] {self.filename}"):
self.add_error(1, f"FileHeaderIntegrity: File must start with '// [FILE] {self.filename}'.")
if not self.lines[0].startswith(f"// [FILE] {self.file_path.as_posix()}"):
self.add_error(1, f"FileHeaderIntegrity: File must start with '// [FILE] {self.file_path.as_posix()}'.")
if not self.lines[1].startswith("// [SEMANTICS]"):
self.add_error(2, "FileHeaderIntegrity: Second line must start with '// [SEMANTICS]'.")
# [END_ANCHOR:SemanticValidator.check_file_header]
@@ -163,14 +166,38 @@ class SemanticValidator:
self.add_error(line_num, f"Anchor Error: Opening anchor '// [ANCHOR:{anchor_id}:...]' at line {line_num} has no matching closing anchor.")
# [END_ANCHOR:SemanticValidator.check_anchors]
# [ANCHOR:SemanticValidator.check_function_anchors:Method]
# [CONTRACT:SemanticValidator.check_function_anchors]
# [PURPOSE] Validates that all functions have a corresponding ANCHOR.
# [POST] Errors are added if a function is found without an ANCHOR.
# [END_CONTRACT:SemanticValidator.check_function_anchors]
def check_function_anchors(self):
fun_pattern = re.compile(r"fun\s+(.+?)\s*\(")
anchor_pattern = re.compile(r"// \[ANCHOR:(\w+):Function\]")
for i, line in enumerate(self.lines, 1):
fun_match = fun_pattern.search(line)
if fun_match:
function_name = fun_match.group(1).strip()
# Look for an ANCHOR comment in the preceding lines
found_anchor = False
for j in range(max(0, i-5), i): # Check up to 5 lines before the function
anchor_match = anchor_pattern.search(self.lines[j])
if anchor_match and anchor_match.group(1) == function_name:
found_anchor = True
break
if not found_anchor:
self.add_error(i, f"Function Anchor Error: Function '{function_name}' is missing a corresponding '// [ANCHOR:{function_name}:Function]' comment.")
# [END_ANCHOR:SemanticValidator.check_function_anchors]
# [ANCHOR:SemanticValidator.check_file_termination:Method]
# [CONTRACT:SemanticValidator.check_file_termination]
# [PURPOSE] Validates Rule 5: FileTermination.
# [POST] An error is added if the file does not have the correct termination anchor.
# [END_CONTRACT:SemanticValidator.check_file_termination]
def check_file_termination(self):
if not self.lines[-1].strip() == f"// [END_FILE_{self.filename}]":
self.add_error(len(self.lines), f"FileTermination: File must end with '// [END_FILE_{self.filename}]'.")
if not self.lines[-1].strip() == f"// [END_FILE_{self.file_path.as_posix()}]":
self.add_error(len(self.lines), f"FileTermination: File must end with '// [END_FILE_{self.file_path.as_posix()}]'.")
# [END_ANCHOR:SemanticValidator.check_file_termination]
# [ANCHOR:SemanticValidator.check_no_stray_comments:Method]
@@ -201,13 +228,30 @@ class SemanticValidator:
end_contract_pattern = re.compile(r"// \[END_CONTRACT:(\w+)\]")
pre_pattern = re.compile(r'// \[PRE\](.*)')
post_pattern = re.compile(r'// \[POST\](.*)')
fun_pattern = re.compile(r"fun\s+\w+\(.*\)\s*\{")
fun_pattern = re.compile(r"fun\s+(.+?)\(.*\)\s*\{")
in_contract = False
contract_id = None
pre_conditions = []
for i, line in enumerate(self.lines, 1):
fun_match = fun_pattern.search(line)
if fun_match:
function_name = fun_match.group(1).strip()
# Check for CONTRACT comment in the preceding lines
found_contract = False
for j in range(max(0, i-5), i): # Check up to 5 lines before the function
contract_match = contract_pattern.search(self.lines[j])
if contract_match:
contract_id_from_comment = contract_match.group(1)
if contract_id_from_comment == function_name: # Check if contract ID matches function name
found_contract = True
break
else:
self.add_error(j, f"Function Contract Error: Contract ID '{contract_id_from_comment}' does not match function name '{function_name}'.")
if not found_contract:
self.add_error(i, f"Function Contract Error: Function '{function_name}' is missing a corresponding '// [CONTRACT:{function_name}]' comment.")
if contract_pattern.search(line):
in_contract = True
contract_id = contract_pattern.search(line).group(1)
@@ -255,6 +299,49 @@ class SemanticValidator:
return len(self.lines) -1 # fallback
# [END_ANCHOR:SemanticValidator.check_contracts_and_implementation]
# [ANCHOR:SemanticValidator.check_function_contracts:Method]
# [CONTRACT:SemanticValidator.check_function_contracts]
# [PURPOSE] Validates that all functions have a corresponding CONTRACT.
# [POST] Errors are added if a function is found without a CONTRACT.
# [END_CONTRACT:SemanticValidator.check_function_contracts]
def check_function_contracts(self):
fun_pattern = re.compile(r"fun\s+(.+?)\(.*\)\s*\{")
contract_pattern = re.compile(r"// \[CONTRACT:(\w+)\]")
for i, line in enumerate(self.lines, 1):
fun_match = fun_pattern.search(line)
if fun_match:
function_name = fun_match.group(1).strip()
# Look for a CONTRACT comment in the preceding lines
found_contract = False
for j in range(max(0, i-5), i): # Check up to 5 lines before the function
contract_match = contract_pattern.search(self.lines[j])
if contract_match and contract_match.group(1) == function_name:
found_contract = True
break
if not found_contract:
self.add_error(i, f"Function Contract Error: Function '{function_name}' is missing a corresponding '// [CONTRACT:{function_name}]' comment.")
# [END_ANCHOR:SemanticValidator.check_function_contracts]
# [ANCHOR:SemanticValidator.check_relation_triplets:Method]
# [CONTRACT:SemanticValidator.check_relation_triplets]
# [PURPOSE] Validates the syntax of relation triplets within ANCHOR blocks.
# [POST] Errors are added for invalid relation triplet syntax or unknown predicates.
# [END_CONTRACT:SemanticValidator.check_relation_triplets]
def check_relation_triplets(self):
relation_pattern = re.compile(r"// \[RELATION:(\w+):(\w+)\]")
valid_predicates = ["CALLS", "CREATES_INSTANCE_OF", "INHERITS_FROM", "IMPLEMENTS",
"READS_FROM", "WRITES_TO", "MODIFIES_STATE_OF", "DEPENDS_ON",
"DISPATCHES_EVENT", "OBSERVES", "TRIGGERS", "EMITS_STATE", "CONSUMES_STATE"]
for i, line in enumerate(self.lines, 1):
match = relation_pattern.search(line)
if match:
predicate, object_id = match.groups()
if predicate not in valid_predicates:
self.add_error(i, f"Relation Triplet Error: Invalid predicate '{predicate}' in relation triplet.")
# [END_ANCHOR:SemanticValidator.check_relation_triplets]
# [ANCHOR:SemanticValidator.check_ai_friendly_logging:Method]
# [CONTRACT:SemanticValidator.check_ai_friendly_logging]
# [PURPOSE] Validates Principle A: AIFriendlyLogging.
@@ -288,22 +375,44 @@ class SemanticValidator:
# [POST] Exits with code 0 on validation success.
# [END_CONTRACT:main_execution]
if __name__ == "__main__":
if len(sys.argv) != 2:
logging.error("[ERROR][main_execution][FATAL] Incorrect number of arguments provided.")
print("Usage: python validate_semantics.py <file_path>")
parser = argparse.ArgumentParser(description="Validate Kotlin source files against the Semantic Enrichment Protocol.")
parser.add_argument("paths", nargs="+", help="One or more file paths or directory paths to validate.")
args = parser.parse_args()
all_files_to_validate = []
for path_str in args.paths:
path = Path(path_str)
if path.is_file() and path.suffix == ".kt":
all_files_to_validate.append(path)
elif path.is_dir():
for kt_file in path.rglob("*.kt"):
all_files_to_validate.append(kt_file)
else:
logging.warning("[WARNING][main_execution][SKIP] Skipping invalid path: %s (not a .kt file or directory).", path_str)
if not all_files_to_validate:
logging.error("[ERROR][main_execution][FATAL] No .kt files found to validate.")
sys.exit(1)
file_to_validate = sys.argv[1]
validator = SemanticValidator(file_to_validate)
errors = validator.validate()
overall_success = True
for file_path in all_files_to_validate:
logging.info("\n[INFO][main_execution][START] Validating file: %s", file_path)
validator = SemanticValidator(file_path)
errors = validator.validate()
if errors:
print(f"Semantic validation failed for {file_to_validate}:")
for error in errors:
print(f"- {error}")
if errors:
overall_success = False
print(f"Semantic validation failed for {file_path}:")
for error in errors:
print(f"- {error}")
else:
print(f"Semantic validation passed for {file_path}.")
if not overall_success:
print("\n[ERROR][main_execution][SUMMARY] One or more files failed semantic validation.")
sys.exit(1)
else:
print(f"Semantic validation passed for {file_to_validate}.")
print("\n[INFO][main_execution][SUMMARY] All specified .kt files passed semantic validation.")
# [END_ANCHOR:main_execution]
# [END_FILE_validate_semantics.py]