Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion scripts/engine.browser.d.mts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
declare const ENGINE_VERSION = "2.31.8";
declare const SCHEMA_VERSION = 5;
declare const EXTRACTOR_VERSION = 17;
declare const EXTRACTOR_VERSION = 18;
type FileKind = "code" | "doc" | "config" | "asset" | "other";
type EdgeKind = "contains" | "doc-link" | "import" | "call" | "extends" | "implements" | "use" | "mention";
type Tier = 0 | 1 | 2;
Expand Down
278 changes: 139 additions & 139 deletions scripts/engine.browser.mjs

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion scripts/engine.d.mts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
declare const ENGINE_VERSION = "2.31.8";
declare const SCHEMA_VERSION = 5;
declare const EXTRACTOR_VERSION = 17;
declare const EXTRACTOR_VERSION = 18;
type FileKind = "code" | "doc" | "config" | "asset" | "other";
type EdgeKind = "contains" | "doc-link" | "import" | "call" | "extends" | "implements" | "use" | "mention";
type Tier = 0 | 1 | 2;
Expand Down
84 changes: 74 additions & 10 deletions scripts/engine.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ var init_types = __esm({
"use strict";
ENGINE_VERSION = "2.31.8";
SCHEMA_VERSION = 5;
EXTRACTOR_VERSION = 17;
EXTRACTOR_VERSION = 18;
}
});

