fixes
This commit is contained in:
@@ -1,7 +1,8 @@
|
||||
/* PHP symbol index + reference lookup.
|
||||
*
|
||||
* Two jobs, both on ripgrep:
|
||||
* - the index: every class/interface/trait/enum DECLARED in the project, as
|
||||
* - the index: every class/interface/trait/enum DECLARED in the project AND in
|
||||
* vendor (so a framework class is clickable too), as
|
||||
* name → {path, line}. The renderer needs the bare name list to decide which
|
||||
* tokens it may underline, and that decision is per visible token per frame,
|
||||
* so it cannot be a search. One rg pass answers it for every token at once.
|
||||
@@ -49,6 +50,11 @@ const BASE_IGNORE = [
|
||||
'node_modules', '.git', 'out', 'dist', 'build', '.cache',
|
||||
'vendor', 'coverage', '.helder', '.next', '.nuxt', '.turbo', '.idea', '.vscode',
|
||||
]
|
||||
/** `vendor/` is out of the reference search — nobody wants to read how Symfony
|
||||
* uses Throwable — but it IS indexed for declarations, so a framework class is
|
||||
* still a name we can underline and open. Measured on a Laravel app: 48 project
|
||||
* classes in 30 ms, 7k more with vendor in 170 ms. */
|
||||
const DECL_IGNORE = BASE_IGNORE.filter((d) => d !== 'vendor')
|
||||
|
||||
/** Declarations only. `readonly`/`final`/`abstract` may precede the keyword, and
|
||||
* an enum may carry a backing type. Anchored at the line start (with optional
|
||||
@@ -63,13 +69,14 @@ const NS_RE = /^[ \t]*namespace[ \t]+([A-Za-z_\\][\w\\]*)[ \t]*;/
|
||||
const TRAIT_RE = /^[ \t]+use[ \t]+([A-Za-z_\\][\w\\ \t,]*?)[ \t]*[;{]/
|
||||
const TRAIT_RG = '^\\s+use\\s+[A-Za-z_\\\\][\\w\\\\ \t,]*[;{]'
|
||||
|
||||
const MAX_DEFS = 25
|
||||
const MAX_REF_FILES = 300
|
||||
const MAX_LINE = 1000
|
||||
|
||||
function ignoreArgs(): string[] {
|
||||
function ignoreArgs(dirs: string[] = BASE_IGNORE): string[] {
|
||||
const cfg = getConfig()
|
||||
const args: string[] = []
|
||||
for (const d of BASE_IGNORE) args.push('--glob', `!${d}`)
|
||||
for (const d of dirs) args.push('--glob', `!${d}`)
|
||||
for (const g of cfg.files.exclude) if (g) args.push('--glob', `!${g}`)
|
||||
if (!cfg.files.followGitignore) args.push('--no-ignore')
|
||||
return args
|
||||
@@ -165,7 +172,7 @@ async function build(root: string): Promise<Index> {
|
||||
const byFile = new Map<string, SymbolDef[]>()
|
||||
const nsByFile = new Map<string, string>()
|
||||
await rgJson(
|
||||
['--json', '--hidden', '--glob', '*.php', ...ignoreArgs(), '-e', DECL_RG, '--', root],
|
||||
['--json', '--hidden', '--glob', '*.php', ...ignoreArgs(DECL_IGNORE), '-e', DECL_RG, '--', root],
|
||||
(abs, line, text) => {
|
||||
const rel = toRel(root, abs)
|
||||
const ns = parseNamespace(text)
|
||||
@@ -188,7 +195,7 @@ async function build(root: string): Promise<Index> {
|
||||
// pass. A `use` belongs to the last declaration above it in the same file —
|
||||
// which is also why the declaration pass has to run first.
|
||||
await rgJson(
|
||||
['--json', '--hidden', '--glob', '*.php', ...ignoreArgs(), '-e', TRAIT_RG, '--', root],
|
||||
['--json', '--hidden', '--glob', '*.php', ...ignoreArgs(DECL_IGNORE), '-e', TRAIT_RG, '--', root],
|
||||
(abs, line, text) => {
|
||||
const names = parseTraitUse(text)
|
||||
if (!names.length) return
|
||||
@@ -229,7 +236,12 @@ export async function symbolNames(root: string): Promise<string[]> {
|
||||
export async function lookupSymbol(root: string, name: string): Promise<SymbolLookup> {
|
||||
if (!/^[A-Za-z_]\w*$/.test(name)) return { name, defs: [], refs: [], refCount: 0 }
|
||||
const ix = await getIndex(root)
|
||||
const defs = ix.byName.get(name) ?? []
|
||||
// The project's own declaration comes first: a common name like `Handler` is
|
||||
// declared a dozen times inside vendor, and none of those is what was clicked.
|
||||
const defs = (ix.byName.get(name) ?? [])
|
||||
.slice()
|
||||
.sort((a, b) => Number(a.path.startsWith('vendor/')) - Number(b.path.startsWith('vendor/')) || a.path.localeCompare(b.path))
|
||||
.slice(0, MAX_DEFS)
|
||||
const declared = new Set(defs.map((d) => d.path + ':' + d.line))
|
||||
const order: string[] = []
|
||||
const groups = new Map<string, RefGroup>()
|
||||
|
||||
Reference in New Issue
Block a user