Comprehensive backend review and cleanup for GreyCat projects
Performs comprehensive backend review to identify dead code, duplications, anti-patterns, and optimization opportunities.
/plugin marketplace add datathings/marketplace/plugin install greycat@datathingsPurpose: Comprehensive analysis of GreyCat backend code to identify dead code, duplications, anti-patterns, and optimization opportunities
Run After: Each sprint, before releases, during refactoring sessions
This command performs a multi-phase analysis:
Identify unused code that can be safely removed.
A. Find All Type Definitions:
# Find all types (excluding @volatile API response types initially)
grep -rn "^type [A-Z]" backend/src/ --include="*.gcl" | grep -v "@volatile"
B. Check Usage: For each type found, search for references:
# Search for type name usage across codebase
grep -r "TypeName" backend/ --include="*.gcl" | grep -v "^type TypeName"
C. Categorize:
Output Format:
š backend/src/model/old_model.gcl:42
ā UNUSED TYPE: OldDataStructure
References: 0
Defined: Line 42
Safe to delete: YES
Impact: None (no usages found)
A. Find All Functions:
# Find static functions (services)
grep -rn "static fn [a-z_]" backend/src/service/ --include="*.gcl"
# Find type methods
grep -rn "^\s*fn [a-z_]" backend/src/model/ --include="*.gcl"
# Find API endpoints
grep -rn "@expose" backend/src/api/ --include="*.gcl" -A 1
B. Check Usage: For each function:
# Search for function calls
grep -r "FunctionName(" backend/ --include="*.gcl"
C. Special Cases:
Output Format:
š backend/src/service/data/helper_service.gcl:156
ā UNUSED FUNCTION: processOldFormat
References: 0 call sites
Type: Static function
Safe to delete: YES
Code:
156: static fn processOldFormat(data: String): Result {
157: // ... 20 lines of unused logic
177: }
A. Find Global Variables:
# Find module-level variables
grep -rn "^var [a-z_]" backend/src/model/ --include="*.gcl"
B. Check Usage:
# Search for variable references
grep -r "variableName" backend/ --include="*.gcl"
C. Important:
Output Format:
š backend/src/model/cache.gcl:12
ā ļø UNUSED VARIABLE: temp_cache
Type: nodeIndex<String, String>
References: 1 (only definition)
Safe to delete: REVIEW (might be populated dynamically)
Note: GreyCat uses @include for files, not per-symbol imports. Check if entire files are unused.
# Files with no references from other files
for file in backend/src/**/*.gcl; do
filename=$(basename "$file" .gcl)
refs=$(grep -r "$filename" backend/ --include="*.gcl" | grep -v "$file" | wc -l)
if [ $refs -eq 0 ]; then
echo "Unused file: $file"
fi
done
# Find large commented blocks (potential dead code)
grep -rn "^//.*fn \|^//.*type \|^//.*var " backend/ --include="*.gcl"
Output Format:
š backend/src/service/old_service.gcl:45-78
ā ļø COMMENTED CODE: 33 lines
Content: Old implementation of processData function
Recommendation: Delete if no longer needed, or document why kept
Identify repeated code patterns that could be refactored.
Common Patterns to Detect:
A. Repeated Validation Logic:
# Search for similar validation patterns
grep -rn "if.*== null.*return null" backend/ --include="*.gcl"
grep -rn "if.*\.size\(\) == 0.*return" backend/ --include="*.gcl"
Example Output:
š DUPLICATION: Null checks (8 occurrences)
Locations:
- backend/src/service/user_service.gcl:23
- backend/src/service/document_service.gcl:45
- backend/src/service/search_service.gcl:67
... (5 more)
Pattern:
if (input == null) {
return null;
}
Suggestion:
Extract to validation utility:
abstract type ValidationUtils {
static fn requireNonNull<T>(value: T?, errorMsg: String): T {
if (value == null) {
throw errorMsg;
}
return value;
}
}
Usage:
var validated = ValidationUtils::requireNonNull(input, "Input required");
B. Repeated Query Patterns:
# Find similar loops over global indices
grep -rn "for.*in.*_by_id" backend/ --include="*.gcl" -A 3
C. Repeated Type Conversions:
# Find repeated mapping logic
grep -rn "\.map\|for.*in.*{" backend/ --include="*.gcl" -B 2 -A 5
Compare types with similar field structures:
# Extract all type definitions
grep -rn "^type [A-Z]" backend/src/model/ --include="*.gcl" -A 10
Analyze for:
Example Output:
š SIMILAR TYPES: DocumentView and DocumentDetailView
DocumentView (backend/src/api/api_types.gcl:45):
- id: String
- title: String
- date: time?
- type: String
DocumentDetailView (backend/src/api/api_types.gcl:89):
- id: String
- title: String
- date: time?
- type: String
- content: String ā Only difference
- sections: Array<SectionView>
Similarity: 80% (4/5 fields identical)
Suggestion:
Consider making DocumentDetailView extend DocumentView,
or create shared base type for common fields.
Use heuristics to detect copy-pasted code:
Example Output:
š DUPLICATED BLOCK: Error handling (identical in 3 locations)
Locations:
- backend/src/api/user_api.gcl:67-74
- backend/src/api/document_api.gcl:123-130
- backend/src/api/search_api.gcl:45-52
Code (8 lines):
try {
// ... operation
} catch (ex) {
error("Operation failed: ${ex}");
return ErrorResponse { message: "Internal error" };
}
Suggestion:
Extract to error handling utility:
abstract type ErrorHandler {
static fn handle<T>(operation: fn(): T, errorMsg: String): T {
try {
return operation();
} catch (ex) {
error("${errorMsg}: ${ex}");
throw "Internal error";
}
}
}
Identify GreyCat-specific anti-patterns and bad practices.
Pattern: Using nodeList/nodeIndex for temporary local variables
# Find local variable declarations with persistent types
grep -rn "var.*= nodeList\|var.*= nodeIndex" backend/ --include="*.gcl" -B 2 -A 2
Analysis:
Example Output:
š backend/src/service/builder_service.gcl:34
ā ļø ANTI-PATTERN: Local variable using nodeList
Code:
32: fn buildResults(items: Array<Item>): Array<Result> {
33: var results = nodeList<node<Result>> {}; ā WRONG
34: for (i, item in items) {
35: results.add(node<Result>{ ... });
36: }
37: return results; ā Type mismatch (nodeList vs Array)
38: }
Problem:
- Using persistent nodeList for temporary local variable
- Should use Array for non-persisted collections
Fix:
var results = Array<node<Result>> {};
Impact: Performance overhead, unnecessary persistence
Priority: HIGH
Pattern: Types returned by @expose without @volatile
# Find @expose functions
grep -rn "@expose" backend/src/api/ --include="*.gcl" -A 5
# For each, check return type has @volatile
Example Output:
š backend/src/api/search_api.gcl:23
ā ļø ANTI-PATTERN: Missing @volatile on API response type
Function:
@expose
fn search(...): SearchResults { ā Return type SearchResults
...
}
Type Definition (backend/src/api/api_types.gcl:45):
type SearchResults { ā Missing @volatile decorator
items: Array<ResultView>;
total: int;
}
Problem:
- API response type should be @volatile (not persisted)
- Missing @volatile causes unnecessary database storage
Fix:
@volatile
type SearchResults {
items: Array<ResultView>;
total: int;
}
Priority: MEDIUM
Pattern: Storing objects directly instead of node references
# Find nodeList/nodeIndex storing objects not nodes
grep -rn "nodeList<[^n].*>" backend/ --include="*.gcl"
grep -rn "nodeIndex<.*,\s*[^n].*>" backend/ --include="*.gcl"
Example Output:
š backend/src/model/data.gcl:12
ā ļø ANTI-PATTERN: Storing objects directly in nodeList
Code:
var items: nodeList<Item>; ā WRONG (should be nodeList<node<Item>>)
Problem:
- nodeList should store node references, not objects directly
- Objects should be wrapped in nodes for persistence
Fix:
var items: nodeList<node<Item>>;
// When adding:
items.add(node<Item>{ Item { ... } });
Priority: HIGH (breaks persistence model)
Pattern: Non-nullable collections not initialized in constructor
# Find type fields with collections
grep -rn "^\s*[a-z_]*:\s*\(Array\|Map\|nodeList\|nodeIndex\)" backend/src/model/ --include="*.gcl"
Check if initialization happens in object creation.
Example Output:
š backend/src/model/document.gcl:8
ā ļø ANTI-PATTERN: Non-nullable collection not initialized
Type:
type Document {
id: String;
chunks: nodeList<node<Chunk>>; ā Non-nullable, must initialize
}
Usage (backend/src/service/import_service.gcl:45):
var doc = node<Document>{ Document {
id: "123",
// chunks not initialized ā WILL FAIL at runtime
}};
Problem:
- Non-nullable collections must be initialized on object creation
- Missing initialization causes runtime errors
Fix Option 1 (Make nullable):
chunks: nodeList<node<Chunk>>?;
Fix Option 2 (Initialize):
var doc = node<Document>{ Document {
id: "123",
chunks: nodeList<node<Chunk>> {}
}};
Priority: HIGH (runtime error)
Pattern: Missing null checks, incorrect optional chaining
# Find potential null dereference
grep -rn "\.resolve()\..*\..*\|->.*->.*" backend/ --include="*.gcl"
Example Output:
š backend/src/service/data_service.gcl:67
ā ļø ANTI-PATTERN: Potential null pointer dereference
Code:
var name = user.resolve().profile.name; ā Can fail if profile is null
Problem:
- No null check on profile field
- Will throw runtime error if profile is null
Fix:
var name = user.resolve().profile?.name ?? "Unknown";
Priority: MEDIUM
Identify performance bottlenecks and inefficiencies.
# Find loops with potential expensive operations
grep -rn "for.*in.*{" backend/ --include="*.gcl" -A 10 | grep -E "\.resolve\(\)|\.get\(|->.*->"
Example Output:
š backend/src/service/query_service.gcl:89
ā ļø OPTIMIZATION: Repeated node resolution in loop
Code:
for (i, doc_node in documents) {
var doc = doc_node.resolve(); ā Resolving in every iteration
var chunks = doc.chunks.resolve(); ā Nested resolution
for (j, chunk_node in chunks) {
var chunk = chunk_node.resolve();
// process chunk
}
}
Problem:
- Resolving nodes inside nested loops
- Potential for hundreds/thousands of resolution calls
Optimization:
// Batch resolve if possible
// Or restructure query to minimize resolution depth
Estimated Impact: HIGH (if documents is large collection)
Priority: MEDIUM
Analyze query patterns to suggest missing indices:
# Find linear searches that could use indices
grep -rn "for.*in.*if.*==.*return" backend/ --include="*.gcl"
Example Output:
š backend/src/service/user_service.gcl:34
ā ļø OPTIMIZATION: Linear search could use index
Code:
fn getUserByEmail(email: String): User? {
for (i, user_node in users) {
var user = user_node.resolve();
if (user.email == email) {
return user;
}
}
return null;
}
Problem:
- O(n) linear search through all users
- Called frequently (23 call sites found)
Suggestion:
Create email index in model:
var users_by_email: nodeIndex<String, node<User>>;
fn getUserByEmail(email: String): User? {
var user_node = users_by_email.get(email);
return user_node?.resolve(); // O(1) lookup
}
Estimated Impact: HIGH (if users collection is large)
Priority: HIGH
# Find loops that could use for-in syntax or better iteration
grep -rn "for (.*=.*;.*<.*\.size().*;.*++)" backend/ --include="*.gcl"
Example Output:
š backend/src/service/processor.gcl:56
ā ļø OPTIMIZATION: C-style loop could use for-in
Code:
for (var i = 0; i < items.size(); i++) {
var item = items[i];
process(item);
}
Optimization:
for (i, item in items) {
process(item);
}
Benefits:
- More readable
- Potentially faster (no repeated .size() calls)
- Idiomatic GreyCat style
Priority: LOW (readability improvement)
# Find @expose functions returning full objects
grep -rn "@expose" backend/src/api/ --include="*.gcl" -A 10
Check if response includes unnecessary fields.
Example Output:
š backend/src/api/document_api.gcl:45
ā ļø OPTIMIZATION: API returning too much data
Function:
@expose
fn searchDocuments(...): Array<Document> {
// Returns full Document objects
}
Problem:
- Document has many fields (20+)
- Search results only need: id, title, excerpt
- Sending unnecessary data over network
Suggestion:
Create lightweight view type:
@volatile
type DocumentSearchResult {
id: String;
title: String;
excerpt: String;
score: float;
}
fn searchDocuments(...): Array<DocumentSearchResult> {
// Map to view
}
Estimated Impact: MEDIUM (network payload reduction)
Priority: MEDIUM
Check for proper service abstraction:
# Find abstract types (services)
grep -rn "^abstract type.*Service" backend/src/service/ --include="*.gcl"
Verify:
abstract type patternExample Output:
ā GOOD: Proper service organization
Services found:
- UserService (backend/src/service/auth/user_service.gcl)
- DocumentService (backend/src/service/data/document_service.gcl)
- SearchService (backend/src/service/search/search_service.gcl)
Pattern compliance:
ā All use abstract type
ā All static functions
ā Clear separation from API layer
Global indices must be defined before types that use them:
# Check definition order in model files
grep -rn "^var\|^type" backend/src/model/ --include="*.gcl"
Example Output:
ā ļø WARNING: Index defined after type that uses it
File: backend/src/model/data.gcl
Line 10: type Document {
Line 15: // references documents_by_id
Line 20: }
Line 25: var documents_by_id: nodeIndex<String, node<Document>>; ā Defined after type
Problem:
- Global variables should be defined before types
- May cause initialization issues
Fix:
Move variable definition to top of file (before type definitions)
Priority: MEDIUM
Verify all @expose functions have @permission decorator:
# Find @expose without @permission
grep -rn "@expose" backend/src/api/ --include="*.gcl" -A 1 | grep -v "@permission"
Example Output:
ā ļø WARNING: @expose function missing @permission
Function: backend/src/api/admin_api.gcl:34
@expose
fn deleteUser(userId: String): bool { ā Missing @permission
...
}
Problem:
- No permission check on sensitive operation
- Function is publicly accessible
Fix:
@expose
@permission("app.admin") ā Add appropriate permission
fn deleteUser(userId: String): bool {
...
}
Priority: HIGH (security issue)
Check for proper error handling in API functions:
# Find @expose functions without try-catch
grep -rn "@expose" backend/src/api/ --include="*.gcl" -A 20 | grep -v "try\|catch"
Optionally clean up detected issues with user confirmation.
After analysis, present summary:
===============================================================================
CLEANUP OPTIONS
===============================================================================
Found Issues:
[ ] 12 unused functions (safe to delete)
[ ] 5 unused types (safe to delete)
[ ] 3 unused global variables (needs review)
[ ] 8 duplicated code blocks (extract to utilities)
[ ] 15 anti-patterns (requires code changes)
[ ] 23 optimization opportunities
What would you like to do?
A) Delete unused code (functions + types)
B) Fix anti-patterns (persistence issues, missing @volatile)
C) Show detailed report only (no changes)
D) Custom selection (I'll ask for each category)
If user selects option A:
git status
# Ensure working directory is clean or create backup branch
# For each unused function, use Edit tool to remove
# Example:
# Edit file: backend/src/service/helper.gcl
# Remove lines 45-67 (unused function processOldFormat)
# For each unused type, use Edit tool to remove
greycat-lang lint
# Ensure no errors introduced
ā Cleanup Complete
Deleted:
- 12 unused functions (saved ~450 lines)
- 5 unused types (saved ~120 lines)
Total reduction: 570 lines
Next steps:
1. Run: greycat-lang lint (should pass)
2. Run: greycat test (verify no broken tests)
3. Commit changes: git commit -m "Clean up dead code"
If user selects option B:
For each anti-pattern, apply automated fix:
Example: Fix persistent collection usage:
# Find: var results = nodeList<T> {};
# Replace: var results = Array<T> {};
Example: Add @volatile to API response types:
# Find type definition for API response
# Add @volatile decorator before type
Report each fix applied and verify with lint.
===============================================================================
BACKEND REVIEW & CLEANUP REPORT
===============================================================================
Project: backend/src/
Files Analyzed: 45 .gcl files
Analysis Date: 2024-01-15
SUMMARY:
Dead Code: 17 items (12 functions, 5 types)
Duplications: 8 code blocks
Anti-Patterns: 15 issues
Optimizations: 23 opportunities
Best Practice Gaps: 6 issues
PRIORITY BREAKDOWN:
HIGH Priority: 18 issues (security, runtime errors, major performance)
MEDIUM Priority: 24 issues (performance, maintainability)
LOW Priority: 19 issues (readability, minor optimizations)
TOTAL ISSUES: 61
ESTIMATED CLEANUP EFFORT:
Quick Wins: 2 hours (delete dead code, fix anti-patterns)
Refactoring: 1 day (extract duplications)
Optimization: 2 days (add indices, restructure queries)
===============================================================================
===============================================================================
HIGH PRIORITY ISSUES
===============================================================================
1. SECURITY: Missing @permission on admin function
š backend/src/api/admin_api.gcl:34
Priority: HIGH
Effort: 5 minutes
[Details above]
2. ANTI-PATTERN: Local variable using nodeList
š backend/src/service/builder.gcl:67
Priority: HIGH
Effort: 2 minutes
[Details above]
3. PERFORMANCE: Missing index on frequent query
š backend/src/service/user_service.gcl:34
Priority: HIGH
Effort: 15 minutes
[Details above]
...
===============================================================================
MEDIUM PRIORITY ISSUES
===============================================================================
...
===============================================================================
ā All backend files scanned (.gcl files in backend/src/) ā Dead code identified with safe-to-delete classification ā Duplications detected with refactoring suggestions ā Anti-patterns found with fix recommendations ā Optimizations suggested with impact estimates ā Best practices checked against GreyCat guidelines ā Report generated with prioritized action items ā Lint passes after cleanup (if cleanup performed)
greycat-lang lint passes before runninggreycat test after cleanup# 1. Run backend review
/backend
# 2. Review report (61 issues found)
# 3. Choose cleanup option
# ā A) Delete unused code
# 4. Cleanup executes
# - 12 functions deleted
# - 5 types removed
# - 570 lines saved
# 5. Verify
greycat-lang lint # ā Passes
greycat test # ā All tests pass
# 6. Commit
git add backend/
git commit -m "Backend cleanup: remove dead code, fix anti-patterns"
# 7. Address remaining issues
# - Fix HIGH priority anti-patterns (15 min)
# - Extract duplicated logic (1 hour)
# - Add missing indices (30 min)
# 8. Re-run review to verify improvements
/backend
# ā Issues reduced from 61 to 23