Files
XericLibrary-WebGL-Publish/Documentation~/MacroObjectAnalyzerReadme.md
T
2026-06-24 15:16:59 +08:00

327 lines
8.1 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# XericUnityAnalyzer 规则文档
## 所有诊断规则一览
本文档列出 `com.lrss3.deconstruction` 包中 `XericUnityAnalyzer` Roslyn 分析器的所有诊断规则,
涵盖 MacroObject(Unity 层级/组件操作)和 MacroString(TextBlockBuilder 富文本)的优化建议。
---
### XRX0001 — 重复访问 Transform.parent 属性
| 属性 | 值 |
|------|---|
| 分类 | Usage |
| 严重性 | Warning |
**触发条件:** 对 Transform 对象的 `.parent` 属性进行重复链式访问(直接链式、变量中转、赋值链)。
**示例:**
```csharp
// 触发警告
transform.parent.parent;
Transform p = transform.parent;
p.parent; // ← 这里报警
```
**建议方案:** `MacroObject.GetParents()` 扩展方法,返回 `IEnumerable<Transform>`。
---
### XRX0002 — 重复调用 GetParents()
| 属性 | 值 |
|------|---|
| 分类 | Performance |
| 严重性 | Warning |
**触发条件:** 在同一方法中对同一对象调用 `GetParents()` 超过 1 次。
**示例:**
```csharp
// 触发警告
transform.GetParents();
transform.GetParents(); // ← 第二次调用报警
```
**建议方案:** `MacroObject.GetParentsSafety()` 扩展方法,返回 `IList<Transform>` 可复用。
---
### XRX0003 — 重复调用 GetChild()
| 属性 | 值 |
|------|---|
| 分类 | Performance |
| 严重性 | Warning |
**触发条件:** 在同一方法中对同一对象调用 `Transform.GetChild()` 超过 1 次。
**示例:**
```csharp
// 触发警告
transform.GetChild(0);
transform.GetChild(1); // ← 第二次调用报警
```
**建议方案:** `MacroObject.GetChildren()` 扩展方法,一次性获取所有子节点。
---
### XRX0004 — for 循环 + GetChild 遍历子节点
| 属性 | 值 |
|------|---|
| 分类 | Usage |
| 严重性 | Warning |
**触发条件:** 使用 `for (int i = 0; i < xxx.childCount; i++)` 配合 `GetChild(i)` 遍历子节点。
**示例:**
```csharp
// 触发警告
for (int i = 0; i < transform.childCount; i++)
{
transform.GetChild(i); // ← 建议替换为 foreach
}
```
**建议方案:** `MacroObject.GetChildren()` 扩展方法,配合 `foreach` 更简洁。
---
### XRX0005 — 重复调用 GetChildren()
| 属性 | 值 |
|------|---|
| 分类 | Performance |
| 严重性 | Warning |
**触发条件:** 在同一方法中对同一对象调用 `GetChildren()` 超过 1 次。
**示例:**
```csharp
// 触发警告
transform.GetChildren();
transform.GetChildren(); // ← 第二次调用报警
```
**建议方案:** `MacroObject.GetChildrenSafety()` 扩展方法,返回 `IList<Transform>` 可复用。
---
### XRX0006 — GetChildren 后提取 gameObject
| 属性 | 值 |
|------|---|
| 分类 | Usage |
| 严重性 | Warning |
**触发条件:** 对 `GetChildren()` 结果使用 `.Select(x => x.gameObject)` 或 LINQ 查询提取 gameObject。
**示例:**
```csharp
// 触发警告
transform.GetChildren().Select(c => c.gameObject);
// 或
from c in transform.GetChildren() select c.gameObject;
```
**建议方案:** `MacroObject.GetChildrenGameObject()` 扩展方法,直接返回 `IEnumerable<GameObject>`。
---
### XRX0007 — 嵌套遍历子节点层级
| 属性 | 值 |
|------|---|
| 分类 | Usage |
| 严重性 | Warning |
**触发条件:** 嵌套调用 `GetChildren()` 或嵌套使用 for + GetChild 遍历多层子节点。
**示例:**
```csharp
// 触发警告
foreach (var child in transform.GetChildren())
{
foreach (var grandchild in child.GetChildren()) // ← 嵌套报警
{
// ...
}
}
```
**建议方案:** `MacroObject.GetChildrenBFS()` 扩展方法,BFS 一步到位返回所有层级子节点。
---
### XRX0008 — 在 parent 和 GetChild 之间跳跃访问
| 属性 | 值 |
|------|---|
| 分类 | Usage |
| 严重性 | Warning |
**触发条件:** 在同一方法中对同一对象同时访问 `.parent` 属性和调用 `GetChild()` 方法。
**示例:**
```csharp
// 触发警告
var p = transform.parent; // ← 访问父级
var c = transform.GetChild(0); // ← 访问子级
// 可能在寻找兄弟节点
```
**建议方案:** `MacroObject.GetBrother()` 扩展方法,返回所有兄弟节点。
---
### XRX0009 — GetComponent 判空后 AddComponent
| 属性 | 值 |
|------|---|
| 分类 | Usage |
| 严重性 | Warning |
**触发条件:** 先调用 `GetComponent<T>()`,判空后再调用 `AddComponent<T>()` 的"获取或添加"模式。
**示例:**
```csharp
// 触发警告
var comp = obj.GetComponent<Image>();
if (comp == null)
comp = obj.AddComponent<Image>();
```
**建议方案:** `MacroObject.GetComponentAnyway<T>()` 扩展方法,一步完成获取或添加。
---
### XRX0010 — 对枚举器逐项 GetComponent
| 属性 | 值 |
|------|---|
| 分类 | Usage |
| 严重性 | Warning |
**触发条件:** 在 `.Select()` / `foreach` / `for` 循环中对成员逐项调用 `GetComponent`。
**示例:**
```csharp
// 触发警告
transform.GetChildren().Select(c => c.GetComponent<Image>());
// 或
foreach (var child in transform.GetChildren())
child.GetComponent<Image>(); // ← 逐项报警
```
**建议方案:** `MacroObject.IEnumerable.GetComponent<T>()` 扩展方法,针对枚举器直接提取组件。
---
### XRX0011 — 循环中查找特定组件后跳出
| 属性 | 值 |
|------|---|
| 分类 | Usage |
| 严重性 | Warning |
**触发条件:** 在循环中逐项 GetComponent 并在找到后判空 break 的"搜索组件"模式。
**示例:**
```csharp
// 触发警告
Image found = null;
foreach (var child in transform.GetChildren())
{
found = child.GetComponent<Image>();
if (found != null) break; // ← 搜索模式报警
}
```
**建议方案:** `MacroObject.IEnumerable.GetComponent<T>(out T comp)` 扩展方法,一次完成搜索。
---
### XRX0012 — 通过名称查找返回对象
| 属性 | 值 |
|------|---|
| 分类 | Usage |
| 严重性 | Warning |
**触发条件:** 遍历子节点并比较 `.name` 来查找特定名称的对象(foreach + name == "xxx" + return)。
**示例:**
```csharp
// 触发警告
foreach (var child in transform.GetChildren())
{
if (child.name == "Target") // ← 名称比较
return child; // ← 找到返回
}
// 或 LINQ:
transform.GetChildren().FirstOrDefault(c => c.name == "Target");
```
**建议方案:** `MacroObject.FindFamilyMember()` / `FindFamilyMemberExact()` / `FindFamilyMemberFuzzy()` 扩展方法。
---
### XRX0101 — 富文本字符串字面量
| 属性 | 值 |
|------|---|
| 分类 | Usage |
| 严重性 | Warning |
**触发条件:** 检测到字符串字面量中包含类似 XML 的 Unity 富文本标签(如 `<b>`, `<color=...>`, `<line-height=...>` 等)。
**示例:**
```csharp
// 触发警告
var text = "<b>abc</b>";
```
**建议方案:** 使用 **TextBlockBuilder 包裹器语法** 或 **BlockUtilKit 框架语法** 进行类型安全构建:
<!-- 代码修复 1: TextBlockBuilder 语法 -->
```csharp
// 优化为 TextBlockBuilder 语法
new TextBlockBuilder()
{
new BBlock("abc")
}
```
<!-- 代码修复 2: 框架语法 -->
```csharp
// 优化为框架语法(配合 using static BlockUtilKit)
Pure(
B(Label("abc"))
).BuildBlockByAgentOnce()
```
**注意:** 此规则提供两个 CodeFix 选项——"转换为 TextBlockBuilder 语法"和"转换为框架语法",可通过 IDE 的自动修复功能直接应用。
---
## 规则索引
| ID | 规则标题 | 文件 |
|----|---------|------|
| XRX0001 | 重复访问 parent 属性 | ObjectRelation |
| XRX0002 | 重复调用 GetParents() | ObjectRelation |
| XRX0003 | 重复调用 GetChild() | ObjectRelation |
| XRX0004 | for 循环 + GetChild 遍历 | ObjectRelation |
| XRX0005 | 重复调用 GetChildren() | ObjectRelation |
| XRX0006 | GetChildren + Select gameObject | ObjectRelation |
| XRX0007 | 嵌套遍历子节点层级 | ObjectRelation |
| XRX0008 | parent 和 GetChild 跳跃访问 | ObjectRelation |
| XRX0009 | GetComponent + AddComponent | ComponentSearch |
| XRX0010 | 枚举器逐项 GetComponent | ComponentSearch |
| XRX0011 | 循环查找特定组件 | ComponentSearch |
| XRX0012 | 名称查找返回对象 | FamilyNaming |
| XRX0101 | 富文本字符串字面量 | RichTextDetection |