Skip to content

[refactor] stringutil: consolidate duplicated inline ASCII-alphanumeric rune checks #47446

Description

@github-actions

Semantic Function Clustering Analysis

Analysis of repository: github/gh-aw — scoped to pkg/stats and pkg/stringutil (non-test Go files).

Executive Summary

The analyzed slice is small and, on the whole, well organized. Files in pkg/stringutil are already partitioned by feature (ansi.go, fuzzy_match.go, identifiers.go, pat_validation.go, sanitize.go, urls.go) and pkg/stats/statvar.go is a single cohesive type. One genuine low-risk duplicate was found, plus two minor organizational observations. No large-scale refactor is warranted.

  • Files analyzed: 8 (7 in stringutil, 1 in stats)
  • Functions/methods cataloged: ~35
  • Verified duplicates: 1 (inline ASCII-alphanumeric rune check)
  • Outliers (wrong file): 0 clear cases; 2 mild grouping suggestions
  • Detection method: symbol inventory + naming-cluster analysis + pattern grep

1. Duplicate: inline ASCII-alphanumeric rune check (Priority 1 — low effort)

Two functions in sanitize.go open-code the identical ASCII alphanumeric test:

  • pkg/stringutil/sanitize.go:220 — inside SanitizeIdentifierName
  • pkg/stringutil/sanitize.go:326 — inside SanitizeForFilename
// line 220 (SanitizeIdentifierName)
if (r >= 'a' && r <= 'z') || (r >= 'A' && r <= 'Z') || (r >= '0' && r <= '9') || r == '_' {

// line 326 (SanitizeForFilename)
if (r >= 'a' && r <= 'z') || (r >= 'A' && r <= 'Z') || (r >= '0' && r <= '9') || r == '-' || r == '_' || r == '.' {

Recommendation: extract a small unexported helper in sanitize.go and reuse it in both call sites:

func isASCIIAlphanumeric(r rune) bool {
	return (r >= 'a' && r <= 'z') || (r >= 'A' && r <= 'Z') || (r >= '0' && r <= '9')
}

Then the checks become isASCIIAlphanumeric(r) || r == '_' and isASCIIAlphanumeric(r) || r == '-' || r == '_' || r == '.'. Purely mechanical, behavior-preserving; existing tests cover both functions.

Impact: single source of truth for the character-class definition; easier to keep the two sanitizers consistent.


2. Minor: whitespace helpers could cluster (Priority 3 — optional)

stringutil.go is the catch-all file and currently mixes several unrelated concerns:

  • NormalizeWhitespace (stringutil.go:34) and NormalizeLeadingWhitespace (stringutil.go:97) — whitespace normalization
  • Truncate (stringutil.go:20), FormatList (stringutil.go:77) — formatting
  • ParseVersionValue (stringutil.go:54) — type-to-string conversion
  • IsPositiveInteger (stringutil.go:150) — validation

The two Normalize*Whitespace functions form a natural pair and could move to a whitespace.go file if this catch-all grows. Not urgent — at the current size a single utility file is idiomatic. Flagging only so it is on the radar as the file expands.


3. Confirmed good organization (no action)

  • PAT cluster (pat_validation.go): ClassifyPAT, ValidateCopilotPAT, GetPATTypeDescription + PATType methods — cohesive, correctly isolated.
  • ANSI cluster (ansi.go): StripANSI + skip*/is*CSIChar helpers — cohesive.
  • Identifier/path cluster (identifiers.go): NormalizeWorkflowName, MarkdownToLockFile, LockFileToMarkdown, NormalizeSafeOutputIdentifier — cohesive.
  • Sanitize cluster (sanitize.go): SanitizeParameterName/SanitizePythonVariableName already delegate to a shared SanitizeIdentifierName — good existing reuse.
  • stats (statvar.go): single StatVar type with focused methods — no issues.

Implementation Checklist

  • Add isASCIIAlphanumeric helper in sanitize.go and update lines 220 and 326
  • Run pkg/stringutil tests to confirm no behavior change
  • (Optional) Revisit whitespace-helper grouping if stringutil.go grows

Analysis Metadata

  • Scope: pkg/stats, pkg/stringutil (precomputed slice)
  • Duplicates detected: 1
  • Outliers: 0 clear
  • Analysis date: 2026-07-23

Generated by 🔧 Semantic Function Refactoring · sonnet46 113.5 AIC · ⌖ 10 AIC · ⊞ 9.5K ·

  • expires on Jul 24, 2026, 7:31 PM UTC-08:00

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions