|
1 | 1 | # DecompilerServer Copilot Instructions |
2 | 2 |
|
3 | | -## Project Overview |
| 3 | +Read these files first: |
| 4 | +- `ARCHITECTURE.md` for durable technical rules and contracts |
| 5 | +- `README.md` for user-facing workflow |
| 6 | +- `TODO.md` for backlog |
4 | 7 |
|
5 | | -This is a **DecompilerServer** project that implements an MCP (Model Context Protocol) server for decompiling and analyzing .NET assemblies, specifically focused on Unity's Assembly-CSharp.dll files. The server provides comprehensive decompilation, search, and analysis capabilities through various endpoints. |
| 8 | +## Repository-Specific Rules |
6 | 9 |
|
7 | | -## Key Technologies & Frameworks |
| 10 | +- MCP tools live as static methods under `Tools/`. |
| 11 | +- Tools should return via `ResponseFormatter.TryExecute(...)`. |
| 12 | +- Discovery/search tools should route with `ToolSessionRouter.GetForContext(...)`. |
| 13 | +- `memberId` follow-up tools should route with `ToolSessionRouter.GetForMember(...)`. |
| 14 | +- Reuse `TypeSurfaceComparer` for type-surface semantics instead of duplicating compare logic. |
| 15 | +- Use `DecompilerService.DecompileEntitySnippet(...)` for focused compare body retrieval. |
| 16 | +- Prefer structured JSON output over pre-rendered diff text for overview commands. |
8 | 17 |
|
9 | | -- **.NET 8.0** - Target framework |
10 | | -- **ICSharpCode.Decompiler** - Core decompilation engine |
11 | | -- **Microsoft.Extensions.Hosting** - Hosting and dependency injection |
12 | | -- **ModelContextProtocol** - MCP server implementation |
13 | | -- **System.Text.Json** - JSON serialization with camelCase naming |
14 | | -- **xUnit** - Testing framework |
| 18 | +## Workspace and Compare Expectations |
15 | 19 |
|
16 | | -## Project Structure |
| 20 | +- Assume multi-context workspace support is the primary model. |
| 21 | +- Preserve stable member ID format: `<mvid-32hex>:<token-8hex>:<kind-code>`. |
| 22 | +- `compare_contexts` is structural. `changed` means direct member surface changed. |
| 23 | +- `compare_symbols(compareMode: "body")` is method-only and should stay opt-in. |
| 24 | +- Do not broaden compare semantics casually; update `ARCHITECTURE.md` if a durable contract changes. |
17 | 25 |
|
18 | | -``` |
19 | | -DecompilerServer/ |
20 | | -├── Services/ # Core service implementations |
21 | | -│ ├── AssemblyContextManager.cs # Assembly loading and context management |
22 | | -│ ├── DecompilerService.cs # C# decompilation with caching |
23 | | -│ ├── MemberResolver.cs # Member ID resolution and normalization |
24 | | -│ ├── SearchServiceBase.cs # Base search and pagination functionality |
25 | | -│ ├── UsageAnalyzer.cs # Code usage analysis |
26 | | -│ ├── InheritanceAnalyzer.cs # Inheritance relationship analysis |
27 | | -│ └── ResponseFormatter.cs # JSON response formatting |
28 | | -├── Tools/ # MCP tool implementations (static methods) |
29 | | -│ ├── ResolveMemberId.cs # Member ID validation |
30 | | -│ ├── ListNamespaces.cs # Namespace enumeration |
31 | | -│ ├── SearchTypes.cs # Type discovery with search |
32 | | -│ ├── GetDecompiledSource.cs # Core decompilation to C# |
33 | | -│ ├── GetSourceSlice.cs # Source code range viewing |
34 | | -│ └── GetMemberDetails.cs # Rich member metadata |
35 | | -├── Tests/ # xUnit test suite |
36 | | -├── TestLibrary/ # Test assembly for validation |
37 | | -├── ServiceLocator.cs # Service locator for MCP tools |
38 | | -├── Program.cs # Application entry point |
39 | | -└── *.md # Documentation files |
40 | | -``` |
41 | | - |
42 | | -## Documentation |
43 | | - |
44 | | -### Developer Guides |
45 | | -- **[HELPER_METHODS_GUIDE.md](../HELPER_METHODS_GUIDE.md)** - Comprehensive guide to all service helper methods and implementation patterns for MCP tools. Essential reading for understanding the service architecture and implementing new endpoints. |
46 | | -- **[TESTING.md](../TESTING.md)** - Complete testing framework documentation covering xUnit setup, test data structure, and testing patterns. Required reading for writing tests and understanding the test infrastructure. |
47 | | -- **[TODO.md](../TODO.md)** - Comprehensive list of prioritized TODOs and enhancement opportunities based on thorough code review. Organized by priority and complexity for systematic AI-assisted development. Contains detailed context and reasoning for each improvement. |
48 | | - |
49 | | -All guides are actively maintained and provide crucial implementation guidance for developers working on the DecompilerServer. |
50 | | - |
51 | | -## Core Architecture Principles |
52 | | - |
53 | | -### Member ID System |
54 | | -- **Format**: `<mvid-32hex>:<token-8hex>:<kind-code>` |
55 | | -- **Kind Codes**: T=Type, M=Method/Constructor, P=Property, F=Field, E=Event, N=Namespace |
56 | | -- All member IDs must be stable and consistent across sessions |
57 | | - |
58 | | -### Threading & Performance |
59 | | -- Use `ReaderWriterLockSlim` for thread-safe access (fast reads, guarded writes) |
60 | | -- Implement lazy indexing - build minimal maps on first access |
61 | | -- Cache decompiled source with line indexing for efficient slicing |
62 | | -- Always paginate results (default limit: 50, max: 500) |
63 | | - |
64 | | -### Error Handling |
65 | | -- Return structured errors: `{ error: { code, message, detail? } }` |
66 | | -- Never throw exceptions across MCP boundaries |
67 | | -- Handle assembly loading failures gracefully |
68 | | - |
69 | | -## Code Style & Conventions |
70 | | - |
71 | | -### Formatting |
72 | | -- **Important**: Run `dotnet format DecompilerServer.sln` before committing |
73 | | -- During development, focus on functionality over formatting |
74 | | -- The formatter will handle code style consistency |
| 26 | +## Testing |
75 | 27 |
|
76 | | -### Naming Conventions |
77 | | -- Use PascalCase for public members and types |
78 | | -- Use camelCase for private fields and local variables |
79 | | -- Prefix private fields with underscore (`_fieldName`) |
80 | | -- Use descriptive names for member IDs and handles |
| 28 | +- Use xUnit and real compiled test assemblies. |
| 29 | +- `Tests/ServiceTestBase.cs` is the base fixture for service-level tests. |
| 30 | +- Add dedicated `*ToolTests.cs` files for MCP tool behavior. |
| 31 | +- Use `Tests/TemporaryAssemblyBuilder.cs` for controlled version-drift and compare tests. |
| 32 | +- When tests need workspace-aware behavior, register `DecompilerWorkspace` in the test service provider. |
81 | 33 |
|
82 | | -### JSON Serialization |
83 | | -- Use camelCase property naming |
84 | | -- Ignore null values in output |
85 | | -- Ensure deterministic ordering for stable diffs |
| 34 | +## Verification |
86 | 35 |
|
87 | | -## Development Workflow |
| 36 | +Run after code changes: |
88 | 37 |
|
89 | | -### Building & Testing |
90 | 38 | ```bash |
91 | | -# Build the solution |
92 | | -dotnet build DecompilerServer.sln |
93 | | - |
94 | | -# Run tests |
95 | | -dotnet test DecompilerServer.sln |
96 | | - |
97 | | -# Format code before committing |
98 | 39 | dotnet format DecompilerServer.sln |
| 40 | +dotnet test -c Release --no-restore |
99 | 41 | ``` |
100 | 42 |
|
101 | | -### Test Strategy |
102 | | -- All service helpers have comprehensive tests using real test assembly |
103 | | -- Use `ServiceTestBase` for integration tests with loaded test.dll |
104 | | -- Validate both functionality and output format |
105 | | -- Test with various C# constructs (generics, inheritance, attributes, etc.) |
106 | | - |
107 | | -## Key Implementation Guidelines |
108 | | - |
109 | | -### Assembly Context Management |
110 | | -- Maintain single in-memory context with PEFile, UniversalAssemblyResolver, DecompilerTypeSystem |
111 | | -- Load assemblies with `PEStreamOptions.PrefetchEntireImage` (or equivalent in-memory loading) so the source DLL is not kept locked on disk |
112 | | -- Configure resolver with appropriate search directories (Game*_Data/Managed, Unity directories) |
113 | | -- Use proper decompiler settings (UsingDeclarations, ShowXmlDocumentation, NamedArguments) |
114 | | -- `Unload` should clear the current assembly context and caches without disposing the singleton `AssemblyContextManager`; reserve `Dispose()` for service/provider shutdown |
115 | | - |
116 | | -### Search & Pagination |
117 | | -- Implement cursor-based pagination for all search endpoints |
118 | | -- Support filtering by accessibility, member types, namespaces |
119 | | -- Return structured results with `{ items, nextCursor, totalEstimate }` |
120 | | - |
121 | | -### Source Management |
122 | | -- Cache decompiled C# source with line indexing |
123 | | -- Support ranged retrieval without re-decompilation |
124 | | -- Include proper headers/footers and maintain source document metadata |
125 | | -- When decompiling nested types by name, prefer reflection names such as `Outer+Inner`; dotted names such as `Outer.Inner` can fail in ILSpy lookup paths even when the type exists in metadata. |
126 | | - |
127 | | -### IL Handling |
128 | | -- Use ICSharpCode.Decompiler.Disassembler for readable IL output |
129 | | -- Leverage MetadataReader, avoid reflection-only loading |
130 | | -- Provide both IL and decompiled C# views |
131 | | - |
132 | | -## Common Patterns |
133 | | - |
134 | | -**See [HELPER_METHODS_GUIDE.md](../HELPER_METHODS_GUIDE.md) for comprehensive service helper documentation and implementation patterns.** |
135 | | - |
136 | | -### Service Dependencies |
137 | | -Services typically depend on: |
138 | | -- `AssemblyContextManager` - for assembly access |
139 | | -- `MemberResolver` - for ID resolution and validation |
140 | | -- Other services as needed for specific functionality |
141 | | - |
142 | | -### MCP Tool Dependencies |
143 | | -MCP tools (static methods) access services via: |
144 | | -- `ServiceLocator.ContextManager` - assembly context access |
145 | | -- `ServiceLocator.MemberResolver` - member ID operations |
146 | | -- `ServiceLocator.DecompilerService` - source decompilation |
147 | | -- `ServiceLocator.ResponseFormatter` - consistent JSON responses |
148 | | - |
149 | | -### Response Models |
150 | | -Use consistent model types (defined in shared Models.cs): |
151 | | -- `MemberHandle`, `MemberSummary`, `SearchResult<T>` |
152 | | -- `MemberDetails`, `SourceDocument`, `SourceSlice` |
153 | | -- `UsageRef`, `GraphResult`, `Stats` |
154 | | - |
155 | | -### Error Responses |
156 | | -Always return structured error objects rather than throwing exceptions when implementing MCP endpoints. |
157 | | - |
158 | | -## Testing Considerations |
159 | | - |
160 | | -- Use the TestLibrary project for consistent test data |
161 | | -- Test with various C# language features and constructs |
162 | | -- Validate both service functionality and JSON output format |
163 | | -- Ensure thread safety in concurrent scenarios |
164 | | -- Test pagination and cursor handling |
165 | | - |
166 | | -**See [TESTING.md](../TESTING.md) for complete testing framework documentation and best practices.** |
167 | | - |
168 | | -### MCP Tool Testing Patterns |
169 | | -When implementing MCP tools (static methods), follow these patterns: |
170 | | - |
171 | | -- **ServiceLocator Setup**: Create a service provider in test constructor and register all required services: |
172 | | - ```csharp |
173 | | - public ToolImplementationTests() |
174 | | - { |
175 | | - var services = new ServiceCollection(); |
176 | | - services.AddSingleton(ContextManager); |
177 | | - services.AddSingleton(MemberResolver); |
178 | | - services.AddSingleton<DecompilerService>(); |
179 | | - services.AddSingleton<UsageAnalyzer>(); |
180 | | - services.AddSingleton<InheritanceAnalyzer>(); |
181 | | - services.AddSingleton<ResponseFormatter>(); |
182 | | - |
183 | | - _serviceProvider = services.BuildServiceProvider(); |
184 | | - ServiceLocator.SetServiceProvider(_serviceProvider); |
185 | | - } |
186 | | - ``` |
187 | | - |
188 | | -- **Service Dependencies**: Always register services in the correct dependency order: |
189 | | - 1. `AssemblyContextManager` (core, no dependencies) |
190 | | - 2. `MemberResolver` (depends on AssemblyContextManager) |
191 | | - 3. All other services (DecompilerService, UsageAnalyzer, etc.) |
192 | | - 4. `ResponseFormatter` (standalone) |
193 | | - |
194 | | -- **Test Cleanup**: Do NOT override Dispose() with [Fact] attribute - this causes xUnit errors. Let ServiceTestBase handle disposal naturally. |
195 | | - |
196 | | -- **SearchService Pattern**: When tools need SearchServiceBase functionality, create a concrete implementation: |
197 | | - ```csharp |
198 | | - internal class SearchService : SearchServiceBase |
199 | | - { |
200 | | - public SearchService(AssemblyContextManager contextManager, MemberResolver memberResolver) |
201 | | - : base(contextManager, memberResolver) { } |
202 | | - } |
203 | | - ``` |
204 | | - |
205 | | -## Performance Optimization |
206 | | - |
207 | | -- Implement lazy loading for expensive operations |
208 | | -- Use concurrent collections for thread-safe caching |
209 | | -- Build indexes incrementally rather than upfront |
210 | | -- Consider memory usage when caching large decompiled sources |
211 | | - |
212 | | -## MCP Tool Implementation Guidelines |
213 | | - |
214 | | -### Static Method Pattern |
215 | | -MCP tools must be implemented as static methods with specific attributes: |
216 | | -```csharp |
217 | | -[McpServerTool, Description("Tool description")] |
218 | | -public static string ToolName(parameters...) |
219 | | -{ |
220 | | - return ResponseFormatter.TryExecute(() => |
221 | | - { |
222 | | - // Access services via ServiceLocator |
223 | | - var service = ServiceLocator.GetRequiredService<ServiceType>(); |
224 | | - // Implementation logic |
225 | | - return result; |
226 | | - }); |
227 | | -} |
228 | | -``` |
229 | | - |
230 | | -### ServiceLocator Usage |
231 | | -- Use ServiceLocator pattern to provide dependency injection for static MCP tools |
232 | | -- Always check if assembly is loaded before performing operations |
233 | | -- Use ResponseFormatter.TryExecute() for consistent error handling across all tools |
234 | | - |
235 | | -## Final Development Step |
236 | | - |
237 | | -**Before completing any major work or making the final commit, always review and update `.github/copilot-instructions.md` if:** |
238 | | -- You encountered unexpected patterns or pitfalls during development |
239 | | -- New architectural patterns or testing approaches were discovered |
240 | | -- Additional framework-specific guidance would help future development |
241 | | -- The current instructions have become outdated or incomplete |
242 | | - |
243 | | -**When working on improvements, refer to [TODO.md](../TODO.md) for:** |
244 | | -- Prioritized list of enhancement opportunities |
245 | | -- Detailed context and reasoning for each improvement |
246 | | -- Implementation guidelines and testing requirements |
247 | | -- Technical debt items and maintenance tasks |
| 43 | +## Documentation Policy |
248 | 44 |
|
249 | | -This ensures knowledge from each development cycle is captured for improved efficiency in future work, and provides a systematic approach to project enhancement. |
| 45 | +- Keep durable technical content in `ARCHITECTURE.md`. |
| 46 | +- Keep `README.md` user-facing. |
| 47 | +- Keep `TODO.md` backlog-focused. |
| 48 | +- Do not add new helper, testing, or plan documents unless there is a durable need that cannot fit those files. |
0 commit comments