Я работаю над инструментом анализа кода JavaScript, который проходит абстрактное синтаксисное дерево (AST) для анализа вызовов функций и их условия. Цель состоит в том, чтобы динамически генерировать цепочку условий для каждого вызова функции на основе вложенного if , else, если и else операторы.
Описание задачи Описание
При обработке блока Else я не могу правильно получить доступ к родительскому условию (
Код: Выделить всё
parent.condition
Вот упрощенная версия кода, которую я анализирую:
javascript < /p>
复制 < /p>
Код: Выделить всё
function foo(a, b) {
var c = 100;
if (c > a) {
if (a > 200) {
alert(1);
} else if (a > 100) {
alert(2);
} else {
alert(3); // Condition here is incorrect
}
}
}
для блока else (
Код: Выделить всё
alert(3)
复制
Код: Выделить всё
100 > a 并且 非(a > 200) 且 非(a > 100)
< /code>
Однако текущая реализация генерирует неправильные условия, поскольку контекст родительского условия не поддерживается должным образом. < /p>
Текущая реализация < /h3>
Вот соответствующая часть моего кода: < /p>
javascript < /p>
复制 < /p>
if (
node.type === 'BlockStatement' &&
parent.type === 'IfStatement' &&
parent.alternate === node
) {
// Attempt to get the parent condition
const parentCondition = currentConditionContext.parent.condition; // ❌ Fails here
currentConditionContext = {
type: 'else',
condition: `非(${parentCondition})`,
parent: currentConditionContext.parent.parent, // Incorrect parent reference
siblingNegation: null
};
}
< /code>
проблема < /h3>
Проблема возникает из -за: < /p>
[*] else
Код: Выделить всё
parent.parent
[*] родительское условие недоступно из -за неправильной родительской справки.
< /li>
< /ol>
Вопрос < /h3>
Как я могу правильно поддерживать контекст исходного состояния для блоков else < /code> для создания правильного отрицание предыдущего Если условие?
желаемое решение
Мне нужен способ:
Правильно ссылайтесь на контекст родительского условия для else блоки. Если условие Динамически.
[*] Убедитесь, что цепочка состояния является точной для вложенных if-else структур.
< /li>
< /ol>
Дополнительный контекст < /h3>
- Я использую esprima < /code> для анализа, Estraverse для обхода и escodegen для генерации кода.
- Цепочка условий должна поддерживать произвольные уровни гнездования.
javascript
复制 < /p>
Код: Выделить всё
// Full code implementation
< /code>
Любые рекомендации или предложения были бы очень оценены! Необходимый контекст для кого -то, чтобы понять и помочь с вашей проблемой. Вы можете заменить // полное реализацию кода
Это мой код, следующий код не достигает желаемого эффекта /strong> < /h1>
Код: Выделить всё
import esprima from 'esprima';
import estraverse from 'estraverse';
import escodegen from 'escodegen';
export function analyzeFunctionCalls(code, functionName, methods) {
try {
const ast = esprima.parseScript(code, { range: true, tokens: true, comment: true });
const functionCalls = [];
const variableMap = {};
// 树形条件链管理(使用根节点初始化)
let currentConditionNode = {
condition: null,
parent: null,
children: []
};
estraverse.traverse(ast, {
enter: (node, parent) => {
// 变量声明处理
if (node.type === 'VariableDeclaration') {
node.declarations.forEach(declaration => {
if (declaration.init) {
variableMap[declaration.id.name] = escodegen.generate(declaration.init);
}
});
}
// 处理 if 语句
if (node.type === 'IfStatement') {
const condition = processCondition(node.test, variableMap);
// 创建新的条件节点并链接到当前节点
const newNode = {
condition: condition,
parent: currentConditionNode,
children: []
};
currentConditionNode.children.push(newNode);
currentConditionNode = newNode;
}
// 处理 else if
if (
node.type === 'IfStatement' &&
parent.type === 'IfStatement' &&
parent.alternate === node
) {
// 获取父 if 的条件
const parentIfCondition = currentConditionNode.parent.condition;
const currentCondition = processCondition(node.test, variableMap);
// 创建 else if 节点
const newNode = {
condition: `非(${parentIfCondition}) 且 ${currentCondition}`,
parent: currentConditionNode.parent, // 关键修正:父节点指向原 if 的父级
children: []
};
currentConditionNode.parent.children.push(newNode);
currentConditionNode = newNode;
}
// 处理 else 块
if (
node.type === 'BlockStatement' &&
parent.type === 'IfStatement' &&
parent.alternate === node
) {
// 获取父 if 的条件
const parentIfCondition = currentConditionNode.parent.condition;
// 创建 else 节点
const newNode = {
condition: `非(${parentIfCondition})`,
parent: currentConditionNode.parent, // 关键修正:父节点指向原 if 的父级
children: []
};
currentConditionNode.parent.children.push(newNode);
currentConditionNode = newNode;
}
// 收集函数调用
if (node.type === 'CallExpression') {
const callee = node.callee;
const fullCondition = getFullConditionChain(currentConditionNode);
if (
(callee.type === 'Identifier' && methods.includes(callee.name)) ||
(callee.type === 'MemberExpression' &&
callee.object.name === functionName &&
methods.includes(callee.property.name))
) {
functionCalls.push({
call: escodegen.generate(node),
condition: fullCondition
});
}
}
},
leave: (node) => {
// 离开 if 语句时回溯到父节点
if (node.type === 'IfStatement') {
currentConditionNode = currentConditionNode.parent;
}
}
});
return functionCalls;
} catch (error) {
console.error('Error parsing code:', error);
return [];
}
}
// 生成完整条件链(从根到当前节点)
function getFullConditionChain(node) {
const path = [];
let current = node;
while (current && current.condition !== null) {
path.unshift(current.condition);
current = current.parent;
}
return path.join(' 并且 ');
}
// 优化后的条件处理
function processCondition(testNode, variableMap) {
return escodegen.generate(testNode)
.replace(/\b\w+\b/g, m => variableMap[m] || m)
.replace(/>=/g, '≥')
.replace(//g, '>')
.replace(/ a){
if( a > 200){
alert(1)
alert(4)
}else if(a > 100){
alert(2)
if(b > 200){
alert(5)
}else{
alert(6)
}
alert(7)
}else{
alert(3)
if(b > 200){
alert(8)
}else{
alert(9)
}
alert(10)
}
}
}
`, "DV",["alert"]));
Код: Выделить всё
[
{ call: 'alert(1)', condition: '100>a 并且 a>200' },
{ call: 'alert(4)', condition: '100>a 并且 a>200' },
{ call: 'alert(2)', condition: '100>a 并且 非(a>200) 且 a>100' },
{ call: 'alert(5)', condition: '100>a 并且 非(a>200) 且 a>100 并且 b>200' },
{ call: 'alert(6)', condition: '100>a 并且 非(a>200) 且 a>100 并且 非(b>200)' },
{ call: 'alert(7)', condition: '100>a 并且 非(a>200) 且 a>100' },
{ call: 'alert(3)', condition: '100>a 并且 非(a>200) 且 非(a>100)' }, // ✅ 正确
{ call: 'alert(8)', condition: '100>a 并且 非(a>200) 且 非(a>100) 并且 b>200' }, // ✅
{ call: 'alert(9)', condition: '100>a 并且 非(a>200) 且 非(a>100) 并且 非(b>200)' }, // ✅
{ call: 'alert(10)', condition: '100>a 并且 非(a>200) 且 非(a>100)' } // ✅
]
< /code>
Фактический результат < /p>
[
{ call: 'alert(1)', condition: '100 > a 并且 a > 200' },
{ call: 'alert(4)', condition: '100 > a 并且 a > 200' },
{
call: 'alert(2)',
condition: '100 > a 并且 a > 200 并且 非(a > 200) 且 a > 100'
},
{
call: 'alert(5)',
condition: '100 > a 并且 a > 200 并且 非(a > 200) 且 a > 100 并且 b > 200'
},
{
call: 'alert(6)',
condition: '100 > a 并且 a > 200 并且 非(a > 200) 且 a > 100 并且 非(非(a > 200) 且 a > 100)'
},
{
call: 'alert(7)',
condition: '100 > a 并且 a > 200 并且 非(a > 200) 且 a > 100'
},
{ call: 'alert(3)', condition: '100 > a 并且 a > 200 并且 非(a > 200)' },
{
call: 'alert(8)',
condition: '100 > a 并且 a > 200 并且 非(a > 200) 并且 b > 200'
},
{
call: 'alert(9)',
condition: '100 > a 并且 a > 200 并且 非(a > 200) 并且 非(非(a > 200))'
},
{ call: 'alert(10)', condition: '100 > a 并且 a > 200 并且 非(a > 200)' }
]
Спасибо
Подробнее здесь: https://stackoverflow.com/questions/794 ... ditions-of