a-calc 3.0.0-beta.20260130.1 → 3.0.0-beta.20260201.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -0
- package/a-calc.versions.js +4 -3
- package/browser/index.js +2 -4
- package/calc.d.ts +57 -0
- package/cjs/index.js +2 -4
- package/es/index.js +2 -4
- package/package.json +9 -7
- package/ts-plugin/dist/config_extractor.d.ts +9 -0
- package/ts-plugin/dist/config_extractor.js +104 -0
- package/ts-plugin/dist/constants.d.ts +34 -0
- package/ts-plugin/dist/constants.js +274 -0
- package/ts-plugin/dist/index.d.ts +7 -0
- package/ts-plugin/dist/index.js +294 -0
- package/ts-plugin/dist/utils.d.ts +49 -0
- package/ts-plugin/dist/utils.js +204 -0
- package/ts-plugin/dist/variable_extractor.d.ts +16 -0
- package/ts-plugin/dist/variable_extractor.js +138 -0
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.extract_variables_from_arg = void 0;
|
|
4
|
+
/**
|
|
5
|
+
* 从第二个参数中提取所有可用变量
|
|
6
|
+
*/
|
|
7
|
+
function extract_variables_from_arg(ts_module, arg, type_checker, logger) {
|
|
8
|
+
const result = [];
|
|
9
|
+
const type = type_checker.getTypeAtLocation(arg);
|
|
10
|
+
logger.info(`a-calc-ts-plugin: extracting variables from arg, type=${type_checker.typeToString(type)}`);
|
|
11
|
+
// 检查是否是数组类型
|
|
12
|
+
if (is_array_type(ts_module, type, type_checker)) {
|
|
13
|
+
// 数组类型:提取元素类型的属性
|
|
14
|
+
const element_type = get_array_element_type(ts_module, type, type_checker);
|
|
15
|
+
if (element_type) {
|
|
16
|
+
extract_properties_from_type(ts_module, element_type, '', type_checker, result, logger, 0);
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
else {
|
|
20
|
+
// 对象类型:直接提取属性
|
|
21
|
+
extract_properties_from_type(ts_module, type, '', type_checker, result, logger, 0);
|
|
22
|
+
}
|
|
23
|
+
logger.info(`a-calc-ts-plugin: extracted ${result.length} variables`);
|
|
24
|
+
return result;
|
|
25
|
+
}
|
|
26
|
+
exports.extract_variables_from_arg = extract_variables_from_arg;
|
|
27
|
+
/**
|
|
28
|
+
* 检查是否是数组类型
|
|
29
|
+
*/
|
|
30
|
+
function is_array_type(ts_module, type, type_checker) {
|
|
31
|
+
const type_str = type_checker.typeToString(type);
|
|
32
|
+
// 检查是否是数组字面量或 Array<T>
|
|
33
|
+
if (type_str.endsWith('[]') || type_str.startsWith('Array<')) {
|
|
34
|
+
return true;
|
|
35
|
+
}
|
|
36
|
+
// 检查 symbol
|
|
37
|
+
const symbol = type.getSymbol();
|
|
38
|
+
if (symbol && symbol.getName() === 'Array') {
|
|
39
|
+
return true;
|
|
40
|
+
}
|
|
41
|
+
// 检查是否有 length 属性和数字索引签名
|
|
42
|
+
if (type_checker.getIndexTypeOfType(type, ts_module.IndexKind.Number)) {
|
|
43
|
+
return true;
|
|
44
|
+
}
|
|
45
|
+
return false;
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* 获取数组元素类型
|
|
49
|
+
*/
|
|
50
|
+
function get_array_element_type(ts_module, type, type_checker) {
|
|
51
|
+
// 尝试获取数字索引类型
|
|
52
|
+
const index_type = type_checker.getIndexTypeOfType(type, ts_module.IndexKind.Number);
|
|
53
|
+
if (index_type) {
|
|
54
|
+
return index_type;
|
|
55
|
+
}
|
|
56
|
+
// 尝试从类型参数获取
|
|
57
|
+
const type_args = type.typeArguments;
|
|
58
|
+
if (type_args && type_args.length > 0) {
|
|
59
|
+
return type_args[0];
|
|
60
|
+
}
|
|
61
|
+
return undefined;
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* 从类型中递归提取属性
|
|
65
|
+
*/
|
|
66
|
+
function extract_properties_from_type(ts_module, type, prefix, type_checker, result, logger, depth) {
|
|
67
|
+
// 限制递归深度,防止无限递归
|
|
68
|
+
const MAX_DEPTH = 5;
|
|
69
|
+
if (depth > MAX_DEPTH) {
|
|
70
|
+
return;
|
|
71
|
+
}
|
|
72
|
+
const properties = type.getProperties();
|
|
73
|
+
for (const prop of properties) {
|
|
74
|
+
const prop_name = prop.getName();
|
|
75
|
+
// 跳过以 _ 开头的内部属性(如 _error, _fmt 等配置项)
|
|
76
|
+
if (prop_name.startsWith('_')) {
|
|
77
|
+
continue;
|
|
78
|
+
}
|
|
79
|
+
// 跳过一些常见的内置属性
|
|
80
|
+
if (['__proto__', 'constructor', 'prototype'].includes(prop_name)) {
|
|
81
|
+
continue;
|
|
82
|
+
}
|
|
83
|
+
const full_path = prefix ? `${prefix}.${prop_name}` : prop_name;
|
|
84
|
+
// 获取属性类型
|
|
85
|
+
let prop_type;
|
|
86
|
+
try {
|
|
87
|
+
if (prop.valueDeclaration) {
|
|
88
|
+
prop_type = type_checker.getTypeOfSymbolAtLocation(prop, prop.valueDeclaration);
|
|
89
|
+
}
|
|
90
|
+
else {
|
|
91
|
+
// 尝试从声明中获取
|
|
92
|
+
const declarations = prop.getDeclarations();
|
|
93
|
+
if (declarations && declarations.length > 0) {
|
|
94
|
+
prop_type = type_checker.getTypeOfSymbolAtLocation(prop, declarations[0]);
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
catch (e) {
|
|
99
|
+
// 忽略获取类型失败的情况
|
|
100
|
+
}
|
|
101
|
+
const type_desc = prop_type ? type_checker.typeToString(prop_type) : 'unknown';
|
|
102
|
+
const has_children = prop_type ? has_object_properties(ts_module, prop_type, type_checker) : false;
|
|
103
|
+
result.push({
|
|
104
|
+
path: full_path,
|
|
105
|
+
type_desc,
|
|
106
|
+
has_children,
|
|
107
|
+
});
|
|
108
|
+
// 如果是对象类型,递归提取子属性
|
|
109
|
+
if (prop_type && has_children) {
|
|
110
|
+
extract_properties_from_type(ts_module, prop_type, full_path, type_checker, result, logger, depth + 1);
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
/**
|
|
115
|
+
* 检查类型是否有对象属性(用于判断是否需要深度补全)
|
|
116
|
+
*/
|
|
117
|
+
function has_object_properties(ts_module, type, type_checker) {
|
|
118
|
+
// 排除基本类型
|
|
119
|
+
const type_str = type_checker.typeToString(type);
|
|
120
|
+
const primitive_types = ['string', 'number', 'boolean', 'null', 'undefined', 'void', 'never', 'any', 'unknown'];
|
|
121
|
+
if (primitive_types.includes(type_str)) {
|
|
122
|
+
return false;
|
|
123
|
+
}
|
|
124
|
+
// 排除数组类型(不递归进入数组元素)
|
|
125
|
+
if (type_str.endsWith('[]') || type_str.startsWith('Array<')) {
|
|
126
|
+
return false;
|
|
127
|
+
}
|
|
128
|
+
// 排除函数类型
|
|
129
|
+
const call_signatures = type.getCallSignatures();
|
|
130
|
+
if (call_signatures && call_signatures.length > 0) {
|
|
131
|
+
return false;
|
|
132
|
+
}
|
|
133
|
+
// 检查是否有属性
|
|
134
|
+
const properties = type.getProperties();
|
|
135
|
+
// 过滤掉以 _ 开头的属性
|
|
136
|
+
const user_properties = properties.filter(p => !p.getName().startsWith('_'));
|
|
137
|
+
return user_properties.length > 0;
|
|
138
|
+
}
|