Fading Coder

One Final Commit for the Last Sprint

Home > Tech > Content

CodeNavi Static Analysis Rule Language: Nodes and Node Properties for Code Statements

Tech 1

Source code is parsed into discrete tokens during static analysis, the smallest grammatical units that form programming language syntax. Common token types include keywords (e.g. if, while), identifiers (variable/function names), literals (numeric values, strings), operators (e.g. +, /), and separators (commas, semicolons). CodeNavi maps parsed code elements to standardized nodes, with explicitly defined properties for each node type. Users write inspection rules by combining logical conditions for these nodes and their attributes to match target defect patterns, without requiring knowledge of underlying static analysis implementation details.

Node and Attribute Definition Conventions

All nodes are referenced by their English identifier in CodeNavi DSL for simplified rule writing. A node set represents a collection of logically related nodes, while node attributes also use standardized English names for consistent reference.

Statement Nodes

Programming languages include multiple statement types for different runtime operations. Common statements are shown in the sample below:

// Expression statements: execute assignments, method calls
int userCount = 24;
System.out.println("Static analysis routine running");

// Conditional statements: execute branch logic based on boolean checks
int customerScore = 82;
if (customerScore > 75) {
    System.out.println("Premium user tier");
} else {
    System.out.println("Standard user tier");
}

// Switch statements: multi-branch selection
int orderStatus = 2;
switch(orderStatus) {
    case 1: System.out.println("Pending payment"); break;
    case 2: System.out.println("Processing shipment"); break;
    default: System.out.println("Unrecognized order state");
}

// Loop statements: repeat code execution
// For loop
for (int idx = 0; idx < 12; idx++) {
    System.out.println(idx);
}
// While loop
int counter = 0;
while (counter < 12) {
    System.out.println(counter++);
}
// Do-while loop
int retry = 0;
do {
    System.out.println(retry++);
} while (retry < 12);

// Jump statements: alter execution flow
// Break
for (int idx = 0; idx < 12; idx++) {
    if (idx == 7) break;
    System.out.println(idx);
}
// Continue
for (int idx = 0; idx < 12; idx++) {
    if (idx %3 ==0) continue;
    System.out.println(idx);
}

// Exception handling
try {
    int result = 200 / eligibleUserCount;
} catch (ArithmeticException e) {
    System.out.println("Cannot calculate discount for zero users");
}

// Return statement
public int getMin(int x, int y) {
    return x < y ? x : y;
}

Assign Statement (assignStatement)

Assign statements store the output of an expression or literal value to a target variable, used for variable initialization, state updates, and complex result caching to simplify code readability. Sample code:

int orderAmount = 199;
String userGroup = "premium_" + userId;

Node attributes:

Name Description Value Type Sample DSL Rule
lhs Left-hand assignment target valueAccess node orderAmount = 199; assignStatement assign where assign.lhs.name == "orderAmount";
rhs Right-hand value source literal, valueAccess, functionCall node orderAmount = 199; assignStatement assign where assign.rhs.value == 199;

Control Flow Statement Nodes

Control flow statements define the execution order of code blocks, supporting conditional branching, repeated execution, exception handlign, and execution flow redirection.

Jump Statements

Jump statements alter normal sequential execution to skip code blocks or redirect execution to other parts of the program.

Continue Statement (continueStatement)

The continue statement skips remaining logic in the current loop iteration and starts the next iteration, typically used to skip processing for elements that do not match filter conditions, reduce nested logic depth, and avoid duplicate processing of already handled records. Sample code:

for (int idx = 0; idx < 15; idx++) {
    // Skip multiples of 3
    if (idx %3 == 0) {
        continue;
    }
    System.out.println(idx);
}

Break Statement (breakStatement)

The break statement immediately terminates execution of the innermost enclosing loop or switch block, used to exit loops early when a target condition is met, avoid infinite loops, stop processing once a search target is found, and exit execution when an error state is detected. Sample code:

for (int idx = 0; idx < 15; idx++) {
    if (idx == 7) {
        break;
    }
    System.out.println(idx);
}

Return Statement (returnStatement)

The return statement exits the current function and optionally passes a result value back to the caller, used to return computation outputs, exit functions early when preconditions are not met, simplify conditional logic, and return error states during exception handling. Sample code:

public int getMin(int x, int y) {
    return x < y ? x : y;
}

Node attributes:

Name Description Value Type Sample DSL Rule
returnValue Returned value Any node type return userId; returnStatement ret where ret.returnValue.name == "userId";

Throw Statement (throwStatement)

The throw statement manually triggers an exception to interrupt normal execution when an invalid state is detected, supporting explicit error propagation, custom error type definition, and enforcement of interface implementation constraints. Sample code:

throw new IllegalArgumentException("Invalid input parameter value");

Node attributes:

Name Description Value Type Sample DSL Rule
operand Thrown exception instance Node throw new RuntimeException(); throwStatement thr where thr.operand is objectCreationExpression;

