Skip to content

fix(regexpcompileinfunction): resolve package identity via type checker instead of identifier name#39773

Merged
pelikhan merged 4 commits into
mainfrom
copilot/fix-regexp-compile-call
Jun 17, 2026
Merged

fix(regexpcompileinfunction): resolve package identity via type checker instead of identifier name#39773
pelikhan merged 4 commits into
mainfrom
copilot/fix-regexp-compile-call

Conversation

Copilot AI commented Jun 17, 2026

Copy link
Copy Markdown
Contributor

isRegexpCompileCall matched regexp.MustCompile/regexp.Compile by comparing the AST identifier's .Name to the string "regexp" — no type-checker involvement. This produces false negatives for aliased imports (import re "regexp") and false positives for any local identifier named regexp with a Compile/MustCompile method.

Changes

regexpcompileinfunction.go

  • isRegexpCompileCall now accepts *analysis.Pass and resolves the caller's package via pass.TypesInfo.ObjectOf(ident).(*types.PkgName), then gates on pkgName.Imported().Path() == "regexp" — same pattern as the sortslice linter
  • Added nil guard for pkgName.Imported() to prevent panic when the type checker's error-recovery path creates a PkgName with a nil imported package
// before
return ident.Name == "regexp" && (sel.Sel.Name == "MustCompile" || sel.Sel.Name == "Compile")

// after
obj := pass.TypesInfo.ObjectOf(ident)
pkgName, ok := obj.(*types.PkgName)
if !ok || pkgName.Imported() == nil {
    return false
}
return pkgName.Imported().Path() == "regexp"

Test fixtures

  • alias_import.goimport re "regexp" with in-function re.MustCompile/re.Compile; both annotated // want to verify they are now flagged (FN fix)
  • shadowed_identifier.go — local variable named regexp of a custom type with MustCompile called with a constant string pattern; no // want, verifying it is not flagged (FP fix)
  • dot_import.go — documents the known limitation that import . "regexp" calls are not flagged, since dot imports produce bare identifier calls rather than selector expressions

Copilot AI and others added 2 commits June 17, 2026 12:23
Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
…einfunction linter

Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
Copilot AI changed the title [WIP] Fix regexp compile call identification logic fix(regexpcompileinfunction): resolve package identity via type checker instead of identifier name Jun 17, 2026
Copilot AI requested a review from pelikhan June 17, 2026 12:32
@pelikhan pelikhan marked this pull request as ready for review June 17, 2026 12:34
Copilot AI review requested due to automatic review settings June 17, 2026 12:34
@github-actions

github-actions Bot commented Jun 17, 2026

Copy link
Copy Markdown
Contributor

Test Quality Sentinel completed test quality analysis.

No test files were added or modified in this PR. The PR modifies pkg/linters/regexpcompileinfunction/regexpcompileinfunction.go (production code) and adds two testdata fixture files (alias_import.go, shadowed_identifier.go) under testdata/src/. These fixture files are Go source inputs analyzed by the existing regexpcompileinfunction_test.go, not test implementations themselves. Test Quality Sentinel skipped.

@github-actions

github-actions Bot commented Jun 17, 2026

Copy link
Copy Markdown
Contributor

Design Decision Gate 🏗️ completed the design decision gate check.

No ADR enforcement needed: PR #39773 does not have the 'implementation' label (has_implementation_label=false) and has only 49 new lines of code in business logic directories (≤100 threshold). Neither Condition A nor Condition B is met.

@github-actions

github-actions Bot commented Jun 17, 2026

Copy link
Copy Markdown
Contributor

PR Code Quality Reviewer completed the code quality review.

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

Updates the regexpcompileinfunction Go analyzer to identify regexp.Compile / regexp.MustCompile calls based on type-checked package identity (fixing alias-import false negatives and shadowing false positives), and adds test fixtures to validate the behavior.

Changes:

  • Resolve the selector qualifier via pass.TypesInfo (*types.PkgName) instead of comparing identifier names to "regexp".
  • Add testdata fixtures for import re "regexp" and for a shadowed regexp identifier.
  • Regenerate/update several workflow .lock.yml schemas (not described in the PR text).
Show a summary per file
File Description
pkg/linters/regexpcompileinfunction/regexpcompileinfunction.go Uses type checker to confirm the selector targets the stdlib regexp package.
pkg/linters/regexpcompileinfunction/testdata/src/regexpcompileinfunction/alias_import.go Adds alias-import fixture to ensure re.MustCompile / re.Compile are flagged inside functions.
pkg/linters/regexpcompileinfunction/testdata/src/regexpcompileinfunction/shadowed_identifier.go Adds shadowing fixture to ensure a local regexp identifier is not treated as the stdlib package.
.github/workflows/test-quality-sentinel.lock.yml Updates pull_request_number schema validation key.
.github/workflows/smoke-copilot.lock.yml Updates pull_request_number schema validation key.
.github/workflows/smoke-copilot-arm.lock.yml Updates pull_request_number schema validation key.
.github/workflows/smoke-copilot-aoai-entra.lock.yml Updates pull_request_number schema validation key.
.github/workflows/smoke-copilot-aoai-apikey.lock.yml Updates pull_request_number schema validation key.
.github/workflows/smoke-claude.lock.yml Updates pull_request_number schema validation key.
.github/workflows/security-review.lock.yml Updates pull_request_number schema validation key.
.github/workflows/refiner.lock.yml Updates pull_request_number schema validation key.
.github/workflows/pr-triage-agent.lock.yml Updates pull_request_number schema validation key.
.github/workflows/pr-nitpick-reviewer.lock.yml Updates pull_request_number schema validation key.
.github/workflows/pr-code-quality-reviewer.lock.yml Updates pull_request_number schema validation key.
.github/workflows/mattpocock-skills-reviewer.lock.yml Updates pull_request_number schema validation key.
.github/workflows/grumpy-reviewer.lock.yml Updates pull_request_number schema validation key.

