From 6dfbceae74917ee5b04a2201e73d032b06cdfe70 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Sat, 27 Jun 2026 06:07:32 +0000 Subject: [PATCH 1/2] perf: hoist C# type-declaration Set to static readonly and use childForFieldName in Go receiver lookup MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - csharpAnalyzer: move the inline `new Set([...])` in `getEnclosingTypeName` to a `private static readonly` class field (TYPE_DECLARATION_TYPES). The set was reallocated on every call to `getEnclosingTypeName`, which is invoked once per method/accessor/operator in every C# file analysed. A static field is allocated once at class load time and reused across all calls. - goAnalyzer: replace the linear `.children.find(c => c.type === ...)` scan in `findTypeInParameterList` with `child.childForFieldName("type")` — an O(1) tree-sitter field lookup. This also removes the hard-coded list of receiver type node kinds (type_identifier, pointer_type, qualified_type), making the lookup correctly handle any type form the grammar may return (slice, map, channel, etc.). Both changes are pure performance micro-optimisations with no semantic effect; all 153 unit tests pass. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .../languages/csharpAnalyzer.ts | 18 ++++++++++-------- src/metricsAnalyzer/languages/goAnalyzer.ts | 10 +++------- 2 files changed, 13 insertions(+), 15 deletions(-) diff --git a/src/metricsAnalyzer/languages/csharpAnalyzer.ts b/src/metricsAnalyzer/languages/csharpAnalyzer.ts index f8232d0..4b509d8 100644 --- a/src/metricsAnalyzer/languages/csharpAnalyzer.ts +++ b/src/metricsAnalyzer/languages/csharpAnalyzer.ts @@ -77,6 +77,15 @@ interface CSharpFunctionMetrics { * ``` */ export class CSharpMetricsAnalyzer { + /** Node types that represent type declarations (class, struct, interface, record, enum). */ + private static readonly TYPE_DECLARATION_TYPES = new Set([ + "class_declaration", + "struct_declaration", + "interface_declaration", + "record_declaration", + "enum_declaration", + ]); + /** Current nesting level during analysis */ private nesting = 0; /** Current complexity score during analysis */ @@ -221,16 +230,9 @@ export class CSharpMetricsAnalyzer { * @returns The enclosing type name, or null if none found */ private getEnclosingTypeName(node: Parser.SyntaxNode): string | null { - const typeDeclarations = new Set([ - "class_declaration", - "struct_declaration", - "interface_declaration", - "record_declaration", - "enum_declaration", - ]); let parent = node.parent; while (parent) { - if (typeDeclarations.has(parent.type)) { + if (CSharpMetricsAnalyzer.TYPE_DECLARATION_TYPES.has(parent.type)) { const nameNode = parent.childForFieldName("name"); if (nameNode) { return this.sourceText.substring(nameNode.startIndex, nameNode.endIndex); diff --git a/src/metricsAnalyzer/languages/goAnalyzer.ts b/src/metricsAnalyzer/languages/goAnalyzer.ts index 7f828a7..ee58889 100644 --- a/src/metricsAnalyzer/languages/goAnalyzer.ts +++ b/src/metricsAnalyzer/languages/goAnalyzer.ts @@ -278,13 +278,9 @@ export class GoMetricsAnalyzer { ): Parser.SyntaxNode | null { for (const child of parameterList.children) { if (child.type === "parameter_declaration") { - // Look for type_identifier or pointer_type - const typeNode = child.children.find( - (c) => - c.type === "type_identifier" || - c.type === "pointer_type" || - c.type === "qualified_type" - ); + // Use childForFieldName for O(1) field access rather than a linear + // scan over the parameter's children. + const typeNode = child.childForFieldName("type"); if (typeNode) { return typeNode; } From e935a7347869cf5e77b01499245bff4f5ae48e29 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 27 Jun 2026 12:45:59 +0000 Subject: [PATCH 2/2] fix: address review comments on TYPE_DECLARATION_TYPES and findTypeInParameterList JSDoc - csharpAnalyzer: type TYPE_DECLARATION_TYPES as ReadonlySet to enforce compile-time immutability; private static readonly prevents reassignment but not mutation (e.g. .add()), so the explicit ReadonlySet annotation closes that gap at the type level. - goAnalyzer: update findTypeInParameterList JSDoc to accurately describe that the method returns the receiver's full type node via the tree-sitter 'type' field, not merely a 'type identifier'. The new wording also documents that the field-based lookup correctly handles pointer, qualified, slice, and other type forms the grammar may produce. Co-authored-by: askpt <2493377+askpt@users.noreply.github.com> --- src/metricsAnalyzer/languages/csharpAnalyzer.ts | 2 +- src/metricsAnalyzer/languages/goAnalyzer.ts | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/metricsAnalyzer/languages/csharpAnalyzer.ts b/src/metricsAnalyzer/languages/csharpAnalyzer.ts index 4b509d8..3ccf2db 100644 --- a/src/metricsAnalyzer/languages/csharpAnalyzer.ts +++ b/src/metricsAnalyzer/languages/csharpAnalyzer.ts @@ -78,7 +78,7 @@ interface CSharpFunctionMetrics { */ export class CSharpMetricsAnalyzer { /** Node types that represent type declarations (class, struct, interface, record, enum). */ - private static readonly TYPE_DECLARATION_TYPES = new Set([ + private static readonly TYPE_DECLARATION_TYPES: ReadonlySet = new Set([ "class_declaration", "struct_declaration", "interface_declaration", diff --git a/src/metricsAnalyzer/languages/goAnalyzer.ts b/src/metricsAnalyzer/languages/goAnalyzer.ts index ee58889..3f1cbc1 100644 --- a/src/metricsAnalyzer/languages/goAnalyzer.ts +++ b/src/metricsAnalyzer/languages/goAnalyzer.ts @@ -268,7 +268,9 @@ export class GoMetricsAnalyzer { } /** - * Finds the type identifier within a parameter list (used for method receivers). + * Finds the type node within a parameter list (used for method receivers). + * Returns the full type node via the tree-sitter "type" field, which correctly + * handles any type form the grammar may produce (pointer, qualified, slice, etc.). * * @param parameterList - The parameter list node to search * @returns The type node or null if not found