@lcap/nasl
Version:
NetEase Application Specific Language
320 lines • 11.5 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.transformUnionTypeAnnotation = exports.hasParamNameOfAnonymousFunction = exports.checkParamNameOfAnonymousFunction = exports.getAncestorExistingVarNames = exports.getAncestorExistingParamNames = exports.AnonymousFnNode = exports.replaceNode = exports.officialCustoms = exports.waitPromise = exports.clearObjectDeep = exports.clearObject = exports.throttle = exports.findClosestModule = void 0;
const nasl_concepts_1 = require("@lcap/nasl-concepts");
const nasl_utils_1 = require("@lcap/nasl-utils");
// 查找最近的模块
function findClosestModule(node) {
let moduleNode = node;
while (moduleNode && !['App', 'Module'].includes(moduleNode.concept)) {
moduleNode = moduleNode.parentNode;
}
return moduleNode;
}
exports.findClosestModule = findClosestModule;
/**
* 用 lodash 的 throttle 好像有点问题,先临时做个处理
* @param func
* @param wait
* @param options
*/
const throttle = (func, wait, options) => func;
exports.throttle = throttle;
function clearObject(obj) {
Object.keys(obj).forEach((key) => {
if (obj[key] === undefined || obj[key] === null)
delete obj[key];
});
}
exports.clearObject = clearObject;
function clearObjectDeep(obj) {
(0, nasl_utils_1.traverse)((current) => {
Object.keys(current.node).forEach((key) => {
if (current.node[key] === null)
delete current.node[key];
});
}, { node: obj, stack: [] }, { mode: 'anyObject' });
}
exports.clearObjectDeep = clearObjectDeep;
const waitPromise = (wait) => new Promise((res) => setTimeout(() => res(wait), wait));
exports.waitPromise = waitPromise;
// 官方扩展组件暂时不包含 css 文件
exports.officialCustoms = [
'u-sider-modal',
'timer-count-down',
'u-calendar-table',
'lcap-login',
'lcap-video',
'lcap-amap-nav',
'lcap-amap-poi',
'lcap-echarts-bar',
'lcap-echarts-line',
'lcap-echarts-pie',
'lcap-report',
'lcap-wang-editor',
'lcap-clock',
];
function replaceNode(oldNode, newNode) {
const { parentNode, parentKey, offsetX, offsetY, app } = oldNode;
const { logic } = oldNode;
if (!Array.isArray(parentNode[parentKey])) {
parentNode.update({
[parentKey]: newNode,
});
}
else {
// 虽然如果不在参数里使用属性访问没有意义,但是得兼容
app.emit('collect:start', {
actionMsg: '删除属性变量',
});
if (parentNode.concept === 'Logic') {
if (parentKey === 'body') {
const expIndex = logic.body.findIndex((item) => item === oldNode);
logic.insertItemInBodyAt(newNode, expIndex);
}
else {
const expIndex = logic.playground.findIndex((item) => item === oldNode);
Object.assign(newNode, { offsetX, offsetY });
logic.insertItemInPlaygroundAt(newNode, expIndex);
}
}
else {
const expIndex = parentNode[parentKey].findIndex((item) => item === oldNode);
const firstUpperText = parentKey[0].toUpperCase() + parentKey.slice(1, parentKey.length);
if (parentNode[`insertItemIn${firstUpperText}At`])
parentNode[`insertItemIn${firstUpperText}At`](newNode, expIndex);
else
parentNode.insertItemAt(newNode, expIndex);
}
oldNode.delete();
app.emit('collect:end');
}
}
exports.replaceNode = replaceNode;
class AnonymousFnNode {
}
exports.AnonymousFnNode = AnonymousFnNode;
/**
* 收集匿名函数
* @param param0
* @returns
*/
function collectAnonymousFn({ anonymousFnNode, cb }) {
const descendantsAnonyList = cb(anonymousFnNode);
const { node } = anonymousFnNode;
const propertyMap = (0, nasl_concepts_1.getConceptPropertyMap)(node?.concept);
if (!propertyMap) {
return;
}
for (const property of propertyMap.keys()) {
const child = node[property];
if (!child) {
continue;
}
else if (Array.isArray(child)) {
child.forEach((node) => collectAnonymousFn({
anonymousFnNode: {
node,
descendants: descendantsAnonyList
},
cb
}));
}
else {
collectAnonymousFn({
anonymousFnNode: {
node: child,
descendants: descendantsAnonyList
},
cb
});
}
}
}
function getAnonymousFnNodes(node) {
const anonymousFnNodes = [];
// 1.匿名函数可能在里层,如:ListDistinctBy
// 2.存在多级匿名数据结构
collectAnonymousFn({
anonymousFnNode: {
node,
descendants: anonymousFnNodes
},
cb: (anonymousFnNode) => {
const { node, descendants } = anonymousFnNode;
if (node?.concept === 'AnonymousFunction') {
const newAnonymousNode = {
node,
descendants: [],
};
descendants?.push(newAnonymousNode);
return newAnonymousNode.descendants;
}
return descendants;
}
});
return anonymousFnNodes;
}
/**
* 父链上存在的参数名字
* @returns
*/
function getAncestorExistingParamNames(baseNode) {
let node = baseNode;
const names = new Set();
while (node) {
node = node.parentNode;
switch (node?.concept) {
case 'AnonymousFunction':
node.params.forEach((param) => {
names.add(param.name);
});
break;
case 'Logic':
case 'View':
const varList = [
...(node.params || []),
];
varList?.forEach((variable) => {
names.add(variable?.name);
});
break;
}
}
return names;
}
exports.getAncestorExistingParamNames = getAncestorExistingParamNames;
/**
* 父链上存在的变量名字
* @returns
*/
function getAncestorExistingVarNames(baseNode) {
let node = baseNode;
const names = new Set();
while (node) {
node = node.parentNode;
switch (node?.concept) {
case 'AnonymousFunction':
node.params.forEach((param) => {
names.add(param.name);
});
break;
case 'ForEachStatement':
names.add(node.item?.name);
names.add(node.index?.name);
break;
case 'Logic':
case 'View':
const varList = [
...(node.params || []),
...(node.returns || []),
...(node.variables || [])
];
varList?.forEach((variable) => {
names.add(variable?.name);
});
break;
}
}
return names;
}
exports.getAncestorExistingVarNames = getAncestorExistingVarNames;
/**
* 确保匿名函数的参数名称都是不重复的,且更新内部的引用关系
* @param param0
*/
function ensureAnonymousFnsParamName({ ancestorParamNames, anonymousFnNodes, }) {
const paramInfoMapList = [];
anonymousFnNodes.forEach((anonymousFnNode) => {
const { node: anonymousFn, descendants } = anonymousFnNode || {};
const tempParamInfoMap = anonymousFn?.ensureParamName(ancestorParamNames);
paramInfoMapList.push(tempParamInfoMap);
if (Array.isArray(descendants)) {
const paramNames = new Set([...ancestorParamNames]);
tempParamInfoMap.forEach((value) => {
paramNames.add(value.newName);
});
const descendantTempParamInfoMap = ensureAnonymousFnsParamName({
ancestorParamNames: paramNames,
anonymousFnNodes: descendants,
});
paramInfoMapList.push(...descendantTempParamInfoMap);
}
});
return paramInfoMapList;
}
/**
* 校验匿名函数的局部变量是否重名
*/
function checkParamNameOfAnonymousFunction(node) {
const anonymousFnNodes = getAnonymousFnNodes(node);
// 从外到里计算更改的name
const paramInfoMapList = ensureAnonymousFnsParamName({
ancestorParamNames: getAncestorExistingVarNames(node),
anonymousFnNodes
});
paramInfoMapList?.forEach((paramInfoMap) => {
paramInfoMap.forEach((paramInfo) => {
const { newName, param, identifiers } = paramInfo || {};
param?.update({
name: newName,
});
if (Array.isArray(identifiers)) {
identifiers.forEach((identifier) => {
identifier?.update({
name: newName,
});
});
}
});
});
}
exports.checkParamNameOfAnonymousFunction = checkParamNameOfAnonymousFunction;
// 获取内部匿名函数的局部变量
function collectAnonymousFnNodesParams(node) {
const paramNames = new Set();
const anonymousFnNodes = getAnonymousFnNodes(node);
if (Array.isArray(anonymousFnNodes)) {
anonymousFnNodes.forEach((anonymousFnNode) => {
const { node: anonymousFn, descendants } = anonymousFnNode || {};
anonymousFn.params.forEach((param) => {
paramNames.add(param.name);
});
if (Array.isArray(descendants)) {
descendants.forEach(({ node: descendantNode }) => {
const descendantParamNames = collectAnonymousFnNodesParams(descendantNode);
descendantParamNames.forEach((descendantParamName) => {
paramNames.add(descendantParamName);
});
});
}
});
}
return paramNames;
}
/**
* 新的参数名是否存在同名
* @param param0
*/
function hasParamNameOfAnonymousFunction({ node, newName, }) {
const ancestorParamNames = getAncestorExistingVarNames(node);
const anonymousFnNodesParams = collectAnonymousFnNodesParams(node);
const paramNames = new Set([...ancestorParamNames.values(), ...anonymousFnNodesParams.values()]);
return paramNames.has(newName);
}
exports.hasParamNameOfAnonymousFunction = hasParamNameOfAnonymousFunction;
function transformUnionTypeAnnotation(expTypeAnnotation, app) {
// 针对union类型,typeAnntatation拿不到app数据,暂时先在这里处理
if (expTypeAnnotation?.typeKind === 'union' && expTypeAnnotation?.typeArguments?.length) {
expTypeAnnotation?.typeArguments?.forEach((typeArg) => {
if (typeArg.typeNamespace?.endsWith('.metadataTypes')) {
const referenceNode = app?.findNodeByCompleteName(typeArg.typeNamespace + '.' + typeArg.typeName)?.typeAnnotation || {};
typeArg.typeName = referenceNode.typeName;
typeArg.typeKind = referenceNode.typeKind;
typeArg.typeNamespace = referenceNode.typeNamespace;
}
});
}
}
exports.transformUnionTypeAnnotation = transformUnionTypeAnnotation;
//# sourceMappingURL=node.js.map