# CSharpStringExtractor.ts 核心逻辑详细说明

本文档详细解释 CSharpStringExtractor.ts 文件中的核心逻辑，特别是代码语句边界识别和状态机实现。

---

## 1. 状态机变量说明

在多个提取方法中使用以下状态变量来跟踪代码解析状态：

### 1.1 基础状态变量

| 变量名 | 类型 | 说明 |
|--------|------|------|
| `inString` | boolean | 是否在字符串内部。避免将字符串内的分号、斜杠等当作代码分隔符处理 |
| `escapeNext` | boolean | 是否遇到转义字符（反斜杠 `\`）。设置为 true 时，下一个字符会被跳过，不作为特殊字符处理 |
| `stringDelimiter` | string | 字符串分隔符。`'\\"` 表示双引号字符串，`'\\'` 表示单引号字符串 |
| `inComment` | boolean | 是否在注释内部 |
| `commentType` | string | 注释类型。`'//'` 表示单行注释，`'/*'` 表示多行注释 |

### 1.2 深度计数变量

| 变量名 | 类型 | 说明 |
|--------|------|------|
| `parenthesesDepth` | number | 圆括号 `()` 深度。用于判断分号是否在括号内（如 for 循环、函数调用等） |
| `braceDepth` | number | 大括号 `{}` 深度。用于识别代码块边界 |

### 1.3 位置追踪变量

| 变量名 | 类型 | 说明 |
|--------|------|------|
| `statementStartIndex` | number | 语句开始位置。用于截取完整的语句 |
| `i` | number | 当前遍历的字符索引 |

---

## 2. 语句边界识别逻辑

### 2.1 主循环结构

```typescript
while (i < code.length) {
    const char = code[i];
    const nextChar = i + 1 < code.length ? code[i + 1] : '';
    
    // 按优先级处理各种情况
    // 1. 处理注释
    // 2. 处理转义字符
    // 3. 处理字符串
    // 4. 识别注释开始
    // 5. 括号深度计数
    // 6. 大括号处理
    // 7. 语句边界识别
    
    i++;
}
```

### 2.2 处理优先级

#### 优先级 1: 处理注释内部
```typescript
if (inComment) {
    if (commentType === '//') {
        // 单行注释：遇到换行符结束
        if (char === '\n') {
            inComment = false;
            commentType = '';
            statementStartIndex = i + 1;
        }
    } else if (commentType === '/*') {
        // 多行注释：遇到 */ 结束
        if (char === '*' && nextChar === '/') {
            i++;
            inComment = false;
            commentType = '';
            statementStartIndex = i + 1;
        }
    }
    i++;
    continue;  // 跳过其他处理
}
```

**要点**：
- 注释内的所有字符都被跳过
- 单行注释 `//` 以换行符 `\n` 结束
- 多行注释 `/* */` 需要匹配结束标记 `*/`

#### 优先级 2: 处理转义字符
```typescript
// 遇到反斜杠，设置转义标志，下一个字符不作为特殊字符处理
if (escapeNext) {
    escapeNext = false;
    i++;
    continue;
}

// 遇到反斜杠，设置转义标志
if (char === '\\') {
    escapeNext = true;
    i++;
    continue;
}
```

**要点**：
- `\` 是转义字符的开始
- 设置 `escapeNext = true` 后，下一个字符会被原样保留
- 这确保了字符串内的 `\"`、`\\` 等不会被误识别

#### 优先级 3: 处理字符串
```typescript
if (char === '"' || char === '\'') {
    if (!inString) {
        // 字符串开始
        inString = true;
        stringDelimiter = char;
    } else if (char === stringDelimiter) {
        // 字符串结束（遇到相同分隔符）
        inString = false;
        stringDelimiter = '';
    }
    i++;
    continue;
}
```

**要点**：
- 只有遇到与开始时相同的引号才结束字符串
- 单引号和双引号分别处理
- 字符串内的所有字符都被跳过

#### 优先级 4: 识别注释开始
```typescript
// 只有在字符串外部才能识别注释开始
if (!inString && char === '/' && nextChar === '/') {
    inComment = true;
    commentType = '//';
    statementStartIndex = i + 2;
    i++;
    continue;
}
if (!inString && char === '/' && nextChar === '*') {
    inComment = true;
    commentType = '/*';
    statementStartIndex = i + 2;
    i++;
    continue;
}
```

