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

Method resolveCfmlComponentPath

src/resolution/index.ts:2174–2243  ·  view source on GitHub ↗

* Resolve a CFML inheritance reference written as a component path (#1152). * Two forms exist in real code: * * - Dotted: `extends="coldbox.system.web.Controller"` — dots are directory * separators from the webroot or a CFML mapping. Mappings live in server * config / Application.

(ref: UnresolvedRef)

Source from the content-addressed store, hash-verified

2172 * dotted paths are written to match the on-disk file name.
2173 */
2174 private resolveCfmlComponentPath(ref: UnresolvedRef): ResolvedRef | null {
2175 const cfmlCandidates = (name: string): Node[] =>
2176 this.context
2177 .getNodesByName(name)
2178 .filter(
2179 (n) =>
2180 (n.kind === 'class' || n.kind === 'interface') &&
2181 (n.language === 'cfml' || n.language === 'cfscript')
2182 );
2183 const norm = (p: string): string => p.replace(/\\/g, '/').toLowerCase();
2184
2185 // Relative-path form: `../base`, `./base`, `sub/thing` — resolve against
2186 // the referencing file's directory and require an exact (case-insensitive)
2187 // file match.
2188 if (ref.referenceName.includes('/')) {
2189 const rel = ref.referenceName.replace(/\.cfc$/i, '');
2190 const fromDir = ref.filePath.replace(/\\/g, '/').split('/').slice(0, -1);
2191 const parts = [...fromDir];
2192 for (const seg of rel.split('/')) {
2193 if (seg === '' || seg === '.') continue;
2194 if (seg === '..') {
2195 if (parts.length === 0) return null; // escapes the project root
2196 parts.pop();
2197 } else {
2198 parts.push(seg);
2199 }
2200 }
2201 const wantPath = norm(parts.join('/') + '.cfc');
2202 const className = parts[parts.length - 1];
2203 if (!className) return null;
2204 const target = cfmlCandidates(className).find((c) => norm(c.filePath) === wantPath);
2205 return target
2206 ? { original: ref, targetNodeId: target.id, confidence: 0.95, resolvedBy: 'file-path' }
2207 : null;
2208 }
2209
2210 // Dotted form.
2211 const segments = ref.referenceName.split('.').map((s) => s.trim()).filter(Boolean);
2212 if (segments.length < 2) return null;
2213 const className = segments[segments.length - 1]!;
2214 const dirSegments = segments.slice(0, -1);
2215
2216 let best: Node | null = null;
2217 let bestScore = 0;
2218 let tie = false;
2219 for (const cand of cfmlCandidates(className)) {
2220 const dirs = cand.filePath.replace(/\\/g, '/').split('/').slice(0, -1);
2221 // Count matching directory segments right-to-left: for
2222 // `coldbox.system.web.Controller` vs `system/web/Controller.cfc`,
2223 // `web` and `system` match, then the repo root ends the run → score 2.
2224 let score = 0;
2225 while (
2226 score < dirSegments.length &&
2227 score < dirs.length &&
2228 dirSegments[dirSegments.length - 1 - score]!.toLowerCase() ===
2229 dirs[dirs.length - 1 - score]!.toLowerCase()
2230 ) {
2231 score++;

Callers 1

resolveOneMethod · 0.95

Calls 2

normFunction · 0.70
joinMethod · 0.45

Tested by

no test coverage detected