extract_function
Extract selected code into a new function to improve code structure and maintainability through refactoring.
Instructions
Extract selected code into a new function
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| file | Yes | File containing the code to extract | |
| startLine | Yes | Start line of code to extract | |
| startCharacter | No | Start character position | |
| endLine | Yes | End line of code to extract | |
| endCharacter | No | End character position | |
| functionName | Yes | Name for the new function | |
| language | No | Programming language | typescript |
Implementation Reference
- src/commands/extractFunction.ts:6-91 (handler)Main execution logic for the 'extract_function' MCP tool. Opens the file in LSP, requests code actions with 'refactor.extract.function' context, applies the first available workspace edit to perform the extraction.export async function extractFunction(args: ExtractFunctionArgs, clientManager: LSPClientManager) { const { file, startLine, startCharacter = 0, endLine, endCharacter = 0, functionName: _functionName, language = 'typescript', } = args; const workspaceRoot = findWorkspaceRoot(file); try { const client = await clientManager.getOrCreateLSPClient(language, workspaceRoot); // Open the file const content = await fs.readFile(file, 'utf-8'); await clientManager.sendLSPNotification(client, 'textDocument/didOpen', { textDocument: { uri: `file://${file}`, languageId: language, version: 1, text: content, }, }); // Request LSP code actions for extract function const codeActions = await clientManager.sendLSPRequest(client, 'textDocument/codeAction', { textDocument: { uri: `file://${file}` }, range: { start: { line: startLine - 1, character: startCharacter }, end: { line: endLine - 1, character: endCharacter }, }, context: { diagnostics: [], only: ['refactor.extract.function'], }, }); const actions = Array.isArray(codeActions) ? codeActions : []; if (actions.length === 0) { return { content: [ { type: 'text', text: `No extract function refactoring available for the selected range in ${file}. This could be because the range does not contain extractable code or the language server doesn't support this refactoring.`, }, ], }; } // Apply the first extract function action const action = actions[0]; if (!action.edit) { return { content: [ { type: 'text', text: `Extract function code action does not contain workspace edit. The language server may not be configured properly for refactoring operations.`, }, ], }; } const { applyWorkspaceEdit } = await import('../lsp/utils.js'); await applyWorkspaceEdit(action.edit); return { content: [ { type: 'text', text: `Successfully extracted function from lines ${startLine}-${endLine} in ${file}`, }, ], }; } catch (error) { return { content: [ { type: 'text', text: `Failed to extract function: ${error instanceof Error ? error.message : String(error)}`, }, ], }; } }
- src/server.ts:102-142 (registration)Registration of the 'extract_function' tool in the MCP server's listTools handler, including name, description, and input schema.{ name: 'extract_function', description: 'Extract selected code into a new function', inputSchema: { type: 'object', properties: { file: { type: 'string', description: 'File containing the code to extract', }, startLine: { type: 'number', description: 'Start line of code to extract', }, startCharacter: { type: 'number', description: 'Start character position', default: 0, }, endLine: { type: 'number', description: 'End line of code to extract', }, endCharacter: { type: 'number', description: 'End character position', default: 0, }, functionName: { type: 'string', description: 'Name for the new function', }, language: { type: 'string', description: 'Programming language', default: 'typescript', }, }, required: ['file', 'startLine', 'endLine', 'functionName'], }, },
- src/server.ts:216-217 (registration)Dispatch handler in the CallToolRequestSchema that invokes the extractFunction handler for the 'extract_function' tool.case 'extract_function': return await extractFunction(args as unknown as ExtractFunctionArgs, this.clientManager);
- src/types.ts:62-70 (schema)TypeScript interface defining the input arguments for the extract_function tool handler.export interface ExtractFunctionArgs { file: string; startLine: number; startCharacter?: number; endLine: number; endCharacter?: number; functionName: string; language?: string; }
- src/lsp/utils.ts:119-140 (helper)Utility function used by the handler to apply the LSP workspace edit resulting from the extract function refactoring.export async function applyWorkspaceEdit(edit: LSPWorkspaceEdit): Promise<void> { if (edit.changes) { for (const [uri, changes] of Object.entries(edit.changes)) { const filePath = uri.replace('file://', ''); const content = await fs.readFile(filePath, 'utf-8'); const lines = content.split('\n'); // Apply changes in reverse order to maintain line numbers const sortedChanges = changes.sort((a, b) => b.range.start.line - a.range.start.line); for (const change of sortedChanges) { const startLine = change.range.start.line; const endLine = change.range.end.line; const newText = change.newText; lines.splice(startLine, endLine - startLine + 1, ...newText.split('\n')); } await fs.writeFile(filePath, lines.join('\n')); } } }