Expand Down Expand Up @@ -8119,7 +8119,12 @@ function readName(node) {
function readReceiver(node) {
if (!node || node.namedChildren.length === 0) return void 0;
const obj = node.childForFieldName("object") ?? node.childForFieldName("operand") ?? node.childForFieldName("value") ?? node.childForFieldName("path") ?? node.childForFieldName("expression") ?? node.childForFieldName("argument") ?? node.childForFieldName("receiver") ?? node.childForFieldName("table");
if (obj && (obj.type === "crate" || obj.type === "super")) return obj.type;
if (obj?.type === "super" || obj?.type === "crate" && node.type === "scoped_identifier") return obj.type;
if (obj?.type === "composite_literal") {
const type = obj.childForFieldName("type");
const name3 = type ? readTypeName(type) : void 0;
return name3 && /^[A-Za-z_]\w*$/.test(name3) ? name3 : void 0;
}
const name2 = obj ? readName(obj) : void 0;
return name2 && /^[A-Za-z_]\w*$/.test(name2) ? name2 : void 0;
}
Expand Down Expand Up @@ -15543,8 +15548,38 @@ function createCallBinder(scan2, pairs, opts = {}) {
if (files) (rustModules ??= /* @__PURE__ */ new Map()).set(q, files);
}
inlineMods = f.symbols.filter((s) => s.kind === "mod" && s.endLine !== void 0 && s.endLine > s.line);
if (inlineMods.length) (rustModules ??= /* @__PURE__ */ new Map()).set(INLINE_SUPER, [f.rel]);
}
const modScope = (line2) => {
let best = 0;
for (const m of inlineMods ?? []) if (line2 > m.line && line2 <= m.endLine && m.line > best) best = m.line;
return best;
};
const baseOf = (cls) => f.relations?.find((r) => r.kind === "extends" && r.from === cls)?.to;
const classAround = (e) => {
if (e === void 0) return void 0;
if (e.parent !== void 0 && baseOf(e.parent) !== void 0) return e.parent;
let best;
for (const s of f.symbols) {
if (s.endLine === void 0 || s.line > e.line || e.line > s.endLine || baseOf(s.name) === void 0) continue;
if (!best || s.line > best.line) best = s;
}
return best?.name ?? e.parent;
};
let usedPaths;
const variantInScope = (d) => {
if (d.file !== f.rel || d.parent === void 0) return false;
if (!usedPaths) {
usedPaths = /* @__PURE__ */ new Set();
for (const r of f.refs) {
if (r.kind !== "import") continue;
const segs = r.spec.split("::");
usedPaths.add(segs[segs.length - 1]);
if (segs.length > 1) usedPaths.add(`${segs[segs.length - 2]}::${segs[segs.length - 1]}`);
}
}
if (PRELUDE_VARIANTS.has(d.name)) return usedPaths.has(`${d.parent}::${d.name}`);
return usedPaths.has(d.parent) || usedPaths.has(`${d.parent}::${d.name}`);
};
const corroborated = (name2, pool) => {
const out2 = scope.reached(exportedGroup(name2, family, pool), f, name2);
const priv = hiddenGroup(name2, family, pool);
Expand All @@ -15571,11 +15606,17 @@ function createCallBinder(scan2, pairs, opts = {}) {
const read = (c2, enclosing) => {
let receiver = c2.receiver;
if (receiver === void 0) return BARE;
if (receiver === "super" && inlineMods?.some((m) => c2.line > m.line && c2.line <= m.endLine)) receiver = INLINE_SUPER;
if (family === "rust" && receiver === "super") {
const block = modScope(c2.line);
if (block) {
receiver = `${INLINE_SUPER}${modScope(block)}`;
if (!rustModules?.has(receiver)) (rustModules ??= /* @__PURE__ */ new Map()).set(receiver, [f.rel]);
}
}
let r = byReceiver.get(receiver);
if (r) return r;
const self = (t) => reading("self", receiver, t, t);
if (!SELF_NAMES.has(receiver)) {
if (!SELF_NAMES.has(receiver) && !(receiver === "super" && family !== "rust")) {
if (rustModules?.has(receiver)) r = reading("module", receiver);
else if (aliases.modules.has(receiver)) r = reading("module", receiver);
else if (ownTypes.has(receiver)) r = self(receiver);
Expand All @@ -15602,6 +15643,11 @@ function createCallBinder(scan2, pairs, opts = {}) {
};
const readInScope = (receiver, e, self) => {
if (SELF_NAMES.has(receiver)) return self(e?.parent);
if (receiver === "super") {
const cls = classAround(e);
const base = cls !== void 0 ? baseOf(cls) : void 0;
return base !== void 0 && ownTypes.has(base) ? self(base) : reading("foreign", receiver, void 0, base);
}
if (family === "go" && goReceiverVar(e) === receiver) return self(e.parent);
const d = e?.signature ? declaredType(e.signature, receiver) : void 0;
if (d?.qualifier !== void 0 && !recall && aliases.modules.get(d.qualifier) === null) return OUTSIDE;
Expand All @@ -15613,13 +15659,26 @@ function createCallBinder(scan2, pairs, opts = {}) {
const resolve13 = (name2, how) => {
const { shape, receiver, selfType, typeHint } = how;
if (shape === "outside") return null;
const bareRust = family === "rust" && shape === "bare";
const scopeLine = receiver?.startsWith(INLINE_SUPER) ? Number(receiver.slice(INLINE_SUPER.length)) : void 0;
const reachable = (d) => !(bareRust && d.kind === "enum-member" && !variantInScope(d)) && !(scopeLine !== void 0 && (d.file !== f.rel || modScope(d.line) !== scopeLine));
let local;
if (recall) local = ownAny.get(name2);
else if (shape === "bare") local = shaped ? ownFree.get(name2) : ownAny.get(name2);
else if (shape === "self") {
local = selfType !== void 0 ? memberOf(selfType, name2) : void 0;
if (receiver === "super") {
for (let t = selfType, hops = 0; !local && t !== void 0 && hops < MAX_BASE_HOPS; hops++) {
t = baseOf(t);
if (t !== void 0 && ownTypes.has(t)) local = memberOf(t, name2);
else break;
}
}
if (!local && receiver !== void 0 && SELF_NAMES.has(receiver)) local = ownMember.get(name2);
}
if (local && !reachable(local)) {
local = f.symbols.find((s) => s.name === name2 && !REFERENCE_KINDS3.has(s.kind) && !NOT_CALLABLE.has(s.kind) && reachable(s));
}
if (local) return only && !only.has(local.name) ? null : { hit: { def: local, corroborated: true }, local: true };
let restrict;
let callee = name2;
Expand All @@ -15635,24 +15694,27 @@ function createCallBinder(scan2, pairs, opts = {}) {
if (restrict === null) {
if (!recall) return null;
} else {
const hits = scope.within(exportedGroup(callee, family, pool), restrict, callee);
let hits = scope.within(exportedGroup(callee, family, pool), restrict, callee);
if (hiddenReach === "import" || viaPath) {
for (const d of scope.within(hiddenGroup(callee, family, pool), restrict, callee)) if (!hits.includes(d)) hits.push(d);
}
if (family === "rust") hits = hits.filter(reachable);
const chosen2 = pickCandidate(f.rel, hits);
if (chosen2) return { hit: { def: chosen2, corroborated: true }, local: false };
if (hits.length) return null;
if (!recall && STRICT.has(family)) return null;
}
}
const stated = preferParent(corroborated(callee, pool), typeHint, receiver);
const reached = corroborated(callee, pool);
const stated = preferParent(family === "rust" ? reached.filter(reachable) : reached, typeHint, receiver);
if (stated.length) {
const chosen2 = pickCandidate(f.rel, stated);
return chosen2 ? { hit: { def: chosen2, corroborated: true }, local: false } : null;
}
const group = exportedGroup(callee, family, recall ? "any" : guessPool);
if (!group) return null;
const cands = defsOutside(group, f.rel);
const outside = defsOutside(group, f.rel);
const cands = family === "rust" ? outside.filter(reachable) : outside;
if (!cands.length) return null;
let guesses = [...cands];
if (recall) {
Expand All @@ -15676,7 +15738,7 @@ function createCallBinder(scan2, pairs, opts = {}) {
};
return { forFile };
}
var REFERENCE_KINDS3, STRICT, SHAPED, PACKAGE_DIR, PRIVATE_REACH, NOT_CALLABLE, INLINE_SUPER, SELF_NAMES, FUNCTION_KINDS2, MAX_HOPS, NO_ALIASES, dirOf3, isGoTest, declaredRe, aliasMemo, newTables;
var REFERENCE_KINDS3, STRICT, SHAPED, PACKAGE_DIR, PRIVATE_REACH, NOT_CALLABLE, INLINE_SUPER, MAX_BASE_HOPS, PRELUDE_VARIANTS, SELF_NAMES, FUNCTION_KINDS2, MAX_HOPS, NO_ALIASES, dirOf3, isGoTest, declaredRe, aliasMemo, newTables;
var init_bind = __esm({
"src/bind.ts"() {
"use strict";
Expand All @@ -15693,7 +15755,9 @@ var init_bind = __esm({
PACKAGE_DIR = /* @__PURE__ */ new Set(["go", "java"]);
PRIVATE_REACH = { go: "package", java: "package", python: "import", rust: "path" };
NOT_CALLABLE = /* @__PURE__ */ new Set(["mod", "module", "package", "namespace"]);
INLINE_SUPER = "super\0inline";
INLINE_SUPER = "super\0inline\0";
MAX_BASE_HOPS = 8;
PRELUDE_VARIANTS = /* @__PURE__ */ new Set(["Ok", "Err", "Some", "None"]);
SELF_NAMES = /* @__PURE__ */ new Set(["self", "cls", "this", "Self"]);
FUNCTION_KINDS2 = /* @__PURE__ */ new Set(["function", "method", "def", "constructor", "operator"]);
MAX_HOPS = 3;
Expand Down
16 changes: 13 additions & 3 deletions src/ast/node.ts
Original file line number Diff line number Diff line change
Expand Up @@ -181,9 +181,19 @@ export function readReceiver(node: TSNode | null): string | undefined {
node.childForFieldName("argument") ??
node.childForFieldName("receiver") ??
node.childForFieldName("table");
// Rust's `crate::f()` and `super::f()` name a module by keyword, a leaf
// readName does not take for a name; the binder resolves both to a file.
if (obj && (obj.type === "crate" || obj.type === "super")) return obj.type;
// `super` and Rust's `crate` are keywords, leaves readName does not take for
// a name. Rust's `crate::f()`/`super::f()` name a module the binder resolves
// to a file; JS/TS/Java's `super.f()` the enclosing class's base, which the
// binder reads off the file's `extends` relations.
if (obj?.type === "super" || (obj?.type === "crate" && node.type === "scoped_identifier")) return obj.type;
// A method called on a composite literal (Go's `addrs.Check{…}.Absolute()`)
// is called on the literal's type; the literal's last child is its body,
// whose last identifier is any field value at all.
if (obj?.type === "composite_literal") {
const type = obj.childForFieldName("type");
const name = type ? readTypeName(type) : undefined;
return name && /^[A-Za-z_]\w*$/.test(name) ? name : undefined;
}
const name = obj ? readName(obj) : undefined;
return name && /^[A-Za-z_]\w*$/.test(name) ? name : undefined;
}
Expand Down
Loading
Loading