Skip to content

perf: use node.type for O(1) operator detection across Go, Rust, Python, JS/TS analyzers#412

Merged
askpt merged 2 commits into
mainfrom
repo-assist/perf-operator-type-access-20260624-d2fb2505f0b0cc9e
Jun 25, 2026
Merged

perf: use node.type for O(1) operator detection across Go, Rust, Python, JS/TS analyzers#412
askpt merged 2 commits into
mainfrom
repo-assist/perf-operator-type-access-20260624-d2fb2505f0b0cc9e

Conversation

@github-actions

Copy link
Copy Markdown
Contributor

🤖 This PR was created by Repo Assist, an automated AI assistant.

Summary

Replace sourceText.substring() calls with operatorNode.type for binary and boolean operator detection in the Go, Rust, Python, and JS/TS (jsLikeAnalyzer) analyzers. Also apply two additional O(1) micro-optimisations in the Go and Rust/JS analyzers.

Why this is faster

In tree-sitter, anonymous tokens (e.g. &&, ||, ??, and, or) have their literal text as their .type property. The Java analyzer already uses .type for the same purpose and has done so correctly since the Java analyzer was introduced. This PR brings the other four analyzers into line.

Previously each visit to a binary_expression / boolean_operator / logical_expression node triggered a string allocation via sourceText.substring(operatorNode.startIndex, operatorNode.endIndex). These nodes are among the most common in typical TypeScript/JavaScript/Go/Rust/Python source files.

Changes

All four analyzers: getBinaryOperator / getBooleanOperator / getOperator

-const text = this.sourceText.substring(operatorNode.startIndex, operatorNode.endIndex);
-if (text === "&&" || text === "||") { return text; }
+const type = operatorNode.type;
+if (type === "&&" || type === "||") { return type; }

Go — isRecoverCall

-const funcNode = node.children.find((child) => child.type === "identifier"); // O(n) scan
+const funcNode = node.childForFieldName("function"); // O(1) field access

Rust & jsLikeAnalyzer — else_clause reason detection

-const hasNestedIf = node.children.some((child) => child.type === "if_expression"); // O(n)
+const hasNestedIf = node.firstNamedChild?.type === "if_expression"; // O(1)

Test Status

npm run compile  ✅  (0 errors)
npm run lint     ✅  (0 warnings)
npm run test:unit  ✅  149 passing, 0 failing

The Java analyzer has been using operatorNode.type throughout — that pattern is already validated by the existing test suite. All 149 unit tests (covering binary operators in Go, Rust, Python, JS, and TS) continue to pass unchanged.

Warning

Firewall blocked 1 domain

The following domain was blocked by the firewall during workflow execution:

  • releaseassets.githubusercontent.com

To allow these domains, add them to the network.allowed list in your workflow frontmatter:

network:
  allowed:
    - defaults
    - "releaseassets.githubusercontent.com"

See Network Configuration for more information.

Generated by 🌈 Repo Assist, see workflow run. Learn more.

Add this agentic workflows to your repo

To install this agentic workflow, run

gh aw add githubnext/agentics/workflows/repo-assist.md@d63b34de41bc0dc052096e094c732cf28eafc659

…JS/TS analyzers

Replace sourceText.substring() calls with operatorNode.type for binary
and boolean operator detection across four analyzers. Anonymous tokens
in tree-sitter have their literal text as their .type, so no string
allocation or index arithmetic is needed.

Also:
- Go isRecoverCall: use childForFieldName('function') instead of a
  linear children.find() scan (O(1) vs O(n))
- Rust/JS else_clause reason: use firstNamedChild?.type instead of
  children.some() scan (O(1) vs O(n))

These paths run on every binary/logical expression in the file being
analysed, so avoiding allocations here has measurable benefit on
large, operator-heavy files.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@askpt askpt changed the title [repo-assist] perf: use node.type for O(1) operator detection across Go, Rust, Python, JS/TS analyzers perf: use node.type for O(1) operator detection across Go, Rust, Python, JS/TS analyzers Jun 24, 2026
@codecov

codecov Bot commented Jun 24, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 78.15%. Comparing base (d5d49b9) to head (e689616).
⚠️ Report is 1 commits behind head on main.

Additional details and impacted files
@@            Coverage Diff             @@
##             main     #412      +/-   ##
==========================================
- Coverage   78.18%   78.15%   -0.04%     
==========================================
  Files          13       13              
  Lines        4167     4161       -6     
  Branches      470      469       -1     
==========================================
- Hits         3258     3252       -6     
  Misses        906      906              
  Partials        3        3              

☔ View full report in Codecov by Harness.
📢 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.

@askpt askpt marked this pull request as ready for review June 24, 2026 15:13
@askpt askpt self-requested a review as a code owner June 24, 2026 15:13
Copilot AI review requested due to automatic review settings June 24, 2026 15:13

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR optimizes operator detection in several tree-sitter analyzers by avoiding substring() allocations and using SyntaxNode.type (which is the literal token text for anonymous/keyword tokens), plus a couple of small O(1) AST-access tweaks.

Changes:

  • Rust/Python/JS-like/Go: switch binary/boolean operator extraction from sourceText.substring(...) to operatorNode.type.
  • Go: switch recover() detection from an O(n) child scan to childForFieldName("function").
  • Rust & JS-like: change else-clause “else if” detection to an O(1) check (but this introduces a correctness issue for comments/extras between else and if).

Reviewed changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated 2 comments.

File Description
src/metricsAnalyzer/languages/rustAnalyzer.ts Uses operatorNode.type for logical operator detection; updates else-clause reason detection (issue: firstNamedChild can be a comment).
src/metricsAnalyzer/languages/pythonAnalyzer.ts Uses operatorNode.type for and/or operator detection.
src/metricsAnalyzer/languages/jsLikeAnalyzer.ts Uses operatorNode.type for `&&/
src/metricsAnalyzer/languages/goAnalyzer.ts Uses childForFieldName("function") for recover() detection; uses operatorNode.type for `&&/

Comment thread src/metricsAnalyzer/languages/rustAnalyzer.ts Outdated
Comment thread src/metricsAnalyzer/languages/jsLikeAnalyzer.ts Outdated
Co-authored-by: askpt <2493377+askpt@users.noreply.github.com>
Copilot finished work on behalf of askpt June 25, 2026 07:36
@askpt askpt enabled auto-merge (squash) June 25, 2026 07:40
@askpt askpt merged commit 0aef168 into main Jun 25, 2026
7 checks passed
@askpt askpt deleted the repo-assist/perf-operator-type-access-20260624-d2fb2505f0b0cc9e branch June 25, 2026 07:40
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants