* Resolve a Lua/Luau `require(...)` to its module file. The reference name is * either a dotted module path (`telescope.config` → `telescope/config.lua`) or a * Roblox instance-path leaf (`Signal` from `require(script.Parent.Signal)` → * `Signal.luau`). We try ` .lua|.luau` and ` /init.
(ref: UnresolvedRef, context: ResolutionContext)
| 1888 | * requiring file wins (instance-path requires resolve within the same package). |
| 1889 | */ |
| 1890 | function resolveLuaRequire(ref: UnresolvedRef, context: ResolutionContext): ResolvedRef | null { |
| 1891 | const name = ref.referenceName; |
| 1892 | if (!name) return null; |
| 1893 | const base = name.includes('.') ? name.replace(/\./g, '/') : name; |
| 1894 | const suffixes = [`${base}.lua`, `${base}.luau`, `${base}/init.lua`, `${base}/init.luau`]; |
| 1895 | const byBasename = luaBasenameIndex(context); |
| 1896 | const shared = (a: string, b: string): number => { |
| 1897 | let i = 0; |
| 1898 | while (i < a.length && i < b.length && a[i] === b[i]) i++; |
| 1899 | return i; |
| 1900 | }; |
| 1901 | for (const suffix of suffixes) { |
| 1902 | // Only files sharing the suffix's basename can match — the bucket is in |
| 1903 | // getAllFiles() order, so this filter yields exactly what the full-list |
| 1904 | // scan did. |
| 1905 | const candidates = byBasename.get(suffix.split('/').pop() ?? '') ?? []; |
| 1906 | const matches = candidates.filter((f) => f === suffix || f.endsWith('/' + suffix)); |
| 1907 | if (matches.length === 0) continue; |
| 1908 | matches.sort((x, y) => shared(y, ref.filePath) - shared(x, ref.filePath)); |
| 1909 | const best = matches[0]!; |
| 1910 | if (best === ref.filePath) continue; |
| 1911 | const fileNode = context.getNodesInFile(best).find((n) => n.kind === 'file'); |
| 1912 | if (fileNode) { |
| 1913 | // Confidence ≥ 0.9 so this deterministic path/suffix match wins over |
| 1914 | // name-matching, which otherwise resolves the require to the import node |
| 1915 | // itself (a same-name self-match). |
| 1916 | return { original: ref, targetNodeId: fileNode.id, confidence: 0.9, resolvedBy: 'import' }; |
| 1917 | } |
| 1918 | } |
| 1919 | return null; |
| 1920 | } |
| 1921 | |
| 1922 | /** |
| 1923 | * `UploadApi.uploadARCapture()` where `UploadApi` is a NAMESPACE OBJECT — the |
no test coverage detected