Conditional Control (ifBlock)

Conditional control blocks select execution paths based on boolean condition results, supporting dynamic logic branching, feature toggling, state validation, error prevention, and resource management. Sample code:

if (orderAmount > 200) {
    System.out.println("Eligible for free shipping");
} else {
    System.out.println("Add $15 for standard shipping");
}

Node attributes:

Name Description Value Type Sample DSL Rule
condition If conditional expression binaryOperation node if (orderAmount > 200) {} ifBlock ib where ib.condition contain binaryOperation bo where bo.operator == ">";
thenBlock Code executed when condition evaluates to true block node if (orderAmount > 200) { print("Free shipping"); } ifBlock ib where ib.thenBlock contain stringLiteral sl where sl.value == "Eligible for free shipping";
elseBlock Code executed when condition evaluates to false block node else { print("Shipping fee applied"); } ifBlock ib where ib.elseBlock contain stringLiteral sl where sl.value == "Add $15 for standard shipping";

Switch Control

Switch blocks provide a cleaner alternative to nested if-else chains for multi-branch selection based on discrete value matches, reducing code nesting, improving readability, and simplifying maintenance of multi-condition logic. Sample code:

switch (orderStatus) {
    case 1:
        System.out.println("Pending payment confirmation");
        break;
    case 2:
    case 3:
        System.out.println("Order processing in progress");
        break;
    default:
        System.out.println("Unknown order state");
}

Switch Block (switchBlock)

Node attributes:

Name Description Value Type Sample DSL Rule
selector Value evaluated for case matching Any node type switch (orderStatus) {} switchBlock sw where sw.selector.name == "orderStatus";

Case Statement (caseStatement)

DSL rule sample:

caseStatement cs where cs contain numericLiteral;

Default Statement (defaultStatement)

DSL rule sample:

switchBlock sw where sw contain defaultStatement;

Loop Control

Loop control blocks enable repeated execution of code segments for iterative data processing, algorithm implementation, and batch operation handling. Supported loop types include forBlock, forEachBlock, whileBlock, and doWhileBlock.

Loop Block Base Attributes

All loop types share the following common attributes:

Name Description Value Type Sample DSL Rule
condition Loop continuation condition Any node type while (stock > 0) {} whileBlock wb where wb.condition contain binaryOperation bo where bo.lhs.name == "stock";
body Loop execution code block body node while (stock >0) { stock--; } whileBlock wb where wb.body contain unaryOperation;
body.statementNum Number of statements in loop body Numeric while (stock>0) { stock--; print(stock); } whileBlock wb where wb.body.statementNum == 2;
firstStatement First statement in loop block Any node type while (stock>0) { stock--; print(stock); } whileBlock wb where wb.firstStatement contain unaryOperation;
lastStatement Last statement in loop block Any node type while (stock>0) { stock--; print(stock); } whileBlock wb where wb.lastStatement contain functionCall;

For Loop Block (forBlock)

Sample code:

for (int prodIdx = 0; prodIdx < productList.size(); prodIdx++) {
    processProduct(productList.get(prodIdx));
}

Node attributes:

Name Description Value Type Sample DSL Rule
initialization Loop variable enitialization variableDeclaration, variableAccess node for (int prodIdx =0; ...) {} forBlock fb where fb.initialization.name == "prodIdx";
condition Loop continuation condition binaryOperation node for (...; prodIdx < productList.size(); ...) {} forBlock fb where fb.condition.rhs is functionCall;
iteration Post-iteration update operation unaryOperation node for (...; prodIdx++) {} forBlock fb where fb.iteration.operator == "++";

ForEach Loop Block (forEachBlock)

Sample code:

List<String> skuList = List.of("SKU001", "SKU002", "SKU003");
for (String sku : skuList) {
    logInventoryLevel(sku);
}

Node attributes:

Name Description Value Type Sample DSL Rule
variable Iteration variable variableDeclaration node for (String sku : skuList) {} forEachBlock feb where and(feb.variable is variableDeclaration, feb.variable.name == "sku");
iterable Collection being iterated over Any node type for (String sku : skuList) {} forEachBlock feb where feb.iterable.name == "skuList";

While Loop Block (whileBlock)

Sample code:

int stock = 100;
while (stock > 0) {
    stock -= fulfillSingleOrder();
}

Do-While Loop Block (doWhileBlock)

Sample code:

int retryCount = 0;
do {
    retryCount++;
    sendNotificationAlert();
} while (retryCount < 3 && !alertDelivered);

Node attributes align with the base loop block attribute set.

Exception Handling

Exception handling blocks separate error detection and recovery logic from normal business flow, preventing unexpected program crashes, ensuring proper resource cleanup, and providing actionable error diagnostics. Sample code:

try {
    int discount = 100 / eligibleUserCount;
} catch (Exception e) {
    throw new RuntimeException("Failed to calculate user discount", e);
} finally {
    clearTemporaryCalculationData();
}

