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

Method resolveCfmlComponentPath

src/resolution/index.ts:2182–2251  ·  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

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

Callers 1

resolveOneMethod · 0.95

Calls 2

normFunction · 0.70
joinMethod · 0.45

Tested by

no test coverage detected