Copilot's findings

Tip

Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

  • Files reviewed: 16/16 changed files
  • Comments generated: 2

Comment on lines +10 to +14
func GoodShadowedRegexpIdentifier(s string) bool {
regexp := customRegexp{}
_ = regexp.MustCompile(s)
return true
}

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Fixed in commit fix: address review feedback.... The fixture now uses a compile-time constant string pattern (^[a-z]+$) and the unused parameter s has been removed, so it properly exercises the false-positive case against the old name-based check.

Comment on lines 731 to 735
]
},
"pull_request_number": {
"optionalPositiveInteger": true
"issueOrPRNumber": true
},

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

The lock.yml changes were auto-generated by make recompile during the initial plan commit and are unrelated to this linter fix. Reverted all 13 lock.yml files to their base state in the latest commit.

@github-actions github-actions Bot 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.

🔎 Code quality review by PR Code Quality Reviewer

}
return ident.Name == "regexp" && (sel.Sel.Name == "MustCompile" || sel.Sel.Name == "Compile")
pkgName, ok := obj.(*types.PkgName)
return ok && pkgName.Imported().Path() == "regexp"

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.

Potential nil dereference on pkgName.Imported(): when the type checker's error-recovery path creates a PkgName for an unresolvable import, Imported() returns nil, and the .Path() call will panic the linter instead of gracefully returning false.

💡 Suggested fix
pkgName, ok := obj.(*types.PkgName)
if !ok || pkgName.Imported() == nil {
    return false
}
return pkgName.Imported().Path() == "regexp"

The go/types resolver (see resolver.go) calls types.NewPkgName(..., nil) when it cannot resolve an import during error recovery. Any linter run against a package with a broken or missing import dependency will hit this nil and crash. The existing pattern of guarding obj == nil makes the missing guard here inconsistent and easy to overlook.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Fixed in the latest commit. Added the nil guard as suggested:

pkgName, ok := obj.(*types.PkgName)
if !ok || pkgName.Imported() == nil {
    return false
}
return pkgName.Imported().Path() == "regexp"

@@ -0,0 +1,20 @@
package regexpcompileinfunction

import re "regexp"

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.

Undocumented false negative: import . "regexp" is silently skipped. With a dot import, call sites are bare identifiers (MustCompile(...)) rather than selector expressions, so isRegexpCompileCall exits early at the *ast.SelectorExpr guard and produces no diagnostic.

💡 Details

This is a pre-existing limitation, not introduced by this PR, but the PR adds test fixtures specifically targeting import-aliasing edge cases without mentioning this gap. Either add a comment in the function doc noting the limitation, or add a dot_import.go fixture that documents the known miss:

package regexpcompileinfunction

import . "regexp"

// NOT flagged (known limitation: dot imports are not selector expressions).
func DotImportExample(s string) bool {
    r := MustCompile(`^[a-z]+$`) // no // want — dot-import calls are silently skipped
    return r.MatchString(s)
}

Without this, a future refactor that adds dot-import detection would have no regression test to verify the change.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Added dot_import.go in the latest commit to document this known limitation. The fixture confirms dot-import calls are silently skipped (no // want annotation) and includes a comment explaining why: dot imports produce bare identifier calls, not selector expressions, so isRegexpCompileCall exits early at the *ast.SelectorExpr guard.

@pelikhan

Copy link
Copy Markdown
Collaborator

@copilot run pr-finisher skill

- Guard pkgName.Imported() against nil before calling .Path()
- Fix shadowed_identifier.go fixture to use constant string pattern
- Add dot_import.go fixture documenting dot-import known limitation
- Revert unrelated lock.yml changes (optionalPositiveInteger -> issueOrPRNumber)

Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>

Copilot AI commented Jun 17, 2026

Copy link
Copy Markdown
Contributor Author

@copilot run pr-finisher skill

All review threads addressed in the latest commit. Summary of changes made:

  • Added nil guard for pkgName.Imported() to prevent panic on unresolvable imports
  • Fixed shadowed_identifier.go fixture to use a constant string pattern (exercises the false-positive case properly)
  • Added dot_import.go fixture documenting the known dot-import limitation
  • Reverted 13 unrelated lock.yml changes back to base

@pelikhan pelikhan merged commit 62994a2 into main Jun 17, 2026
@pelikhan pelikhan deleted the copilot/fix-regexp-compile-call branch June 17, 2026 13:54
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants