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

Function inferJavaFieldReceiverType

src/resolution/name-matcher.ts:1176–1223  ·  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

1174 * null when no matching field is in the enclosing class.
1175 */
1176function inferJavaFieldReceiverType(
1177 receiverName: string,
1178 ref: UnresolvedRef,
1179 context: ResolutionContext,
1180): string | null {
1181 const inFile = context.getNodesInFile(ref.filePath);
1182 if (inFile.length === 0) return null;
1183
1184 // Find the class enclosing the call line (tightest match by latest start).
1185 let enclosing: Node | null = null;
1186 for (const n of inFile) {
1187 if (n.kind !== 'class' && n.kind !== 'interface') continue;
1188 if (n.language !== ref.language) continue;
1189 const end = n.endLine ?? n.startLine;
1190 if (n.startLine <= ref.line && end >= ref.line) {
1191 if (!enclosing || n.startLine >= enclosing.startLine) enclosing = n;
1192 }
1193 }
1194 if (!enclosing) return null;
1195
1196 const enclosingEnd = enclosing.endLine ?? enclosing.startLine;
1197 const field = inFile.find(
1198 (n) =>
1199 n.kind === 'field' &&
1200 n.name === receiverName &&
1201 n.language === ref.language &&
1202 n.startLine >= enclosing.startLine &&
1203 (n.endLine ?? n.startLine) <= enclosingEnd,
1204 );
1205 if (!field || !field.signature) return null;
1206
1207 // Signature shape: "<TypeName> <fieldName>" (extractField). Pull the type,
1208 // strip generics + dotted package, drop array/varargs markers.
1209 const beforeName = field.signature.slice(
1210 0,
1211 field.signature.lastIndexOf(field.name),
1212 );
1213 const typeRaw = beforeName.trim();
1214 if (!typeRaw) return null;
1215
1216 const typeNoGenerics = typeRaw.replace(/<[^>]*>/g, '').trim();
1217 const typeNoArray = typeNoGenerics.replace(/\[\s*\]/g, '').replace(/\.\.\.$/, '').trim();
1218 const parts = typeNoArray.split(/[.\s]+/).filter(Boolean);
1219 const lastPart = parts[parts.length - 1];
1220 if (!lastPart) return null;
1221 if (!/^[A-Z]/.test(lastPart)) return null; // primitives / lowercase → skip
1222 return lastPart;
1223}
1224
1225// ── Local-variable receiver-type inference (#1108) ──────────────────────────
1226//

Callers 1

matchMethodCallFunction · 0.85

Calls 1

getNodesInFileMethod · 0.65

Tested by

no test coverage detected