**要点**：
- 必须在字符串外部才能识别注释开始
- 这避免了字符串内的 `/` 被误识别为注释

#### 优先级 5: 括号深度计数
```typescript
// 只有在字符串和注释外部才计数
if (!inString && char === '(') {
    parenthesesDepth++;
}
if (!inString && char === ')') {
    parenthesesDepth--;
}
```

**要点**：
- 用于判断分号是否在括号内
- `for (int i = 0; i < 10; i++)` 中的分号不应被识别为语句边界

#### 优先级 6: 大括号处理
```typescript
// 遇到大括号时更新语句起始位置（代码块边界）
if (!inString && (char === '{' || char === '}')) {
    statementStartIndex = i + 1;
}
```

**要点**：
- 代码块边界需要重置语句起始位置

#### 优先级 7: 语句边界识别
```typescript
// 只有在字符串外部、注释外部、括号深度为0时，分号才表示语句结束
if (char === ';' && !inString && parenthesesDepth === 0) {
    const fullStatement = code.substring(statementStartIndex, i + 1);
    const statement = fullStatement.trim();
    // ... 处理语句
}
```

**要点**：
- 三个条件必须同时满足：`!inString && !inComment && parenthesesDepth === 0`
- 这是语句边界识别的核心逻辑

---

## 3. 字符串类型识别

### 3.1 普通字符串
- 双引号字符串：`"Hello World"`
- 单引号字符串：`'Hello World'`

### 3.2 插值字符串
- 标准插值：`$"Hello {name}"`
- 原生插值：`$@"Hello {name}"` 或 `@$"Hello {name}"`

### 3.3 多行字符串
- 原生字符串：`@"Hello\nWorld"`

---

## 4. 关键方法说明

### 4.1 findMatchingParenthesis
查找匹配的圆括号位置。

```typescript
private findMatchingParenthesis(code: string, startIndex: number): number
```

**逻辑**：
1. 从 startIndex 开始查找 `(` 
2. 使用括号深度计数器追踪
3. 遇到 `(` 深度+1，遇到 `)` 深度-1
4. 深度为0时找到匹配位置

### 4.2 splitArguments
分割函数参数列表。

```typescript
private splitArguments(argsString: string): string[]
```

**逻辑**：
1. 遍历参数字符串
2. 跟踪括号深度（处理嵌套调用）
3. 遇到逗号且括号深度为0时分割

### 4.3 splitExpression
分割表达式（按+号分割）。

```typescript
private splitExpression(expression: string): string[]
```

**逻辑**：
1. 跳过字符串内容
2. 跟踪括号深度
3. 遇到 `+` 且深度为0时分割

---

## 5. 边界情况处理

### 5.1 嵌套括号
```csharp
string.Format("Hello {0}", GetName(arg1, arg2))
```
- 外层括号深度为1时，遇到逗号不分割
- 内层括号深度为2时，逗号被忽略

### 5.2 字符串内的分号
```csharp
string s = "Hello;World";  // 分号在字符串内，不作为语句边界
```

### 5.3 转义字符
```csharp
string s = "Hello\"World";  // \" 不是字符串结束
```

### 5.4 多行字符串
```csharp
string s = @"Line 1
Line 2";  // 换行符在字符串内
```

---

## 6. 测试验证要点

### 6.1 originalIndex 精确性
- `originalIndex` 必须精确指向原始代码中的位置
- 测试用例通过 `code.indexOf(expectedString)` 验证位置

### 6.2 内容完整性
- 提取的字符串内容必须与原始代码完全一致
- 包括空格、缩进、转义字符等

---

## 流程7. 代码图

```
开始遍历
    │
    ▼
┌─────────────────┐
│  在注释内?      │──是──▶  处理注释内部逻辑
└────────┬────────┘
         │否
         ▼
┌─────────────────┐
│  转义字符?      │──是──▶  设置 escapeNext, 跳过下一字符
└────────┬────────┘
         │否
         ▼
┌─────────────────┐
│  字符串内?      │──是──▶  更新字符串状态
└────────┬────────┘
         │否
         ▼
┌─────────────────┐
│  注释开始?      │──是──▶  进入注释模式
└────────┬────────┘
         │否
         ▼
┌─────────────────┐
│  括号?          │──是──▶  更新括号深度
└────────┬────────┘
         │否
         ▼
┌─────────────────┐
│  分号边界?      │──是──▶  提取语句
└────────┬────────┘
         │否
         ▼
    继续下一字符
```
