Enforce code quality standards for IDAPython including strict typing, Google-style docstrings, modular architecture, and design patterns. Use when writing type-safe IDA plugins, documenting IDAPython code, structuring large plugin architectures, or implementing clean code practices in reverse engineering tools.
Strict quality enforcement for maintainable reverse engineering tools.
Mandatory Type Annotations:
selfNone explicitly for void functionsIDA-Specific Type Aliases:
from typing import NewType, TypeAlias
EffectiveAddress: TypeAlias = int # Valid address in loaded binary
FileOffset: TypeAlias = int # Offset in original file
SegmentSelector: TypeAlias = int # Segment/selector value
InstructionLength: TypeAlias = int # Instruction size in bytes
FunctionId = NewType('FunctionId', int) # Unique identifier, not address
Advanced Typing Features:
Protocol - Interface definitions for duck typing (FunctionAnalyzer protocol)TypedDict - Structured configuration (PluginConfig)NamedTuple - Immutable data records (XrefRecord)Enum - Enumeration values with semantics (AnalysisPhase)Generic[T] - Type-specific caching (Cache[T])Example Protocol:
from typing import Protocol, runtime_checkable
@runtime_checkable
class FunctionAnalyzer(Protocol):
def can_analyze(self, func: functions.Function) -> bool: ...
def analyze(self, func: functions.Function) -> "AnalysisResult": ...
@property
def name(self) -> str: ...
Google-Style Docstrings Required:
def find_indirect_calls(
func: functions.Function,
max_depth: int = 5,
*,
include_imports: bool = False
) -> list["IndirectCall"]:
"""Identify indirect function calls within given function.
Indirect calls (call [reg], call [mem], call reg) are critical for
understanding dynamic dispatch, vtables, and callback mechanisms.
Design rationale: Iterative depth-limit prevents explosion in complex
functions. Position-only max_depth for concise calls, keyword-only
include_imports for explicit intent.
Args:
func: Function to analyze. Must have valid CFG.
max_depth: Maximum iterations for fixed-point calculation.
Higher values increase precision but also runtime.
include_imports: Whether to include imported functions (IAT/EAT)
as possible call targets. Default False (many false positives).
Returns:
List of detected indirect calls, sorted by address.
Empty list if none found.
Raises:
AnalysisError: If func has no valid CFG.
ValueError: If max_depth not positive.
Example:
>>> func = functions.at(0x401000)
>>> calls = find_indirect_calls(func, max_depth=3)
>>> for call in calls:
... print(f"{call.ea:#x}: {call.pattern.name}")
"""
Inline Comments Rules:
Module-Level Docstrings: Must include: purpose, key components list, design principles, dependencies.
Three-Layer Architecture:
Design Patterns for IDA Pro:
import ida_idaapi
class MyPlugin(ida_idaapi.plugin_t):
flags = ida_idaapi.PLUGIN_MULTI | ida_idaapi.PLUGIN_MOD
comment = "Automated function analysis with Domain API"
help = "https://docs.example.com/ida-plugins/myplugin"
wanted_name = "MyAnalyzer"
wanted_hotkey = "Ctrl-Shift-M"
def init(self) -> int:
if not ida_idaapi.is_ida_initialized():
return ida_idaapi.PLUGIN_SKIP
return ida_idaapi.PLUGIN_OK
def run(self, arg: int) -> None: ...
def term(self) -> None: ...
Observer Pattern (Event handling):
ida_domain.hooks.IDBHook for database changesUI_Hooks for interface eventsFactory Pattern: AnalyzerFactory for architecture-specific instantiation
Strategy Pattern: DeobfuscationStrategy interface with multiple implementations
Context Manager: Database.open(), transaction() for atomicity
Single Responsibility Principle: Each module/class/function has one reason to change. Separation of concerns enables unit testing without IDA Pro runtime.