list_symbols
List all symbols in a Rust crate to explore available types and paths. Includes structs, enums, and traits, aiding in trait implementation and code navigation.
Instructions
List all symbols in a crate. Use when implementing traits or exploring available types. Shows structs, enums, traits with their paths.
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| crate_name | Yes | Name of the crate to list symbols for | |
| project_path | Yes | Path to the Rust project (must be absolute path) |
Implementation Reference
- src/doc-manager.ts:284-325 (handler)Core implementation of the list_symbols tool. Traverses the crate's documentation directory, parses symbols from HTML filenames using helpers, collects SymbolInfo objects, sorts them by path, and returns the list.public async listSymbols(projectPath: string, crateName: string): Promise<SymbolInfo[]> { const isBuilt = await this.checkDoc(projectPath, crateName); if (!isBuilt) { throw new DocError( DocErrorCode.SEARCH_FAILED, 'Failed to access documentation' ); } const cached = await this.cache.get(projectPath, crateName); if (!cached) { throw new DocError( DocErrorCode.CACHE_ERROR, 'Cache error: Documentation entry not found' ); } try { const { docPath } = cached; const docDir = path.dirname(docPath); const symbols: SymbolInfo[] = []; // 定义符号收集处理函数 const symbolHandler = async (fileName: string, filePath: string, modulePath: string) => { const symbol = this.parseSymbolFromFile(fileName, modulePath, crateName, filePath); if (symbol) { symbols.push(symbol); } }; // 使用通用的traverseDirectory收集符号 await this.traverseDirectory(docDir, crateName, '', symbolHandler); return symbols.sort((a, b) => a.path.localeCompare(b.path)); } catch (error) { throw new DocError( DocErrorCode.SEARCH_FAILED, 'Failed to list symbols', error ); } }
- src/index.ts:172-194 (handler)MCP server tool call handler for list_symbols. Extracts project_path and crate_name from arguments, invokes docManager.listSymbols, formats the output as structured text content with symbol counts, types, paths, and URLs.case "list_symbols": { const { project_path, crate_name } = request.params.arguments as { project_path: string; crate_name: string; }; const symbols = await docManager.listSymbols(project_path, crate_name); return { content: [ { type: "text", text: `Found ${symbols.length} symbols:\n`, }, { type: "text", text: symbols .map((sym) => `${sym.type} ${sym.path}\n URL: ${sym.url}`) .join("\n"), }, ], }; }
- src/index.ts:106-123 (registration)Registration of the list_symbols tool in the ListToolsRequestSchema response, including name, description, and input schema definition.{ name: "list_symbols", description: "List all symbols in a crate. Use when implementing traits or exploring available types. Shows structs, enums, traits with their paths.", inputSchema: { type: "object", properties: { project_path: { type: "string", description: "Path to the Rust project (must be absolute path)", }, crate_name: { type: "string", description: "Name of the crate to list symbols for", }, }, required: ["project_path", "crate_name"], }, },
- src/doc-manager.ts:219-237 (helper)Helper function parseSymbolFromFile used by listSymbols to extract SymbolInfo (name, type, path, url) from documentation HTML filenames via regex matching.private parseSymbolFromFile(fileName: string, modulePath: string, crateName: string, filePath: string): SymbolInfo | null { const match = fileName.match(/^(struct|enum|trait|fn|const|type|macro|mod)\.(.+)\.html$/); if (!match) { return null; } const [, type, name] = match; const symbolName = name.replace(/-/g, '::'); const fullPath = modulePath ? `${crateName}::${modulePath}::${symbolName}` : `${crateName}::${symbolName}`; return { name: symbolName, type: type as SymbolType, path: fullPath, url: RustdocUrl.create(filePath) }; }
- src/doc-manager.ts:249-279 (helper)Helper function traverseDirectory used by listSymbols to recursively walk the documentation directory, skipping certain dirs, building module paths, and invoking fileHandler on relevant HTML files.private async traverseDirectory( docDir: string, crateName: string, modulePath: string = '', fileHandler: (fileName: string, filePath: string, modulePath: string) => Promise<void> ): Promise<void> { const entries = await fs.readdir(docDir, { withFileTypes: true }); for (const entry of entries) { if (entry.isDirectory()) { // 跳过特殊目录 if (entry.name === 'src' || entry.name === 'implementors') { continue; } // 递归遍历子目录 const nextModulePath = modulePath ? `${modulePath}::${entry.name}` : entry.name; await this.traverseDirectory( path.join(docDir, entry.name), crateName, nextModulePath, fileHandler ); } else if (entry.name.endsWith('.html') && entry.name !== 'index.html') { await fileHandler(entry.name, path.join(docDir, entry.name), modulePath); } } }