diff --git a/README.md b/README.md
index a5773d9..ef0c866 100644
--- a/README.md
+++ b/README.md
@@ -4,21 +4,16 @@
## 安装
-### 从NuGet安装
-
```bash
dotnet add package TypeScriptParser
```
-或通过包管理器控制台:
-
-```powershell
-Install-Package TypeScriptParser
-```
+## 文档
-也可以访问 [NuGet包页面](https://www.nuget.org/packages/TypeScriptParser) 查看更多安装选项。
+- [使用指南](docs/USAGE_GUIDE.md) - 快速开始和常用示例
+- [API参考](docs/API_REFERENCE.md) - 完整的API文档
-## 快速开始
+## 构建项目
```bash
# 1. 构建native库
@@ -36,6 +31,10 @@ dotnet test --configuration Release
# 4. 打包NuGet包
dotnet pack -c Release -o ./artifacts
+
+# 5. 测试打包
+dotnet package add TypeScriptParser --project TypeScriptParser.TestPackage/ --version 0.0.1-dev
+dotnet test TypeScriptParser.TestPackage
```
## 项目结构
@@ -44,15 +43,7 @@ dotnet pack -c Release -o ./artifacts
- [`TypeScriptParser.Native/`](TypeScriptParser.Native/) - 跨平台Native库包
- [`TypeScriptParser.Tests/`](TypeScriptParser.Tests/) - 单元测试
-## 开发指南
-
-### Debug模式构建
-```bash
-dotnet build -c Debug
-dotnet test --configuration Debug
-```
-
-### 支持平台
+## 支持平台
- Linux x64
- macOS ARM64
- Windows x64
diff --git a/TypeScriptParser.TestPackage/TypeScriptParser.TestPackage.csproj b/TypeScriptParser.TestPackage/TypeScriptParser.TestPackage.csproj
index b8d1e63..1735d3c 100644
--- a/TypeScriptParser.TestPackage/TypeScriptParser.TestPackage.csproj
+++ b/TypeScriptParser.TestPackage/TypeScriptParser.TestPackage.csproj
@@ -5,6 +5,8 @@
enable
enable
false
+
+ $(NoWarn);CS1591
diff --git a/TypeScriptParser.TestPackage/UnitTest1.cs b/TypeScriptParser.TestPackage/UnitTest1.cs
index 8a3f826..4b738b9 100644
--- a/TypeScriptParser.TestPackage/UnitTest1.cs
+++ b/TypeScriptParser.TestPackage/UnitTest1.cs
@@ -1,4 +1,5 @@
using Xunit;
+using TypeScriptParser;
namespace TypeScriptParser.TestPackage;
@@ -7,14 +8,16 @@ public class UnitTest1
[Fact]
public void Can_Create_Parser()
{
- using var parser = new TreeSitter.TypeScript.TypeScriptParser();
- Assert.True(parser.IsAvailable);
+ using var parser = new Parser();
+ // 通过能否成功解析来验证Parser可用性
+ var tree = parser.ParseString("const x = 1;");
+ Assert.NotNull(tree);
}
[Fact]
public void Can_Parse_Code()
{
- using var parser = new TreeSitter.TypeScript.TypeScriptParser();
+ using var parser = new Parser();
var tree = parser.ParseString("const x = 1;");
Assert.Equal("program", tree.root_node().type());
}
diff --git a/TypeScriptParser.Tests/TypeScriptAnalyzer.cs b/TypeScriptParser.Tests/TypeScriptAnalyzer.cs
index 153b9f8..de80345 100644
--- a/TypeScriptParser.Tests/TypeScriptAnalyzer.cs
+++ b/TypeScriptParser.Tests/TypeScriptAnalyzer.cs
@@ -1,9 +1,10 @@
using System;
using System.Collections.Generic;
-using GitHub.TreeSitter;
+using TypeScriptParser.TreeSitter;
using System.Runtime.InteropServices;
+using TypeScriptParser;
-namespace TreeSitter.TypeScript
+namespace TypeScriptParser.Tests
{
// 参数信息结构
public class Parameter
@@ -28,13 +29,13 @@ public class ExportedFunction
// TypeScript分析器模块
public class TypeScriptAnalyzer : IDisposable
{
- private readonly TypeScriptParser parser;
+ private readonly Parser parser;
private readonly List exportedFunctions = [];
private bool disposed = false;
public TypeScriptAnalyzer()
{
- parser = new TypeScriptParser();
+ parser = new Parser();
}
public List AnalyzeFile(string fileContent)
@@ -49,7 +50,7 @@ public List AnalyzeFile(string fileContent)
return exportedFunctions;
}
- using var cursor = parser.CreateCursor(tree);
+ using var cursor = new TSCursor(tree.root_node(), tree.language());
TraverseForExports(cursor, fileContent);
return [.. exportedFunctions];
diff --git a/TypeScriptParser.Tests/TypeScriptParser.Tests.csproj b/TypeScriptParser.Tests/TypeScriptParser.Tests.csproj
index fc13e17..818c315 100644
--- a/TypeScriptParser.Tests/TypeScriptParser.Tests.csproj
+++ b/TypeScriptParser.Tests/TypeScriptParser.Tests.csproj
@@ -6,6 +6,8 @@
disable
false
true
+
+ $(NoWarn);CS1591
diff --git a/TypeScriptParser.Tests/tests/ExportExtractorTests.cs b/TypeScriptParser.Tests/tests/ExportExtractorTests.cs
new file mode 100644
index 0000000..6609e6d
--- /dev/null
+++ b/TypeScriptParser.Tests/tests/ExportExtractorTests.cs
@@ -0,0 +1,197 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using Xunit;
+using TypeScriptParser;
+using TypeScriptParser.TreeSitter;
+
+namespace TypeScriptParser.Tests
+{
+ public class ExportExtractorTests
+ {
+ [Fact]
+ public void ExtractExportFunctions_SimpleExport_ShouldReturnFunctionNames()
+ {
+ // Arrange
+ string code = @"
+export function add(a: number, b: number): number {
+ return a + b;
+}
+
+export function multiply(x: number, y: number): number {
+ return x * y;
+}";
+
+ // Act
+ var exportedFunctions = ExtractExportFunctions(code);
+
+ // Assert
+ Assert.Equal(2, exportedFunctions.Count);
+ Assert.Contains("add", exportedFunctions);
+ Assert.Contains("multiply", exportedFunctions);
+ }
+
+ [Fact]
+ public void ExtractExportFunctions_MixedExports_ShouldOnlyReturnFunctions()
+ {
+ // Arrange
+ string code = @"
+export function add(a: number, b: number): number {
+ return a + b;
+}
+
+function helper() {
+ return 'not exported';
+}
+
+export const PI = 3.14;
+
+export function multiply(x: number, y: number): number {
+ return x * y;
+}";
+
+ // Act
+ var exportedFunctions = ExtractExportFunctions(code);
+
+ // Assert
+ Assert.Equal(2, exportedFunctions.Count);
+ Assert.Contains("add", exportedFunctions);
+ Assert.Contains("multiply", exportedFunctions);
+ Assert.DoesNotContain("helper", exportedFunctions);
+ Assert.DoesNotContain("PI", exportedFunctions);
+ }
+
+ [Fact]
+ public void ExtractExportFunctions_NoExports_ShouldReturnEmpty()
+ {
+ // Arrange
+ string code = @"
+function helper() {
+ return 'not exported';
+}
+
+const PI = 3.14;";
+
+ // Act
+ var exportedFunctions = ExtractExportFunctions(code);
+
+ // Assert
+ Assert.Empty(exportedFunctions);
+ }
+
+ [Fact]
+ public void ExtractExportFunctions_EmptyCode_ShouldReturnEmpty()
+ {
+ // Arrange
+ string code = "";
+
+ // Act
+ var exportedFunctions = ExtractExportFunctions(code);
+
+ // Assert
+ Assert.Empty(exportedFunctions);
+ }
+
+ [Fact]
+ public void ExtractExportFunctions_ComplexExports_ShouldExtractAllFunctions()
+ {
+ // Arrange
+ string code = @"
+export function calculate(x: number): number {
+ return x * 2;
+}
+
+export function processData(data: any[]): any[] {
+ return data.filter(item => item != null);
+}
+
+export function validateInput(input: string): boolean {
+ return input && input.length > 0;
+}
+
+// 非函数导出
+export const config = { api: 'https://api.example.com' };
+export let counter = 0;
+
+// 非导出函数
+function internalHelper() {
+ return 'internal';
+}";
+
+ // Act
+ var exportedFunctions = ExtractExportFunctions(code);
+
+ // Assert
+ Assert.Equal(3, exportedFunctions.Count);
+ Assert.Contains("calculate", exportedFunctions);
+ Assert.Contains("processData", exportedFunctions);
+ Assert.Contains("validateInput", exportedFunctions);
+ Assert.DoesNotContain("internalHelper", exportedFunctions);
+ }
+
+ [Fact]
+ public void ExtractExportFunctions_AsyncFunctions_ShouldExtractAsyncFunctions()
+ {
+ // Arrange
+ string code = @"
+export async function fetchData(url: string): Promise {
+ const response = await fetch(url);
+ return response.json();
+}
+
+export function syncFunction(): string {
+ return 'sync';
+}";
+
+ // Act
+ var exportedFunctions = ExtractExportFunctions(code);
+
+ // Assert
+ Assert.Equal(2, exportedFunctions.Count);
+ Assert.Contains("fetchData", exportedFunctions);
+ Assert.Contains("syncFunction", exportedFunctions);
+ }
+
+ ///
+ /// 提取TypeScript代码中所有导出的函数名称
+ ///
+ /// TypeScript源代码
+ /// 导出函数名称列表
+ private List ExtractExportFunctions(string code)
+ {
+ var exportedFunctions = new List();
+
+ using var parser = new Parser();
+ using var tree = parser.ParseString(code);
+
+ // 创建查询匹配 export 函数
+ var query = tree.language().query_new(@"
+ (export_statement
+ declaration: (function_declaration
+ name: (identifier) @func_name))
+ ", out var offset, out var error);
+
+ if (query != null && error == TSQueryError.TSQueryErrorNone)
+ {
+ using var cursor = new TSQueryCursor();
+ cursor.exec(query, tree.root_node());
+
+ while (cursor.next_match(out var match, out var captures))
+ {
+ foreach (var capture in captures)
+ {
+ var funcName = capture.node.text(code);
+ if (!string.IsNullOrWhiteSpace(funcName))
+ {
+ exportedFunctions.Add(funcName);
+ }
+ }
+ }
+
+ query.Dispose();
+ }
+
+ return exportedFunctions;
+ }
+ }
+}
\ No newline at end of file
diff --git a/TypeScriptParser.Tests/tests/TypeScriptAnalyzerTests.cs b/TypeScriptParser.Tests/tests/TypeScriptAnalyzerTests.cs
index 14b4371..e0d52c4 100644
--- a/TypeScriptParser.Tests/tests/TypeScriptAnalyzerTests.cs
+++ b/TypeScriptParser.Tests/tests/TypeScriptAnalyzerTests.cs
@@ -1,7 +1,7 @@
using System;
using System.IO;
using Xunit;
-using TreeSitter.TypeScript;
+using TypeScriptParser.Tests;
namespace TypeScriptParser.Tests
{
diff --git a/TypeScriptParser.Tests/tests/TypeScriptParserTests.cs b/TypeScriptParser.Tests/tests/TypeScriptParserTests.cs
index 22e9147..027be78 100644
--- a/TypeScriptParser.Tests/tests/TypeScriptParserTests.cs
+++ b/TypeScriptParser.Tests/tests/TypeScriptParserTests.cs
@@ -1,6 +1,7 @@
using System;
using Xunit;
-using TreeSitter.TypeScript;
+using TypeScriptParser;
+using TypeScriptParser.TreeSitter;
namespace TypeScriptParser.Tests
{
@@ -10,19 +11,20 @@ public class TypeScriptParserTests
public void TypeScriptParser_Constructor_ShouldCreateValidInstance()
{
// Arrange & Act
- using var parser = new TreeSitter.TypeScript.TypeScriptParser();
+ using var parser = new Parser();
// Assert
Assert.NotNull(parser);
- Assert.NotNull(parser.Language);
- Assert.True(parser.IsAvailable);
+ // 通过能否成功解析来验证Parser可用性
+ var tree = parser.ParseString("const x = 1;");
+ Assert.NotNull(tree);
}
[Fact]
public void ParseString_SimpleTypeScriptCode_ShouldReturnValidTree()
{
// Arrange
- using var parser = new TreeSitter.TypeScript.TypeScriptParser();
+ using var parser = new Parser();
string sourceCode = "const x: number = 42;";
// Act
@@ -36,7 +38,7 @@ public void ParseString_SimpleTypeScriptCode_ShouldReturnValidTree()
public void ParseString_EmptyString_ShouldReturnValidTree()
{
// Arrange
- using var parser = new TreeSitter.TypeScript.TypeScriptParser();
+ using var parser = new Parser();
string sourceCode = "";
// Act
@@ -50,46 +52,48 @@ public void ParseString_EmptyString_ShouldReturnValidTree()
public void CreateCursor_WithValidTree_ShouldReturnCursor()
{
// Arrange
- using var parser = new TreeSitter.TypeScript.TypeScriptParser();
+ using var parser = new Parser();
string sourceCode = "function hello() { return 'world'; }";
using var tree = parser.ParseString(sourceCode);
// Act
- using var cursor = parser.CreateCursor(tree);
+ using var cursor = new TSCursor(tree.root_node(), tree.language());
// Assert
Assert.NotNull(cursor);
}
[Fact]
- public void CreateCursor_WithNullTree_ShouldThrowArgumentNullException()
+ public void CreateCursor_WithValidNode_ShouldWork()
{
// Arrange
- using var parser = new TreeSitter.TypeScript.TypeScriptParser();
+ using var parser = new Parser();
+ var tree = parser.ParseString("const x = 1;");
- // Act & Assert
- Assert.Throws(() => parser.CreateCursor(null));
+ // Act & Assert - 测试正常创建游标
+ using var cursor = new TSCursor(tree.root_node(), tree.language());
+ Assert.NotNull(cursor);
+ Assert.NotNull(cursor.current_symbol());
}
[Fact]
- public void Dispose_AfterDispose_IsAvailableShouldBeFalse()
+ public void Dispose_AfterDispose_ParseStringShouldThrow()
{
// Arrange
- var parser = new TreeSitter.TypeScript.TypeScriptParser();
- Assert.True(parser.IsAvailable);
+ var parser = new Parser();
// Act
parser.Dispose();
// Assert
- Assert.False(parser.IsAvailable);
+ Assert.Throws(() => parser.ParseString("const x = 1;"));
}
[Fact]
public void ParseString_AfterDispose_ShouldThrowObjectDisposedException()
{
// Arrange
- var parser = new TreeSitter.TypeScript.TypeScriptParser();
+ var parser = new Parser();
parser.Dispose();
// Act & Assert
diff --git a/TypeScriptParser/src/TypeScriptParser.cs b/TypeScriptParser/src/TypeScriptParser.cs
index d1a675f..03546db 100644
--- a/TypeScriptParser/src/TypeScriptParser.cs
+++ b/TypeScriptParser/src/TypeScriptParser.cs
@@ -1,13 +1,13 @@
using System;
-using GitHub.TreeSitter;
+using TypeScriptParser.TreeSitter;
using System.Runtime.InteropServices;
-namespace TreeSitter.TypeScript
+namespace TypeScriptParser
{
///
/// TypeScript 解析器模块 - 负责 Tree-sitter TypeScript 语言的初始化和基础解析功能
///
- public class TypeScriptParser : IDisposable
+ public class Parser : IDisposable
{
private readonly TSLanguage lang;
private TSParser parser;
@@ -16,18 +16,13 @@ public class TypeScriptParser : IDisposable
[DllImport("tree-sitter-typescript", CallingConvention = CallingConvention.Cdecl)]
private static extern IntPtr tree_sitter_typescript();
- public TypeScriptParser()
+ public Parser()
{
lang = new TSLanguage(tree_sitter_typescript());
parser = new TSParser();
parser.set_language(lang);
}
- ///
- /// 获取 TypeScript 语言对象
- ///
- public TSLanguage Language => lang;
-
///
/// 解析 TypeScript 源代码字符串
///
@@ -36,32 +31,10 @@ public TypeScriptParser()
public TSTree ParseString(string sourceCode)
{
if (disposed)
- throw new ObjectDisposedException(nameof(TypeScriptParser));
-
+ throw new ObjectDisposedException(nameof(Parser));
return parser.parse_string(null, sourceCode);
}
- ///
- /// 创建语法树游标
- ///
- /// 语法树
- /// TSCursor 对象
- public TSCursor CreateCursor(TSTree tree)
- {
- if (disposed)
- throw new ObjectDisposedException(nameof(TypeScriptParser));
-
- if (tree == null)
- throw new ArgumentNullException(nameof(tree));
-
- return new TSCursor(tree.root_node(), lang);
- }
-
- ///
- /// 检查解析器是否可用
- ///
- public bool IsAvailable => !disposed && parser != null && lang != null;
-
public void Dispose()
{
Dispose(true);
@@ -81,7 +54,7 @@ protected virtual void Dispose(bool disposing)
}
}
- ~TypeScriptParser()
+ ~Parser()
{
Dispose(false);
}
diff --git a/TypeScriptParser/src/binding.cs b/TypeScriptParser/src/binding.cs
index 30c7772..4c8b880 100644
--- a/TypeScriptParser/src/binding.cs
+++ b/TypeScriptParser/src/binding.cs
@@ -11,7 +11,7 @@
using System.Diagnostics;
using System.Runtime.InteropServices;
-namespace GitHub.TreeSitter
+namespace TypeScriptParser.TreeSitter
{
public enum TSInputEncoding {
TSInputEncodingUTF8,
diff --git a/docs/API_REFERENCE.md b/docs/API_REFERENCE.md
new file mode 100644
index 0000000..87e1773
--- /dev/null
+++ b/docs/API_REFERENCE.md
@@ -0,0 +1,262 @@
+# TypeScript Parser API 参考
+
+基于 Tree-sitter 的 TypeScript 解析器 .NET 绑定。
+
+## 快速开始
+
+```csharp
+using TypeScriptParser;
+
+using var parser = new Parser();
+using var tree = parser.ParseString("const x: number = 42;");
+var root = tree.root_node();
+Console.WriteLine(root.type()); // "program"
+```
+
+## 高级 API
+
+### Parser
+
+```csharp
+public class Parser : IDisposable
+{
+ public Parser()
+ public TSTree ParseString(string sourceCode)
+ public void Dispose()
+}
+```
+
+**使用:**
+```csharp
+using var parser = new Parser();
+using var tree = parser.ParseString(code);
+```
+
+## 底层 API
+
+### TSTree - 语法树
+
+```csharp
+public sealed class TSTree : IDisposable
+{
+ public TSNode root_node()
+ public TSTree copy() // 多线程使用
+ public TSLanguage language()
+ public void edit(TSInputEdit edit) // 增量解析
+}
+```
+
+### TSNode - 节点
+
+```csharp
+public struct TSNode
+{
+ // 基本信息
+ public string type()
+ public bool is_null()
+ public bool is_named()
+ public bool has_error()
+
+ // 位置
+ public uint start_offset()
+ public uint end_offset()
+ public TSPoint start_point()
+ public TSPoint end_point()
+
+ // 导航
+ public TSNode parent()
+ public TSNode child(uint index)
+ public uint child_count()
+ public TSNode next_sibling()
+ public TSNode prev_sibling()
+
+ // 字段访问
+ public TSNode child_by_field_name(string field_name)
+
+ // 文本
+ public string text(string sourceCode)
+}
+```
+
+### TSCursor - 遍历
+
+```csharp
+public sealed class TSCursor : IDisposable
+{
+ public TSCursor(TSNode node, TSLanguage lang)
+
+ public TSNode current_node()
+ public string current_symbol()
+ public bool goto_first_child()
+ public bool goto_next_sibling()
+ public bool goto_parent()
+}
+```
+
+**遍历示例:**
+```csharp
+using var cursor = new TSCursor(tree.root_node(), tree.language());
+do {
+ var node = cursor.current_node();
+ Console.WriteLine($"{cursor.current_symbol()}: {node.type()}");
+} while (cursor.goto_next_sibling() || cursor.goto_first_child());
+```
+
+### TSQuery - 查询
+
+```csharp
+public sealed class TSQuery : IDisposable
+{
+ public uint pattern_count()
+ public uint capture_count()
+ public void disable_pattern(uint patternIndex)
+}
+
+public sealed class TSQueryCursor : IDisposable
+{
+ public void exec(TSQuery query, TSNode node)
+ public bool next_match(out TSQueryMatch match, out TSQueryCapture[] captures)
+ public void set_match_limit(uint limit)
+}
+```
+
+**查询示例:**
+```csharp
+var query = language.query_new("(function_declaration name: (identifier) @name)",
+ out var offset, out var error);
+using var queryCursor = new TSQueryCursor();
+queryCursor.exec(query, tree.root_node());
+
+while (queryCursor.next_match(out var match, out var captures)) {
+ foreach (var capture in captures) {
+ Console.WriteLine($"函数名: {capture.node.text(sourceCode)}");
+ }
+}
+```
+
+### TSLanguage - 语言定义
+
+```csharp
+public sealed class TSLanguage : IDisposable
+{
+ public string[] symbols
+ public string[] fields
+
+ public string symbol_name(ushort symbol)
+ public string field_name_for_id(ushort fieldId)
+ public TSQuery query_new(string source, out uint error_offset, out TSQueryError error_type)
+}
+```
+
+## 数据结构
+
+### TSPoint
+```csharp
+public struct TSPoint
+{
+ public uint row; // 行号(从0开始)
+ public uint column; // 列号(从0开始)
+}
+```
+
+### TSRange
+```csharp
+public struct TSRange
+{
+ public TSPoint start_point;
+ public TSPoint end_point;
+ public uint start_byte;
+ public uint end_byte;
+}
+```
+
+### TSQueryCapture
+```csharp
+public struct TSQueryCapture
+{
+ public TSNode node;
+ public uint index;
+}
+```
+
+## 实用示例
+
+### 查找所有函数
+
+```csharp
+var query = language.query_new(@"
+ (function_declaration
+ name: (identifier) @func_name
+ parameters: (formal_parameters) @params) @func
+", out var offset, out var error);
+
+using var cursor = new TSQueryCursor();
+cursor.exec(query, tree.root_node());
+
+while (cursor.next_match(out var match, out var captures)) {
+ var funcNode = captures[0].node; // @func
+ var nameNode = captures[1].node; // @func_name
+
+ Console.WriteLine($"函数: {nameNode.text(sourceCode)}");
+ Console.WriteLine($"位置: 行{funcNode.start_point().row + 1}");
+}
+```
+
+### 遍历所有变量声明
+
+```csharp
+using var cursor = new TSCursor(tree.root_node(), tree.language());
+
+void TraverseNode() {
+ var node = cursor.current_node();
+
+ if (node.type() == "variable_declarator") {
+ var nameNode = node.child_by_field_name("name");
+ if (!nameNode.is_null()) {
+ Console.WriteLine($"变量: {nameNode.text(sourceCode)}");
+ }
+ }
+
+ if (cursor.goto_first_child()) {
+ do {
+ TraverseNode();
+ } while (cursor.goto_next_sibling());
+ cursor.goto_parent();
+ }
+}
+
+TraverseNode();
+```
+
+### 增量解析
+
+```csharp
+// 初始解析
+using var tree = parser.ParseString("const x = 1;");
+
+// 编辑:在末尾添加内容
+var edit = new TSInputEdit {
+ start_byte = 12, // "const x = 1;" 长度
+ old_end_byte = 12,
+ new_end_byte = 25, // 新增 "const y = 2;" 长度
+ start_point = new TSPoint(0, 12),
+ old_end_point = new TSPoint(0, 12),
+ new_end_point = new TSPoint(0, 25)
+};
+
+tree.edit(edit);
+var newTree = parser.ParseString(tree, "const x = 1;const y = 2;");
+```
+
+## 注意事项
+
+- 所有 `IDisposable` 对象使用 `using` 语句
+- 多线程使用 `tree.copy()` 创建副本
+- 设置超时:`parser.set_timeout_micros(5000000)`
+- 检查错误:`root.has_error()`
+
+## 平台支持
+
+- Linux x64
+- macOS ARM64
+- Windows x64
\ No newline at end of file
diff --git a/docs/USAGE_GUIDE.md b/docs/USAGE_GUIDE.md
new file mode 100644
index 0000000..9da3bc8
--- /dev/null
+++ b/docs/USAGE_GUIDE.md
@@ -0,0 +1,170 @@
+# TypeScript Parser 使用指南
+
+一个简单易用的 TypeScript 解析器,帮你分析和处理 TypeScript 代码。
+
+## 🚀 快速开始
+
+### 安装
+```bash
+dotnet add package TypeScriptParser
+```
+
+### 第一个例子
+```csharp
+using TypeScriptParser;
+
+// 1. 创建解析器
+using var parser = new Parser();
+
+// 2. 解析代码
+using var tree = parser.ParseString("const message = 'Hello TypeScript!';");
+
+// 3. 查看结果
+var root = tree.root_node();
+Console.WriteLine($"解析成功!根节点类型: {root.type()}");
+// 输出: 解析成功!根节点类型: program
+```
+
+## 📖 基础概念
+
+### 语法树
+当你写代码时:
+```typescript
+const x = 42;
+```
+
+解析器会把它变成这样的树结构:
+```
+program
+└── variable_declaration
+ └── variable_declarator
+ ├── identifier (x)
+ └── number (42)
+```
+
+### 探索节点
+```csharp
+using var parser = new Parser();
+using var tree = parser.ParseString("const name = 'Alice';");
+
+var root = tree.root_node();
+Console.WriteLine($"根节点类型: {root.type()}");
+Console.WriteLine($"子节点数量: {root.child_count()}");
+
+// 遍历子节点
+for (uint i = 0; i < root.child_count(); i++)
+{
+ var child = root.child(i);
+ Console.WriteLine($"子节点 {i}: {child.type()}");
+}
+```
+
+## 🎯 实用示例
+
+### 提取所有导出函数
+```csharp
+using TypeScriptParser;
+using TypeScriptParser.TreeSitter;
+
+string code = @"
+export function add(a: number, b: number): number {
+ return a + b;
+}
+
+function helper() {
+ return 'not exported';
+}
+
+export function multiply(x: number, y: number): number {
+ return x * y;
+}
+";
+
+using var parser = new Parser();
+using var tree = parser.ParseString(code);
+
+// 创建查询
+var query = tree.language().query_new(@"
+ (export_statement
+ declaration: (function_declaration
+ name: (identifier) @func_name))
+", out var offset, out var error);
+
+if (query != null && error == TSQueryError.TSQueryErrorNone)
+{
+ using var cursor = new TSQueryCursor();
+ cursor.exec(query, tree.root_node());
+
+ Console.WriteLine("导出的函数:");
+ while (cursor.next_match(out var match, out var captures))
+ {
+ foreach (var capture in captures)
+ {
+ var funcName = capture.node.text(code);
+ Console.WriteLine($" - {funcName}");
+ }
+ }
+
+ query.Dispose();
+}
+
+// 输出:
+// 导出的函数:
+// - add
+// - multiply
+```
+
+### 遍历所有节点
+```csharp
+using var parser = new Parser();
+using var tree = parser.ParseString("const x = 1; let y = 'hello';");
+using var cursor = new TSCursor(tree.root_node(), tree.language());
+
+void TraverseTree()
+{
+ var node = cursor.current_node();
+ Console.WriteLine($"{node.type()}: {node.text(code)}");
+
+ if (cursor.goto_first_child())
+ {
+ do
+ {
+ TraverseTree();
+ } while (cursor.goto_next_sibling());
+ cursor.goto_parent();
+ }
+}
+
+TraverseTree();
+```
+
+## 💡 最佳实践
+
+### ✅ 推荐做法
+```csharp
+// 使用 using 语句管理资源
+using var parser = new Parser();
+using var tree = parser.ParseString(code);
+
+// 检查节点是否为空
+var nameNode = node.child_by_field_name("name");
+if (!nameNode.is_null())
+{
+ Console.WriteLine(nameNode.text(code));
+}
+
+// 检查解析错误
+if (tree.root_node().has_error())
+{
+ Console.WriteLine("代码有语法错误");
+}
+```
+
+### ❌ 避免做法
+- 忘记释放 `IDisposable` 对象
+- 直接访问可能为空的节点
+- 在循环中重复创建相同的查询
+
+---
+
+更多详细信息请参考 [API参考文档](API_REFERENCE.md)
\ No newline at end of file