MCPcopy Create free account
hub / github.com/colbymchenry/codegraph / matchFunctionRef

Function matchFunctionRef

src/resolution/name-matcher.ts:208–353  ·  view source on GitHub ↗
(
  ref: UnresolvedRef,
  context: ResolutionContext
)

Source from the content-addressed store, hash-verified

206 * edge is worse than none.
207 */
208export function matchFunctionRef(
209 ref: UnresolvedRef,
210 context: ResolutionContext
211): ResolvedRef | null {
212 // `this.<member>` refs are resolved ONLY by the class-scoped resolver in
213 // resolveOne (resolveThisMemberFnRef) — never by name matching here.
214 if (ref.referenceName.startsWith('this.')) return null;
215
216 // In JS/TS/Python a bare identifier can never be a method value (methods
217 // are only reachable through a receiver — `this.m` / `self.m` /
218 // `Cls.m`), so bare fn-refs match FUNCTIONS only. This also sidesteps the
219 // pre-existing TS quirk of class fields extracting as method-kind nodes,
220 // which otherwise soaked up local names passed as arguments (excalidraw
221 // A/B finding; same pattern in vendored docopt.py). Python's `self.m`
222 // form keeps method targets via its own capture shape. C++ likewise: a
223 // bare identifier can only be a FREE function (member values need
224 // `&Cls::method`). PHP string callables name global FUNCTIONS (methods
225 // need the `[$obj, 'm']` array form, which carries its own shape). Other
226 // languages keep method targets: C# method groups, Swift/Dart
227 // implicit-self, Java/Kotlin method references.
228 const bareFnOnly =
229 ref.language === 'typescript' || ref.language === 'tsx' ||
230 ref.language === 'javascript' || ref.language === 'jsx' ||
231 ref.language === 'arkts' ||
232 ref.language === 'cpp' || ref.language === 'python' ||
233 ref.language === 'php';
234
235 // Python additionally accepts CLASS targets for bare identifiers (#1478):
236 // class-as-value is a core Python idiom (`return SomeSerializer`,
237 // `Meta.model = Org`, registry dicts, `admin.site.register(Model, Admin)`)
238 // and, unlike TS, Python has no type-annotation recovery path. The
239 // false-positive mechanism behind the function-only rule was lowercase
240 // locals colliding with same-named METHODS (docopt.py) — a candidate must
241 // be an exact-name CLASS node here, and the extraction gate (same-file
242 // class ∪ imports) plus unique-or-drop still apply. Methods stay excluded.
243 const bareClassOk = ref.language === 'python';
244
245 // Qualified member-pointer (`&Widget::on_click` → "Widget::on_click"):
246 // resolve the member ON THAT SCOPE — exempt from bareFnOnly (the `&Cls::m`
247 // shape is an explicit member reference). Unique-or-drop like everything else.
248 if (ref.referenceName.includes('::')) {
249 const memberName = ref.referenceName.slice(ref.referenceName.lastIndexOf('::') + 2);
250 const scoped = context
251 .getNodesByName(memberName)
252 .filter(
253 (n) =>
254 (n.kind === 'function' || n.kind === 'method') &&
255 sameLanguageFamily(n.language, ref.language) &&
256 n.id !== ref.fromNodeId &&
257 (n.qualifiedName === ref.referenceName ||
258 n.qualifiedName.endsWith(`::${ref.referenceName}`))
259 );
260 if (scoped.length === 0) return null;
261 const sameFileScoped = scoped.filter((n) => n.filePath === ref.filePath);
262 const pool = sameFileScoped.length > 0 ? sameFileScoped : scoped;
263 if (sameFileScoped.length === 0 && scoped.length > 1) return null;
264 const target = pool.reduce((a, b) => (a.startLine <= b.startLine ? a : b));
265 return {

Callers 2

resolveOneMethod · 0.90
matchReferenceFunction · 0.85

Calls 3

sameLanguageFamilyFunction · 0.85
getNodesByNameMethod · 0.65
getNodeByIdMethod · 0.65

Tested by

no test coverage detected