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

Method hasAnyPossibleMatch

src/resolution/index.ts:766–831  ·  view source on GitHub ↗

* Check if a reference name has any possible match in the codebase. * Uses the pre-built knownNames set to skip expensive resolution * for names that definitely don't exist as symbols.

(name: string)

Source from the content-addressed store, hash-verified

764 * for names that definitely don't exist as symbols.
765 */
766 private hasAnyPossibleMatch(name: string): boolean {
767 if (!this.knownNames) return true; // no pre-filter available
768
769 // Direct name match
770 if (this.knownNames.has(name)) return true;
771
772 // For qualified names like "obj.method" or "Class::method", check the parts
773 const dotIdx = name.indexOf('.');
774 if (dotIdx > 0) {
775 const receiver = name.substring(0, dotIdx);
776 const member = name.substring(dotIdx + 1);
777 if (this.knownNames.has(receiver) || this.knownNames.has(member)) return true;
778 // Also check capitalized receiver (instance-method resolution)
779 const capitalized = receiver.charAt(0).toUpperCase() + receiver.slice(1);
780 if (this.knownNames.has(capitalized)) return true;
781 // JVM FQN: `com.example.foo.Bar` — the only useful segment is the
782 // last one (`Bar`); the earlier check finds `example.foo.Bar` which
783 // never matches a node name.
784 const lastDot = name.lastIndexOf('.');
785 if (lastDot > dotIdx) {
786 const tail = name.substring(lastDot + 1);
787 if (tail && this.knownNames.has(tail)) return true;
788 }
789 }
790 const colonIdx = name.indexOf('::');
791 if (colonIdx > 0) {
792 const receiver = name.substring(0, colonIdx);
793 const member = name.substring(colonIdx + 2);
794 if (this.knownNames.has(receiver) || this.knownNames.has(member)) return true;
795 // Multi-segment path `a::b::c` (a Rust/C++ module call like
796 // `database::profiles::find`) — the only segment that names a symbol is
797 // the last (`c`); `member` above is `b::c`, which never matches a node
798 // name, so without this the pre-filter drops the ref before the Rust path
799 // resolver ever sees it. Mirror the dotted-name leaf check above.
800 const lastColon = name.lastIndexOf('::');
801 if (lastColon > colonIdx) {
802 const tail = name.substring(lastColon + 2);
803 if (tail && this.knownNames.has(tail)) return true;
804 }
805 }
806
807 // Lua/Luau method calls use a single `:` (`lg:log`); R uses `$` (`lg$log`).
808 // Check the member (and receiver) around these separators too, so the ref
809 // isn't dropped here before the method-call resolver ever sees it. The `:`
810 // case is skipped when the name actually contains `::` (handled above).
811 for (const sep of [':', '$']) {
812 if (sep === ':' && name.includes('::')) continue;
813 const sepIdx = name.indexOf(sep);
814 if (sepIdx > 0) {
815 const receiver = name.substring(0, sepIdx);
816 const member = name.substring(sepIdx + 1);
817 if (this.knownNames.has(member) || this.knownNames.has(receiver)) return true;
818 const capitalized = receiver.charAt(0).toUpperCase() + receiver.slice(1);
819 if (this.knownNames.has(capitalized)) return true;
820 }
821 }
822
823 // For path-like references (e.g., "snippets/drawer-menu.liquid"), check the filename

Callers 2

resolveOneMethod · 0.95
isBuiltInOrExternalMethod · 0.95

Calls 1

hasMethod · 0.80

Tested by

no test coverage detected