Initial commit
This commit is contained in:
193
skills/unity-compile-fixer/SKILL.md
Normal file
193
skills/unity-compile-fixer/SKILL.md
Normal file
@@ -0,0 +1,193 @@
|
||||
---
|
||||
name: unity-compile-fixer
|
||||
description: Detect and resolve Unity C# compilation errors using VSCode diagnostics. Use this skill when Unity projects have compilation errors that need diagnosis and automated fixes. Analyzes errors from VSCode Language Server, proposes solutions based on error patterns, and handles version control conflicts for Unity projects.
|
||||
---
|
||||
|
||||
# Unity Compile Fixer
|
||||
|
||||
## Overview
|
||||
|
||||
This skill enables automatic detection and resolution of Unity C# compilation errors by leveraging VSCode's diagnostic system. It collects real-time errors from the OmniSharp C# language server, analyzes error patterns against a curated database of common Unity issues, and proposes context-aware solutions for user approval before applying fixes.
|
||||
|
||||
## When to Use This Skill
|
||||
|
||||
Use this skill when:
|
||||
- Unity projects report C# compilation errors in VSCode
|
||||
- Need to diagnose the root cause of Unity compiler errors (CS* error codes)
|
||||
- Want automated fix suggestions for common Unity scripting issues
|
||||
- Working with Unity projects that have version control integration (Git, Unity Collaborate, Plastic SCM)
|
||||
- Need to handle Unity .meta file conflicts
|
||||
|
||||
**Example user requests:**
|
||||
- "Check Unity compilation errors and help me fix them"
|
||||
- "My Unity project has compiler errors, can you diagnose and fix?"
|
||||
- "Unity scripts are not compiling, what's wrong?"
|
||||
- "Fix the C# errors in my Unity project"
|
||||
|
||||
## Workflow
|
||||
|
||||
Follow this workflow when the skill is invoked:
|
||||
|
||||
### 1. Detect Compilation Errors
|
||||
|
||||
Use the `mcp__ide__getDiagnostics` tool to collect errors from VSCode:
|
||||
|
||||
```typescript
|
||||
// Collect all project diagnostics
|
||||
mcp__ide__getDiagnostics()
|
||||
|
||||
// Or target specific Unity script files
|
||||
mcp__ide__getDiagnostics({ uri: "file:///path/to/PlayerController.cs" })
|
||||
```
|
||||
|
||||
Filter the diagnostics to focus on Unity-relevant errors:
|
||||
- **Severity**: Only process errors with `severity: "Error"` (ignore warnings)
|
||||
- **Source**: Only process `source: "csharp"` (OmniSharp C# diagnostics)
|
||||
- **Error Codes**: Focus on CS* compiler error codes (e.g., CS0246, CS0029, CS1061)
|
||||
|
||||
### 2. Analyze Error Patterns
|
||||
|
||||
For each detected error:
|
||||
|
||||
1. **Extract error information:**
|
||||
- File path and line number from `uri` and `range`
|
||||
- Error code from `message` (e.g., "CS0246")
|
||||
- Full error message text
|
||||
|
||||
2. **Match against error pattern database:**
|
||||
- Load `references/error-patterns.json`
|
||||
- Find the error code entry (e.g., CS0246)
|
||||
- Retrieve common causes and solutions
|
||||
|
||||
3. **Read affected file context:**
|
||||
- Use Read tool to load the file with errors
|
||||
- Examine surrounding code for context
|
||||
- Identify missing imports, incorrect types, or API misuse
|
||||
|
||||
### 3. Generate Solution Proposals
|
||||
|
||||
For each error, create a structured fix proposal:
|
||||
|
||||
```markdown
|
||||
**Error**: CS0246 at PlayerController.cs:45
|
||||
**Message**: The type or namespace name 'Rigidbody' could not be found
|
||||
|
||||
**Analysis**:
|
||||
- Missing using directive for UnityEngine namespace
|
||||
- Common Unity API usage pattern
|
||||
|
||||
**Proposed Solution**:
|
||||
Add `using UnityEngine;` at the top of PlayerController.cs
|
||||
|
||||
**Changes Required**:
|
||||
- File: Assets/Scripts/PlayerController.cs
|
||||
- Action: Insert using directive at line 1
|
||||
```
|
||||
|
||||
### 4. User Confirmation
|
||||
|
||||
Before applying any fixes:
|
||||
|
||||
1. **Present all proposed solutions** in a clear, structured format
|
||||
2. **Use AskUserQuestion tool** to get user approval:
|
||||
- List each error and proposed fix
|
||||
- Allow user to approve all, select specific fixes, or cancel
|
||||
|
||||
3. **Wait for explicit confirmation** - do not apply fixes automatically
|
||||
|
||||
### 5. Apply Approved Fixes
|
||||
|
||||
For each approved fix:
|
||||
|
||||
1. **Use Edit tool** to modify the affected file
|
||||
2. **Preserve code formatting** and existing structure
|
||||
3. **Apply minimal changes** - only fix the specific error
|
||||
|
||||
Example:
|
||||
```typescript
|
||||
Edit({
|
||||
file_path: "Assets/Scripts/PlayerController.cs",
|
||||
old_string: "public class PlayerController : MonoBehaviour",
|
||||
new_string: "using UnityEngine;\n\npublic class PlayerController : MonoBehaviour"
|
||||
})
|
||||
```
|
||||
|
||||
### 6. Verify Version Control Status
|
||||
|
||||
After applying fixes:
|
||||
|
||||
1. **Check for .meta file conflicts:**
|
||||
- Use Grep to search for Unity .meta files
|
||||
- Verify that script GUID hasn't changed
|
||||
- Check for merge conflict markers (<<<<<<, ======, >>>>>>)
|
||||
|
||||
2. **Report VCS status:**
|
||||
- List modified files
|
||||
- Warn about any .meta file issues
|
||||
- Suggest git operations if needed
|
||||
|
||||
### 7. Re-validate Compilation
|
||||
|
||||
After fixes are applied:
|
||||
|
||||
1. **Re-run diagnostics** using `mcp__ide__getDiagnostics()`
|
||||
2. **Compare error count** before and after
|
||||
3. **Report results** to the user:
|
||||
- Number of errors fixed
|
||||
- Remaining errors (if any)
|
||||
- Success rate
|
||||
|
||||
## Error Pattern Database
|
||||
|
||||
The skill relies on `references/error-patterns.json` for error analysis. This database contains:
|
||||
|
||||
- **Error Code**: CS* compiler error code
|
||||
- **Description**: Human-readable explanation
|
||||
- **Common Causes**: Typical reasons this error occurs in Unity
|
||||
- **Solutions**: Step-by-step fix instructions
|
||||
- **Unity-Specific Notes**: Unity API considerations
|
||||
|
||||
To analyze an error, load the database and match the error code:
|
||||
|
||||
```typescript
|
||||
Read({ file_path: "references/error-patterns.json" })
|
||||
// Parse JSON and find errorCode entry
|
||||
```
|
||||
|
||||
## Analysis Scripts
|
||||
|
||||
The skill includes Node.js scripts in `scripts/` for complex error analysis:
|
||||
|
||||
### scripts/analyze-diagnostics.js
|
||||
|
||||
Processes VSCode diagnostics JSON output and extracts Unity-relevant errors.
|
||||
|
||||
**Usage:**
|
||||
```bash
|
||||
node scripts/analyze-diagnostics.js <diagnostics-json-file>
|
||||
```
|
||||
|
||||
**Output:**
|
||||
- Filtered list of Unity C# compilation errors
|
||||
- Error classification by type (missing imports, type errors, API issues)
|
||||
- Severity and file location information
|
||||
|
||||
This script can be run independently or invoked from the SKILL.md workflow when detailed analysis is needed.
|
||||
|
||||
## Best Practices
|
||||
|
||||
When using this skill:
|
||||
|
||||
1. **Start with full project diagnostics** - use `mcp__ide__getDiagnostics()` without parameters to get complete error picture
|
||||
2. **Prioritize errors by severity and dependency** - fix foundational errors (missing imports) before downstream errors
|
||||
3. **Batch related fixes** - group errors from the same file for efficient editing
|
||||
4. **Always verify VCS status** - Unity .meta files are critical for version control
|
||||
5. **Re-validate after fixes** - ensure errors are actually resolved
|
||||
|
||||
## Resources
|
||||
|
||||
### scripts/analyze-diagnostics.js
|
||||
Node.js script for processing VSCode diagnostics and filtering Unity-specific C# errors.
|
||||
|
||||
### references/error-patterns.json
|
||||
Curated database of common Unity C# compilation errors with solutions and Unity-specific guidance.
|
||||
368
skills/unity-compile-fixer/references/error-patterns.json
Normal file
368
skills/unity-compile-fixer/references/error-patterns.json
Normal file
@@ -0,0 +1,368 @@
|
||||
{
|
||||
"CS0246": {
|
||||
"errorCode": "CS0246",
|
||||
"description": "The type or namespace name could not be found",
|
||||
"commonCauses": [
|
||||
"Missing using directive (e.g., using UnityEngine;)",
|
||||
"Assembly definition reference not added",
|
||||
"Typo in type name",
|
||||
"Missing package or plugin"
|
||||
],
|
||||
"solutions": [
|
||||
{
|
||||
"step": 1,
|
||||
"action": "Add missing using directive",
|
||||
"example": "using UnityEngine;\nusing UnityEngine.UI;\nusing TMPro;"
|
||||
},
|
||||
{
|
||||
"step": 2,
|
||||
"action": "Check assembly definition references",
|
||||
"details": "If using Assembly Definition files (.asmdef), ensure required assemblies are referenced"
|
||||
},
|
||||
{
|
||||
"step": 3,
|
||||
"action": "Verify type name spelling",
|
||||
"details": "Check for typos in class, struct, or namespace names"
|
||||
},
|
||||
{
|
||||
"step": 4,
|
||||
"action": "Install missing packages",
|
||||
"details": "Open Package Manager and install required Unity packages (TextMeshPro, Input System, etc.)"
|
||||
}
|
||||
],
|
||||
"unityNotes": "Common Unity namespaces: UnityEngine, UnityEngine.UI, UnityEngine.SceneManagement, UnityEditor (editor-only)",
|
||||
"examples": [
|
||||
{
|
||||
"error": "The type or namespace name 'Rigidbody' could not be found",
|
||||
"fix": "Add 'using UnityEngine;' at the top of the file"
|
||||
},
|
||||
{
|
||||
"error": "The type or namespace name 'TextMeshProUGUI' could not be found",
|
||||
"fix": "Add 'using TMPro;' and ensure TextMeshPro package is installed"
|
||||
}
|
||||
]
|
||||
},
|
||||
"CS0029": {
|
||||
"errorCode": "CS0029",
|
||||
"description": "Cannot implicitly convert type",
|
||||
"commonCauses": [
|
||||
"Assigning incompatible types",
|
||||
"Missing type cast",
|
||||
"Incorrect GameObject/Component access",
|
||||
"Unity API version changes"
|
||||
],
|
||||
"solutions": [
|
||||
{
|
||||
"step": 1,
|
||||
"action": "Add explicit cast",
|
||||
"example": "Rigidbody rb = (Rigidbody)GetComponent(typeof(Rigidbody));"
|
||||
},
|
||||
{
|
||||
"step": 2,
|
||||
"action": "Use generic GetComponent",
|
||||
"example": "Rigidbody rb = GetComponent<Rigidbody>();"
|
||||
},
|
||||
{
|
||||
"step": 3,
|
||||
"action": "Check variable type declaration",
|
||||
"details": "Ensure variable type matches assigned value type"
|
||||
}
|
||||
],
|
||||
"unityNotes": "Unity uses generic methods extensively. Prefer GetComponent<T>() over non-generic versions",
|
||||
"examples": [
|
||||
{
|
||||
"error": "Cannot implicitly convert type 'UnityEngine.Component' to 'UnityEngine.Rigidbody'",
|
||||
"fix": "Use GetComponent<Rigidbody>() instead of GetComponent(typeof(Rigidbody))"
|
||||
}
|
||||
]
|
||||
},
|
||||
"CS1061": {
|
||||
"errorCode": "CS1061",
|
||||
"description": "Type does not contain a definition for member",
|
||||
"commonCauses": [
|
||||
"Typo in method or property name",
|
||||
"Unity API version difference",
|
||||
"Accessing wrong object type",
|
||||
"Missing component reference"
|
||||
],
|
||||
"solutions": [
|
||||
{
|
||||
"step": 1,
|
||||
"action": "Check spelling and capitalization",
|
||||
"details": "C# is case-sensitive. Ensure method/property name is correct"
|
||||
},
|
||||
{
|
||||
"step": 2,
|
||||
"action": "Verify Unity API version",
|
||||
"details": "Some APIs change between Unity versions. Check Unity documentation"
|
||||
},
|
||||
{
|
||||
"step": 3,
|
||||
"action": "Ensure correct component type",
|
||||
"example": "transform.position (correct) vs gameObject.position (incorrect)"
|
||||
},
|
||||
{
|
||||
"step": 4,
|
||||
"action": "Use correct Unity API",
|
||||
"details": "GameObject vs Component vs Transform have different members"
|
||||
}
|
||||
],
|
||||
"unityNotes": "Common confusion: GameObject.transform.position (correct) vs GameObject.position (incorrect)",
|
||||
"examples": [
|
||||
{
|
||||
"error": "'GameObject' does not contain a definition for 'position'",
|
||||
"fix": "Use 'transform.position' or 'gameObject.transform.position'"
|
||||
},
|
||||
{
|
||||
"error": "'Rigidbody' does not contain a definition for 'Translate'",
|
||||
"fix": "Use 'transform.Translate()' instead - Translate is a Transform method, not Rigidbody"
|
||||
}
|
||||
]
|
||||
},
|
||||
"CS0101": {
|
||||
"errorCode": "CS0101",
|
||||
"description": "The namespace already contains a definition",
|
||||
"commonCauses": [
|
||||
"Duplicate class names in same namespace",
|
||||
"Partial class definitions conflict",
|
||||
"Multiple files with same class name",
|
||||
"Copy-pasted scripts not renamed"
|
||||
],
|
||||
"solutions": [
|
||||
{
|
||||
"step": 1,
|
||||
"action": "Rename one of the conflicting classes",
|
||||
"details": "Each class in a namespace must have a unique name"
|
||||
},
|
||||
{
|
||||
"step": 2,
|
||||
"action": "Move class to different namespace",
|
||||
"example": "namespace MyGame.Player { class Controller { } }"
|
||||
},
|
||||
{
|
||||
"step": 3,
|
||||
"action": "Check for duplicate files",
|
||||
"details": "Search project for files with same class name"
|
||||
}
|
||||
],
|
||||
"unityNotes": "Unity script file names should match class names. Rename both file and class together",
|
||||
"examples": [
|
||||
{
|
||||
"error": "The namespace 'MyGame' already contains a definition for 'PlayerController'",
|
||||
"fix": "Rename one class to 'PlayerMovement' or use different namespaces"
|
||||
}
|
||||
]
|
||||
},
|
||||
"CS1002": {
|
||||
"errorCode": "CS1002",
|
||||
"description": "Expected semicolon",
|
||||
"commonCauses": [
|
||||
"Missing semicolon at end of statement",
|
||||
"Incomplete method call",
|
||||
"Syntax error in expression"
|
||||
],
|
||||
"solutions": [
|
||||
{
|
||||
"step": 1,
|
||||
"action": "Add missing semicolon",
|
||||
"example": "int health = 100; // semicolon required"
|
||||
},
|
||||
{
|
||||
"step": 2,
|
||||
"action": "Check line above error",
|
||||
"details": "Error often reported on line after the actual missing semicolon"
|
||||
}
|
||||
],
|
||||
"unityNotes": "Check Unity lifecycle methods (Start, Update) for missing semicolons",
|
||||
"examples": [
|
||||
{
|
||||
"error": "Expected ';' after 'transform.position = newPos'",
|
||||
"fix": "Add semicolon: transform.position = newPos;"
|
||||
}
|
||||
]
|
||||
},
|
||||
"CS1003": {
|
||||
"errorCode": "CS1003",
|
||||
"description": "Syntax error, expected comma",
|
||||
"commonCauses": [
|
||||
"Missing comma in parameter list",
|
||||
"Missing comma in array initialization",
|
||||
"Incorrect method signature"
|
||||
],
|
||||
"solutions": [
|
||||
{
|
||||
"step": 1,
|
||||
"action": "Add missing comma",
|
||||
"example": "Vector3 pos = new Vector3(1.0f, 2.0f, 3.0f);"
|
||||
},
|
||||
{
|
||||
"step": 2,
|
||||
"action": "Check method parameters",
|
||||
"details": "Ensure parameters are separated by commas"
|
||||
}
|
||||
],
|
||||
"unityNotes": "Unity methods like Vector3, Quaternion require commas between components",
|
||||
"examples": [
|
||||
{
|
||||
"error": "Expected ',' in Vector3 constructor",
|
||||
"fix": "new Vector3(1.0f, 2.0f, 3.0f) // commas required"
|
||||
}
|
||||
]
|
||||
},
|
||||
"CS1525": {
|
||||
"errorCode": "CS1525",
|
||||
"description": "Invalid expression term",
|
||||
"commonCauses": [
|
||||
"Keyword used in wrong context",
|
||||
"Incomplete expression",
|
||||
"Missing opening brace"
|
||||
],
|
||||
"solutions": [
|
||||
{
|
||||
"step": 1,
|
||||
"action": "Check for matching braces",
|
||||
"details": "Ensure all { } are properly matched"
|
||||
},
|
||||
{
|
||||
"step": 2,
|
||||
"action": "Verify expression syntax",
|
||||
"details": "Check for incomplete or malformed expressions"
|
||||
}
|
||||
],
|
||||
"unityNotes": "Common in Unity lifecycle methods - ensure proper { } around method bodies",
|
||||
"examples": [
|
||||
{
|
||||
"error": "Invalid expression term 'void'",
|
||||
"fix": "Check for missing brace before method definition"
|
||||
}
|
||||
]
|
||||
},
|
||||
"CS0122": {
|
||||
"errorCode": "CS0122",
|
||||
"description": "Member is inaccessible due to its protection level",
|
||||
"commonCauses": [
|
||||
"Accessing private member from outside class",
|
||||
"Missing public/protected modifier",
|
||||
"Incorrect inheritance setup"
|
||||
],
|
||||
"solutions": [
|
||||
{
|
||||
"step": 1,
|
||||
"action": "Change member to public",
|
||||
"example": "public float speed = 5.0f;"
|
||||
},
|
||||
{
|
||||
"step": 2,
|
||||
"action": "Use SerializeField for private fields",
|
||||
"example": "[SerializeField] private float speed;"
|
||||
},
|
||||
{
|
||||
"step": 3,
|
||||
"action": "Add public property or method",
|
||||
"example": "public float Speed { get { return speed; } }"
|
||||
}
|
||||
],
|
||||
"unityNotes": "Use [SerializeField] for private fields that should appear in Inspector",
|
||||
"examples": [
|
||||
{
|
||||
"error": "'PlayerController.speed' is inaccessible due to its protection level",
|
||||
"fix": "Change 'private float speed;' to 'public float speed;' or add [SerializeField]"
|
||||
}
|
||||
]
|
||||
},
|
||||
"CS0103": {
|
||||
"errorCode": "CS0103",
|
||||
"description": "The name does not exist in the current context",
|
||||
"commonCauses": [
|
||||
"Variable not declared",
|
||||
"Typo in variable name",
|
||||
"Variable out of scope",
|
||||
"Missing component reference"
|
||||
],
|
||||
"solutions": [
|
||||
{
|
||||
"step": 1,
|
||||
"action": "Declare variable before use",
|
||||
"example": "Rigidbody rb;\nvoid Start() { rb = GetComponent<Rigidbody>(); }"
|
||||
},
|
||||
{
|
||||
"step": 2,
|
||||
"action": "Check variable name spelling",
|
||||
"details": "Variable names are case-sensitive"
|
||||
},
|
||||
{
|
||||
"step": 3,
|
||||
"action": "Ensure variable is in scope",
|
||||
"details": "Variables declared in methods are only accessible within that method"
|
||||
}
|
||||
],
|
||||
"unityNotes": "Common with component references - ensure they're declared as class fields",
|
||||
"examples": [
|
||||
{
|
||||
"error": "The name 'rb' does not exist in the current context",
|
||||
"fix": "Declare 'Rigidbody rb;' at class level before using in methods"
|
||||
}
|
||||
]
|
||||
},
|
||||
"CS0119": {
|
||||
"errorCode": "CS0119",
|
||||
"description": "Member is a type, which is not valid in the given context",
|
||||
"commonCauses": [
|
||||
"Using type name instead of instance",
|
||||
"Missing instantiation",
|
||||
"Incorrect static/instance usage"
|
||||
],
|
||||
"solutions": [
|
||||
{
|
||||
"step": 1,
|
||||
"action": "Create instance of type",
|
||||
"example": "GameObject player = new GameObject(); // not just 'GameObject'"
|
||||
},
|
||||
{
|
||||
"step": 2,
|
||||
"action": "Use correct Unity API",
|
||||
"example": "GameObject.Find('Player') // static method on type"
|
||||
}
|
||||
],
|
||||
"unityNotes": "Unity has both static methods (GameObject.Find) and instance methods (gameObject.SetActive)",
|
||||
"examples": [
|
||||
{
|
||||
"error": "'GameObject' is a type but is used like a variable",
|
||||
"fix": "Use 'gameObject' (lowercase - current instance) or 'new GameObject()'"
|
||||
}
|
||||
]
|
||||
},
|
||||
"CS0117": {
|
||||
"errorCode": "CS0117",
|
||||
"description": "Type does not contain a definition",
|
||||
"commonCauses": [
|
||||
"Unity API version change",
|
||||
"Incorrect class/namespace",
|
||||
"Missing package reference"
|
||||
],
|
||||
"solutions": [
|
||||
{
|
||||
"step": 1,
|
||||
"action": "Check Unity documentation",
|
||||
"details": "API may have changed in your Unity version"
|
||||
},
|
||||
{
|
||||
"step": 2,
|
||||
"action": "Verify class name",
|
||||
"details": "Ensure using correct Unity class"
|
||||
},
|
||||
{
|
||||
"step": 3,
|
||||
"action": "Update deprecated APIs",
|
||||
"details": "Some APIs are replaced in newer Unity versions"
|
||||
}
|
||||
],
|
||||
"unityNotes": "Unity 2020+ changed many APIs. Check Unity Upgrade Guide",
|
||||
"examples": [
|
||||
{
|
||||
"error": "'Input' does not contain a definition for 'GetKey'",
|
||||
"fix": "In new Input System, use 'Keyboard.current.spaceKey.isPressed' instead"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
228
skills/unity-compile-fixer/scripts/analyze-diagnostics.js
Normal file
228
skills/unity-compile-fixer/scripts/analyze-diagnostics.js
Normal file
@@ -0,0 +1,228 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
/**
|
||||
* Unity Compile Error Analyzer
|
||||
*
|
||||
* Processes VSCode diagnostics JSON output and extracts Unity-relevant C# compilation errors.
|
||||
* Filters by severity (Error only), source (csharp), and classifies errors by type.
|
||||
*
|
||||
* Usage:
|
||||
* node analyze-diagnostics.js <diagnostics-json-file>
|
||||
* node analyze-diagnostics.js (reads from stdin)
|
||||
*
|
||||
* Output: JSON array of classified Unity errors
|
||||
*/
|
||||
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
|
||||
// Error classification patterns
|
||||
const ERROR_CLASSIFICATIONS = {
|
||||
MISSING_IMPORT: {
|
||||
patterns: [/CS0246/, /type or namespace.*could not be found/i],
|
||||
category: 'Missing Import/Namespace',
|
||||
priority: 1
|
||||
},
|
||||
TYPE_MISMATCH: {
|
||||
patterns: [/CS0029/, /cannot implicitly convert/i, /cannot convert type/i],
|
||||
category: 'Type Mismatch',
|
||||
priority: 2
|
||||
},
|
||||
MEMBER_NOT_FOUND: {
|
||||
patterns: [/CS1061/, /does not contain a definition/i],
|
||||
category: 'Member Not Found',
|
||||
priority: 2
|
||||
},
|
||||
DUPLICATE_DEFINITION: {
|
||||
patterns: [/CS0101/, /already contains a definition/i],
|
||||
category: 'Duplicate Definition',
|
||||
priority: 3
|
||||
},
|
||||
SYNTAX_ERROR: {
|
||||
patterns: [/CS1002/, /CS1003/, /CS1525/, /expected/i],
|
||||
category: 'Syntax Error',
|
||||
priority: 1
|
||||
},
|
||||
ACCESS_MODIFIER: {
|
||||
patterns: [/CS0122/, /inaccessible due to its protection level/i],
|
||||
category: 'Access Modifier Issue',
|
||||
priority: 2
|
||||
},
|
||||
UNITY_API: {
|
||||
patterns: [/MonoBehaviour/, /GameObject/, /Transform/, /Component/],
|
||||
category: 'Unity API Issue',
|
||||
priority: 1
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Classify error based on message content
|
||||
*/
|
||||
function classifyError(message) {
|
||||
for (const [key, classifier] of Object.entries(ERROR_CLASSIFICATIONS)) {
|
||||
for (const pattern of classifier.patterns) {
|
||||
if (pattern.test(message)) {
|
||||
return {
|
||||
type: key,
|
||||
category: classifier.category,
|
||||
priority: classifier.priority
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
return {
|
||||
type: 'UNKNOWN',
|
||||
category: 'Other Error',
|
||||
priority: 4
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Extract error code from message (e.g., "CS0246")
|
||||
*/
|
||||
function extractErrorCode(message) {
|
||||
const match = message.match(/CS\d{4}/);
|
||||
return match ? match[0] : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Filter and process diagnostics
|
||||
*/
|
||||
function analyzeDiagnostics(diagnostics) {
|
||||
if (!diagnostics || !Array.isArray(diagnostics)) {
|
||||
console.error('Error: Invalid diagnostics format. Expected array.');
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
const unityErrors = diagnostics
|
||||
.filter(diag => {
|
||||
// Filter: Only errors (not warnings)
|
||||
if (diag.severity !== 'Error') return false;
|
||||
|
||||
// Filter: Only C# errors from OmniSharp
|
||||
if (diag.source !== 'csharp') return false;
|
||||
|
||||
// Filter: Must have valid message
|
||||
if (!diag.message) return false;
|
||||
|
||||
return true;
|
||||
})
|
||||
.map(diag => {
|
||||
const classification = classifyError(diag.message);
|
||||
const errorCode = extractErrorCode(diag.message);
|
||||
|
||||
return {
|
||||
file: diag.uri ? diag.uri.replace('file:///', '') : 'unknown',
|
||||
line: diag.range?.start?.line ?? 0,
|
||||
column: diag.range?.start?.character ?? 0,
|
||||
errorCode: errorCode,
|
||||
message: diag.message,
|
||||
classification: classification.category,
|
||||
type: classification.type,
|
||||
priority: classification.priority,
|
||||
source: diag.source
|
||||
};
|
||||
});
|
||||
|
||||
// Sort by priority (lower number = higher priority)
|
||||
unityErrors.sort((a, b) => a.priority - b.priority);
|
||||
|
||||
return unityErrors;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate summary statistics
|
||||
*/
|
||||
function generateSummary(errors) {
|
||||
const summary = {
|
||||
totalErrors: errors.length,
|
||||
byCategory: {},
|
||||
byFile: {},
|
||||
highPriority: errors.filter(e => e.priority === 1).length
|
||||
};
|
||||
|
||||
errors.forEach(error => {
|
||||
// Count by category
|
||||
summary.byCategory[error.classification] =
|
||||
(summary.byCategory[error.classification] || 0) + 1;
|
||||
|
||||
// Count by file
|
||||
const fileName = path.basename(error.file);
|
||||
summary.byFile[fileName] = (summary.byFile[fileName] || 0) + 1;
|
||||
});
|
||||
|
||||
return summary;
|
||||
}
|
||||
|
||||
/**
|
||||
* Main execution
|
||||
*/
|
||||
function main() {
|
||||
const args = process.argv.slice(2);
|
||||
|
||||
let diagnosticsData;
|
||||
|
||||
if (args.length === 0) {
|
||||
// Read from stdin
|
||||
console.error('Reading diagnostics from stdin...');
|
||||
const input = fs.readFileSync(0, 'utf-8');
|
||||
try {
|
||||
diagnosticsData = JSON.parse(input);
|
||||
} catch (error) {
|
||||
console.error('Error parsing JSON from stdin:', error.message);
|
||||
process.exit(1);
|
||||
}
|
||||
} else {
|
||||
// Read from file
|
||||
const filePath = args[0];
|
||||
|
||||
if (!fs.existsSync(filePath)) {
|
||||
console.error(`Error: File not found: ${filePath}`);
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
try {
|
||||
const fileContent = fs.readFileSync(filePath, 'utf-8');
|
||||
diagnosticsData = JSON.parse(fileContent);
|
||||
} catch (error) {
|
||||
console.error(`Error reading/parsing file: ${error.message}`);
|
||||
process.exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
// Extract diagnostics array (handle different formats)
|
||||
let diagnostics;
|
||||
if (Array.isArray(diagnosticsData)) {
|
||||
diagnostics = diagnosticsData;
|
||||
} else if (diagnosticsData.diagnostics && Array.isArray(diagnosticsData.diagnostics)) {
|
||||
diagnostics = diagnosticsData.diagnostics;
|
||||
} else {
|
||||
console.error('Error: Could not find diagnostics array in input');
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
// Analyze
|
||||
const errors = analyzeDiagnostics(diagnostics);
|
||||
const summary = generateSummary(errors);
|
||||
|
||||
// Output results
|
||||
const output = {
|
||||
summary: summary,
|
||||
errors: errors
|
||||
};
|
||||
|
||||
console.log(JSON.stringify(output, null, 2));
|
||||
}
|
||||
|
||||
// Run if executed directly
|
||||
if (require.main === module) {
|
||||
main();
|
||||
}
|
||||
|
||||
// Export for use as module
|
||||
module.exports = {
|
||||
analyzeDiagnostics,
|
||||
classifyError,
|
||||
extractErrorCode,
|
||||
generateSummary
|
||||
};
|
||||
Reference in New Issue
Block a user