Skip to content

feat(golang): Go variable, constant, and assignment parsing (PR-05) - #524

Merged
shivasurya merged 1 commit into
mainfrom
shiva/golang-pr05-variables
Feb 15, 2026
Merged

shivasurya merged 1 commit into
mainfrom
shiva/golang-pr05-variables

Conversation

@shivasurya

Copy link
Copy Markdown
Owner

Summary

  • Add VarInfo struct and parsing functions in graph/golang/variables.go for extracting variable/constant/assignment information from Go AST nodes
  • Handle var declarations (including grouped and multi-name: var x, y int)
  • Handle short variable declarations (:=) with blank identifier filtering (_, err := foo() creates only one node for "err")
  • Handle const declarations (including grouped with iota: const ( A = iota; B; C ))
  • Handle assignment statements (=) with multi-variable support
  • Set VariableValue field on all nodes for DSL variable() matcher support (required for hardcoded credentials rule GO-SEC-004)
  • Add dispatchers in parser_golang.go that convert VarInfo into graph.Node with correct types and SourceLocation byte ranges
  • Fill four stubs in parser.go for var_declaration, short_var_declaration, const_declaration, assignment_statement

Test plan

  • go build ./... compiles without errors
  • go vet ./... clean
  • All existing tests pass (go test ./graph/...) — no regressions
  • New tests in variables_test.go: var with type only, var with type+value, var with inferred type, var grouped, var multi-name, single short var, multi short var, short var with blank, single const, const iota group, unexported const, single assignment, multi assignment
  • ParseVarDeclaration 100% coverage, extractVarSpec 100% coverage
  • ParseShortVarDeclaration 95.2%, ParseConstDeclaration 92.9%, ParseAssignment 94.1% coverage
  • Overall golang package coverage: 95.4%

🤖 Generated with Claude Code

@shivasurya shivasurya added the enhancement New feature or request label Feb 14, 2026
@shivasurya shivasurya self-assigned this Feb 14, 2026
@safedep

safedep Bot commented Feb 14, 2026 •

Copy link
Copy Markdown

SafeDep Report Summary

Green Malicious Packages Badge Green Vulnerable Packages Badge Green Risky License Badge

No dependency changes detected. Nothing to scan.

This report is generated by SafeDep Github App

@codecov

codecov Bot commented Feb 14, 2026 •

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 84.97653% with 32 lines in your changes missing coverage. Please review.
✅ Project coverage is 83.00%. Comparing base (f581b39) to head (b941020).
⚠️ Report is 1 commits behind head on main.

Files with missing lines Patch % Lines
sast-engine/graph/parser_golang.go 71.08% 23 Missing and 1 partial ⚠️
sast-engine/graph/golang/variables.go 95.08% 3 Missing and 3 partials ⚠️
sast-engine/graph/parser.go 75.00% 2 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main     #524      +/-   ##
==========================================
+ Coverage   82.97%   83.00%   +0.02%     
==========================================
  Files         126      127       +1     
  Lines       14623    14836     +213     
==========================================
+ Hits        12134    12315     +181     
- Misses       2034     2062      +28     
- Partials      455      459       +4     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@shivasurya shivasurya changed the title feat: Go variable, constant, and assignment parsing feat(golang): Go variable, constant, and assignment parsing (PR-05) Feb 14, 2026

shivasurya commented Feb 15, 2026 •

Copy link
Copy Markdown
Owner Author

Merge activity

  • Feb 15, 4:00 AM UTC: A user started a stack merge that includes this pull request via Graphite.
  • Feb 15, 4:07 AM UTC: Graphite rebased this pull request as part of a merge.
  • Feb 15, 4:08 AM UTC: @shivasurya merged this pull request with Graphite.

@shivasurya
shivasurya changed the base branch from shiva/golang-pr04-types to graphite-base/524 February 15, 2026 04:05
@shivasurya
shivasurya changed the base branch from graphite-base/524 to main February 15, 2026 04:06
Add VarInfo extraction from Go var/const/:= AST nodes. Handles grouped
declarations, multi-name vars (var x, y int), blank identifier filtering
in short var (_, err := foo()), and iota const groups. Sets VariableValue
field for DSL matcher support. Dispatchers create CodeGraph nodes with
correct types (module_variable, variable_assignment, multi_var_assignment,
constant) and SourceLocation byte ranges.

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
@shivasurya
shivasurya force-pushed the shiva/golang-pr05-variables branch from 7a92a2e to b941020 Compare February 15, 2026 04:07
@github-actions

Copy link
Copy Markdown

Code Pathfinder Security Scan

Pass Critical High Medium Low Info

