Skip to content

代码补全

MyDeskBot 的智能代码补全功能基于深度理解您的代码库上下文,提供高质量、相关性强的代码建议。

目录

工作原理

MyDeskBot 的代码补全系统采用多阶段处理流程:

1. 上下文收集

  • 文件分析: 解析当前文件的语法结构
  • 项目扫描: 理解项目整体架构和依赖关系
  • 历史学习: 从您的编码习惯中学习偏好
  • LSP 集成: 结合语言服务器提供类型信息

2. 智能分析

  • 语义理解: 理解代码的语义而非仅文本匹配
  • 模式识别: 识别常见代码模式和最佳实践
  • 类型推断: 基于类型系统提供类型安全建议
  • 风格一致: 保持与项目现有代码风格一致

3. 建议生成

  • 多选项: 提供 3-5 个高质量建议
  • 置信度评分: 每个建议都有置信度指示
  • 实时更新: 随着代码变化动态调整建议
  • 学习能力: 从您的接受/拒绝反馈中学习

使用方式

IntelliJ IDEA

自动触发

开始键入时,MyDeskBot 会自动显示补全建议:

java
public List<User> filterActiveUsers(List<User> users) {
    return users.stream()
        .filter(u -> u.  // MyDeskBot 自动建议: isActive()
        .collect(Collectors.toList());
}

手动触发

  • 快捷键: Ctrl+Shift+Space
  • 菜单: Code → Completion → MyDeskBot

示例场景

场景 1: 实现 CRUD 操作

java
// 输入: public interface UserRepository {
// 光标位置在 { 后,MyDeskBot 建议整个接口定义
public interface UserRepository {
    User findById(Long id);
    List<User> findAll();
    User save(User user);
    void deleteById(Long id);
    boolean existsById(Long id);
}

场景 2: 处理异常

java
try {
    // 危险操作
} catch (  // MyDeskBot 建议合适的异常类型
    SQLException e) {
    log.error("Database error", e);
    throw new RuntimeException("Failed to execute query", e);
}

VS Code

Inline 补全

typescript
// 开始输入,MyDeskBot 以灰色文本显示建议
function calculateArea(radius: number) {
  return Math.PI * r; // MyDeskBot: adius * radius
}

接受建议

  • Tab: 接受整个建议
  • Ctrl+Right Arrow: 接受下一个单词
  • Esc: 拒绝建议

多选项选择

如果有多个建议,使用 Alt+] / Alt+[ 循环选择:

typescript
// 建议 1: return users.filter(u => u.isActive())
// 建议 2: return users.filter(u => u.status === 'active')
// 建议 3: return users.filter(u => u.active)

Neovim

nvim-cmp 集成

lua
-- 配置补全菜单
require('cmp').setup({
  sources = {
    { name = 'nvim_lsp' },
    { name = 'mydeskbot', max_item_count = 3 },
  },
})

手动触发

vim
-- Visual 模式选中代码
:MyDeskBotComplete

上下文感知

文件级上下文

MyDeskBot 理解当前文件的:

  • 导入语句: 只建议已导入的类型和方法
  • 命名空间: 考虑当前命名空间的作用域
  • 类成员: 建议类的字段和方法

示例:

python
# 文件顶部导入
from typing import List, Optional
from datetime import datetime

class User:
    def __init__(self, name: str, email: str):
        self.name = name
        self.email = email

    def get_display_name(self) -> str:
        # MyDeskBot 建议使用 self.name 和 self.email
        return f"{self.name} <{self.email}>"

项目级上下文

MyDeskBot 会扫描项目:

  • 项目结构: 理解目录布局和模块组织
  • 依赖关系: 分析模块间的依赖
  • 配置文件: 读取配置文件(package.json, requirements.txt 等)

示例:

typescript
// 假设项目使用 Express + TypeScript + TypeORM

import { Controller, Get, Post, Body } from "@nestjs/common";
import { User } from "./user.entity";

@Controller("users")
export class UsersController {
  // MyDeskBot 基于项目结构建议完整实现
  @Get()
  async findAll(): Promise<User[]> {
    return this.userService.findAll();
  }

  @Post()
  async create(@Body() createUserDto: CreateUserDto): Promise<User> {
    return this.userService.create(createUserDto);
  }
}

跨文件引用

MyDeskBot 理解跨文件的引用关系:

javascript
// file1.js
export const API_BASE = "https://api.example.com";

export async function fetchUser(id) {
  const response = await fetch(`${API_BASE}/users/${id}`);
  return response.json();
}

// file2.js
import { fetchUser, API_BASE } from "./file1.js";

// MyDeskBot 知道这些是从 file1.js 导入的
const user = await fetchUser(123);
console.log(user);

类型感知

对于类型化语言,MyDeskBot 利用类型信息:

typescript
interface Product {
  id: number;
  name: string;
  price: number;
  category: string;
}

function formatProduct(product: Product): string {
  // MyDeskBot 知道 product 有 id, name, price, category 字段
  return `[${product.id}] ${product.name} - $${product.price}`;
}

最佳实践

1. 编写清晰的意图

❌ 不好的代码:

python
def d(l):
    # 不清晰的变量名
    pass

✅ 好的代码:

python
def download_large_file(url: str) -> None:
    # 清晰的函数名和类型提示
    pass

MyDeskBot 能更好地理解有清晰命名和类型提示的代码。

2. 保持一致性

在整个项目中保持一致的命名和风格:

java
// 项目统一使用下划线命名
private String user_name;
private String email_address;

// MyDeskBot 会继续使用相同风格建议
public String get_user_id() {
    return user_id;
}

3. 使用类型注解

类型注解能大幅提高补全质量:

python
# 无类型
def process(data):
    return data.upper()  # MyDeskBot 不确定 data 是否有 upper() 方法

# 有类型
def process(data: str) -> str:
    return data.upper()  # MyDeskBot 确信可以建议 upper() 方法

4. 添加有用的注释

注释可以帮助 MyDeskBot 理解您的意图:

javascript
// 计算两个日期之间的工作日数量(排除周末)
function countWeekdays(start, end) {
  // MyDeskBot 基于注释建议实现
  let count = 0;
  let current = new Date(start);
  while (current <= end) {
    const day = current.getDay();
    if (day !== 0 && day !== 6) {
      // 排除周日(0)和周六(6)
      count++;
    }
    current.setDate(current.getDate() + 1);
  }
  return count;
}

5. 利用现有模式

MyDeskBot 会学习和重复项目中的模式:

typescript
// 项目中的模式:使用 async/await + 错误处理
async function getUser(id: number): Promise<User> {
  try {
    const response = await fetch(`/api/users/${id}`);
    if (!response.ok) {
      throw new Error(`HTTP error! status: ${response.status}`);
    }
    return await response.json();
  } catch (error) {
    console.error("Failed to fetch user:", error);
    throw error;
  }
}

// MyDeskBot 会建议类似模式的实现
async function getPost(id: number): Promise<Post> {
  try {
    const response = await fetch(`/api/posts/${id}`);
    if (!response.ok) {
      throw new Error(`HTTP error! status: ${response.status}`);
    }
    return await response.json();
  } catch (error) {
    console.error("Failed to fetch post:", error);
    throw error;
  }
}

高级技巧

1. 使用框架约定

MyDeskBot 了解常见框架的约定:

java
// Spring Boot REST 控制器模式
@RestController
@RequestMapping("/api/products")
public class ProductController {

    @GetMapping("/{id}")
    public ResponseEntity<Product> getProduct(@PathVariable Long id) {
        // MyDeskBot 建议标准的 CRUD 模式
        return productService.findById(id)
            .map(ResponseEntity::ok)
            .orElse(ResponseEntity.notFound().build());
    }
}

2. 链式调用

javascript
// JavaScript 数组链式调用
const activeUsers = users
  .filter((user) => user.active)
  .map((user) => ({
    id: user.id,
    name: user.name,
  }))
  .sort((a, b) => a.name.localeCompare(b.name));

// MyDeskBot 能建议完整的链式调用
const inactiveUsers = users
  .filter((user) => !user.active) // 建议相反条件
  .map((user) => ({
    id: user.id,
    name: user.name,
    lastLogin: user.lastLogin, // 建议额外字段
  }))
  .sort((a, b) => b.lastLogin - a.lastLogin); // 建议降序排序

3. 模式匹配

rust
// Rust 模式匹配
enum Result<T, E> {
    Ok(T),
    Err(E),
}

fn handle_result(result: Result<i32, String>) {
    // MyDeskBot 建议完整的模式匹配
    match result {
        Ok(value) => println!("成功: {}", value),
        Err(error) => eprintln!("错误: {}", error),
    }
}

4. 装饰器模式

python
# Python 装饰器
def validate_email(func):
    def wrapper(email):
        if '@' not in email:
            raise ValueError("Invalid email")
        return func(email)
    return wrapper

@validate_email
def send_notification(email: str) -> None:
    # MyDeskBot 知道这里 email 已经过验证
    print(f"Sending notification to {email}")

常见问题

Q: 补全建议不准确怎么办?

A: 确保代码库有清晰的结构、类型注解和注释。MyDeskBot 依赖于代码的上下文信息。

Q: 如何禁用自动补全?

A: 在设置中关闭自动触发,只使用手动触发快捷键。

Q: 补全速度慢怎么办?

A: 可以调整上下文收集的范围,减少扫描的文件数量。

Q: 支持哪些语言?

A: 支持 JavaScript, TypeScript, Python, Java, Go, Rust, C++, C#, PHP, Ruby 等主流语言。

下一步

相关资源