Exception Block (exceptionBlock)

Covers tryBlock, catchBlock, and finallyBlock components. Node attributes:

Name Description Value Type Sample DSL Rule
tryBlock Code block where exceptions may be thrown tryBlock node try { int discount = 100 / eligibleUserCount; } exceptionBlock eb where eb.tryBlock contain variableDeclaration;
catchBlocks Collection of catch blocks for handling different exception types List of catchBlock nodes catch (Exception e) { throw new RuntimeException(e); } exceptionBlock eb where eb.catchBlocks contain cb where cb contain throwStatement;
finallyBlock Code guaranteed to execute regardless of exception state finallyBlock node finally { clearTempData(); } exceptionBlock eb where eb.finallyBlock contain functionCall fc where fc.name == "clearTemporaryCalculationData";
Catch Block (catchBlock)

Node attributes:

Name Description Value Type Sample DSL Rule
parameters List of exception parameters declared for the catch block Node list catch (Exception e) {} catchBlock cb where cb.parameters contain p where p.name == "e";

Try-With-Resources Block (tryWithResources)

Auto-closes declared resources after execution to prevent resource leaks, no manual cleanup required. Sample code:

try (FileReader fr = new FileReader("app-config.properties"); BufferedReader br = new BufferedReader(fr)) {
    loadApplicationConfig(br);
} catch (FileNotFoundException fnfe) {
    logger.error("Configuration file not found", fnfe);
} catch (IOException ioe) {
    logger.error("Failed to read configuration file", ioe);
}

Node attributes:

Name Description Value Type Sample DSL Rule
tryBlock Main execution code block tryBlock node try (...) { loadConfig(br); } tryWithResources twr where twr.tryBlock contain functionCall;
catchBlocks Collection of exception handling blocks List of catchBlock nodes catch (FileNotFoundException fnfe) {} tryWithResources twr where twr.catchBlocks contain cb where cb contain functionCall fc where fc.name == "error";
finallyBlock Optional final execution block finallyBlock node tryWithResources twr where twr.finallyBlock is not null;
resources Collection of auto-closeable resources declared in the try header List of statement nodes try (FileReader fr = new FileReader("config.properties")) {} tryWithResources twr where twr.resources contain re where re contain functionCall fc where fc.name == "FileReader";

Static Block (staticBlock)

Static initialization blocks run once when a class is first loaded, before any instance creation or static method invocation, used for static variable initialization, one-time resource loading, class-level configuration setup, and static constant assignment. Sample code:

static {
    MAX_RETRY_ATTEMPTS = 5;
    loadDefaultConfiguration();
}

DSL rule sample:

staticBlock sb where sb contain variableDeclaration vd where vd.name == "MAX_RETRY_ATTEMPTS";

Synchronized Block (synchronizedBlock)

Synchronized blocks enforce thread safety for shared resource access in multi-threaded environments, ensuring atomicity of operations, preventing race conditions, implementing mutual exclusion, and maintaining data consistency. Sample code:

// Object lock for instance-level resource protection
synchronized (inventoryLock) {
    updateStockLevel(skuId, adjustedQuantity);
}

// Class lock for global resource protection
synchronized (OrderService.class) {
    return generateUniqueOrderId();
}

Node attributes:

Name Description Value Typpe Sample DSL Rule
lock Monitor object used for synchronization Any node type synchronized (inventoryLock) {} synchronizedBlock synb where synb.lock contain variableAccess va where va.name == "inventoryLock";
body Code block protected by the synchronization lock block node synchronized (inventoryLock) { updateStockLevel(...); } synchronizedBlock synb where synb.body contain functionCall fc where fc.name == "updateStockLevel";
body.statementNum Number of statements in the synchronized block Numeric synchronized (inventoryLock) { updateStockLevel(skuId, qty); } synchronizedBlock synb where synb.body.statementNum == 1;
firstStatement First statement in the synchronized block Any node type synchronizedBlock synb where synb.firstStatement contain functionCall;
lastStatement Last statement in the synchronized block Any node type synchronizedBlock synb where synb.lastStatement contain returnStatement;

Related Articles

Understanding Strong and Weak References in Java

Strong References Strong reference are the most prevalent type of object referencing in Java. When an object has a strong reference pointing to it, the garbage collector will not reclaim its memory. F...

Comprehensive Guide to SSTI Explained with Payload Bypass Techniques

Introduction Server-Side Template Injection (SSTI) is a vulnerability in web applications where user input is improper handled within the template engine and executed on the server. This exploit can r...

Implement Image Upload Functionality for Django Integrated TinyMCE Editor

Django’s Admin panel is highly user-friendly, and pairing it with TinyMCE, an effective rich text editor, simplifies content management significantly. Combining the two is particular useful for bloggi...

Leave a Comment

Anonymous

◎Feel free to join the discussion and share your thoughts.