/** * Test with logging inside the rule */ const rule = { meta: { type: 'problem', docs: { description: 'Test', category: 'Page Query', }, fixable: null, schema: [], messages: { mustUseBuilder: 'Must use builders', }, }, create(context) { let inPageQueryExecute = false; let hasManualTransformation = false; let hasBuilderCall = false; let pageQueryClassName = null; return { ClassDeclaration(node) { if (node.id && node.id.name && node.id.name.endsWith('PageQuery')) { pageQueryClassName = node.id.name; console.log(' [ClassDeclaration] Found:', pageQueryClassName); } }, MethodDefinition(node) { if (node.key.type === 'Identifier' && node.key.name === 'execute' && node.parent.type === 'ClassBody') { const classNode = node.parent.parent; if (classNode && classNode.id && classNode.id.name && classNode.id.name.endsWith('PageQuery')) { inPageQueryExecute = true; console.log(' [MethodDefinition] execute() in PageQuery'); } } }, CallExpression(node) { if (inPageQueryExecute) { console.log(' [CallExpression] inside execute:', node.callee.type); if (node.callee.type === 'MemberExpression' && node.callee.property.type === 'Identifier' && (node.callee.property.name === 'build' || node.callee.property.name === 'createViewData')) { console.log(' [CallExpression] Found Builder call!'); hasBuilderCall = true; } } }, VariableDeclarator(node) { if (inPageQueryExecute && node.init && node.init.type === 'ObjectExpression') { console.log(' [VariableDeclarator] ObjectExpression found'); hasManualTransformation = true; } }, ReturnStatement(node) { if (inPageQueryExecute && node.argument) { console.log(' [ReturnStatement] type:', node.argument.type); // Direct object literal return if (node.argument.type === 'ObjectExpression') { console.log(' [ReturnStatement] ObjectExpression - setting manual transformation'); hasManualTransformation = true; } // Direct identifier return else if (node.argument.type === 'Identifier') { console.log(' [ReturnStatement] Identifier:', node.argument.name); if (!node.argument.name.includes('ViewData') && !node.argument.name.includes('viewData')) { console.log(' [ReturnStatement] Not ViewData, checking builder call...'); if (!hasBuilderCall) { console.log(' [ReturnStatement] No builder call - setting manual transformation'); hasManualTransformation = true; } } } // CallExpression else if (node.argument.type === 'CallExpression') { console.log(' [ReturnStatement] CallExpression'); const callExpr = node.argument; if (callExpr.callee.type === 'MemberExpression' && callExpr.callee.object.type === 'Identifier' && callExpr.callee.object.name === 'Result' && callExpr.callee.property.type === 'Identifier' && (callExpr.callee.property.name === 'ok' || callExpr.callee.property.name === 'err')) { console.log(' [ReturnStatement] Result.' + callExpr.callee.property.name + '()'); if (callExpr.callee.property.name === 'ok' && callExpr.arguments.length > 0 && callExpr.arguments[0].type === 'Identifier') { const argName = callExpr.arguments[0].name; console.log(' [ReturnStatement] Argument:', argName); const isApiDto = argName.includes('Dto') || argName.includes('api') || argName === 'result' || argName === 'data'; console.log(' [ReturnStatement] Is API DTO?', isApiDto); console.log(' [ReturnStatement] Has builder call?', hasBuilderCall); if (isApiDto && !hasBuilderCall) { console.log(' [ReturnStatement] ✓ Setting manual transformation!'); hasManualTransformation = true; } } } } } }, 'MethodDefinition:exit'(node) { if (node.key.type === 'Identifier' && node.key.name === 'execute') { inPageQueryExecute = false; console.log(' [MethodDefinition:exit] execute()'); } }, 'Program:exit'() { console.log('\n[Program:exit]'); console.log(' hasManualTransformation:', hasManualTransformation); console.log(' hasBuilderCall:', hasBuilderCall); console.log(' Should report?', hasManualTransformation && !hasBuilderCall); if (hasManualTransformation && !hasBuilderCall) { console.log(' ✓✓✓ REPORTING ERROR ✓✓✓'); context.report({ node: context.getSourceCode().ast, messageId: 'mustUseBuilder', }); } }, }; }, }; // Test it const mockContext = { getSourceCode: () => ({ ast: {} }), report: (data) => { console.log('\n*** REPORT CALLED ***'); } }; const visitor = rule.create(mockContext); console.log('=== Test with Logging ===\n'); visitor.ClassDeclaration({ id: { name: 'AdminDashboardPageQuery' } }); visitor.MethodDefinition({ key: { type: 'Identifier', name: 'execute' }, parent: { type: 'ClassBody' } }); visitor.VariableDeclarator({ init: { type: 'CallExpression' } }); visitor.ReturnStatement({ argument: { type: 'CallExpression', callee: { type: 'MemberExpression', object: { type: 'Identifier', name: 'Result' }, property: { type: 'Identifier', name: 'ok' } }, arguments: [{ type: 'Identifier', name: 'apiDto' }] } }); visitor['MethodDefinition:exit']({ key: { type: 'Identifier', name: 'execute' } }); visitor['Program:exit'](); console.log('\n=== Done ===');