mirror of
https://wget.la/https://github.com/leookun/cursor-byok
synced 2026-08-17 11:37:20 +08:00
191 lines
5.3 KiB
Go
191 lines
5.3 KiB
Go
// services.go 解析枚举、服务方法和压缩对象的配对括号。
|
|
package main
|
|
|
|
import (
|
|
"regexp"
|
|
"strconv"
|
|
)
|
|
|
|
// extractEnums 从旧式和工厂式声明中提取枚举。
|
|
func extractEnums(text string, moduleStarts []int) []Enum {
|
|
var enums []Enum
|
|
enumExists := func(typeName, varName string) bool {
|
|
for _, existing := range enums {
|
|
if existing.TypeName == typeName && existing.VarName == varName {
|
|
return true
|
|
}
|
|
}
|
|
return false
|
|
}
|
|
|
|
// 匹配任意包中的 setEnumType(XXX, "xxx.v1.EnumName", [...]) 枚举声明。
|
|
// JS 变量名可以包含 $ 符号
|
|
enumRe := regexp.MustCompile(`setEnumType\s*\(\s*([\w$]+)\s*,\s*"([\w.]+)"\s*,\s*\[`)
|
|
|
|
matches := enumRe.FindAllStringSubmatchIndex(text, -1)
|
|
for _, match := range matches {
|
|
varName := text[match[2]:match[3]]
|
|
typeName := text[match[4]:match[5]]
|
|
|
|
// 提取枚举值数组。
|
|
bracketStart := match[1] - 1
|
|
values := extractEnumValues(text, bracketStart)
|
|
|
|
pkg, shortName := parseTypeName(typeName)
|
|
enum := Enum{
|
|
TypeName: typeName,
|
|
VarName: varName,
|
|
Values: values,
|
|
Package: pkg,
|
|
ShortName: shortName,
|
|
Pos: match[0],
|
|
ModuleStart: moduleStartForPos(moduleStarts, match[0]),
|
|
}
|
|
enums = append(enums, enum)
|
|
}
|
|
|
|
// 匹配现代 @bufbuild/protobuf 工厂形式,例如 Role=A.makeEnum("aiserver.v1.InferenceMessageRole",[{...}])。
|
|
enumFactoryRe := regexp.MustCompile(`([\w$]+)\s*=\s*[\w$.]+\.makeEnum\s*\(\s*["']([\w.]+)["']\s*,\s*\[`)
|
|
factoryMatches := enumFactoryRe.FindAllStringSubmatchIndex(text, -1)
|
|
for _, match := range factoryMatches {
|
|
varName := text[match[2]:match[3]]
|
|
typeName := text[match[4]:match[5]]
|
|
if enumExists(typeName, varName) {
|
|
continue
|
|
}
|
|
|
|
bracketStart := match[1] - 1
|
|
if bracketStart < 0 || bracketStart >= len(text) || text[bracketStart] != '[' {
|
|
continue
|
|
}
|
|
|
|
pkg, shortName := parseTypeName(typeName)
|
|
enums = append(enums, Enum{
|
|
TypeName: typeName,
|
|
VarName: varName,
|
|
Values: extractEnumValues(text, bracketStart),
|
|
Package: pkg,
|
|
ShortName: shortName,
|
|
Pos: match[0],
|
|
ModuleStart: moduleStartForPos(moduleStarts, match[0]),
|
|
})
|
|
}
|
|
|
|
return enums
|
|
}
|
|
|
|
// extractServices 从命名或匿名描述符中提取服务。
|
|
func extractServices(text string, moduleStarts []int) []Service {
|
|
var services []Service
|
|
seenTypeNames := make(map[string]bool)
|
|
appendService := func(varName, typeName string, pos, methodsStart int) {
|
|
if seenTypeNames[typeName] {
|
|
return
|
|
}
|
|
methodsEnd := findMatchingBrace(text, methodsStart)
|
|
if methodsEnd == -1 {
|
|
return
|
|
}
|
|
|
|
pkg, shortName := parseTypeName(typeName)
|
|
services = append(services, Service{
|
|
TypeName: typeName,
|
|
VarName: varName,
|
|
Methods: extractMethods(text[methodsStart:methodsEnd]),
|
|
Package: pkg,
|
|
ShortName: shortName,
|
|
Pos: pos,
|
|
ModuleStart: moduleStartForPos(moduleStarts, pos),
|
|
})
|
|
seenTypeNames[typeName] = true
|
|
}
|
|
|
|
// 匹配 VarName = { typeName: "xxx.v1.ServiceName", methods: { ... } } 服务对象。
|
|
serviceRe := regexp.MustCompile(`([\w$]+)\s*=\s*\{\s*typeName:\s*"([\w.]+)"\s*,\s*methods:\s*\{`)
|
|
|
|
matches := serviceRe.FindAllStringSubmatchIndex(text, -1)
|
|
for _, match := range matches {
|
|
varName := text[match[2]:match[3]]
|
|
typeName := text[match[4]:match[5]]
|
|
|
|
appendService(varName, typeName, match[0], match[1]-1)
|
|
}
|
|
|
|
// 部分 bundle 把服务描述符直接放入数组,不预先赋给变量。
|
|
anonymousServiceRe := regexp.MustCompile(`\{\s*typeName:\s*["']([\w.]+)["']\s*,\s*methods:\s*\{`)
|
|
for _, match := range anonymousServiceRe.FindAllStringSubmatchIndex(text, -1) {
|
|
typeName := text[match[2]:match[3]]
|
|
appendService("", typeName, match[0], match[1]-1)
|
|
}
|
|
|
|
return services
|
|
}
|
|
|
|
// extractMethods 解析服务对象中的 RPC 方法列表。
|
|
func extractMethods(methodsText string) []Method {
|
|
var methods []Method
|
|
|
|
// 匹配包含方法名、输入、输出和调用类型的方法对象。
|
|
methodRe := regexp.MustCompile(`\w+:\s*\{\s*name:\s*"([^"]+)"\s*,\s*I:\s*([\w$.]+)\s*,\s*O:\s*([\w$.]+)\s*,\s*kind:\s*[\w$.]+\.(Unary|ServerStreaming|ClientStreaming|BiDiStreaming)`)
|
|
|
|
matches := methodRe.FindAllStringSubmatch(methodsText, -1)
|
|
for _, m := range matches {
|
|
method := Method{
|
|
Name: m[1],
|
|
InputType: m[2],
|
|
OutputType: m[3],
|
|
Kind: m[4],
|
|
}
|
|
methods = append(methods, method)
|
|
}
|
|
|
|
return methods
|
|
}
|
|
|
|
// findMatchingBrace 查找花括号块的结束位置。
|
|
func findMatchingBrace(text string, start int) int {
|
|
depth := 0
|
|
for i := start; i < len(text); i++ {
|
|
if text[i] == '{' {
|
|
depth++
|
|
} else if text[i] == '}' {
|
|
depth--
|
|
if depth == 0 {
|
|
return i + 1
|
|
}
|
|
}
|
|
}
|
|
return -1
|
|
}
|
|
|
|
// extractEnumValues 从数组起点解析枚举值。
|
|
func extractEnumValues(text string, start int) []EnumValue {
|
|
// 查找数组的配对结束括号。
|
|
depth := 0
|
|
end := start
|
|
for i := start; i < len(text); i++ {
|
|
if text[i] == '[' {
|
|
depth++
|
|
} else if text[i] == ']' {
|
|
depth--
|
|
if depth == 0 {
|
|
end = i + 1
|
|
break
|
|
}
|
|
}
|
|
}
|
|
|
|
arrayText := text[start:end]
|
|
|
|
var values []EnumValue
|
|
valueRe := regexp.MustCompile(`\{\s*no:\s*(\d+)\s*,\s*name:\s*"([^"]+)"`)
|
|
|
|
matches := valueRe.FindAllStringSubmatch(arrayText, -1)
|
|
for _, m := range matches {
|
|
no, _ := strconv.Atoi(m[1])
|
|
values = append(values, EnumValue{No: no, Name: m[2]})
|
|
}
|
|
|
|
return values
|
|
}
|