No security issues detected.

Metric Value
Files Scanned 4
Rules 38

Powered by Code Pathfinder

@shivasurya
shivasurya merged commit 31b7631 into main Feb 15, 2026
4 of 5 checks passed
@shivasurya
shivasurya deleted the shiva/golang-pr05-variables branch February 15, 2026 04:08
shivasurya added a commit that referenced this pull request Feb 15, 2026
…(PR-06 complete) (#525)

## Summary
Complete implementation of PR-06 (Calls, Closures & Statements), broken down into three focused sub-PRs for easier review. Implements call expressions, function literals, defer/go statements, and control flow statements (return, for, if).

## Changes

### PR-06a: Call Expressions (#cf466cd)
**New Files:**
- **`graph/golang/calls.go`** (111 lines)
  - `CallInfo` struct: FunctionName, ObjectName, Arguments, IsSelector
  - `ParseCallExpression`: Handles simple calls, method calls, package calls
  - `ParseSelectorExpression`: Extracts object and field from selector_expression
  - `extractArguments`: Helper to extract arguments from argument_list

- **`graph/golang/calls_test.go`** (185 lines)
  - 6 test cases for ParseCallExpression (simple, method, package, no args, chained, complex)
  - 3 test cases for ParseSelectorExpression
  - Nil/error handling tests

**Modified Files:**
- **`parser_golang.go`**
  - Added `parseGoCallExpression` dispatcher (lines 227-274)
  - Creates Type: "call" or "method_expression" nodes
  - **CRITICAL**: Uses `graph.AddEdge(currentContext, callNode)` for parent-child linking
  - Stores ObjectName in Interface field for method calls

- **`parser.go`**
  - Filled call_expression stub (lines 105-108)

### PR-06b: Closures, Defer & Go Statements (#3d1b667)
**New Files:**
- **`graph/golang/closures.go`** (93 lines)
  - `ClosureInfo` struct: Params, ReturnType, LineNumber, StartByte, EndByte
  - `ParseFuncLiteral`: Handles func literals with params/returns
  - `ParseDeferStatement`: Extracts call from defer statement
  - `ParseGoStatement`: Extracts call from go statement

- **`graph/golang/closures_test.go`** (259 lines)
  - 5 test cases for ParseFuncLiteral (simple, no params, multi params, multi returns, IIFE)
  - 3 test cases for ParseDeferStatement (method, function, with args)
  - 3 test cases for ParseGoStatement (function, method, closure)
  - Nil/error handling tests

**Modified Files:**
- **`parser_golang.go`** (added lines 277-394)
  - `anonCounters` map for tracking anonymous function names per parent
  - `generateAnonName`: Generates $anon_N names scoped to parent context
  - `parseGoFuncLiteral`: Creates func_literal nodes, returns node as currentContext
  - `parseGoDeferStatement`: Creates defer_call nodes with edge to parent
  - `parseGoGoStatement`: Creates go_call nodes with edge to parent

- **`helpers.go`**
  - Fixed ExtractParameters to initialize with empty slices (not nil)

- **`parser.go`**
  - Filled func_literal stub (returns currentContext for body traversal)
  - Filled defer_statement stub
  - Filled go_statement stub

### PR-06c: Control Flow Statements (#2067448)
**New Files:**
- **`graph/golang/statements.go`** (177 lines)
  - `ReturnInfo` struct: Values, LineNumber, StartByte, EndByte
  - `ParseReturnStatement`: Handles single/multiple return values
  - `ForInfo` struct: IsRange, Condition, Init, Update, Left, Right
  - `ParseForStatement`: Handles C-style, range, while-style, infinite loops
  - `IfInfo` struct: Condition, LineNumber, StartByte, EndByte
  - `ParseIfStatement`: Extracts if statement condition

- **`graph/golang/statements_test.go`** (306 lines)
  - 5 test cases for ParseReturnStatement
  - 5 test cases for ParseForStatement
  - 4 test cases for ParseIfStatement
  - Nil/error handling tests

**Modified Files:**
- **`parser_golang.go`** (added lines 417-556)
  - `parseGoReturnStatement`: Creates ReturnStmt model nodes
  - `parseGoForStatement`: Creates ForStmt model nodes
  - `parseGoIfStatement`: Creates IfStmt model nodes
  - `joinStrings`: Helper to join string slices with commas
  - Uses GenerateSha256 for statement IDs (NOT GenerateMethodID)
  - Does NOT create edges for statement nodes (Python pattern)

- **`parser.go`**
  - Added Go handler to return_statement case (line 30-32)
  - Added Go handler to for_statement case (line 66-68)
  - Added Go handler to if_statement case (line 59-61)

- **Lint fixes**: Added comment periods, refactored to switch statement

## Test Results
```bash
go build ./...                      # ✅ passes
go vet ./...                        # ✅ passes
golangci-lint run                   # ✅ passes
go test -v ./graph/golang/...      # ✅ all pass, 94.6% coverage
go test ./graph/...                # ✅ no regressions
```

### Coverage Details
- PR-06a: ParseCallExpression 76.2%, ParseSelectorExpression 100%, extractArguments 100%
- PR-06b: ParseFuncLiteral 100%, ParseDeferStatement 100%, ParseGoStatement 100%
- PR-06c: ParseReturnStatement 100%, ParseForStatement 100%, ParseIfStatement 100%

## Examples

### PR-06a: Call Expressions
| Code | Node Type | Name | Interface | Arguments |
|------|-----------|------|-----------|-----------|
| `fmt.Println("hello")` | method_expression | Println | ["fmt"] | ["\"hello\""] |
| `foo(x, y)` | call | foo | - | ["x", "y"] |
| `obj.Method(a, b)` | method_expression | Method | ["obj"] | ["a", "b"] |
| `bar()` | call | bar | - | [] |

### PR-06b: Closures, Defer & Go
| Code | Node Type | Name | Params | ReturnType |
|------|-----------|------|--------|------------|
| `func(x int) int { return x + 1 }` | func_literal | $anon_1 | ["x"] | "int" |
| `defer f.Close()` | defer_call | Close | - | - |
| `go handler(conn)` | go_call | handler | - | - |

### PR-06c: Control Flow Statements
| Code | Node Type | Values/Condition |
|------|-----------|------------------|
| `return 42` | ReturnStmt | Values: ["42"] |
| `return 0, nil` | ReturnStmt | Values: ["0", "nil"] |
| `for i := 0; i < 10; i++ {}` | ForStmt | IsRange: false, Condition: "i < 10" |
| `for _, v := range items {}` | ForStmt | IsRange: true, Left: "_, v", Right: "items" |
| `if err != nil {}` | IfStmt | Condition: "err != nil" |

## Design Decisions

### PR-06a: Call Expressions
1. **Edge creation**: Uses `graph.AddEdge(currentContext, callNode)` for parent-child linking (CRITICAL for call graph construction in PR-08)
2. **Node.Interface overloading**: Stores ObjectName in Interface field for method/package calls
3. **Empty slice initialization**: `arguments := []string{}` for consistency
4. **IIFE handling**: func_literal case deferred to PR-06b

### PR-06b: Closures
1. **Anonymous naming**: $anon_N scoped to parent function using anonCounters map
2. **func_literal returns node**: Becomes currentContext for closure body traversal
3. **defer/go create edges**: Uses graph.AddEdge pattern for parent-child linking
4. **Empty slices**: ExtractParameters now initializes with []string{} for consistency

### PR-06c: Statements
1. **Statement IDs**: Uses GenerateSha256 following Python pattern (NOT GenerateMethodID)
2. **No edge creation**: Statement nodes don't create edges (Python pattern)
3. **model objects**: Creates minimal model.ReturnStmt, model.ForStmt, model.IfStmt wrappers
4. **While-style loops**: Stores condition in Init field for consistency
5. **Switch statement**: Refactored if-else chain for gocritic lint compliance

## Stack
- **Base**: shiva/golang-pr05-variables (#524)
- **This PR**: shiva/golang-pr06-calls-closures
- **Next**: PR-07 (call graph construction)

## Verification Against PR-06 Doc
### PR-06a
✅ CallInfo struct matches spec
✅ ParseCallExpression handles simple/method/package calls
✅ ParseSelectorExpression extracts object and field
✅ graph.AddEdge creates parent-child relationship
✅ Tests cover all call types from doc examples

### PR-06b
✅ ClosureInfo struct matches spec
✅ ParseFuncLiteral handles params and return types
✅ ParseDeferStatement/ParseGoStatement extract calls
✅ Anonymous function naming: $anon_N scoped to parent
✅ func_literal returns node for currentContext
✅ defer/go create edges with graph.AddEdge

### PR-06c
✅ ReturnInfo/ForInfo/IfInfo structs match spec
✅ ParseReturnStatement handles single/multiple values
✅ ParseForStatement handles C-style, range, while-style, infinite loops
✅ ParseIfStatement extracts condition
✅ Statement nodes use GenerateSha256 (not GenerateMethodID)
✅ Statement nodes don't create edges

🤖 Generated with [Claude Code](https://claude.com/claude-code)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant