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

Function inferJavaFieldReceiverType

src/resolution/name-matcher.ts:1048–1095  ·  view source on GitHub ↗

* Java/Kotlin: infer a receiver's declared type by walking field declarations * in the class enclosing the call site. The field's `signature` is already in * the form " " (set by tree-sitter.ts extractField), so we * pull the type from there. Handles Spring `@Resource UserBO

(
  receiverName: string,
  ref: UnresolvedRef,
  context: ResolutionContext,
)

Source from the content-addressed store, hash-verified

1046 * null when no matching field is in the enclosing class.
1047 */
1048function inferJavaFieldReceiverType(
1049 receiverName: string,
1050 ref: UnresolvedRef,
1051 context: ResolutionContext,
1052): string | null {
1053 const inFile = context.getNodesInFile(ref.filePath);
1054 if (inFile.length === 0) return null;
1055
1056 // Find the class enclosing the call line (tightest match by latest start).
1057 let enclosing: Node | null = null;
1058 for (const n of inFile) {
1059 if (n.kind !== 'class' && n.kind !== 'interface') continue;
1060 if (n.language !== ref.language) continue;
1061 const end = n.endLine ?? n.startLine;
1062 if (n.startLine <= ref.line && end >= ref.line) {
1063 if (!enclosing || n.startLine >= enclosing.startLine) enclosing = n;
1064 }
1065 }
1066 if (!enclosing) return null;
1067
1068 const enclosingEnd = enclosing.endLine ?? enclosing.startLine;
1069 const field = inFile.find(
1070 (n) =>
1071 n.kind === 'field' &&
1072 n.name === receiverName &&
1073 n.language === ref.language &&
1074 n.startLine >= enclosing.startLine &&
1075 (n.endLine ?? n.startLine) <= enclosingEnd,
1076 );
1077 if (!field || !field.signature) return null;
1078
1079 // Signature shape: "<TypeName> <fieldName>" (extractField). Pull the type,
1080 // strip generics + dotted package, drop array/varargs markers.
1081 const beforeName = field.signature.slice(
1082 0,
1083 field.signature.lastIndexOf(field.name),
1084 );
1085 const typeRaw = beforeName.trim();
1086 if (!typeRaw) return null;
1087
1088 const typeNoGenerics = typeRaw.replace(/<[^>]*>/g, '').trim();
1089 const typeNoArray = typeNoGenerics.replace(/\[\s*\]/g, '').replace(/\.\.\.$/, '').trim();
1090 const parts = typeNoArray.split(/[.\s]+/).filter(Boolean);
1091 const lastPart = parts[parts.length - 1];
1092 if (!lastPart) return null;
1093 if (!/^[A-Z]/.test(lastPart)) return null; // primitives / lowercase → skip
1094 return lastPart;
1095}
1096
1097// ── Local-variable receiver-type inference (#1108) ──────────────────────────
1098//

Callers 1

matchMethodCallFunction · 0.85

Calls 1

getNodesInFileMethod · 0.65

Tested by

no test coverage detected