diff --git a/CHANGELOG.md b/CHANGELOG.md index 143cf3314e..150b32e2d9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -646,6 +646,70 @@ and adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). - In Go, a call through a parameter or local variable named like a standard-library package, such as `context`, `log`, `trace`, `printer` or `token`, now links to the method it calls. Before, every call written `context.…` or `printer.…` was taken for a call into the standard library and linked to nothing: gin's `context.AbortWithError(…)` inside `func(context *Context)`, harbor's `context.IsAuthenticated()` after `context := NewSecurityContext(…)` and `log.Errorf(…)` after `log := log.G(ctx)`, etcd's `printer.DBHashKV(…)` and `trace.Step(…)`. The variable's declaration decides the method: the type it is declared as, or the package of the project function its value comes from. A variable holding a value from outside your project, like `scanner := bufio.NewScanner(r)` or `url, err := url.Parse(raw)`, still links to nothing, and one whose type can't be told links only to a method no other type in the project has, never to one picked because it matches the variable's name. Re-index Go projects after upgrading. +- `codegraph sync` and the file watcher now also link the imports of an added or restored JavaScript or TypeScript file whose name hundreds of other imports share, like a project's own `utils.ts` among `jotai/utils` and `@scope/pkg/utils` imports, or `assert.ts` in a project full of `import * as assert from 'assert'`. Before, a name that common was skipped as noise no single file could answer, so in a large project the file's own `./utils` and `~/settings/utils` imports stayed unlinked until the importing files changed or the project was re-indexed. + +- `codegraph sync` and the file watcher now link an import of a folder two or more levels up, like `import { Excalidraw } from "../.."` in excalidraw's tests, to that folder's `index` file when the file is added after the importing file was indexed, or comes back after being deleted. Before, only an import of the file's own folder or the one above (`.`, `..`) was relinked; one reaching further up stayed unlinked until the importing file changed or the project was re-indexed. + +- `codegraph sync` and the file watcher now also link a call on a variable or parameter declared with a class a file imports, like `cache.get(key)` after `const cache = new LRUCache(10)` or in a function that takes `cache: LRUCache`, when the class's module gets the class in a later edit, is added after the file was indexed, or comes back after being deleted, in JavaScript and TypeScript. Before, such a call stayed unlinked until its own file changed or the project was re-indexed whenever its method's name, like `get`, was too common for sync to look up. Re-index after upgrading to pick up links an earlier version missed. + +- In TypeScript and JavaScript, a call of an array method, like `items.find(…)` or `items.push(…)`, on a variable or parameter annotated as an array of a class (`items: Item[]`) no longer links to the class's method of the same name. Before, the annotation was read as the class itself: in vscode, `distinctElements.find(…)` on an `ExplorerItem[]` linked to `ExplorerItem.find`, and `ranges.map(…)` on an `OffsetRange[]` to `OffsetRange.map`, so those methods showed callers they don't have. A call on an element that shares the array's name, as in `d.forEach(d => d.dispose())`, still links to the class. Re-index TypeScript and JavaScript projects after upgrading. + +- In TypeScript and JavaScript, a call on a variable or parameter annotated as one of a type's properties, like `editor.executeEdits(…)` with `editor: IChatWidget['inputEditor']`, now links to the method of the type that property is declared with, or to nothing when that type has no such method. That type is the class the file declaring the property imports or declares, and the indexed type itself the one the call's file imports, when several classes share a name. Before, the annotation was read as the type it indexes, so in vscode `visibility.isVisible(…)` with `visibility: ISessionChatPillVisibilityService['pullRequests']` linked to the service's own `isVisible`, and a call that type didn't have was matched by the method's name alone: `chatModel.onDidChange(…)` with `chatModel: IInlineChatSession['chatModel']` reached a folding model's `onDidChange`. A property declared as an array follows the same rules as an array annotation, and one whose type isn't written there, like a getter, is read as the type it indexes, as before. Re-index TypeScript and JavaScript projects after upgrading. + +- In a pnpm, npm, Yarn or Bun workspace whose globs reach packages more than one folder down, like pnpm's `packages/**/*` or npm's `libs/**/*`, those packages now count as part of the project, so an import of one is no longer taken for an outside package's, and `codegraph sync` and the file watcher relink the calls through it when its files change. A workspace glob can now also name packages by part of a folder name (`packages/plugin-*`) or by a folder below the wildcard (`apps/*/web`), and a negated glob like `!**/example` leaves packages out, as the package managers do. Before, only the folders directly under a glob's first wildcard were read, and a negated glob was ignored. Re-index after upgrading. + +- In this fork, a workspace glob that climbs out of the project (`../**/*`) or names an absolute path matches nothing, so indexing never reads other folders' manifests. + +- In a project that uses Vue, an import written through an `@/` or `~/` alias, like `import { Button } from '@/components'`, now links the file it imports, as it does in any other project, so `codegraph sync` and the file watcher update the files that import a module when that module, or a barrel they import through, is added or deleted. Before, Vue support linked such an import to the first declaration or the component in that file, which sync does not follow, and an import through a `tsconfig` alias that starts like one of Nuxt's built-in modules, like `#app/where`, linked the importing file to itself. Re-index Vue projects after upgrading. + +- In this fork, an `@/` or `~/` import in a Vue project links the file it names through the import resolver, so the edge points at the imported file. Before the merge a framework rule linked a `.vue` import to the component node in that file; a router's `() => import('@/views/Home.vue')` and a component's import of another component now point at the file, with the same confidence. + +- In Go, a struct now links to the types its fields are declared with, like etcd's `PutResponse` holding a `*ResponseHeader` or gin's `Context` holding a `HandlersChain`, so impact on `ResponseHeader` or `HandlersChain` reaches every struct that holds one and the code that uses those structs, and `codegraph_node` lists a struct's field types. Before, a struct linked only to the types it embeds. A field written through another package, like `*pb.ResponseHeader`, links to that package's type, one from outside your project, like `context.Context`, links to nothing, the types an embedded generic is filled in with, like the `Pod` in client-go's `listers.ResourceIndexer[*v1.Pod]`, link too, and a struct that holds itself, like a list node's `next *node`, doesn't link to itself. `codegraph_explore` still answers a question about a flow with the code that runs it, not with the structs that merely hold one of its types. Re-index Go projects after upgrading. + +- In Go, an unexported name used in another file of its package, like prometheus's `memSeries` in `tsdb/head_append.go`, now links to that package's own declaration when a package nested inside it, like `tsdb/agent`, declares the same name. Before, such a parameter, result, struct field, composite literal or call linked to nothing. A call or a function value that the surrounding function binds itself, like a test's `init := func(…)` followed by `init(t)`, or a local `volumeSpec` variable passed on, no longer links to the package's declaration of that name. Re-index Go projects after upgrading. + +- In Go, a method an interface declares, like etcd's `KV.Put(ctx context.Context, key, val string, opts ...OpOption) (*PutResponse, error)`, now links to the types its parameters and results name, so impact on `PutResponse` or `OpOption` reaches the interface method and every caller that goes through the interface. Before, an interface's methods linked to no types at all. Re-index Go projects after upgrading. + +- In Go, a package imported under an explicit name, like `v3 "go.etcd.io/etcd/client/v3"`, now owns that name even when another import's path ends in it, like `"github.com/cheggaaa/pb/v3"` (package `pb`) in etcd's benchmark tool. Before, whichever of the two came first took every `v3.` name, so `v3.Client` and `v3.Op` could link to nothing. Re-index Go projects after upgrading. + +- In Go, a call of a method name that nearly every type has, like `err.Error()`, `id.String()`, `ctx.Err()` or `mu.Lock()`, now links to that method of the type its variable is declared as, and to nothing when that type is built into Go, like `error` or `string`, or comes from outside your project, like `context.Context`, `sync.Mutex` or `testing.TB`. Before, when the variable's type wasn't worked out, such a call was matched by a word its name shares with a type's, so kubernetes' `err.Error()` calls linked to an unrelated `notRegisteredErr` type and etcd's `leaderID.String()` to `MoveLeaderRequest`. A call on a variable whose type still can't be told now links only to a type the variable is named after, like `id` for an `ID`. Re-index Go projects after upgrading. + +- In Go, a method call on a variable or constant declared at the top level of a package, like `lg.Panic(…)` after `var lg *zap.Logger` or `RoleEndpoint.String()` after `RoleEndpoint Role = "endpoints"`, now links to that method of the type it is declared with, from any file of the package, and to nothing when that type, or the value it is set to, comes from outside your project. Before, nothing read such a declaration, so the call was matched by its method's name alone and could link to an unrelated type's method, like a project logger's `Panic` or another package's `Role`. Re-index Go projects after upgrading. + +- In this fork, the two Go changes above for `err.Error()`-style calls and for package-level variables and constants run in the native resolver, which reads a variable's declared type from the same binding rows it uses for locals. A call whose receiver's type it read links at confidence 0.9 where upstream's text guess gives 0.65 to 0.8, such as `id.String()` on the range variable of a `[]types.ID` or `Exec` on a `Query` result. And when the type it read is a project type that declares no such method, as with a variable declared as a `Codec` interface whose `Encode` the node doesn't carry, the call links to nothing, where upstream falls back to a method of that name on some other type. + +- React Router routes are now indexed when the router gets its table from a function through a variable, as in Medusa's admin dashboard, which writes `const routes = getRouteMap({ … })` and then `createBrowserRouter(routes)`. The same goes for `export const routes = buildRoutes()` or `export default buildRoutes()` imported into `useRoutes(routes)`, and for `const routes = await loadRoutes()`. Before, such a variable was read only when it held the table itself, so these apps had no routes: their pages had no route leading to them, and their `navigate('/orders/…')` calls and `` links led nowhere. Routes the function is handed by its caller, like the plugin routes Medusa spreads in, are still not read, and when two functions in one file each keep a `routes` variable, the router reads its own and never the other's, which may be a menu. Re-index React projects after upgrading. + +- A React Router route written as `element: ` or `Component: Outlet`, or whose `lazy` loader hands back `{ Component: Outlet }`, now counts as rendering nothing of its own, as a route with no element does and as `}>` already did. Before, `Outlet` was taken for the route's page and for the layout of the routes inside it, which linked nothing, and a loader returning `{ Component: Outlet }` made the module it loads for its `loader` the layout of the routes inside: in Medusa's admin dashboard, a product's detail page was drawn around its variants' pages. Such a route is still a route at its own address, inside the layouts around it, and a page inside it at the same address still takes the address over. Re-index React projects after upgrading. + +- In JavaScript and TypeScript, a function the file imports from a package and passes along as a value, like react-router's `Link` in `styled(Link)`, lodash's `noop` in `createContext({ onClose: noop })` or chart.js's `Legend` in `Chart.register(Legend)`, no longer links to a project function that only shares its name. Before, whenever the project had exactly one function of that name, every such value linked to it: outline's breadcrumbs, menus and document lists showed up among the callers of an email template's `Link`, and a test's own `noop` stub in cord-field among the code the app's contexts use, so `codegraph callers`, impact and `codegraph_explore` followed references that never happen. A function the file declares itself, including one that hides the import inside a function, and one imported from a file of your project link as before. Re-index JavaScript and TypeScript projects after upgrading. + +- In TypeScript and JavaScript, a call through a field the calling class inherits, like `this._store.add(…)` in a class whose base class declares `_store`, now links to the method of the field's class, with the base class found the way the subclass's file imports it, under its own name, an alias or a re-export. Before, such a call linked only when some other class with the calling class's name happened to declare the field, which could be another app's class: that last resort now needs a type the calling file imports or declares. A call on a field or variable whose type comes from a package outside your project, like `TelemetryReporter` from `@vscode/extension-telemetry`, no longer links to a project class that only shares the type's name, unless a file in your project declares that package (`declare module '…'`). Re-index TypeScript and JavaScript projects after upgrading. + +- In TypeScript and JavaScript, a call on a variable, parameter or field whose class the file imports, like `store.add(…)` with `store: DisposableStore`, now links to the method of the class that import names when other classes in the project share its name, such as a vendored copy, a test mock or another app's class. Before, it linked to whichever of them was indexed first, or to the one in the nearest folder: in vscode, calls on classes imported from vscode's own `vs/base` and `vs/platform` reached the copies the Copilot extension vendors or its test fixtures, in bitwarden the desktop app's `initService.init()` reached the browser extension's `InitService`, and in react-native `Keyboard` and `WebSocket` reached the Jest mock of `NativeEventEmitter`. A call whose first match was a test file's class, which then linked to nothing, now reaches the imported class too. The import is followed through re-exports, `import type`, namespace imports like `new async.Delayer()` and `require(…)`. Re-index TypeScript and JavaScript projects after upgrading. + +- In TypeScript and JavaScript, a call on a value another file exports, like `store.add(…)` after `import { store } from './state'` with `export const store = new Store()` there, now links to the method of the class that file imports or declares when other classes in the project share its name, in Vue, Svelte and Astro components too. Before, it linked to whichever of them was indexed first: in vscode, calls on `FileAccess`, `extUri`, `errorHandler` and `MenuRegistry` reached the copies the Copilot extension vendors or one of its test fixtures, and in folo the mobile app's `settingSyncQueue.init()` reached the desktop app's `SettingSyncQueue`. Re-index TypeScript and JavaScript projects after upgrading. + +- In TypeScript, a call through a field that a wrapper sets up, like `this._onDidChange.fire()` after `private readonly _onDidChange = this._register(new Emitter())` or `= this._store.add(new Emitter())`, now links to the method of the class handed to the wrapper, also in a class that inherits the field. Before, such a field had no type, so its calls linked nowhere, and that is one of the most common ways vscode declares its event emitters and disposables. A wrapper counts only when its own declaration hands back what it is given, like `_register(o: T): T`, so a field set from a wrapper that returns something else, or from a member of what it returns (`.event`), is never taken for the class. A call through an inherited field is also found now when the field is declared further up the class hierarchy than before. Re-index TypeScript projects after upgrading. + +- In TypeScript and JavaScript, a class whose declaration constrains a type parameter, like `class EditorPane extends Composite`, is now read as extending the class after its type parameters. Before, the constraint's type was taken for its base class, so fields, wrapped event emitters and static methods inherited through such a class were missed or found on the wrong class. Class declarations that span several lines or sit below a decorator are read too. Re-index TypeScript and JavaScript projects after upgrading. + +- In TypeScript, an abstract method like `abstract send(path: string): Promise;` is now indexed as a method of its class. Before, it was missing, so a call through a value typed as an abstract class, as Angular apps register many of their services, linked to whichever class elsewhere had a method of that name, often another app's, and the types written in an abstract method's parameters and return type were read as properties of the class. Such a call now links to the abstract method, which also leads to the classes that implement it. Re-index TypeScript projects after upgrading. + +- In TypeScript and JavaScript, a call on a field or variable whose class the file imports now goes through that class and the classes and interfaces it extends, each found the way its own file names it, before any other class of the same name. Before, when the class didn't declare the method itself, the call went to whichever same-named class had it: in vscode, `this._storage.dispose()` reached a test fixture's `Disposable`, and calls on a library's services in bitwarden reached the browser app's copies. A call like `this.logService.trace()`, whose `ILogService` gets `trace` from the `ILogger` it extends, linked nowhere and now links to `ILogger`'s method. A field's call whose class and everything it extends are known but lack the method, as when a package's base class provides it, now links to nothing rather than to an unrelated class. Re-index TypeScript and JavaScript projects after upgrading. + +- In this fork, the TypeScript and JavaScript changes above run in the native resolver. A field whose type the file imports from a package no `package.json` lists, such as a project with no manifest at all, still links to no project class, as it did before; upstream matches the method on a same-named project class there. A local's `inject(X)` or `createInstance(X)` is typed without checking that the file imports Angular's `inject`, as upstream does; a field's `inject(X)` requires that import. A local typed as `External.Store` from a namespace import of a package no project file declares links to no project class named `Store`. A method arrays don't have, called on a local annotated `Item[]`, reaches `Item` only inside a callback whose parameter takes the local's name (`d.forEach(d => d.dispose())`); upstream links it anywhere. + +- In TypeScript, a call on a value of an interface that extends one also declared as a constant, like vscode's `ITerminalLogService extends ILogService` where `ILogService` is its dependency-injection decorator too, now links to the method the extended interface declares, such as `ILogger`'s `trace`. Before, the constant was taken for the extended type, so the call linked nowhere. Re-index TypeScript projects after upgrading. + +- In TypeScript, a field or variable set from a dependency-injection call now has the class that call is given, so calls through it link to that class's methods: Angular's `private readonly dataService = inject(DataService)` or `inject(DIALOG_DATA)`, and vscode's `this.instantiationService.createInstance(Widget, …)`, also inside a wrapper like `this._register(…)`. Before, such a value had no type, so calls through it, among the most common in Angular apps, linked nowhere or to a same-named method of another class. Only Angular's `inject` counts, and only a `createInstance` the project declares to return an instance of the class it is given. A call on a value whose type the file imports under another name, like `import { OrganizationApiServiceAbstraction as OrganizationApiService }`, now also reaches the imported class rather than a class with the local name. Re-index TypeScript projects after upgrading. + +- In JavaScript and TypeScript, a call to a method whose name contains a `$` now links to that method through its receiver's type, like any other method call: RxJS-style `this.organizationService.organizations$(userId)`, or vscode's `this._proxy.$acceptModelChanged(…)` on the interface its RPC proxy is declared with. Before, such a call linked nothing, however well its receiver was typed. Re-index JavaScript and TypeScript projects after upgrading. + +- In JavaScript and TypeScript, an import written from a jsconfig or tsconfig `baseUrl`, like `import MainLayout from 'layout/MainLayout'` under `"baseUrl": "src"`, or through a catch-all `"paths": { "*": ["./src/*"] }`, now links to the file it names, read with the config of the app the importing file belongs to, and so does an import of a single name like `'config'` or `'themes'`. Create React App and Vite admin templates such as Berry, Mantis and MatX write nearly every import this way. Before, each one was taken for an npm package, so it linked nothing, its names were matched by name alone, which could reach a same-named component in another app of the same repository, and a React Router route whose page loads through `lazy(() => import('views/dashboard/Default'))` pointed at that loader instead of the page and its layout. A package the app's `package.json` declares, or a Node built-in, never links to a project module of the same name, only to type declarations the project keeps for it, and only a file the index holds counts, never a folder or something in `node_modules`. `codegraph sync` and the file watcher link such an import too when the file it names is added later or gains what it imports. Re-index JavaScript and TypeScript projects after upgrading. + +- `codegraph sync` and the file watcher now relink an import that reaches a module through a barrel file passing it on under another name, like `import { MatxLoading } from './components'` when `components/index.js` says `export { default as MatxLoading } from './MatxLoading'`, once an edit gives that module what is imported. Before, the import and every call through it stayed unlinked, or stayed on something else in the project with the same name, until the importing file itself changed or the project was indexed again. + #### MCP / indexing - Full indexes of large projects no longer sometimes run two to three times slower than usual. A timing clash between two background database maintenance steps could switch reference resolution from several threads to one partway through. diff --git a/README.md b/README.md index 48d2bd656e..ae42499e7c 100644 --- a/README.md +++ b/README.md @@ -52,7 +52,7 @@ Follow [@getcodegraph](https://x.com/getcodegraph) on X for updates. ## About this fork -This is **bompus/codegraph**, a fork of [colbymchenry/codegraph](https://github.com/colbymchenry/codegraph). Its default branch, `fork/consolidated`, contains upstream `main` through [`baf19067`](https://github.com/colbymchenry/codegraph/commit/baf19067) (after v1.6.2) plus the fork's own work, and it takes upstream changes as they land. Changes that suit upstream are also offered there as pull requests. +This is **bompus/codegraph**, a fork of [colbymchenry/codegraph](https://github.com/colbymchenry/codegraph). Its default branch, `fork/consolidated`, contains upstream `main` through [`b8f81e2c`](https://github.com/colbymchenry/codegraph/commit/b8f81e2c) (after v1.6.2) plus the fork's own work, and it takes upstream changes as they land. Changes that suit upstream are also offered there as pull requests. The fork publishes no releases. The install scripts, npm package, badges and `codegraph upgrade` further down this page install **upstream's** releases. To run the fork, build it from source (below). @@ -159,6 +159,8 @@ Call resolution the fork adds: - C++ object creation sees a header under a test directory, such as nlohmann/json's old-release copy in `tests/abi/`, only from inside that directory's tree or through an `#include`; upstream sees every header. A class declared in an included `.cc` file is the includer's too, and of two headers declaring one class the creation takes the one in its include closure. - C# namespace `using` directives and `using` aliases apply only inside their enclosing namespace, not to sibling namespaces in the same file (`using static` is still file-wide, as upstream). - A Java field declared with a qualified type (`outside.Repository`) keeps its qualifier, so calls through it never resolve to an unrelated project class with the same simple name. +- A Go call on a variable or constant whose declared type is a project type with no method of that name links to nothing; upstream falls back to a method of that name on some other type. A call whose receiver type the bindings read links at confidence 0.9, where upstream's text guess gives 0.65 to 0.8. +- A TypeScript or JavaScript field whose type is imported from a package that no `package.json` lists (a project with no manifest at all) links to no project class of that name; upstream matches it to a same-named project class. - Python `super().method()` resolves along the class's C3 method resolution order, starting after the class itself. Upstream resolves it like `self.method()` and drops the link only when it lands on the calling method. - Python receivers reassigned on later lines use the latest preceding value in their lexical scope. An unknown replacement leaves the member call unresolved. Calls and method values through a captured receiver stay unlinked when a later replacement makes its invocation-time value uncertain. Same-line replacements also stay unlinked when statement order cannot establish a reliable receiver type. Unaliased imports that add submodules to the same package preserve that package receiver. - A `require` call creates no file dependency when a local binding shadows `require`. diff --git a/__tests__/explore-cross-call-dedup.test.ts b/__tests__/explore-cross-call-dedup.test.ts index ce208dc95f..265f9c5500 100644 --- a/__tests__/explore-cross-call-dedup.test.ts +++ b/__tests__/explore-cross-call-dedup.test.ts @@ -264,7 +264,28 @@ describe('a second call against a real index', () => { // Every file whose source the second call withheld carries a pointer, and // the pointer names it. expect(second).toContain(POINTER); - for (const [file, lines] of before) { + // Fork: a run shorter than EXPLORE_DEDUP.MIN_COVERED_LINES is re-served by + // design (a pointer for it would cost more than the lines). The fork's Go + // struct-field references leave a 7-line orphan window of + // `payslipstore.Store.Timesheet` in the first call, so only runs at least + // that long count as source the agent holds. + const heldRuns = (lines: Set): Set => { + const sorted = [...lines].sort((a, b) => a - b); + const held = new Set(); + let run: number[] = []; + const flush = () => { + if (run.length >= EXPLORE_DEDUP.MIN_COVERED_LINES) run.forEach((n) => held.add(n)); + run = []; + }; + for (const n of sorted) { + if (run.length > 0 && n !== run[run.length - 1]! + 1) flush(); + run.push(n); + } + flush(); + return held; + }; + for (const [file, sent] of before) { + const lines = heldRuns(sent); const repeated = [...(after.get(file) ?? [])].filter((n) => lines.has(n)); if (repeated.length === 0) continue; // The only sanctioned repeat is the anti-abandonment restore, which fires diff --git a/__tests__/fixtures/golden/payroll-go.dump b/__tests__/fixtures/golden/payroll-go.dump index 150ef22027..8caf3109d7 100644 --- a/__tests__/fixtures/golden/payroll-go.dump +++ b/__tests__/fixtures/golden/payroll-go.dump @@ -312,7 +312,7 @@ {"id":"variable:6b7bef84822056845bdabeb41a821f0a","kind":"variable","name":"ErrCycleClosed","qualified_name":"ErrCycleClosed","file_path":"internal/usecase/payroll/cycle.go","language":"go","start_line":16,"end_line":16,"start_column":4,"end_column":58,"docstring":"ErrCycleClosed is returned when a cycle has already been finalized.","signature":"= errors.New(\"payroll cycle is closed\")","visibility":null,"is_exported":1,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":null} {"id":"variable:9c3a0c9681a69504be5d3af6ddb5378c","kind":"variable","name":"file_payroll_v1_payroll_proto_goTypes","qualified_name":"file_payroll_v1_payroll_proto_goTypes","file_path":"internal/gen/payrollpb/payroll.pb.go","language":"go","start_line":132,"end_line":137,"start_column":4,"end_column":1,"docstring":null,"signature":"= []any{\n\t(*RunPayrollCycleRequest)(nil),\n\t(*RunPayrollCycleResponse)(nil),\n\t(*Payslip)(nil),\n\t(*Payro...","visibility":null,"is_exported":0,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":null} {"id":"variable:baa4aee814b380ae99f1b1829407b106","kind":"variable","name":"ErrNoEmployees","qualified_name":"ErrNoEmployees","file_path":"internal/usecase/payroll/cycle.go","language":"go","start_line":19,"end_line":19,"start_column":4,"end_column":72,"docstring":"ErrNoEmployees is returned when a cycle resolves to an empty roster.","signature":"= errors.New(\"payroll cycle has no active employees\")","visibility":null,"is_exported":1,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":null} -== edges (626) +== edges (657) {"source":"file:69f63e0581b8138f256b63d2aac60e8a","target":"module:1be454da0953954aef45c525ee8f8b51","kind":"contains","metadata":null,"line":null,"col":null,"provenance":"heuristic"} {"source":"file:cmd/payrolld/main.go","target":"function:90eb51f51a3d9a397d4a53f26f2019aa","kind":"contains","metadata":null,"line":null,"col":null,"provenance":null} {"source":"file:cmd/payrolld/main.go","target":"import:0a9ee69fa4c64208200c3bebcbbf0b75","kind":"contains","metadata":null,"line":null,"col":null,"provenance":null} @@ -684,6 +684,8 @@ {"source":"method:12243ae31857f370c8d5ea75c91b702f","target":"method:59c25996edd43745355454c918ca737d","kind":"calls","metadata":"{\"confidence\":0.85,\"resolvedBy\":\"instance-method\",\"refName\":\"s.store.SaveCycle\"}","line":226,"col":8,"provenance":null} {"source":"method:12243ae31857f370c8d5ea75c91b702f","target":"method:d14d0b12675b711f5f90a392b7b297aa","kind":"calls","metadata":"{\"confidence\":0.9,\"resolvedBy\":\"instance-method\",\"refName\":\"s.loadCycle\"}","line":216,"col":15,"provenance":null} {"source":"method:16a61da8990e9e8548eaba76a0d96d9f","target":"method:64fce125a13481bd9c53202505ebb26f","kind":"calls","metadata":"{\"synthesizedBy\":\"interface-impl\",\"via\":\"GetPayrollCycle\",\"registeredAt\":\"internal/gen/payrollpb/payroll_grpc.pb.go:79\"}","line":67,"col":null,"provenance":"heuristic"} +{"source":"method:16a61da8990e9e8548eaba76a0d96d9f","target":"struct:3d4fd5cb833f90205ff1d82443698813","kind":"references","metadata":"{\"confidence\":0.9,\"resolvedBy\":\"exact-match\",\"refName\":\"PayrollCycle\"}","line":67,"col":61,"provenance":null} +{"source":"method:16a61da8990e9e8548eaba76a0d96d9f","target":"struct:4325013490f7f7a77604146f5e38c292","kind":"references","metadata":"{\"confidence\":0.9,\"resolvedBy\":\"exact-match\",\"refName\":\"RunPayrollCycleRequest\"}","line":67,"col":35,"provenance":null} {"source":"method:18a9696cad4179d634834650c0684f0c","target":"struct:4325013490f7f7a77604146f5e38c292","kind":"references","metadata":"{\"confidence\":0.9,\"resolvedBy\":\"exact-match\",\"refName\":\"RunPayrollCycleRequest\"}","line":37,"col":72,"provenance":null} {"source":"method:18a9696cad4179d634834650c0684f0c","target":"struct:e66f442bcf28c3bd0a3f42fbacb69b2a","kind":"references","metadata":"{\"confidence\":0.9,\"resolvedBy\":\"exact-match\",\"refName\":\"RunPayrollCycleResponse\"}","line":37,"col":123,"provenance":null} {"source":"method:24e3292f2546abebcb9d371572f38e20","target":"struct:f1c05936f2b11591d1f90efa9d981fa7","kind":"references","metadata":"{\"confidence\":0.9,\"resolvedBy\":\"import\",\"refName\":\"Payslip\"}","line":50,"col":76,"provenance":null} @@ -716,8 +718,12 @@ {"source":"method:41899a297d23af6d3d2da3506b936eec","target":"struct:f1c05936f2b11591d1f90efa9d981fa7","kind":"references","metadata":"{\"confidence\":0.9,\"resolvedBy\":\"import\",\"refName\":\"Payslip\"}","line":22,"col":11,"provenance":null} {"source":"method:4275e437d50514e430b25f9c11363ddf","target":"method:64fce125a13481bd9c53202505ebb26f","kind":"calls","metadata":"{\"synthesizedBy\":\"interface-impl\",\"via\":\"GetPayrollCycle\",\"registeredAt\":\"internal/gen/payrollpb/payroll_grpc.pb.go:79\"}","line":24,"col":null,"provenance":"heuristic"} {"source":"method:4275e437d50514e430b25f9c11363ddf","target":"method:e0490e3e69744ec0d57d332d3bda8c60","kind":"calls","metadata":"{\"synthesizedBy\":\"interface-impl\",\"via\":\"GetPayrollCycle\",\"registeredAt\":\"internal/gen/payrollpb/payroll_grpc.pb.go:46\"}","line":24,"col":null,"provenance":"heuristic"} +{"source":"method:4275e437d50514e430b25f9c11363ddf","target":"struct:3d4fd5cb833f90205ff1d82443698813","kind":"references","metadata":"{\"confidence\":0.9,\"resolvedBy\":\"exact-match\",\"refName\":\"PayrollCycle\"}","line":24,"col":93,"provenance":null} +{"source":"method:4275e437d50514e430b25f9c11363ddf","target":"struct:4325013490f7f7a77604146f5e38c292","kind":"references","metadata":"{\"confidence\":0.9,\"resolvedBy\":\"exact-match\",\"refName\":\"RunPayrollCycleRequest\"}","line":24,"col":42,"provenance":null} {"source":"method:4a3dff65c0d488ecc09cf9edabe95d42","target":"struct:62563918fc7ed271ca7e2c7b11f2c17a","kind":"references","metadata":"{\"confidence\":0.9,\"resolvedBy\":\"import\",\"refName\":\"Employee\"}","line":119,"col":37,"provenance":null} {"source":"method:4df364d0c37da3d10e39207b87a94ca8","target":"method:b90cd7088a55c9068e12a8120b256e13","kind":"calls","metadata":"{\"synthesizedBy\":\"interface-impl\",\"via\":\"RunPayrollCycle\",\"registeredAt\":\"internal/gen/payrollpb/payroll_grpc.pb.go:75\"}","line":66,"col":null,"provenance":"heuristic"} +{"source":"method:4df364d0c37da3d10e39207b87a94ca8","target":"struct:4325013490f7f7a77604146f5e38c292","kind":"references","metadata":"{\"confidence\":0.9,\"resolvedBy\":\"exact-match\",\"refName\":\"RunPayrollCycleRequest\"}","line":66,"col":35,"provenance":null} +{"source":"method:4df364d0c37da3d10e39207b87a94ca8","target":"struct:e66f442bcf28c3bd0a3f42fbacb69b2a","kind":"references","metadata":"{\"confidence\":0.9,\"resolvedBy\":\"exact-match\",\"refName\":\"RunPayrollCycleResponse\"}","line":66,"col":61,"provenance":null} {"source":"method:4f0ac2154c360ad1c55284c03d1f0c73","target":"struct:13bfc2acbe1de6557e9a28c0be484ffa","kind":"references","metadata":"{\"framework\":\"go\",\"confidence\":0.8,\"resolvedBy\":\"framework\",\"refName\":\"Store\"}","line":85,"col":49,"provenance":null} {"source":"method:4f57884a5e57e13884848a959e466e9d","target":"function:63f3bd99966467470cbabcb097ad36dd","kind":"calls","metadata":"{\"confidence\":0.7,\"resolvedBy\":\"exact-match\",\"refName\":\"ListPayslipsByCycle\"}","line":66,"col":8,"provenance":null} {"source":"method:4f57884a5e57e13884848a959e466e9d","target":"struct:eed7116b6261c410c79b06f6b3a3aebe","kind":"references","metadata":"{\"confidence\":0.9,\"resolvedBy\":\"exact-match\",\"refName\":\"PayslipRow\"}","line":65,"col":76,"provenance":null} @@ -761,6 +767,8 @@ {"source":"method:8baae5c5fb59db7a88c19bb295635d18","target":"method:abcc0b4bca6145184f692d4019641c7f","kind":"calls","metadata":"{\"confidence\":0.85,\"resolvedBy\":\"instance-method\",\"refName\":\"h.svc.Cycle\"}","line":71,"col":15,"provenance":null} {"source":"method:8c66da74e1212eca1d1b1483bbfeec6d","target":"method:18a9696cad4179d634834650c0684f0c","kind":"calls","metadata":"{\"synthesizedBy\":\"interface-impl\",\"via\":\"RunPayrollCycle\",\"registeredAt\":\"internal/gen/payrollpb/payroll_grpc.pb.go:37\"}","line":23,"col":null,"provenance":"heuristic"} {"source":"method:8c66da74e1212eca1d1b1483bbfeec6d","target":"method:b90cd7088a55c9068e12a8120b256e13","kind":"calls","metadata":"{\"synthesizedBy\":\"interface-impl\",\"via\":\"RunPayrollCycle\",\"registeredAt\":\"internal/gen/payrollpb/payroll_grpc.pb.go:75\"}","line":23,"col":null,"provenance":"heuristic"} +{"source":"method:8c66da74e1212eca1d1b1483bbfeec6d","target":"struct:4325013490f7f7a77604146f5e38c292","kind":"references","metadata":"{\"confidence\":0.9,\"resolvedBy\":\"exact-match\",\"refName\":\"RunPayrollCycleRequest\"}","line":23,"col":42,"provenance":null} +{"source":"method:8c66da74e1212eca1d1b1483bbfeec6d","target":"struct:e66f442bcf28c3bd0a3f42fbacb69b2a","kind":"references","metadata":"{\"confidence\":0.9,\"resolvedBy\":\"exact-match\",\"refName\":\"RunPayrollCycleResponse\"}","line":23,"col":93,"provenance":null} {"source":"method:9b6984f4380172dd0fa8449ec4848fd9","target":"function:209f5fe0d451b33db0d6395638a62fe8","kind":"calls","metadata":"{\"confidence\":0.9,\"resolvedBy\":\"exact-match\",\"refName\":\"scanPayrollCycle\"}","line":41,"col":8,"provenance":null} {"source":"method:9b6984f4380172dd0fa8449ec4848fd9","target":"struct:19321b921e8669d1052268136951cb96","kind":"references","metadata":"{\"confidence\":0.9,\"resolvedBy\":\"exact-match\",\"refName\":\"PayrollCycleRow\"}","line":36,"col":60,"provenance":null} {"source":"method:9b6984f4380172dd0fa8449ec4848fd9","target":"struct:19321b921e8669d1052268136951cb96","kind":"references","metadata":"{\"confidence\":0.9,\"resolvedBy\":\"exact-match\",\"refName\":\"PayrollCycleRow\"}","line":36,"col":78,"provenance":null} @@ -775,8 +783,12 @@ {"source":"method:a1cfcb03fa859746d05499b8e1b91979","target":"struct:e0ae7fcd0d04a65b1a2a768c40e373d3","kind":"instantiates","metadata":"{\"confidence\":0.9,\"resolvedBy\":\"import\",\"refName\":\"payroll.Timesheet\"}","line":99,"col":9,"provenance":null} {"source":"method:a1cfcb03fa859746d05499b8e1b91979","target":"struct:e0ae7fcd0d04a65b1a2a768c40e373d3","kind":"references","metadata":"{\"confidence\":0.9,\"resolvedBy\":\"import\",\"refName\":\"Timesheet\"}","line":97,"col":84,"provenance":null} {"source":"method:a235478f8389c36b95d45a62664c4557","target":"method:68acffbff0c2b5a4b3846a2cb887e3d0","kind":"calls","metadata":"{\"synthesizedBy\":\"interface-impl\",\"via\":\"ListPayslips\",\"registeredAt\":\"internal/gen/payrollpb/payroll_grpc.pb.go:83\"}","line":68,"col":null,"provenance":"heuristic"} +{"source":"method:a235478f8389c36b95d45a62664c4557","target":"struct:4325013490f7f7a77604146f5e38c292","kind":"references","metadata":"{\"confidence\":0.9,\"resolvedBy\":\"exact-match\",\"refName\":\"RunPayrollCycleRequest\"}","line":68,"col":32,"provenance":null} +{"source":"method:a235478f8389c36b95d45a62664c4557","target":"struct:e66f442bcf28c3bd0a3f42fbacb69b2a","kind":"references","metadata":"{\"confidence\":0.9,\"resolvedBy\":\"exact-match\",\"refName\":\"RunPayrollCycleResponse\"}","line":68,"col":58,"provenance":null} {"source":"method:a51e3df6f33aff769f591399d86eb5af","target":"method:68acffbff0c2b5a4b3846a2cb887e3d0","kind":"calls","metadata":"{\"synthesizedBy\":\"interface-impl\",\"via\":\"ListPayslips\",\"registeredAt\":\"internal/gen/payrollpb/payroll_grpc.pb.go:83\"}","line":25,"col":null,"provenance":"heuristic"} {"source":"method:a51e3df6f33aff769f591399d86eb5af","target":"method:c481d719be40f20f63e077521f87b89b","kind":"calls","metadata":"{\"synthesizedBy\":\"interface-impl\",\"via\":\"ListPayslips\",\"registeredAt\":\"internal/gen/payrollpb/payroll_grpc.pb.go:55\"}","line":25,"col":null,"provenance":"heuristic"} +{"source":"method:a51e3df6f33aff769f591399d86eb5af","target":"struct:4325013490f7f7a77604146f5e38c292","kind":"references","metadata":"{\"confidence\":0.9,\"resolvedBy\":\"exact-match\",\"refName\":\"RunPayrollCycleRequest\"}","line":25,"col":39,"provenance":null} +{"source":"method:a51e3df6f33aff769f591399d86eb5af","target":"struct:e66f442bcf28c3bd0a3f42fbacb69b2a","kind":"references","metadata":"{\"confidence\":0.9,\"resolvedBy\":\"exact-match\",\"refName\":\"RunPayrollCycleResponse\"}","line":25,"col":90,"provenance":null} {"source":"method:abcc0b4bca6145184f692d4019641c7f","target":"method:d14d0b12675b711f5f90a392b7b297aa","kind":"calls","metadata":"{\"confidence\":0.9,\"resolvedBy\":\"instance-method\",\"refName\":\"s.loadCycle\"}","line":201,"col":8,"provenance":null} {"source":"method:abcc0b4bca6145184f692d4019641c7f","target":"struct:4831ac24c172065fee6e46751021f7ba","kind":"references","metadata":"{\"confidence\":0.9,\"resolvedBy\":\"import\",\"refName\":\"Cycle\"}","line":200,"col":70,"provenance":null} {"source":"method:b27d090751d2cb16edf0e5b79bf229a6","target":"function:9a1275209a1a60e56b21de5aba04f222","kind":"calls","metadata":"{\"confidence\":0.7,\"resolvedBy\":\"exact-match\",\"refName\":\"GetPayslip\"}","line":51,"col":8,"provenance":null} @@ -867,6 +879,7 @@ {"source":"route:internal/transport/httpapi/router.go:11:GET:/v1/payroll/cycles/{cycleID}/payslips","target":"method:6e0fe8d0272ee955601347cf37b5a383","kind":"references","metadata":"{\"confidence\":0.7,\"resolvedBy\":\"exact-match\",\"refName\":\"ListPayslips\"}","line":11,"col":0,"provenance":null} {"source":"route:internal/transport/httpapi/router.go:12:GET:/healthz","target":"function:4bfd3234b60c7cb018e09fa29aea24df","kind":"references","metadata":"{\"confidence\":0.9,\"resolvedBy\":\"exact-match\",\"refName\":\"health\"}","line":12,"col":0,"provenance":null} {"source":"route:internal/transport/httpapi/router.go:9:POST:/v1/payroll/cycles/{cycleID}/run","target":"method:84b624c4861c4c33658499d7a4d48d3b","kind":"references","metadata":"{\"confidence\":0.7,\"resolvedBy\":\"exact-match\",\"refName\":\"RunCycle\"}","line":9,"col":0,"provenance":null} +{"source":"struct:09a019d5ab5eefb1f1bc3b25ad95d81c","target":"struct:f1c05936f2b11591d1f90efa9d981fa7","kind":"references","metadata":"{\"confidence\":0.9,\"resolvedBy\":\"import\",\"refName\":\"Payslip\"}","line":34,"col":27,"provenance":null} {"source":"struct:13bfc2acbe1de6557e9a28c0be484ffa","target":"method:069338e91f3b3bc0a6b434212386e59b","kind":"contains","metadata":null,"line":null,"col":null,"provenance":null} {"source":"struct:13bfc2acbe1de6557e9a28c0be484ffa","target":"method:0f882862f60ecd98b79db60e64ec66eb","kind":"contains","metadata":null,"line":null,"col":null,"provenance":null} {"source":"struct:13bfc2acbe1de6557e9a28c0be484ffa","target":"method:4f0ac2154c360ad1c55284c03d1f0c73","kind":"contains","metadata":null,"line":null,"col":null,"provenance":null} @@ -878,6 +891,7 @@ {"source":"struct:13bfc2acbe1de6557e9a28c0be484ffa","target":"method:9fb9bdbd7bbd9dc61cf38dda2c30809a","kind":"contains","metadata":null,"line":null,"col":null,"provenance":null} {"source":"struct:13bfc2acbe1de6557e9a28c0be484ffa","target":"method:b27d090751d2cb16edf0e5b79bf229a6","kind":"contains","metadata":null,"line":null,"col":null,"provenance":null} {"source":"struct:13bfc2acbe1de6557e9a28c0be484ffa","target":"method:ee60f0f8c18e9fd703205c637e5b5f8d","kind":"contains","metadata":null,"line":null,"col":null,"provenance":null} +{"source":"struct:2f7383e9af9d4a001f3e116d2accaae5","target":"struct:416d70a4ba3bd67a9d4b7114f2abd3a6","kind":"references","metadata":"{\"confidence\":0.9,\"resolvedBy\":\"exact-match\",\"refName\":\"PayslipDTO\"}","line":33,"col":14,"provenance":null} {"source":"struct:31bc406f5571401a2e5b9ea60dcc57a5","target":"interface:a2c04a6e9d1203f224eb044d73e38f03","kind":"implements","metadata":"{\"synthesizedBy\":\"go-implements\",\"via\":\"Clock\",\"registeredAt\":\"internal/platform/clock/clock.go:16\"}","line":16,"col":null,"provenance":"heuristic"} {"source":"struct:31bc406f5571401a2e5b9ea60dcc57a5","target":"method:a68d11d25279e217ec83342d95b172f6","kind":"contains","metadata":null,"line":null,"col":null,"provenance":null} {"source":"struct:33239c589ef83d64d5f6e73c2e021ee6","target":"method:24e3292f2546abebcb9d371572f38e20","kind":"contains","metadata":null,"line":null,"col":null,"provenance":null} @@ -887,6 +901,10 @@ {"source":"struct:33239c589ef83d64d5f6e73c2e021ee6","target":"method:a1cfcb03fa859746d05499b8e1b91979","kind":"contains","metadata":null,"line":null,"col":null,"provenance":null} {"source":"struct:33239c589ef83d64d5f6e73c2e021ee6","target":"method:c51ef8827ea4d4e2fac8c8e0b7dce61d","kind":"contains","metadata":null,"line":null,"col":null,"provenance":null} {"source":"struct:33239c589ef83d64d5f6e73c2e021ee6","target":"method:e5d8405d7063593214cc4d16d2bbec81","kind":"contains","metadata":null,"line":null,"col":null,"provenance":null} +{"source":"struct:33239c589ef83d64d5f6e73c2e021ee6","target":"struct:4831ac24c172065fee6e46751021f7ba","kind":"references","metadata":"{\"confidence\":0.9,\"resolvedBy\":\"import\",\"refName\":\"Cycle\"}","line":17,"col":30,"provenance":null} +{"source":"struct:33239c589ef83d64d5f6e73c2e021ee6","target":"struct:62563918fc7ed271ca7e2c7b11f2c17a","kind":"references","metadata":"{\"confidence\":0.9,\"resolvedBy\":\"import\",\"refName\":\"Employee\"}","line":18,"col":32,"provenance":null} +{"source":"struct:33239c589ef83d64d5f6e73c2e021ee6","target":"struct:e0ae7fcd0d04a65b1a2a768c40e373d3","kind":"references","metadata":"{\"confidence\":0.9,\"resolvedBy\":\"import\",\"refName\":\"Timesheet\"}","line":19,"col":30,"provenance":null} +{"source":"struct:33239c589ef83d64d5f6e73c2e021ee6","target":"struct:f1c05936f2b11591d1f90efa9d981fa7","kind":"references","metadata":"{\"confidence\":0.9,\"resolvedBy\":\"import\",\"refName\":\"Payslip\"}","line":16,"col":30,"provenance":null} {"source":"struct:3d4fd5cb833f90205ff1d82443698813","target":"method:b7b7504326d93c240db9e8bcb37454e5","kind":"contains","metadata":null,"line":null,"col":null,"provenance":null} {"source":"struct:3d4fd5cb833f90205ff1d82443698813","target":"method:e267262348db43f8e9f40f77f277ce9c","kind":"contains","metadata":null,"line":null,"col":null,"provenance":null} {"source":"struct:3d4fd5cb833f90205ff1d82443698813","target":"method:ff7a7eea8969534c02484b666f0ef39b","kind":"contains","metadata":null,"line":null,"col":null,"provenance":null} @@ -895,9 +913,15 @@ {"source":"struct:4325013490f7f7a77604146f5e38c292","target":"method:578c07e761ce9e31fb80ec2ae5ee7713","kind":"contains","metadata":null,"line":null,"col":null,"provenance":null} {"source":"struct:4325013490f7f7a77604146f5e38c292","target":"method:599cba080912c1a44a7e4f727a98e155","kind":"contains","metadata":null,"line":null,"col":null,"provenance":null} {"source":"struct:4325013490f7f7a77604146f5e38c292","target":"method:f5fda95d052fb685f72d11db016c53d3","kind":"contains","metadata":null,"line":null,"col":null,"provenance":null} +{"source":"struct:4831ac24c172065fee6e46751021f7ba","target":"type_alias:b9cce2d7abf2b9b9935cb4d77e3958f1","kind":"references","metadata":"{\"confidence\":0.9,\"resolvedBy\":\"exact-match\",\"refName\":\"CycleStatus\"}","line":34,"col":14,"provenance":null} +{"source":"struct:51160f165aa24865c9ffd701638e08de","target":"type_alias:ef3b795cc61dfe835d31042c3fa65786","kind":"references","metadata":"{\"confidence\":0.9,\"resolvedBy\":\"exact-match\",\"refName\":\"LineKind\"}","line":42,"col":13,"provenance":null} {"source":"struct:5a24b812343adf92b595b492746cf9ab","target":"interface:a2c04a6e9d1203f224eb044d73e38f03","kind":"implements","metadata":"{\"synthesizedBy\":\"go-implements\",\"via\":\"Clock\",\"registeredAt\":\"internal/platform/clock/clock.go:11\"}","line":11,"col":null,"provenance":"heuristic"} {"source":"struct:5a24b812343adf92b595b492746cf9ab","target":"method:69ac55ca7f86919d7f4ed769540cd552","kind":"contains","metadata":null,"line":null,"col":null,"provenance":null} {"source":"struct:62563918fc7ed271ca7e2c7b11f2c17a","target":"method:1b4f96e5a5a8b2784487acc4f7134ff7","kind":"contains","metadata":null,"line":null,"col":null,"provenance":null} +{"source":"struct:62563918fc7ed271ca7e2c7b11f2c17a","target":"struct:610f8af9b6ba30a6ee3daaff4c8cee08","kind":"references","metadata":"{\"confidence\":0.9,\"resolvedBy\":\"exact-match\",\"refName\":\"Leave\"}","line":145,"col":14,"provenance":null} +{"source":"struct:62563918fc7ed271ca7e2c7b11f2c17a","target":"struct:8fdbd9772ccdeff71633c382f7d0a8bf","kind":"references","metadata":"{\"confidence\":0.9,\"resolvedBy\":\"exact-match\",\"refName\":\"TaxBand\"}","line":144,"col":14,"provenance":null} +{"source":"struct:62563918fc7ed271ca7e2c7b11f2c17a","target":"struct:b3960082884fafd52356f38f6551082f","kind":"references","metadata":"{\"confidence\":0.9,\"resolvedBy\":\"exact-match\",\"refName\":\"Contract\"}","line":142,"col":12,"provenance":null} +{"source":"struct:62563918fc7ed271ca7e2c7b11f2c17a","target":"struct:f221a626c8918bb65aeb52f4f2641203","kind":"references","metadata":"{\"confidence\":0.9,\"resolvedBy\":\"exact-match\",\"refName\":\"Deduction\"}","line":143,"col":14,"provenance":null} {"source":"struct:647d9ed99f3edb65583226ac47408b04","target":"interface:42cfdfeed096dbb476259a39846085a2","kind":"implements","metadata":"{\"synthesizedBy\":\"go-implements\",\"via\":\"PayrollServiceClient\",\"registeredAt\":\"internal/gen/payrollpb/payroll_grpc.pb.go:73\"}","line":73,"col":null,"provenance":"heuristic"} {"source":"struct:647d9ed99f3edb65583226ac47408b04","target":"interface:9382b4b7c3b120f81bd0566fb2d74864","kind":"implements","metadata":"{\"synthesizedBy\":\"go-implements\",\"via\":\"PayrollServiceServer\",\"registeredAt\":\"internal/gen/payrollpb/payroll_grpc.pb.go:73\"}","line":73,"col":null,"provenance":"heuristic"} {"source":"struct:647d9ed99f3edb65583226ac47408b04","target":"method:412163f69abf5ae22adf9b9141ba79e2","kind":"contains","metadata":null,"line":null,"col":null,"provenance":null} @@ -906,9 +930,13 @@ {"source":"struct:647d9ed99f3edb65583226ac47408b04","target":"method:b90cd7088a55c9068e12a8120b256e13","kind":"contains","metadata":null,"line":null,"col":null,"provenance":null} {"source":"struct:b3960082884fafd52356f38f6551082f","target":"method:5da2578b83fc2de6a32dda8e01704ad3","kind":"contains","metadata":null,"line":null,"col":null,"provenance":null} {"source":"struct:b3960082884fafd52356f38f6551082f","target":"method:b32c3975c878ce8570b17cb4638c5055","kind":"contains","metadata":null,"line":null,"col":null,"provenance":null} +{"source":"struct:b3960082884fafd52356f38f6551082f","target":"struct:6ee2c8b983ba47afa67ded3413cb1af3","kind":"references","metadata":"{\"confidence\":0.9,\"resolvedBy\":\"exact-match\",\"refName\":\"Allowance\"}","line":85,"col":26,"provenance":null} +{"source":"struct:b3960082884fafd52356f38f6551082f","target":"type_alias:00d20770b36eea887e218cb63cc6196c","kind":"references","metadata":"{\"confidence\":0.9,\"resolvedBy\":\"exact-match\",\"refName\":\"ContractKind\"}","line":79,"col":24,"provenance":null} {"source":"struct:cd1ed508e3b308169888959466534fa8","target":"method:6e0fe8d0272ee955601347cf37b5a383","kind":"contains","metadata":null,"line":null,"col":null,"provenance":null} {"source":"struct:cd1ed508e3b308169888959466534fa8","target":"method:84b624c4861c4c33658499d7a4d48d3b","kind":"contains","metadata":null,"line":null,"col":null,"provenance":null} {"source":"struct:cd1ed508e3b308169888959466534fa8","target":"method:8baae5c5fb59db7a88c19bb295635d18","kind":"contains","metadata":null,"line":null,"col":null,"provenance":null} +{"source":"struct:cd1ed508e3b308169888959466534fa8","target":"struct:d40c8ed73128048826648f1ac8c1bc35","kind":"references","metadata":"{\"confidence\":0.9,\"resolvedBy\":\"import\",\"refName\":\"Service\"}","line":13,"col":14,"provenance":null} +{"source":"struct:d40c8ed73128048826648f1ac8c1bc35","target":"interface:a2c04a6e9d1203f224eb044d73e38f03","kind":"references","metadata":"{\"confidence\":0.9,\"resolvedBy\":\"import\",\"refName\":\"Clock\"}","line":47,"col":13,"provenance":null} {"source":"struct:d40c8ed73128048826648f1ac8c1bc35","target":"method:01c8a961c1fdfb54ea0c32614f905acc","kind":"contains","metadata":null,"line":null,"col":null,"provenance":null} {"source":"struct:d40c8ed73128048826648f1ac8c1bc35","target":"method:12243ae31857f370c8d5ea75c91b702f","kind":"contains","metadata":null,"line":null,"col":null,"provenance":null} {"source":"struct:d40c8ed73128048826648f1ac8c1bc35","target":"method:3af34007f72fd40aebe0e4504e8228ae","kind":"contains","metadata":null,"line":null,"col":null,"provenance":null} @@ -922,6 +950,7 @@ {"source":"struct:d40c8ed73128048826648f1ac8c1bc35","target":"method:d4c880f819795f197c94de3201fb709e","kind":"contains","metadata":"{\"synthesizedBy\":\"go-method-contains\"}","line":92,"col":null,"provenance":null} {"source":"struct:d40c8ed73128048826648f1ac8c1bc35","target":"method:ed702f7226c3efff6b07f6f5afd73bf8","kind":"contains","metadata":null,"line":null,"col":null,"provenance":null} {"source":"struct:d40c8ed73128048826648f1ac8c1bc35","target":"method:fd95c33dd58bbddc5221ee4ced0bbcd3","kind":"contains","metadata":null,"line":null,"col":null,"provenance":null} +{"source":"struct:d40c8ed73128048826648f1ac8c1bc35","target":"struct:33239c589ef83d64d5f6e73c2e021ee6","kind":"references","metadata":"{\"confidence\":0.9,\"resolvedBy\":\"import\",\"refName\":\"Store\"}","line":46,"col":21,"provenance":null} {"source":"struct:d541b867b240edf388feab5ff2002afd","target":"method:1137aabcdc698c3b11d27a0e8701d23e","kind":"contains","metadata":null,"line":null,"col":null,"provenance":null} {"source":"struct:d541b867b240edf388feab5ff2002afd","target":"method:3367319bda79cdcf1fefc366ce7322ac","kind":"contains","metadata":null,"line":null,"col":null,"provenance":null} {"source":"struct:d541b867b240edf388feab5ff2002afd","target":"method:912c820bb3fa62b0be6eb7671273d2a1","kind":"contains","metadata":null,"line":null,"col":null,"provenance":null} @@ -933,13 +962,15 @@ {"source":"struct:e66f442bcf28c3bd0a3f42fbacb69b2a","target":"method:2f3ad781c22d07dedb06b0a2f536ba18","kind":"contains","metadata":null,"line":null,"col":null,"provenance":null} {"source":"struct:e66f442bcf28c3bd0a3f42fbacb69b2a","target":"method:3f9811f3a17dc661bfba3de069234279","kind":"contains","metadata":null,"line":null,"col":null,"provenance":null} {"source":"struct:e66f442bcf28c3bd0a3f42fbacb69b2a","target":"method:eba91430ad280a0c070af5c64e79d2d0","kind":"contains","metadata":null,"line":null,"col":null,"provenance":null} +{"source":"struct:e66f442bcf28c3bd0a3f42fbacb69b2a","target":"struct:d541b867b240edf388feab5ff2002afd","kind":"references","metadata":"{\"framework\":\"go\",\"confidence\":0.7,\"resolvedBy\":\"framework\",\"refName\":\"Payslip\"}","line":57,"col":15,"provenance":null} +{"source":"struct:f1c05936f2b11591d1f90efa9d981fa7","target":"struct:51160f165aa24865c9ffd701638e08de","kind":"references","metadata":"{\"confidence\":0.9,\"resolvedBy\":\"exact-match\",\"refName\":\"Line\"}","line":53,"col":18,"provenance":null} {"source":"struct:f221a626c8918bb65aeb52f4f2641203","target":"method:dd6580e3209a7f4efedb099a9bd5576d","kind":"contains","metadata":null,"line":null,"col":null,"provenance":null} {"source":"variable:02a9b4868be4f999189e4d930af29b95","target":"interface:9382b4b7c3b120f81bd0566fb2d74864","kind":"calls","metadata":"{\"confidence\":0.9,\"resolvedBy\":\"exact-match\",\"refName\":\"PayrollServiceServer\"}","line":97,"col":14,"provenance":null} {"source":"variable:9c3a0c9681a69504be5d3af6ddb5378c","target":"struct:3d4fd5cb833f90205ff1d82443698813","kind":"instantiates","metadata":"{\"confidence\":0.9,\"resolvedBy\":\"exact-match\",\"refName\":\"PayrollCycle\",\"refKind\":\"calls\"}","line":136,"col":1,"provenance":null} {"source":"variable:9c3a0c9681a69504be5d3af6ddb5378c","target":"struct:4325013490f7f7a77604146f5e38c292","kind":"instantiates","metadata":"{\"confidence\":0.9,\"resolvedBy\":\"exact-match\",\"refName\":\"RunPayrollCycleRequest\",\"refKind\":\"calls\"}","line":133,"col":1,"provenance":null} {"source":"variable:9c3a0c9681a69504be5d3af6ddb5378c","target":"struct:d541b867b240edf388feab5ff2002afd","kind":"instantiates","metadata":"{\"confidence\":0.9,\"resolvedBy\":\"exact-match\",\"refName\":\"Payslip\",\"refKind\":\"calls\"}","line":135,"col":1,"provenance":null} {"source":"variable:9c3a0c9681a69504be5d3af6ddb5378c","target":"struct:e66f442bcf28c3bd0a3f42fbacb69b2a","kind":"instantiates","metadata":"{\"confidence\":0.9,\"resolvedBy\":\"exact-match\",\"refName\":\"RunPayrollCycleResponse\",\"refKind\":\"calls\"}","line":134,"col":1,"provenance":null} -== refs (531) +== refs (599) {"from_node_id":"file:cmd/payrolld/main.go","reference_name":"github.com/example/payroll-svc/internal/platform/clock","reference_kind":"imports","line":9,"col":1,"candidates":null,"file_path":"cmd/payrolld/main.go","language":"go","status":"failed","name_tail":"clock"} {"from_node_id":"file:cmd/payrolld/main.go","reference_name":"github.com/example/payroll-svc/internal/store/payslipstore","reference_kind":"imports","line":10,"col":1,"candidates":null,"file_path":"cmd/payrolld/main.go","language":"go","status":"failed","name_tail":"payslipstore"} {"from_node_id":"file:cmd/payrolld/main.go","reference_name":"github.com/example/payroll-svc/internal/transport/httpapi","reference_kind":"imports","line":11,"col":1,"candidates":null,"file_path":"cmd/payrolld/main.go","language":"go","status":"failed","name_tail":"httpapi"} @@ -1254,6 +1285,7 @@ {"from_node_id":"method:12243ae31857f370c8d5ea75c91b702f","reference_name":"Context","reference_kind":"references","line":215,"col":37,"candidates":null,"file_path":"internal/usecase/payroll/cycle.go","language":"go","status":"failed","name_tail":"Context"} {"from_node_id":"method:12243ae31857f370c8d5ea75c91b702f","reference_name":"payroll.CycleOpen","reference_kind":"function_ref","line":223,"col":24,"candidates":null,"file_path":"internal/usecase/payroll/cycle.go","language":"go","status":"failed","name_tail":"CycleOpen"} {"from_node_id":"method:12243ae31857f370c8d5ea75c91b702f","reference_name":"time.Time","reference_kind":"instantiates","line":225,"col":18,"candidates":null,"file_path":"internal/usecase/payroll/cycle.go","language":"go","status":"failed","name_tail":"Time"} +{"from_node_id":"method:16a61da8990e9e8548eaba76a0d96d9f","reference_name":"Context","reference_kind":"references","line":67,"col":25,"candidates":null,"file_path":"internal/gen/payrollpb/payroll_grpc.pb.go","language":"go","status":"failed","name_tail":"Context"} {"from_node_id":"method:18a9696cad4179d634834650c0684f0c","reference_name":"CallOption","reference_kind":"references","line":37,"col":109,"candidates":null,"file_path":"internal/gen/payrollpb/payroll_grpc.pb.go","language":"go","status":"failed","name_tail":"CallOption"} {"from_node_id":"method:18a9696cad4179d634834650c0684f0c","reference_name":"Context","reference_kind":"references","line":37,"col":59,"candidates":null,"file_path":"internal/gen/payrollpb/payroll_grpc.pb.go","language":"go","status":"failed","name_tail":"Context"} {"from_node_id":"method:18a9696cad4179d634834650c0684f0c","reference_name":"c.cc.Invoke","reference_kind":"calls","line":39,"col":8,"candidates":null,"file_path":"internal/gen/payrollpb/payroll_grpc.pb.go","language":"go","status":"failed","name_tail":"Invoke","failure_reason":"unknown-receiver"} @@ -1300,12 +1332,15 @@ {"from_node_id":"method:41899a297d23af6d3d2da3506b936eec","reference_name":"slip.GrossCents","reference_kind":"function_ref","line":62,"col":29,"candidates":null,"file_path":"internal/usecase/payroll/payslip_builder.go","language":"go","status":"failed","name_tail":"GrossCents"} {"from_node_id":"method:41899a297d23af6d3d2da3506b936eec","reference_name":"slip.Lines","reference_kind":"function_ref","line":39,"col":26,"candidates":null,"file_path":"internal/usecase/payroll/payslip_builder.go","language":"go","status":"failed","name_tail":"Lines"} {"from_node_id":"method:41899a297d23af6d3d2da3506b936eec","reference_name":"timesheet.EmployeeID","reference_kind":"function_ref","line":27,"col":90,"candidates":null,"file_path":"internal/usecase/payroll/payslip_builder.go","language":"go","status":"failed","name_tail":"EmployeeID"} +{"from_node_id":"method:4275e437d50514e430b25f9c11363ddf","reference_name":"CallOption","reference_kind":"references","line":24,"col":79,"candidates":null,"file_path":"internal/gen/payrollpb/payroll_grpc.pb.go","language":"go","status":"failed","name_tail":"CallOption"} +{"from_node_id":"method:4275e437d50514e430b25f9c11363ddf","reference_name":"Context","reference_kind":"references","line":24,"col":29,"candidates":null,"file_path":"internal/gen/payrollpb/payroll_grpc.pb.go","language":"go","status":"failed","name_tail":"Context"} {"from_node_id":"method:4a3dff65c0d488ecc09cf9edabe95d42","reference_name":"band.RateBasisPoints","reference_kind":"function_ref","line":130,"col":53,"candidates":null,"file_path":"internal/usecase/payroll/payslip_builder.go","language":"go","status":"failed","name_tail":"RateBasisPoints"} {"from_node_id":"method:4a3dff65c0d488ecc09cf9edabe95d42","reference_name":"band.UpToCents","reference_kind":"function_ref","line":134,"col":16,"candidates":null,"file_path":"internal/usecase/payroll/payslip_builder.go","language":"go","status":"failed","name_tail":"UpToCents"} {"from_node_id":"method:4a3dff65c0d488ecc09cf9edabe95d42","reference_name":"e.TaxBands","reference_kind":"function_ref","line":120,"col":10,"candidates":null,"file_path":"internal/usecase/payroll/payslip_builder.go","language":"go","status":"failed","name_tail":"TaxBands"} {"from_node_id":"method:4a3dff65c0d488ecc09cf9edabe95d42","reference_name":"fmt.Errorf","reference_kind":"calls","line":130,"col":13,"candidates":null,"file_path":"internal/usecase/payroll/payslip_builder.go","language":"go","status":"failed","name_tail":"Errorf","failure_reason":"unknown-receiver"} {"from_node_id":"method:4a3dff65c0d488ecc09cf9edabe95d42","reference_name":"int64","reference_kind":"calls","line":136,"col":17,"candidates":null,"file_path":"internal/usecase/payroll/payslip_builder.go","language":"go","status":"failed","name_tail":"int64"} {"from_node_id":"method:4a3dff65c0d488ecc09cf9edabe95d42","reference_name":"len","reference_kind":"calls","line":120,"col":4,"candidates":null,"file_path":"internal/usecase/payroll/payslip_builder.go","language":"go","status":"failed","name_tail":"len"} +{"from_node_id":"method:4df364d0c37da3d10e39207b87a94ca8","reference_name":"Context","reference_kind":"references","line":66,"col":25,"candidates":null,"file_path":"internal/gen/payrollpb/payroll_grpc.pb.go","language":"go","status":"failed","name_tail":"Context"} {"from_node_id":"method:4f0ac2154c360ad1c55284c03d1f0c73","reference_name":"Context","reference_kind":"references","line":85,"col":31,"candidates":null,"file_path":"internal/gen/fkit/payroll/store.go","language":"go","status":"failed","name_tail":"Context"} {"from_node_id":"method:4f0ac2154c360ad1c55284c03d1f0c73","reference_name":"fn","reference_kind":"calls","line":90,"col":11,"candidates":null,"file_path":"internal/gen/fkit/payroll/store.go","language":"go","status":"failed","name_tail":"fn"} {"from_node_id":"method:4f0ac2154c360ad1c55284c03d1f0c73","reference_name":"s.db.BeginTx","reference_kind":"calls","line":86,"col":12,"candidates":null,"file_path":"internal/gen/fkit/payroll/store.go","language":"go","status":"failed","name_tail":"BeginTx","failure_reason":"unknown-receiver"} @@ -1388,6 +1423,8 @@ {"from_node_id":"method:8baae5c5fb59db7a88c19bb295635d18","reference_name":"http.StatusOK","reference_kind":"function_ref","line":76,"col":19,"candidates":null,"file_path":"internal/transport/httpapi/payroll_handler.go","language":"go","status":"failed","name_tail":"StatusOK"} {"from_node_id":"method:8baae5c5fb59db7a88c19bb295635d18","reference_name":"r.Context","reference_kind":"calls","line":71,"col":27,"candidates":null,"file_path":"internal/transport/httpapi/payroll_handler.go","language":"go","status":"failed","name_tail":"Context","failure_reason":"unknown-receiver"} {"from_node_id":"method:8baae5c5fb59db7a88c19bb295635d18","reference_name":"r.PathValue","reference_kind":"calls","line":71,"col":40,"candidates":null,"file_path":"internal/transport/httpapi/payroll_handler.go","language":"go","status":"failed","name_tail":"PathValue","failure_reason":"unknown-receiver"} +{"from_node_id":"method:8c66da74e1212eca1d1b1483bbfeec6d","reference_name":"CallOption","reference_kind":"references","line":23,"col":79,"candidates":null,"file_path":"internal/gen/payrollpb/payroll_grpc.pb.go","language":"go","status":"failed","name_tail":"CallOption"} +{"from_node_id":"method:8c66da74e1212eca1d1b1483bbfeec6d","reference_name":"Context","reference_kind":"references","line":23,"col":29,"candidates":null,"file_path":"internal/gen/payrollpb/payroll_grpc.pb.go","language":"go","status":"failed","name_tail":"Context"} {"from_node_id":"method:9b6984f4380172dd0fa8449ec4848fd9","reference_name":"Context","reference_kind":"references","line":36,"col":47,"candidates":null,"file_path":"internal/gen/fkit/payroll/store.go","language":"go","status":"failed","name_tail":"Context"} {"from_node_id":"method:9b6984f4380172dd0fa8449ec4848fd9","reference_name":"row.End","reference_kind":"function_ref","line":41,"col":77,"candidates":null,"file_path":"internal/gen/fkit/payroll/store.go","language":"go","status":"failed","name_tail":"End"} {"from_node_id":"method:9b6984f4380172dd0fa8449ec4848fd9","reference_name":"row.ID","reference_kind":"function_ref","line":41,"col":58,"candidates":null,"file_path":"internal/gen/fkit/payroll/store.go","language":"go","status":"failed","name_tail":"ID"} @@ -1409,6 +1446,9 @@ {"from_node_id":"method:a1cfcb03fa859746d05499b8e1b91979","reference_name":"fmt.Errorf","reference_kind":"calls","line":105,"col":30,"candidates":null,"file_path":"internal/store/payslipstore/store.go","language":"go","status":"failed","name_tail":"Errorf","failure_reason":"unknown-receiver"} {"from_node_id":"method:a1cfcb03fa859746d05499b8e1b91979","reference_name":"s.mu.RLock","reference_kind":"calls","line":101,"col":1,"candidates":null,"file_path":"internal/store/payslipstore/store.go","language":"go","status":"failed","name_tail":"RLock","failure_reason":"unknown-receiver"} {"from_node_id":"method:a1cfcb03fa859746d05499b8e1b91979","reference_name":"s.mu.RUnlock","reference_kind":"calls","line":102,"col":7,"candidates":null,"file_path":"internal/store/payslipstore/store.go","language":"go","status":"failed","name_tail":"RUnlock","failure_reason":"unknown-receiver"} +{"from_node_id":"method:a235478f8389c36b95d45a62664c4557","reference_name":"Context","reference_kind":"references","line":68,"col":22,"candidates":null,"file_path":"internal/gen/payrollpb/payroll_grpc.pb.go","language":"go","status":"failed","name_tail":"Context"} +{"from_node_id":"method:a51e3df6f33aff769f591399d86eb5af","reference_name":"CallOption","reference_kind":"references","line":25,"col":76,"candidates":null,"file_path":"internal/gen/payrollpb/payroll_grpc.pb.go","language":"go","status":"failed","name_tail":"CallOption"} +{"from_node_id":"method:a51e3df6f33aff769f591399d86eb5af","reference_name":"Context","reference_kind":"references","line":25,"col":26,"candidates":null,"file_path":"internal/gen/payrollpb/payroll_grpc.pb.go","language":"go","status":"failed","name_tail":"Context"} {"from_node_id":"method:a68d11d25279e217ec83342d95b172f6","reference_name":"Time","reference_kind":"references","line":18,"col":26,"candidates":null,"file_path":"internal/platform/clock/clock.go","language":"go","status":"failed","name_tail":"Time"} {"from_node_id":"method:abcc0b4bca6145184f692d4019641c7f","reference_name":"Context","reference_kind":"references","line":200,"col":36,"candidates":null,"file_path":"internal/usecase/payroll/cycle.go","language":"go","status":"failed","name_tail":"Context"} {"from_node_id":"method:b27d090751d2cb16edf0e5b79bf229a6","reference_name":"Context","reference_kind":"references","line":50,"col":39,"candidates":null,"file_path":"internal/gen/fkit/payroll/store.go","language":"go","status":"failed","name_tail":"Context"} @@ -1439,6 +1479,7 @@ {"from_node_id":"method:d4c880f819795f197c94de3201fb709e","reference_name":"e.Contract.PeriodRateCents","reference_kind":"function_ref","line":95,"col":21,"candidates":null,"file_path":"internal/usecase/payroll/payslip_builder.go","language":"go","status":"failed","name_tail":"PeriodRateCents"} {"from_node_id":"method:d4c880f819795f197c94de3201fb709e","reference_name":"int64","reference_kind":"calls","line":98,"col":32,"candidates":null,"file_path":"internal/usecase/payroll/payslip_builder.go","language":"go","status":"failed","name_tail":"int64"} {"from_node_id":"method:d4c880f819795f197c94de3201fb709e","reference_name":"ts.Units","reference_kind":"function_ref","line":98,"col":41,"candidates":null,"file_path":"internal/usecase/payroll/payslip_builder.go","language":"go","status":"failed","name_tail":"Units"} +{"from_node_id":"method:d73f595573e869571a14f1606df5c296","reference_name":"Time","reference_kind":"references","line":7,"col":12,"candidates":null,"file_path":"internal/platform/clock/clock.go","language":"go","status":"failed","name_tail":"Time"} {"from_node_id":"method:dd6580e3209a7f4efedb099a9bd5576d","reference_name":"d.RateBasisPoints","reference_kind":"function_ref","line":123,"col":29,"candidates":null,"file_path":"internal/domain/payroll/payslip.go","language":"go","status":"failed","name_tail":"RateBasisPoints"} {"from_node_id":"method:dd6580e3209a7f4efedb099a9bd5576d","reference_name":"int64","reference_kind":"calls","line":123,"col":21,"candidates":null,"file_path":"internal/domain/payroll/payslip.go","language":"go","status":"failed","name_tail":"int64"} {"from_node_id":"method:e0490e3e69744ec0d57d332d3bda8c60","reference_name":"CallOption","reference_kind":"references","line":46,"col":109,"candidates":null,"file_path":"internal/gen/payrollpb/payroll_grpc.pb.go","language":"go","status":"failed","name_tail":"CallOption"} @@ -1468,6 +1509,64 @@ {"from_node_id":"module:a883d05f3bb8edb262fd18c8c2849417","reference_name":"docs/design/explore-budget-allocation.md","reference_kind":"references","line":82,"col":1,"candidates":null,"file_path":"README.md","language":"markdown","status":"failed","name_tail":"explore-budget-allocation.md"} {"from_node_id":"module:a883d05f3bb8edb262fd18c8c2849417","reference_name":"scripts/agent-eval/allocation-fixtures.js","reference_kind":"references","line":79,"col":49,"candidates":null,"file_path":"README.md","language":"markdown","status":"failed","name_tail":"allocation-fixtures.js"} {"from_node_id":"module:f8d63ed69e573ade27e2d1d4fc0ae8b4","reference_name":"internal/gen/fkit/payroll/store.go","reference_kind":"references","line":87,"col":56,"candidates":null,"file_path":"README.md","language":"markdown","status":"failed","name_tail":"store.go"} +{"from_node_id":"struct:09a019d5ab5eefb1f1bc3b25ad95d81c","reference_name":"Time","reference_kind":"references","line":38,"col":22,"candidates":null,"file_path":"internal/usecase/payroll/cycle.go","language":"go","status":"failed","name_tail":"Time"} +{"from_node_id":"struct:13bfc2acbe1de6557e9a28c0be484ffa","reference_name":"DB","reference_kind":"references","line":15,"col":9,"candidates":null,"file_path":"internal/gen/fkit/payroll/store.go","language":"go","status":"failed","name_tail":"DB"} +{"from_node_id":"struct:141301eeb403e252d3f06decd0665c41","reference_name":"Time","reference_kind":"references","line":21,"col":17,"candidates":null,"file_path":"internal/gen/fkit/timesheet/timesheet.go","language":"go","status":"failed","name_tail":"Time"} +{"from_node_id":"struct:141301eeb403e252d3f06decd0665c41","reference_name":"Time","reference_kind":"references","line":22,"col":17,"candidates":null,"file_path":"internal/gen/fkit/timesheet/timesheet.go","language":"go","status":"failed","name_tail":"Time"} +{"from_node_id":"struct:141301eeb403e252d3f06decd0665c41","reference_name":"Time","reference_kind":"references","line":23,"col":17,"candidates":null,"file_path":"internal/gen/fkit/timesheet/timesheet.go","language":"go","status":"failed","name_tail":"Time"} +{"from_node_id":"struct:19321b921e8669d1052268136951cb96","reference_name":"Time","reference_kind":"references","line":17,"col":19,"candidates":null,"file_path":"internal/gen/fkit/payroll/payroll_cycle.go","language":"go","status":"failed","name_tail":"Time"} +{"from_node_id":"struct:19321b921e8669d1052268136951cb96","reference_name":"Time","reference_kind":"references","line":18,"col":19,"candidates":null,"file_path":"internal/gen/fkit/payroll/payroll_cycle.go","language":"go","status":"failed","name_tail":"Time"} +{"from_node_id":"struct:19321b921e8669d1052268136951cb96","reference_name":"Time","reference_kind":"references","line":20,"col":19,"candidates":null,"file_path":"internal/gen/fkit/payroll/payroll_cycle.go","language":"go","status":"failed","name_tail":"Time"} +{"from_node_id":"struct:19321b921e8669d1052268136951cb96","reference_name":"Time","reference_kind":"references","line":22,"col":19,"candidates":null,"file_path":"internal/gen/fkit/payroll/payroll_cycle.go","language":"go","status":"failed","name_tail":"Time"} +{"from_node_id":"struct:19321b921e8669d1052268136951cb96","reference_name":"Time","reference_kind":"references","line":23,"col":19,"candidates":null,"file_path":"internal/gen/fkit/payroll/payroll_cycle.go","language":"go","status":"failed","name_tail":"Time"} +{"from_node_id":"struct:31bc406f5571401a2e5b9ea60dcc57a5","reference_name":"Time","reference_kind":"references","line":16,"col":27,"candidates":null,"file_path":"internal/platform/clock/clock.go","language":"go","status":"failed","name_tail":"Time"} +{"from_node_id":"struct:33239c589ef83d64d5f6e73c2e021ee6","reference_name":"RWMutex","reference_kind":"references","line":15,"col":16,"candidates":null,"file_path":"internal/store/payslipstore/store.go","language":"go","status":"failed","name_tail":"RWMutex"} +{"from_node_id":"struct:3859374e7027b649f8650d5d9e1ac768","reference_name":"Time","reference_kind":"references","line":28,"col":13,"candidates":null,"file_path":"internal/gen/fkit/payroll/payroll_cycle.go","language":"go","status":"failed","name_tail":"Time"} +{"from_node_id":"struct:3859374e7027b649f8650d5d9e1ac768","reference_name":"Time","reference_kind":"references","line":29,"col":13,"candidates":null,"file_path":"internal/gen/fkit/payroll/payroll_cycle.go","language":"go","status":"failed","name_tail":"Time"} +{"from_node_id":"struct:3d4fd5cb833f90205ff1d82443698813","reference_name":"MessageState","reference_kind":"references","line":107,"col":25,"candidates":null,"file_path":"internal/gen/payrollpb/payroll.pb.go","language":"go","status":"failed","name_tail":"MessageState"} +{"from_node_id":"struct:3d4fd5cb833f90205ff1d82443698813","reference_name":"SizeCache","reference_kind":"references","line":108,"col":25,"candidates":null,"file_path":"internal/gen/payrollpb/payroll.pb.go","language":"go","status":"failed","name_tail":"SizeCache"} +{"from_node_id":"struct:3d4fd5cb833f90205ff1d82443698813","reference_name":"Timestamp","reference_kind":"references","line":112,"col":21,"candidates":null,"file_path":"internal/gen/payrollpb/payroll.pb.go","language":"go","status":"failed","name_tail":"Timestamp"} +{"from_node_id":"struct:3d4fd5cb833f90205ff1d82443698813","reference_name":"Timestamp","reference_kind":"references","line":113,"col":21,"candidates":null,"file_path":"internal/gen/payrollpb/payroll.pb.go","language":"go","status":"failed","name_tail":"Timestamp"} +{"from_node_id":"struct:3d4fd5cb833f90205ff1d82443698813","reference_name":"UnknownFields","reference_kind":"references","line":109,"col":25,"candidates":null,"file_path":"internal/gen/payrollpb/payroll.pb.go","language":"go","status":"failed","name_tail":"UnknownFields"} +{"from_node_id":"struct:416d70a4ba3bd67a9d4b7114f2abd3a6","reference_name":"Time","reference_kind":"references","line":16,"col":21,"candidates":null,"file_path":"internal/gen/fkit/payroll/dto.go","language":"go","status":"failed","name_tail":"Time"} +{"from_node_id":"struct:416d70a4ba3bd67a9d4b7114f2abd3a6","reference_name":"Time","reference_kind":"references","line":17,"col":21,"candidates":null,"file_path":"internal/gen/fkit/payroll/dto.go","language":"go","status":"failed","name_tail":"Time"} +{"from_node_id":"struct:4325013490f7f7a77604146f5e38c292","reference_name":"MessageState","reference_kind":"references","line":17,"col":25,"candidates":null,"file_path":"internal/gen/payrollpb/payroll.pb.go","language":"go","status":"failed","name_tail":"MessageState"} +{"from_node_id":"struct:4325013490f7f7a77604146f5e38c292","reference_name":"SizeCache","reference_kind":"references","line":18,"col":25,"candidates":null,"file_path":"internal/gen/payrollpb/payroll.pb.go","language":"go","status":"failed","name_tail":"SizeCache"} +{"from_node_id":"struct:4325013490f7f7a77604146f5e38c292","reference_name":"UnknownFields","reference_kind":"references","line":19,"col":25,"candidates":null,"file_path":"internal/gen/payrollpb/payroll.pb.go","language":"go","status":"failed","name_tail":"UnknownFields"} +{"from_node_id":"struct:44ba5408fc435805ad63b792fae78895","reference_name":"Time","reference_kind":"references","line":20,"col":16,"candidates":null,"file_path":"internal/gen/fkit/employee/employee.go","language":"go","status":"failed","name_tail":"Time"} +{"from_node_id":"struct:44ba5408fc435805ad63b792fae78895","reference_name":"Time","reference_kind":"references","line":21,"col":16,"candidates":null,"file_path":"internal/gen/fkit/employee/employee.go","language":"go","status":"failed","name_tail":"Time"} +{"from_node_id":"struct:44ba5408fc435805ad63b792fae78895","reference_name":"Time","reference_kind":"references","line":22,"col":16,"candidates":null,"file_path":"internal/gen/fkit/employee/employee.go","language":"go","status":"failed","name_tail":"Time"} +{"from_node_id":"struct:4831ac24c172065fee6e46751021f7ba","reference_name":"Time","reference_kind":"references","line":32,"col":19,"candidates":null,"file_path":"internal/domain/payroll/payslip.go","language":"go","status":"failed","name_tail":"Time"} +{"from_node_id":"struct:4831ac24c172065fee6e46751021f7ba","reference_name":"Time","reference_kind":"references","line":33,"col":19,"candidates":null,"file_path":"internal/domain/payroll/payslip.go","language":"go","status":"failed","name_tail":"Time"} +{"from_node_id":"struct:4831ac24c172065fee6e46751021f7ba","reference_name":"Time","reference_kind":"references","line":35,"col":19,"candidates":null,"file_path":"internal/domain/payroll/payslip.go","language":"go","status":"failed","name_tail":"Time"} +{"from_node_id":"struct:4fe3ee95b0653e99de95b099499b1dda","reference_name":"Time","reference_kind":"references","line":26,"col":13,"candidates":null,"file_path":"internal/gen/fkit/payroll/dto.go","language":"go","status":"failed","name_tail":"Time"} +{"from_node_id":"struct:4fe3ee95b0653e99de95b099499b1dda","reference_name":"Time","reference_kind":"references","line":27,"col":13,"candidates":null,"file_path":"internal/gen/fkit/payroll/dto.go","language":"go","status":"failed","name_tail":"Time"} +{"from_node_id":"struct:610f8af9b6ba30a6ee3daaff4c8cee08","reference_name":"Time","reference_kind":"references","line":134,"col":13,"candidates":null,"file_path":"internal/domain/payroll/payslip.go","language":"go","status":"failed","name_tail":"Time"} +{"from_node_id":"struct:610f8af9b6ba30a6ee3daaff4c8cee08","reference_name":"Time","reference_kind":"references","line":135,"col":13,"candidates":null,"file_path":"internal/domain/payroll/payslip.go","language":"go","status":"failed","name_tail":"Time"} +{"from_node_id":"struct:8ae9f91523a30c90667e8f5ba09c3fc1","reference_name":"Time","reference_kind":"references","line":22,"col":22,"candidates":null,"file_path":"internal/gen/fkit/employee/contract.go","language":"go","status":"failed","name_tail":"Time"} +{"from_node_id":"struct:8ae9f91523a30c90667e8f5ba09c3fc1","reference_name":"Time","reference_kind":"references","line":23,"col":22,"candidates":null,"file_path":"internal/gen/fkit/employee/contract.go","language":"go","status":"failed","name_tail":"Time"} +{"from_node_id":"struct:8ae9f91523a30c90667e8f5ba09c3fc1","reference_name":"Time","reference_kind":"references","line":24,"col":22,"candidates":null,"file_path":"internal/gen/fkit/employee/contract.go","language":"go","status":"failed","name_tail":"Time"} +{"from_node_id":"struct:8ae9f91523a30c90667e8f5ba09c3fc1","reference_name":"Time","reference_kind":"references","line":25,"col":22,"candidates":null,"file_path":"internal/gen/fkit/employee/contract.go","language":"go","status":"failed","name_tail":"Time"} +{"from_node_id":"struct:b3960082884fafd52356f38f6551082f","reference_name":"Time","reference_kind":"references","line":86,"col":29,"candidates":null,"file_path":"internal/domain/payroll/payslip.go","language":"go","status":"failed","name_tail":"Time"} +{"from_node_id":"struct:b3960082884fafd52356f38f6551082f","reference_name":"Time","reference_kind":"references","line":87,"col":29,"candidates":null,"file_path":"internal/domain/payroll/payslip.go","language":"go","status":"failed","name_tail":"Time"} +{"from_node_id":"struct:cb7da9d97cf09a07df5635a95a92dec6","reference_name":"Time","reference_kind":"references","line":35,"col":22,"candidates":null,"file_path":"internal/gen/fkit/employee/contract.go","language":"go","status":"failed","name_tail":"Time"} +{"from_node_id":"struct:d541b867b240edf388feab5ff2002afd","reference_name":"MessageState","reference_kind":"references","line":74,"col":25,"candidates":null,"file_path":"internal/gen/payrollpb/payroll.pb.go","language":"go","status":"failed","name_tail":"MessageState"} +{"from_node_id":"struct:d541b867b240edf388feab5ff2002afd","reference_name":"SizeCache","reference_kind":"references","line":75,"col":25,"candidates":null,"file_path":"internal/gen/payrollpb/payroll.pb.go","language":"go","status":"failed","name_tail":"SizeCache"} +{"from_node_id":"struct:d541b867b240edf388feab5ff2002afd","reference_name":"Timestamp","reference_kind":"references","line":84,"col":29,"candidates":null,"file_path":"internal/gen/payrollpb/payroll.pb.go","language":"go","status":"failed","name_tail":"Timestamp"} +{"from_node_id":"struct:d541b867b240edf388feab5ff2002afd","reference_name":"Timestamp","reference_kind":"references","line":85,"col":29,"candidates":null,"file_path":"internal/gen/payrollpb/payroll.pb.go","language":"go","status":"failed","name_tail":"Timestamp"} +{"from_node_id":"struct:d541b867b240edf388feab5ff2002afd","reference_name":"UnknownFields","reference_kind":"references","line":76,"col":25,"candidates":null,"file_path":"internal/gen/payrollpb/payroll.pb.go","language":"go","status":"failed","name_tail":"UnknownFields"} +{"from_node_id":"struct:db17ae001afec7778c7fa0f59b53efa3","reference_name":"ClientConnInterface","reference_kind":"references","line":29,"col":9,"candidates":null,"file_path":"internal/gen/payrollpb/payroll_grpc.pb.go","language":"go","status":"failed","name_tail":"ClientConnInterface"} +{"from_node_id":"struct:e66f442bcf28c3bd0a3f42fbacb69b2a","reference_name":"MessageState","reference_kind":"references","line":52,"col":25,"candidates":null,"file_path":"internal/gen/payrollpb/payroll.pb.go","language":"go","status":"failed","name_tail":"MessageState"} +{"from_node_id":"struct:e66f442bcf28c3bd0a3f42fbacb69b2a","reference_name":"SizeCache","reference_kind":"references","line":53,"col":25,"candidates":null,"file_path":"internal/gen/payrollpb/payroll.pb.go","language":"go","status":"failed","name_tail":"SizeCache"} +{"from_node_id":"struct:e66f442bcf28c3bd0a3f42fbacb69b2a","reference_name":"UnknownFields","reference_kind":"references","line":54,"col":25,"candidates":null,"file_path":"internal/gen/payrollpb/payroll.pb.go","language":"go","status":"failed","name_tail":"UnknownFields"} +{"from_node_id":"struct:eed7116b6261c410c79b06f6b3a3aebe","reference_name":"Time","reference_kind":"references","line":20,"col":21,"candidates":null,"file_path":"internal/gen/fkit/payroll/payslip.go","language":"go","status":"failed","name_tail":"Time"} +{"from_node_id":"struct:eed7116b6261c410c79b06f6b3a3aebe","reference_name":"Time","reference_kind":"references","line":21,"col":21,"candidates":null,"file_path":"internal/gen/fkit/payroll/payslip.go","language":"go","status":"failed","name_tail":"Time"} +{"from_node_id":"struct:eed7116b6261c410c79b06f6b3a3aebe","reference_name":"Time","reference_kind":"references","line":26,"col":21,"candidates":null,"file_path":"internal/gen/fkit/payroll/payslip.go","language":"go","status":"failed","name_tail":"Time"} +{"from_node_id":"struct:eed7116b6261c410c79b06f6b3a3aebe","reference_name":"Time","reference_kind":"references","line":28,"col":21,"candidates":null,"file_path":"internal/gen/fkit/payroll/payslip.go","language":"go","status":"failed","name_tail":"Time"} +{"from_node_id":"struct:eed7116b6261c410c79b06f6b3a3aebe","reference_name":"Time","reference_kind":"references","line":29,"col":21,"candidates":null,"file_path":"internal/gen/fkit/payroll/payslip.go","language":"go","status":"failed","name_tail":"Time"} +{"from_node_id":"struct:f1c05936f2b11591d1f90efa9d981fa7","reference_name":"Time","reference_kind":"references","line":51,"col":21,"candidates":null,"file_path":"internal/domain/payroll/payslip.go","language":"go","status":"failed","name_tail":"Time"} +{"from_node_id":"struct:f1c05936f2b11591d1f90efa9d981fa7","reference_name":"Time","reference_kind":"references","line":52,"col":21,"candidates":null,"file_path":"internal/domain/payroll/payslip.go","language":"go","status":"failed","name_tail":"Time"} +{"from_node_id":"struct:f1c05936f2b11591d1f90efa9d981fa7","reference_name":"Time","reference_kind":"references","line":58,"col":21,"candidates":null,"file_path":"internal/domain/payroll/payslip.go","language":"go","status":"failed","name_tail":"Time"} {"from_node_id":"variable:02a9b4868be4f999189e4d930af29b95","reference_name":"grpc.ServiceDesc","reference_kind":"instantiates","line":95,"col":33,"candidates":null,"file_path":"internal/gen/payrollpb/payroll_grpc.pb.go","language":"go","status":"failed","name_tail":"ServiceDesc"} {"from_node_id":"variable:6b7bef84822056845bdabeb41a821f0a","reference_name":"errors.New","reference_kind":"calls","line":16,"col":21,"candidates":null,"file_path":"internal/usecase/payroll/cycle.go","language":"go","status":"failed","name_tail":"New","failure_reason":"unknown-receiver"} {"from_node_id":"variable:baa4aee814b380ae99f1b1829407b106","reference_name":"errors.New","reference_kind":"calls","line":19,"col":21,"candidates":null,"file_path":"internal/usecase/payroll/cycle.go","language":"go","status":"failed","name_tail":"New","failure_reason":"unknown-receiver"} diff --git a/__tests__/fixtures/golden/torture-multilang.dump b/__tests__/fixtures/golden/torture-multilang.dump index 9de005b74e..83c5bca70a 100644 --- a/__tests__/fixtures/golden/torture-multilang.dump +++ b/__tests__/fixtures/golden/torture-multilang.dump @@ -1,4 +1,4 @@ -== nodes (1838) +== nodes (1845) {"id":"class:0083dc18baa2b629e8572db20ba2b464","kind":"class","name":"Widget","qualified_name":"Widget","file_path":"torture.cpp","language":"cpp","start_line":98,"end_line":104,"start_column":0,"end_column":1,"docstring":"UE-macro shapes — every one below is recovered by the hoisted preParse\n(export macro, reflection markup, inline specifier, API member prefix).","signature":null,"visibility":null,"is_exported":1,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":null} {"id":"class:00e4c67aff13a714886744f6829e0cea","kind":"class","name":"Cfg","qualified_name":"Cfg","file_path":"TortureDoubleWalk.dart","language":"dart","start_line":60,"end_line":62,"start_column":0,"end_column":1,"docstring":null,"signature":null,"visibility":"public","is_exported":0,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":null} {"id":"class:01a3945fa12793f1af9ac531aedcc8cd","kind":"class","name":"Widget","qualified_name":"Widget","file_path":"TortureMini.dart","language":"dart","start_line":34,"end_line":52,"start_column":0,"end_column":1,"docstring":null,"signature":null,"visibility":"public","is_exported":0,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":null} @@ -596,7 +596,7 @@ {"id":"file:torture.c","kind":"file","name":"torture.c","qualified_name":"torture.c","file_path":"torture.c","language":"c","start_line":1,"end_line":204,"start_column":0,"end_column":0,"docstring":null,"signature":null,"visibility":null,"is_exported":0,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":null} {"id":"file:torture.cpp","kind":"file","name":"torture.cpp","qualified_name":"torture.cpp","file_path":"torture.cpp","language":"cpp","start_line":1,"end_line":171,"start_column":0,"end_column":0,"docstring":null,"signature":null,"visibility":null,"is_exported":0,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":null} {"id":"file:torture.dart","kind":"file","name":"torture.dart","qualified_name":"torture.dart","file_path":"torture.dart","language":"dart","start_line":1,"end_line":247,"start_column":0,"end_column":0,"docstring":null,"signature":null,"visibility":null,"is_exported":0,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":null} -{"id":"file:torture.go","kind":"file","name":"torture.go","qualified_name":"torture.go","file_path":"torture.go","language":"go","start_line":1,"end_line":147,"start_column":0,"end_column":0,"docstring":null,"signature":null,"visibility":null,"is_exported":0,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":null} +{"id":"file:torture.go","kind":"file","name":"torture.go","qualified_name":"torture.go","file_path":"torture.go","language":"go","start_line":1,"end_line":188,"start_column":0,"end_column":0,"docstring":null,"signature":null,"visibility":null,"is_exported":0,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":null} {"id":"file:torture.hpp","kind":"file","name":"torture.hpp","qualified_name":"torture.hpp","file_path":"torture.hpp","language":"cpp","start_line":1,"end_line":32,"start_column":0,"end_column":0,"docstring":null,"signature":null,"visibility":null,"is_exported":0,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":null} {"id":"file:torture.js","kind":"file","name":"torture.js","qualified_name":"torture.js","file_path":"torture.js","language":"javascript","start_line":1,"end_line":111,"start_column":0,"end_column":0,"docstring":null,"signature":null,"visibility":null,"is_exported":0,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":null} {"id":"file:torture.kt","kind":"file","name":"torture.kt","qualified_name":"torture.kt","file_path":"torture.kt","language":"kotlin","start_line":1,"end_line":307,"start_column":0,"end_column":0,"docstring":null,"signature":null,"visibility":null,"is_exported":0,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":null} @@ -628,7 +628,6 @@ {"id":"function:0aa0f690f342ae80a20985c7f14eab2e","kind":"function","name":"whereClause","qualified_name":"com.example.torture::whereClause","file_path":"torture.kt","language":"kotlin","start_line":274,"end_line":274,"start_column":0,"end_column":54,"docstring":null,"signature":"(): Int","visibility":"public","is_exported":1,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":"Int"} {"id":"function:0c1d3ee54fb89c70227c258f88e42210","kind":"function","name":"local_fn","qualified_name":"local_fn","file_path":"torture.R","language":"r","start_line":167,"end_line":167,"start_column":2,"end_column":27,"docstring":null,"signature":"()","visibility":null,"is_exported":0,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":null} {"id":"function:0de344286ef5d117cc0e4de7b71092f1","kind":"function","name":"localFn","qualified_name":"localFn","file_path":"torture.lua","language":"lua","start_line":23,"end_line":25,"start_column":0,"end_column":3,"docstring":"Block comment doc\nspanning two lines","signature":"(...)","visibility":null,"is_exported":0,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":null} -{"id":"function:0e1ad124e719c2d18615cda6816af46c","kind":"function","name":"TargetCb","qualified_name":"TargetCb","file_path":"torture.go","language":"go","start_line":122,"end_line":122,"start_column":0,"end_column":23,"docstring":null,"signature":"(n int)","visibility":null,"is_exported":1,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":null} {"id":"function:0ee9c05170d819c3032465e6e84710b8","kind":"function","name":"scriptFn","qualified_name":"scriptFn","file_path":"TortureScript.sc","language":"scala","start_line":2,"end_line":2,"start_column":0,"end_column":35,"docstring":null,"signature":"(): Int","visibility":"public","is_exported":0,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":"Int"} {"id":"function:0f2100f205cfad2b7709d99a570648a7","kind":"function","name":"fetch_data","qualified_name":"fetch_data","file_path":"torture.rs","language":"rust","start_line":194,"end_line":198,"start_column":0,"end_column":1,"docstring":"Block-doc for an async fn — isAsync must stay FALSE (dead-code hook).","signature":"(url: &str) -> Result","visibility":"public","is_exported":0,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":"Result"} {"id":"function:0f620fa18b10178b2f19c93a79ca33eb","kind":"function","name":"bodyTypes","qualified_name":"bodyTypes","file_path":"TortureSigs.dart","language":"dart","start_line":30,"end_line":38,"start_column":0,"end_column":24,"docstring":null,"signature":"void (Object x)","visibility":"public","is_exported":0,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":null} @@ -640,7 +639,6 @@ {"id":"function:11c7b584c938a133a0a90b82afcafbd9","kind":"function","name":"afterUnicode","qualified_name":"afterUnicode","file_path":"TortureVrefDart.dart","language":"dart","start_line":59,"end_line":61,"start_column":0,"end_column":27,"docstring":"π and émoji 🎯 in a comment","signature":"void (String s)","visibility":"public","is_exported":0,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":null} {"id":"function:1208905d9075e0385bf235f1e34697b1","kind":"function","name":"interpolated_doc","qualified_name":"interpolated_doc","file_path":"docstrings.py","language":"python","start_line":57,"end_line":59,"start_column":0,"end_column":12,"docstring":null,"signature":"()","visibility":null,"is_exported":1,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":null} {"id":"function:121e79a499d2427981d508cc90426407","kind":"function","name":"audit_ledger","qualified_name":"audit_ledger","file_path":"docstrings.py","language":"python","start_line":12,"end_line":13,"start_column":0,"end_column":12,"docstring":"Settle the nightly discrepancy with the bank.","signature":"()","visibility":null,"is_exported":1,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":null} -{"id":"function:140cc1d2e83fc5a1968f8058b5457dd1","kind":"function","name":"shadowed","qualified_name":"shadowed","file_path":"torture.go","language":"go","start_line":124,"end_line":127,"start_column":0,"end_column":1,"docstring":null,"signature":"()","visibility":null,"is_exported":0,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":null} {"id":"function:141b9348d2428090cbb42de6932b54ad","kind":"function","name":"afterImport","qualified_name":"afterImport","file_path":"TortureAnnotatedComments.dart","language":"dart","start_line":9,"end_line":9,"start_column":0,"end_column":18,"docstring":"A comment after the import.\nAnd one below the annotation.","signature":"void ()","visibility":"public","is_exported":0,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":null} {"id":"function:148b2a64a4ad451870ce9e7de7c95bfc","kind":"function","name":"positional","qualified_name":"positional","file_path":"TortureFnrefDart.dart","language":"dart","start_line":21,"end_line":21,"start_column":0,"end_column":17,"docstring":null,"signature":"void ()","visibility":"public","is_exported":0,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":null} {"id":"function:15790b08cab7e8d7cb5b8a474d94c359","kind":"function","name":"destructuringBody","qualified_name":"com.example.torture::destructuringBody","file_path":"torture.kt","language":"kotlin","start_line":251,"end_line":254,"start_column":0,"end_column":1,"docstring":null,"signature":"(p: Pair)","visibility":"public","is_exported":1,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":null} @@ -649,7 +647,6 @@ {"id":"function:16e7773d0267cca9529c1c7e89948222","kind":"function","name":"assignOnly","qualified_name":"assignOnly","file_path":"TortureVrefDart.dart","language":"dart","start_line":32,"end_line":34,"start_column":0,"end_column":17,"docstring":null,"signature":"void ()","visibility":"public","is_exported":0,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":null} {"id":"function:1762c7fa1f3cd4e18196d93c05883108","kind":"function","name":"cbA","qualified_name":"cbA","file_path":"torture.swift","language":"swift","start_line":111,"end_line":111,"start_column":0,"end_column":13,"docstring":null,"signature":null,"visibility":"internal","is_exported":0,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":null} {"id":"function:178c6f5073dbe3085b9a39b8c2723861","kind":"function","name":"describe","qualified_name":"describe","file_path":"torture.R","language":"r","start_line":78,"end_line":78,"start_column":0,"end_column":65,"docstring":null,"signature":"(obj)","visibility":null,"is_exported":0,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":null} -{"id":"function:179a74d774cb7efadf2594cebb29f4a9","kind":"function","name":"reads","qualified_name":"reads","file_path":"torture.go","language":"go","start_line":129,"end_line":131,"start_column":0,"end_column":1,"docstring":null,"signature":"() int","visibility":null,"is_exported":0,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":"int"} {"id":"function:17dec1e0fa812cc39e6fe41decdff8ce","kind":"function","name":"onSave","qualified_name":"handlerMap::onSave","file_path":"torture.js","language":"javascript","start_line":91,"end_line":91,"start_column":29,"end_column":55,"docstring":null,"signature":"()","visibility":null,"is_exported":0,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":null} {"id":"function:1932b46aef9b5a9c946962703eaf2c1c","kind":"function","name":"localWithNew","qualified_name":"localWithNew","file_path":"TortureDoubleWalk.dart","language":"dart","start_line":14,"end_line":17,"start_column":2,"end_column":20,"docstring":null,"signature":"int ()","visibility":"public","is_exported":0,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":"int"} {"id":"function:197783ccd4e0addc08a46e60af554114","kind":"function","name":"pragged","qualified_name":"pragged","file_path":"TortureDoubleWalk.dart","language":"dart","start_line":58,"end_line":58,"start_column":0,"end_column":14,"docstring":null,"signature":"void ()","visibility":"public","is_exported":0,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":null} @@ -714,7 +711,6 @@ {"id":"function:452af9ab50e94846870ef417047aa76b","kind":"function","name":"useUpdateWidgetMutation","qualified_name":"useUpdateWidgetMutation","file_path":"torture.tsx","language":"tsx","start_line":184,"end_line":184,"start_column":34,"end_column":57,"docstring":null,"signature":"= RTK Query generated hook","visibility":null,"is_exported":1,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":null} {"id":"function:4660fc91e385ee68f62141cd432fb335","kind":"function","name":"uninitShadow","qualified_name":"uninitShadow","file_path":"TortureVrefDart.dart","language":"dart","start_line":26,"end_line":30,"start_column":0,"end_column":19,"docstring":null,"signature":"void ()","visibility":"public","is_exported":0,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":null} {"id":"function:466dea0452e4cb4198514e9b7cc2907f","kind":"function","name":"afterVariable","qualified_name":"afterVariable","file_path":"TortureAnnotatedComments.dart","language":"dart","start_line":59,"end_line":59,"start_column":0,"end_column":20,"docstring":"A comment.","signature":"void ()","visibility":"public","is_exported":0,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":null} -{"id":"function:46864a1a62b2fd2a4e1657a52005c4e7","kind":"function","name":"mdLoad","qualified_name":"mdLoad","file_path":"torture.go","language":"go","start_line":144,"end_line":146,"start_column":0,"end_column":1,"docstring":null,"signature":"()","visibility":null,"is_exported":0,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":null} {"id":"function:46f110a0d62117633ba74019905246aa","kind":"function","name":"on_close","qualified_name":"on_close","file_path":"torture.cpp","language":"cpp","start_line":114,"end_line":114,"start_column":0,"end_column":18,"docstring":null,"signature":null,"visibility":null,"is_exported":1,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":null} {"id":"function:4759298ab8dfe6cd0b2c0574d59fdde3","kind":"function","name":"top_singleton","qualified_name":"top_singleton","file_path":"torture.rb","language":"ruby","start_line":228,"end_line":230,"start_column":0,"end_column":3,"docstring":null,"signature":null,"visibility":"private","is_exported":0,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":null} {"id":"function:497300b7c8854deb5abe80f7446e4447","kind":"function","name":"top","qualified_name":"top","file_path":"TortureAnnotatedDocs.dart","language":"dart","start_line":12,"end_line":12,"start_column":0,"end_column":10,"docstring":"Top function doc.","signature":"void ()","visibility":"public","is_exported":0,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":null} @@ -736,6 +732,7 @@ {"id":"function:522d9f8bb2b74fbe8b74a3a07afd73b8","kind":"function","name":"mdLoad","qualified_name":"App\\Services::mdLoad","file_path":"torture.php","language":"php","start_line":232,"end_line":235,"start_column":0,"end_column":1,"docstring":null,"signature":null,"visibility":"public","is_exported":1,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":null} {"id":"function:5346ad53a982756298bce064d4466e98","kind":"function","name":"syncGen","qualified_name":"syncGen","file_path":"TortureDoubleWalk.dart","language":"dart","start_line":46,"end_line":48,"start_column":0,"end_column":23,"docstring":null,"signature":"Iterable ()","visibility":"public","is_exported":0,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":"Iterable"} {"id":"function:53c0fffeaad4e0f1a99e53e75d5fc1e4","kind":"function","name":"mixedBlockThenLine","qualified_name":"mixedBlockThenLine","file_path":"TortureDocs.scala","language":"scala","start_line":12,"end_line":12,"start_column":0,"end_column":33,"docstring":"block doc\ntrailing line","signature":"(): Int","visibility":"public","is_exported":0,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":"Int"} +{"id":"function:55a555881f22d77e916122b15425f092","kind":"function","name":"shadowed","qualified_name":"shadowed","file_path":"torture.go","language":"go","start_line":165,"end_line":168,"start_column":0,"end_column":1,"docstring":null,"signature":"()","visibility":null,"is_exported":0,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":null} {"id":"function:55cede4db3e8d5f75ad247fc3ca8d566","kind":"function","name":"area","qualified_name":"area","file_path":"torture.R","language":"r","start_line":136,"end_line":136,"start_column":0,"end_column":18,"docstring":null,"signature":null,"visibility":null,"is_exported":0,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":null} {"id":"function:55dc9b62ca2dd87561c5e882ec386c0c","kind":"function","name":"afterAnno","qualified_name":"afterAnno","file_path":"TortureVrefDart.dart","language":"dart","start_line":53,"end_line":53,"start_column":0,"end_column":16,"docstring":"Doc broken.","signature":"void ()","visibility":"public","is_exported":0,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":null} {"id":"function:56cb1de0995a7b9d69ddf4fb79468d76","kind":"function","name":"om","qualified_name":"com.example.torture::caller::om","file_path":"torture.kt","language":"kotlin","start_line":228,"end_line":228,"start_column":8,"end_column":19,"docstring":null,"signature":"()","visibility":"public","is_exported":0,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":null} @@ -749,7 +746,6 @@ {"id":"function:5a1cba4779c5504c58fbd64f89d70b6e","kind":"function","name":"labeledLambda","qualified_name":"com.example.torture::labeledLambda","file_path":"torture.kt","language":"kotlin","start_line":270,"end_line":272,"start_column":0,"end_column":1,"docstring":null,"signature":"()","visibility":"public","is_exported":1,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":null} {"id":"function:5a7d206b3379379dcd0e8c8ee7fbb2e6","kind":"function","name":"prefixedRet","qualified_name":"prefixedRet","file_path":"torture.dart","language":"dart","start_line":51,"end_line":51,"start_column":0,"end_column":30,"docstring":null,"signature":"other ()","visibility":"public","is_exported":0,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":"other"} {"id":"function:5b434632abf9fbeb07e0a630ec66d9d3","kind":"function","name":"caller","qualified_name":"com.example.torture::caller","file_path":"torture.kt","language":"kotlin","start_line":180,"end_line":236,"start_column":0,"end_column":1,"docstring":null,"signature":"()","visibility":"public","is_exported":1,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":null} -{"id":"function:5caa38feff95389d550207e842f7ac7e","kind":"function","name":"useAlias","qualified_name":"useAlias","file_path":"torture.go","language":"go","start_line":101,"end_line":103,"start_column":0,"end_column":1,"docstring":null,"signature":"(a *Alias) LocalAlias","visibility":null,"is_exported":0,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":"LocalAlias"} {"id":"function:5dc21154b53bd116f5aeca7ef6be095b","kind":"function","name":"bodiless","qualified_name":"C::bodiless","file_path":"TortureAnnotatedDocs.dart","language":"dart","start_line":83,"end_line":83,"start_column":2,"end_column":17,"docstring":"Bodiless member doc.","signature":"void ()","visibility":"public","is_exported":0,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":null} {"id":"function:5dc6386ba18e3f1f04ce01163a8dd750","kind":"function","name":"emoji_caller","qualified_name":"emoji_caller","file_path":"torture.R","language":"r","start_line":204,"end_line":204,"start_column":0,"end_column":59,"docstring":null,"signature":"()","visibility":null,"is_exported":0,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":null} {"id":"function:5e11e2f2f13fc49082f194406a604caa","kind":"function","name":"doubleAnno","qualified_name":"doubleAnno","file_path":"torture.dart","language":"dart","start_line":25,"end_line":25,"start_column":0,"end_column":17,"docstring":null,"signature":"void ()","visibility":"public","is_exported":0,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":null} @@ -807,7 +803,10 @@ {"id":"function:806f3d4192b24f744ac921f4d6d3ac68","kind":"function","name":"unicodeNext","qualified_name":"unicodeNext","file_path":"TortureVrefDart.dart","language":"dart","start_line":56,"end_line":56,"start_column":0,"end_column":18,"docstring":"Kept doc.","signature":"void ()","visibility":"public","is_exported":0,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":null} {"id":"function:80c7293664161116a029e8aa43f2becf","kind":"function","name":"staticReads","qualified_name":"staticReads","file_path":"torture.swift","language":"swift","start_line":177,"end_line":184,"start_column":0,"end_column":1,"docstring":null,"signature":null,"visibility":"internal","is_exported":0,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":null} {"id":"function:80da340756dc392f312235faff12318c","kind":"function","name":"localFn","qualified_name":"com.example.torture::caller::localFn","file_path":"torture.kt","language":"kotlin","start_line":222,"end_line":222,"start_column":4,"end_column":26,"docstring":null,"signature":"(): Int","visibility":"public","is_exported":0,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":"Int"} +{"id":"function:815f561efb2f5946fda7806c34dbd966","kind":"function","name":"useAlias","qualified_name":"useAlias","file_path":"torture.go","language":"go","start_line":142,"end_line":144,"start_column":0,"end_column":1,"docstring":null,"signature":"(a *Alias) LocalAlias","visibility":null,"is_exported":0,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":"LocalAlias"} {"id":"function:81ba5a98d0931cbf162f4338fae53766","kind":"function","name":"reader","qualified_name":"reader","file_path":"TortureDoubleWalk.dart","language":"dart","start_line":64,"end_line":68,"start_column":0,"end_column":13,"docstring":null,"signature":"void ()","visibility":"public","is_exported":0,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":null} +{"id":"function:81cc5b0d788ee9727656191bb6a35597","kind":"function","name":"NewRegistry","qualified_name":"NewRegistry","file_path":"torture.go","language":"go","start_line":146,"end_line":153,"start_column":0,"end_column":1,"docstring":null,"signature":"() *Registry","visibility":null,"is_exported":1,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":"Registry"} +{"id":"function:8307a8a823f2c272e33236a2f73c9f60","kind":"function","name":"mdLoad","qualified_name":"mdLoad","file_path":"torture.go","language":"go","start_line":185,"end_line":187,"start_column":0,"end_column":1,"docstring":null,"signature":"()","visibility":null,"is_exported":0,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":null} {"id":"function:83c5dee82ba42b15ad5d74163798335f","kind":"function","name":"masked_entry","qualified_name":"masked_entry","file_path":"torture.c","language":"c","start_line":24,"end_line":24,"start_column":9,"end_column":48,"docstring":"Leading attribute macro — blanked by preParseCSource (#1211), so the real\nname survives on both arms.","signature":null,"visibility":null,"is_exported":1,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":"UINT32"} {"id":"function:8761b1046f98e14b1f36f385926edabf","kind":"function","name":"tuple_string","qualified_name":"tuple_string","file_path":"docstrings.py","language":"python","start_line":78,"end_line":80,"start_column":0,"end_column":12,"docstring":null,"signature":"()","visibility":null,"is_exported":1,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":null} {"id":"function:8809c136e5c07e098ad199e0ef72e4cb","kind":"function","name":"lambdaRet","qualified_name":"com.example.torture::lambdaRet","file_path":"torture.kt","language":"kotlin","start_line":34,"end_line":34,"start_column":0,"end_column":36,"docstring":null,"signature":"(): (Int) -> Unit","visibility":"public","is_exported":1,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":null} @@ -853,6 +852,7 @@ {"id":"function:a4b908646a5315f4505eec1514c9da0a","kind":"function","name":"plainDoc","qualified_name":"plainDoc","file_path":"torture.dart","language":"dart","start_line":17,"end_line":17,"start_column":0,"end_column":17,"docstring":"Plain comment doc.","signature":"String ()","visibility":"public","is_exported":0,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":"String"} {"id":"function:a6b241930489a440e4bc3a5a7f47d98a","kind":"function","name":"genericFn","qualified_name":"genericFn","file_path":"torture.luau","language":"luau","start_line":18,"end_line":20,"start_column":0,"end_column":3,"docstring":null,"signature":"(v: T): T","visibility":null,"is_exported":0,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":null} {"id":"function:a7e6f3daf2b9428e6be15b312b88381c","kind":"function","name":"nativeCount","qualified_name":"Store::nativeCount","file_path":"TortureDeclarationDocs.dart","language":"dart","start_line":26,"end_line":26,"start_column":11,"end_column":28,"docstring":"Block dartdoc on an external member.","signature":"int ()","visibility":"public","is_exported":0,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":"int"} +{"id":"function:a832b3ad2e6b57ff9463fbd6c86c5a97","kind":"function","name":"TargetCb","qualified_name":"TargetCb","file_path":"torture.go","language":"go","start_line":163,"end_line":163,"start_column":0,"end_column":23,"docstring":null,"signature":"(n int)","visibility":null,"is_exported":1,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":null} {"id":"function:a8b3ba1f61d34a0f609783e7365e5b87","kind":"function","name":"blankLineBetween","qualified_name":"blankLineBetween","file_path":"TortureDocs.scala","language":"scala","start_line":20,"end_line":20,"start_column":0,"end_column":31,"docstring":"detached","signature":"(): Int","visibility":"public","is_exported":0,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":"Int"} {"id":"function:a8c2c8f513bc437341958e1e409a8797","kind":"function","name":"shadowed_reader","qualified_name":"shadowed_reader","file_path":"torture.c","language":"c","start_line":68,"end_line":71,"start_column":0,"end_column":1,"docstring":"Local shadow of a file-scope const — the shadow prune drops HIGH_WATER as a\nvalue-ref target while LOW_WATER stays live.","signature":null,"visibility":null,"is_exported":1,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":null} {"id":"function:a946d3f4be94fcb7a892061e107ac66a","kind":"function","name":"annotated","qualified_name":"annotated","file_path":"torture.dart","language":"dart","start_line":21,"end_line":21,"start_column":0,"end_column":16,"docstring":"Kept past the annotation.","signature":"void ()","visibility":"public","is_exported":0,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":null} @@ -977,9 +977,9 @@ {"id":"function:fc39ac9d6fa99fdcacbc414210e777d6","kind":"function","name":"f_in_if","qualified_name":"f_in_if","file_path":"torture.R","language":"r","start_line":44,"end_line":44,"start_column":10,"end_column":33,"docstring":null,"signature":"()","visibility":null,"is_exported":0,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":null} {"id":"function:fcb3c4babe7cfee4371d8e472c3bde0b","kind":"function","name":"mod_method","qualified_name":"Documented::container_method::mod_method","file_path":"torture.rb","language":"ruby","start_line":193,"end_line":193,"start_column":6,"end_column":25,"docstring":null,"signature":null,"visibility":"public","is_exported":0,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":null} {"id":"function:fcd5e95c35b0d729f302762b3d2c7201","kind":"function","name":"cb_b","qualified_name":"cb_b","file_path":"torture.c","language":"c","start_line":50,"end_line":50,"start_column":0,"end_column":44,"docstring":null,"signature":null,"visibility":null,"is_exported":1,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":null} +{"id":"function:fd52d5daf195fabf0870d2a4c709d61f","kind":"function","name":"reads","qualified_name":"reads","file_path":"torture.go","language":"go","start_line":170,"end_line":172,"start_column":0,"end_column":1,"docstring":null,"signature":"() int","visibility":null,"is_exported":0,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":"int"} {"id":"function:fd9e1ad6a248dcc467e99c8f7c23127e","kind":"function","name":"curried","qualified_name":"curried","file_path":"torture.scala","language":"scala","start_line":16,"end_line":16,"start_column":0,"end_column":68,"docstring":null,"signature":"(a: Int): Int","visibility":"public","is_exported":0,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":"Int"} {"id":"function:fdace61258b1ce2e795b000effa9d472","kind":"function","name":"bucket_chains","qualified_name":"bucket_chains","file_path":"torture.py","language":"python","start_line":58,"end_line":63,"start_column":0,"end_column":28,"docstring":"--- call receivers (#1683) ---------------------------------------------------","signature":"(d, k, v)","visibility":null,"is_exported":1,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":null} -{"id":"function:ffbfbea1bf90b2536f05eed532eb53ce","kind":"function","name":"NewRegistry","qualified_name":"NewRegistry","file_path":"torture.go","language":"go","start_line":105,"end_line":112,"start_column":0,"end_column":1,"docstring":null,"signature":"() *Registry","visibility":null,"is_exported":1,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":"Registry"} {"id":"function:ffcd4f74cccf7789d0592c11c1b4cf65","kind":"function","name":"handler2","qualified_name":"handler2","file_path":"torture.rs","language":"rust","start_line":234,"end_line":234,"start_column":0,"end_column":16,"docstring":null,"signature":"()","visibility":"private","is_exported":0,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":null} {"id":"import:00014f95d514cd4a9297fb78c6d267a7","kind":"import","name":"com","qualified_name":"com","file_path":"torture.scala","language":"scala","start_line":3,"end_line":3,"start_column":0,"end_column":35,"docstring":null,"signature":"import com.example.other.OtherClass","visibility":null,"is_exported":0,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":null} {"id":"import:014653bb4cdb1b43354937ba89cb80b5","kind":"import","name":"java.util.Map","qualified_name":"com.example.torture::java.util.Map","file_path":"Torture.java","language":"java","start_line":10,"end_line":10,"start_column":0,"end_column":21,"docstring":null,"signature":"import java.util.Map;","visibility":null,"is_exported":0,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":null} @@ -1108,18 +1108,19 @@ {"id":"import:fc9f9b76e80a941cfd067660dce5b24b","kind":"import","name":"package:foo/util.dart","qualified_name":"package:foo/util.dart","file_path":"TortureVrefDart.dart","language":"dart","start_line":1,"end_line":1,"start_column":0,"end_column":39,"docstring":null,"signature":"import 'package:foo/util.dart' as util;","visibility":null,"is_exported":0,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":null} {"id":"import:ff41135c2cec39441d276072d4dbd64a","kind":"import","name":"Config","qualified_name":"Config","file_path":"torture.luau","language":"luau","start_line":11,"end_line":11,"start_column":25,"end_column":54,"docstring":null,"signature":"require(script.Parent.Config)","visibility":null,"is_exported":0,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":null} {"id":"interface:24159e084fc50d320c624ae5b6655041","kind":"interface","name":"Shape","qualified_name":"App\\Services::Shape","file_path":"torture.php","language":"php","start_line":180,"end_line":185,"start_column":0,"end_column":1,"docstring":null,"signature":null,"visibility":null,"is_exported":1,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":null} +{"id":"interface:3003e30a3fc9ee8bf1f1153918085038","kind":"interface","name":"IfaceAlias","qualified_name":"IfaceAlias","file_path":"torture.go","language":"go","start_line":113,"end_line":115,"start_column":5,"end_column":1,"docstring":null,"signature":null,"visibility":null,"is_exported":1,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":null} +{"id":"interface:3970ad34905c85bf731cae6e1386687f","kind":"interface","name":"Repo","qualified_name":"Repo","file_path":"torture.go","language":"go","start_line":83,"end_line":87,"start_column":5,"end_column":1,"docstring":"An interface method references the types its signature names, but the\ninterface's own type parameters and the predeclared types.","signature":null,"visibility":null,"is_exported":1,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":null} +{"id":"interface:479db15a71788832458ca8ffe80aba83","kind":"interface","name":"Number","qualified_name":"Number","file_path":"torture.go","language":"go","start_line":89,"end_line":91,"start_column":5,"end_column":1,"docstring":null,"signature":null,"visibility":null,"is_exported":1,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":null} {"id":"interface:55f4df0844e34d3f058bf4546af2ed95","kind":"interface","name":"SealedIface","qualified_name":"com.example.torture::SealedIface","file_path":"torture.kt","language":"kotlin","start_line":122,"end_line":122,"start_column":0,"end_column":28,"docstring":null,"signature":null,"visibility":null,"is_exported":1,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":null} -{"id":"interface:5a28b97ecb59911dbe27ad63e859459d","kind":"interface","name":"Exact","qualified_name":"Exact","file_path":"torture.go","language":"go","start_line":52,"end_line":52,"start_column":5,"end_column":29,"docstring":null,"signature":null,"visibility":null,"is_exported":1,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":null} +{"id":"interface:6ed108f5ca6c8f6b9f40a746e9396c03","kind":"interface","name":"Core","qualified_name":"Core","file_path":"torture.go","language":"go","start_line":72,"end_line":79,"start_column":5,"end_column":1,"docstring":null,"signature":null,"visibility":null,"is_exported":1,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":null} {"id":"interface:7101ee1e3e068d01630d3b0128a15b2d","kind":"interface","name":"Inherited","qualified_name":"Inherited","file_path":"torture.swift","language":"swift","start_line":140,"end_line":143,"start_column":0,"end_column":1,"docstring":null,"signature":null,"visibility":null,"is_exported":0,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":null} {"id":"interface:7423d683e426467682cab43a0f65b9a1","kind":"interface","name":"RequestDelegate","qualified_name":"RequestDelegate","file_path":"torture.swift","language":"swift","start_line":52,"end_line":56,"start_column":0,"end_column":1,"docstring":null,"signature":null,"visibility":null,"is_exported":0,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":null} -{"id":"interface:8045ff3999885f68bd3b9b0e8709aeeb","kind":"interface","name":"IfaceAlias","qualified_name":"IfaceAlias","file_path":"torture.go","language":"go","start_line":72,"end_line":74,"start_column":5,"end_column":1,"docstring":null,"signature":null,"visibility":null,"is_exported":1,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":null} -{"id":"interface:87965a8e467d41375154fe8ae108b529","kind":"interface","name":"Core","qualified_name":"Core","file_path":"torture.go","language":"go","start_line":39,"end_line":46,"start_column":5,"end_column":1,"docstring":null,"signature":null,"visibility":null,"is_exported":1,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":null} {"id":"interface:99971b764b215730f05d3e4892162ca7","kind":"interface","name":"Shape","qualified_name":"com.example.torture::Shape","file_path":"Torture.java","language":"java","start_line":126,"end_line":128,"start_column":0,"end_column":1,"docstring":null,"signature":null,"visibility":null,"is_exported":0,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":null} {"id":"interface:9bd1b24347e7ea5b41e0f709184263f2","kind":"interface","name":"Listener","qualified_name":"com.example.torture::TortureService::Listener","file_path":"Torture.java","language":"java","start_line":103,"end_line":105,"start_column":2,"end_column":3,"docstring":null,"signature":null,"visibility":null,"is_exported":0,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":null} {"id":"interface:a05baa699fc9324830859524f09604c9","kind":"interface","name":"Shape","qualified_name":"Shape","file_path":"torture.tsx","language":"tsx","start_line":66,"end_line":70,"start_column":7,"end_column":1,"docstring":null,"signature":null,"visibility":null,"is_exported":1,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":null} {"id":"interface:a5b7485366f313123bd3a63c11116ec0","kind":"interface","name":"Drawable","qualified_name":"com.example.torture::Drawable","file_path":"torture.kt","language":"kotlin","start_line":111,"end_line":115,"start_column":0,"end_column":1,"docstring":null,"signature":null,"visibility":null,"is_exported":1,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":null} {"id":"interface:ac832273445e5a59ca5679d25afdcdc1","kind":"interface","name":"IWidgetRepo","qualified_name":"Torture.Alpha::IWidgetRepo","file_path":"Torture.cs","language":"csharp","start_line":158,"end_line":163,"start_column":4,"end_column":5,"docstring":null,"signature":null,"visibility":null,"is_exported":0,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":null} -{"id":"interface:c15bd0cb4f4a33ae49f280e29878fb61","kind":"interface","name":"Number","qualified_name":"Number","file_path":"torture.go","language":"go","start_line":48,"end_line":50,"start_column":5,"end_column":1,"docstring":null,"signature":null,"visibility":null,"is_exported":1,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":null} +{"id":"interface:b5773212ca0e5396a677e9062f68d204","kind":"interface","name":"Exact","qualified_name":"Exact","file_path":"torture.go","language":"go","start_line":93,"end_line":93,"start_column":5,"end_column":29,"docstring":null,"signature":null,"visibility":null,"is_exported":1,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":null} {"id":"interface:fa3f5e7c386fbbd874e9de21b328cc5c","kind":"interface","name":"Marker","qualified_name":"com.example.torture::Marker","file_path":"Torture.java","language":"java","start_line":130,"end_line":132,"start_column":0,"end_column":1,"docstring":null,"signature":null,"visibility":null,"is_exported":0,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":null} {"id":"method:008f2ecd9ce97a5947e4c945b89814b6","kind":"method","name":"prev","qualified_name":"Point::prev","file_path":"TortureDeclarationDocs.dart","language":"dart","start_line":62,"end_line":62,"start_column":2,"end_column":28,"docstring":null,"signature":"(this.x, this.y)","visibility":"public","is_exported":0,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":"Point"} {"id":"method:033ac2ba34fbab2bc8e4448a87dd89ce","kind":"method","name":"computed","qualified_name":"Holder::computed","file_path":"TortureDoubleWalk.dart","language":"dart","start_line":34,"end_line":34,"start_column":2,"end_column":18,"docstring":null,"signature":"int","visibility":"public","is_exported":0,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":"int"} @@ -1175,6 +1176,7 @@ {"id":"method:2482c6a39c7a71c514ac4eda10980efa","kind":"method","name":"done","qualified_name":"Builder::done","file_path":"torture.swift","language":"swift","start_line":63,"end_line":63,"start_column":2,"end_column":36,"docstring":null,"signature":null,"visibility":"internal","is_exported":0,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":"Builder"} {"id":"method:24c035e708d78d21a14444ab77e5c1e5","kind":"method","name":"setName","qualified_name":"com.example.torture::LombokBean::setName","file_path":"Torture.java","language":"java","start_line":110,"end_line":110,"start_column":17,"end_column":21,"docstring":"Lombok-generated (@Data)","signature":"void setName(String name)","visibility":"public","is_exported":0,"is_async":0,"is_static":0,"is_abstract":0,"decorators":"[\"lombok\"]","type_parameters":null,"return_type":null} {"id":"method:24c8aca9dc4f3844a403d5753ed00b92","kind":"method","name":"chained","qualified_name":"M.sub.deep::chained","file_path":"torture.lua","language":"lua","start_line":60,"end_line":62,"start_column":0,"end_column":3,"docstring":null,"signature":"(x)","visibility":null,"is_exported":0,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":null} +{"id":"method:24ccc96de44e1d4e1608658cfe083a33","kind":"method","name":"Render","qualified_name":"Widget::Render","file_path":"torture.go","language":"go","start_line":159,"end_line":161,"start_column":0,"end_column":1,"docstring":null,"signature":"() string","visibility":null,"is_exported":1,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":"string"} {"id":"method:24f4495de2244cb913781f4fb1a18226","kind":"method","name":"selfRet","qualified_name":"App\\Services::Documented::selfRet","file_path":"torture.php","language":"php","start_line":64,"end_line":67,"start_column":4,"end_column":5,"docstring":null,"signature":null,"visibility":"public","is_exported":0,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":"self"} {"id":"method:256f83a3935f0101fcb9728044b46196","kind":"method","name":"register","qualified_name":"com.example.torture::Registry::register","file_path":"torture.kt","language":"kotlin","start_line":147,"end_line":147,"start_column":4,"end_column":49,"docstring":null,"signature":"(w: WidgetK)","visibility":"public","is_exported":0,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":null} {"id":"method:2596782eaecc1c154a4fdc2334a968a4","kind":"method","name":"reads","qualified_name":"StaticReads::reads","file_path":"torture.scala","language":"scala","start_line":164,"end_line":171,"start_column":2,"end_column":3,"docstring":null,"signature":"(): Unit","visibility":"public","is_exported":0,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":"Unit"} @@ -1284,6 +1286,7 @@ {"id":"method:5725e0ae1651a9d377cc184a5f890d67","kind":"method","name":"shadower","qualified_name":"Documented::shadower","file_path":"torture.rb","language":"ruby","start_line":208,"end_line":211,"start_column":2,"end_column":5,"docstring":null,"signature":null,"visibility":"public","is_exported":0,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":null} {"id":"method:57860865154ab9d9c7dc0dd14f5eaa79","kind":"method","name":"reader_one","qualified_name":"Documented::reader_one","file_path":"torture.rb","language":"ruby","start_line":198,"end_line":200,"start_column":2,"end_column":5,"docstring":null,"signature":null,"visibility":"public","is_exported":0,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":null} {"id":"method:581cacf02c5580f95fc293758de7be4e","kind":"method","name":"run","qualified_name":"com.example.torture::TortureService::fieldAnonClass::::run","file_path":"Torture.java","language":"java","start_line":28,"end_line":31,"start_column":4,"end_column":5,"docstring":null,"signature":"void ()","visibility":"public","is_exported":0,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":null} +{"id":"method:598927e1a898855d3029efb1ca0f4966","kind":"method","name":"Self","qualified_name":"Repo::Self","file_path":"torture.go","language":"go","start_line":86,"end_line":86,"start_column":1,"end_column":15,"docstring":null,"signature":"() Repo[T]","visibility":null,"is_exported":0,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":"Repo"} {"id":"method:5a7084ca31a4c3f066eae18a918d54f8","kind":"method","name":"area","qualified_name":"Widget::area","file_path":"TortureMini.dart","language":"dart","start_line":48,"end_line":48,"start_column":2,"end_column":14,"docstring":null,"signature":"int","visibility":"public","is_exported":0,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":"int"} {"id":"method:5c2e8db84b29af68fc13a77bb8cbbc71","kind":"method","name":"stop","qualified_name":"Handle::stop","file_path":"torture.tsx","language":"tsx","start_line":79,"end_line":79,"start_column":2,"end_column":18,"docstring":null,"signature":"stop: () => void","visibility":null,"is_exported":0,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":null} {"id":"method:5c7ee5f7df4ea497aa603662d6664c48","kind":"method","name":"draw","qualified_name":"com.example.torture::SubK::draw","file_path":"torture.kt","language":"kotlin","start_line":104,"end_line":104,"start_column":4,"end_column":26,"docstring":null,"signature":"()","visibility":"public","is_exported":0,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":null} @@ -1301,6 +1304,7 @@ {"id":"method:64996a1706443006da9f4a15b38abbe2","kind":"method","name":"render","qualified_name":"Container::render","file_path":"torture.rs","language":"rust","start_line":117,"end_line":117,"start_column":4,"end_column":23,"docstring":null,"signature":"(&self)","visibility":"private","is_exported":0,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":null} {"id":"method:64c1b80c824cce93f8b404c23c64eadb","kind":"method","name":"label","qualified_name":"com.example.torture::Http::label","file_path":"torture.kt","language":"kotlin","start_line":136,"end_line":136,"start_column":4,"end_column":32,"docstring":null,"signature":"(): String","visibility":"public","is_exported":0,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":"String"} {"id":"method:657476865c1d18e13cef7d2249fab0e5","kind":"method","name":"__construct","qualified_name":"App\\Services::Documented::__construct","file_path":"torture.php","language":"php","start_line":49,"end_line":51,"start_column":4,"end_column":5,"docstring":null,"signature":null,"visibility":"public","is_exported":0,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":null} +{"id":"method:67012fcd3f5d759fab7fa829faf85af2","kind":"method","name":"Marshal","qualified_name":"Core::Marshal","file_path":"torture.go","language":"go","start_line":77,"end_line":77,"start_column":1,"end_column":31,"docstring":null,"signature":"(v any) ([]byte, error)","visibility":null,"is_exported":0,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":null} {"id":"method:6915f37555573a844fad9f0204da57bc","kind":"method","name":"run","qualified_name":"com.example.torture::TortureService::TortureService::::run","file_path":"Torture.java","language":"java","start_line":43,"end_line":46,"start_column":6,"end_column":7,"docstring":null,"signature":"void ()","visibility":"public","is_exported":0,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":null} {"id":"method:699f626fc6f4bd965e80eb3fb6831ddb","kind":"method","name":"json","qualified_name":"ProviderT::json","file_path":"TortureConstCtors.dart","language":"dart","start_line":25,"end_line":25,"start_column":2,"end_column":75,"docstring":null,"signature":"(Map json)","visibility":"public","is_exported":0,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":"ProviderT"} {"id":"method:6a4e21b6c6d90666a239ba82af310544","kind":"method","name":"run","qualified_name":"CurryCall::run","file_path":"TortureMisc.scala","language":"scala","start_line":16,"end_line":21,"start_column":2,"end_column":3,"docstring":null,"signature":"(): Unit","visibility":"public","is_exported":0,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":"Unit"} @@ -1308,12 +1312,10 @@ {"id":"method:6d1eec9ae656dd2a0648d3d0fab88219","kind":"method","name":"StaticHandler","qualified_name":"Torture.Alpha::TortureClass::StaticHandler","file_path":"Torture.cs","language":"csharp","start_line":67,"end_line":67,"start_column":8,"end_column":47,"docstring":null,"signature":null,"visibility":"private","is_exported":0,"is_async":0,"is_static":1,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":null} {"id":"method:6d7307466b96d91d4250060ab9832404","kind":"method","name":"onEvent","qualified_name":"Plain::onEvent","file_path":"torture.tsx","language":"tsx","start_line":62,"end_line":62,"start_column":2,"end_column":14,"docstring":null,"signature":"()","visibility":null,"is_exported":0,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":null} {"id":"method:6d9dc963c222f94eab797e7bbd0151d3","kind":"method","name":"localHost","qualified_name":"CallSites::localHost","file_path":"torture.scala","language":"scala","start_line":154,"end_line":160,"start_column":2,"end_column":3,"docstring":null,"signature":"(): Int","visibility":"public","is_exported":0,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":"Int"} -{"id":"method:6fc4e3ad2b4db571a700d39f81c2c090","kind":"method","name":"Marshal","qualified_name":"Core::Marshal","file_path":"torture.go","language":"go","start_line":44,"end_line":44,"start_column":1,"end_column":31,"docstring":null,"signature":"(v any) ([]byte, error)","visibility":null,"is_exported":0,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":null} {"id":"method:6febee4cfe85097558083cae10bd506a","kind":"method","name":"parse","qualified_name":"StatusT::parse","file_path":"torture.dart","language":"dart","start_line":205,"end_line":205,"start_column":2,"end_column":29,"docstring":null,"signature":"StatusT (int c)","visibility":"public","is_exported":0,"is_async":0,"is_static":1,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":"StatusT"} {"id":"method:708ce73244e05d4377ef1c40a8d916e3","kind":"method","name":"unnamedTarget","qualified_name":"ProviderT::unnamedTarget","file_path":"TortureConstCtors.dart","language":"dart","start_line":31,"end_line":31,"start_column":2,"end_column":50,"docstring":null,"signature":"()","visibility":"public","is_exported":0,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":"ProviderT"} {"id":"method:71f85d20982180a51528b4d3198ef659","kind":"method","name":"attached","qualified_name":"M::attached","file_path":"torture.lua","language":"lua","start_line":52,"end_line":54,"start_column":1,"end_column":4,"docstring":null,"signature":"(q)","visibility":null,"is_exported":0,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":null} {"id":"method:7231bc149b5bd7a542e2abad6e64605f","kind":"method","name":"alpha","qualified_name":"H2::alpha","file_path":"TortureFnref.scala","language":"scala","start_line":16,"end_line":16,"start_column":2,"end_column":24,"docstring":null,"signature":"(): Unit","visibility":"public","is_exported":0,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":"Unit"} -{"id":"method:72417d24bc1311c2e420094c5d05c459","kind":"method","name":"Render","qualified_name":"Widget::Render","file_path":"torture.go","language":"go","start_line":118,"end_line":120,"start_column":0,"end_column":1,"docstring":null,"signature":"() string","visibility":null,"is_exported":1,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":"string"} {"id":"method:72cb204a2502f0fc52da51fc83084ef6","kind":"method","name":"hook","qualified_name":"App\\Services::AbstractBase::hook","file_path":"torture.php","language":"php","start_line":218,"end_line":218,"start_column":4,"end_column":45,"docstring":null,"signature":null,"visibility":"protected","is_exported":0,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":null} {"id":"method:72f15a456926768949344a03c531d90d","kind":"method","name":"opposite","qualified_name":"com.example.torture::TortureService::Direction::opposite","file_path":"Torture.java","language":"java","start_line":77,"end_line":79,"start_column":4,"end_column":5,"docstring":null,"signature":"Direction ()","visibility":null,"is_exported":0,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":"Direction"} {"id":"method:736a454a1f159019a862854710311b0c","kind":"method","name":"Peek","qualified_name":"Meter::Peek","file_path":"torture.hpp","language":"cpp","start_line":24,"end_line":24,"start_column":14,"end_column":50,"docstring":null,"signature":null,"visibility":"public","is_exported":0,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":null} @@ -1347,6 +1349,7 @@ {"id":"method:83f5ff48266a5d96c4d5b98a95728023","kind":"method","name":"apply","qualified_name":"com.example.torture::TortureService::Step::NEXT::apply","file_path":"Torture.java","language":"java","start_line":84,"end_line":87,"start_column":6,"end_column":7,"docstring":null,"signature":"int (int at)","visibility":null,"is_exported":0,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":null} {"id":"method:846b59388a77b469427475c32a0d11a3","kind":"method","name":"dedup","qualified_name":"Array::dedup","file_path":"torture.swift","language":"swift","start_line":67,"end_line":67,"start_column":2,"end_column":36,"docstring":null,"signature":null,"visibility":"internal","is_exported":0,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":null} {"id":"method:8483571327ac38d3149266645da49b87","kind":"method","name":"wire","qualified_name":"H2::wire","file_path":"TortureFnref.scala","language":"scala","start_line":20,"end_line":25,"start_column":2,"end_column":3,"docstring":null,"signature":"(): Unit","visibility":"public","is_exported":0,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":"Unit"} +{"id":"method:849d12c566dceb8c4bfcf1e81b828752","kind":"method","name":"Render","qualified_name":"IfaceAlias::Render","file_path":"torture.go","language":"go","start_line":114,"end_line":114,"start_column":1,"end_column":16,"docstring":null,"signature":"() string","visibility":null,"is_exported":0,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":"string"} {"id":"method:84b1066798bf4890531cf6d4cd0b61b2","kind":"method","name":"make","qualified_name":"AFError::make","file_path":"torture.swift","language":"swift","start_line":49,"end_line":49,"start_column":2,"end_column":56,"docstring":null,"signature":null,"visibility":"internal","is_exported":0,"is_async":0,"is_static":1,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":"AFError"} {"id":"method:8548d1a1ae6a218367c89732ef65fd41","kind":"method","name":"instance","qualified_name":"ObjectFirst::instance","file_path":"ScalaCompanions.scala","language":"scala","start_line":5,"end_line":5,"start_column":2,"end_column":25,"docstring":null,"signature":"(): Int","visibility":"public","is_exported":0,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":"Int"} {"id":"method:85900113e22446c44e33f53abe4c7c18","kind":"method","name":"instance","qualified_name":"Config::instance","file_path":"TortureReadsTypes.dart","language":"dart","start_line":78,"end_line":78,"start_column":2,"end_column":28,"docstring":null,"signature":"Config","visibility":"public","is_exported":0,"is_async":0,"is_static":1,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":"Config"} @@ -1382,7 +1385,6 @@ {"id":"method:9211cf8bfe7afb9ef1178048ba02bf75","kind":"method","name":"toString","qualified_name":"Mode::toString","file_path":"TortureAnnotatedComments.dart","language":"dart","start_line":167,"end_line":167,"start_column":2,"end_column":19,"docstring":"A comment.","signature":"String ()","visibility":"public","is_exported":0,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":"String"} {"id":"method:9261c793bb9fc642ab27474918702485","kind":"method","name":"g","qualified_name":"decl_types::Bar::g","file_path":"torture.cpp","language":"cpp","start_line":121,"end_line":121,"start_column":12,"end_column":23,"docstring":null,"signature":null,"visibility":null,"is_exported":0,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":null} {"id":"method:926288bc50b23061234ae22e7a64157e","kind":"method","name":"km","qualified_name":"Meters::km","file_path":"TortureAnnotatedDocs.dart","language":"dart","start_line":169,"end_line":169,"start_column":2,"end_column":13,"docstring":"Extension type member doc.","signature":"double ()","visibility":"public","is_exported":0,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":"double"} -{"id":"method:92741f1ace46d5b7eeb9715c9a1098f9","kind":"method","name":"Render","qualified_name":"IfaceAlias::Render","file_path":"torture.go","language":"go","start_line":73,"end_line":73,"start_column":1,"end_column":16,"docstring":null,"signature":"() string","visibility":null,"is_exported":0,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":"string"} {"id":"method:92a8713561f12be598ec1528262af25b","kind":"method","name":"push","qualified_name":"Stack::push","file_path":"torture.R","language":"r","start_line":99,"end_line":102,"start_column":4,"end_column":5,"docstring":null,"signature":"(x)","visibility":null,"is_exported":0,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":null} {"id":"method:93186283b69cc2f35644199f0963df2b","kind":"method","name":"assigned","qualified_name":"M::assigned","file_path":"torture.lua","language":"lua","start_line":67,"end_line":69,"start_column":13,"end_column":3,"docstring":null,"signature":"(z)","visibility":null,"is_exported":0,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":null} {"id":"method:93da452ed3de4387bac858c8e967a897","kind":"method","name":"nm","qualified_name":"Nested1::nm","file_path":"TortureMisc.scala","language":"scala","start_line":2,"end_line":2,"start_column":18,"end_column":35,"docstring":null,"signature":"(): Int","visibility":"public","is_exported":0,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":"Int"} @@ -1411,6 +1413,8 @@ {"id":"method:a384d29bf9bd230adf42b24d2846de6f","kind":"method","name":"m","qualified_name":"A::m","file_path":"TortureMisc.scala","language":"scala","start_line":23,"end_line":23,"start_column":29,"end_column":45,"docstring":null,"signature":"(): Int","visibility":"public","is_exported":0,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":"Int"} {"id":"method:a4d5cdb280703ee014c0dcd82cf09306","kind":"method","name":"wire","qualified_name":"Documented::wire","file_path":"torture.rb","language":"ruby","start_line":117,"end_line":123,"start_column":2,"end_column":5,"docstring":null,"signature":null,"visibility":"public","is_exported":0,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":null} {"id":"method:a590c5f459d7f6915b37eb92e75a1d83","kind":"method","name":"calls_zoo","qualified_name":"Documented::calls_zoo","file_path":"torture.rb","language":"ruby","start_line":125,"end_line":160,"start_column":2,"end_column":5,"docstring":null,"signature":null,"visibility":"public","is_exported":0,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":null} +{"id":"method:a5cd5e67746962200f8230ebedb5413e","kind":"method","name":"Each","qualified_name":"Repo::Each","file_path":"torture.go","language":"go","start_line":85,"end_line":85,"start_column":1,"end_column":47,"docstring":null,"signature":"(fn func(T, *Stack[int]) bool) []pkga.Item","visibility":null,"is_exported":0,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":null} +{"id":"method:a6d269b87546a3383d51ca2de232a1de","kind":"method","name":"Push","qualified_name":"Stack::Push","file_path":"torture.go","language":"go","start_line":155,"end_line":157,"start_column":0,"end_column":1,"docstring":null,"signature":"(item T)","visibility":null,"is_exported":1,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":null} {"id":"method:a7103764da0854afee05bc7d100478a4","kind":"method","name":"typed","qualified_name":"ProviderT::typed","file_path":"TortureConstCtors.dart","language":"dart","start_line":43,"end_line":50,"start_column":2,"end_column":34,"docstring":null,"signature":"Object (dynamic box)","visibility":"public","is_exported":0,"is_async":0,"is_static":1,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":"Object"} {"id":"method:a718dbc13c2e00a42febe0fbdce991be","kind":"method","name":"pm","qualified_name":"App\\Services::Documented::nester::Poly::pm","file_path":"torture.php","language":"php","start_line":151,"end_line":154,"start_column":16,"end_column":17,"docstring":null,"signature":null,"visibility":"public","is_exported":0,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":null} {"id":"method:a7b6861e2ff780d68310f545ca791d3c","kind":"method","name":"compare","qualified_name":"WidgetS::compare","file_path":"torture.scala","language":"scala","start_line":58,"end_line":58,"start_column":2,"end_column":52,"docstring":null,"signature":"(that: WidgetS): Int","visibility":"public","is_exported":0,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":"Int"} @@ -1424,7 +1428,6 @@ {"id":"method:aa3a8f86d1972af5856f74de23c7c284","kind":"method","name":"afterField","qualified_name":"C::afterField","file_path":"TortureAnnotatedComments.dart","language":"dart","start_line":122,"end_line":122,"start_column":2,"end_column":19,"docstring":"A comment after a field.","signature":"void ()","visibility":"public","is_exported":0,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":null} {"id":"method:ab213ee53e8eb8093551b4d30c73f026","kind":"method","name":"`strange def`","qualified_name":"`Weird Name`::`strange def`","file_path":"TortureMisc.scala","language":"scala","start_line":13,"end_line":13,"start_column":21,"end_column":49,"docstring":null,"signature":"(): Int","visibility":"public","is_exported":0,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":"Int"} {"id":"method:ac9d754fee3741f21584a0086c577453","kind":"method","name":"clone_self","qualified_name":"Widget::clone_self","file_path":"torture.rs","language":"rust","start_line":85,"end_line":92,"start_column":4,"end_column":5,"docstring":null,"signature":"(&self) -> Self","visibility":"private","is_exported":0,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":"self"} -{"id":"method:ae63e6f68d18ae3e3794926b4f75768b","kind":"method","name":"Push","qualified_name":"Stack::Push","file_path":"torture.go","language":"go","start_line":114,"end_line":116,"start_column":0,"end_column":1,"docstring":null,"signature":"(item T)","visibility":null,"is_exported":1,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":null} {"id":"method:afca03b4aca12c9f04530a20d67acad7","kind":"method","name":"lm","qualified_name":"factory::LocalCls::lm","file_path":"torture.R","language":"r","start_line":124,"end_line":124,"start_column":50,"end_column":73,"docstring":null,"signature":"()","visibility":null,"is_exported":0,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":null} {"id":"method:aff4cbff9ff5e0d8d44b76d6b40cb120","kind":"method","name":"WithLocal","qualified_name":"Torture.Alpha::TortureClass::WithLocal","file_path":"Torture.cs","language":"csharp","start_line":134,"end_line":138,"start_column":8,"end_column":9,"docstring":null,"signature":null,"visibility":"public","is_exported":0,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":null} {"id":"method:b02eab5f6eaac34cea7b2d8b5f76f0bf","kind":"method","name":"Reader","qualified_name":"Torture.Alpha::TortureClass::Reader","file_path":"Torture.cs","language":"csharp","start_line":144,"end_line":148,"start_column":8,"end_column":9,"docstring":null,"signature":null,"visibility":"public","is_exported":0,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":null} @@ -1479,6 +1482,7 @@ {"id":"method:d2641bcfda7a0ae7faff0c9555283d76","kind":"method","name":"calls","qualified_name":"Chains::calls","file_path":"TortureCommentChains.dart","language":"dart","start_line":27,"end_line":57,"start_column":2,"end_column":56,"docstring":null,"signature":"void (WidgetTester tester, Box box, List xs)","visibility":"public","is_exported":0,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":null} {"id":"method:d4d1bdff912565cf5eb03756e02aaa26","kind":"method","name":"c","qualified_name":"C::c","file_path":"TortureAnnotatedComments.dart","language":"dart","start_line":82,"end_line":82,"start_column":2,"end_column":13,"docstring":"A comment.","signature":"()","visibility":"public","is_exported":0,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":"C"} {"id":"method:d50020a1a43788b961bf8a4652e85a45","kind":"method","name":"on_start","qualified_name":"M.callbacks::on_start","file_path":"torture.lua","language":"lua","start_line":72,"end_line":74,"start_column":12,"end_column":4,"docstring":null,"signature":"()","visibility":null,"is_exported":0,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":null} +{"id":"method:d63eca909d73707a025ddf2fd591a13e","kind":"method","name":"Unmarshal","qualified_name":"Core::Unmarshal","file_path":"torture.go","language":"go","start_line":78,"end_line":78,"start_column":1,"end_column":29,"docstring":null,"signature":"(data []byte) error","visibility":null,"is_exported":0,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":"error"} {"id":"method:d6d1b0f141d5bfc74b43a2ab89ce76e7","kind":"method","name":"validate","qualified_name":"Point::validate","file_path":"TortureDeclarationDocs.dart","language":"dart","start_line":80,"end_line":80,"start_column":2,"end_column":17,"docstring":null,"signature":"void ()","visibility":"public","is_exported":0,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":null} {"id":"method:d768a3f8cc0fe5ab53663ca7efd83d5f","kind":"method","name":"unwrap","qualified_name":"Box::unwrap","file_path":"torture.cpp","language":"cpp","start_line":69,"end_line":71,"start_column":0,"end_column":1,"docstring":null,"signature":null,"visibility":null,"is_exported":1,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":"T"} {"id":"method:d8351ffc5da3f8f323ccc3c86f09983d","kind":"method","name":"m","qualified_name":"Indented::m","file_path":"TortureIndent.scala","language":"scala","start_line":5,"end_line":9,"start_column":2,"end_column":0,"docstring":null,"signature":"(): Int","visibility":"public","is_exported":0,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":"Int"} @@ -1487,6 +1491,7 @@ {"id":"method:d8b7bf52a458a666b599421ddc96b9fe","kind":"method","name":"plus","qualified_name":"WidgetK::plus","file_path":"torture.kt","language":"kotlin","start_line":44,"end_line":44,"start_column":0,"end_column":53,"docstring":null,"signature":"(o: WidgetK): WidgetK","visibility":"public","is_exported":1,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":"WidgetK"} {"id":"method:dbc683708e8c0217a76edc711cab984f","kind":"method","name":"create","qualified_name":"Widget::create","file_path":"torture.js","language":"javascript","start_line":36,"end_line":38,"start_column":2,"end_column":3,"docstring":null,"signature":"(opts)","visibility":null,"is_exported":0,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":null} {"id":"method:dbedc27f10579fd7567f0cbda93fb625","kind":"method","name":"privado","qualified_name":"WidgetT::privado","file_path":"torture.dart","language":"dart","start_line":138,"end_line":138,"start_column":2,"end_column":18,"docstring":null,"signature":"bool","visibility":"public","is_exported":0,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":"bool"} +{"id":"method:dc018b19c95524f99100bf15538c815b","kind":"method","name":"Find","qualified_name":"Repo::Find","file_path":"torture.go","language":"go","start_line":84,"end_line":84,"start_column":1,"end_column":48,"docstring":null,"signature":"(ctx pkga.Context, id Dur) (*Widget, error)","visibility":null,"is_exported":0,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":"Widget"} {"id":"method:dd439e569e5643b7eab01af84e7b86a4","kind":"method","name":"constructor","qualified_name":"Widget::constructor","file_path":"torture.js","language":"javascript","start_line":26,"end_line":30,"start_column":2,"end_column":3,"docstring":null,"signature":"(opts)","visibility":null,"is_exported":0,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":null} {"id":"method:ddb060d6aff7b30b2ec58ad67c7db95a","kind":"method","name":"getName","qualified_name":"com.example.torture::LombokBean::getName","file_path":"Torture.java","language":"java","start_line":116,"end_line":116,"start_column":2,"end_column":42,"docstring":"taken: no synthetic toString field collision","signature":"String ()","visibility":"public","is_exported":0,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":"String"} {"id":"method:de718159205cba9b0d17647ac71f8f2a","kind":"method","name":"render","qualified_name":"com.example.torture::WidgetK::render","file_path":"torture.kt","language":"kotlin","start_line":76,"end_line":78,"start_column":4,"end_column":5,"docstring":null,"signature":"(): Unit","visibility":"public","is_exported":0,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":null} @@ -1506,7 +1511,6 @@ {"id":"method:e3a8fd81bee3f156fa7af9c4f66a1329","kind":"method","name":"HandleThing","qualified_name":"Torture.Alpha::TortureClass::HandleThing","file_path":"Torture.cs","language":"csharp","start_line":66,"end_line":66,"start_column":8,"end_column":43,"docstring":null,"signature":null,"visibility":"private","is_exported":0,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":null} {"id":"method:e530b69dfedb3e6da7735d250c91870b","kind":"method","name":"reads","qualified_name":"Chains::reads","file_path":"TortureCommentChains.dart","language":"dart","start_line":59,"end_line":76,"start_column":2,"end_column":41,"docstring":null,"signature":"int (Box box, WidgetTester tester)","visibility":"public","is_exported":0,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":"int"} {"id":"method:e56906659412f1f464fdd82d5518f5de","kind":"method","name":"_privateMethod","qualified_name":"WidgetT2::_privateMethod","file_path":"torture.dart","language":"dart","start_line":155,"end_line":155,"start_column":2,"end_column":23,"docstring":null,"signature":"void ()","visibility":"private","is_exported":0,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":null} -{"id":"method:e5720c08e3888accbb1c2aa2421e1dd1","kind":"method","name":"Unmarshal","qualified_name":"Core::Unmarshal","file_path":"torture.go","language":"go","start_line":45,"end_line":45,"start_column":1,"end_column":29,"docstring":null,"signature":"(data []byte) error","visibility":null,"is_exported":0,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":"error"} {"id":"method:e69984c0ba5730f8ad2a8f6e795dda98","kind":"method","name":"create","qualified_name":"_$GeneratedT::create","file_path":"TortureConstCtors.dart","language":"dart","start_line":62,"end_line":62,"start_column":2,"end_column":29,"docstring":null,"signature":"()","visibility":"public","is_exported":0,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":"_$GeneratedT"} {"id":"method:e6d61456bc02617e3b7dcad6aa4e8517","kind":"method","name":"delta","qualified_name":"H2::delta","file_path":"TortureFnref.scala","language":"scala","start_line":19,"end_line":19,"start_column":2,"end_column":24,"docstring":null,"signature":"(): Unit","visibility":"public","is_exported":0,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":"Unit"} {"id":"method:e721803e0b4da8cdc52d9c909006f907","kind":"method","name":"create","qualified_name":"WidgetT::create","file_path":"torture.dart","language":"dart","start_line":127,"end_line":127,"start_column":2,"end_column":26,"docstring":null,"signature":null,"visibility":"public","is_exported":0,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":"WidgetT"} @@ -1615,17 +1619,18 @@ {"id":"struct:08acded06d18f155491d1e66e44ba80b","kind":"struct","name":"Vec2","qualified_name":"Vec2","file_path":"torture.cpp","language":"cpp","start_line":82,"end_line":87,"start_column":0,"end_column":1,"docstring":null,"signature":null,"visibility":null,"is_exported":1,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":null} {"id":"struct:0c309a8ed6f33456724d94ba73599e04","kind":"struct","name":"Widget","qualified_name":"Widget","file_path":"torture.rs","language":"rust","start_line":12,"end_line":16,"start_column":0,"end_column":1,"docstring":"Widget docs.","signature":null,"visibility":"public","is_exported":0,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":null} {"id":"struct:1c29d35c6762fac3ee71d6250a39c107","kind":"struct","name":"","qualified_name":"","file_path":"torture.c","language":"c","start_line":198,"end_line":198,"start_column":0,"end_column":22,"docstring":null,"signature":null,"visibility":null,"is_exported":1,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":null} -{"id":"struct:2062166f706221e2d500e7d9807245d9","kind":"struct","name":"AnonAlias","qualified_name":"AnonAlias","file_path":"torture.go","language":"go","start_line":67,"end_line":70,"start_column":5,"end_column":1,"docstring":null,"signature":null,"visibility":null,"is_exported":1,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":null} {"id":"struct:22cb841d7a3265379018f5b56364e98c","kind":"struct","name":"BufSource","qualified_name":"BufSource","file_path":"torture.rs","language":"rust","start_line":136,"end_line":138,"start_column":0,"end_column":1,"docstring":null,"signature":null,"visibility":"public","is_exported":0,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":null} {"id":"struct:27fbb507111460b65bffde24338f1495","kind":"struct","name":"flex_tail","qualified_name":"flex_tail","file_path":"torture.c","language":"c","start_line":119,"end_line":122,"start_column":0,"end_column":1,"docstring":null,"signature":null,"visibility":null,"is_exported":1,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":null} {"id":"struct:2b5cee7ee15906697f79c2d4a7d886a3","kind":"struct","name":"Registry","qualified_name":"decl_types::Registry","file_path":"torture.cpp","language":"cpp","start_line":117,"end_line":120,"start_column":0,"end_column":1,"docstring":"The handler registry.","signature":null,"visibility":null,"is_exported":1,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":null} {"id":"struct:33e3531d750b08f5b854203467928f28","kind":"struct","name":"Widget","qualified_name":"Widget","file_path":"torture.go","language":"go","start_line":18,"end_line":26,"start_column":5,"end_column":1,"docstring":"Widget is documented above its own type declaration.","signature":null,"visibility":null,"is_exported":1,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":null} +{"id":"struct:44d6f0ea6746cda4ce3d410ce9c99a46","kind":"struct","name":"AnonFields","qualified_name":"AnonFields","file_path":"torture.go","language":"go","start_line":61,"end_line":63,"start_column":5,"end_column":1,"docstring":null,"signature":null,"visibility":null,"is_exported":1,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":null} {"id":"struct:487d89e7a287a16bb02adabeb6c061a0","kind":"struct","name":"MainApp","qualified_name":"MainApp","file_path":"torture.swift","language":"swift","start_line":121,"end_line":123,"start_column":0,"end_column":1,"docstring":null,"signature":null,"visibility":"internal","is_exported":0,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":null} {"id":"struct:4c67fc2c851f10cf7803489ef577fc3c","kind":"struct","name":"Stack","qualified_name":"Stack","file_path":"torture.go","language":"go","start_line":28,"end_line":30,"start_column":5,"end_column":1,"docstring":null,"signature":null,"visibility":null,"is_exported":1,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":null} {"id":"struct:4ea1b361173ba3f6b1b2e8dfe74e13d3","kind":"struct","name":"Parents","qualified_name":"Parents","file_path":"torture.rs","language":"rust","start_line":146,"end_line":148,"start_column":0,"end_column":1,"docstring":null,"signature":null,"visibility":"public","is_exported":0,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":null} {"id":"struct:5fcea532f9aedc459fa2d53ba939f3c3","kind":"struct","name":"Pair","qualified_name":"Pair","file_path":"torture.rs","language":"rust","start_line":20,"end_line":20,"start_column":0,"end_column":26,"docstring":null,"signature":null,"visibility":"public","is_exported":0,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":null} {"id":"struct:68ba8bd4bb0864aeb77213901028683d","kind":"struct","name":"Point3","qualified_name":"Torture.Alpha::Point3","file_path":"Torture.cs","language":"csharp","start_line":171,"end_line":171,"start_column":4,"end_column":42,"docstring":null,"signature":null,"visibility":"public","is_exported":0,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":null} {"id":"struct:6b67af1b786b02de97ae0b93e58bf381","kind":"struct","name":"Holder","qualified_name":"Holder","file_path":"torture.rs","language":"rust","start_line":243,"end_line":245,"start_column":0,"end_column":1,"docstring":null,"signature":null,"visibility":"public","is_exported":0,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":null} +{"id":"struct:6b80d8f1dbee1c34e187c63b7e616a70","kind":"struct","name":"Server","qualified_name":"Server","file_path":"torture.go","language":"go","start_line":35,"end_line":52,"start_column":5,"end_column":1,"docstring":"A struct references the types its fields are declared with, but the types\nit embeds (supertypes), its own type parameters, predeclared types and its\nown name written bare.","signature":null,"visibility":null,"is_exported":1,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":null} {"id":"struct:6d96b486579cf3fdd66718872215294c","kind":"struct","name":"HTTPMethod","qualified_name":"HTTPMethod","file_path":"torture.swift","language":"swift","start_line":39,"end_line":42,"start_column":0,"end_column":1,"docstring":null,"signature":null,"visibility":"internal","is_exported":0,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":null} {"id":"struct:7dcc3e8c0c639ebb09d04ec84126b25b","kind":"struct","name":"conn_t","qualified_name":"conn_t","file_path":"torture.c","language":"c","start_line":28,"end_line":31,"start_column":0,"end_column":9,"docstring":null,"signature":null,"visibility":null,"is_exported":1,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":null} {"id":"struct:8590f547340aeeb50be0e4d16f1a205f","kind":"struct","name":"packet_t","qualified_name":"packet_t","file_path":"torture.cpp","language":"cpp","start_line":91,"end_line":93,"start_column":0,"end_column":11,"docstring":null,"signature":null,"visibility":null,"is_exported":1,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":null} @@ -1636,7 +1641,9 @@ {"id":"struct:a71590fb65103a7d401e479351d84b52","kind":"struct","name":"Pointish","qualified_name":"Torture.Scoped::Pointish","file_path":"TortureFileScoped.cs","language":"csharp","start_line":12,"end_line":12,"start_column":0,"end_column":44,"docstring":null,"signature":null,"visibility":"public","is_exported":0,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":null} {"id":"struct:aa7ce416b52984c7ea2b1b6d43e70da9","kind":"struct","name":"","qualified_name":"packet_hdr::","file_path":"torture.c","language":"c","start_line":160,"end_line":160,"start_column":2,"end_column":38,"docstring":null,"signature":null,"visibility":null,"is_exported":0,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":null} {"id":"struct:ab1ddae19b44311cc03a2493e898f4db","kind":"struct","name":"local_stats","qualified_name":"declared_types_local::local_stats","file_path":"torture.c","language":"c","start_line":201,"end_line":201,"start_column":9,"end_column":29,"docstring":null,"signature":null,"visibility":null,"is_exported":0,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":null} +{"id":"struct:ad8421763ee39344ef65f68fc90dd015","kind":"struct","name":"AnonAlias","qualified_name":"AnonAlias","file_path":"torture.go","language":"go","start_line":108,"end_line":111,"start_column":5,"end_column":1,"docstring":null,"signature":null,"visibility":null,"is_exported":1,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":null} {"id":"struct:b332a5023d7677bcdc4456c24d9b6be6","kind":"struct","name":"settings","qualified_name":"decl_types::settings","file_path":"torture.cpp","language":"cpp","start_line":122,"end_line":122,"start_column":7,"end_column":30,"docstring":null,"signature":null,"visibility":null,"is_exported":1,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":null} +{"id":"struct:b5d2c300d801f1233941b73d992ba7eb","kind":"struct","name":"Pool","qualified_name":"Pool","file_path":"torture.go","language":"go","start_line":54,"end_line":59,"start_column":5,"end_column":1,"docstring":null,"signature":null,"visibility":null,"is_exported":1,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":null} {"id":"struct:be0bce4f35c3b001691d2298b42277a7","kind":"struct","name":"builtin_table","qualified_name":"builtin_table","file_path":"torture.c","language":"c","start_line":193,"end_line":193,"start_column":13,"end_column":59,"docstring":null,"signature":null,"visibility":null,"is_exported":1,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":null} {"id":"struct:c178330f11d7b530d10a9a362596e95e","kind":"struct","name":"packet","qualified_name":"packet","file_path":"torture.c","language":"c","start_line":39,"end_line":44,"start_column":0,"end_column":1,"docstring":null,"signature":null,"visibility":null,"is_exported":1,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":null} {"id":"struct:c1ae7a1f5526f34c24c26eeaa97abd1b","kind":"struct","name":"Counter","qualified_name":"app::detail::Counter","file_path":"torture.cpp","language":"cpp","start_line":27,"end_line":30,"start_column":0,"end_column":1,"docstring":null,"signature":null,"visibility":null,"is_exported":1,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":null} @@ -1659,59 +1666,58 @@ {"id":"trait:dcec472700533c7d65fd2f90ea3c6830","kind":"trait","name":"Base","qualified_name":"Base","file_path":"torture.rs","language":"rust","start_line":50,"end_line":50,"start_column":0,"end_column":17,"docstring":null,"signature":null,"visibility":null,"is_exported":0,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":null} {"id":"trait:e04dbb1eecf85e1d939fb1816b47ffdf","kind":"trait","name":"TraitI","qualified_name":"TraitI","file_path":"TortureIndent.scala","language":"scala","start_line":16,"end_line":19,"start_column":0,"end_column":0,"docstring":null,"signature":null,"visibility":"public","is_exported":0,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":null} {"id":"trait:f91851c14912462ae9592cb13a51f3b1","kind":"trait","name":"Drawable","qualified_name":"Drawable","file_path":"torture.scala","language":"scala","start_line":80,"end_line":84,"start_column":0,"end_column":1,"docstring":null,"signature":null,"visibility":"public","is_exported":0,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":null} +{"id":"type_alias:02bad22974119233684c4cdc31b84c08","kind":"type_alias","name":"FnAlias","qualified_name":"FnAlias","file_path":"torture.go","language":"go","start_line":103,"end_line":103,"start_column":1,"end_column":34,"docstring":null,"signature":null,"visibility":null,"is_exported":1,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":null} +{"id":"type_alias:056dd5fe2cc3e2ad87323386146effcc","kind":"type_alias","name":"Lookup","qualified_name":"Lookup","file_path":"torture.go","language":"go","start_line":128,"end_line":128,"start_column":1,"end_column":31,"docstring":null,"signature":null,"visibility":null,"is_exported":1,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":null} +{"id":"type_alias:09f9cb5669970256407b8aebd0528e7d","kind":"type_alias","name":"LocalAlias","qualified_name":"LocalAlias","file_path":"torture.go","language":"go","start_line":101,"end_line":101,"start_column":1,"end_column":20,"docstring":null,"signature":null,"visibility":null,"is_exported":1,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":null} {"id":"type_alias:0bd2a1055ccaf6d38ca745ac51664b04","kind":"type_alias","name":"LegacyCb","qualified_name":"LegacyCb","file_path":"torture.dart","language":"dart","start_line":209,"end_line":209,"start_column":0,"end_column":29,"docstring":null,"signature":null,"visibility":null,"is_exported":0,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":null} {"id":"type_alias:0cc126fa729916372d1e6d88ee0e2415","kind":"type_alias","name":"(*cb_t)","qualified_name":"(*cb_t)","file_path":"torture.c","language":"c","start_line":35,"end_line":35,"start_column":0,"end_column":25,"docstring":null,"signature":null,"visibility":null,"is_exported":1,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":null} -{"id":"type_alias:10728d965a9856b988bb2359a09666f9","kind":"type_alias","name":"Dur","qualified_name":"Dur","file_path":"torture.go","language":"go","start_line":54,"end_line":54,"start_column":5,"end_column":12,"docstring":null,"signature":null,"visibility":null,"is_exported":1,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":null} {"id":"type_alias:1b5eb3ef72c3df6177bec86b60d9b4ab","kind":"type_alias","name":"Handle","qualified_name":"Handle","file_path":"torture.cpp","language":"cpp","start_line":94,"end_line":94,"start_column":0,"end_column":27,"docstring":null,"signature":null,"visibility":null,"is_exported":1,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":null} +{"id":"type_alias:1bc21f6b21632fe87943700ca4573be4","kind":"type_alias","name":"Alias","qualified_name":"Alias","file_path":"torture.go","language":"go","start_line":98,"end_line":98,"start_column":5,"end_column":24,"docstring":"Aliases (`=`): the types they name are references; a literal makes a struct or interface.","signature":null,"visibility":null,"is_exported":1,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":null} {"id":"type_alias:1cd665599e50d4f472ddeda93071b27a","kind":"type_alias","name":"Member","qualified_name":"Outer2::Member","file_path":"TortureMisc.scala","language":"scala","start_line":8,"end_line":8,"start_column":2,"end_column":25,"docstring":null,"signature":null,"visibility":null,"is_exported":0,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":null} -{"id":"type_alias:2652fcdf36b42377e527cf35f8d800c9","kind":"type_alias","name":"WatchChan","qualified_name":"WatchChan","file_path":"torture.go","language":"go","start_line":84,"end_line":84,"start_column":5,"end_column":33,"docstring":null,"signature":null,"visibility":null,"is_exported":1,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":null} -{"id":"type_alias:27e49398ec8ebe39651fd8822e253a54","kind":"type_alias","name":"MapAlias","qualified_name":"MapAlias","file_path":"torture.go","language":"go","start_line":63,"end_line":63,"start_column":1,"end_column":36,"docstring":null,"signature":null,"visibility":null,"is_exported":1,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":null} -{"id":"type_alias:27e7afa3d9358e091e23f4ee6e495fc5","kind":"type_alias","name":"Seconds","qualified_name":"Seconds","file_path":"torture.go","language":"go","start_line":34,"end_line":34,"start_column":1,"end_column":12,"docstring":null,"signature":null,"visibility":null,"is_exported":1,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":null} +{"id":"type_alias:2a5e03d369bc91073bc0792b6964ac16","kind":"type_alias","name":"Dur","qualified_name":"Dur","file_path":"torture.go","language":"go","start_line":95,"end_line":95,"start_column":5,"end_column":12,"docstring":null,"signature":null,"visibility":null,"is_exported":1,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":null} {"id":"type_alias:428bef2eb5ba989d4984c0c1fb4a1e02","kind":"type_alias","name":"WidgetList","qualified_name":"com.example.torture::WidgetList","file_path":"torture.kt","language":"kotlin","start_line":168,"end_line":168,"start_column":0,"end_column":36,"docstring":null,"signature":null,"visibility":null,"is_exported":1,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":null} -{"id":"type_alias:44cb4653a5e07bdcee1050ba3133ab31","kind":"type_alias","name":"Grid","qualified_name":"Grid","file_path":"torture.go","language":"go","start_line":88,"end_line":88,"start_column":1,"end_column":26,"docstring":null,"signature":null,"visibility":null,"is_exported":1,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":null} -{"id":"type_alias:4b2d750ab1f528d33a2d6713cb2193a7","kind":"type_alias","name":"FnAlias","qualified_name":"FnAlias","file_path":"torture.go","language":"go","start_line":62,"end_line":62,"start_column":1,"end_column":34,"docstring":null,"signature":null,"visibility":null,"is_exported":1,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":null} +{"id":"type_alias:439984898e3d20cbd0156ea66c4aab37","kind":"type_alias","name":"Minutes","qualified_name":"Minutes","file_path":"torture.go","language":"go","start_line":69,"end_line":69,"start_column":1,"end_column":12,"docstring":"Minutes is documented inside its group.","signature":null,"visibility":null,"is_exported":1,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":null} {"id":"type_alias:4eac8834dd1ceb7059cdc0ebd6a23f96","kind":"type_alias","name":"Handler","qualified_name":"Handler","file_path":"torture.swift","language":"swift","start_line":75,"end_line":75,"start_column":0,"end_column":34,"docstring":null,"signature":null,"visibility":null,"is_exported":0,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":null} {"id":"type_alias:544f3be472935dfbe579fa190ead63ab","kind":"type_alias","name":"MapAlias","qualified_name":"MapAlias","file_path":"torture.dart","language":"dart","start_line":210,"end_line":210,"start_column":0,"end_column":40,"docstring":null,"signature":null,"visibility":null,"is_exported":0,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":null} +{"id":"type_alias:55981ee7594cc71cc0d5283a993cd5f2","kind":"type_alias","name":"Item","qualified_name":"Item","file_path":"torture.go","language":"go","start_line":131,"end_line":131,"start_column":1,"end_column":18,"docstring":null,"signature":null,"visibility":null,"is_exported":1,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":null} {"id":"type_alias:58bcebb7feaaca7a0be3c251dfa21bd7","kind":"type_alias","name":"Item","qualified_name":"Item","file_path":"torture.rs","language":"rust","start_line":151,"end_line":151,"start_column":4,"end_column":20,"docstring":null,"signature":null,"visibility":null,"is_exported":0,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":null} {"id":"type_alias:5cd4631080c4eec3535487f74a11a6e5","kind":"type_alias","name":"Handler","qualified_name":"Handler","file_path":"torture.luau","language":"luau","start_line":9,"end_line":9,"start_column":0,"end_column":41,"docstring":"- doc for exported Handler","signature":null,"visibility":null,"is_exported":1,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":null} +{"id":"type_alias:5d4689c66e6a4956859f7b921c3610c8","kind":"type_alias","name":"Seconds","qualified_name":"Seconds","file_path":"torture.go","language":"go","start_line":67,"end_line":67,"start_column":1,"end_column":12,"docstring":null,"signature":null,"visibility":null,"is_exported":1,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":null} +{"id":"type_alias:5fab20424fd8ff6f365fbb0e5eec9c84","kind":"type_alias","name":"HandlersChain","qualified_name":"HandlersChain","file_path":"torture.go","language":"go","start_line":123,"end_line":123,"start_column":5,"end_column":32,"docstring":null,"signature":null,"visibility":null,"is_exported":1,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":null} {"id":"type_alias:600473b4a3158649443b2f214febf906","kind":"type_alias","name":"Handle","qualified_name":"Handle","file_path":"torture.tsx","language":"tsx","start_line":78,"end_line":82,"start_column":7,"end_column":2,"docstring":null,"signature":null,"visibility":null,"is_exported":1,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":null} +{"id":"type_alias:608221a5f58d68322f43ee54c190640e","kind":"type_alias","name":"Nested","qualified_name":"Nested","file_path":"torture.go","language":"go","start_line":132,"end_line":135,"start_column":1,"end_column":2,"docstring":null,"signature":null,"visibility":null,"is_exported":1,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":null} {"id":"type_alias:6a21437777e4b07c717fdfe64d7d88a6","kind":"type_alias","name":"IntFn","qualified_name":"IntFn","file_path":"TortureMini.dart","language":"dart","start_line":73,"end_line":73,"start_column":0,"end_column":34,"docstring":null,"signature":null,"visibility":null,"is_exported":0,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":null} -{"id":"type_alias:70a70301f02c5dd34c45fea884736d5d","kind":"type_alias","name":"Defined","qualified_name":"Defined","file_path":"torture.go","language":"go","start_line":64,"end_line":64,"start_column":1,"end_column":18,"docstring":null,"signature":null,"visibility":null,"is_exported":1,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":null} {"id":"type_alias:72c3072a93008168a6b815b2218734ab","kind":"type_alias","name":"Meters","qualified_name":"Meters","file_path":"torture.scala","language":"scala","start_line":124,"end_line":124,"start_column":0,"end_column":27,"docstring":null,"signature":null,"visibility":null,"is_exported":0,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":null} -{"id":"type_alias:75662b893c34aed98e64700a6d01bf8d","kind":"type_alias","name":"HandlerFunc","qualified_name":"HandlerFunc","file_path":"torture.go","language":"go","start_line":80,"end_line":80,"start_column":5,"end_column":47,"docstring":"Defined types reference what they are defined from, but their own type\nparameters, predeclared types and their own name written bare.","signature":null,"visibility":null,"is_exported":1,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":null} +{"id":"type_alias:771117de3df76a903822e0fab4467df8","kind":"type_alias","name":"Wrapped","qualified_name":"Wrapped","file_path":"torture.go","language":"go","start_line":130,"end_line":130,"start_column":1,"end_column":17,"docstring":null,"signature":null,"visibility":null,"is_exported":1,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":null} {"id":"type_alias:7af544d97a5a08e375d93b8c948094a3","kind":"type_alias","name":"Point","qualified_name":"Point","file_path":"torture.luau","language":"luau","start_line":7,"end_line":7,"start_column":0,"end_column":37,"docstring":"doc for Point","signature":null,"visibility":null,"is_exported":0,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":null} {"id":"type_alias:7c915e16af01cef4bda8242d2331796c","kind":"type_alias","name":"Cb","qualified_name":"Cb","file_path":"TortureAnnotatedDocs.dart","language":"dart","start_line":185,"end_line":186,"start_column":0,"end_column":29,"docstring":"Typedef doc.","signature":null,"visibility":null,"is_exported":0,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":null} -{"id":"type_alias:80c39c4f28c27d78ecdedc474ae4af7b","kind":"type_alias","name":"PtrAlias","qualified_name":"PtrAlias","file_path":"torture.go","language":"go","start_line":61,"end_line":61,"start_column":1,"end_column":25,"docstring":null,"signature":null,"visibility":null,"is_exported":1,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":null} {"id":"type_alias:813393b308ca1d8f278ce99d55bf11d7","kind":"type_alias","name":"IntFn","qualified_name":"IntFn","file_path":"torture.dart","language":"dart","start_line":208,"end_line":208,"start_column":0,"end_column":34,"docstring":null,"signature":null,"visibility":null,"is_exported":0,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":null} {"id":"type_alias:82325cc15cfda33fe564374ff3fd49d0","kind":"type_alias","name":"PlatformClock","qualified_name":"com.example.torture::PlatformClock","file_path":"torture.kt","language":"kotlin","start_line":178,"end_line":178,"start_column":0,"end_column":48,"docstring":null,"signature":null,"visibility":null,"is_exported":1,"is_async":0,"is_static":0,"is_abstract":0,"decorators":"[\"actual\"]","type_parameters":null,"return_type":null} +{"id":"type_alias:882c227f07ef59b639ecf2c0cfb69f1c","kind":"type_alias","name":"MapAlias","qualified_name":"MapAlias","file_path":"torture.go","language":"go","start_line":104,"end_line":104,"start_column":1,"end_column":36,"docstring":null,"signature":null,"visibility":null,"is_exported":1,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":null} {"id":"type_alias:8d09bbd71ebfe2d1aa557e0e79aaab99","kind":"type_alias","name":"BuilderAlias","qualified_name":"BuilderAlias","file_path":"torture.swift","language":"swift","start_line":76,"end_line":76,"start_column":0,"end_column":35,"docstring":null,"signature":null,"visibility":null,"is_exported":0,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":null} -{"id":"type_alias:99498bda61debd01b2e7459030084c24","kind":"type_alias","name":"WordAlias","qualified_name":"WordAlias","file_path":"torture.go","language":"go","start_line":76,"end_line":76,"start_column":5,"end_column":21,"docstring":null,"signature":null,"visibility":null,"is_exported":1,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":null} +{"id":"type_alias:965915e648eebc2c230c7f5df6ca9700","kind":"type_alias","name":"HandlerFunc","qualified_name":"HandlerFunc","file_path":"torture.go","language":"go","start_line":121,"end_line":121,"start_column":5,"end_column":47,"docstring":"Defined types reference what they are defined from, but their own type\nparameters, predeclared types and their own name written bare.","signature":null,"visibility":null,"is_exported":1,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":null} +{"id":"type_alias:a10c4f47aeab87402ced28d09f54ddfb","kind":"type_alias","name":"WatchChan","qualified_name":"WatchChan","file_path":"torture.go","language":"go","start_line":125,"end_line":125,"start_column":5,"end_column":33,"docstring":null,"signature":null,"visibility":null,"is_exported":1,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":null} {"id":"type_alias:a4b2f4669bb9b6a430127b2bd835436f","kind":"type_alias","name":"FromTypeof","qualified_name":"FromTypeof","file_path":"torture.luau","language":"luau","start_line":11,"end_line":11,"start_column":0,"end_column":55,"docstring":null,"signature":null,"visibility":null,"is_exported":0,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":null} -{"id":"type_alias:a54bf143682054f499fe157e6b733087","kind":"type_alias","name":"Alias","qualified_name":"Alias","file_path":"torture.go","language":"go","start_line":57,"end_line":57,"start_column":5,"end_column":24,"docstring":"Aliases (`=`): the types they name are references; a literal makes a struct or interface.","signature":null,"visibility":null,"is_exported":1,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":null} +{"id":"type_alias:a9e7f1010d06f6bbc8039f4b63877b56","kind":"type_alias","name":"WordAlias","qualified_name":"WordAlias","file_path":"torture.go","language":"go","start_line":117,"end_line":117,"start_column":5,"end_column":21,"docstring":null,"signature":null,"visibility":null,"is_exported":1,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":null} {"id":"type_alias:afe0d22243bb9ac1575ca6df41bf921c","kind":"type_alias","name":"WidgetList","qualified_name":"WidgetList","file_path":"torture.scala","language":"scala","start_line":123,"end_line":123,"start_column":0,"end_column":31,"docstring":null,"signature":null,"visibility":null,"is_exported":0,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":null} -{"id":"type_alias:bb8bd8650e34457304e34b86851c1431","kind":"type_alias","name":"LocalAlias","qualified_name":"LocalAlias","file_path":"torture.go","language":"go","start_line":60,"end_line":60,"start_column":1,"end_column":20,"docstring":null,"signature":null,"visibility":null,"is_exported":1,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":null} -{"id":"type_alias:c0ad8af1b5e37e6ad90fd0c5790b6209","kind":"type_alias","name":"HandlersChain","qualified_name":"HandlersChain","file_path":"torture.go","language":"go","start_line":82,"end_line":82,"start_column":5,"end_column":32,"docstring":null,"signature":null,"visibility":null,"is_exported":1,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":null} +{"id":"type_alias:b826ea0f1f4d158a41ccfe0c21c225f3","kind":"type_alias","name":"Tree","qualified_name":"Tree","file_path":"torture.go","language":"go","start_line":138,"end_line":138,"start_column":5,"end_column":27,"docstring":null,"signature":null,"visibility":null,"is_exported":1,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":null} {"id":"type_alias:c5961e802ae860f4834791477a9aa980","kind":"type_alias","name":"OldStyle","qualified_name":"OldStyle","file_path":"TortureMini.dart","language":"dart","start_line":74,"end_line":74,"start_column":0,"end_column":29,"docstring":null,"signature":null,"visibility":null,"is_exported":0,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":null} -{"id":"type_alias:c925710f298dd798808037fcf660f73b","kind":"type_alias","name":"stateFn","qualified_name":"stateFn","file_path":"torture.go","language":"go","start_line":99,"end_line":99,"start_column":5,"end_column":34,"docstring":null,"signature":null,"visibility":null,"is_exported":0,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":null} +{"id":"type_alias:c9336784d0211d92b205b7194a5ce3a7","kind":"type_alias","name":"PtrAlias","qualified_name":"PtrAlias","file_path":"torture.go","language":"go","start_line":102,"end_line":102,"start_column":1,"end_column":25,"docstring":null,"signature":null,"visibility":null,"is_exported":1,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":null} +{"id":"type_alias:c9fe81e444d43593fc382a0be628bc66","kind":"type_alias","name":"Defined","qualified_name":"Defined","file_path":"torture.go","language":"go","start_line":105,"end_line":105,"start_column":1,"end_column":18,"docstring":null,"signature":null,"visibility":null,"is_exported":1,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":null} {"id":"type_alias:cd058f941742f057073628ddb35e0b9c","kind":"type_alias","name":"Handler","qualified_name":"com.example.torture::Handler","file_path":"torture.kt","language":"kotlin","start_line":167,"end_line":167,"start_column":0,"end_column":33,"docstring":null,"signature":null,"visibility":null,"is_exported":1,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":null} {"id":"type_alias:cdaae8f951716ba1d5b3f5faa698cf1c","kind":"type_alias","name":"MaybeShape","qualified_name":"MaybeShape","file_path":"torture.tsx","language":"tsx","start_line":89,"end_line":89,"start_column":7,"end_column":38,"docstring":null,"signature":null,"visibility":null,"is_exported":1,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":null} -{"id":"type_alias:d4964291bed60f871ad9554b4572ac9b","kind":"type_alias","name":"Item","qualified_name":"Item","file_path":"torture.go","language":"go","start_line":90,"end_line":90,"start_column":1,"end_column":18,"docstring":null,"signature":null,"visibility":null,"is_exported":1,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":null} -{"id":"type_alias:d9cf57aaa8c6be0b025ae6b685745a39","kind":"type_alias","name":"Nested","qualified_name":"Nested","file_path":"torture.go","language":"go","start_line":91,"end_line":94,"start_column":1,"end_column":2,"docstring":null,"signature":null,"visibility":null,"is_exported":1,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":null} -{"id":"type_alias:df1bf626c237f1dfe84e753a6edace47","kind":"type_alias","name":"Tree","qualified_name":"Tree","file_path":"torture.go","language":"go","start_line":97,"end_line":97,"start_column":5,"end_column":27,"docstring":null,"signature":null,"visibility":null,"is_exported":1,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":null} -{"id":"type_alias:e67f0306e684e2b34de4b379a1546426","kind":"type_alias","name":"Lookup","qualified_name":"Lookup","file_path":"torture.go","language":"go","start_line":87,"end_line":87,"start_column":1,"end_column":31,"docstring":null,"signature":null,"visibility":null,"is_exported":1,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":null} +{"id":"type_alias:d1df73c8269ea5dd18f9aaaac0a8088d","kind":"type_alias","name":"stateFn","qualified_name":"stateFn","file_path":"torture.go","language":"go","start_line":140,"end_line":140,"start_column":5,"end_column":34,"docstring":null,"signature":null,"visibility":null,"is_exported":0,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":null} {"id":"type_alias:ea7602cc1268d15f573f37f43c58d4e8","kind":"type_alias","name":"conn_pool_t","qualified_name":"conn_pool_t","file_path":"torture.c","language":"c","start_line":33,"end_line":33,"start_column":0,"end_column":37,"docstring":null,"signature":null,"visibility":null,"is_exported":1,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":null} {"id":"type_alias:f11a5d6472370edc6684dfe077359e68","kind":"type_alias","name":"Generic","qualified_name":"Generic","file_path":"torture.luau","language":"luau","start_line":10,"end_line":10,"start_column":0,"end_column":37,"docstring":null,"signature":null,"visibility":null,"is_exported":1,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":null} -{"id":"type_alias:f61f67035897704f4a03cf76fb59e8a9","kind":"type_alias","name":"Wrapped","qualified_name":"Wrapped","file_path":"torture.go","language":"go","start_line":89,"end_line":89,"start_column":1,"end_column":17,"docstring":null,"signature":null,"visibility":null,"is_exported":1,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":null} +{"id":"type_alias:f6d4e998f3c2200dadf5c1e05f9368ab","kind":"type_alias","name":"Grid","qualified_name":"Grid","file_path":"torture.go","language":"go","start_line":129,"end_line":129,"start_column":1,"end_column":26,"docstring":null,"signature":null,"visibility":null,"is_exported":1,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":null} {"id":"type_alias:f84ae3400c1d88837e6d67a42d5eea5a","kind":"type_alias","name":"ServiceList","qualified_name":"ServiceList","file_path":"torture.tsx","language":"tsx","start_line":84,"end_line":87,"start_column":7,"end_column":2,"docstring":null,"signature":null,"visibility":null,"is_exported":1,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":null} {"id":"type_alias:feafa08c2035b9892203463ba89e6d20","kind":"type_alias","name":"Alias","qualified_name":"Alias","file_path":"torture.rs","language":"rust","start_line":38,"end_line":38,"start_column":0,"end_column":29,"docstring":null,"signature":null,"visibility":null,"is_exported":0,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":null} -{"id":"type_alias:ff4b77836c3d72b57438c1723760af51","kind":"type_alias","name":"Minutes","qualified_name":"Minutes","file_path":"torture.go","language":"go","start_line":36,"end_line":36,"start_column":1,"end_column":12,"docstring":"Minutes is documented inside its group.","signature":null,"visibility":null,"is_exported":1,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":null} {"id":"union:81a2d91de5ccea8a0abe398570c1efcb","kind":"union","name":"scratch_word","qualified_name":"scratch_word","file_path":"torture.c","language":"c","start_line":196,"end_line":196,"start_column":0,"end_column":25,"docstring":null,"signature":null,"visibility":null,"is_exported":1,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":null} {"id":"union:87328bb244dc25e95ff76f307ddb5a57","kind":"union","name":"packet_hdr","qualified_name":"packet_hdr","file_path":"torture.c","language":"c","start_line":158,"end_line":161,"start_column":0,"end_column":1,"docstring":"named union definition, forward declaration, and anonymous typedef union —\n the definition is a node, the forward decl is not (#UNION)","signature":null,"visibility":null,"is_exported":1,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":null} {"id":"union:dca892bf5affbe24bc5af9c2fb3f133d","kind":"union","name":"Reg","qualified_name":"Reg","file_path":"torture.rs","language":"rust","start_line":293,"end_line":296,"start_column":0,"end_column":1,"docstring":null,"signature":null,"visibility":"public","is_exported":0,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":null} {"id":"union:effd1738dcf4c1fe91118605ac444272","kind":"union","name":"word_t","qualified_name":"word_t","file_path":"torture.c","language":"c","start_line":165,"end_line":168,"start_column":0,"end_column":9,"docstring":null,"signature":null,"visibility":null,"is_exported":1,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":null} {"id":"variable:016e87e7ea84d651c93fc40b46e09ab5","kind":"variable","name":"top_var","qualified_name":"top_var","file_path":"torture.rb","language":"ruby","start_line":13,"end_line":13,"start_column":0,"end_column":25,"docstring":null,"signature":"= compute_default","visibility":null,"is_exported":0,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":null} {"id":"variable:0560d6516d21bba56151a91b46a3458f","kind":"variable","name":"handlers","qualified_name":"handlers","file_path":"torture.py","language":"python","start_line":48,"end_line":48,"start_column":0,"end_column":30,"docstring":null,"signature":"= {\"recv\": target_cb}","visibility":null,"is_exported":1,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":null} -{"id":"variable:07821b80e054d5ee85de38b0c45e1662","kind":"variable","name":"mdQueried","qualified_name":"mdQueried","file_path":"torture.go","language":"go","start_line":141,"end_line":141,"start_column":4,"end_column":38,"docstring":null,"signature":"= \"./notes.md?raw=1#top\"","visibility":null,"is_exported":0,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":null} {"id":"variable:07f4c15ac5517d372045b53113f115ec","kind":"variable","name":"md_remote","qualified_name":"md_remote","file_path":"torture.lua","language":"lua","start_line":116,"end_line":116,"start_column":6,"end_column":15,"docstring":null,"signature":"= \"https://example.com/remote.md\"","visibility":null,"is_exported":0,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":null} {"id":"variable:0e1ebe0c408eb313069b90ffe30e9c10","kind":"variable","name":"s1","qualified_name":"s1","file_path":"torture.lua","language":"lua","start_line":100,"end_line":100,"start_column":6,"end_column":8,"docstring":null,"signature":"= [[long\nstring]]","visibility":null,"is_exported":0,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":null} {"id":"variable:0ed0b2f1feb1a982c7ebed5a22b8d476","kind":"variable","name":"s3.method","qualified_name":"s3.method","file_path":"torture.R","language":"r","start_line":129,"end_line":129,"start_column":0,"end_column":34,"docstring":null,"signature":null,"visibility":null,"is_exported":0,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":null} @@ -1719,6 +1725,7 @@ {"id":"variable:105fdc9ff6cbb7586a586de31e0407cd","kind":"variable","name":"tbl","qualified_name":"tbl","file_path":"torture.lua","language":"lua","start_line":81,"end_line":81,"start_column":6,"end_column":9,"docstring":null,"signature":"= { cb = topFn, [1] = localFn, nested = { deep_cb = topFn } }","visibility":null,"is_exported":0,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":null} {"id":"variable:107967afd523982bfd99c4fe3b90a2a1","kind":"variable","name":"md_queried","qualified_name":"md_queried","file_path":"torture.lua","language":"lua","start_line":117,"end_line":117,"start_column":6,"end_column":16,"docstring":null,"signature":"= \"./notes.md?raw=1#top\"","visibility":null,"is_exported":0,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":null} {"id":"variable:11e6afeefeea23348d79ed6171ed6abf","kind":"variable","name":"topVar","qualified_name":"topVar","file_path":"torture.scala","language":"scala","start_line":35,"end_line":35,"start_column":0,"end_column":14,"docstring":null,"signature":null,"visibility":"public","is_exported":0,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":null} +{"id":"variable:1408b0cc15b4db6aa165d25216f1f59a","kind":"variable","name":"mdRooted","qualified_name":"mdRooted","file_path":"torture.go","language":"go","start_line":179,"end_line":179,"start_column":4,"end_column":32,"docstring":null,"signature":"= \"/docs/rooted.md\"","visibility":null,"is_exported":0,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":null} {"id":"variable:144c41f1fe7d4cdfb643e499172e0f2c","kind":"variable","name":"MD_TWO_IN_ONE","qualified_name":"MD_TWO_IN_ONE","file_path":"torture.rb","language":"ruby","start_line":243,"end_line":243,"start_column":0,"end_column":45,"docstring":null,"signature":"= 'see a.md and also sub/b.mdx'","visibility":null,"is_exported":0,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":null} {"id":"variable:150a636395ceb800837ea1ef750c2979","kind":"variable","name":"Signal","qualified_name":"Signal","file_path":"torture.luau","language":"luau","start_line":4,"end_line":4,"start_column":6,"end_column":12,"docstring":null,"signature":"= require(script.Parent.Signal)","visibility":null,"is_exported":0,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":null} {"id":"variable:1837cd19ce5f7a8f45b7fa4b8fc8a0e6","kind":"variable","name":"DefaultRegistry","qualified_name":"DefaultRegistry","file_path":"torture.go","language":"go","start_line":11,"end_line":11,"start_column":4,"end_column":35,"docstring":null,"signature":"= NewRegistry()","visibility":null,"is_exported":1,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":null} @@ -1728,7 +1735,6 @@ {"id":"variable:247f05d883ce1a98f012960b2a5ad930","kind":"variable","name":"twoB","qualified_name":"twoB","file_path":"torture.lua","language":"lua","start_line":11,"end_line":11,"start_column":12,"end_column":16,"docstring":null,"signature":"= require(\"two.b\")","visibility":null,"is_exported":0,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":null} {"id":"variable:24ba9f675d787f6d3fe83c1c31297927","kind":"variable","name":"INIT_CONST","qualified_name":"INIT_CONST","file_path":"torture.rs","language":"rust","start_line":289,"end_line":289,"start_column":6,"end_column":16,"docstring":"Initializer walks attributed to the declared symbol (#693).","signature":null,"visibility":null,"is_exported":0,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":null} {"id":"variable:2677eb705e56b60786411fedec1ca6bc","kind":"variable","name":"md_escapes","qualified_name":"md_escapes","file_path":"torture.luau","language":"luau","start_line":68,"end_line":68,"start_column":6,"end_column":16,"docstring":null,"signature":"= \"../../../../outside.md\"","visibility":null,"is_exported":0,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":null} -{"id":"variable:275e942a48e8d317edfcc10e72224781","kind":"variable","name":"mdBare","qualified_name":"mdBare","file_path":"torture.go","language":"go","start_line":137,"end_line":137,"start_column":4,"end_column":24,"docstring":null,"signature":"= \"README.md\"","visibility":null,"is_exported":0,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":null} {"id":"variable:27ec9bbbab400f41caf30a5180e555d4","kind":"variable","name":"CONST_N","qualified_name":"CONST_N","file_path":"torture.luau","language":"luau","start_line":29,"end_line":29,"start_column":6,"end_column":13,"docstring":null,"signature":"= 7","visibility":null,"is_exported":0,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":null} {"id":"variable:2a0c00fec19253efc994ef6afb4eb8bd","kind":"variable","name":"cpuhp_state","qualified_name":"cpuhp_state","file_path":"torture.c","language":"c","start_line":97,"end_line":99,"start_column":35,"end_column":1,"docstring":"---- deferral round 2 (the linux-idiom preParse family) --------------------\nEvery shape below used to drop the WHOLE file into error recovery (and\ntherefore defer it to wasm). Each now parses via a round-2 blank/rewrite;\nthis section pins kernel-vs-wasm parity on all of them at once.\nfile-scope prefixed declaration macros — whole-line blank\ninitialized per-cpu declaration — the REWRITE (type + name survive)","signature":"= {\n .fd = 1,\n}","visibility":null,"is_exported":1,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":null} {"id":"variable:2b617ae851391aec3cce4ab34663df46","kind":"variable","name":"md_rooted","qualified_name":"md_rooted","file_path":"torture.luau","language":"luau","start_line":67,"end_line":67,"start_column":6,"end_column":15,"docstring":null,"signature":"= \"/docs/rooted.md\"","visibility":null,"is_exported":0,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":null} @@ -1759,7 +1765,6 @@ {"id":"variable:5c2476d778ac4e63728eb013a773fbac","kind":"variable","name":"x2","qualified_name":"x2","file_path":"torture.R","language":"r","start_line":28,"end_line":28,"start_column":0,"end_column":8,"docstring":null,"signature":null,"visibility":null,"is_exported":0,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":null} {"id":"variable:5c92c8f07975e49e2066cf90d65d4e3e","kind":"variable","name":"s2","qualified_name":"s2","file_path":"torture.lua","language":"lua","start_line":102,"end_line":102,"start_column":6,"end_column":8,"docstring":null,"signature":"= [==[nested ]] ok]==]","visibility":null,"is_exported":0,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":null} {"id":"variable:5cbfbd2a59a71a50f9a1ce36a6858ef9","kind":"variable","name":"MD_TWO_IN_ONE","qualified_name":"MD_TWO_IN_ONE","file_path":"torture.rs","language":"rust","start_line":309,"end_line":309,"start_column":6,"end_column":19,"docstring":null,"signature":null,"visibility":null,"is_exported":0,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":null} -{"id":"variable:5fcf61afe5e989403b634479bb7f684a","kind":"variable","name":"mdRemote","qualified_name":"mdRemote","file_path":"torture.go","language":"go","start_line":140,"end_line":140,"start_column":4,"end_column":46,"docstring":null,"signature":"= \"https://example.com/remote.md\"","visibility":null,"is_exported":0,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":null} {"id":"variable:6220c3d7eef20669a8b80503fb692f8a","kind":"variable","name":"md_escapes","qualified_name":"md_escapes","file_path":"torture.R","language":"r","start_line":213,"end_line":213,"start_column":0,"end_column":38,"docstring":null,"signature":null,"visibility":null,"is_exported":0,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":null} {"id":"variable:6adfcec1106f14a610956b32cf60e621","kind":"variable","name":"CLASS_LIMIT","qualified_name":"Documented::CLASS_LIMIT","file_path":"torture.rb","language":"ruby","start_line":58,"end_line":58,"start_column":2,"end_column":17,"docstring":null,"signature":"= 9","visibility":null,"is_exported":0,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":null} {"id":"variable:6b7262d2883839c6f601126f4dd59e9b","kind":"variable","name":"handlerTable","qualified_name":"handlerTable","file_path":"torture.go","language":"go","start_line":13,"end_line":15,"start_column":4,"end_column":1,"docstring":null,"signature":"= map[string]func(int){\n\t\"recv\": TargetCb,\n}","visibility":null,"is_exported":0,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":null} @@ -1776,7 +1781,6 @@ {"id":"variable:7b3f83bd083d272c56d09652de471592","kind":"variable","name":"TOP_LIMIT","qualified_name":"TOP_LIMIT","file_path":"torture.rb","language":"ruby","start_line":10,"end_line":10,"start_column":0,"end_column":15,"docstring":null,"signature":"= 100","visibility":null,"is_exported":0,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":null} {"id":"variable:7b87f33408ea977593aa88e51a783e75","kind":"variable","name":"préfixe","qualified_name":"préfixe","file_path":"torture.luau","language":"luau","start_line":59,"end_line":59,"start_column":6,"end_column":13,"docstring":null,"signature":"= \"café\"","visibility":null,"is_exported":0,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":null} {"id":"variable:7c6b3910f19f92cae4c38a7565832746","kind":"variable","name":"dyn","qualified_name":"dyn","file_path":"torture.lua","language":"lua","start_line":10,"end_line":10,"start_column":6,"end_column":9,"docstring":null,"signature":"= require(dynName)","visibility":null,"is_exported":0,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":null} -{"id":"variable:800eb8cdb0ef790d2cef3a151e6db41c","kind":"variable","name":"mdGuide","qualified_name":"mdGuide","file_path":"torture.go","language":"go","start_line":136,"end_line":136,"start_column":4,"end_column":40,"docstring":"Markdown path references: code -> documentation edges. Every shape the\nnormalizer branches on, so the two arms have to agree about the rejections\n(URL, escape above the root) as well as the emissions.","signature":"= \"../docs/guide.md#install\"","visibility":null,"is_exported":0,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":null} {"id":"variable:81d0ff7eaabc267206fbd5529a482e62","kind":"variable","name":"md_rooted","qualified_name":"md_rooted","file_path":"torture.lua","language":"lua","start_line":114,"end_line":114,"start_column":6,"end_column":15,"docstring":null,"signature":"= \"/docs/rooted.md\"","visibility":null,"is_exported":0,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":null} {"id":"variable:8259711bc12da5017d83b9e8f3bd51a7","kind":"variable","name":"md_bare","qualified_name":"md_bare","file_path":"torture.luau","language":"luau","start_line":66,"end_line":66,"start_column":6,"end_column":13,"docstring":null,"signature":"= \"README.md\"","visibility":null,"is_exported":0,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":null} {"id":"variable:82fce40eeaabd8ccadc6779d37a57209","kind":"variable","name":"one","qualified_name":"one","file_path":"torture.lua","language":"lua","start_line":98,"end_line":98,"start_column":6,"end_column":9,"docstring":null,"signature":"= 1","visibility":null,"is_exported":0,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":null} @@ -1787,6 +1791,7 @@ {"id":"variable:8fef25ea8abe486ee94190ed47c3644b","kind":"variable","name":"RETRY_LIMITS","qualified_name":"RETRY_LIMITS","file_path":"torture.py","language":"python","start_line":8,"end_line":8,"start_column":0,"end_column":23,"docstring":null,"signature":"= {\"a\": 1}","visibility":null,"is_exported":1,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":null} {"id":"variable:96a031e283e601ba4b3a8a5a2e9cc77f","kind":"variable","name":"core","qualified_name":"core","file_path":"torture.lua","language":"lua","start_line":4,"end_line":4,"start_column":6,"end_column":10,"docstring":"File-header comment run line 1\nline 2 of the run","signature":"= require(\"app.core\")","visibility":null,"is_exported":0,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":null} {"id":"variable:9b11e2d2271460cf5d5c12d00f607ca1","kind":"variable","name":"INIT_EAGER","qualified_name":"INIT_EAGER","file_path":"torture.py","language":"python","start_line":52,"end_line":52,"start_column":0,"end_column":21,"docstring":null,"signature":"= helper()","visibility":null,"is_exported":1,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":null} +{"id":"variable:9ebd601a4fad63af418ac0bc8c0ec04c","kind":"variable","name":"mdRemote","qualified_name":"mdRemote","file_path":"torture.go","language":"go","start_line":181,"end_line":181,"start_column":4,"end_column":46,"docstring":null,"signature":"= \"https://example.com/remote.md\"","visibility":null,"is_exported":0,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":null} {"id":"variable:9fb41be398c637882380aa0ca5e183b4","kind":"variable","name":"UPPER_CONST","qualified_name":"UPPER_CONST","file_path":"torture.lua","language":"lua","start_line":33,"end_line":33,"start_column":6,"end_column":17,"docstring":null,"signature":"= 42","visibility":null,"is_exported":0,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":null} {"id":"variable:9fc45d7622662ba5576f1caf82a1db04","kind":"variable","name":"x","qualified_name":"x","file_path":"torture.lua","language":"lua","start_line":103,"end_line":103,"start_column":6,"end_column":7,"docstring":null,"signature":"= 99","visibility":null,"is_exported":0,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":null} {"id":"variable:a3010762100ceede1704e3bb28ca9968","kind":"variable","name":"bar","qualified_name":"decl_types::bar","file_path":"torture.cpp","language":"cpp","start_line":121,"end_line":121,"start_column":26,"end_column":29,"docstring":null,"signature":null,"visibility":null,"is_exported":1,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":null} @@ -1796,6 +1801,7 @@ {"id":"variable:a811f3247c619993a74bd06169ef8003","kind":"variable","name":"dup_var","qualified_name":"dup_var","file_path":"torture.R","language":"r","start_line":188,"end_line":188,"start_column":0,"end_column":12,"docstring":null,"signature":null,"visibility":null,"is_exported":0,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":null} {"id":"variable:a811f3247c619993a74bd06169ef8003:14","kind":"variable","name":"dup_var","qualified_name":"dup_var","file_path":"torture.R","language":"r","start_line":188,"end_line":188,"start_column":14,"end_column":26,"docstring":null,"signature":null,"visibility":null,"is_exported":0,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":null} {"id":"variable:acd0d7053b14d1a5ab405005581fcc7b","kind":"variable","name":"INIT_ALIAS","qualified_name":"INIT_ALIAS","file_path":"torture.rs","language":"rust","start_line":291,"end_line":291,"start_column":7,"end_column":17,"docstring":null,"signature":null,"visibility":null,"is_exported":0,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":null} +{"id":"variable:adb6634d66354e5a2f46a0cd4ab58050","kind":"variable","name":"mdTwoInOne","qualified_name":"mdTwoInOne","file_path":"torture.go","language":"go","start_line":183,"end_line":183,"start_column":4,"end_column":46,"docstring":null,"signature":"= \"see a.md and also sub/b.mdx\"","visibility":null,"is_exported":0,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":null} {"id":"variable:ae80428a1b53633b9c3cbce4411dc5e0","kind":"variable","name":"md_two_in_one","qualified_name":"md_two_in_one","file_path":"torture.R","language":"r","start_line":216,"end_line":216,"start_column":0,"end_column":46,"docstring":null,"signature":null,"visibility":null,"is_exported":0,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":null} {"id":"variable:b0140d6f939baa22cf37e9ceb649296a","kind":"variable","name":"counter","qualified_name":"Session::counter","file_path":"torture.swift","language":"swift","start_line":10,"end_line":10,"start_column":2,"end_column":24,"docstring":null,"signature":null,"visibility":"internal","is_exported":0,"is_async":0,"is_static":1,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":null} {"id":"variable:b2096ca0d0fb7b488116cbaa8064123a","kind":"variable","name":"MD_ESCAPES","qualified_name":"MD_ESCAPES","file_path":"torture.rb","language":"ruby","start_line":240,"end_line":240,"start_column":0,"end_column":37,"docstring":null,"signature":"= '../../../../outside.md'","visibility":null,"is_exported":0,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":null} @@ -1810,34 +1816,35 @@ {"id":"variable:bd3123c2d8b795f8be0ffe79b04b4849","kind":"variable","name":"RETRY_MAX","qualified_name":"RETRY_MAX","file_path":"torture.rb","language":"ruby","start_line":11,"end_line":11,"start_column":0,"end_column":13,"docstring":null,"signature":"= 3","visibility":null,"is_exported":0,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":null} {"id":"variable:bf2954d02fcbda60d24c41d412ca4ee9","kind":"variable","name":"MD_ESCAPES","qualified_name":"MD_ESCAPES","file_path":"torture.rs","language":"rust","start_line":306,"end_line":306,"start_column":6,"end_column":16,"docstring":null,"signature":null,"visibility":null,"is_exported":0,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":null} {"id":"variable:c23cd3435fea1505587b5a4809da3f5e","kind":"variable","name":"INIT_LAZY","qualified_name":"INIT_LAZY","file_path":"torture.rs","language":"rust","start_line":290,"end_line":290,"start_column":7,"end_column":16,"docstring":null,"signature":null,"visibility":null,"is_exported":0,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":null} +{"id":"variable:c460b12b198d9c2ffe3164cd43876109","kind":"variable","name":"mdEscapes","qualified_name":"mdEscapes","file_path":"torture.go","language":"go","start_line":180,"end_line":180,"start_column":4,"end_column":40,"docstring":null,"signature":"= \"../../../../outside.md\"","visibility":null,"is_exported":0,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":null} {"id":"variable:c82f8b71ef680df0fd17cb09af4e970b","kind":"variable","name":"piped","qualified_name":"piped","file_path":"torture.R","language":"r","start_line":200,"end_line":200,"start_column":0,"end_column":25,"docstring":null,"signature":null,"visibility":null,"is_exported":0,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":null} {"id":"variable:c875e8abf5e83b47e8f6ef7b75a87498","kind":"variable","name":"quoted","qualified_name":"quoted","file_path":"torture.lua","language":"lua","start_line":6,"end_line":6,"start_column":6,"end_column":12,"docstring":null,"signature":"= require 'app.quoted'","visibility":null,"is_exported":0,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":null} {"id":"variable:c894021aa1d161a9e838078ff40e180b","kind":"variable","name":"md_guide","qualified_name":"md_guide","file_path":"torture.R","language":"r","start_line":210,"end_line":210,"start_column":0,"end_column":38,"docstring":null,"signature":null,"visibility":null,"is_exported":0,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":null} {"id":"variable:cd9e9fe748d0f3513f7f6c6c74264f2c","kind":"variable","name":"MD_BARE","qualified_name":"MD_BARE","file_path":"torture.rs","language":"rust","start_line":304,"end_line":304,"start_column":6,"end_column":13,"docstring":null,"signature":null,"visibility":null,"is_exported":0,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":null} {"id":"variable:ce402baede726151c63ca285667ad38d","kind":"variable","name":"MD_GUIDE","qualified_name":"MD_GUIDE","file_path":"torture.rs","language":"rust","start_line":303,"end_line":303,"start_column":6,"end_column":14,"docstring":"Markdown path references: code -> documentation edges. Every shape the\nnormalizer branches on, so the two arms have to agree about the rejections\n(URL, escape above the root) as well as the emissions.","signature":null,"visibility":null,"is_exported":0,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":null} +{"id":"variable:d0140163eccfbe839cf7b486e7f09269","kind":"variable","name":"mdBare","qualified_name":"mdBare","file_path":"torture.go","language":"go","start_line":178,"end_line":178,"start_column":4,"end_column":24,"docstring":null,"signature":"= \"README.md\"","visibility":null,"is_exported":0,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":null} {"id":"variable:d05afb272af289f14ee6904b352e652d","kind":"variable","name":"M","qualified_name":"M","file_path":"torture.lua","language":"lua","start_line":32,"end_line":32,"start_column":6,"end_column":7,"docstring":null,"signature":"= {}","visibility":null,"is_exported":0,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":null} {"id":"variable:d5ac0580bbe1c8e68c2b18d6412d5285","kind":"variable","name":"md_rooted","qualified_name":"md_rooted","file_path":"torture.R","language":"r","start_line":212,"end_line":212,"start_column":0,"end_column":30,"docstring":null,"signature":null,"visibility":null,"is_exported":0,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":null} {"id":"variable:dbc613381e28e1df4546b4ebea616589","kind":"variable","name":"result","qualified_name":"result","file_path":"torture.R","language":"r","start_line":161,"end_line":161,"start_column":0,"end_column":39,"docstring":null,"signature":null,"visibility":null,"is_exported":0,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":null} {"id":"variable:dc32e43e11cbd6a5aa9ed4fd06aa4e45","kind":"variable","name":"MD_REMOTE","qualified_name":"MD_REMOTE","file_path":"torture.rb","language":"ruby","start_line":241,"end_line":241,"start_column":0,"end_column":43,"docstring":null,"signature":"= 'https://example.com/remote.md'","visibility":null,"is_exported":0,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":null} {"id":"variable:e01982441782327b70b675a02536d3be","kind":"variable","name":"guarded","qualified_name":"guarded","file_path":"torture.lua","language":"lua","start_line":12,"end_line":12,"start_column":11,"end_column":18,"docstring":null,"signature":null,"visibility":null,"is_exported":0,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":null} {"id":"variable:e226fd913c4b21d87da0115d1007adab","kind":"variable","name":"md_remote","qualified_name":"md_remote","file_path":"torture.luau","language":"luau","start_line":69,"end_line":69,"start_column":6,"end_column":15,"docstring":null,"signature":"= \"https://example.com/remote.md\"","visibility":null,"is_exported":0,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":null} -{"id":"variable:e44edf805f627d7e108028e303a440cd","kind":"variable","name":"mdEscapes","qualified_name":"mdEscapes","file_path":"torture.go","language":"go","start_line":139,"end_line":139,"start_column":4,"end_column":40,"docstring":null,"signature":"= \"../../../../outside.md\"","visibility":null,"is_exported":0,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":null} -{"id":"variable:e86e18d25431b1b127ce786fcbaa833d","kind":"variable","name":"mdRooted","qualified_name":"mdRooted","file_path":"torture.go","language":"go","start_line":138,"end_line":138,"start_column":4,"end_column":32,"docstring":null,"signature":"= \"/docs/rooted.md\"","visibility":null,"is_exported":0,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":null} +{"id":"variable:e6121ba1baf8c5f551e7d79391a5f970","kind":"variable","name":"mdQueried","qualified_name":"mdQueried","file_path":"torture.go","language":"go","start_line":182,"end_line":182,"start_column":4,"end_column":38,"docstring":null,"signature":"= \"./notes.md?raw=1#top\"","visibility":null,"is_exported":0,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":null} {"id":"variable:e891c0e9e17b31eebb4e60f882c2a520","kind":"variable","name":"A_B_CONST","qualified_name":"A::B::A_B_CONST","file_path":"torture.rb","language":"ruby","start_line":31,"end_line":31,"start_column":2,"end_column":15,"docstring":null,"signature":"= 5","visibility":null,"is_exported":0,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":null} {"id":"variable:ed0f6849f3707109c6ff9afba21baed1","kind":"variable","name":"rs2","qualified_name":"rs2","file_path":"torture.R","language":"r","start_line":197,"end_line":197,"start_column":0,"end_column":8,"docstring":null,"signature":null,"visibility":null,"is_exported":0,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":null} +{"id":"variable:edb5fbbe020242a5060c5fd64110716d","kind":"variable","name":"mdGuide","qualified_name":"mdGuide","file_path":"torture.go","language":"go","start_line":177,"end_line":177,"start_column":4,"end_column":40,"docstring":"Markdown path references: code -> documentation edges. Every shape the\nnormalizer branches on, so the two arms have to agree about the rejections\n(URL, escape above the root) as well as the emissions.","signature":"= \"../docs/guide.md#install\"","visibility":null,"is_exported":0,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":null} {"id":"variable:ee9c6e0fee8889153857dd10264fe3d8","kind":"variable","name":"DISPATCH_TABLE","qualified_name":"DISPATCH_TABLE","file_path":"torture.c","language":"c","start_line":53,"end_line":53,"start_column":12,"end_column":45,"docstring":"fn-ptr table at file scope — the ungated 'list' capture positions.","signature":"= { cb_a, cb_b }","visibility":null,"is_exported":1,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":null} {"id":"variable:efaad7436497114b49f6ec800f159b1e","kind":"variable","name":"state","qualified_name":"decl_types::state","file_path":"torture.cpp","language":"cpp","start_line":123,"end_line":123,"start_column":22,"end_column":27,"docstring":null,"signature":null,"visibility":null,"is_exported":1,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":null} {"id":"variable:f151a47c40a2ea5929850df0150dba2e","kind":"variable","name":"res","qualified_name":"res","file_path":"torture.R","language":"r","start_line":53,"end_line":53,"start_column":0,"end_column":24,"docstring":null,"signature":null,"visibility":null,"is_exported":0,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":null} {"id":"variable:f3b5417555124c6b694cb2bb38b69a36","kind":"variable","name":"viaChild","qualified_name":"viaChild","file_path":"torture.lua","language":"lua","start_line":8,"end_line":8,"start_column":6,"end_column":14,"docstring":null,"signature":"= require(script:WaitForChild(\"Child\"))","visibility":null,"is_exported":0,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":null} {"id":"variable:f5c91b5d428fbf38125a7649d47f4de6","kind":"variable","name":"dotted.var","qualified_name":"dotted.var","file_path":"torture.R","language":"r","start_line":27,"end_line":27,"start_column":0,"end_column":15,"docstring":null,"signature":null,"visibility":null,"is_exported":0,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":null} {"id":"variable:f78d0c729b2be3077931d1a700cb66ca","kind":"variable","name":"MD_GUIDE","qualified_name":"MD_GUIDE","file_path":"torture.rb","language":"ruby","start_line":237,"end_line":237,"start_column":0,"end_column":37,"docstring":"Markdown path references: code -> documentation edges. Every shape the\nnormalizer branches on, so the two arms have to agree about the rejections\n(URL, escape above the root) as well as the emissions.","signature":"= '../docs/guide.md#install'","visibility":null,"is_exported":0,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":null} -{"id":"variable:f86a0cee4e700858bb0604100cdf9f50","kind":"variable","name":"mdTwoInOne","qualified_name":"mdTwoInOne","file_path":"torture.go","language":"go","start_line":142,"end_line":142,"start_column":4,"end_column":46,"docstring":null,"signature":"= \"see a.md and also sub/b.mdx\"","visibility":null,"is_exported":0,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":null} {"id":"variable:f90ca95a6ecd4291f24e8cc99492595f","kind":"variable","name":"md_queried","qualified_name":"md_queried","file_path":"torture.luau","language":"luau","start_line":70,"end_line":70,"start_column":6,"end_column":16,"docstring":null,"signature":"= \"./notes.md?raw=1#top\"","visibility":null,"is_exported":0,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":null} {"id":"variable:fb02f37b8f22f515de132d7d8c361361","kind":"variable","name":"md_guide","qualified_name":"md_guide","file_path":"torture.luau","language":"luau","start_line":65,"end_line":65,"start_column":6,"end_column":14,"docstring":"Markdown path references: code -> documentation edges. Every shape the\nnormalizer branches on, so the two arms have to agree about the rejections\n(URL, escape above the root) as well as the emissions.","signature":"= \"../docs/guide.md#install\"","visibility":null,"is_exported":0,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":null} {"id":"variable:fb450996c12f335b36201ead67a34f64","kind":"variable","name":"INIT_MAP","qualified_name":"INIT_MAP","file_path":"torture.py","language":"python","start_line":54,"end_line":54,"start_column":0,"end_column":26,"docstring":null,"signature":"= {\"a\": helper()}","visibility":null,"is_exported":1,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":null} {"id":"variable:feb330d554c5d0caaa8978323a006e52","kind":"variable","name":"MD_BARE","qualified_name":"MD_BARE","file_path":"torture.rb","language":"ruby","start_line":238,"end_line":238,"start_column":0,"end_column":21,"docstring":null,"signature":"= 'README.md'","visibility":null,"is_exported":0,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":null} {"id":"variable:fedacda34e94b85718ac655a74368326","kind":"variable","name":"okG","qualified_name":"okG","file_path":"torture.lua","language":"lua","start_line":12,"end_line":12,"start_column":6,"end_column":9,"docstring":null,"signature":"= pcall(require, \"app.guarded\")","visibility":null,"is_exported":0,"is_async":0,"is_static":0,"is_abstract":0,"decorators":null,"type_parameters":null,"return_type":null} -== edges (2454) +== edges (2477) {"source":"class:0083dc18baa2b629e8572db20ba2b464","target":"class:25244cbdbe3e9bc720df9fc4d54fac0a","kind":"extends","metadata":"{\"confidence\":0.9,\"resolvedBy\":\"qualified-name\",\"refName\":\"app::Config\"}","line":98,"col":35,"provenance":null} {"source":"class:0083dc18baa2b629e8572db20ba2b464","target":"method:0795ac46f5bef3826c20039a05014ebc","kind":"contains","metadata":null,"line":null,"col":null,"provenance":null} {"source":"class:0083dc18baa2b629e8572db20ba2b464","target":"method:35a476809e2727e80d7f2c8c404180b2","kind":"contains","metadata":null,"line":null,"col":null,"provenance":null} @@ -3115,53 +3122,57 @@ {"source":"file:torture.dart","target":"type_alias:544f3be472935dfbe579fa190ead63ab","kind":"contains","metadata":null,"line":null,"col":null,"provenance":null} {"source":"file:torture.dart","target":"type_alias:813393b308ca1d8f278ce99d55bf11d7","kind":"contains","metadata":null,"line":null,"col":null,"provenance":null} {"source":"file:torture.go","target":"constant:0558b57204d51fcce0a73629df252447","kind":"contains","metadata":null,"line":null,"col":null,"provenance":null} -{"source":"file:torture.go","target":"function:0e1ad124e719c2d18615cda6816af46c","kind":"contains","metadata":null,"line":null,"col":null,"provenance":null} -{"source":"file:torture.go","target":"function:0e1ad124e719c2d18615cda6816af46c","kind":"references","metadata":"{\"confidence\":0.95,\"resolvedBy\":\"function-ref\",\"refName\":\"TargetCb\",\"refKind\":\"function_ref\",\"fnRef\":true}","line":14,"col":9,"provenance":null} -{"source":"file:torture.go","target":"function:140cc1d2e83fc5a1968f8058b5457dd1","kind":"contains","metadata":null,"line":null,"col":null,"provenance":null} -{"source":"file:torture.go","target":"function:179a74d774cb7efadf2594cebb29f4a9","kind":"contains","metadata":null,"line":null,"col":null,"provenance":null} -{"source":"file:torture.go","target":"function:46864a1a62b2fd2a4e1657a52005c4e7","kind":"contains","metadata":null,"line":null,"col":null,"provenance":null} -{"source":"file:torture.go","target":"function:5caa38feff95389d550207e842f7ac7e","kind":"contains","metadata":null,"line":null,"col":null,"provenance":null} -{"source":"file:torture.go","target":"function:ffbfbea1bf90b2536f05eed532eb53ce","kind":"contains","metadata":null,"line":null,"col":null,"provenance":null} +{"source":"file:torture.go","target":"function:55a555881f22d77e916122b15425f092","kind":"contains","metadata":null,"line":null,"col":null,"provenance":null} +{"source":"file:torture.go","target":"function:815f561efb2f5946fda7806c34dbd966","kind":"contains","metadata":null,"line":null,"col":null,"provenance":null} +{"source":"file:torture.go","target":"function:81cc5b0d788ee9727656191bb6a35597","kind":"contains","metadata":null,"line":null,"col":null,"provenance":null} +{"source":"file:torture.go","target":"function:8307a8a823f2c272e33236a2f73c9f60","kind":"contains","metadata":null,"line":null,"col":null,"provenance":null} +{"source":"file:torture.go","target":"function:a832b3ad2e6b57ff9463fbd6c86c5a97","kind":"contains","metadata":null,"line":null,"col":null,"provenance":null} +{"source":"file:torture.go","target":"function:a832b3ad2e6b57ff9463fbd6c86c5a97","kind":"references","metadata":"{\"confidence\":0.95,\"resolvedBy\":\"function-ref\",\"refName\":\"TargetCb\",\"refKind\":\"function_ref\",\"fnRef\":true}","line":14,"col":9,"provenance":null} +{"source":"file:torture.go","target":"function:fd52d5daf195fabf0870d2a4c709d61f","kind":"contains","metadata":null,"line":null,"col":null,"provenance":null} {"source":"file:torture.go","target":"import:17cf6081e0b98e781b1b457772f3dd34","kind":"contains","metadata":null,"line":null,"col":null,"provenance":null} {"source":"file:torture.go","target":"import:64743408a7371afefc7768c546b83fb2","kind":"contains","metadata":null,"line":null,"col":null,"provenance":null} -{"source":"file:torture.go","target":"interface:5a28b97ecb59911dbe27ad63e859459d","kind":"contains","metadata":null,"line":null,"col":null,"provenance":null} -{"source":"file:torture.go","target":"interface:8045ff3999885f68bd3b9b0e8709aeeb","kind":"contains","metadata":null,"line":null,"col":null,"provenance":null} -{"source":"file:torture.go","target":"interface:87965a8e467d41375154fe8ae108b529","kind":"contains","metadata":null,"line":null,"col":null,"provenance":null} -{"source":"file:torture.go","target":"interface:c15bd0cb4f4a33ae49f280e29878fb61","kind":"contains","metadata":null,"line":null,"col":null,"provenance":null} -{"source":"file:torture.go","target":"method:72417d24bc1311c2e420094c5d05c459","kind":"contains","metadata":null,"line":null,"col":null,"provenance":null} -{"source":"file:torture.go","target":"method:ae63e6f68d18ae3e3794926b4f75768b","kind":"contains","metadata":null,"line":null,"col":null,"provenance":null} -{"source":"file:torture.go","target":"struct:2062166f706221e2d500e7d9807245d9","kind":"contains","metadata":null,"line":null,"col":null,"provenance":null} +{"source":"file:torture.go","target":"interface:3003e30a3fc9ee8bf1f1153918085038","kind":"contains","metadata":null,"line":null,"col":null,"provenance":null} +{"source":"file:torture.go","target":"interface:3970ad34905c85bf731cae6e1386687f","kind":"contains","metadata":null,"line":null,"col":null,"provenance":null} +{"source":"file:torture.go","target":"interface:479db15a71788832458ca8ffe80aba83","kind":"contains","metadata":null,"line":null,"col":null,"provenance":null} +{"source":"file:torture.go","target":"interface:6ed108f5ca6c8f6b9f40a746e9396c03","kind":"contains","metadata":null,"line":null,"col":null,"provenance":null} +{"source":"file:torture.go","target":"interface:b5773212ca0e5396a677e9062f68d204","kind":"contains","metadata":null,"line":null,"col":null,"provenance":null} +{"source":"file:torture.go","target":"method:24ccc96de44e1d4e1608658cfe083a33","kind":"contains","metadata":null,"line":null,"col":null,"provenance":null} +{"source":"file:torture.go","target":"method:a6d269b87546a3383d51ca2de232a1de","kind":"contains","metadata":null,"line":null,"col":null,"provenance":null} {"source":"file:torture.go","target":"struct:33e3531d750b08f5b854203467928f28","kind":"contains","metadata":null,"line":null,"col":null,"provenance":null} +{"source":"file:torture.go","target":"struct:44d6f0ea6746cda4ce3d410ce9c99a46","kind":"contains","metadata":null,"line":null,"col":null,"provenance":null} {"source":"file:torture.go","target":"struct:4c67fc2c851f10cf7803489ef577fc3c","kind":"contains","metadata":null,"line":null,"col":null,"provenance":null} -{"source":"file:torture.go","target":"type_alias:10728d965a9856b988bb2359a09666f9","kind":"contains","metadata":null,"line":null,"col":null,"provenance":null} -{"source":"file:torture.go","target":"type_alias:2652fcdf36b42377e527cf35f8d800c9","kind":"contains","metadata":null,"line":null,"col":null,"provenance":null} -{"source":"file:torture.go","target":"type_alias:27e49398ec8ebe39651fd8822e253a54","kind":"contains","metadata":null,"line":null,"col":null,"provenance":null} -{"source":"file:torture.go","target":"type_alias:27e7afa3d9358e091e23f4ee6e495fc5","kind":"contains","metadata":null,"line":null,"col":null,"provenance":null} -{"source":"file:torture.go","target":"type_alias:44cb4653a5e07bdcee1050ba3133ab31","kind":"contains","metadata":null,"line":null,"col":null,"provenance":null} -{"source":"file:torture.go","target":"type_alias:4b2d750ab1f528d33a2d6713cb2193a7","kind":"contains","metadata":null,"line":null,"col":null,"provenance":null} -{"source":"file:torture.go","target":"type_alias:70a70301f02c5dd34c45fea884736d5d","kind":"contains","metadata":null,"line":null,"col":null,"provenance":null} -{"source":"file:torture.go","target":"type_alias:75662b893c34aed98e64700a6d01bf8d","kind":"contains","metadata":null,"line":null,"col":null,"provenance":null} -{"source":"file:torture.go","target":"type_alias:80c39c4f28c27d78ecdedc474ae4af7b","kind":"contains","metadata":null,"line":null,"col":null,"provenance":null} -{"source":"file:torture.go","target":"type_alias:99498bda61debd01b2e7459030084c24","kind":"contains","metadata":null,"line":null,"col":null,"provenance":null} -{"source":"file:torture.go","target":"type_alias:a54bf143682054f499fe157e6b733087","kind":"contains","metadata":null,"line":null,"col":null,"provenance":null} -{"source":"file:torture.go","target":"type_alias:bb8bd8650e34457304e34b86851c1431","kind":"contains","metadata":null,"line":null,"col":null,"provenance":null} -{"source":"file:torture.go","target":"type_alias:c0ad8af1b5e37e6ad90fd0c5790b6209","kind":"contains","metadata":null,"line":null,"col":null,"provenance":null} -{"source":"file:torture.go","target":"type_alias:c925710f298dd798808037fcf660f73b","kind":"contains","metadata":null,"line":null,"col":null,"provenance":null} -{"source":"file:torture.go","target":"type_alias:d4964291bed60f871ad9554b4572ac9b","kind":"contains","metadata":null,"line":null,"col":null,"provenance":null} -{"source":"file:torture.go","target":"type_alias:d9cf57aaa8c6be0b025ae6b685745a39","kind":"contains","metadata":null,"line":null,"col":null,"provenance":null} -{"source":"file:torture.go","target":"type_alias:df1bf626c237f1dfe84e753a6edace47","kind":"contains","metadata":null,"line":null,"col":null,"provenance":null} -{"source":"file:torture.go","target":"type_alias:e67f0306e684e2b34de4b379a1546426","kind":"contains","metadata":null,"line":null,"col":null,"provenance":null} -{"source":"file:torture.go","target":"type_alias:f61f67035897704f4a03cf76fb59e8a9","kind":"contains","metadata":null,"line":null,"col":null,"provenance":null} -{"source":"file:torture.go","target":"type_alias:ff4b77836c3d72b57438c1723760af51","kind":"contains","metadata":null,"line":null,"col":null,"provenance":null} -{"source":"file:torture.go","target":"variable:07821b80e054d5ee85de38b0c45e1662","kind":"contains","metadata":null,"line":null,"col":null,"provenance":null} +{"source":"file:torture.go","target":"struct:6b80d8f1dbee1c34e187c63b7e616a70","kind":"contains","metadata":null,"line":null,"col":null,"provenance":null} +{"source":"file:torture.go","target":"struct:ad8421763ee39344ef65f68fc90dd015","kind":"contains","metadata":null,"line":null,"col":null,"provenance":null} +{"source":"file:torture.go","target":"struct:b5d2c300d801f1233941b73d992ba7eb","kind":"contains","metadata":null,"line":null,"col":null,"provenance":null} +{"source":"file:torture.go","target":"type_alias:02bad22974119233684c4cdc31b84c08","kind":"contains","metadata":null,"line":null,"col":null,"provenance":null} +{"source":"file:torture.go","target":"type_alias:056dd5fe2cc3e2ad87323386146effcc","kind":"contains","metadata":null,"line":null,"col":null,"provenance":null} +{"source":"file:torture.go","target":"type_alias:09f9cb5669970256407b8aebd0528e7d","kind":"contains","metadata":null,"line":null,"col":null,"provenance":null} +{"source":"file:torture.go","target":"type_alias:1bc21f6b21632fe87943700ca4573be4","kind":"contains","metadata":null,"line":null,"col":null,"provenance":null} +{"source":"file:torture.go","target":"type_alias:2a5e03d369bc91073bc0792b6964ac16","kind":"contains","metadata":null,"line":null,"col":null,"provenance":null} +{"source":"file:torture.go","target":"type_alias:439984898e3d20cbd0156ea66c4aab37","kind":"contains","metadata":null,"line":null,"col":null,"provenance":null} +{"source":"file:torture.go","target":"type_alias:55981ee7594cc71cc0d5283a993cd5f2","kind":"contains","metadata":null,"line":null,"col":null,"provenance":null} +{"source":"file:torture.go","target":"type_alias:5d4689c66e6a4956859f7b921c3610c8","kind":"contains","metadata":null,"line":null,"col":null,"provenance":null} +{"source":"file:torture.go","target":"type_alias:5fab20424fd8ff6f365fbb0e5eec9c84","kind":"contains","metadata":null,"line":null,"col":null,"provenance":null} +{"source":"file:torture.go","target":"type_alias:608221a5f58d68322f43ee54c190640e","kind":"contains","metadata":null,"line":null,"col":null,"provenance":null} +{"source":"file:torture.go","target":"type_alias:771117de3df76a903822e0fab4467df8","kind":"contains","metadata":null,"line":null,"col":null,"provenance":null} +{"source":"file:torture.go","target":"type_alias:882c227f07ef59b639ecf2c0cfb69f1c","kind":"contains","metadata":null,"line":null,"col":null,"provenance":null} +{"source":"file:torture.go","target":"type_alias:965915e648eebc2c230c7f5df6ca9700","kind":"contains","metadata":null,"line":null,"col":null,"provenance":null} +{"source":"file:torture.go","target":"type_alias:a10c4f47aeab87402ced28d09f54ddfb","kind":"contains","metadata":null,"line":null,"col":null,"provenance":null} +{"source":"file:torture.go","target":"type_alias:a9e7f1010d06f6bbc8039f4b63877b56","kind":"contains","metadata":null,"line":null,"col":null,"provenance":null} +{"source":"file:torture.go","target":"type_alias:b826ea0f1f4d158a41ccfe0c21c225f3","kind":"contains","metadata":null,"line":null,"col":null,"provenance":null} +{"source":"file:torture.go","target":"type_alias:c9336784d0211d92b205b7194a5ce3a7","kind":"contains","metadata":null,"line":null,"col":null,"provenance":null} +{"source":"file:torture.go","target":"type_alias:c9fe81e444d43593fc382a0be628bc66","kind":"contains","metadata":null,"line":null,"col":null,"provenance":null} +{"source":"file:torture.go","target":"type_alias:d1df73c8269ea5dd18f9aaaac0a8088d","kind":"contains","metadata":null,"line":null,"col":null,"provenance":null} +{"source":"file:torture.go","target":"type_alias:f6d4e998f3c2200dadf5c1e05f9368ab","kind":"contains","metadata":null,"line":null,"col":null,"provenance":null} +{"source":"file:torture.go","target":"variable:1408b0cc15b4db6aa165d25216f1f59a","kind":"contains","metadata":null,"line":null,"col":null,"provenance":null} {"source":"file:torture.go","target":"variable:1837cd19ce5f7a8f45b7fa4b8fc8a0e6","kind":"contains","metadata":null,"line":null,"col":null,"provenance":null} -{"source":"file:torture.go","target":"variable:275e942a48e8d317edfcc10e72224781","kind":"contains","metadata":null,"line":null,"col":null,"provenance":null} -{"source":"file:torture.go","target":"variable:5fcf61afe5e989403b634479bb7f684a","kind":"contains","metadata":null,"line":null,"col":null,"provenance":null} {"source":"file:torture.go","target":"variable:6b7262d2883839c6f601126f4dd59e9b","kind":"contains","metadata":null,"line":null,"col":null,"provenance":null} -{"source":"file:torture.go","target":"variable:800eb8cdb0ef790d2cef3a151e6db41c","kind":"contains","metadata":null,"line":null,"col":null,"provenance":null} -{"source":"file:torture.go","target":"variable:e44edf805f627d7e108028e303a440cd","kind":"contains","metadata":null,"line":null,"col":null,"provenance":null} -{"source":"file:torture.go","target":"variable:e86e18d25431b1b127ce786fcbaa833d","kind":"contains","metadata":null,"line":null,"col":null,"provenance":null} -{"source":"file:torture.go","target":"variable:f86a0cee4e700858bb0604100cdf9f50","kind":"contains","metadata":null,"line":null,"col":null,"provenance":null} +{"source":"file:torture.go","target":"variable:9ebd601a4fad63af418ac0bc8c0ec04c","kind":"contains","metadata":null,"line":null,"col":null,"provenance":null} +{"source":"file:torture.go","target":"variable:adb6634d66354e5a2f46a0cd4ab58050","kind":"contains","metadata":null,"line":null,"col":null,"provenance":null} +{"source":"file:torture.go","target":"variable:c460b12b198d9c2ffe3164cd43876109","kind":"contains","metadata":null,"line":null,"col":null,"provenance":null} +{"source":"file:torture.go","target":"variable:d0140163eccfbe839cf7b486e7f09269","kind":"contains","metadata":null,"line":null,"col":null,"provenance":null} +{"source":"file:torture.go","target":"variable:e6121ba1baf8c5f551e7d79391a5f970","kind":"contains","metadata":null,"line":null,"col":null,"provenance":null} +{"source":"file:torture.go","target":"variable:edb5fbbe020242a5060c5fd64110716d","kind":"contains","metadata":null,"line":null,"col":null,"provenance":null} {"source":"file:torture.hpp","target":"class:da855a76803320806ba08457a72b59fa","kind":"contains","metadata":null,"line":null,"col":null,"provenance":null} {"source":"file:torture.hpp","target":"function:a07d8ba50e32351d67a5892444ec6842","kind":"contains","metadata":null,"line":null,"col":null,"provenance":null} {"source":"file:torture.hpp","target":"method:ca160b191e7fb257769f213a8450ab4c","kind":"contains","metadata":null,"line":null,"col":null,"provenance":null} @@ -3653,9 +3664,6 @@ {"source":"function:5b434632abf9fbeb07e0a630ec66d9d3","target":"method:de718159205cba9b0d17647ac71f8f2a","kind":"calls","metadata":"{\"confidence\":0.9,\"resolvedBy\":\"instance-method\",\"refName\":\"w.render\"}","line":182,"col":4,"provenance":null} {"source":"function:5b434632abf9fbeb07e0a630ec66d9d3","target":"method:de718159205cba9b0d17647ac71f8f2a","kind":"calls","metadata":"{\"confidence\":0.9,\"resolvedBy\":\"instance-method\",\"refName\":\"w.render\"}","line":214,"col":34,"provenance":null} {"source":"function:5b434632abf9fbeb07e0a630ec66d9d3","target":"method:e947ab8444253c3743504176397bb986","kind":"calls","metadata":"{\"confidence\":0.9,\"resolvedBy\":\"instance-method\",\"refName\":\"WidgetK.create\"}","line":189,"col":4,"provenance":null} -{"source":"function:5caa38feff95389d550207e842f7ac7e","target":"type_alias:a54bf143682054f499fe157e6b733087","kind":"references","metadata":"{\"confidence\":0.9,\"resolvedBy\":\"exact-match\",\"refName\":\"Alias\"}","line":101,"col":17,"provenance":null} -{"source":"function:5caa38feff95389d550207e842f7ac7e","target":"type_alias:bb8bd8650e34457304e34b86851c1431","kind":"instantiates","metadata":"{\"confidence\":0.9,\"resolvedBy\":\"exact-match\",\"refName\":\"LocalAlias\"}","line":102,"col":8,"provenance":null} -{"source":"function:5caa38feff95389d550207e842f7ac7e","target":"type_alias:bb8bd8650e34457304e34b86851c1431","kind":"references","metadata":"{\"confidence\":0.9,\"resolvedBy\":\"exact-match\",\"refName\":\"LocalAlias\"}","line":101,"col":24,"provenance":null} {"source":"function:63d9de443c4037dc8b215d1a36090856","target":"import:45a9713638e09bad6f7c9947b6689b11","kind":"contains","metadata":null,"line":null,"col":null,"provenance":null} {"source":"function:64514e020343f839129de60fb3d0e82a","target":"function:d34b72d7848b01f2bb9cc6eea3206a67","kind":"calls","metadata":"{\"confidence\":0.9,\"resolvedBy\":\"exact-match\",\"refName\":\"add\"}","line":49,"col":32,"provenance":null} {"source":"function:676efed68fe8c7f7281531530ae6ae6f","target":"class:89a6327dc2e1da4b990c740c891aaa96","kind":"references","metadata":"{\"confidence\":0.4,\"resolvedBy\":\"exact-match\",\"refName\":\"Session\"}","line":158,"col":17,"provenance":null} @@ -3677,8 +3685,12 @@ {"source":"function:7a0b33da86ba854a62dfdbc9159b1318","target":"field:c798d3703257f8a5dfbd95045e25247e","kind":"calls","metadata":"{\"confidence\":0.9,\"resolvedBy\":\"field-call\",\"refName\":\"c.on_recv\"}","line":77,"col":2,"provenance":null} {"source":"function:7a0b33da86ba854a62dfdbc9159b1318","target":"variable:ee9c6e0fee8889153857dd10264fe3d8","kind":"references","metadata":"{\"valueRef\":true}","line":null,"col":null,"provenance":null} {"source":"function:80c7293664161116a029e8aa43f2becf","target":"enum:62b26973d47047974a3723ff3d5d23ee","kind":"references","metadata":"{\"confidence\":0.9,\"resolvedBy\":\"exact-match\",\"refName\":\"Suit\"}","line":179,"col":10,"provenance":null} +{"source":"function:815f561efb2f5946fda7806c34dbd966","target":"type_alias:09f9cb5669970256407b8aebd0528e7d","kind":"instantiates","metadata":"{\"confidence\":0.9,\"resolvedBy\":\"exact-match\",\"refName\":\"LocalAlias\"}","line":143,"col":8,"provenance":null} +{"source":"function:815f561efb2f5946fda7806c34dbd966","target":"type_alias:09f9cb5669970256407b8aebd0528e7d","kind":"references","metadata":"{\"confidence\":0.9,\"resolvedBy\":\"exact-match\",\"refName\":\"LocalAlias\"}","line":142,"col":24,"provenance":null} +{"source":"function:815f561efb2f5946fda7806c34dbd966","target":"type_alias:1bc21f6b21632fe87943700ca4573be4","kind":"references","metadata":"{\"confidence\":0.9,\"resolvedBy\":\"exact-match\",\"refName\":\"Alias\"}","line":142,"col":17,"provenance":null} {"source":"function:81ba5a98d0931cbf162f4338fae53766","target":"class:00e4c67aff13a714886744f6829e0cea","kind":"references","metadata":"{\"confidence\":0.9,\"resolvedBy\":\"exact-match\",\"refName\":\"Cfg\"}","line":65,"col":6,"provenance":null} {"source":"function:81ba5a98d0931cbf162f4338fae53766","target":"constant:b856b01947367087fe9201022f432145","kind":"references","metadata":"{\"valueRef\":true}","line":null,"col":null,"provenance":null} +{"source":"function:81cc5b0d788ee9727656191bb6a35597","target":"struct:33e3531d750b08f5b854203467928f28","kind":"instantiates","metadata":"{\"confidence\":0.9,\"resolvedBy\":\"exact-match\",\"refName\":\"Widget\"}","line":147,"col":6,"provenance":null} {"source":"function:893e190d6be04144b7ebe001bdd3cdba","target":"function:077abb142cd38f50fd7aeb4958ac54b7","kind":"calls","metadata":"{\"confidence\":0.9,\"resolvedBy\":\"exact-match\",\"refName\":\"register\"}","line":103,"col":10,"provenance":null} {"source":"function:893e190d6be04144b7ebe001bdd3cdba","target":"function:e47ec30588abc2975d100ed00651ad8a","kind":"references","metadata":"{\"confidence\":0.95,\"resolvedBy\":\"function-ref\",\"refName\":\"blockDoc\",\"refKind\":\"function_ref\",\"fnRef\":true}","line":105,"col":27,"provenance":null} {"source":"function:893e190d6be04144b7ebe001bdd3cdba","target":"function:e4aabfa896d12d328d860b0b6db8b41f","kind":"references","metadata":"{\"confidence\":0.95,\"resolvedBy\":\"function-ref\",\"refName\":\"topLevel\",\"refKind\":\"function_ref\",\"fnRef\":true}","line":103,"col":11,"provenance":null} @@ -3791,15 +3803,17 @@ {"source":"function:fa31a4bba4af75d85403a627a9e62897","target":"module:3e98a45ef089de69c402c540a05c492e","kind":"references","metadata":"{\"confidence\":0.4,\"resolvedBy\":\"exact-match\",\"refName\":\"WidgetS\"}","line":108,"col":17,"provenance":null} {"source":"function:fa31a4bba4af75d85403a627a9e62897","target":"module:3e98a45ef089de69c402c540a05c492e","kind":"references","metadata":"{\"confidence\":0.4,\"resolvedBy\":\"exact-match\",\"refName\":\"WidgetS\"}","line":108,"col":29,"provenance":null} {"source":"function:fcd5e95c35b0d729f302762b3d2c7201","target":"function:d34b72d7848b01f2bb9cc6eea3206a67","kind":"calls","metadata":"{\"confidence\":0.9,\"resolvedBy\":\"exact-match\",\"refName\":\"add\"}","line":50,"col":32,"provenance":null} -{"source":"function:ffbfbea1bf90b2536f05eed532eb53ce","target":"struct:33e3531d750b08f5b854203467928f28","kind":"instantiates","metadata":"{\"confidence\":0.9,\"resolvedBy\":\"exact-match\",\"refName\":\"Widget\"}","line":106,"col":6,"provenance":null} {"source":"interface:24159e084fc50d320c624ae5b6655041","target":"constant:fb9e37e5fcc4a7b9c8eb331327e95331","kind":"contains","metadata":null,"line":null,"col":null,"provenance":null} {"source":"interface:24159e084fc50d320c624ae5b6655041","target":"method:def1d5aea454ef9901acfcaf7964e646","kind":"contains","metadata":null,"line":null,"col":null,"provenance":null} +{"source":"interface:3003e30a3fc9ee8bf1f1153918085038","target":"method:849d12c566dceb8c4bfcf1e81b828752","kind":"contains","metadata":null,"line":null,"col":null,"provenance":null} +{"source":"interface:3970ad34905c85bf731cae6e1386687f","target":"method:598927e1a898855d3029efb1ca0f4966","kind":"contains","metadata":null,"line":null,"col":null,"provenance":null} +{"source":"interface:3970ad34905c85bf731cae6e1386687f","target":"method:a5cd5e67746962200f8230ebedb5413e","kind":"contains","metadata":null,"line":null,"col":null,"provenance":null} +{"source":"interface:3970ad34905c85bf731cae6e1386687f","target":"method:dc018b19c95524f99100bf15538c815b","kind":"contains","metadata":null,"line":null,"col":null,"provenance":null} +{"source":"interface:6ed108f5ca6c8f6b9f40a746e9396c03","target":"method:67012fcd3f5d759fab7fa829faf85af2","kind":"contains","metadata":null,"line":null,"col":null,"provenance":null} +{"source":"interface:6ed108f5ca6c8f6b9f40a746e9396c03","target":"method:d63eca909d73707a025ddf2fd591a13e","kind":"contains","metadata":null,"line":null,"col":null,"provenance":null} {"source":"interface:7101ee1e3e068d01630d3b0128a15b2d","target":"property:29504b99e9cc6f02e270e9cbd71ab750","kind":"contains","metadata":null,"line":null,"col":null,"provenance":null} {"source":"interface:7101ee1e3e068d01630d3b0128a15b2d","target":"property:beb5e1a8fd1d9ea9b8af4b67ce292937","kind":"contains","metadata":null,"line":null,"col":null,"provenance":null} {"source":"interface:7423d683e426467682cab43a0f65b9a1","target":"property:23ed107148c12d05a3a6e675933995a4","kind":"contains","metadata":null,"line":null,"col":null,"provenance":null} -{"source":"interface:8045ff3999885f68bd3b9b0e8709aeeb","target":"method:92741f1ace46d5b7eeb9715c9a1098f9","kind":"contains","metadata":null,"line":null,"col":null,"provenance":null} -{"source":"interface:87965a8e467d41375154fe8ae108b529","target":"method:6fc4e3ad2b4db571a700d39f81c2c090","kind":"contains","metadata":null,"line":null,"col":null,"provenance":null} -{"source":"interface:87965a8e467d41375154fe8ae108b529","target":"method:e5720c08e3888accbb1c2aa2421e1dd1","kind":"contains","metadata":null,"line":null,"col":null,"provenance":null} {"source":"interface:99971b764b215730f05d3e4892162ca7","target":"method:1c1de6529d50c65660d96850b42290ba","kind":"contains","metadata":null,"line":null,"col":null,"provenance":null} {"source":"interface:9bd1b24347e7ea5b41e0f709184263f2","target":"method:44905846518cffb09fc9166f8d106c68","kind":"contains","metadata":null,"line":null,"col":null,"provenance":null} {"source":"interface:a05baa699fc9324830859524f09604c9","target":"method:4017466a6ee15798edb42bffc34d8939","kind":"contains","metadata":null,"line":null,"col":null,"provenance":null} @@ -3897,6 +3911,7 @@ {"source":"method:57860865154ab9d9c7dc0dd14f5eaa79","target":"variable:7b3f83bd083d272c56d09652de471592","kind":"references","metadata":"{\"valueRef\":true}","line":null,"col":null,"provenance":null} {"source":"method:581cacf02c5580f95fc293758de7be4e","target":"constant:9ef5f2100c2250165378d22671ea7a78","kind":"references","metadata":"{\"valueRef\":true}","line":null,"col":null,"provenance":null} {"source":"method:581cacf02c5580f95fc293758de7be4e","target":"method:830203603e74b357be75b6353bc5377e","kind":"calls","metadata":"{\"confidence\":0.9,\"resolvedBy\":\"exact-match\",\"refName\":\"helper\"}","line":30,"col":6,"provenance":null} +{"source":"method:598927e1a898855d3029efb1ca0f4966","target":"interface:3970ad34905c85bf731cae6e1386687f","kind":"references","metadata":"{\"confidence\":0.9,\"resolvedBy\":\"exact-match\",\"refName\":\"Repo\"}","line":86,"col":8,"provenance":null} {"source":"method:5f23af2b373950fe2a4c01962e426926","target":"method:35091377684dd9ce1422bc199925f095","kind":"calls","metadata":"{\"synthesizedBy\":\"interface-impl\",\"via\":\"read\",\"registeredAt\":\"torture.rs:131\"}","line":123,"col":null,"provenance":"heuristic"} {"source":"method:5f23af2b373950fe2a4c01962e426926","target":"method:ebf2f082376e23dff7ba2531c9a9d71f","kind":"calls","metadata":"{\"synthesizedBy\":\"interface-impl\",\"via\":\"read\",\"registeredAt\":\"torture.rs:141\"}","line":123,"col":null,"provenance":"heuristic"} {"source":"method:60108b3d293a4763b06368be872be2d7","target":"variable:7b3f83bd083d272c56d09652de471592","kind":"references","metadata":"{\"valueRef\":true}","line":null,"col":null,"provenance":null} @@ -3921,6 +3936,7 @@ {"source":"method:83f5ff48266a5d96c4d5b98a95728023","target":"method:335c8c9cd5ae7a9cbfe56af0ef8dd4ee","kind":"calls","metadata":"{\"confidence\":0.9,\"resolvedBy\":\"exact-match\",\"refName\":\"clamp\"}","line":86,"col":15,"provenance":null} {"source":"method:8483571327ac38d3149266645da49b87","target":"method:7231bc149b5bd7a542e2abad6e64605f","kind":"references","metadata":"{\"confidence\":0.95,\"resolvedBy\":\"function-ref\",\"refName\":\"alpha\",\"refKind\":\"function_ref\",\"fnRef\":true}","line":21,"col":17,"provenance":null} {"source":"method:8483571327ac38d3149266645da49b87","target":"method:77f181371bcfbbcf69325e830e407276","kind":"references","metadata":"{\"confidence\":0.95,\"resolvedBy\":\"function-ref\",\"refName\":\"beta\",\"refKind\":\"function_ref\",\"fnRef\":true}","line":22,"col":13,"provenance":null} +{"source":"method:849d12c566dceb8c4bfcf1e81b828752","target":"method:24ccc96de44e1d4e1608658cfe083a33","kind":"calls","metadata":"{\"synthesizedBy\":\"interface-impl\",\"via\":\"Render\",\"registeredAt\":\"torture.go:159\"}","line":114,"col":null,"provenance":"heuristic"} {"source":"method:84b1066798bf4890531cf6d4cd0b61b2","target":"enum:1bea39061b126572ffb641ee6a98eab8","kind":"references","metadata":"{\"confidence\":0.9,\"resolvedBy\":\"exact-match\",\"refName\":\"AFError\"}","line":49,"col":24,"provenance":null} {"source":"method:85900113e22446c44e33f53abe4c7c18","target":"class:f8e582f520a44132c2813d50c7bfdca0","kind":"instantiates","metadata":"{\"confidence\":0.9,\"resolvedBy\":\"exact-match\",\"refName\":\"Config\",\"refKind\":\"calls\"}","line":78,"col":38,"provenance":null} {"source":"method:85900113e22446c44e33f53abe4c7c18","target":"class:f8e582f520a44132c2813d50c7bfdca0","kind":"references","metadata":"{\"confidence\":0.9,\"resolvedBy\":\"exact-match\",\"refName\":\"Config\"}","line":78,"col":9,"provenance":null} @@ -3933,7 +3949,6 @@ {"source":"method:90c2e7d9608647c254c97e9a9cfea8f0","target":"class:54c0d1e485f298b4f9827706f928657f","kind":"instantiates","metadata":"{\"confidence\":0.4,\"resolvedBy\":\"exact-match\",\"refName\":\"WidgetS\"}","line":67,"col":26,"provenance":null} {"source":"method:90c2e7d9608647c254c97e9a9cfea8f0","target":"constant:8c40c7aa0ee817d211362e5149ec2220","kind":"references","metadata":"{\"valueRef\":true}","line":null,"col":null,"provenance":null} {"source":"method:90c2e7d9608647c254c97e9a9cfea8f0","target":"module:3e98a45ef089de69c402c540a05c492e","kind":"references","metadata":"{\"confidence\":0.4,\"resolvedBy\":\"exact-match\",\"refName\":\"WidgetS\"}","line":67,"col":16,"provenance":null} -{"source":"method:92741f1ace46d5b7eeb9715c9a1098f9","target":"method:72417d24bc1311c2e420094c5d05c459","kind":"calls","metadata":"{\"synthesizedBy\":\"interface-impl\",\"via\":\"Render\",\"registeredAt\":\"torture.go:118\"}","line":73,"col":null,"provenance":"heuristic"} {"source":"method:93186283b69cc2f35644199f0963df2b","target":"function:6f1b9bec32998e16cfe282d768bf4888","kind":"calls","metadata":"{\"confidence\":0.9,\"resolvedBy\":\"exact-match\",\"refName\":\"topFn\"}","line":68,"col":8,"provenance":null} {"source":"method:990b4370e5cfe670dca95f5ffb0a6def","target":"class:9dda33440f493ae9929e2412fded8370","kind":"references","metadata":"{\"confidence\":0.9,\"resolvedBy\":\"exact-match\",\"refName\":\"C\"}","line":90,"col":24,"provenance":null} {"source":"method:9929f3843a6ba7abd6ea209fd32f08c6","target":"enum:f20e15cb271bf122063fc98641681a0b","kind":"references","metadata":"{\"confidence\":0.9,\"resolvedBy\":\"exact-match\",\"refName\":\"Suit\"}","line":137,"col":16,"provenance":null} @@ -3943,6 +3958,7 @@ {"source":"method:a590c5f459d7f6915b37eb92e75a1d83","target":"method:13c9531613aeb47a53465632e14fde0a","kind":"calls","metadata":"{\"confidence\":0.9,\"resolvedBy\":\"exact-match\",\"refName\":\"done?\"}","line":129,"col":4,"provenance":null} {"source":"method:a590c5f459d7f6915b37eb92e75a1d83","target":"variable:bd3123c2d8b795f8be0ffe79b04b4849","kind":"references","metadata":"{\"confidence\":0.9,\"resolvedBy\":\"exact-match\",\"refName\":\"RETRY_MAX\"}","line":141,"col":4,"provenance":null} {"source":"method:a590c5f459d7f6915b37eb92e75a1d83","target":"variable:bd3123c2d8b795f8be0ffe79b04b4849","kind":"references","metadata":"{\"valueRef\":true}","line":null,"col":null,"provenance":null} +{"source":"method:a5cd5e67746962200f8230ebedb5413e","target":"struct:4c67fc2c851f10cf7803489ef577fc3c","kind":"references","metadata":"{\"confidence\":0.9,\"resolvedBy\":\"exact-match\",\"refName\":\"Stack\"}","line":85,"col":18,"provenance":null} {"source":"method:a7103764da0854afee05bc7d100478a4","target":"class:ca530cf4e2520283a176c1937131d988","kind":"references","metadata":"{\"confidence\":0.9,\"resolvedBy\":\"exact-match\",\"refName\":\"ProviderT\"}","line":44,"col":4,"provenance":null} {"source":"method:a7103764da0854afee05bc7d100478a4","target":"class:ca530cf4e2520283a176c1937131d988","kind":"references","metadata":"{\"confidence\":0.9,\"resolvedBy\":\"exact-match\",\"refName\":\"ProviderT\"}","line":45,"col":17,"provenance":null} {"source":"method:a7103764da0854afee05bc7d100478a4","target":"class:ca530cf4e2520283a176c1937131d988","kind":"references","metadata":"{\"confidence\":0.9,\"resolvedBy\":\"exact-match\",\"refName\":\"ProviderT\"}","line":46,"col":11,"provenance":null} @@ -4003,6 +4019,8 @@ {"source":"method:d50020a1a43788b961bf8a4652e85a45","target":"function:6f1b9bec32998e16cfe282d768bf4888","kind":"calls","metadata":"{\"confidence\":0.9,\"resolvedBy\":\"exact-match\",\"refName\":\"topFn\"}","line":73,"col":9,"provenance":null} {"source":"method:dbc683708e8c0217a76edc711cab984f","target":"class:7b9fe84bf0a135fd43dd8e0a43329327","kind":"instantiates","metadata":"{\"confidence\":0.9,\"resolvedBy\":\"exact-match\",\"refName\":\"Widget\"}","line":37,"col":11,"provenance":null} {"source":"method:dbedc27f10579fd7567f0cbda93fb625","target":"method:4ae22cd4d1a4129053ffee5c71219d2c","kind":"calls","metadata":"{\"confidence\":0.9,\"resolvedBy\":\"exact-match\",\"refName\":\"_check\"}","line":138,"col":28,"provenance":null} +{"source":"method:dc018b19c95524f99100bf15538c815b","target":"struct:33e3531d750b08f5b854203467928f28","kind":"references","metadata":"{\"confidence\":0.9,\"resolvedBy\":\"exact-match\",\"refName\":\"Widget\"}","line":84,"col":34,"provenance":null} +{"source":"method:dc018b19c95524f99100bf15538c815b","target":"type_alias:2a5e03d369bc91073bc0792b6964ac16","kind":"references","metadata":"{\"confidence\":0.9,\"resolvedBy\":\"exact-match\",\"refName\":\"Dur\"}","line":84,"col":27,"provenance":null} {"source":"method:dd439e569e5643b7eab01af84e7b86a4","target":"method:2bb5bc1d26d448e27c9c5b94d36a1051","kind":"references","metadata":"{\"confidence\":0.95,\"resolvedBy\":\"function-ref\",\"refName\":\"this.onTick\",\"refKind\":\"function_ref\",\"fnRef\":true}","line":29,"col":18,"provenance":null} {"source":"method:dfc92724bc8e56ce4fffe93fa68a9d43","target":"class:fa355652331eee519e97b9ef15a61b2d","kind":"instantiates","metadata":"{\"confidence\":0.9,\"resolvedBy\":\"exact-match\",\"refName\":\"WidgetT\",\"refKind\":\"calls\"}","line":143,"col":42,"provenance":null} {"source":"method:dfc92724bc8e56ce4fffe93fa68a9d43","target":"class:fa355652331eee519e97b9ef15a61b2d","kind":"references","metadata":"{\"confidence\":0.9,\"resolvedBy\":\"exact-match\",\"refName\":\"WidgetT\"}","line":143,"col":2,"provenance":null} @@ -4235,13 +4253,23 @@ {"source":"struct:2b5cee7ee15906697f79c2d4a7d886a3","target":"function:46f110a0d62117633ba74019905246aa","kind":"references","metadata":"{\"confidence\":0.95,\"resolvedBy\":\"function-ref\",\"refName\":\"on_close\",\"refKind\":\"function_ref\",\"fnRef\":true}","line":119,"col":38,"provenance":null} {"source":"struct:2b5cee7ee15906697f79c2d4a7d886a3","target":"function:9941625592508f28273d0020ebb7dcb0","kind":"references","metadata":"{\"confidence\":0.95,\"resolvedBy\":\"function-ref\",\"refName\":\"on_open\",\"refKind\":\"function_ref\",\"fnRef\":true}","line":119,"col":28,"provenance":null} {"source":"struct:2b5cee7ee15906697f79c2d4a7d886a3","target":"method:a0bb2c26488aac1590dead02a7eada05","kind":"contains","metadata":null,"line":null,"col":null,"provenance":null} -{"source":"struct:33e3531d750b08f5b854203467928f28","target":"interface:8045ff3999885f68bd3b9b0e8709aeeb","kind":"implements","metadata":"{\"synthesizedBy\":\"go-implements\",\"via\":\"IfaceAlias\",\"registeredAt\":\"torture.go:18\"}","line":18,"col":null,"provenance":"heuristic"} -{"source":"struct:33e3531d750b08f5b854203467928f28","target":"method:72417d24bc1311c2e420094c5d05c459","kind":"contains","metadata":null,"line":null,"col":null,"provenance":null} +{"source":"struct:33e3531d750b08f5b854203467928f28","target":"interface:3003e30a3fc9ee8bf1f1153918085038","kind":"implements","metadata":"{\"synthesizedBy\":\"go-implements\",\"via\":\"IfaceAlias\",\"registeredAt\":\"torture.go:18\"}","line":18,"col":null,"provenance":"heuristic"} +{"source":"struct:33e3531d750b08f5b854203467928f28","target":"method:24ccc96de44e1d4e1608658cfe083a33","kind":"contains","metadata":null,"line":null,"col":null,"provenance":null} {"source":"struct:33e3531d750b08f5b854203467928f28","target":"struct:4c67fc2c851f10cf7803489ef577fc3c","kind":"extends","metadata":"{\"confidence\":0.9,\"resolvedBy\":\"exact-match\",\"refName\":\"Stack\"}","line":23,"col":1,"provenance":null} +{"source":"struct:44d6f0ea6746cda4ce3d410ce9c99a46","target":"struct:33e3531d750b08f5b854203467928f28","kind":"references","metadata":"{\"confidence\":0.9,\"resolvedBy\":\"exact-match\",\"refName\":\"Widget\"}","line":62,"col":3,"provenance":null} {"source":"struct:487d89e7a287a16bb02adabeb6c061a0","target":"property:13da6cd7fb88d8425ef100ac799b81ef","kind":"contains","metadata":null,"line":null,"col":null,"provenance":null} -{"source":"struct:4c67fc2c851f10cf7803489ef577fc3c","target":"method:ae63e6f68d18ae3e3794926b4f75768b","kind":"contains","metadata":null,"line":null,"col":null,"provenance":null} +{"source":"struct:4c67fc2c851f10cf7803489ef577fc3c","target":"method:a6d269b87546a3383d51ca2de232a1de","kind":"contains","metadata":null,"line":null,"col":null,"provenance":null} {"source":"struct:4ea1b361173ba3f6b1b2e8dfe74e13d3","target":"method:b739f420ee12a433408dfb1f4a2911de","kind":"contains","metadata":null,"line":null,"col":null,"provenance":null} {"source":"struct:68ba8bd4bb0864aeb77213901028683d","target":"field:67881ece80318447542caf9c533fa2c9","kind":"contains","metadata":null,"line":null,"col":null,"provenance":null} +{"source":"struct:6b80d8f1dbee1c34e187c63b7e616a70","target":"struct:33e3531d750b08f5b854203467928f28","kind":"references","metadata":"{\"confidence\":0.9,\"resolvedBy\":\"exact-match\",\"refName\":\"Widget\"}","line":37,"col":21,"provenance":null} +{"source":"struct:6b80d8f1dbee1c34e187c63b7e616a70","target":"struct:33e3531d750b08f5b854203467928f28","kind":"references","metadata":"{\"confidence\":0.9,\"resolvedBy\":\"exact-match\",\"refName\":\"Widget\"}","line":39,"col":21,"provenance":null} +{"source":"struct:6b80d8f1dbee1c34e187c63b7e616a70","target":"struct:33e3531d750b08f5b854203467928f28","kind":"references","metadata":"{\"confidence\":0.9,\"resolvedBy\":\"exact-match\",\"refName\":\"Widget\"}","line":40,"col":36,"provenance":null} +{"source":"struct:6b80d8f1dbee1c34e187c63b7e616a70","target":"struct:33e3531d750b08f5b854203467928f28","kind":"references","metadata":"{\"confidence\":0.9,\"resolvedBy\":\"exact-match\",\"refName\":\"Widget\"}","line":41,"col":10,"provenance":null} +{"source":"struct:6b80d8f1dbee1c34e187c63b7e616a70","target":"struct:33e3531d750b08f5b854203467928f28","kind":"references","metadata":"{\"confidence\":0.9,\"resolvedBy\":\"exact-match\",\"refName\":\"Widget\"}","line":43,"col":4,"provenance":null} +{"source":"struct:6b80d8f1dbee1c34e187c63b7e616a70","target":"struct:33e3531d750b08f5b854203467928f28","kind":"references","metadata":"{\"confidence\":0.9,\"resolvedBy\":\"exact-match\",\"refName\":\"Widget\"}","line":49,"col":15,"provenance":null} +{"source":"struct:6b80d8f1dbee1c34e187c63b7e616a70","target":"struct:4c67fc2c851f10cf7803489ef577fc3c","kind":"references","metadata":"{\"confidence\":0.9,\"resolvedBy\":\"exact-match\",\"refName\":\"Stack\"}","line":40,"col":46,"provenance":null} +{"source":"struct:6b80d8f1dbee1c34e187c63b7e616a70","target":"type_alias:2a5e03d369bc91073bc0792b6964ac16","kind":"references","metadata":"{\"confidence\":0.9,\"resolvedBy\":\"exact-match\",\"refName\":\"Dur\"}","line":37,"col":14,"provenance":null} +{"source":"struct:6b80d8f1dbee1c34e187c63b7e616a70","target":"type_alias:5fab20424fd8ff6f365fbb0e5eec9c84","kind":"references","metadata":"{\"confidence\":0.9,\"resolvedBy\":\"exact-match\",\"refName\":\"HandlersChain\"}","line":36,"col":10,"provenance":null} {"source":"struct:6d96b486579cf3fdd66718872215294c","target":"constant:03a7deca3c8e64b747972d99b0c1bcdc","kind":"contains","metadata":null,"line":null,"col":null,"provenance":null} {"source":"struct:6d96b486579cf3fdd66718872215294c","target":"field:81b9c56215cb5a70857091431b97bd1a","kind":"contains","metadata":null,"line":null,"col":null,"provenance":null} {"source":"struct:6d96b486579cf3fdd66718872215294c","target":"struct:6d96b486579cf3fdd66718872215294c","kind":"instantiates","metadata":"{\"confidence\":0.9,\"resolvedBy\":\"exact-match\",\"refName\":\"HTTPMethod\",\"refKind\":\"calls\"}","line":41,"col":19,"provenance":null} @@ -4250,6 +4278,8 @@ {"source":"struct:8af466b07dba0b708a3b1922902ab00a","target":"method:c19898b8b84cce6cc2b80007d1b6f588","kind":"contains","metadata":null,"line":null,"col":null,"provenance":null} {"source":"struct:8af466b07dba0b708a3b1922902ab00a","target":"trait:7cbd29a1473d80a74da70be5024bc1d6","kind":"implements","metadata":"{\"confidence\":0.9,\"resolvedBy\":\"exact-match\",\"refName\":\"Source\"}","line":130,"col":5,"provenance":null} {"source":"struct:8dd22c4fc56baeba045e9bf82329d7eb","target":"trait:dcec472700533c7d65fd2f90ea3c6830","kind":"implements","metadata":"{\"confidence\":0.9,\"resolvedBy\":\"exact-match\",\"refName\":\"Base\"}","line":169,"col":5,"provenance":null} +{"source":"struct:b5d2c300d801f1233941b73d992ba7eb","target":"struct:33e3531d750b08f5b854203467928f28","kind":"references","metadata":"{\"confidence\":0.9,\"resolvedBy\":\"exact-match\",\"refName\":\"Widget\"}","line":58,"col":7,"provenance":null} +{"source":"struct:b5d2c300d801f1233941b73d992ba7eb","target":"struct:4c67fc2c851f10cf7803489ef577fc3c","kind":"extends","metadata":"{\"confidence\":0.9,\"resolvedBy\":\"exact-match\",\"refName\":\"Stack\"}","line":57,"col":1,"provenance":null} {"source":"struct:be0bce4f35c3b001691d2298b42277a7","target":"field:45e081c79633beb77c0d4cbb1977d1cb","kind":"contains","metadata":null,"line":null,"col":null,"provenance":null} {"source":"struct:dc1fb066a6c08cc705216a045fa93a24","target":"method:36b2c35b96abd233c6449d02d9c4ef2f","kind":"contains","metadata":null,"line":null,"col":null,"provenance":null} {"source":"struct:edcb8b15c67daf532c1057d9efe8ac3d","target":"method:0843076b0b3cc6a4287f1bbbb3ec931d","kind":"contains","metadata":null,"line":null,"col":null,"provenance":null} @@ -4268,31 +4298,31 @@ {"source":"trait:f91851c14912462ae9592cb13a51f3b1","target":"field:3ee68904db11f62059a076599040234d","kind":"contains","metadata":null,"line":null,"col":null,"provenance":null} {"source":"trait:f91851c14912462ae9592cb13a51f3b1","target":"method:ef770437bcc4f4b3a1dbf17b8a1720a6","kind":"contains","metadata":null,"line":null,"col":null,"provenance":null} {"source":"trait:f91851c14912462ae9592cb13a51f3b1","target":"method:fb3814b6e956f06c3746e1758bfb591d","kind":"contains","metadata":null,"line":null,"col":null,"provenance":null} -{"source":"type_alias:2652fcdf36b42377e527cf35f8d800c9","target":"struct:4c67fc2c851f10cf7803489ef577fc3c","kind":"references","metadata":"{\"confidence\":0.9,\"resolvedBy\":\"exact-match\",\"refName\":\"Stack\"}","line":84,"col":23,"provenance":null} -{"source":"type_alias:44cb4653a5e07bdcee1050ba3133ab31","target":"struct:33e3531d750b08f5b854203467928f28","kind":"references","metadata":"{\"confidence\":0.9,\"resolvedBy\":\"exact-match\",\"refName\":\"Widget\"}","line":88,"col":20,"provenance":null} -{"source":"type_alias:4b2d750ab1f528d33a2d6713cb2193a7","target":"struct:33e3531d750b08f5b854203467928f28","kind":"references","metadata":"{\"confidence\":0.9,\"resolvedBy\":\"exact-match\",\"refName\":\"Widget\"}","line":62,"col":21,"provenance":null} +{"source":"type_alias:02bad22974119233684c4cdc31b84c08","target":"struct:33e3531d750b08f5b854203467928f28","kind":"references","metadata":"{\"confidence\":0.9,\"resolvedBy\":\"exact-match\",\"refName\":\"Widget\"}","line":103,"col":21,"provenance":null} +{"source":"type_alias:056dd5fe2cc3e2ad87323386146effcc","target":"type_alias:2a5e03d369bc91073bc0792b6964ac16","kind":"references","metadata":"{\"confidence\":0.9,\"resolvedBy\":\"exact-match\",\"refName\":\"Dur\"}","line":128,"col":13,"provenance":null} +{"source":"type_alias:09f9cb5669970256407b8aebd0528e7d","target":"struct:33e3531d750b08f5b854203467928f28","kind":"references","metadata":"{\"confidence\":0.9,\"resolvedBy\":\"exact-match\",\"refName\":\"Widget\"}","line":101,"col":14,"provenance":null} +{"source":"type_alias:5fab20424fd8ff6f365fbb0e5eec9c84","target":"type_alias:965915e648eebc2c230c7f5df6ca9700","kind":"references","metadata":"{\"confidence\":0.9,\"resolvedBy\":\"exact-match\",\"refName\":\"HandlerFunc\"}","line":123,"col":21,"provenance":null} {"source":"type_alias:600473b4a3158649443b2f214febf906","target":"method:137fead1f10b4a2a010aa8787ef9782e","kind":"contains","metadata":null,"line":null,"col":null,"provenance":null} {"source":"type_alias:600473b4a3158649443b2f214febf906","target":"method:5c2e8db84b29af68fc13a77bb8cbbc71","kind":"contains","metadata":null,"line":null,"col":null,"provenance":null} {"source":"type_alias:600473b4a3158649443b2f214febf906","target":"property:e9465b48a55d84277b38665854459a7a","kind":"contains","metadata":null,"line":null,"col":null,"provenance":null} -{"source":"type_alias:70a70301f02c5dd34c45fea884736d5d","target":"struct:33e3531d750b08f5b854203467928f28","kind":"references","metadata":"{\"confidence\":0.9,\"resolvedBy\":\"exact-match\",\"refName\":\"Widget\"}","line":64,"col":12,"provenance":null} -{"source":"type_alias:75662b893c34aed98e64700a6d01bf8d","target":"struct:33e3531d750b08f5b854203467928f28","kind":"references","metadata":"{\"confidence\":0.9,\"resolvedBy\":\"exact-match\",\"refName\":\"Widget\"}","line":80,"col":23,"provenance":null} -{"source":"type_alias:80c39c4f28c27d78ecdedc474ae4af7b","target":"struct:4c67fc2c851f10cf7803489ef577fc3c","kind":"references","metadata":"{\"confidence\":0.9,\"resolvedBy\":\"exact-match\",\"refName\":\"Stack\"}","line":61,"col":15,"provenance":null} -{"source":"type_alias:bb8bd8650e34457304e34b86851c1431","target":"struct:33e3531d750b08f5b854203467928f28","kind":"references","metadata":"{\"confidence\":0.9,\"resolvedBy\":\"exact-match\",\"refName\":\"Widget\"}","line":60,"col":14,"provenance":null} -{"source":"type_alias:c0ad8af1b5e37e6ad90fd0c5790b6209","target":"type_alias:75662b893c34aed98e64700a6d01bf8d","kind":"references","metadata":"{\"confidence\":0.9,\"resolvedBy\":\"exact-match\",\"refName\":\"HandlerFunc\"}","line":82,"col":21,"provenance":null} -{"source":"type_alias:c925710f298dd798808037fcf660f73b","target":"struct:33e3531d750b08f5b854203467928f28","kind":"references","metadata":"{\"confidence\":0.9,\"resolvedBy\":\"exact-match\",\"refName\":\"Widget\"}","line":99,"col":19,"provenance":null} +{"source":"type_alias:608221a5f58d68322f43ee54c190640e","target":"struct:33e3531d750b08f5b854203467928f28","kind":"references","metadata":"{\"confidence\":0.9,\"resolvedBy\":\"exact-match\",\"refName\":\"Widget\"}","line":133,"col":4,"provenance":null} +{"source":"type_alias:771117de3df76a903822e0fab4467df8","target":"struct:33e3531d750b08f5b854203467928f28","kind":"references","metadata":"{\"confidence\":0.9,\"resolvedBy\":\"exact-match\",\"refName\":\"Widget\"}","line":130,"col":10,"provenance":null} +{"source":"type_alias:965915e648eebc2c230c7f5df6ca9700","target":"struct:33e3531d750b08f5b854203467928f28","kind":"references","metadata":"{\"confidence\":0.9,\"resolvedBy\":\"exact-match\",\"refName\":\"Widget\"}","line":121,"col":23,"provenance":null} +{"source":"type_alias:a10c4f47aeab87402ced28d09f54ddfb","target":"struct:4c67fc2c851f10cf7803489ef577fc3c","kind":"references","metadata":"{\"confidence\":0.9,\"resolvedBy\":\"exact-match\",\"refName\":\"Stack\"}","line":125,"col":23,"provenance":null} +{"source":"type_alias:c9336784d0211d92b205b7194a5ce3a7","target":"struct:4c67fc2c851f10cf7803489ef577fc3c","kind":"references","metadata":"{\"confidence\":0.9,\"resolvedBy\":\"exact-match\",\"refName\":\"Stack\"}","line":102,"col":15,"provenance":null} +{"source":"type_alias:c9fe81e444d43593fc382a0be628bc66","target":"struct:33e3531d750b08f5b854203467928f28","kind":"references","metadata":"{\"confidence\":0.9,\"resolvedBy\":\"exact-match\",\"refName\":\"Widget\"}","line":105,"col":12,"provenance":null} {"source":"type_alias:cdaae8f951716ba1d5b3f5faa698cf1c","target":"interface:a05baa699fc9324830859524f09604c9","kind":"references","metadata":"{\"confidence\":0.9,\"resolvedBy\":\"exact-match\",\"refName\":\"Shape\"}","line":89,"col":25,"provenance":null} -{"source":"type_alias:d9cf57aaa8c6be0b025ae6b685745a39","target":"struct:33e3531d750b08f5b854203467928f28","kind":"references","metadata":"{\"confidence\":0.9,\"resolvedBy\":\"exact-match\",\"refName\":\"Widget\"}","line":92,"col":4,"provenance":null} -{"source":"type_alias:e67f0306e684e2b34de4b379a1546426","target":"type_alias:10728d965a9856b988bb2359a09666f9","kind":"references","metadata":"{\"confidence\":0.9,\"resolvedBy\":\"exact-match\",\"refName\":\"Dur\"}","line":87,"col":13,"provenance":null} -{"source":"type_alias:f61f67035897704f4a03cf76fb59e8a9","target":"struct:33e3531d750b08f5b854203467928f28","kind":"references","metadata":"{\"confidence\":0.9,\"resolvedBy\":\"exact-match\",\"refName\":\"Widget\"}","line":89,"col":10,"provenance":null} +{"source":"type_alias:d1df73c8269ea5dd18f9aaaac0a8088d","target":"struct:33e3531d750b08f5b854203467928f28","kind":"references","metadata":"{\"confidence\":0.9,\"resolvedBy\":\"exact-match\",\"refName\":\"Widget\"}","line":140,"col":19,"provenance":null} +{"source":"type_alias:f6d4e998f3c2200dadf5c1e05f9368ab","target":"struct:33e3531d750b08f5b854203467928f28","kind":"references","metadata":"{\"confidence\":0.9,\"resolvedBy\":\"exact-match\",\"refName\":\"Widget\"}","line":129,"col":20,"provenance":null} {"source":"type_alias:f84ae3400c1d88837e6d67a42d5eea5a","target":"method:17231adc3d18205998834087d654a9b4","kind":"contains","metadata":null,"line":null,"col":null,"provenance":null} {"source":"type_alias:f84ae3400c1d88837e6d67a42d5eea5a","target":"method:3694d7519adf9e129231e61b011b3738","kind":"contains","metadata":null,"line":null,"col":null,"provenance":null} {"source":"union:87328bb244dc25e95ff76f307ddb5a57","target":"struct:aa7ce416b52984c7ea2b1b6d43e70da9","kind":"contains","metadata":null,"line":null,"col":null,"provenance":null} {"source":"union:dca892bf5affbe24bc5af9c2fb3f133d","target":"trait:dcec472700533c7d65fd2f90ea3c6830","kind":"implements","metadata":"{\"confidence\":0.9,\"resolvedBy\":\"exact-match\",\"refName\":\"Base\"}","line":298,"col":5,"provenance":null} -{"source":"variable:1837cd19ce5f7a8f45b7fa4b8fc8a0e6","target":"function:ffbfbea1bf90b2536f05eed532eb53ce","kind":"calls","metadata":"{\"confidence\":0.9,\"resolvedBy\":\"exact-match\",\"refName\":\"NewRegistry\"}","line":11,"col":22,"provenance":null} +{"source":"variable:1837cd19ce5f7a8f45b7fa4b8fc8a0e6","target":"function:81cc5b0d788ee9727656191bb6a35597","kind":"calls","metadata":"{\"confidence\":0.9,\"resolvedBy\":\"exact-match\",\"refName\":\"NewRegistry\"}","line":11,"col":22,"provenance":null} {"source":"variable:36e608fb368763b7f8a74a69f477cec7","target":"function:692077921d04b315880bc35a0bc872a9","kind":"references","metadata":"{\"confidence\":0.95,\"resolvedBy\":\"function-ref\",\"refName\":\"view\",\"refKind\":\"function_ref\",\"fnRef\":true}","line":49,"col":24,"provenance":null} -{"source":"variable:6b7262d2883839c6f601126f4dd59e9b","target":"function:0e1ad124e719c2d18615cda6816af46c","kind":"references","metadata":"{\"confidence\":0.95,\"resolvedBy\":\"function-ref\",\"refName\":\"TargetCb\",\"refKind\":\"function_ref\",\"fnRef\":true}","line":14,"col":9,"provenance":null} +{"source":"variable:6b7262d2883839c6f601126f4dd59e9b","target":"function:a832b3ad2e6b57ff9463fbd6c86c5a97","kind":"references","metadata":"{\"confidence\":0.95,\"resolvedBy\":\"function-ref\",\"refName\":\"TargetCb\",\"refKind\":\"function_ref\",\"fnRef\":true}","line":14,"col":9,"provenance":null} {"source":"variable:788d75a828c79f9847e0be0e2b73a196","target":"variable:8fef25ea8abe486ee94190ed47c3644b","kind":"references","metadata":"{\"valueRef\":true}","line":null,"col":null,"provenance":null} -== refs (1715) +== refs (1723) {"from_node_id":"class:01a3945fa12793f1af9ac531aedcc8cd","reference_name":"Mix2","reference_kind":"implements","line":34,"col":37,"candidates":null,"file_path":"TortureMini.dart","language":"dart","status":"failed","name_tail":"Mix2"} {"from_node_id":"class:01a3945fa12793f1af9ac531aedcc8cd","reference_name":"Paint","reference_kind":"implements","line":34,"col":59,"candidates":null,"file_path":"TortureMini.dart","language":"dart","status":"failed","name_tail":"Paint"} {"from_node_id":"class:027779b3581d9f4aee2aef4dbd5c8873","reference_name":"immutable","reference_kind":"decorates","line":144,"col":0,"candidates":null,"file_path":"TortureAnnotatedDocs.dart","language":"dart","status":"failed","name_tail":"immutable"} @@ -4858,7 +4888,6 @@ {"from_node_id":"function:112bb390a54043c8ee6b3ee94ba6c956","reference_name":"inner","reference_kind":"calls","line":11,"col":9,"candidates":null,"file_path":"TortureDoubleWalk.dart","language":"dart","status":"failed","name_tail":"inner"} {"from_node_id":"function:112bb390a54043c8ee6b3ee94ba6c956","reference_name":"w.n","reference_kind":"references","line":16,"col":13,"candidates":null,"file_path":"TortureDoubleWalk.dart","language":"dart","status":"failed","name_tail":"n"} {"from_node_id":"function:11c7b584c938a133a0a90b82afcafbd9","reference_name":"emit","reference_kind":"calls","line":60,"col":6,"candidates":null,"file_path":"TortureVrefDart.dart","language":"dart","status":"failed","name_tail":"emit"} -{"from_node_id":"function:140cc1d2e83fc5a1968f8058b5457dd1","reference_name":"fmt.Println","reference_kind":"calls","line":126,"col":1,"candidates":null,"file_path":"torture.go","language":"go","status":"failed","name_tail":"Println","failure_reason":"unknown-receiver"} {"from_node_id":"function:141b9348d2428090cbb42de6932b54ad","reference_name":"visibleForTesting","reference_kind":"decorates","line":7,"col":0,"candidates":null,"file_path":"TortureAnnotatedComments.dart","language":"dart","status":"failed","name_tail":"visibleForTesting"} {"from_node_id":"function:15790b08cab7e8d7cb5b8a474d94c359","reference_name":"draw","reference_kind":"calls","line":253,"col":4,"candidates":null,"file_path":"torture.kt","language":"kotlin","status":"failed","name_tail":"draw"} {"from_node_id":"function:1591d6baa7249cbfb88bb162e736cb3e","reference_name":"docs/deep/nested.markdown","reference_kind":"references","line":217,"col":32,"candidates":null,"file_path":"torture.R","language":"r","status":"failed","name_tail":"nested.markdown"} @@ -4973,8 +5002,6 @@ {"from_node_id":"function:44b4a8cf45d87bc437f1a71cb9d95ab9","reference_name":"docs/deep/nested.markdown","reference_kind":"references","line":183,"col":38,"candidates":null,"file_path":"torture.c","language":"c","status":"failed","name_tail":"nested.markdown"} {"from_node_id":"function:44b4a8cf45d87bc437f1a71cb9d95ab9","reference_name":"load_doc","reference_kind":"calls","line":183,"col":28,"candidates":null,"file_path":"torture.c","language":"c","status":"failed","name_tail":"load_doc"} {"from_node_id":"function:4660fc91e385ee68f62141cd432fb335","reference_name":"use","reference_kind":"calls","line":29,"col":5,"candidates":null,"file_path":"TortureVrefDart.dart","language":"dart","status":"failed","name_tail":"use"} -{"from_node_id":"function:46864a1a62b2fd2a4e1657a52005c4e7","reference_name":"docs/deep/nested.markdown","reference_kind":"references","line":145,"col":10,"candidates":null,"file_path":"torture.go","language":"go","status":"failed","name_tail":"nested.markdown"} -{"from_node_id":"function:46864a1a62b2fd2a4e1657a52005c4e7","reference_name":"loadDoc","reference_kind":"calls","line":145,"col":1,"candidates":null,"file_path":"torture.go","language":"go","status":"failed","name_tail":"loadDoc"} {"from_node_id":"function:4759298ab8dfe6cd0b2c0574d59fdde3","reference_name":"singleton_body_call","reference_kind":"calls","line":229,"col":2,"candidates":null,"file_path":"torture.rb","language":"ruby","status":"failed","name_tail":"singleton_body_call"} {"from_node_id":"function:497300b7c8854deb5abe80f7446e4447","reference_name":"pragma","reference_kind":"decorates","line":11,"col":0,"candidates":null,"file_path":"TortureAnnotatedDocs.dart","language":"dart","status":"failed","name_tail":"pragma"} {"from_node_id":"function:49b34d67e6038f90631cab938e6ba5e8","reference_name":"T","reference_kind":"references","line":52,"col":0,"candidates":null,"file_path":"torture.dart","language":"dart","status":"failed","name_tail":"T"} @@ -4995,6 +5022,7 @@ {"from_node_id":"function:522d9f8bb2b74fbe8b74a3a07afd73b8","reference_name":"docs/deep/nested.markdown","reference_kind":"references","line":234,"col":13,"candidates":null,"file_path":"torture.php","language":"php","status":"failed","name_tail":"nested.markdown"} {"from_node_id":"function:522d9f8bb2b74fbe8b74a3a07afd73b8","reference_name":"loadDoc","reference_kind":"calls","line":234,"col":4,"candidates":null,"file_path":"torture.php","language":"php","status":"failed","name_tail":"loadDoc"} {"from_node_id":"function:5346ad53a982756298bce064d4466e98","reference_name":"Iterable","reference_kind":"references","line":46,"col":0,"candidates":null,"file_path":"TortureDoubleWalk.dart","language":"dart","status":"failed","name_tail":"Iterable"} +{"from_node_id":"function:55a555881f22d77e916122b15425f092","reference_name":"fmt.Println","reference_kind":"calls","line":167,"col":1,"candidates":null,"file_path":"torture.go","language":"go","status":"failed","name_tail":"Println","failure_reason":"unknown-receiver"} {"from_node_id":"function:55dc9b62ca2dd87561c5e882ec386c0c","reference_name":"override","reference_kind":"decorates","line":52,"col":0,"candidates":null,"file_path":"TortureVrefDart.dart","language":"dart","status":"failed","name_tail":"override"} {"from_node_id":"function:58cc4881761cc60fc8688b7b929434dc","reference_name":"Foo","reference_kind":"calls","line":156,"col":36,"candidates":null,"file_path":"torture.swift","language":"swift","status":"failed","name_tail":"Foo"} {"from_node_id":"function:58cc4881761cc60fc8688b7b929434dc","reference_name":"Foo","reference_kind":"references","line":156,"col":25,"candidates":null,"file_path":"torture.swift","language":"swift","status":"failed","name_tail":"Foo"} @@ -5114,6 +5142,15 @@ {"from_node_id":"function:81ba5a98d0931cbf162f4338fae53766","reference_name":"Cfg.retries","reference_kind":"references","line":65,"col":10,"candidates":null,"file_path":"TortureDoubleWalk.dart","language":"dart","status":"failed","name_tail":"retries"} {"from_node_id":"function:81ba5a98d0931cbf162f4338fae53766","reference_name":"print","reference_kind":"calls","line":67,"col":7,"candidates":null,"file_path":"TortureDoubleWalk.dart","language":"dart","status":"failed","name_tail":"print"} {"from_node_id":"function:81ba5a98d0931cbf162f4338fae53766","reference_name":"use","reference_kind":"calls","line":65,"col":5,"candidates":null,"file_path":"TortureDoubleWalk.dart","language":"dart","status":"failed","name_tail":"use"} +{"from_node_id":"function:81cc5b0d788ee9727656191bb6a35597","reference_name":"New","reference_kind":"calls","line":152,"col":8,"candidates":null,"file_path":"torture.go","language":"go","status":"failed","name_tail":"New"} +{"from_node_id":"function:81cc5b0d788ee9727656191bb6a35597","reference_name":"New().Init","reference_kind":"calls","line":152,"col":8,"candidates":null,"file_path":"torture.go","language":"go","status":"failed","name_tail":"Init"} +{"from_node_id":"function:81cc5b0d788ee9727656191bb6a35597","reference_name":"Registry","reference_kind":"references","line":146,"col":20,"candidates":null,"file_path":"torture.go","language":"go","status":"failed","name_tail":"Registry"} +{"from_node_id":"function:81cc5b0d788ee9727656191bb6a35597","reference_name":"cfg.conn.Exec","reference_kind":"calls","line":151,"col":1,"candidates":null,"file_path":"torture.go","language":"go","status":"failed","name_tail":"Exec","failure_reason":"unknown-receiver"} +{"from_node_id":"function:81cc5b0d788ee9727656191bb6a35597","reference_name":"fmt.Println","reference_kind":"calls","line":149,"col":1,"candidates":null,"file_path":"torture.go","language":"go","status":"failed","name_tail":"Println","failure_reason":"unknown-receiver"} +{"from_node_id":"function:81cc5b0d788ee9727656191bb6a35597","reference_name":"loadConfig","reference_kind":"calls","line":150,"col":8,"candidates":null,"file_path":"torture.go","language":"go","status":"failed","name_tail":"loadConfig"} +{"from_node_id":"function:81cc5b0d788ee9727656191bb6a35597","reference_name":"pkga.Widget","reference_kind":"instantiates","line":148,"col":6,"candidates":null,"file_path":"torture.go","language":"go","status":"failed","name_tail":"Widget"} +{"from_node_id":"function:8307a8a823f2c272e33236a2f73c9f60","reference_name":"docs/deep/nested.markdown","reference_kind":"references","line":186,"col":10,"candidates":null,"file_path":"torture.go","language":"go","status":"failed","name_tail":"nested.markdown"} +{"from_node_id":"function:8307a8a823f2c272e33236a2f73c9f60","reference_name":"loadDoc","reference_kind":"calls","line":186,"col":1,"candidates":null,"file_path":"torture.go","language":"go","status":"failed","name_tail":"loadDoc"} {"from_node_id":"function:893e190d6be04144b7ebe001bdd3cdba","reference_name":"forward","reference_kind":"calls","line":108,"col":9,"candidates":null,"file_path":"torture.dart","language":"dart","status":"failed","name_tail":"forward"} {"from_node_id":"function:893e190d6be04144b7ebe001bdd3cdba","reference_name":"reg2","reference_kind":"calls","line":107,"col":6,"candidates":null,"file_path":"torture.dart","language":"dart","status":"failed","name_tail":"reg2"} {"from_node_id":"function:89b5279cd19a084e8974e1c0985c27d9","reference_name":"api.load","reference_kind":"calls","line":159,"col":27,"candidates":null,"file_path":"torture.tsx","language":"tsx","status":"failed","name_tail":"load","failure_reason":"unknown-receiver"} @@ -5332,20 +5369,13 @@ {"from_node_id":"function:fdace61258b1ce2e795b000effa9d472","reference_name":"make().run","reference_kind":"calls","line":61,"col":4,"candidates":null,"file_path":"torture.py","language":"python","status":"failed","name_tail":"run"} {"from_node_id":"function:fdace61258b1ce2e795b000effa9d472","reference_name":"obj.make","reference_kind":"calls","line":63,"col":4,"candidates":null,"file_path":"torture.py","language":"python","status":"failed","name_tail":"make","failure_reason":"unknown-receiver"} {"from_node_id":"function:fdace61258b1ce2e795b000effa9d472","reference_name":"obj.make().run","reference_kind":"calls","line":63,"col":4,"candidates":null,"file_path":"torture.py","language":"python","status":"failed","name_tail":"run"} -{"from_node_id":"function:ffbfbea1bf90b2536f05eed532eb53ce","reference_name":"New","reference_kind":"calls","line":111,"col":8,"candidates":null,"file_path":"torture.go","language":"go","status":"failed","name_tail":"New"} -{"from_node_id":"function:ffbfbea1bf90b2536f05eed532eb53ce","reference_name":"New().Init","reference_kind":"calls","line":111,"col":8,"candidates":null,"file_path":"torture.go","language":"go","status":"failed","name_tail":"Init"} -{"from_node_id":"function:ffbfbea1bf90b2536f05eed532eb53ce","reference_name":"Registry","reference_kind":"references","line":105,"col":20,"candidates":null,"file_path":"torture.go","language":"go","status":"failed","name_tail":"Registry"} -{"from_node_id":"function:ffbfbea1bf90b2536f05eed532eb53ce","reference_name":"cfg.conn.Exec","reference_kind":"calls","line":110,"col":1,"candidates":null,"file_path":"torture.go","language":"go","status":"failed","name_tail":"Exec","failure_reason":"unknown-receiver"} -{"from_node_id":"function:ffbfbea1bf90b2536f05eed532eb53ce","reference_name":"fmt.Println","reference_kind":"calls","line":108,"col":1,"candidates":null,"file_path":"torture.go","language":"go","status":"failed","name_tail":"Println","failure_reason":"unknown-receiver"} -{"from_node_id":"function:ffbfbea1bf90b2536f05eed532eb53ce","reference_name":"loadConfig","reference_kind":"calls","line":109,"col":8,"candidates":null,"file_path":"torture.go","language":"go","status":"failed","name_tail":"loadConfig"} -{"from_node_id":"function:ffbfbea1bf90b2536f05eed532eb53ce","reference_name":"pkga.Widget","reference_kind":"instantiates","line":107,"col":6,"candidates":null,"file_path":"torture.go","language":"go","status":"failed","name_tail":"Widget"} {"from_node_id":"interface:24159e084fc50d320c624ae5b6655041","reference_name":"Base1","reference_kind":"extends","line":180,"col":24,"candidates":null,"file_path":"torture.php","language":"php","status":"failed","name_tail":"Base1"} +{"from_node_id":"interface:6ed108f5ca6c8f6b9f40a746e9396c03","reference_name":"Closer","reference_kind":"extends","line":74,"col":6,"candidates":null,"file_path":"torture.go","language":"go","status":"failed","name_tail":"Closer"} +{"from_node_id":"interface:6ed108f5ca6c8f6b9f40a746e9396c03","reference_name":"Lister","reference_kind":"extends","line":75,"col":1,"candidates":null,"file_path":"torture.go","language":"go","status":"failed","name_tail":"Lister"} +{"from_node_id":"interface:6ed108f5ca6c8f6b9f40a746e9396c03","reference_name":"Reader","reference_kind":"extends","line":73,"col":1,"candidates":null,"file_path":"torture.go","language":"go","status":"failed","name_tail":"Reader"} {"from_node_id":"interface:7101ee1e3e068d01630d3b0128a15b2d","reference_name":"AnyObject","reference_kind":"extends","line":140,"col":20,"candidates":null,"file_path":"torture.swift","language":"swift","status":"failed","name_tail":"AnyObject"} {"from_node_id":"interface:7101ee1e3e068d01630d3b0128a15b2d","reference_name":"Identifiable","reference_kind":"extends","line":140,"col":31,"candidates":null,"file_path":"torture.swift","language":"swift","status":"failed","name_tail":"Identifiable"} {"from_node_id":"interface:7423d683e426467682cab43a0f65b9a1","reference_name":"AnyObject","reference_kind":"extends","line":52,"col":26,"candidates":null,"file_path":"torture.swift","language":"swift","status":"failed","name_tail":"AnyObject"} -{"from_node_id":"interface:87965a8e467d41375154fe8ae108b529","reference_name":"Closer","reference_kind":"extends","line":41,"col":6,"candidates":null,"file_path":"torture.go","language":"go","status":"failed","name_tail":"Closer"} -{"from_node_id":"interface:87965a8e467d41375154fe8ae108b529","reference_name":"Lister","reference_kind":"extends","line":42,"col":1,"candidates":null,"file_path":"torture.go","language":"go","status":"failed","name_tail":"Lister"} -{"from_node_id":"interface:87965a8e467d41375154fe8ae108b529","reference_name":"Reader","reference_kind":"extends","line":40,"col":1,"candidates":null,"file_path":"torture.go","language":"go","status":"failed","name_tail":"Reader"} {"from_node_id":"interface:99971b764b215730f05d3e4892162ca7","reference_name":"Cloneable","reference_kind":"extends","line":126,"col":43,"candidates":null,"file_path":"Torture.java","language":"java","status":"failed","name_tail":"Cloneable"} {"from_node_id":"interface:99971b764b215730f05d3e4892162ca7","reference_name":"Comparable","reference_kind":"extends","line":126,"col":24,"candidates":null,"file_path":"Torture.java","language":"java","status":"failed","name_tail":"Comparable"} {"from_node_id":"method:033ac2ba34fbab2bc8e4448a87dd89ce","reference_name":"helperCall","reference_kind":"calls","line":34,"col":32,"candidates":null,"file_path":"TortureDoubleWalk.dart","language":"dart","status":"failed","name_tail":"helperCall"} @@ -5673,6 +5703,10 @@ {"from_node_id":"method:a590c5f459d7f6915b37eb92e75a1d83","reference_name":"puts","reference_kind":"calls","line":128,"col":4,"candidates":null,"file_path":"torture.rb","language":"ruby","status":"failed","name_tail":"puts"} {"from_node_id":"method:a590c5f459d7f6915b37eb92e75a1d83","reference_name":"puts","reference_kind":"calls","line":152,"col":4,"candidates":null,"file_path":"torture.rb","language":"ruby","status":"failed","name_tail":"puts"} {"from_node_id":"method:a590c5f459d7f6915b37eb92e75a1d83","reference_name":"reset","reference_kind":"calls","line":126,"col":4,"candidates":null,"file_path":"torture.rb","language":"ruby","status":"failed","name_tail":"reset"} +{"from_node_id":"method:a5cd5e67746962200f8230ebedb5413e","reference_name":"Item","reference_kind":"references","line":85,"col":43,"candidates":null,"file_path":"torture.go","language":"go","status":"failed","name_tail":"Item"} +{"from_node_id":"method:a6d269b87546a3383d51ca2de232a1de","reference_name":"T","reference_kind":"references","line":155,"col":29,"candidates":null,"file_path":"torture.go","language":"go","status":"failed","name_tail":"T"} +{"from_node_id":"method:a6d269b87546a3383d51ca2de232a1de","reference_name":"append","reference_kind":"calls","line":156,"col":11,"candidates":null,"file_path":"torture.go","language":"go","status":"failed","name_tail":"append"} +{"from_node_id":"method:a6d269b87546a3383d51ca2de232a1de","reference_name":"s.items","reference_kind":"function_ref","line":156,"col":20,"candidates":null,"file_path":"torture.go","language":"go","status":"failed","name_tail":"items"} {"from_node_id":"method:a7103764da0854afee05bc7d100478a4","reference_name":"Object","reference_kind":"references","line":43,"col":9,"candidates":null,"file_path":"TortureConstCtors.dart","language":"dart","status":"failed","name_tail":"Object"} {"from_node_id":"method:a7103764da0854afee05bc7d100478a4","reference_name":"OtherT","reference_kind":"references","line":49,"col":13,"candidates":null,"file_path":"TortureConstCtors.dart","language":"dart","status":"failed","name_tail":"OtherT"} {"from_node_id":"method:a7103764da0854afee05bc7d100478a4","reference_name":"OtherT.named","reference_kind":"calls","line":49,"col":11,"candidates":null,"file_path":"TortureConstCtors.dart","language":"dart","status":"failed","name_tail":"named"} @@ -5684,9 +5718,6 @@ {"from_node_id":"method:aa3a8f86d1972af5856f74de23c7c284","reference_name":"override","reference_kind":"decorates","line":121,"col":2,"candidates":null,"file_path":"TortureAnnotatedComments.dart","language":"dart","status":"failed","name_tail":"override"} {"from_node_id":"method:ac9d754fee3741f21584a0086c577453","reference_name":"Self::assoc","reference_kind":"calls","line":86,"col":8,"candidates":null,"file_path":"torture.rs","language":"rust","status":"failed","name_tail":"assoc"} {"from_node_id":"method:ac9d754fee3741f21584a0086c577453","reference_name":"String::new","reference_kind":"calls","line":89,"col":18,"candidates":null,"file_path":"torture.rs","language":"rust","status":"failed","name_tail":"new"} -{"from_node_id":"method:ae63e6f68d18ae3e3794926b4f75768b","reference_name":"T","reference_kind":"references","line":114,"col":29,"candidates":null,"file_path":"torture.go","language":"go","status":"failed","name_tail":"T"} -{"from_node_id":"method:ae63e6f68d18ae3e3794926b4f75768b","reference_name":"append","reference_kind":"calls","line":115,"col":11,"candidates":null,"file_path":"torture.go","language":"go","status":"failed","name_tail":"append"} -{"from_node_id":"method:ae63e6f68d18ae3e3794926b4f75768b","reference_name":"s.items","reference_kind":"function_ref","line":115,"col":20,"candidates":null,"file_path":"torture.go","language":"go","status":"failed","name_tail":"items"} {"from_node_id":"method:afca03b4aca12c9f04530a20d67acad7","reference_name":"lcall","reference_kind":"calls","line":124,"col":66,"candidates":null,"file_path":"torture.R","language":"r","status":"failed","name_tail":"lcall"} {"from_node_id":"method:aff4cbff9ff5e0d8d44b76d6b40cb120","reference_name":"Local","reference_kind":"calls","line":137,"col":19,"candidates":null,"file_path":"Torture.cs","language":"csharp","status":"failed","name_tail":"Local"} {"from_node_id":"method:b0857dfe91cdb9b6241e743372a66cdf","reference_name":"ICloneable","reference_kind":"references","line":140,"col":121,"candidates":null,"file_path":"Torture.cs","language":"csharp","status":"failed","name_tail":"ICloneable"} @@ -5770,6 +5801,7 @@ {"from_node_id":"method:d85e75675c9c25670ba7f631481482f8","reference_name":"Canvas","reference_kind":"references","line":46,"col":14,"candidates":null,"file_path":"TortureMini.dart","language":"dart","status":"failed","name_tail":"Canvas"} {"from_node_id":"method:d85e75675c9c25670ba7f631481482f8","reference_name":"c.draw","reference_kind":"calls","line":46,"col":32,"candidates":null,"file_path":"TortureMini.dart","language":"dart","status":"failed","name_tail":"draw"} {"from_node_id":"method:d85e75675c9c25670ba7f631481482f8","reference_name":"override","reference_kind":"decorates","line":45,"col":2,"candidates":null,"file_path":"TortureMini.dart","language":"dart","status":"failed","name_tail":"override"} +{"from_node_id":"method:dc018b19c95524f99100bf15538c815b","reference_name":"Context","reference_kind":"references","line":84,"col":15,"candidates":null,"file_path":"torture.go","language":"go","status":"failed","name_tail":"Context"} {"from_node_id":"method:dd439e569e5643b7eab01af84e7b86a4","reference_name":"register","reference_kind":"calls","line":29,"col":4,"candidates":null,"file_path":"torture.js","language":"javascript","status":"failed","name_tail":"register"} {"from_node_id":"method:dd439e569e5643b7eab01af84e7b86a4","reference_name":"super","reference_kind":"calls","line":27,"col":4,"candidates":null,"file_path":"torture.js","language":"javascript","status":"failed","name_tail":"super"} {"from_node_id":"method:de718159205cba9b0d17647ac71f8f2a","reference_name":"draw","reference_kind":"calls","line":77,"col":8,"candidates":null,"file_path":"torture.kt","language":"kotlin","status":"failed","name_tail":"draw"} @@ -5937,32 +5969,38 @@ {"from_node_id":"property:b907b8e69e94f2fd52096df43b482b7b","reference_name":"Widget","reference_kind":"references","line":36,"col":20,"candidates":null,"file_path":"Torture.cs","language":"csharp","status":"failed","name_tail":"Widget"} {"from_node_id":"property:d0f96e89ea9b060af016b84a2b5c71ef","reference_name":"FontConfig","reference_kind":"references","line":27,"col":16,"candidates":null,"file_path":"torture.tsx","language":"tsx","status":"failed","name_tail":"FontConfig"} {"from_node_id":"struct:0c309a8ed6f33456724d94ba73599e04","reference_name":"fmt::Display","reference_kind":"implements","line":62,"col":5,"candidates":null,"file_path":"torture.rs","language":"rust","status":"failed","name_tail":"Display"} -{"from_node_id":"struct:2062166f706221e2d500e7d9807245d9","reference_name":"Base","reference_kind":"extends","line":68,"col":2,"candidates":null,"file_path":"torture.go","language":"go","status":"failed","name_tail":"Base"} {"from_node_id":"struct:33e3531d750b08f5b854203467928f28","reference_name":"Base","reference_kind":"extends","line":19,"col":2,"candidates":null,"file_path":"torture.go","language":"go","status":"failed","name_tail":"Base"} {"from_node_id":"struct:33e3531d750b08f5b854203467928f28","reference_name":"Embedded","reference_kind":"extends","line":21,"col":6,"candidates":null,"file_path":"torture.go","language":"go","status":"failed","name_tail":"Embedded"} {"from_node_id":"struct:33e3531d750b08f5b854203467928f28","reference_name":"Pointer","reference_kind":"extends","line":22,"col":7,"candidates":null,"file_path":"torture.go","language":"go","status":"failed","name_tail":"Pointer"} {"from_node_id":"struct:33e3531d750b08f5b854203467928f28","reference_name":"Queryable","reference_kind":"extends","line":20,"col":1,"candidates":null,"file_path":"torture.go","language":"go","status":"failed","name_tail":"Queryable"} {"from_node_id":"struct:487d89e7a287a16bb02adabeb6c061a0","reference_name":"View","reference_kind":"references","line":122,"col":17,"candidates":null,"file_path":"torture.swift","language":"swift","status":"failed","name_tail":"View"} {"from_node_id":"struct:4ea1b361173ba3f6b1b2e8dfe74e13d3","reference_name":"Iterator","reference_kind":"implements","line":150,"col":9,"candidates":null,"file_path":"torture.rs","language":"rust","status":"failed","name_tail":"Iterator"} +{"from_node_id":"struct:6b80d8f1dbee1c34e187c63b7e616a70","reference_name":"Base","reference_kind":"references","line":44,"col":3,"candidates":null,"file_path":"torture.go","language":"go","status":"failed","name_tail":"Base"} +{"from_node_id":"struct:6b80d8f1dbee1c34e187c63b7e616a70","reference_name":"Context","reference_kind":"references","line":40,"col":24,"candidates":null,"file_path":"torture.go","language":"go","status":"failed","name_tail":"Context"} +{"from_node_id":"struct:6b80d8f1dbee1c34e187c63b7e616a70","reference_name":"Item","reference_kind":"references","line":38,"col":22,"candidates":null,"file_path":"torture.go","language":"go","status":"failed","name_tail":"Item"} +{"from_node_id":"struct:6b80d8f1dbee1c34e187c63b7e616a70","reference_name":"Item","reference_kind":"references","line":47,"col":14,"candidates":null,"file_path":"torture.go","language":"go","status":"failed","name_tail":"Item"} +{"from_node_id":"struct:6b80d8f1dbee1c34e187c63b7e616a70","reference_name":"Item","reference_kind":"references","line":49,"col":28,"candidates":null,"file_path":"torture.go","language":"go","status":"failed","name_tail":"Item"} +{"from_node_id":"struct:6b80d8f1dbee1c34e187c63b7e616a70","reference_name":"Lister","reference_kind":"extends","line":49,"col":7,"candidates":null,"file_path":"torture.go","language":"go","status":"failed","name_tail":"Lister"} {"from_node_id":"struct:6d96b486579cf3fdd66718872215294c","reference_name":"Equatable","reference_kind":"extends","line":39,"col":37,"candidates":null,"file_path":"torture.swift","language":"swift","status":"failed","name_tail":"Equatable"} {"from_node_id":"struct:6d96b486579cf3fdd66718872215294c","reference_name":"RawRepresentable","reference_kind":"extends","line":39,"col":19,"candidates":null,"file_path":"torture.swift","language":"swift","status":"failed","name_tail":"RawRepresentable"} {"from_node_id":"struct:8af466b07dba0b708a3b1922902ab00a","reference_name":"From","reference_kind":"implements","line":171,"col":5,"candidates":null,"file_path":"torture.rs","language":"rust","status":"failed","name_tail":"From"} +{"from_node_id":"struct:ad8421763ee39344ef65f68fc90dd015","reference_name":"Base","reference_kind":"extends","line":109,"col":2,"candidates":null,"file_path":"torture.go","language":"go","status":"failed","name_tail":"Base"} {"from_node_id":"trait:36abc0be91b35b7b2663de83c007b572","reference_name":"Producer","reference_kind":"extends","line":52,"col":18,"candidates":null,"file_path":"torture.rs","language":"rust","status":"failed","name_tail":"Producer"} {"from_node_id":"trait:43a05f33dc47873c975e3feb8f75cbf8","reference_name":"Deserialize","reference_kind":"extends","line":54,"col":26,"candidates":null,"file_path":"torture.rs","language":"rust","status":"failed","name_tail":"Deserialize"} {"from_node_id":"trait:a58fd1ab5cf02f43676433b760728c37","reference_name":"init_cap","reference_kind":"calls","line":46,"col":23,"candidates":null,"file_path":"torture.rs","language":"rust","status":"failed","name_tail":"init_cap"} -{"from_node_id":"type_alias:27e49398ec8ebe39651fd8822e253a54","reference_name":"Item","reference_kind":"references","line":63,"col":32,"candidates":null,"file_path":"torture.go","language":"go","status":"failed","name_tail":"Item"} +{"from_node_id":"type_alias:056dd5fe2cc3e2ad87323386146effcc","reference_name":"Widget","reference_kind":"references","line":128,"col":25,"candidates":null,"file_path":"torture.go","language":"go","status":"failed","name_tail":"Widget"} +{"from_node_id":"type_alias:1bc21f6b21632fe87943700ca4573be4","reference_name":"Widget","reference_kind":"references","line":98,"col":18,"candidates":null,"file_path":"torture.go","language":"go","status":"failed","name_tail":"Widget"} {"from_node_id":"type_alias:4eac8834dd1ceb7059cdc0ebd6a23f96","reference_name":"Data","reference_kind":"references","line":75,"col":21,"candidates":null,"file_path":"torture.swift","language":"swift","status":"failed","name_tail":"Data"} {"from_node_id":"type_alias:4eac8834dd1ceb7059cdc0ebd6a23f96","reference_name":"Void","reference_kind":"references","line":75,"col":30,"candidates":null,"file_path":"torture.swift","language":"swift","status":"failed","name_tail":"Void"} +{"from_node_id":"type_alias:55981ee7594cc71cc0d5283a993cd5f2","reference_name":"Item","reference_kind":"references","line":131,"col":14,"candidates":null,"file_path":"torture.go","language":"go","status":"failed","name_tail":"Item"} {"from_node_id":"type_alias:600473b4a3158649443b2f214febf906","reference_name":"Promise","reference_kind":"references","line":81,"col":27,"candidates":null,"file_path":"torture.tsx","language":"tsx","status":"failed","name_tail":"Promise"} {"from_node_id":"type_alias:600473b4a3158649443b2f214febf906","reference_name":"Promise","reference_kind":"references","line":81,"col":27,"candidates":null,"file_path":"torture.tsx","language":"tsx","status":"failed","name_tail":"Promise"} {"from_node_id":"type_alias:600473b4a3158649443b2f214febf906","reference_name":"Promise","reference_kind":"references","line":81,"col":27,"candidates":null,"file_path":"torture.tsx","language":"tsx","status":"failed","name_tail":"Promise"} -{"from_node_id":"type_alias:75662b893c34aed98e64700a6d01bf8d","reference_name":"Item","reference_kind":"references","line":80,"col":36,"candidates":null,"file_path":"torture.go","language":"go","status":"failed","name_tail":"Item"} +{"from_node_id":"type_alias:608221a5f58d68322f43ee54c190640e","reference_name":"Base","reference_kind":"references","line":134,"col":3,"candidates":null,"file_path":"torture.go","language":"go","status":"failed","name_tail":"Base"} +{"from_node_id":"type_alias:882c227f07ef59b639ecf2c0cfb69f1c","reference_name":"Item","reference_kind":"references","line":104,"col":32,"candidates":null,"file_path":"torture.go","language":"go","status":"failed","name_tail":"Item"} {"from_node_id":"type_alias:8d09bbd71ebfe2d1aa557e0e79aaab99","reference_name":"Builder","reference_kind":"references","line":76,"col":28,"candidates":null,"file_path":"torture.swift","language":"swift","status":"failed","name_tail":"Builder"} {"from_node_id":"type_alias:8d09bbd71ebfe2d1aa557e0e79aaab99","reference_name":"KF","reference_kind":"references","line":76,"col":25,"candidates":null,"file_path":"torture.swift","language":"swift","status":"failed","name_tail":"KF"} -{"from_node_id":"type_alias:a54bf143682054f499fe157e6b733087","reference_name":"Widget","reference_kind":"references","line":57,"col":18,"candidates":null,"file_path":"torture.go","language":"go","status":"failed","name_tail":"Widget"} -{"from_node_id":"type_alias:d4964291bed60f871ad9554b4572ac9b","reference_name":"Item","reference_kind":"references","line":90,"col":14,"candidates":null,"file_path":"torture.go","language":"go","status":"failed","name_tail":"Item"} -{"from_node_id":"type_alias:d9cf57aaa8c6be0b025ae6b685745a39","reference_name":"Base","reference_kind":"references","line":93,"col":3,"candidates":null,"file_path":"torture.go","language":"go","status":"failed","name_tail":"Base"} -{"from_node_id":"type_alias:e67f0306e684e2b34de4b379a1546426","reference_name":"Widget","reference_kind":"references","line":87,"col":25,"candidates":null,"file_path":"torture.go","language":"go","status":"failed","name_tail":"Widget"} +{"from_node_id":"type_alias:965915e648eebc2c230c7f5df6ca9700","reference_name":"Item","reference_kind":"references","line":121,"col":36,"candidates":null,"file_path":"torture.go","language":"go","status":"failed","name_tail":"Item"} {"from_node_id":"type_alias:f84ae3400c1d88837e6d67a42d5eea5a","reference_name":"Req","reference_kind":"references","line":85,"col":32,"candidates":null,"file_path":"torture.tsx","language":"tsx","status":"failed","name_tail":"Req"} {"from_node_id":"type_alias:f84ae3400c1d88837e6d67a42d5eea5a","reference_name":"Req","reference_kind":"references","line":86,"col":27,"candidates":null,"file_path":"torture.tsx","language":"tsx","status":"failed","name_tail":"Req"} {"from_node_id":"type_alias:f84ae3400c1d88837e6d67a42d5eea5a","reference_name":"Resp","reference_kind":"references","line":85,"col":37,"candidates":null,"file_path":"torture.tsx","language":"tsx","status":"failed","name_tail":"Resp"} @@ -5970,14 +6008,13 @@ {"from_node_id":"type_alias:f84ae3400c1d88837e6d67a42d5eea5a","reference_name":"Service","reference_kind":"references","line":85,"col":2,"candidates":null,"file_path":"torture.tsx","language":"tsx","status":"failed","name_tail":"Service"} {"from_node_id":"type_alias:f84ae3400c1d88837e6d67a42d5eea5a","reference_name":"Service","reference_kind":"references","line":86,"col":2,"candidates":null,"file_path":"torture.tsx","language":"tsx","status":"failed","name_tail":"Service"} {"from_node_id":"variable:0560d6516d21bba56151a91b46a3458f","reference_name":"target_cb","reference_kind":"function_ref","line":48,"col":20,"candidates":null,"file_path":"torture.py","language":"python","status":"failed","name_tail":"target_cb"} -{"from_node_id":"variable:07821b80e054d5ee85de38b0c45e1662","reference_name":"notes.md#top","reference_kind":"references","line":141,"col":17,"candidates":null,"file_path":"torture.go","language":"go","status":"failed","name_tail":"md#top"} {"from_node_id":"variable:07f4c15ac5517d372045b53113f115ec","reference_name":"example.com/remote.md","reference_kind":"references","line":116,"col":25,"candidates":null,"file_path":"torture.lua","language":"lua","status":"failed","name_tail":"remote.md"} {"from_node_id":"variable:107967afd523982bfd99c4fe3b90a2a1","reference_name":"notes.md#top","reference_kind":"references","line":117,"col":20,"candidates":null,"file_path":"torture.lua","language":"lua","status":"failed","name_tail":"md#top"} +{"from_node_id":"variable:1408b0cc15b4db6aa165d25216f1f59a","reference_name":"docs/rooted.md","reference_kind":"references","line":179,"col":16,"candidates":null,"file_path":"torture.go","language":"go","status":"failed","name_tail":"rooted.md"} {"from_node_id":"variable:144c41f1fe7d4cdfb643e499172e0f2c","reference_name":"a.md","reference_kind":"references","line":243,"col":21,"candidates":null,"file_path":"torture.rb","language":"ruby","status":"failed","name_tail":"md"} {"from_node_id":"variable:144c41f1fe7d4cdfb643e499172e0f2c","reference_name":"sub/b.mdx","reference_kind":"references","line":243,"col":35,"candidates":null,"file_path":"torture.rb","language":"ruby","status":"failed","name_tail":"b.mdx"} {"from_node_id":"variable:1c2f423d65ed4cdd847201e9ee1dab10","reference_name":"notes.md#top","reference_kind":"references","line":308,"col":26,"candidates":null,"file_path":"torture.rs","language":"rust","status":"failed","name_tail":"md#top"} {"from_node_id":"variable:24ba9f675d787f6d3fe83c1c31297927","reference_name":"compute_len","reference_kind":"calls","line":289,"col":26,"candidates":null,"file_path":"torture.rs","language":"rust","status":"failed","name_tail":"compute_len"} -{"from_node_id":"variable:275e942a48e8d317edfcc10e72224781","reference_name":"README.md","reference_kind":"references","line":137,"col":14,"candidates":null,"file_path":"torture.go","language":"go","status":"failed","name_tail":"md"} {"from_node_id":"variable:2b617ae851391aec3cce4ab34663df46","reference_name":"docs/rooted.md","reference_kind":"references","line":67,"col":19,"candidates":null,"file_path":"torture.luau","language":"luau","status":"failed","name_tail":"rooted.md"} {"from_node_id":"variable:2c97371982bc8cb00d33dea8739ea6e0","reference_name":"notes.md#top","reference_kind":"references","line":242,"col":14,"candidates":null,"file_path":"torture.rb","language":"ruby","status":"failed","name_tail":"md#top"} {"from_node_id":"variable:31334faedc88ad501a488504f781e9a8","reference_name":"docs/rooted.md","reference_kind":"references","line":305,"col":25,"candidates":null,"file_path":"torture.rs","language":"rust","status":"failed","name_tail":"rooted.md"} @@ -5987,7 +6024,6 @@ {"from_node_id":"variable:5bd0b7aea699a56bf2affd88c24f6f47","reference_name":"README.md","reference_kind":"references","line":113,"col":17,"candidates":null,"file_path":"torture.lua","language":"lua","status":"failed","name_tail":"md"} {"from_node_id":"variable:5cbfbd2a59a71a50f9a1ce36a6858ef9","reference_name":"a.md","reference_kind":"references","line":309,"col":33,"candidates":null,"file_path":"torture.rs","language":"rust","status":"failed","name_tail":"md"} {"from_node_id":"variable:5cbfbd2a59a71a50f9a1ce36a6858ef9","reference_name":"sub/b.mdx","reference_kind":"references","line":309,"col":47,"candidates":null,"file_path":"torture.rs","language":"rust","status":"failed","name_tail":"b.mdx"} -{"from_node_id":"variable:5fcf61afe5e989403b634479bb7f684a","reference_name":"example.com/remote.md","reference_kind":"references","line":140,"col":22,"candidates":null,"file_path":"torture.go","language":"go","status":"failed","name_tail":"remote.md"} {"from_node_id":"variable:751570e9a1f8514a268f013d78119aad","reference_name":"docs/rooted.md","reference_kind":"references","line":239,"col":13,"candidates":null,"file_path":"torture.rb","language":"ruby","status":"failed","name_tail":"rooted.md"} {"from_node_id":"variable:788d75a828c79f9847e0be0e2b73a196","reference_name":"compute","reference_kind":"calls","line":10,"col":4,"candidates":null,"file_path":"torture.py","language":"python","status":"failed","name_tail":"compute"} {"from_node_id":"variable:81d0ff7eaabc267206fbd5529a482e62","reference_name":"docs/rooted.md","reference_kind":"references","line":114,"col":19,"candidates":null,"file_path":"torture.lua","language":"lua","status":"failed","name_tail":"rooted.md"} @@ -5995,20 +6031,22 @@ {"from_node_id":"variable:8ba939f37f98d071b9c0a5d1c73590cd","reference_name":"a.md","reference_kind":"references","line":118,"col":27,"candidates":null,"file_path":"torture.lua","language":"lua","status":"failed","name_tail":"md"} {"from_node_id":"variable:8ba939f37f98d071b9c0a5d1c73590cd","reference_name":"sub/b.mdx","reference_kind":"references","line":118,"col":41,"candidates":null,"file_path":"torture.lua","language":"lua","status":"failed","name_tail":"b.mdx"} {"from_node_id":"variable:9b11e2d2271460cf5d5c12d00f607ca1","reference_name":"helper","reference_kind":"calls","line":52,"col":13,"candidates":null,"file_path":"torture.py","language":"python","status":"failed","name_tail":"helper"} +{"from_node_id":"variable:9ebd601a4fad63af418ac0bc8c0ec04c","reference_name":"example.com/remote.md","reference_kind":"references","line":181,"col":22,"candidates":null,"file_path":"torture.go","language":"go","status":"failed","name_tail":"remote.md"} +{"from_node_id":"variable:adb6634d66354e5a2f46a0cd4ab58050","reference_name":"a.md","reference_kind":"references","line":183,"col":22,"candidates":null,"file_path":"torture.go","language":"go","status":"failed","name_tail":"md"} +{"from_node_id":"variable:adb6634d66354e5a2f46a0cd4ab58050","reference_name":"sub/b.mdx","reference_kind":"references","line":183,"col":36,"candidates":null,"file_path":"torture.go","language":"go","status":"failed","name_tail":"b.mdx"} {"from_node_id":"variable:b414249421e00ef2a2debd7c2865720f","reference_name":"a.md","reference_kind":"references","line":71,"col":27,"candidates":null,"file_path":"torture.luau","language":"luau","status":"failed","name_tail":"md"} {"from_node_id":"variable:b414249421e00ef2a2debd7c2865720f","reference_name":"sub/b.mdx","reference_kind":"references","line":71,"col":41,"candidates":null,"file_path":"torture.luau","language":"luau","status":"failed","name_tail":"b.mdx"} {"from_node_id":"variable:c23cd3435fea1505587b5a4809da3f5e","reference_name":"Lazy::new","reference_kind":"calls","line":290,"col":30,"candidates":null,"file_path":"torture.rs","language":"rust","status":"failed","name_tail":"new"} {"from_node_id":"variable:c23cd3435fea1505587b5a4809da3f5e","reference_name":"build_cfg","reference_kind":"calls","line":290,"col":43,"candidates":null,"file_path":"torture.rs","language":"rust","status":"failed","name_tail":"build_cfg"} {"from_node_id":"variable:cd9e9fe748d0f3513f7f6c6c74264f2c","reference_name":"README.md","reference_kind":"references","line":304,"col":23,"candidates":null,"file_path":"torture.rs","language":"rust","status":"failed","name_tail":"md"} +{"from_node_id":"variable:d0140163eccfbe839cf7b486e7f09269","reference_name":"README.md","reference_kind":"references","line":178,"col":14,"candidates":null,"file_path":"torture.go","language":"go","status":"failed","name_tail":"md"} {"from_node_id":"variable:dc32e43e11cbd6a5aa9ed4fd06aa4e45","reference_name":"example.com/remote.md","reference_kind":"references","line":241,"col":19,"candidates":null,"file_path":"torture.rb","language":"ruby","status":"failed","name_tail":"remote.md"} {"from_node_id":"variable:e226fd913c4b21d87da0115d1007adab","reference_name":"example.com/remote.md","reference_kind":"references","line":69,"col":25,"candidates":null,"file_path":"torture.luau","language":"luau","status":"failed","name_tail":"remote.md"} -{"from_node_id":"variable:e86e18d25431b1b127ce786fcbaa833d","reference_name":"docs/rooted.md","reference_kind":"references","line":138,"col":16,"candidates":null,"file_path":"torture.go","language":"go","status":"failed","name_tail":"rooted.md"} -{"from_node_id":"variable:f86a0cee4e700858bb0604100cdf9f50","reference_name":"a.md","reference_kind":"references","line":142,"col":22,"candidates":null,"file_path":"torture.go","language":"go","status":"failed","name_tail":"md"} -{"from_node_id":"variable:f86a0cee4e700858bb0604100cdf9f50","reference_name":"sub/b.mdx","reference_kind":"references","line":142,"col":36,"candidates":null,"file_path":"torture.go","language":"go","status":"failed","name_tail":"b.mdx"} +{"from_node_id":"variable:e6121ba1baf8c5f551e7d79391a5f970","reference_name":"notes.md#top","reference_kind":"references","line":182,"col":17,"candidates":null,"file_path":"torture.go","language":"go","status":"failed","name_tail":"md#top"} {"from_node_id":"variable:f90ca95a6ecd4291f24e8cc99492595f","reference_name":"notes.md#top","reference_kind":"references","line":70,"col":20,"candidates":null,"file_path":"torture.luau","language":"luau","status":"failed","name_tail":"md#top"} {"from_node_id":"variable:fb450996c12f335b36201ead67a34f64","reference_name":"helper","reference_kind":"calls","line":54,"col":17,"candidates":null,"file_path":"torture.py","language":"python","status":"failed","name_tail":"helper"} {"from_node_id":"variable:feb330d554c5d0caaa8978323a006e52","reference_name":"README.md","reference_kind":"references","line":238,"col":11,"candidates":null,"file_path":"torture.rb","language":"ruby","status":"failed","name_tail":"md"} -== bindings (849) +== bindings (859) {"file_path":"Torture.java","name":"","kind":"local","node_id":"class:c4ed77533cd6f14e451fe7962f484e20","target_spec":null,"target_name":null,"exported_as":null,"export_form":null,"scope_start":27,"scope_end":32,"storage":null,"line":27} {"file_path":"Torture.java","name":"","kind":"local","node_id":"class:66085d60d16ebfd037ddd1bd9273a82e","target_spec":null,"target_name":null,"exported_as":null,"export_form":null,"scope_start":36,"scope_end":48,"storage":null,"line":42} {"file_path":"Torture.java","name":"API_BASE","kind":"local","node_id":"constant:027c429f02116e6725f83e648b4778cf","target_spec":null,"target_name":null,"exported_as":null,"export_form":null,"scope_start":16,"scope_end":106,"storage":null,"line":21} @@ -6329,67 +6367,77 @@ {"file_path":"torture.cpp","name":"vector","kind":"import","node_id":null,"target_spec":"vector","target_name":"*","exported_as":null,"export_form":null,"scope_start":1,"scope_end":171,"storage":null,"line":8} {"file_path":"torture.cpp","name":"widget_base","kind":"import","node_id":null,"target_spec":"widget_base.hpp","target_name":"*","exported_as":null,"export_form":null,"scope_start":1,"scope_end":171,"storage":null,"line":9} {"file_path":"torture.cpp","name":"~Session","kind":"local","node_id":"method:2328804ffd8c133163e907a0d7dac30c","target_spec":null,"target_name":null,"exported_as":null,"export_form":null,"scope_start":38,"scope_end":44,"storage":null,"line":41} -{"file_path":"torture.go","name":"Alias","kind":"decl","node_id":"type_alias:a54bf143682054f499fe157e6b733087","target_spec":null,"target_name":null,"exported_as":"Alias","export_form":"public","scope_start":1,"scope_end":147,"storage":null,"line":57} -{"file_path":"torture.go","name":"AnonAlias","kind":"decl","node_id":"struct:2062166f706221e2d500e7d9807245d9","target_spec":null,"target_name":null,"exported_as":"AnonAlias","export_form":"public","scope_start":1,"scope_end":147,"storage":null,"line":67} -{"file_path":"torture.go","name":"Core","kind":"decl","node_id":"interface:87965a8e467d41375154fe8ae108b529","target_spec":null,"target_name":null,"exported_as":"Core","export_form":"public","scope_start":1,"scope_end":147,"storage":null,"line":39} -{"file_path":"torture.go","name":"DefaultRegistry","kind":"decl","node_id":"variable:1837cd19ce5f7a8f45b7fa4b8fc8a0e6","target_spec":null,"target_name":null,"exported_as":"DefaultRegistry","export_form":"public","scope_start":1,"scope_end":147,"storage":null,"line":11} -{"file_path":"torture.go","name":"Defined","kind":"decl","node_id":"type_alias:70a70301f02c5dd34c45fea884736d5d","target_spec":null,"target_name":null,"exported_as":"Defined","export_form":"public","scope_start":1,"scope_end":147,"storage":null,"line":64} -{"file_path":"torture.go","name":"Dur","kind":"decl","node_id":"type_alias:10728d965a9856b988bb2359a09666f9","target_spec":null,"target_name":null,"exported_as":"Dur","export_form":"public","scope_start":1,"scope_end":147,"storage":null,"line":54} -{"file_path":"torture.go","name":"Exact","kind":"decl","node_id":"interface:5a28b97ecb59911dbe27ad63e859459d","target_spec":null,"target_name":null,"exported_as":"Exact","export_form":"public","scope_start":1,"scope_end":147,"storage":null,"line":52} -{"file_path":"torture.go","name":"FnAlias","kind":"decl","node_id":"type_alias:4b2d750ab1f528d33a2d6713cb2193a7","target_spec":null,"target_name":null,"exported_as":"FnAlias","export_form":"public","scope_start":1,"scope_end":147,"storage":null,"line":62} -{"file_path":"torture.go","name":"Grid","kind":"decl","node_id":"type_alias:44cb4653a5e07bdcee1050ba3133ab31","target_spec":null,"target_name":null,"exported_as":"Grid","export_form":"public","scope_start":1,"scope_end":147,"storage":null,"line":88} -{"file_path":"torture.go","name":"HandlerFunc","kind":"decl","node_id":"type_alias:75662b893c34aed98e64700a6d01bf8d","target_spec":null,"target_name":null,"exported_as":"HandlerFunc","export_form":"public","scope_start":1,"scope_end":147,"storage":null,"line":80} -{"file_path":"torture.go","name":"HandlersChain","kind":"decl","node_id":"type_alias:c0ad8af1b5e37e6ad90fd0c5790b6209","target_spec":null,"target_name":null,"exported_as":"HandlersChain","export_form":"public","scope_start":1,"scope_end":147,"storage":null,"line":82} -{"file_path":"torture.go","name":"IfaceAlias","kind":"decl","node_id":"interface:8045ff3999885f68bd3b9b0e8709aeeb","target_spec":null,"target_name":null,"exported_as":"IfaceAlias","export_form":"public","scope_start":1,"scope_end":147,"storage":null,"line":72} -{"file_path":"torture.go","name":"Item","kind":"decl","node_id":"type_alias:d4964291bed60f871ad9554b4572ac9b","target_spec":null,"target_name":null,"exported_as":"Item","export_form":"public","scope_start":1,"scope_end":147,"storage":null,"line":90} -{"file_path":"torture.go","name":"LocalAlias","kind":"decl","node_id":"type_alias:bb8bd8650e34457304e34b86851c1431","target_spec":null,"target_name":null,"exported_as":"LocalAlias","export_form":"public","scope_start":1,"scope_end":147,"storage":null,"line":60} -{"file_path":"torture.go","name":"Lookup","kind":"decl","node_id":"type_alias:e67f0306e684e2b34de4b379a1546426","target_spec":null,"target_name":null,"exported_as":"Lookup","export_form":"public","scope_start":1,"scope_end":147,"storage":null,"line":87} -{"file_path":"torture.go","name":"MAX_ITEMS","kind":"decl","node_id":"constant:0558b57204d51fcce0a73629df252447","target_spec":null,"target_name":null,"exported_as":"MAX_ITEMS","export_form":"public","scope_start":1,"scope_end":147,"storage":null,"line":9} -{"file_path":"torture.go","name":"MAX_ITEMS","kind":"local","node_id":null,"target_spec":null,"target_name":null,"exported_as":null,"export_form":null,"scope_start":124,"scope_end":127,"storage":null,"line":125} -{"file_path":"torture.go","name":"MapAlias","kind":"decl","node_id":"type_alias:27e49398ec8ebe39651fd8822e253a54","target_spec":null,"target_name":null,"exported_as":"MapAlias","export_form":"public","scope_start":1,"scope_end":147,"storage":null,"line":63} -{"file_path":"torture.go","name":"Marshal","kind":"local","node_id":"method:6fc4e3ad2b4db571a700d39f81c2c090","target_spec":null,"target_name":null,"exported_as":null,"export_form":null,"scope_start":39,"scope_end":46,"storage":null,"line":44} -{"file_path":"torture.go","name":"Minutes","kind":"decl","node_id":"type_alias:ff4b77836c3d72b57438c1723760af51","target_spec":null,"target_name":null,"exported_as":"Minutes","export_form":"public","scope_start":1,"scope_end":147,"storage":null,"line":36} -{"file_path":"torture.go","name":"Nested","kind":"decl","node_id":"type_alias:d9cf57aaa8c6be0b025ae6b685745a39","target_spec":null,"target_name":null,"exported_as":"Nested","export_form":"public","scope_start":1,"scope_end":147,"storage":null,"line":91} -{"file_path":"torture.go","name":"NewRegistry","kind":"decl","node_id":"function:ffbfbea1bf90b2536f05eed532eb53ce","target_spec":null,"target_name":null,"exported_as":"NewRegistry","export_form":"public","scope_start":1,"scope_end":147,"storage":null,"line":105} -{"file_path":"torture.go","name":"Number","kind":"decl","node_id":"interface:c15bd0cb4f4a33ae49f280e29878fb61","target_spec":null,"target_name":null,"exported_as":"Number","export_form":"public","scope_start":1,"scope_end":147,"storage":null,"line":48} -{"file_path":"torture.go","name":"PtrAlias","kind":"decl","node_id":"type_alias:80c39c4f28c27d78ecdedc474ae4af7b","target_spec":null,"target_name":null,"exported_as":"PtrAlias","export_form":"public","scope_start":1,"scope_end":147,"storage":null,"line":61} -{"file_path":"torture.go","name":"Push","kind":"decl","node_id":"method:ae63e6f68d18ae3e3794926b4f75768b","target_spec":null,"target_name":null,"exported_as":"Push","export_form":"public","scope_start":1,"scope_end":147,"storage":null,"line":114} -{"file_path":"torture.go","name":"Render","kind":"decl","node_id":"method:72417d24bc1311c2e420094c5d05c459","target_spec":null,"target_name":null,"exported_as":"Render","export_form":"public","scope_start":1,"scope_end":147,"storage":null,"line":118} -{"file_path":"torture.go","name":"Render","kind":"local","node_id":"method:92741f1ace46d5b7eeb9715c9a1098f9","target_spec":null,"target_name":null,"exported_as":null,"export_form":null,"scope_start":72,"scope_end":74,"storage":null,"line":73} -{"file_path":"torture.go","name":"Seconds","kind":"decl","node_id":"type_alias:27e7afa3d9358e091e23f4ee6e495fc5","target_spec":null,"target_name":null,"exported_as":"Seconds","export_form":"public","scope_start":1,"scope_end":147,"storage":null,"line":34} -{"file_path":"torture.go","name":"Stack","kind":"decl","node_id":"struct:4c67fc2c851f10cf7803489ef577fc3c","target_spec":null,"target_name":null,"exported_as":"Stack","export_form":"public","scope_start":1,"scope_end":147,"storage":null,"line":28} -{"file_path":"torture.go","name":"TargetCb","kind":"decl","node_id":"function:0e1ad124e719c2d18615cda6816af46c","target_spec":null,"target_name":null,"exported_as":"TargetCb","export_form":"public","scope_start":1,"scope_end":147,"storage":null,"line":122} -{"file_path":"torture.go","name":"Tree","kind":"decl","node_id":"type_alias:df1bf626c237f1dfe84e753a6edace47","target_spec":null,"target_name":null,"exported_as":"Tree","export_form":"public","scope_start":1,"scope_end":147,"storage":null,"line":97} -{"file_path":"torture.go","name":"Unmarshal","kind":"local","node_id":"method:e5720c08e3888accbb1c2aa2421e1dd1","target_spec":null,"target_name":null,"exported_as":null,"export_form":null,"scope_start":39,"scope_end":46,"storage":null,"line":45} -{"file_path":"torture.go","name":"WatchChan","kind":"decl","node_id":"type_alias:2652fcdf36b42377e527cf35f8d800c9","target_spec":null,"target_name":null,"exported_as":"WatchChan","export_form":"public","scope_start":1,"scope_end":147,"storage":null,"line":84} -{"file_path":"torture.go","name":"Widget","kind":"decl","node_id":"struct:33e3531d750b08f5b854203467928f28","target_spec":null,"target_name":null,"exported_as":"Widget","export_form":"public","scope_start":1,"scope_end":147,"storage":null,"line":18} -{"file_path":"torture.go","name":"WordAlias","kind":"decl","node_id":"type_alias:99498bda61debd01b2e7459030084c24","target_spec":null,"target_name":null,"exported_as":"WordAlias","export_form":"public","scope_start":1,"scope_end":147,"storage":null,"line":76} -{"file_path":"torture.go","name":"Wrapped","kind":"decl","node_id":"type_alias:f61f67035897704f4a03cf76fb59e8a9","target_spec":null,"target_name":null,"exported_as":"Wrapped","export_form":"public","scope_start":1,"scope_end":147,"storage":null,"line":89} -{"file_path":"torture.go","name":"a","kind":"param","node_id":null,"target_spec":null,"target_name":null,"exported_as":null,"export_form":null,"scope_start":101,"scope_end":103,"storage":null,"line":101} -{"file_path":"torture.go","name":"cfg","kind":"local","node_id":null,"target_spec":null,"target_name":null,"exported_as":null,"export_form":null,"scope_start":105,"scope_end":112,"storage":null,"line":109} -{"file_path":"torture.go","name":"data","kind":"param","node_id":null,"target_spec":null,"target_name":null,"exported_as":null,"export_form":null,"scope_start":45,"scope_end":45,"storage":null,"line":45} -{"file_path":"torture.go","name":"fmt","kind":"import","node_id":null,"target_spec":"fmt","target_name":"*","exported_as":null,"export_form":null,"scope_start":1,"scope_end":147,"storage":null,"line":5} -{"file_path":"torture.go","name":"handlerTable","kind":"decl","node_id":"variable:6b7262d2883839c6f601126f4dd59e9b","target_spec":null,"target_name":null,"exported_as":null,"export_form":null,"scope_start":1,"scope_end":147,"storage":"package","line":13} -{"file_path":"torture.go","name":"item","kind":"param","node_id":null,"target_spec":null,"target_name":null,"exported_as":null,"export_form":null,"scope_start":114,"scope_end":116,"storage":null,"line":114} -{"file_path":"torture.go","name":"mdBare","kind":"decl","node_id":"variable:275e942a48e8d317edfcc10e72224781","target_spec":null,"target_name":null,"exported_as":null,"export_form":null,"scope_start":1,"scope_end":147,"storage":"package","line":137} -{"file_path":"torture.go","name":"mdEscapes","kind":"decl","node_id":"variable:e44edf805f627d7e108028e303a440cd","target_spec":null,"target_name":null,"exported_as":null,"export_form":null,"scope_start":1,"scope_end":147,"storage":"package","line":139} -{"file_path":"torture.go","name":"mdGuide","kind":"decl","node_id":"variable:800eb8cdb0ef790d2cef3a151e6db41c","target_spec":null,"target_name":null,"exported_as":null,"export_form":null,"scope_start":1,"scope_end":147,"storage":"package","line":136} -{"file_path":"torture.go","name":"mdLoad","kind":"decl","node_id":"function:46864a1a62b2fd2a4e1657a52005c4e7","target_spec":null,"target_name":null,"exported_as":null,"export_form":null,"scope_start":1,"scope_end":147,"storage":"package","line":144} -{"file_path":"torture.go","name":"mdQueried","kind":"decl","node_id":"variable:07821b80e054d5ee85de38b0c45e1662","target_spec":null,"target_name":null,"exported_as":null,"export_form":null,"scope_start":1,"scope_end":147,"storage":"package","line":141} -{"file_path":"torture.go","name":"mdRemote","kind":"decl","node_id":"variable:5fcf61afe5e989403b634479bb7f684a","target_spec":null,"target_name":null,"exported_as":null,"export_form":null,"scope_start":1,"scope_end":147,"storage":"package","line":140} -{"file_path":"torture.go","name":"mdRooted","kind":"decl","node_id":"variable:e86e18d25431b1b127ce786fcbaa833d","target_spec":null,"target_name":null,"exported_as":null,"export_form":null,"scope_start":1,"scope_end":147,"storage":"package","line":138} -{"file_path":"torture.go","name":"mdTwoInOne","kind":"decl","node_id":"variable:f86a0cee4e700858bb0604100cdf9f50","target_spec":null,"target_name":null,"exported_as":null,"export_form":null,"scope_start":1,"scope_end":147,"storage":"package","line":142} -{"file_path":"torture.go","name":"n","kind":"param","node_id":null,"target_spec":null,"target_name":null,"exported_as":null,"export_form":null,"scope_start":122,"scope_end":122,"storage":null,"line":122} -{"file_path":"torture.go","name":"pkga","kind":"import","node_id":null,"target_spec":"example.com/other/pkga","target_name":"*","exported_as":null,"export_form":null,"scope_start":1,"scope_end":147,"storage":null,"line":6} -{"file_path":"torture.go","name":"q","kind":"local","node_id":null,"target_spec":null,"target_name":null,"exported_as":null,"export_form":null,"scope_start":105,"scope_end":112,"storage":null,"line":107} -{"file_path":"torture.go","name":"reads","kind":"decl","node_id":"function:179a74d774cb7efadf2594cebb29f4a9","target_spec":null,"target_name":null,"exported_as":null,"export_form":null,"scope_start":1,"scope_end":147,"storage":"package","line":129} -{"file_path":"torture.go","name":"s","kind":"param","node_id":null,"target_spec":null,"target_name":null,"exported_as":null,"export_form":null,"scope_start":114,"scope_end":116,"storage":null,"line":114} -{"file_path":"torture.go","name":"shadowed","kind":"decl","node_id":"function:140cc1d2e83fc5a1968f8058b5457dd1","target_spec":null,"target_name":null,"exported_as":null,"export_form":null,"scope_start":1,"scope_end":147,"storage":"package","line":124} -{"file_path":"torture.go","name":"stateFn","kind":"decl","node_id":"type_alias:c925710f298dd798808037fcf660f73b","target_spec":null,"target_name":null,"exported_as":null,"export_form":null,"scope_start":1,"scope_end":147,"storage":"package","line":99} -{"file_path":"torture.go","name":"useAlias","kind":"decl","node_id":"function:5caa38feff95389d550207e842f7ac7e","target_spec":null,"target_name":null,"exported_as":null,"export_form":null,"scope_start":1,"scope_end":147,"storage":"package","line":101} -{"file_path":"torture.go","name":"v","kind":"param","node_id":null,"target_spec":null,"target_name":null,"exported_as":null,"export_form":null,"scope_start":44,"scope_end":44,"storage":null,"line":44} -{"file_path":"torture.go","name":"w","kind":"local","node_id":null,"target_spec":null,"target_name":null,"exported_as":null,"export_form":null,"scope_start":105,"scope_end":112,"storage":null,"line":106} -{"file_path":"torture.go","name":"w","kind":"param","node_id":null,"target_spec":null,"target_name":null,"exported_as":null,"export_form":null,"scope_start":118,"scope_end":120,"storage":null,"line":118} +{"file_path":"torture.go","name":"Alias","kind":"decl","node_id":"type_alias:1bc21f6b21632fe87943700ca4573be4","target_spec":null,"target_name":null,"exported_as":"Alias","export_form":"public","scope_start":1,"scope_end":188,"storage":null,"line":98} +{"file_path":"torture.go","name":"AnonAlias","kind":"decl","node_id":"struct:ad8421763ee39344ef65f68fc90dd015","target_spec":null,"target_name":null,"exported_as":"AnonAlias","export_form":"public","scope_start":1,"scope_end":188,"storage":null,"line":108} +{"file_path":"torture.go","name":"AnonFields","kind":"decl","node_id":"struct:44d6f0ea6746cda4ce3d410ce9c99a46","target_spec":null,"target_name":null,"exported_as":"AnonFields","export_form":"public","scope_start":1,"scope_end":188,"storage":null,"line":61} +{"file_path":"torture.go","name":"Core","kind":"decl","node_id":"interface:6ed108f5ca6c8f6b9f40a746e9396c03","target_spec":null,"target_name":null,"exported_as":"Core","export_form":"public","scope_start":1,"scope_end":188,"storage":null,"line":72} +{"file_path":"torture.go","name":"DefaultRegistry","kind":"decl","node_id":"variable:1837cd19ce5f7a8f45b7fa4b8fc8a0e6","target_spec":null,"target_name":null,"exported_as":"DefaultRegistry","export_form":"public","scope_start":1,"scope_end":188,"storage":null,"line":11} +{"file_path":"torture.go","name":"Defined","kind":"decl","node_id":"type_alias:c9fe81e444d43593fc382a0be628bc66","target_spec":null,"target_name":null,"exported_as":"Defined","export_form":"public","scope_start":1,"scope_end":188,"storage":null,"line":105} +{"file_path":"torture.go","name":"Dur","kind":"decl","node_id":"type_alias:2a5e03d369bc91073bc0792b6964ac16","target_spec":null,"target_name":null,"exported_as":"Dur","export_form":"public","scope_start":1,"scope_end":188,"storage":null,"line":95} +{"file_path":"torture.go","name":"Each","kind":"local","node_id":"method:a5cd5e67746962200f8230ebedb5413e","target_spec":null,"target_name":null,"exported_as":null,"export_form":null,"scope_start":83,"scope_end":87,"storage":null,"line":85} +{"file_path":"torture.go","name":"Exact","kind":"decl","node_id":"interface:b5773212ca0e5396a677e9062f68d204","target_spec":null,"target_name":null,"exported_as":"Exact","export_form":"public","scope_start":1,"scope_end":188,"storage":null,"line":93} +{"file_path":"torture.go","name":"Find","kind":"local","node_id":"method:dc018b19c95524f99100bf15538c815b","target_spec":null,"target_name":null,"exported_as":null,"export_form":null,"scope_start":83,"scope_end":87,"storage":null,"line":84} +{"file_path":"torture.go","name":"FnAlias","kind":"decl","node_id":"type_alias:02bad22974119233684c4cdc31b84c08","target_spec":null,"target_name":null,"exported_as":"FnAlias","export_form":"public","scope_start":1,"scope_end":188,"storage":null,"line":103} +{"file_path":"torture.go","name":"Grid","kind":"decl","node_id":"type_alias:f6d4e998f3c2200dadf5c1e05f9368ab","target_spec":null,"target_name":null,"exported_as":"Grid","export_form":"public","scope_start":1,"scope_end":188,"storage":null,"line":129} +{"file_path":"torture.go","name":"HandlerFunc","kind":"decl","node_id":"type_alias:965915e648eebc2c230c7f5df6ca9700","target_spec":null,"target_name":null,"exported_as":"HandlerFunc","export_form":"public","scope_start":1,"scope_end":188,"storage":null,"line":121} +{"file_path":"torture.go","name":"HandlersChain","kind":"decl","node_id":"type_alias:5fab20424fd8ff6f365fbb0e5eec9c84","target_spec":null,"target_name":null,"exported_as":"HandlersChain","export_form":"public","scope_start":1,"scope_end":188,"storage":null,"line":123} +{"file_path":"torture.go","name":"IfaceAlias","kind":"decl","node_id":"interface:3003e30a3fc9ee8bf1f1153918085038","target_spec":null,"target_name":null,"exported_as":"IfaceAlias","export_form":"public","scope_start":1,"scope_end":188,"storage":null,"line":113} +{"file_path":"torture.go","name":"Item","kind":"decl","node_id":"type_alias:55981ee7594cc71cc0d5283a993cd5f2","target_spec":null,"target_name":null,"exported_as":"Item","export_form":"public","scope_start":1,"scope_end":188,"storage":null,"line":131} +{"file_path":"torture.go","name":"LocalAlias","kind":"decl","node_id":"type_alias:09f9cb5669970256407b8aebd0528e7d","target_spec":null,"target_name":null,"exported_as":"LocalAlias","export_form":"public","scope_start":1,"scope_end":188,"storage":null,"line":101} +{"file_path":"torture.go","name":"Lookup","kind":"decl","node_id":"type_alias:056dd5fe2cc3e2ad87323386146effcc","target_spec":null,"target_name":null,"exported_as":"Lookup","export_form":"public","scope_start":1,"scope_end":188,"storage":null,"line":128} +{"file_path":"torture.go","name":"MAX_ITEMS","kind":"decl","node_id":"constant:0558b57204d51fcce0a73629df252447","target_spec":null,"target_name":null,"exported_as":"MAX_ITEMS","export_form":"public","scope_start":1,"scope_end":188,"storage":null,"line":9} +{"file_path":"torture.go","name":"MAX_ITEMS","kind":"local","node_id":null,"target_spec":null,"target_name":null,"exported_as":null,"export_form":null,"scope_start":165,"scope_end":168,"storage":null,"line":166} +{"file_path":"torture.go","name":"MapAlias","kind":"decl","node_id":"type_alias:882c227f07ef59b639ecf2c0cfb69f1c","target_spec":null,"target_name":null,"exported_as":"MapAlias","export_form":"public","scope_start":1,"scope_end":188,"storage":null,"line":104} +{"file_path":"torture.go","name":"Marshal","kind":"local","node_id":"method:67012fcd3f5d759fab7fa829faf85af2","target_spec":null,"target_name":null,"exported_as":null,"export_form":null,"scope_start":72,"scope_end":79,"storage":null,"line":77} +{"file_path":"torture.go","name":"Minutes","kind":"decl","node_id":"type_alias:439984898e3d20cbd0156ea66c4aab37","target_spec":null,"target_name":null,"exported_as":"Minutes","export_form":"public","scope_start":1,"scope_end":188,"storage":null,"line":69} +{"file_path":"torture.go","name":"Nested","kind":"decl","node_id":"type_alias:608221a5f58d68322f43ee54c190640e","target_spec":null,"target_name":null,"exported_as":"Nested","export_form":"public","scope_start":1,"scope_end":188,"storage":null,"line":132} +{"file_path":"torture.go","name":"NewRegistry","kind":"decl","node_id":"function:81cc5b0d788ee9727656191bb6a35597","target_spec":null,"target_name":null,"exported_as":"NewRegistry","export_form":"public","scope_start":1,"scope_end":188,"storage":null,"line":146} +{"file_path":"torture.go","name":"Number","kind":"decl","node_id":"interface:479db15a71788832458ca8ffe80aba83","target_spec":null,"target_name":null,"exported_as":"Number","export_form":"public","scope_start":1,"scope_end":188,"storage":null,"line":89} +{"file_path":"torture.go","name":"Pool","kind":"decl","node_id":"struct:b5d2c300d801f1233941b73d992ba7eb","target_spec":null,"target_name":null,"exported_as":"Pool","export_form":"public","scope_start":1,"scope_end":188,"storage":null,"line":54} +{"file_path":"torture.go","name":"PtrAlias","kind":"decl","node_id":"type_alias:c9336784d0211d92b205b7194a5ce3a7","target_spec":null,"target_name":null,"exported_as":"PtrAlias","export_form":"public","scope_start":1,"scope_end":188,"storage":null,"line":102} +{"file_path":"torture.go","name":"Push","kind":"decl","node_id":"method:a6d269b87546a3383d51ca2de232a1de","target_spec":null,"target_name":null,"exported_as":"Push","export_form":"public","scope_start":1,"scope_end":188,"storage":null,"line":155} +{"file_path":"torture.go","name":"Render","kind":"decl","node_id":"method:24ccc96de44e1d4e1608658cfe083a33","target_spec":null,"target_name":null,"exported_as":"Render","export_form":"public","scope_start":1,"scope_end":188,"storage":null,"line":159} +{"file_path":"torture.go","name":"Render","kind":"local","node_id":"method:849d12c566dceb8c4bfcf1e81b828752","target_spec":null,"target_name":null,"exported_as":null,"export_form":null,"scope_start":113,"scope_end":115,"storage":null,"line":114} +{"file_path":"torture.go","name":"Repo","kind":"decl","node_id":"interface:3970ad34905c85bf731cae6e1386687f","target_spec":null,"target_name":null,"exported_as":"Repo","export_form":"public","scope_start":1,"scope_end":188,"storage":null,"line":83} +{"file_path":"torture.go","name":"Seconds","kind":"decl","node_id":"type_alias:5d4689c66e6a4956859f7b921c3610c8","target_spec":null,"target_name":null,"exported_as":"Seconds","export_form":"public","scope_start":1,"scope_end":188,"storage":null,"line":67} +{"file_path":"torture.go","name":"Self","kind":"local","node_id":"method:598927e1a898855d3029efb1ca0f4966","target_spec":null,"target_name":null,"exported_as":null,"export_form":null,"scope_start":83,"scope_end":87,"storage":null,"line":86} +{"file_path":"torture.go","name":"Server","kind":"decl","node_id":"struct:6b80d8f1dbee1c34e187c63b7e616a70","target_spec":null,"target_name":null,"exported_as":"Server","export_form":"public","scope_start":1,"scope_end":188,"storage":null,"line":35} +{"file_path":"torture.go","name":"Stack","kind":"decl","node_id":"struct:4c67fc2c851f10cf7803489ef577fc3c","target_spec":null,"target_name":null,"exported_as":"Stack","export_form":"public","scope_start":1,"scope_end":188,"storage":null,"line":28} +{"file_path":"torture.go","name":"TargetCb","kind":"decl","node_id":"function:a832b3ad2e6b57ff9463fbd6c86c5a97","target_spec":null,"target_name":null,"exported_as":"TargetCb","export_form":"public","scope_start":1,"scope_end":188,"storage":null,"line":163} +{"file_path":"torture.go","name":"Tree","kind":"decl","node_id":"type_alias:b826ea0f1f4d158a41ccfe0c21c225f3","target_spec":null,"target_name":null,"exported_as":"Tree","export_form":"public","scope_start":1,"scope_end":188,"storage":null,"line":138} +{"file_path":"torture.go","name":"Unmarshal","kind":"local","node_id":"method:d63eca909d73707a025ddf2fd591a13e","target_spec":null,"target_name":null,"exported_as":null,"export_form":null,"scope_start":72,"scope_end":79,"storage":null,"line":78} +{"file_path":"torture.go","name":"WatchChan","kind":"decl","node_id":"type_alias:a10c4f47aeab87402ced28d09f54ddfb","target_spec":null,"target_name":null,"exported_as":"WatchChan","export_form":"public","scope_start":1,"scope_end":188,"storage":null,"line":125} +{"file_path":"torture.go","name":"Widget","kind":"decl","node_id":"struct:33e3531d750b08f5b854203467928f28","target_spec":null,"target_name":null,"exported_as":"Widget","export_form":"public","scope_start":1,"scope_end":188,"storage":null,"line":18} +{"file_path":"torture.go","name":"WordAlias","kind":"decl","node_id":"type_alias:a9e7f1010d06f6bbc8039f4b63877b56","target_spec":null,"target_name":null,"exported_as":"WordAlias","export_form":"public","scope_start":1,"scope_end":188,"storage":null,"line":117} +{"file_path":"torture.go","name":"Wrapped","kind":"decl","node_id":"type_alias:771117de3df76a903822e0fab4467df8","target_spec":null,"target_name":null,"exported_as":"Wrapped","export_form":"public","scope_start":1,"scope_end":188,"storage":null,"line":130} +{"file_path":"torture.go","name":"a","kind":"param","node_id":null,"target_spec":null,"target_name":null,"exported_as":null,"export_form":null,"scope_start":142,"scope_end":144,"storage":null,"line":142} +{"file_path":"torture.go","name":"cfg","kind":"local","node_id":null,"target_spec":null,"target_name":null,"exported_as":null,"export_form":null,"scope_start":146,"scope_end":153,"storage":null,"line":150} +{"file_path":"torture.go","name":"ctx","kind":"param","node_id":null,"target_spec":null,"target_name":null,"exported_as":null,"export_form":null,"scope_start":84,"scope_end":84,"storage":null,"line":84} +{"file_path":"torture.go","name":"data","kind":"param","node_id":null,"target_spec":null,"target_name":null,"exported_as":null,"export_form":null,"scope_start":78,"scope_end":78,"storage":null,"line":78} +{"file_path":"torture.go","name":"fmt","kind":"import","node_id":null,"target_spec":"fmt","target_name":"*","exported_as":null,"export_form":null,"scope_start":1,"scope_end":188,"storage":null,"line":5} +{"file_path":"torture.go","name":"fn","kind":"param","node_id":null,"target_spec":null,"target_name":null,"exported_as":null,"export_form":null,"scope_start":85,"scope_end":85,"storage":null,"line":85} +{"file_path":"torture.go","name":"handlerTable","kind":"decl","node_id":"variable:6b7262d2883839c6f601126f4dd59e9b","target_spec":null,"target_name":null,"exported_as":null,"export_form":null,"scope_start":1,"scope_end":188,"storage":"package","line":13} +{"file_path":"torture.go","name":"id","kind":"param","node_id":null,"target_spec":null,"target_name":null,"exported_as":null,"export_form":null,"scope_start":84,"scope_end":84,"storage":null,"line":84} +{"file_path":"torture.go","name":"item","kind":"param","node_id":null,"target_spec":null,"target_name":null,"exported_as":null,"export_form":null,"scope_start":155,"scope_end":157,"storage":null,"line":155} +{"file_path":"torture.go","name":"mdBare","kind":"decl","node_id":"variable:d0140163eccfbe839cf7b486e7f09269","target_spec":null,"target_name":null,"exported_as":null,"export_form":null,"scope_start":1,"scope_end":188,"storage":"package","line":178} +{"file_path":"torture.go","name":"mdEscapes","kind":"decl","node_id":"variable:c460b12b198d9c2ffe3164cd43876109","target_spec":null,"target_name":null,"exported_as":null,"export_form":null,"scope_start":1,"scope_end":188,"storage":"package","line":180} +{"file_path":"torture.go","name":"mdGuide","kind":"decl","node_id":"variable:edb5fbbe020242a5060c5fd64110716d","target_spec":null,"target_name":null,"exported_as":null,"export_form":null,"scope_start":1,"scope_end":188,"storage":"package","line":177} +{"file_path":"torture.go","name":"mdLoad","kind":"decl","node_id":"function:8307a8a823f2c272e33236a2f73c9f60","target_spec":null,"target_name":null,"exported_as":null,"export_form":null,"scope_start":1,"scope_end":188,"storage":"package","line":185} +{"file_path":"torture.go","name":"mdQueried","kind":"decl","node_id":"variable:e6121ba1baf8c5f551e7d79391a5f970","target_spec":null,"target_name":null,"exported_as":null,"export_form":null,"scope_start":1,"scope_end":188,"storage":"package","line":182} +{"file_path":"torture.go","name":"mdRemote","kind":"decl","node_id":"variable:9ebd601a4fad63af418ac0bc8c0ec04c","target_spec":null,"target_name":null,"exported_as":null,"export_form":null,"scope_start":1,"scope_end":188,"storage":"package","line":181} +{"file_path":"torture.go","name":"mdRooted","kind":"decl","node_id":"variable:1408b0cc15b4db6aa165d25216f1f59a","target_spec":null,"target_name":null,"exported_as":null,"export_form":null,"scope_start":1,"scope_end":188,"storage":"package","line":179} +{"file_path":"torture.go","name":"mdTwoInOne","kind":"decl","node_id":"variable:adb6634d66354e5a2f46a0cd4ab58050","target_spec":null,"target_name":null,"exported_as":null,"export_form":null,"scope_start":1,"scope_end":188,"storage":"package","line":183} +{"file_path":"torture.go","name":"n","kind":"param","node_id":null,"target_spec":null,"target_name":null,"exported_as":null,"export_form":null,"scope_start":163,"scope_end":163,"storage":null,"line":163} +{"file_path":"torture.go","name":"pkga","kind":"import","node_id":null,"target_spec":"example.com/other/pkga","target_name":"*","exported_as":null,"export_form":null,"scope_start":1,"scope_end":188,"storage":null,"line":6} +{"file_path":"torture.go","name":"q","kind":"local","node_id":null,"target_spec":null,"target_name":null,"exported_as":null,"export_form":null,"scope_start":146,"scope_end":153,"storage":null,"line":148} +{"file_path":"torture.go","name":"reads","kind":"decl","node_id":"function:fd52d5daf195fabf0870d2a4c709d61f","target_spec":null,"target_name":null,"exported_as":null,"export_form":null,"scope_start":1,"scope_end":188,"storage":"package","line":170} +{"file_path":"torture.go","name":"s","kind":"param","node_id":null,"target_spec":null,"target_name":null,"exported_as":null,"export_form":null,"scope_start":155,"scope_end":157,"storage":null,"line":155} +{"file_path":"torture.go","name":"shadowed","kind":"decl","node_id":"function:55a555881f22d77e916122b15425f092","target_spec":null,"target_name":null,"exported_as":null,"export_form":null,"scope_start":1,"scope_end":188,"storage":"package","line":165} +{"file_path":"torture.go","name":"stateFn","kind":"decl","node_id":"type_alias:d1df73c8269ea5dd18f9aaaac0a8088d","target_spec":null,"target_name":null,"exported_as":null,"export_form":null,"scope_start":1,"scope_end":188,"storage":"package","line":140} +{"file_path":"torture.go","name":"useAlias","kind":"decl","node_id":"function:815f561efb2f5946fda7806c34dbd966","target_spec":null,"target_name":null,"exported_as":null,"export_form":null,"scope_start":1,"scope_end":188,"storage":"package","line":142} +{"file_path":"torture.go","name":"v","kind":"param","node_id":null,"target_spec":null,"target_name":null,"exported_as":null,"export_form":null,"scope_start":77,"scope_end":77,"storage":null,"line":77} +{"file_path":"torture.go","name":"w","kind":"local","node_id":null,"target_spec":null,"target_name":null,"exported_as":null,"export_form":null,"scope_start":146,"scope_end":153,"storage":null,"line":147} +{"file_path":"torture.go","name":"w","kind":"param","node_id":null,"target_spec":null,"target_name":null,"exported_as":null,"export_form":null,"scope_start":159,"scope_end":161,"storage":null,"line":159} {"file_path":"torture.hpp","name":"Calibrate","kind":"decl","node_id":"method:ca160b191e7fb257769f213a8450ab4c","target_spec":null,"target_name":null,"exported_as":"Calibrate","export_form":"public","scope_start":1,"scope_end":32,"storage":null,"line":29} {"file_path":"torture.hpp","name":"Meter","kind":"decl","node_id":"class:da855a76803320806ba08457a72b59fa","target_spec":null,"target_name":null,"exported_as":"Meter","export_form":"public","scope_start":1,"scope_end":32,"storage":null,"line":20} {"file_path":"torture.hpp","name":"Peek","kind":"local","node_id":"method:736a454a1f159019a862854710311b0c","target_spec":null,"target_name":null,"exported_as":null,"export_form":null,"scope_start":20,"scope_end":27,"storage":null,"line":24} @@ -6898,7 +6946,7 @@ {"path":"torture.c","language":"c","node_count":69} {"path":"torture.cpp","language":"cpp","node_count":54} {"path":"torture.dart","language":"dart","node_count":94} -{"path":"torture.go","language":"go","node_count":51} +{"path":"torture.go","language":"go","node_count":58} {"path":"torture.hpp","language":"cpp","node_count":5} {"path":"torture.js","language":"javascript","node_count":32} {"path":"torture.kt","language":"kotlin","node_count":117} diff --git a/__tests__/fixtures/golden/vue-sfc.dump b/__tests__/fixtures/golden/vue-sfc.dump index d655cf4376..ca6e53887d 100644 --- a/__tests__/fixtures/golden/vue-sfc.dump +++ b/__tests__/fixtures/golden/vue-sfc.dump @@ -76,9 +76,9 @@ {"source":"component:bb25dfa092c88625d329317b0410e2cf","target":"route:src/router/index.ts:5:/:vue","kind":"navigates","metadata":"{\"synthesizedBy\":\"vue-router-link\",\"href\":\"home\",\"navMethod\":\"link\",\"by\":\"name\",\"registeredAt\":\"src/views/Login.vue:2\"}","line":2,"col":null,"provenance":"heuristic"} {"source":"component:d243da7dd7c0285f73fbc46926de4830","target":"function:cbf5b3b6d9cf6f3f971b79716cb24ec1","kind":"calls","metadata":"{\"confidence\":0.9,\"resolvedBy\":\"exact-match\",\"refName\":\"cellClass\"}","line":2,"col":56,"provenance":null} {"source":"component:d243da7dd7c0285f73fbc46926de4830","target":"function:cbf5b3b6d9cf6f3f971b79716cb24ec1","kind":"contains","metadata":null,"line":null,"col":null,"provenance":null} -{"source":"constant:cc53d30032c6a64950637c56908b7d0b","target":"component:4adc8e1e4bb22917b580e3d56a1ea521","kind":"imports","metadata":"{\"framework\":\"vue\",\"confidence\":0.9,\"resolvedBy\":\"framework\",\"refName\":\"@/views/Home.vue\"}","line":5,"col":48,"provenance":null} -{"source":"constant:cc53d30032c6a64950637c56908b7d0b","target":"component:51ec8fb32fb2e5eb0334651e5437dbb3","kind":"imports","metadata":"{\"framework\":\"vue\",\"confidence\":0.9,\"resolvedBy\":\"framework\",\"refName\":\"@/views/Profile.vue\"}","line":7,"col":68,"provenance":null} -{"source":"constant:cc53d30032c6a64950637c56908b7d0b","target":"component:bb25dfa092c88625d329317b0410e2cf","kind":"imports","metadata":"{\"framework\":\"vue\",\"confidence\":0.9,\"resolvedBy\":\"framework\",\"refName\":\"@/views/Login.vue\"}","line":6,"col":54,"provenance":null} +{"source":"constant:cc53d30032c6a64950637c56908b7d0b","target":"file:src/views/Home.vue","kind":"imports","metadata":"{\"confidence\":0.9,\"resolvedBy\":\"import\",\"refName\":\"@/views/Home.vue\"}","line":5,"col":48,"provenance":null} +{"source":"constant:cc53d30032c6a64950637c56908b7d0b","target":"file:src/views/Login.vue","kind":"imports","metadata":"{\"confidence\":0.9,\"resolvedBy\":\"import\",\"refName\":\"@/views/Login.vue\"}","line":6,"col":54,"provenance":null} +{"source":"constant:cc53d30032c6a64950637c56908b7d0b","target":"file:src/views/Profile.vue","kind":"imports","metadata":"{\"confidence\":0.9,\"resolvedBy\":\"import\",\"refName\":\"@/views/Profile.vue\"}","line":7,"col":68,"provenance":null} {"source":"file:src/components/PlayerTable.vue","target":"component:d243da7dd7c0285f73fbc46926de4830","kind":"contains","metadata":null,"line":null,"col":null,"provenance":null} {"source":"file:src/components/TheHeader.vue","target":"component:a2b972002bba2cab19e7c5b8376f5608","kind":"contains","metadata":null,"line":null,"col":null,"provenance":null} {"source":"file:src/router/index.ts","target":"constant:cc53d30032c6a64950637c56908b7d0b","kind":"contains","metadata":null,"line":null,"col":null,"provenance":null} @@ -90,15 +90,15 @@ {"source":"file:src/stores/session.ts","target":"import:4c3d03fe5b468700553c025bde17c5da","kind":"contains","metadata":null,"line":null,"col":null,"provenance":null} {"source":"file:src/views/Home.vue","target":"component:4adc8e1e4bb22917b580e3d56a1ea521","kind":"contains","metadata":null,"line":null,"col":null,"provenance":null} {"source":"file:src/views/Home.vue","target":"component:a2b972002bba2cab19e7c5b8376f5608","kind":"imports","metadata":"{\"confidence\":0.9,\"resolvedBy\":\"import\",\"refName\":\"TheHeader\"}","line":7,"col":7,"provenance":null} -{"source":"file:src/views/Home.vue","target":"component:a2b972002bba2cab19e7c5b8376f5608","kind":"imports","metadata":"{\"framework\":\"vue\",\"confidence\":0.9,\"resolvedBy\":\"framework\",\"refName\":\"@/components/TheHeader.vue\"}","line":7,"col":0,"provenance":null} {"source":"file:src/views/Home.vue","target":"component:d243da7dd7c0285f73fbc46926de4830","kind":"imports","metadata":"{\"confidence\":0.9,\"resolvedBy\":\"import\",\"refName\":\"PlayerTable\"}","line":8,"col":7,"provenance":null} -{"source":"file:src/views/Home.vue","target":"component:d243da7dd7c0285f73fbc46926de4830","kind":"imports","metadata":"{\"framework\":\"vue\",\"confidence\":0.9,\"resolvedBy\":\"framework\",\"refName\":\"@/components/PlayerTable.vue\"}","line":8,"col":0,"provenance":null} {"source":"file:src/views/Home.vue","target":"constant:452cdd44fc910418f24644cca18f6ebf","kind":"imports","metadata":"{\"confidence\":0.9,\"resolvedBy\":\"import\",\"refName\":\"useSessionStore\"}","line":9,"col":9,"provenance":null} -{"source":"file:src/views/Home.vue","target":"file:src/stores/session.ts","kind":"imports","metadata":"{\"framework\":\"vue\",\"confidence\":0.9,\"resolvedBy\":\"framework\",\"refName\":\"@/stores/session\"}","line":9,"col":0,"provenance":null} +{"source":"file:src/views/Home.vue","target":"file:src/components/PlayerTable.vue","kind":"imports","metadata":"{\"confidence\":0.9,\"resolvedBy\":\"import\",\"refName\":\"@/components/PlayerTable.vue\"}","line":8,"col":0,"provenance":null} +{"source":"file:src/views/Home.vue","target":"file:src/components/TheHeader.vue","kind":"imports","metadata":"{\"confidence\":0.9,\"resolvedBy\":\"import\",\"refName\":\"@/components/TheHeader.vue\"}","line":7,"col":0,"provenance":null} +{"source":"file:src/views/Home.vue","target":"file:src/stores/session.ts","kind":"imports","metadata":"{\"confidence\":0.9,\"resolvedBy\":\"import\",\"refName\":\"@/stores/session\"}","line":9,"col":0,"provenance":null} {"source":"file:src/views/Home.vue","target":"file:src/views/Home.vue","kind":"imports","metadata":"{\"framework\":\"vue\",\"confidence\":1,\"resolvedBy\":\"framework\",\"refName\":\"useRouter\"}","line":6,"col":9,"provenance":null} {"source":"file:src/views/Login.vue","target":"component:bb25dfa092c88625d329317b0410e2cf","kind":"contains","metadata":null,"line":null,"col":null,"provenance":null} {"source":"file:src/views/Login.vue","target":"constant:452cdd44fc910418f24644cca18f6ebf","kind":"imports","metadata":"{\"confidence\":0.9,\"resolvedBy\":\"import\",\"refName\":\"useSessionStore\"}","line":7,"col":9,"provenance":null} -{"source":"file:src/views/Login.vue","target":"file:src/stores/session.ts","kind":"imports","metadata":"{\"framework\":\"vue\",\"confidence\":0.9,\"resolvedBy\":\"framework\",\"refName\":\"@/stores/session\"}","line":7,"col":0,"provenance":null} +{"source":"file:src/views/Login.vue","target":"file:src/stores/session.ts","kind":"imports","metadata":"{\"confidence\":0.9,\"resolvedBy\":\"import\",\"refName\":\"@/stores/session\"}","line":7,"col":0,"provenance":null} {"source":"file:src/views/Login.vue","target":"file:src/views/Login.vue","kind":"imports","metadata":"{\"framework\":\"vue\",\"confidence\":1,\"resolvedBy\":\"framework\",\"refName\":\"useRouter\"}","line":6,"col":9,"provenance":null} {"source":"file:src/views/Profile.vue","target":"component:51ec8fb32fb2e5eb0334651e5437dbb3","kind":"contains","metadata":null,"line":null,"col":null,"provenance":null} {"source":"function:8d98565edda11804927409e8e272013e","target":"function:6be3944381225a6a828e91729caf5788","kind":"calls","metadata":"{\"synthesizedBy\":\"pinia-store\",\"via\":\"login\",\"registeredAt\":\"src/views/Login.vue:12\"}","line":12,"col":null,"provenance":"heuristic"} diff --git a/__tests__/fixtures/kernel-parity/torture.go b/__tests__/fixtures/kernel-parity/torture.go index e364c0c44a..22277ff139 100644 --- a/__tests__/fixtures/kernel-parity/torture.go +++ b/__tests__/fixtures/kernel-parity/torture.go @@ -29,6 +29,39 @@ type Stack[T any] struct { items []T } +// A struct references the types its fields are declared with, but the types +// it embeds (supertypes), its own type parameters, predeclared types and its +// own name written bare. +type Server struct { + handlers HandlersChain + byKey map[Dur][]*Widget `json:"by_key"` + events <-chan pkga.Item + grid [MAX_ITEMS]Widget + cb func(ctx pkga.Context, w *Widget) (*Stack[int], error) + a, b Widget + nested struct { + w Widget + *Base + } + codec interface { + Encode(pkga.Item) ([]byte, error) + } + *pkga.Lister[*Widget, pkga.Item] + next *Server + n int +} + +type Pool[T any] struct { + items []T + next *Pool[T] + Stack[T] + extra Widget +} + +type AnonFields = struct { + w Widget +} + // Units of time: the group's comment, no member's doc. type ( Seconds int @@ -45,6 +78,14 @@ type Core interface { Unmarshal(data []byte) error } +// An interface method references the types its signature names, but the +// interface's own type parameters and the predeclared types. +type Repo[T any] interface { + Find(ctx pkga.Context, id Dur) (*Widget, error) + Each(fn func(T, *Stack[int]) bool) []pkga.Item + Self() Repo[T] +} + type Number interface { ~int | ~float64 } diff --git a/__tests__/function-ref-package-imports.test.ts b/__tests__/function-ref-package-imports.test.ts new file mode 100644 index 0000000000..f651023ffe --- /dev/null +++ b/__tests__/function-ref-package-imports.test.ts @@ -0,0 +1,181 @@ +/** + * A function passed as a value (`styled(Link)`, `createContext({ onClose: + * noop })`, `register(debounce)`) whose name the file imports from a package + * is that package's function. The function-as-value matcher still bound it to + * the one project function of that name whenever there was exactly one: + * outline's `styled(Link)`, with `Link` from react-router-dom, landed on an + * email template's `Footer.tsx:Link`, and cord-field's lodash `noop` on a + * test file's local `const noop = () => {}`. + * + * The import says which `Link` it is. A name the file imports from a package + * its package.json declares (or a Node built-in) names nothing in the + * repository; a project import still resolves through its import, a + * specifier nothing declares may be an alias the resolver doesn't know, and a + * declaration in the same file still wins. + */ +import { describe, it, expect, afterAll } from 'vitest'; +import * as fs from 'fs'; +import * as os from 'os'; +import * as path from 'path'; +import { CodeGraph } from '../src'; + +const roots: string[] = []; +afterAll(() => { + for (const r of roots.splice(0)) fs.rmSync(r, { recursive: true, force: true }); +}); + +async function indexProject(files: Record): Promise { + const root = fs.mkdtempSync(path.join(os.tmpdir(), 'cg-fnref-package-')); + roots.push(root); + for (const [rel, content] of Object.entries(files)) { + fs.mkdirSync(path.dirname(path.join(root, rel)), { recursive: true }); + fs.writeFileSync(path.join(root, rel), content); + } + return CodeGraph.init(root, { index: true }); +} + +/** ` -> :` for each function-as-value edge leaving `file`. */ +function fnRefsFrom(cg: CodeGraph, file: string): string[] { + const ids = cg.getNodesInFile(file).map((n) => n.id); + return [...new Set(cg + .getOutgoingEdgesFrom(ids) + .filter((e) => e.metadata?.fnRef === true) + .map((e) => { + const target = cg.getNode(e.target); + return `${String(e.metadata?.refName)} -> ${target?.filePath}:${target?.qualifiedName}`; + }))] + .sort(); +} + +describe('a function value the file imports from a package', () => { + it('never lands on a project function of the same name', async () => { + const cg = await indexProject({ + 'package.json': JSON.stringify({ + name: 'wiki', + dependencies: { react: '^18.2.0', 'react-router-dom': '^6.22.0', 'styled-components': '^6.1.0', lodash: '^4.17.21' }, + }), + 'tsconfig.json': JSON.stringify({ compilerOptions: { baseUrl: '.', jsx: 'react-jsx', paths: { '~/*': ['./app/*'] } } }), + // The project's only `Link`, `noop`, `debounce` and `format` functions. + 'server/emails/Footer.tsx': `export function Link(props: { href: string; children?: string }) { + return {props.children}; +} +`, + 'app/utils/noop.ts': `export function noop(): void {} +`, + 'app/utils/debounce.ts': `export function debounce(fn: () => void): () => void { return fn; } +`, + 'app/utils/format.ts': `export function format(value: number): string { return String(value); } +`, + // outline's Breadcrumb: react-router-dom's `Link`, wrapped by styled-components. + 'app/components/Breadcrumb.tsx': `import { Link } from 'react-router-dom'; +import styled from 'styled-components'; + +const Item = styled(Link)\` + display: flex; +\`; + +export function Crumb() { + return home; +} +`, + // A named import, a default import of a package path, and a Node built-in. + 'app/hooks/useDeferred.ts': `import { noop } from 'lodash'; +import debounce from 'lodash/debounce'; +import { format } from 'node:util'; + +export const defaults = { onClose: noop }; + +export function useDeferred(register: (cb: unknown) => void): void { + register(debounce); + register(format); +} +`, + }); + try { + expect({ + breadcrumb: fnRefsFrom(cg, 'app/components/Breadcrumb.tsx'), + deferred: fnRefsFrom(cg, 'app/hooks/useDeferred.ts'), + }).toEqual({ breadcrumb: [], deferred: [] }); + } finally { + cg.close(); + } + }, 60_000); + + it('never lands on one under a catch-all path alias either', async () => { + const cg = await indexProject({ + 'package.json': JSON.stringify({ name: 'cord', dependencies: { react: '^18.2.0', lodash: '^4.17.21' } }), + // cord-field's shape: `~/…` for the project's own files, `*` for local + // type declarations of untyped packages. + 'tsconfig.json': JSON.stringify({ + compilerOptions: { baseUrl: 'src', jsx: 'react-jsx', paths: { '~/*': ['./*'], '*': ['./typings/*'] } }, + }), + 'src/scenes/Users/UserForm.test.tsx': `const noop = () => { + // a stub +}; + +export function renderForm(onSubmit: () => void) { + return onSubmit; +} + +renderForm(noop); +`, + 'src/components/form/AllowClose.ts': `import { noop } from 'lodash'; +import { createContext } from 'react'; + +export const AllowFormCloseContext = createContext({ allow: noop }); +`, + }); + try { + expect(fnRefsFrom(cg, 'src/components/form/AllowClose.ts')).toEqual([]); + // The test's own `noop` is still what the test passes. + expect(fnRefsFrom(cg, 'src/scenes/Users/UserForm.test.tsx')).toEqual([ + 'noop -> src/scenes/Users/UserForm.test.tsx:noop', + ]); + } finally { + cg.close(); + } + }, 60_000); + + it('keeps a project import, an undeclared specifier and a same-file declaration resolving', async () => { + const cg = await indexProject({ + 'package.json': JSON.stringify({ name: 'kit', dependencies: { react: '^18.2.0', lodash: '^4.17.21' } }), + 'tsconfig.json': JSON.stringify({ compilerOptions: { baseUrl: '.', jsx: 'react-jsx' } }), + 'src/emails/Footer.tsx': `export function Link(props: { href: string }) { + return ; +} +`, + 'src/lib/handlers.ts': `export function onSave(): void {} +`, + // A project import resolves through the import. + 'src/menus/Menu.tsx': `import { Link } from '../emails/Footer'; + +export function menuItems(wrap: (c: unknown) => unknown) { + return wrap(Link); +} +`, + // SvelteKit's \`$lib\`: no package.json declares it, so it may be the + // project's own folder under an alias this resolver doesn't read. + 'src/routes/page.ts': `import { onSave } from '$lib/handlers'; + +export function bind(register: (cb: () => void) => void): void { + register(onSave); +} +`, + // A declaration in the file shadows the package's \`noop\` where it is in scope. + 'src/hooks/stub.ts': `import { noop } from 'lodash'; + +export function setup(register: (cb: () => void) => void): void { + function noop(): void {} + register(noop); +} +`, + }); + try { + expect(fnRefsFrom(cg, 'src/menus/Menu.tsx')).toEqual(['Link -> src/emails/Footer.tsx:Link']); + expect(fnRefsFrom(cg, 'src/routes/page.ts')).toEqual(['onSave -> src/lib/handlers.ts:onSave']); + expect(fnRefsFrom(cg, 'src/hooks/stub.ts')).toEqual(['noop -> src/hooks/stub.ts:setup::noop']); + } finally { + cg.close(); + } + }, 60_000); +}); diff --git a/__tests__/go-defined-type-refs.test.ts b/__tests__/go-defined-type-refs.test.ts index 3541f2106d..d8521c86b9 100644 --- a/__tests__/go-defined-type-refs.test.ts +++ b/__tests__/go-defined-type-refs.test.ts @@ -169,8 +169,10 @@ describe('a Go defined type references the types it is defined from', () => { // A qualified name keeps its package in the source (`render.Render`, // `context.Context`). Not referenced: the predeclared types (string, // int, uint8, error, comparable), the type parameters T, K and V, and a - // type's own name written bare (stateFn, Tree). + // type's own name written bare (stateFn, Tree). The struct Context + // references its field's type. expect(typeRefs(result)).toEqual([ + 'Context HandlersChain', 'Generic List', 'Grid Cell', 'HandlerFunc Context', diff --git a/__tests__/go-import-alias-precedence.test.ts b/__tests__/go-import-alias-precedence.test.ts new file mode 100644 index 0000000000..c6a700ba5a --- /dev/null +++ b/__tests__/go-import-alias-precedence.test.ts @@ -0,0 +1,118 @@ +/** + * Go binds a name to one import per file. etcd's benchmark tool imports + * `"github.com/cheggaaa/pb/v3"` (package `pb`) beside + * `v3 "go.etcd.io/etcd/client/v3"`, so `v3.Op` is clientv3's `Op`. The index + * also listed the unaliased import under its last path element, `v3`, and the + * import met first — the progress-bar library, outside the project — took + * every `v3.` qualifier, so `v3.Op`, `v3.Client` and `v3.OpGet(…)` linked to + * nothing. + * + * An unaliased import is no longer listed under a name another import is + * explicitly given; it keeps the name goimports assumes for it (`pb`). + */ +import { describe, it, expect, beforeAll, afterAll } from 'vitest'; +import * as fs from 'fs'; +import * as os from 'os'; +import * as path from 'path'; +import CodeGraph from '../src/index'; + +const MODULE: Record = { + 'go.mod': 'module go.etcd.io/etcd\n\ngo 1.24\n', + 'client/v3/op.go': [ + 'package clientv3', + '', + 'type Op struct{}', + '', + 'type Client struct{}', + '', + 'func (c *Client) Do(op Op) error { return nil }', + '', + 'func OpGet(key string) Op { return Op{} }', + '', + ].join('\n'), + // The unaliased import first, as etcd writes it. + 'tools/benchmark/cmd/txn_mixed.go': [ + 'package cmd', + '', + 'import (', + '\t"github.com/cheggaaa/pb/v3"', + '', + '\tv3 "go.etcd.io/etcd/client/v3"', + ')', + '', + 'type request struct {', + '\top v3.Op', + '}', + '', + 'func run(c *v3.Client, bar *pb.ProgressBar) error {', + '\treturn c.Do(v3.OpGet("k"))', + '}', + '', + ].join('\n'), + // The aliased import first. + 'tools/benchmark/cmd/put.go': [ + 'package cmd', + '', + 'import (', + '\tv3 "go.etcd.io/etcd/client/v3"', + '\t"github.com/cheggaaa/pb/v3"', + ')', + '', + 'func put(bar *pb.ProgressBar) v3.Op {', + '\treturn v3.OpGet("k")', + '}', + '', + ].join('\n'), +}; + +describe.each([ + ['default', 'LF'], + ['wasm', 'LF'], + ['default', 'CRLF'], + ['wasm', 'CRLF'], +])('a Go import named explicitly owns its name (%s, %s)', (backend, eol) => { + let root = ''; + let cg: CodeGraph | undefined; + let kernel: string | undefined; + + beforeAll(async () => { + kernel = process.env.CODEGRAPH_KERNEL; + if (backend === 'wasm') process.env.CODEGRAPH_KERNEL = '0'; + else delete process.env.CODEGRAPH_KERNEL; + root = fs.mkdtempSync(path.join(os.tmpdir(), 'cg-go-alias-')); + for (const [rel, content] of Object.entries(MODULE)) { + fs.mkdirSync(path.dirname(path.join(root, rel)), { recursive: true }); + fs.writeFileSync(path.join(root, rel), eol === 'CRLF' ? content.replace(/\n/g, '\r\n') : content); + } + cg = await CodeGraph.init(root, { index: true }); + }, 60_000); + + afterAll(() => { + cg?.destroy(); + if (root) fs.rmSync(root, { recursive: true, force: true }); + if (kernel === undefined) delete process.env.CODEGRAPH_KERNEL; + else process.env.CODEGRAPH_KERNEL = kernel; + }); + + const linksFrom = (file: string, name: string) => { + const node = cg!.getNodesInFile(file).find((n) => n.name === name && n.kind !== 'import')!; + expect(node, `${name} in ${file}`).toBeTruthy(); + return cg!.getOutgoingEdgesFrom([node.id]) + .filter((e) => e.kind !== 'contains') + .map((e) => `${e.kind} ${cg!.getNode(e.target)!.filePath}:${cg!.getNode(e.target)!.qualifiedName}`) + .sort(); + }; + + it('`v3.` is the aliased import, whichever import comes first', () => { + expect(linksFrom('tools/benchmark/cmd/txn_mixed.go', 'request')).toEqual(['references client/v3/op.go:Op']); + expect(linksFrom('tools/benchmark/cmd/txn_mixed.go', 'run')).toEqual([ + 'calls client/v3/op.go:Client::Do', + 'calls client/v3/op.go:OpGet', + 'references client/v3/op.go:Client', + ]); + expect(linksFrom('tools/benchmark/cmd/put.go', 'put')).toEqual([ + 'calls client/v3/op.go:OpGet', + 'references client/v3/op.go:Op', + ]); + }); +}); diff --git a/__tests__/go-interface-method-types.test.ts b/__tests__/go-interface-method-types.test.ts new file mode 100644 index 0000000000..eae868a058 --- /dev/null +++ b/__tests__/go-interface-method-types.test.ts @@ -0,0 +1,297 @@ +/** + * A Go interface's methods are `method` nodes, and their signatures named no + * types: etcd's `KV.Put(ctx context.Context, key, val string, opts + * ...OpOption) (*PutResponse, error)` had no edge to `OpOption` or + * `PutResponse`. A call through the interface reaches that method, so impact + * on `PutResponse` missed the interface method and every caller that goes + * through it — the usual way Go code calls a dependency. + * + * An interface method now references each type its parameters and results + * name, as a function does, on the name. Not references: Go's predeclared + * types, and the interface's own type parameters written bare (`T` in + * `type Store[T any] interface { Get(string) (T, error) }`). The interface's + * own name is a type its method names (`Children() []Node`). + */ +import { describe, it, expect, beforeAll, beforeEach, afterEach, afterAll } from 'vitest'; +import * as fs from 'fs'; +import * as os from 'os'; +import * as path from 'path'; +import CodeGraph from '../src/index'; +import { extractFromSource } from '../src/extraction'; +import { initGrammars, loadGrammarsForLanguages } from '../src/extraction/grammars'; +import { tryKernelExtract, resetKernelForTests } from '../src/extraction/kernel'; +import type { ExtractionResult } from '../src/types'; + +const KERNEL_PATH = path.join( + __dirname, + '..', + 'codegraph-kernel', + 'prebuilds', + `${process.platform}-${process.arch}`, + 'codegraph-kernel.node' +); +const kernelAvailable = fs.existsSync(KERNEL_PATH) || process.env.CODEGRAPH_KERNEL_EXPECT === '1'; + +/** Every shape an interface method's signature can take. */ +const IFACE_SOURCE = `package clientv3 + +import ( + "context" + + pb "go.etcd.io/etcd/api/v3/etcdserverpb" +) + +type KV interface { + // Put puts a key-value pair into etcd. + Put(ctx context.Context, key, val string, opts ...OpOption) (*PutResponse, error) + Get(ctx context.Context, key string, opts ...OpOption) (*GetResponse, error) + Do(ctx context.Context, op Op) (OpResponse, error) + Txn(ctx context.Context) Txn + Close() error + Header() *pb.ResponseHeader + Watch(fn func(Event) bool, ch chan<- []Event, filters map[string]Filter) (<-chan WatchResponse, int64) +} + +type Store[T any, K comparable] interface { + Get(key K) (T, bool) + Put(key K, value T) Store[T, K] + Fetch(item Item[T]) any +} + +type Node interface { + Children() []Node + Name() string +} + +type Embedding interface { + KV + Lease +} +`; + +const ENV_KEYS = ['CODEGRAPH_KERNEL', 'CODEGRAPH_KERNEL_LANGS'] as const; + +/** ` ` for every `references` ref out of a method, sorted. */ +function methodRefs(result: ExtractionResult): string[] { + const byId = new Map(result.nodes.map((n) => [n.id, n])); + return result.unresolvedReferences + .filter((r) => r.referenceKind === 'references' && byId.get(r.fromNodeId)?.kind === 'method') + .map((r) => `${byId.get(r.fromNodeId)!.qualifiedName} ${r.referenceName}`) + .sort(); +} + +describe('a Go interface method references the types its signature names', () => { + let savedEnv: Record = {}; + + beforeAll(async () => { + await initGrammars(); + await loadGrammarsForLanguages(['go']); + }); + + beforeEach(() => { + savedEnv = Object.fromEntries(ENV_KEYS.map((k) => [k, process.env[k]])); + resetKernelForTests(); + }); + + afterEach(() => { + for (const k of ENV_KEYS) { + if (savedEnv[k] === undefined) delete process.env[k]; + else process.env[k] = savedEnv[k]; + } + resetKernelForTests(); + }); + + function extract(backend: 'kernel' | 'wasm', file: string, source: string): ExtractionResult { + if (backend === 'wasm') { + process.env.CODEGRAPH_KERNEL = '0'; + return extractFromSource(file, source, 'go'); + } + delete process.env.CODEGRAPH_KERNEL; + process.env.CODEGRAPH_KERNEL_LANGS = 'all'; + const result = tryKernelExtract(file, source, 'go'); + expect(result, `kernel extraction of ${file}`).not.toBeNull(); + return result!; + } + + const backends = kernelAvailable ? (['kernel', 'wasm'] as const) : (['wasm'] as const); + + for (const crlf of [false, true]) { + const eol = (s: string) => (crlf ? s.replace(/\n/g, '\r\n') : s); + const label = crlf ? ' (CRLF)' : ''; + + it.each(backends)(`each method references the types of its parameters and results: %s${label}`, (backend) => { + const source = eol(IFACE_SOURCE); + const result = extract(backend, 'kv.go', source); + // Not references: string, error, bool, int64, any; Store's own type + // parameters T and K; the embedded KV and Lease, which are its supertypes. + expect(methodRefs(result)).toEqual([ + 'KV::Do Context', + 'KV::Do Op', + 'KV::Do OpResponse', + 'KV::Get Context', + 'KV::Get GetResponse', + 'KV::Get OpOption', + 'KV::Header ResponseHeader', + 'KV::Put Context', + 'KV::Put OpOption', + 'KV::Put PutResponse', + 'KV::Txn Context', + 'KV::Txn Txn', + 'KV::Watch Event', + 'KV::Watch Event', + 'KV::Watch Filter', + 'KV::Watch WatchResponse', + 'Node::Children Node', + 'Store::Fetch Item', + 'Store::Put Store', + ]); + // Each sits on its name, where resolution reads a package qualifier back. + const lines = source.split(/\r?\n/); + const byId = new Map(result.nodes.map((n) => [n.id, n])); + for (const r of result.unresolvedReferences.filter((u) => u.referenceKind === 'references' && byId.get(u.fromNodeId)?.kind === 'method')) { + expect(lines[r.line - 1]!.startsWith(r.referenceName, r.column), `${r.referenceName} at ${r.line}:${r.column}`).toBe(true); + } + }); + + it.each(backends)(`the methods are still the interface's, and embeddings still its supertypes: %s${label}`, (backend) => { + const result = extract(backend, 'kv.go', eol(IFACE_SOURCE)); + expect(result.nodes.filter((n) => n.kind === 'method').map((n) => n.qualifiedName)).toEqual([ + 'KV::Put', 'KV::Get', 'KV::Do', 'KV::Txn', 'KV::Close', 'KV::Header', 'KV::Watch', + 'Store::Get', 'Store::Put', 'Store::Fetch', + 'Node::Children', 'Node::Name', + ]); + const embedding = result.nodes.find((n) => n.name === 'Embedding')!; + expect(result.unresolvedReferences.filter((r) => r.fromNodeId === embedding.id) + .map((r) => `${r.referenceKind} ${r.referenceName}`)).toEqual(['extends KV', 'extends Lease']); + }); + } +}); + +/** etcd's shape, with namesakes in a package that sorts first. */ +const MODULE: Record = { + 'go.mod': 'module go.etcd.io/etcd\n\ngo 1.24\n', + 'alpha/names.go': [ + 'package alpha', + '', + 'type OpOption struct{}', + '', + 'type PutResponse struct{}', + '', + 'type T struct{}', + '', + ].join('\n'), + 'api/v3/etcdserverpb/rpc.pb.go': [ + 'package etcdserverpb', + '', + 'type ResponseHeader struct{}', + '', + ].join('\n'), + 'client/v3/kv.go': [ + 'package clientv3', + '', + 'import (', + '\t"context"', + '', + '\tpb "go.etcd.io/etcd/api/v3/etcdserverpb"', + ')', + '', + 'type PutResponse struct {', + '\tHeader *pb.ResponseHeader', + '}', + '', + 'type Op struct{}', + '', + 'type OpOption func(*Op)', + '', + 'type KV interface {', + '\tPut(ctx context.Context, key, val string, opts ...OpOption) (*PutResponse, error)', + '}', + '', + 'type T struct{}', + '', + 'type Getter[T any] interface {', + '\tGet(key string) (T, error)', + '}', + '', + ].join('\n'), + 'server/store.go': [ + 'package server', + '', + 'import (', + '\t"context"', + '', + '\tclientv3 "go.etcd.io/etcd/client/v3"', + ')', + '', + 'func save(ctx context.Context, kv clientv3.KV) {', + '\tkv.Put(ctx, "k", "v")', + '}', + '', + ].join('\n'), +}; + +describe.each([ + ['default', 'LF'], + ['wasm', 'LF'], + ['default', 'CRLF'], + ['wasm', 'CRLF'], +])('an indexed Go module links its interface methods’ types (%s, %s)', (backend, eol) => { + let root = ''; + let cg: CodeGraph | undefined; + let kernel: string | undefined; + + beforeAll(async () => { + kernel = process.env.CODEGRAPH_KERNEL; + if (backend === 'wasm') process.env.CODEGRAPH_KERNEL = '0'; + else delete process.env.CODEGRAPH_KERNEL; + root = fs.mkdtempSync(path.join(os.tmpdir(), 'cg-go-iface-')); + for (const [rel, content] of Object.entries(MODULE)) { + fs.mkdirSync(path.dirname(path.join(root, rel)), { recursive: true }); + fs.writeFileSync(path.join(root, rel), eol === 'CRLF' ? content.replace(/\n/g, '\r\n') : content); + } + cg = await CodeGraph.init(root, { index: true }); + }, 60_000); + + afterAll(() => { + cg?.destroy(); + if (root) fs.rmSync(root, { recursive: true, force: true }); + if (kernel === undefined) delete process.env.CODEGRAPH_KERNEL; + else process.env.CODEGRAPH_KERNEL = kernel; + }); + + const nodeNamed = (file: string, qualifiedName: string) => { + const nodes = cg!.getNodesInFile(file).filter((n) => n.qualifiedName === qualifiedName && n.kind !== 'import'); + expect(nodes, `${qualifiedName} in ${file}`).toHaveLength(1); + return nodes[0]!; + }; + + const linksFrom = (file: string, qualifiedName: string) => + cg!.getOutgoingEdgesFrom([nodeNamed(file, qualifiedName).id]) + .filter((e) => e.kind !== 'contains') + .map((e) => `${e.kind} ${cg!.getNode(e.target)!.filePath}:${cg!.getNode(e.target)!.name}`) + .sort(); + + const impactOf = (file: string, qualifiedName: string) => + [...cg!.getImpactRadius(nodeNamed(file, qualifiedName).id, 3).nodes.values()].map((n) => `${n.filePath}:${n.qualifiedName}`).sort(); + + it('an interface method references its own package’s types, and nothing for an outside package', () => { + // `context.Context` is outside the project; alpha's namesakes sort first. + expect(linksFrom('client/v3/kv.go', 'KV::Put')).toEqual([ + 'references client/v3/kv.go:OpOption', + 'references client/v3/kv.go:PutResponse', + ]); + }); + + it('a generic interface’s own type parameter is no type its method references', () => { + expect(linksFrom('client/v3/kv.go', 'Getter::Get')).toEqual([]); + expect(cg!.getUnresolvedReferencesFrom(nodeNamed('client/v3/kv.go', 'Getter::Get').id)).toEqual([]); + }); + + it('impact on a type reaches the interface methods that name it, and the callers that go through them', () => { + expect(impactOf('client/v3/kv.go', 'OpOption')).toEqual([ + 'client/v3/kv.go:KV::Put', + 'client/v3/kv.go:OpOption', + 'server/store.go:save', + ]); + }); +}); diff --git a/__tests__/go-package-value-receivers.test.ts b/__tests__/go-package-value-receivers.test.ts new file mode 100644 index 0000000000..48efd0f430 --- /dev/null +++ b/__tests__/go-package-value-receivers.test.ts @@ -0,0 +1,253 @@ +/** + * Go calls through a variable or constant a package declares at the top + * level — `lg.Panic(…)` after `var lg *zap.Logger`, `RoleEndpoint.String()` + * after `RoleEndpoint Role = "endpoints"` — read by that declaration, in the + * file or another of the package, as a local's is: the method of the project + * type it is declared as, or nothing for a type or value from outside the + * project. Before, nothing read such a declaration, and the call was guessed + * by its method's name: etcd's `lg.Panic(…)` reached a project logger's + * `Panic`, prometheus's `RoleEndpoint.String()` another package's `Role`. + */ +import { describe, it, expect, beforeAll, afterAll } from 'vitest'; +import * as fs from 'fs'; +import * as os from 'os'; +import * as path from 'path'; +import { CodeGraph } from '../src'; + +let root = ''; +let cg: CodeGraph; + +beforeAll(async () => { + root = fs.mkdtempSync(path.join(os.tmpdir(), 'cg-go-pkg-values-')); + const files: Record = { + 'go.mod': 'module example.com/app\n\ngo 1.22\n', + 'logx/logger.go': `package logx + +type Logger struct{} + +func New() *Logger { return &Logger{} } + +func (l *Logger) Panic(msg string) {} + +func (l *Logger) Info(msg string) {} +`, + 'tools/dump.go': `package tools + +import "go.uber.org/zap" + +var lg *zap.Logger + +func dump() { + lg.Panic("boom") +} +`, + 'tools/other.go': `package tools + +func other() { + lg.Info("other file") +} +`, + 'tools/shadow.go': `package tools + +import "example.com/app/logx" + +func shadow() { + lg := logx.New() + lg.Panic("local") +} +`, + 'discovery/kubernetes/kubernetes.go': `package kubernetes + +type Role string + +func (r Role) String() string { return string(r) } + +const ( + RoleNode Role = "node" + RolePod Role = "pod" +) +`, + 'discovery/kubernetes/metrics.go': `package kubernetes + +func nodeRole() string { + return RoleNode.String() +} +`, + 'discovery/kubernetes/kind.go': `package kubernetes + +type Kind int + +const ( + KindA Kind = iota + // KindB repeats KindA's type. + KindB + KindC +) + +func (k Kind) Label() string { return "" } + +func kindLabel() string { + return KindB.Label() +} +`, + 'discovery/kubernetes/roles.go': `package kubernetes + +var podRole = Role("pod") + +func podRoleName() string { + return podRole.String() +} +`, + 'discovery/aws/aws.go': `package aws + +type Role string + +func (r Role) String() string { return string(r) } +`, + 'tags/tag.go': `package tags + +type Tag struct{} + +func (t Tag) Label() string { return "" } +`, + 'registry/registry.go': `package registry + +type Registry struct{} + +func (r *Registry) Register(name string) {} + +var defaultRegistry = &Registry{} + +func register() { + defaultRegistry.Register("x") +} +`, + 'plugins/manager.go': `package plugins + +type Manager struct{} + +func (m *Manager) Register(name string) {} +`, + 'buffers/buffers.go': `package buffers + +import ( + "bytes" + "io" +) + +var buf = bytes.NewBuffer(nil) + +func flush(w io.Writer) { + buf.WriteTo(w) +} +`, + 'sinks/sink.go': `package sinks + +import "io" + +type Sink struct{} + +func (s *Sink) WriteTo(w io.Writer) (int64, error) { return 0, nil } +`, + 'parsers/parser.go': `package parsers + +type Parser struct{} + +func NewParser() *Parser { return &Parser{} } + +func (p *Parser) ParseExpr(s string) {} +`, + 'codecs/codec.go': `package codecs + +type Encoder interface { + Encode() string +} + +type Serializer interface { + Encoder +} + +type Codec Serializer + +type jsonCodec struct{} + +func (jsonCodec) Encode() string { return "" } + +var JSONCodec Codec = jsonCodec{} + +func encode() string { + return JSONCodec.Encode() +} +`, + 'parsers/use.go': `package parsers + +var testParser = NewParser() + +func parse() { + testParser.ParseExpr("x") +} +`, + }; + for (const [rel, content] of Object.entries(files)) { + fs.mkdirSync(path.dirname(path.join(root, rel)), { recursive: true }); + fs.writeFileSync(path.join(root, rel), content); + } + cg = await CodeGraph.init(root, { index: true }); +}, 120_000); + +afterAll(() => { + cg?.close(); + if (root) fs.rmSync(root, { recursive: true, force: true }); +}); + +/** `file::qualifiedName resolvedBy@confidence` of every method the function `name` in `file` calls. */ +function calls(file: string, name: string): string[] { + const fn = cg.getNodesInFile(file).find((n) => n.name === name && n.kind !== 'method'); + expect(fn, name).toBeDefined(); + return cg + .getOutgoingEdges(fn!.id) + .filter((e) => e.kind === 'calls') + .map((e) => ({ e, n: cg.getNode(e.target)! })) + .filter(({ n }) => n.kind === 'method') + .map(({ e, n }) => `${n.filePath.replace(/\\/g, '/')}::${n.qualifiedName} ${String(e.metadata?.resolvedBy)}@${String(e.metadata?.confidence)}`) + .sort(); +} + +describe('Go calls through a package-level variable or constant', () => { + it.each([ + // `var lg *zap.Logger`: not the project's only `Panic`. + ['tools/dump.go', 'dump', 'a variable of a type from outside the project'], + // The same `lg`, declared in another file of the package. + ['tools/other.go', 'other', 'a variable another file declares'], + // `var buf = bytes.NewBuffer(nil)`: not the project's only `WriteTo`. + ['buffers/buffers.go', 'flush', 'a value a package from outside the project hands out'], + ])('links nothing from %s %s: %s', (file, fn) => { + expect(calls(file, fn)).toEqual([]); + }); + + it.each([ + // `RoleNode Role = "node"` in kubernetes.go, not aws's `Role`. + ['discovery/kubernetes/metrics.go', 'nodeRole', 'discovery/kubernetes/kubernetes.go::Role::String instance-method@0.9'], + // `KindB`, alone in its group, has `Kind` from `KindA Kind = iota`. + ['discovery/kubernetes/kind.go', 'kindLabel', 'discovery/kubernetes/kind.go::Kind::Label instance-method@0.9'], + // `var defaultRegistry = &Registry{}`, not a plugin `Manager`. + ['registry/registry.go', 'register', 'registry/registry.go::Registry::Register instance-method@0.9'], + // `var podRole = Role("pod")`. + ['discovery/kubernetes/roles.go', 'podRoleName', 'discovery/kubernetes/kubernetes.go::Role::String instance-method@0.9'], + ])('links %s %s through the declared type', (file, fn, target) => { + expect(calls(file, fn)).toEqual([target]); + }); + + it('leaves a local of the name, a value a project function returns and a type whose methods it can\'t see as they were', () => { + // `lg := logx.New()` shadows the package's `lg`. + expect(calls('tools/shadow.go', 'shadow').filter((c) => c.startsWith('logx/logger.go::Logger::Panic '))).toHaveLength(1); + // `var testParser = NewParser()` says no type. + expect(calls('parsers/use.go', 'parse').filter((c) => c.startsWith('parsers/parser.go::Parser::ParseExpr '))).toHaveLength(1); + // `var JSONCodec Codec = jsonCodec{}`: `Codec` is defined over an + // interface, whose methods its node doesn't carry. Fork: upstream leaves + // the call to its name-guessing strategies, which link some `Encode`; the + // fork's native resolver reads the declared type and, finding no method + // on it, links nothing rather than guess. + expect(calls('codecs/codec.go', 'encode')).toEqual([]); + }); +}); diff --git a/__tests__/go-std-method-receivers.test.ts b/__tests__/go-std-method-receivers.test.ts new file mode 100644 index 0000000000..d5a882042e --- /dev/null +++ b/__tests__/go-std-method-receivers.test.ts @@ -0,0 +1,344 @@ +/** + * Go calls of a standard method name — `Error`, `String`, `Err`, `Lock`, + * `Header` — on a receiver nothing types. + * + * Every Go type may carry such a name, so the name alone says nothing of the + * receiver. A guess by a word the receiver shares with a type's name bound + * kubernetes' `err.Error()` to `notRegisteredErr::Error` and etcd's + * `ctx.Err()` to a `valCtx`. The receiver's declaration decides when it can be + * read — its declared type's own method, or nothing for a predeclared type + * or a type from outside the project — and otherwise only a receiver named + * after the owner type itself gets a guess. + */ +import { describe, it, expect, beforeAll, afterAll } from 'vitest'; +import * as fs from 'fs'; +import * as os from 'os'; +import * as path from 'path'; +import { CodeGraph } from '../src'; + +let root = ''; +let cg: CodeGraph; + +beforeAll(async () => { + root = fs.mkdtempSync(path.join(os.tmpdir(), 'cg-go-std-recv-')); + const files: Record = { + 'go.mod': 'module example.com/app\n\ngo 1.22\n', + 'types/id.go': `package types + +type ID uint64 + +func (i ID) String() string { return "" } + +type URLsMap map[string][]string + +func NewURLsMap() URLsMap { return URLsMap{} } + +func (m URLsMap) String() string { return "" } +`, + 'runtime/error.go': `package runtime + +type notRegisteredErr struct{} + +func (e *notRegisteredErr) Error() string { return "" } + +type ParseErr struct{} + +func (e *ParseErr) Error() string { return "" } +`, + 'etcdserver/request.go': `package etcdserver + +type MoveLeaderRequest struct{} + +func (m *MoveLeaderRequest) String() string { return "" } +`, + 'client/watch.go': `package client + +import "context" + +type valCtx struct{ context.Context } + +func (c *valCtx) Err() error { return nil } +`, + 'concurrency/mutex.go': `package concurrency + +type Mutex struct{} + +func (m *Mutex) Lock() error { return nil } + +func (m *Mutex) Unlock() error { return nil } +`, + 'chunks/iterator.go': `package chunks + +type Iterator interface { + Next() bool + Err() error +} +`, + 'index/postings.go': `package index + +type StringIter interface { + Next() bool + Err() error +} + +type symbolsIter struct{} + +func (s *symbolsIter) Next() bool { return false } + +func (s *symbolsIter) Err() error { return nil } +`, + 'featuregate/fgtesting/tb.go': `package fgtesting + +type TB interface { + Error(args ...any) +} +`, + 'kubelet/runtime.go': `package kubelet + +type Status struct{ Code int } + +type RuntimeStatus struct{} + +func (r *RuntimeStatus) String() string { return "" } +`, + 'httpx/recorder.go': `package httpx + +import "net/http" + +type ResponseRecorder struct{} + +func (r *ResponseRecorder) Header() http.Header { return nil } +`, + 'boot/srv.go': `package boot + +type Srv struct{} + +func (s *Srv) Start() {} +`, + 'promql/engine.go': `package promql + +type Query interface { + Exec() string + String() string +} + +func NewQuery(q string) Query { return nil } +`, + 'server/version.go': `package server + +type Version struct{} + +func ParseVersion(s string) (*Version, error) { return &Version{}, nil } + +func (v *Version) Major() string { return "" } + +func (v *Version) String() string { return "" } +`, + 'server/server.go': `package server + +import ( + "context" + "fmt" + "net/http/httptest" + "sync" + "testing" + "time" + + "example.com/app/boot" + "example.com/app/chunks" + "example.com/app/promql" + "example.com/app/types" +) + +type Server struct{} + +func (s *Server) String() string { return "" } + +func (s *Server) Describe() string { return s.String() } + +func doWork() error { return nil } + +func lookupLeader() fmt.Stringer { return nil } + +func currentStatus() fmt.Stringer { return nil } + +func newSrv() *boot.Srv { return nil } + +func errorText(err error) string { return err.Error() } + +func workText() string { + err := doWork() + return err.Error() +} + +func leaderText() string { + leaderID := lookupLeader() + return leaderID.String() +} + +func memberText(memberID types.ID) string { return memberID.String() } + +func idsText(ids []types.ID) string { + out := "" + for _, id := range ids { + out += id.String() + } + return out +} + +func ctxErr(ctx context.Context) error { return ctx.Err() } + +func timeoutErr() error { + ctx, cancel := context.WithTimeout(context.Background(), time.Second) + defer cancel() + return ctx.Err() +} + +func locked() { + var mu sync.Mutex + mu.Lock() +} + +func iterErr(iter chunks.Iterator) error { return iter.Err() } + +func report(tb testing.TB) { tb.Error("failed") } + +func statusText() string { + status := currentStatus() + return status.String() +} + +func headers() { + recorder := httptest.NewRecorder() + _ = recorder.Header() +} + +func urls() string { + urlsMap := types.NewURLsMap() + return urlsMap.String() +} + +func startSrv() { + srv := newSrv() + srv.Start() +} + +func runQueries() { + for _, tc := range []struct { + query string + }{{query: "up"}} { + func() { + var ( + query promql.Query + ) + query = promql.NewQuery(tc.query) + _ = query.Exec() + _ = query.String() + }() + } +} + +func versionText() string { + tests := []struct { + version string + }{{version: "1.0"}} + out := "" + for _, test := range tests { + version, _ := ParseVersion(test.version) + out += version.Major() + version.String() + } + return out +} +`, + }; + for (const [rel, content] of Object.entries(files)) { + fs.mkdirSync(path.dirname(path.join(root, rel)), { recursive: true }); + fs.writeFileSync(path.join(root, rel), content); + } + cg = await CodeGraph.init(root, { index: true }); +}, 120_000); + +afterAll(() => { + cg?.close(); + if (root) fs.rmSync(root, { recursive: true, force: true }); +}); + +/** `file::qualifiedName resolvedBy@confidence` of every method the function `name` in server.go calls. */ +function calls(name: string): string[] { + const fn = cg.getNodesInFile('server/server.go').find((n) => n.name === name && n.kind !== 'method'); + expect(fn, name).toBeDefined(); + return cg + .getOutgoingEdges(fn!.id) + .filter((e) => e.kind === 'calls') + .map((e) => ({ e, n: cg.getNode(e.target)! })) + .filter(({ n }) => n.kind === 'method') + .map(({ e, n }) => `${n.filePath.replace(/\\/g, '/')}::${n.qualifiedName} ${String(e.metadata?.resolvedBy)}@${String(e.metadata?.confidence)}`) + .sort(); +} + +describe('Go standard method names on a receiver nothing types', () => { + it.each([ + // `func errorText(err error)`: the error interface's own method. + ['errorText', 'a receiver of a predeclared type'], + // `err := doWork()`: an `err` is no `notRegisteredErr`. + ['workText', 'a receiver sharing only a word with the owner type'], + // `leaderID := lookupLeader()`: no `MoveLeaderRequest`. + ['leaderText', 'a receiver sharing only a word with the owner type'], + ['ctxErr', 'a parameter of a type from outside the project'], + // `ctx, cancel := context.WithTimeout(…)` + ['timeoutErr', 'a value a package from outside the project hands out'], + // `var mu sync.Mutex`: no project `Mutex`. + ['locked', 'a variable of a type from outside the project'], + // `tb testing.TB`, beside a project interface `TB`. + ['report', 'a parameter of a type from outside the project'], + // `recorder := httptest.NewRecorder()` + ['headers', 'a value a package from outside the project hands out'], + // `status := currentStatus()`, beside a `Status` type and a `RuntimeStatus::String`. + ['statusText', 'a receiver named after a type that lacks the method'], + ])('links nothing from %s: %s', (fn) => { + expect(calls(fn)).toEqual([]); + }); + + it.each([ + ['memberText', 'types/id.go::ID::String instance-method@0.9'], + // Not `StringIter::Err` or `symbolsIter::Err`, by the word "iter". + ['iterErr', 'chunks/iterator.go::Iterator::Err instance-method@0.9'], + ])('links %s through the type its parameter is declared as', (fn, target) => { + expect(calls(fn)).toEqual([target]); + }); + + // Fork: the binding rows type both receivers (a range variable over a + // `[]types.ID`, the result of `types.NewURLsMap()`), so these link by their + // declared type at 0.9 where upstream's text guess lands at 0.65. The + // targets are upstream's. + it.each([ + // `for _, id := range ids` + ['idsText', 'types/id.go::ID::String instance-method@0.9'], + // `urlsMap := types.NewURLsMap()` + ['urls', 'types/id.go::URLsMap::String instance-method@0.9'], + ])('links %s through the type its receiver is bound to', (fn, target) => { + expect(calls(fn)).toEqual([target]); + }); + + it.each([ + // `var ( query promql.Query )`, read past the table's `query string`; + // Fork: `Exec` links through the declared type at 0.9, where upstream + // guesses it at 0.8. + ['runQueries', ['promql/engine.go::Query::Exec instance-method@0.9', 'promql/engine.go::Query::String instance-method@0.9']], + // `version, _ := ParseVersion(…)` says no type, and the table's + // `version string` is another declaration: nothing is ruled out. Fork: + // the fork's bindings read the `Version` result, so both link at 0.9 + // (upstream: 0.8). + ['versionText', ['server/version.go::Version::Major instance-method@0.9', 'server/version.go::Version::String instance-method@0.9']], + ])('reads %s by the declaration in scope, not a test table field of the name', (fn, targets) => { + expect(calls(fn)).toEqual(targets); + }); + + it("leaves typed receivers and other method names as they were", () => { + const describeFn = cg.getNodesInFile('server/server.go').find((n) => n.qualifiedName === 'Server::Describe'); + expect(describeFn).toBeDefined(); + const targets = cg.getOutgoingEdges(describeFn!.id).filter((e) => e.kind === 'calls').map((e) => cg.getNode(e.target)!.qualifiedName); + expect(targets).toEqual(['Server::String']); + expect(calls('startSrv').filter((c) => c.includes('Srv::Start'))).toHaveLength(1); + }); +}); diff --git a/__tests__/go-struct-field-refs.test.ts b/__tests__/go-struct-field-refs.test.ts new file mode 100644 index 0000000000..351f10841e --- /dev/null +++ b/__tests__/go-struct-field-refs.test.ts @@ -0,0 +1,627 @@ +/** + * A Go struct's fields referenced nothing: `type PutResponse struct { Header + * *ResponseHeader }` (etcd) or gin's `type Context struct { handlers + * HandlersChain }` was a `struct` node with no `references` edge to the types + * its fields are declared with, so impact on `ResponseHeader` or + * `HandlersChain` missed every struct that holds one, and everything that + * uses those structs. Only embedded fields were read, as `extends` edges. + * + * The struct now references each type a named field's type names, on the + * name, where resolution reads a package qualifier back. The references are + * the struct's: Go fields mint no nodes, as Dart's don't (#2327), and impact + * never climbs from a member to its container, so a field node would have + * stopped impact short of the struct. Not references: an embedded field (an + * `extends` edge already), the struct's own type parameters, Go's predeclared + * types, and the struct's own name written bare (`next *node`), which names + * the struct itself: no self-edge, and no unresolved row for the name. + * + * Resolution reads each as any type position: a bare name is its own + * package's type, `pb.ResponseHeader` the import's, `context.Context` (a + * package outside the project) nothing, and a name written through a package + * the index doesn't know links to nothing either. + */ +import { describe, it, expect, beforeAll, beforeEach, afterEach, afterAll } from 'vitest'; +import * as fs from 'fs'; +import * as os from 'os'; +import * as path from 'path'; +import CodeGraph from '../src/index'; +import { extractFromSource } from '../src/extraction'; +import { initGrammars, loadGrammarsForLanguages } from '../src/extraction/grammars'; +import { tryKernelExtract, resetKernelForTests } from '../src/extraction/kernel'; +import type { ExtractionResult } from '../src/types'; + +const KERNEL_PATH = path.join( + __dirname, + '..', + 'codegraph-kernel', + 'prebuilds', + `${process.platform}-${process.arch}`, + 'codegraph-kernel.node' +); +const kernelAvailable = fs.existsSync(KERNEL_PATH) || process.env.CODEGRAPH_KERNEL_EXPECT === '1'; + +/** Every shape a field's type can take, beside the declarations that skip names. */ +const FIELDS_SOURCE = `package etcdserverpb + +import ( + "context" + "sync" + + mvccpb "go.etcd.io/etcd/api/v3/mvccpb" + "go.uber.org/zap" + "k8s.io/client-go/gentype" +) + +type ResponseHeader struct { + ClusterId uint64 + Revision int64 +} + +// PutResponse is etcd's: a header and the previous key-value. +type PutResponse struct { + Header *ResponseHeader \`protobuf:"bytes,1,opt,name=header,proto3" json:"header,omitempty"\` + PrevKv *mvccpb.KeyValue +} + +type Server struct { + mu sync.RWMutex + lg *zap.Logger + ctx context.Context + handlers HandlersChain + byKey map[Key][]*Watcher + events <-chan Event + grid [4][4]Cell + cb func(ctx context.Context, req *Request) (*Response, error) + wrapped (Cell) + a, b Pair + cache *List[Item] + boxed mvccpb.Box[Item] + conf struct { + inner Inner + *Base + } + codec interface { + Encode(Message) ([]byte, error) + } + err error + n int + opts []any +} + +// Embedded fields are its supertypes, not references; the type arguments of +// an embedded generic are references, as client-go's typed clients name the +// resource they serve. +type Embedder struct { + *Base + Queryable + mvccpb.Embedded + *mvccpb.Pointer \`json:"-"\` + List[int] + *gentype.ClientWithList[*Pod, *mvccpb.PodList] + error + name string +} + +type Node struct { + next *Node + children map[string]*Node + build func(*Node) error + remote *mvccpb.Node +} + +type List[T any] struct { + items []T + head *elem[T] + next *List[T] + extra Extra +} + +type Pairs[K comparable, V any] struct { + byKey map[K]V + list List[V] + List[K] + *Box[Pairs[K, V]] +} + +type Anon = struct { + w Widget +} + +type Empty struct{} +`; + +const ENV_KEYS = ['CODEGRAPH_KERNEL', 'CODEGRAPH_KERNEL_LANGS'] as const; + +/** ` ` of every node but the file and its imports, in source order. */ +function declarations(result: ExtractionResult): string[] { + return result.nodes.filter((n) => n.kind !== 'file' && n.kind !== 'import').map((n) => `${n.kind} ${n.name}`); +} + +/** ` ` for every `references` ref out of a struct, sorted. */ +function fieldRefs(result: ExtractionResult): string[] { + const byId = new Map(result.nodes.map((n) => [n.id, n])); + return result.unresolvedReferences + .filter((r) => r.referenceKind === 'references' && byId.get(r.fromNodeId)?.kind === 'struct') + .map((r) => `${byId.get(r.fromNodeId)!.name} ${r.referenceName}`) + .sort(); +} + +describe('a Go struct references the types its fields are declared with', () => { + let savedEnv: Record = {}; + + beforeAll(async () => { + await initGrammars(); + await loadGrammarsForLanguages(['go']); + }); + + beforeEach(() => { + savedEnv = Object.fromEntries(ENV_KEYS.map((k) => [k, process.env[k]])); + resetKernelForTests(); + }); + + afterEach(() => { + for (const k of ENV_KEYS) { + if (savedEnv[k] === undefined) delete process.env[k]; + else process.env[k] = savedEnv[k]; + } + resetKernelForTests(); + }); + + function extract(backend: 'kernel' | 'wasm', file: string, source: string): ExtractionResult { + if (backend === 'wasm') { + process.env.CODEGRAPH_KERNEL = '0'; + return extractFromSource(file, source, 'go'); + } + delete process.env.CODEGRAPH_KERNEL; + process.env.CODEGRAPH_KERNEL_LANGS = 'all'; + const result = tryKernelExtract(file, source, 'go'); + expect(result, `kernel extraction of ${file}`).not.toBeNull(); + return result!; + } + + const backends = kernelAvailable ? (['kernel', 'wasm'] as const) : (['wasm'] as const); + + for (const crlf of [false, true]) { + const eol = (s: string) => (crlf ? s.replace(/\n/g, '\r\n') : s); + const label = crlf ? ' (CRLF)' : ''; + + it.each(backends)(`a field mints no node of its own: %s${label}`, (backend) => { + const result = extract(backend, 'rpc.pb.go', eol(FIELDS_SOURCE)); + expect(declarations(result)).toEqual([ + 'struct ResponseHeader', + 'struct PutResponse', + 'struct Server', + 'struct Embedder', + 'struct Node', + 'struct List', + 'struct Pairs', + 'struct Anon', + 'struct Empty', + ]); + }); + + it.each(backends)(`a struct references each type its named fields name: %s${label}`, (backend) => { + const source = eol(FIELDS_SOURCE); + const result = extract(backend, 'rpc.pb.go', source); + // Not references: the predeclared types (uint64, int64, error, int, any, + // byte), the type parameters T, K and V, a struct's own name written bare + // (Node, List, Pairs), and the type an embedded field embeds. A qualified + // name keeps its package in the source (`zap.Logger`, `mvccpb.Node`), and + // an anonymous struct or interface in a field is the field's type: its + // fields, embedded or not, and its methods' types are the struct's. + expect(fieldRefs(result)).toEqual([ + 'Anon Widget', + 'Embedder Pod', + 'Embedder PodList', + 'List Extra', + 'List elem', + 'Node Node', + 'Pairs List', + 'PutResponse KeyValue', + 'PutResponse ResponseHeader', + 'Server Base', + 'Server Box', + 'Server Cell', + 'Server Cell', + 'Server Context', + 'Server Context', + 'Server Event', + 'Server HandlersChain', + 'Server Inner', + 'Server Item', + 'Server Item', + 'Server Key', + 'Server List', + 'Server Logger', + 'Server Message', + 'Server Pair', + 'Server RWMutex', + 'Server Request', + 'Server Response', + 'Server Watcher', + ]); + // Each sits on its name, where resolution reads the qualifier back. + const lines = source.split(/\r?\n/); + const byId = new Map(result.nodes.map((n) => [n.id, n])); + const refs = result.unresolvedReferences.filter((r) => r.referenceKind === 'references' && byId.get(r.fromNodeId)?.kind === 'struct'); + for (const r of refs) { + expect(lines[r.line - 1]!.startsWith(r.referenceName, r.column), `${r.referenceName} at ${r.line}:${r.column}`).toBe(true); + } + const remote = refs.find((r) => byId.get(r.fromNodeId)!.name === 'Node')!; + expect(lines[remote.line - 1]!.slice(0, remote.column).trimStart()).toBe('remote *mvccpb.'); + }); + + it.each(backends)(`an embedded field is still a supertype, and its type arguments references: %s${label}`, (backend) => { + const result = extract(backend, 'rpc.pb.go', eol(FIELDS_SOURCE)); + const refsOf = (name: string) => { + const struct = result.nodes.find((n) => n.kind === 'struct' && n.name === name)!; + return result.unresolvedReferences + .filter((r) => r.fromNodeId === struct.id) + .map((r) => `${r.referenceKind} ${r.referenceName}`) + .sort(); + }; + expect(refsOf('Embedder')).toEqual([ + 'extends Base', + 'extends ClientWithList', + 'extends Embedded', + 'extends List', + 'extends Pointer', + 'extends Queryable', + 'references Pod', + 'references PodList', + ]); + // `List[K]` and `*Box[Pairs[K, V]]` hold a type parameter or the struct + // itself, and nothing else. + expect(refsOf('Pairs')).toEqual(['extends Box', 'extends List', 'references List']); + }); + } +}); + +/** The module of the indexed tests: etcd's and gin's shapes, with namesakes in a package that sorts first. */ +const MODULE: Record = { + 'go.mod': 'module go.etcd.io/etcd\n\ngo 1.24\n', + // A lookup by name meets these first. + 'alpha/names.go': [ + 'package alpha', + '', + 'type ResponseHeader struct{}', + '', + 'type KeyValue struct{}', + '', + 'type Context struct{}', + '', + 'type Config struct{}', + '', + 'type Client struct{}', + '', + 'type Op struct{}', + '', + 'type HandlersChain []int', + '', + 'type Engine struct{}', + '', + 'type node struct{}', + '', + 'type elem struct{}', + '', + 'type T struct{}', + '', + 'type Pod struct{}', + '', + ].join('\n'), + // client-go's lister: the resource is a type argument of the embedded generic. + 'k8s/api/core/v1/types.go': [ + 'package v1', + '', + 'type Pod struct {', + '\tName string', + '}', + '', + ].join('\n'), + 'k8s/client-go/listers/generic.go': [ + 'package listers', + '', + 'type ResourceIndexer[T any] struct {', + '\titems []T', + '}', + '', + ].join('\n'), + 'k8s/client-go/listers/core/v1/pod.go': [ + 'package v1', + '', + 'import (', + '\tcorev1 "go.etcd.io/etcd/k8s/api/core/v1"', + '\t"go.etcd.io/etcd/k8s/client-go/listers"', + ')', + '', + 'type podLister struct {', + '\tlisters.ResourceIndexer[*corev1.Pod]', + '}', + '', + ].join('\n'), + 'api/v3/etcdserverpb/rpc.pb.go': [ + 'package etcdserverpb', + '', + 'import mvccpb "go.etcd.io/etcd/api/v3/mvccpb"', + '', + 'type ResponseHeader struct {', + '\tRevision int64', + '}', + '', + 'type PutResponse struct {', + '\tHeader *ResponseHeader', + '}', + '', + 'type RangeResponse struct {', + '\tHeader *ResponseHeader', + '\tKvs []*mvccpb.KeyValue', + '}', + '', + ].join('\n'), + 'api/v3/mvccpb/kv.pb.go': [ + 'package mvccpb', + '', + 'type KeyValue struct {', + '\tKey []byte', + '}', + '', + ].join('\n'), + 'client/v3/client.go': [ + 'package clientv3', + '', + 'import (', + '\t"context"', + '', + '\tpb "go.etcd.io/etcd/api/v3/etcdserverpb"', + ')', + '', + '// A namesake of context.Context in the same file.', + 'type Context struct{}', + '', + 'type Config struct{}', + '', + 'type Client struct {', + '\tctx context.Context', + '\tcfg Config', + '\theader *pb.ResponseHeader', + '}', + '', + 'func (c *Client) Header() *pb.ResponseHeader { return c.header }', + '', + 'func dial(c *Client) {}', + '', + ].join('\n'), + // Package clientv3, known to the index by its path (`v3`, `client`) only. + 'client/v3/ordering/kv.go': [ + 'package ordering', + '', + 'import "go.etcd.io/etcd/client/v3"', + '', + 'type Op struct{}', + '', + 'type kvOrdering struct {', + '\tkv clientv3.Client', + '\top clientv3.Op', + '}', + '', + ].join('\n'), + 'gin/gin.go': [ + 'package gin', + '', + 'import "sync"', + '', + 'type HandlerFunc func(*Context)', + '', + 'type HandlersChain []HandlerFunc', + '', + 'type Context struct {', + '\thandlers HandlersChain', + '\tengine *Engine', + '}', + '', + 'type Engine struct {', + '\tpool sync.Pool', + '\ttrees methodTrees', + '}', + '', + 'type methodTrees []methodTree', + '', + 'type methodTree struct {', + '\tmethod string', + '\troot *node', + '}', + '', + 'type node struct {', + '\tchildren []*node', + '\thandlers HandlersChain', + '}', + '', + 'func (engine *Engine) handle(c *Context) {}', + '', + ].join('\n'), + 'pkg/adt/list.go': [ + 'package adt', + '', + '// A namesake of the type parameter in its own package.', + 'type T struct{}', + '', + 'type List[T any] struct {', + '\titems []T', + '\thead *elem[T]', + '}', + '', + 'type elem[T any] struct {', + '\tnext *elem[T]', + '\tval T', + '}', + '', + ].join('\n'), +}; + +describe.each([ + ['default', 'LF'], + ['wasm', 'LF'], + ['default', 'CRLF'], + ['wasm', 'CRLF'], +])('an indexed Go module links its struct fields’ types (%s, %s)', (backend, eol) => { + let root = ''; + let cg: CodeGraph | undefined; + let kernel: string | undefined; + + beforeAll(async () => { + kernel = process.env.CODEGRAPH_KERNEL; + if (backend === 'wasm') process.env.CODEGRAPH_KERNEL = '0'; + else delete process.env.CODEGRAPH_KERNEL; + root = fs.mkdtempSync(path.join(os.tmpdir(), 'cg-go-fields-')); + for (const [rel, content] of Object.entries(MODULE)) { + fs.mkdirSync(path.dirname(path.join(root, rel)), { recursive: true }); + fs.writeFileSync(path.join(root, rel), eol === 'CRLF' ? content.replace(/\n/g, '\r\n') : content); + } + cg = await CodeGraph.init(root, { index: true }); + }, 60_000); + + afterAll(() => { + cg?.destroy(); + if (root) fs.rmSync(root, { recursive: true, force: true }); + if (kernel === undefined) delete process.env.CODEGRAPH_KERNEL; + else process.env.CODEGRAPH_KERNEL = kernel; + }); + + const nodeNamed = (file: string, name: string) => { + const nodes = cg!.getNodesInFile(file).filter((n) => n.name === name && n.kind !== 'import'); + expect(nodes, `${name} in ${file}`).toHaveLength(1); + return nodes[0]!; + }; + + /** `kind file:qualifiedName` of each non-contains edge out of `name` in `file`, sorted. */ + const linksFrom = (file: string, name: string) => { + const links = cg!.getOutgoingEdgesFrom([nodeNamed(file, name).id]) + .filter((e) => e.kind !== 'contains') + .map((e) => ({ kind: e.kind, target: cg!.getNode(e.target)! })) + .map(({ kind, target }) => `${kind} ${target.filePath}:${target.qualifiedName}`); + return [...new Set(links)].sort(); + }; + + /** `kind name` of each reference out of `name` in `file` that resolution left unresolved, sorted. */ + const unresolvedFrom = (file: string, name: string) => + cg!.getUnresolvedReferencesFrom(nodeNamed(file, name).id).map((r) => `${r.referenceKind} ${r.referenceName}`).sort(); + + /** `file:qualifiedName` of every node impact on `name` in `file` reaches, sorted. */ + const impactOf = (file: string, name: string) => + [...cg!.getImpactRadius(nodeNamed(file, name).id, 3).nodes.values()].map((n) => `${n.filePath}:${n.qualifiedName}`).sort(); + + it('a struct references the types its fields name, each in its own package', () => { + expect(linksFrom('api/v3/etcdserverpb/rpc.pb.go', 'PutResponse')).toEqual([ + 'references api/v3/etcdserverpb/rpc.pb.go:ResponseHeader', + ]); + expect(linksFrom('api/v3/etcdserverpb/rpc.pb.go', 'RangeResponse')).toEqual([ + 'references api/v3/etcdserverpb/rpc.pb.go:ResponseHeader', + 'references api/v3/mvccpb/kv.pb.go:KeyValue', + ]); + expect(linksFrom('gin/gin.go', 'Context')).toEqual([ + 'references gin/gin.go:Engine', + 'references gin/gin.go:HandlersChain', + ]); + expect(linksFrom('gin/gin.go', 'methodTree')).toEqual(['references gin/gin.go:node']); + }); + + it('a name written through an import is that package’s type, and through an outside package nothing', () => { + // `context.Context` is neither the same file's Context nor alpha's. + expect(linksFrom('client/v3/client.go', 'Client')).toEqual([ + 'references api/v3/etcdserverpb/rpc.pb.go:ResponseHeader', + 'references client/v3/client.go:Config', + ]); + expect(unresolvedFrom('client/v3/client.go', 'Client')).toEqual(['references Context']); + // `sync.Pool` is no project type. + expect(linksFrom('gin/gin.go', 'Engine')).toEqual(['references gin/gin.go:methodTrees']); + }); + + it('a struct naming itself has no edge to itself and no unresolved row for its name', () => { + expect(linksFrom('gin/gin.go', 'node')).toEqual(['references gin/gin.go:HandlersChain']); + expect(unresolvedFrom('gin/gin.go', 'node')).toEqual([]); + }); + + it('an embedded generic is a supertype, and the types it is instantiated with references', () => { + expect(linksFrom('k8s/client-go/listers/core/v1/pod.go', 'podLister')).toEqual([ + 'extends k8s/client-go/listers/generic.go:ResourceIndexer', + 'references k8s/api/core/v1/types.go:Pod', + ]); + expect(impactOf('k8s/api/core/v1/types.go', 'Pod')).toEqual([ + 'k8s/api/core/v1/types.go:Pod', + 'k8s/client-go/listers/core/v1/pod.go:podLister', + ]); + }); + + it('a generic struct’s own type parameters are no types it references', () => { + expect(linksFrom('pkg/adt/list.go', 'List')).toEqual(['references pkg/adt/list.go:elem']); + expect(linksFrom('pkg/adt/list.go', 'elem')).toEqual([]); + expect(unresolvedFrom('pkg/adt/list.go', 'List')).toEqual([]); + expect(unresolvedFrom('pkg/adt/list.go', 'elem')).toEqual([]); + }); + + it('a name written through a package the index does not know links to nothing', () => { + expect(linksFrom('client/v3/ordering/kv.go', 'kvOrdering')).toEqual([]); + expect(unresolvedFrom('client/v3/ordering/kv.go', 'kvOrdering')).toEqual(['references Client', 'references Op']); + }); + + it('impact on a type reaches the structs that hold it, and their users', () => { + expect(impactOf('api/v3/etcdserverpb/rpc.pb.go', 'ResponseHeader')).toEqual([ + 'api/v3/etcdserverpb/rpc.pb.go:PutResponse', + 'api/v3/etcdserverpb/rpc.pb.go:RangeResponse', + 'api/v3/etcdserverpb/rpc.pb.go:ResponseHeader', + 'client/v3/client.go:Client', + 'client/v3/client.go:Client::Header', + 'client/v3/client.go:dial', + ]); + expect(impactOf('gin/gin.go', 'HandlersChain')).toEqual([ + 'gin/gin.go:Context', + 'gin/gin.go:Engine::handle', + 'gin/gin.go:HandlerFunc', + 'gin/gin.go:HandlersChain', + 'gin/gin.go:methodTree', + 'gin/gin.go:methodTrees', + 'gin/gin.go:node', + ]); + }); + + it('no Go field is a node', () => { + for (const file of Object.keys(MODULE).filter((f) => f.endsWith('.go'))) { + expect(cg!.getNodesInFile(file).filter((n) => n.kind === 'field'), file).toEqual([]); + } + }); +}); + +describe.each(['default', 'wasm'])('a field’s type declared after the index links on sync (%s)', (backend) => { + let root = ''; + let cg: CodeGraph | undefined; + let kernel: string | undefined; + + beforeAll(async () => { + kernel = process.env.CODEGRAPH_KERNEL; + if (backend === 'wasm') process.env.CODEGRAPH_KERNEL = '0'; + else delete process.env.CODEGRAPH_KERNEL; + root = fs.mkdtempSync(path.join(os.tmpdir(), 'cg-go-fields-sync-')); + fs.writeFileSync(path.join(root, 'go.mod'), 'module example.com/app\n\ngo 1.24\n'); + fs.mkdirSync(path.join(root, 'store')); + fs.writeFileSync(path.join(root, 'store', 'store.go'), 'package store\n\ntype Store struct {\n\tidx *Index\n}\n'); + cg = await CodeGraph.init(root, { index: true }); + }, 60_000); + + afterAll(() => { + cg?.destroy(); + if (root) fs.rmSync(root, { recursive: true, force: true }); + if (kernel === undefined) delete process.env.CODEGRAPH_KERNEL; + else process.env.CODEGRAPH_KERNEL = kernel; + }); + + it('links the struct to the type once its file is added', async () => { + const store = () => cg!.getNodesInFile('store/store.go').find((n) => n.name === 'Store')!; + expect(cg!.getOutgoingEdgesFrom([store().id]).filter((e) => e.kind === 'references')).toEqual([]); + fs.writeFileSync(path.join(root, 'store', 'index.go'), 'package store\n\ntype Index struct{}\n'); + await cg!.sync(); + const targets = cg!.getOutgoingEdgesFrom([store().id]) + .filter((e) => e.kind === 'references') + .map((e) => `${cg!.getNode(e.target)!.filePath}:${cg!.getNode(e.target)!.name}`); + expect(targets).toEqual(['store/index.go:Index']); + }, 60_000); +}); diff --git a/__tests__/go-type-alias.test.ts b/__tests__/go-type-alias.test.ts index 1b023fa4cc..c3a12c4f18 100644 --- a/__tests__/go-type-alias.test.ts +++ b/__tests__/go-type-alias.test.ts @@ -182,7 +182,8 @@ describe('Go alias declarations are extracted', () => { const result = extract(backend, 'client/v3/watch.go', source); // The package of mvccpb.Event / context.Context stays in the source; // predeclared types (string, uint, error) are no references. The - // defined types (WatchChan, Defined) reference theirs too. + // defined types (WatchChan, Defined) reference theirs too, and a struct + // its fields' (WatchResponse's `Events []*Event`). expect(typeRefs(result)).toEqual([ 'Defined WatchResponse', 'Event Event', @@ -195,6 +196,7 @@ describe('Go alias declarations are extracted', () => { 'Ptr WatchResponse', 'Slice WatchResponse', 'WatchChan WatchResponse', + 'WatchResponse Event', ]); expectRefsOnTheirNames(result, source); }); diff --git a/__tests__/go-unexported-namesake.test.ts b/__tests__/go-unexported-namesake.test.ts new file mode 100644 index 0000000000..3a7fe76c6e --- /dev/null +++ b/__tests__/go-unexported-namesake.test.ts @@ -0,0 +1,171 @@ +/** + * Go keeps an unexported name inside its package: prometheus tsdb's + * `[]*memSeries` in head_append.go can only mean the `memSeries` head.go + * declares, never the one in `tsdb/agent`. Name matching scored the two the + * same — directory proximity counts shared leading directories, so a child + * package's file ties with a file of the package's own directory — and the + * one met first, `tsdb/agent`'s, was then vetoed as invisible, so the + * reference linked to nothing. Parameters, results, struct fields, composite + * literals and calls all failed this way whenever a child package declared + * the same unexported name. + * + * A Go candidate the reference cannot see is now out of the pool before the + * ranking, as for C#, Java and PHP, so the package's own declaration wins. + */ +import { describe, it, expect, beforeAll, afterAll } from 'vitest'; +import * as fs from 'fs'; +import * as os from 'os'; +import * as path from 'path'; +import CodeGraph from '../src/index'; + +/** prometheus's shape: package tsdb, with namesakes in its child packages. */ +const MODULE: Record = { + 'go.mod': 'module example.com/prom\n\ngo 1.24\n', + 'tsdb/head.go': [ + 'package tsdb', + '', + 'type Head struct {', + '\tseries map[uint64]*memSeries', + '}', + '', + 'type memSeries struct {', + '\tref uint64', + '}', + '', + 'type sample struct {', + '\tt int64', + '}', + '', + 'func newSeries() *memSeries { return &memSeries{} }', + '', + 'func init() {}', + '', + ].join('\n'), + 'tsdb/head_append.go': [ + 'package tsdb', + '', + 'type appendBatch struct {', + '\tseries []*memSeries', + '\tsamples []sample', + '}', + '', + 'func appendTo(h *Head, s *memSeries, xs []sample) *memSeries {', + '\tm := newSeries()', + '\t_ = memSeries{}', + '\treturn m', + '}', + '', + '// onlyAgent is declared in tsdb/agent alone: nothing here can name it.', + 'func orphan(x *onlyAgent) {}', + '', + 'func shadowed() *memSeries {', + '\tnewSeries := func() *memSeries { return nil }', + '\tinit := func() {}', + '\tinit()', + '\treturn newSeries()', + '}', + '', + ].join('\n'), + 'tsdb/agent/series.go': [ + 'package agent', + '', + 'type memSeries struct{}', + '', + 'type onlyAgent struct{}', + '', + 'func newSeries() *memSeries { return &memSeries{} }', + '', + 'func use(s *memSeries) { _ = newSeries() }', + '', + ].join('\n'), + 'tsdb/chunks/samples.go': [ + 'package chunks', + '', + 'type sample struct{}', + '', + ].join('\n'), +}; + +describe.each([ + ['default', 'LF'], + ['wasm', 'LF'], + ['default', 'CRLF'], + ['wasm', 'CRLF'], +])('a Go unexported name is its own package’s, whatever a child package declares (%s, %s)', (backend, eol) => { + let root = ''; + let cg: CodeGraph | undefined; + let kernel: string | undefined; + + beforeAll(async () => { + kernel = process.env.CODEGRAPH_KERNEL; + if (backend === 'wasm') process.env.CODEGRAPH_KERNEL = '0'; + else delete process.env.CODEGRAPH_KERNEL; + root = fs.mkdtempSync(path.join(os.tmpdir(), 'cg-go-namesake-')); + for (const [rel, content] of Object.entries(MODULE)) { + fs.mkdirSync(path.dirname(path.join(root, rel)), { recursive: true }); + fs.writeFileSync(path.join(root, rel), eol === 'CRLF' ? content.replace(/\n/g, '\r\n') : content); + } + cg = await CodeGraph.init(root, { index: true }); + }, 60_000); + + afterAll(() => { + cg?.destroy(); + if (root) fs.rmSync(root, { recursive: true, force: true }); + if (kernel === undefined) delete process.env.CODEGRAPH_KERNEL; + else process.env.CODEGRAPH_KERNEL = kernel; + }); + + const nodeNamed = (file: string, name: string) => { + const nodes = cg!.getNodesInFile(file).filter((n) => n.name === name && n.kind !== 'import'); + expect(nodes, `${name} in ${file}`).toHaveLength(1); + return nodes[0]!; + }; + + /** `kind file:name` of each non-contains edge out of `name` in `file`, sorted, duplicates kept. */ + const linksFrom = (file: string, name: string) => + cg!.getOutgoingEdgesFrom([nodeNamed(file, name).id]) + .filter((e) => e.kind !== 'contains') + .map((e) => `${e.kind} ${cg!.getNode(e.target)!.filePath}:${cg!.getNode(e.target)!.name}`) + .sort(); + + const unresolvedFrom = (file: string, name: string) => + cg!.getUnresolvedReferencesFrom(nodeNamed(file, name).id).map((r) => `${r.referenceKind} ${r.referenceName}`).sort(); + + it('a parameter, a result, a composite literal and a call name the package’s own declarations', () => { + expect(linksFrom('tsdb/head_append.go', 'appendTo')).toEqual([ + 'calls tsdb/head.go:newSeries', + 'instantiates tsdb/head.go:memSeries', + 'references tsdb/head.go:Head', + 'references tsdb/head.go:memSeries', + 'references tsdb/head.go:memSeries', + 'references tsdb/head.go:sample', + ]); + expect(unresolvedFrom('tsdb/head_append.go', 'appendTo')).toEqual([]); + }); + + it('a struct’s fields name the package’s own types', () => { + expect(linksFrom('tsdb/head_append.go', 'appendBatch')).toEqual([ + 'references tsdb/head.go:memSeries', + 'references tsdb/head.go:sample', + ]); + }); + + it('the child package keeps its own declarations', () => { + expect(linksFrom('tsdb/agent/series.go', 'use')).toEqual([ + 'calls tsdb/agent/series.go:newSeries', + 'references tsdb/agent/series.go:memSeries', + ]); + }); + + it('a name the function binds itself is that binding, not the package’s declaration', () => { + // Its result type still links; the two calls are to its own closures, + // neither to tsdb's `newSeries` nor to `func init()`, which Go never lets + // a program name. + expect(linksFrom('tsdb/head_append.go', 'shadowed')).toEqual(['references tsdb/head.go:memSeries']); + }); + + it('an unexported name only another package declares links to nothing', () => { + expect(linksFrom('tsdb/head_append.go', 'orphan')).toEqual([]); + expect(unresolvedFrom('tsdb/head_append.go', 'orphan')).toEqual(['references onlyAgent']); + }); +}); diff --git a/__tests__/react-router-call-tables.test.ts b/__tests__/react-router-call-tables.test.ts new file mode 100644 index 0000000000..39e2716f9a --- /dev/null +++ b/__tests__/react-router-call-tables.test.ts @@ -0,0 +1,427 @@ +/** + * A route table handed to React Router through a local that holds a call's + * result: Medusa's admin dashboard writes + * + * const routes = getRouteMap({ settingsRoutes: this.settingsRoutes, coreRoutes: this.coreRoutes }) + * const router = createBrowserRouter(routes, { basename }) + * + * inside a class's `render()`, and `getRouteMap`, imported from its own + * module, returns the literal table. The table is what the function returns. + * Before, the local was read only for a literal, so none of Medusa's routes + * existed. The tables spread in from the function's parameters (`...coreRoutes`) + * are the caller's to fill (Medusa's come from plugins), so they stay unread. + * + * Which `routes` a use reads is the one in scope there: another function's + * `const routes = getMenu()` is that function's own, and a menu is no table. + */ +import { describe, it, expect, beforeAll, afterAll } from 'vitest'; +import * as fs from 'fs'; +import * as os from 'os'; +import * as path from 'path'; +import { CodeGraph } from '../src'; + +function writeFiles(root: string, files: Record): void { + for (const [rel, content] of Object.entries(files)) { + fs.mkdirSync(path.dirname(path.join(root, rel)), { recursive: true }); + fs.writeFileSync(path.join(root, rel), content); + } +} + +async function indexProject(files: Record): Promise<{ root: string; cg: CodeGraph }> { + const root = fs.mkdtempSync(path.join(os.tmpdir(), 'cg-rr-call-tables-')); + writeFiles(root, files); + return { root, cg: await CodeGraph.init(root, { index: true }) }; +} + +/** `path -> Component` for what each route renders, `path ~> Layout` for each layout around it, under `dir`. */ +function routeBindings(cg: CodeGraph, dir: string): string[] { + return cg.getNodesByKind('route').filter((r) => r.filePath.startsWith(dir)).flatMap((r) => cg.getOutgoingEdges(r.id) + .filter((e) => e.kind === 'references') + .map((e) => `${r.name} ${(e.metadata as Record | undefined)?.layout ? '~>' : '->'} ${cg.getNode(e.target)?.name}`)) + .sort(); +} + +const routeNames = (cg: CodeGraph, dir: string): string[] => + cg.getNodesByKind('route').filter((r) => r.filePath.startsWith(dir)).map((r) => r.name).sort(); + +/** A component that renders the routes inside it. */ +const layout = (name: string): string => + `import { Outlet } from 'react-router-dom';\n\nexport const ${name} = () => {\n return ;\n};\n`; + +/** A route module the way Medusa writes one: a barrel that hands React Router its page as `Component`. */ +const routeModule = (dir: string, name: string, file: string): Record => ({ + [`${dir}/index.ts`]: `export { ${name} as Component } from './${file}';\n`, + [`${dir}/${file}.tsx`]: `export const ${name} = () => {\n return
${name}
;\n};\n`, +}); + +const MEDUSA_APP = `import { createBrowserRouter, RouteObject, RouterProvider } from 'react-router-dom'; +import { getRouteMap } from './routes/get-route.map'; + +export class DashboardApp { + private coreRoutes: RouteObject[]; + private settingsRoutes: RouteObject[]; + + constructor({ plugins }: { plugins: { routes: RouteObject[] }[] }) { + this.coreRoutes = plugins.flatMap((p) => p.routes); + this.settingsRoutes = []; + } + + render() { + const routes = getRouteMap({ + settingsRoutes: this.settingsRoutes, + coreRoutes: this.coreRoutes, + }); + + const router = createBrowserRouter(routes, { + basename: '/app', + }); + + return ; + } +} +`; + +const routeMap = (extra = ''): string => `import { RouteObject } from 'react-router-dom'; +import { ProtectedRoute } from '../../components/protected-route'; +import { MainLayout } from '../../components/main-layout'; +import { SettingsLayout } from '../../components/settings-layout'; +import { PublicLayout } from '../../components/public-layout'; + +export function getRouteMap({ + settingsRoutes, + coreRoutes, +}: { + settingsRoutes: RouteObject[] + coreRoutes: RouteObject[] +}) { + return [ + { + element: , + children: [ + { + element: , + children: [ + { + path: '/', + lazy: () => import('../../routes/home'), + }, + { + path: '/products', + children: [ + { + path: '', + lazy: () => import('../../routes/products/product-list'), + children: [ + { + path: 'create', + lazy: () => + import('../../routes/products/product-create'), + }, + ], + }, + ], + },${extra} + ...coreRoutes, + ], + }, + { + element: , + children: [ + { + path: '/settings', + lazy: () => import('../../routes/settings'), + }, + ...settingsRoutes.flatMap((r) => r?.children || []), + ], + }, + ], + }, + { + element: , + children: [ + { + path: '/login', + lazy: () => import('../../routes/login'), + }, + ], + }, + ]; +} +`; + +const ORDERS = ` + { + path: '/orders', + lazy: () => import('../../routes/orders'), + },`; + +const MEDUSA: Record = { + 'admin/package.json': JSON.stringify({ name: 'dashboard', dependencies: { react: '^18', 'react-router-dom': '^6' } }), + 'admin/src/dashboard-app/dashboard-app.tsx': MEDUSA_APP, + 'admin/src/dashboard-app/routes/get-route.map.tsx': routeMap(), + 'admin/src/components/protected-route.tsx': layout('ProtectedRoute'), + 'admin/src/components/main-layout.tsx': layout('MainLayout'), + 'admin/src/components/settings-layout.tsx': layout('SettingsLayout'), + 'admin/src/components/public-layout.tsx': layout('PublicLayout'), + ...routeModule('admin/src/routes/home', 'Home', 'home'), + ...routeModule('admin/src/routes/products/product-list', 'ProductList', 'product-list'), + ...routeModule('admin/src/routes/products/product-create', 'ProductCreate', 'product-create'), + ...routeModule('admin/src/routes/settings', 'Settings', 'settings'), + ...routeModule('admin/src/routes/login', 'Login', 'login'), + ...routeModule('admin/src/routes/orders', 'Orders', 'orders'), +}; + +const MEDUSA_BINDINGS = [ + '/ -> Home', + '/ ~> MainLayout', + '/ ~> ProtectedRoute', + '/login -> Login', + '/login ~> PublicLayout', + // The `''` route under `/products` is the page there, and the layout its + // `create` child renders inside. + '/products -> ProductList', + '/products ~> MainLayout', + '/products ~> ProtectedRoute', + '/products/create -> ProductCreate', + '/products/create ~> MainLayout', + '/products/create ~> ProductList', + '/products/create ~> ProtectedRoute', + '/settings -> Settings', + '/settings ~> ProtectedRoute', + '/settings ~> SettingsLayout', +]; + +/** + * Apps whose routers are handed a call's result in other ways, and the + * shapes around them that are no route table. + */ +const SHAPES: Record = { + 'package.json': JSON.stringify({ name: 'shapes', dependencies: { react: '^18', 'react-router-dom': '^6' } }), + 'src/icons.jsx': `export function HelpIcon() {\n return ;\n}\nexport function BillingIcon() {\n return ;\n}\n`, + 'src/pages.jsx': ['Home', 'Account', 'Dashboard', 'Landing', 'TodoList', 'Reports'] + .map((p) => `export function ${p}() {\n return
${p}
;\n}\n`).join(''), + // A menu: a `{ path, element }` list that nothing hands the router. + 'src/menu.jsx': `import { BillingIcon, HelpIcon } from './icons'; + +export function getMenu() { + return [ + { path: '/help', element: }, + { path: '/billing', element: }, + ]; +} +`, + + // Two functions with a `routes` each: the router is handed App's own. + 'src/scoped/routes.jsx': `import { Account, Home } from '../pages'; + +export const getRoutes = (user) => [ + { path: '/', element: }, + { path: '/account', element: }, +]; +`, + 'src/scoped/App.jsx': `import { Link, useRoutes } from 'react-router-dom'; +import { getMenu } from '../menu'; +import { getRoutes } from './routes'; + +function Sidebar() { + const routes = getMenu(); + return ; +} + +export default function App({ user }) { + const routes = getRoutes(user); + const element = useRoutes(routes); + return
{element}
; +} +`, + + // The router is handed the import; another function's local of that name is its own. + 'src/shadow/routes.jsx': `import { Landing } from '../pages'; + +const routes = [{ path: '/landing', element: }]; + +export default routes; +`, + 'src/shadow/App.jsx': `import { useRoutes } from 'react-router-dom'; +import routes from './routes'; +import { getMenu } from '../menu'; + +function Sidebar() { + const routes = getMenu(); + return
    {routes.map((r) =>
  • {r.path}
  • )}
; +} + +export default function App() { + return useRoutes(routes); +} +`, + + // An exported table that is a call's result, past a function's own local of that name. + 'src/exported/routes.jsx': `import { Dashboard } from '../pages'; +import { getMenu } from '../menu'; + +export function menuSize() { + const routes = getMenu(); + return routes.length; +} + +const makeRoutes = () => [{ path: '/dashboard', element: }]; + +export const routes = makeRoutes(); +`, + 'src/exported/App.jsx': `import { useRoutes } from 'react-router-dom'; +import { routes } from './routes'; + +export default function App() { + return useRoutes(routes); +} +`, + + // A default export that is a call's result. + 'src/default/build.jsx': `import { Reports } from '../pages'; + +export function buildRoutes() { + return [{ path: '/reports', element: }]; +} +`, + 'src/default/routes.js': `import { buildRoutes } from './build'; + +export default buildRoutes(); +`, + 'src/default/App.jsx': `import { useRoutes } from 'react-router-dom'; +import routes from './routes'; + +export default function App() { + return useRoutes(routes); +} +`, + + // A table an async function returns, awaited before the router gets it. + 'src/awaited/load.jsx': `import { Account } from '../pages'; + +export async function loadRoutes() { + return [{ path: '/me', element: }]; +} +`, + 'src/awaited/boot.jsx': `import { createBrowserRouter } from 'react-router-dom'; +import { loadRoutes } from './load'; + +export async function boot() { + const routes = await loadRoutes(); + return createBrowserRouter(routes); +} +`, + + // A router file that builds its table in a function of its own: its route + // objects were read when it was extracted; the table it names is new here. + 'src/features/todo/routes.jsx': `import { TodoList } from '../../pages'; + +export const todoRoutes = [{ path: '/todos', element: }]; +`, + 'src/local/main.jsx': `import { createBrowserRouter } from 'react-router-dom'; +import { todoRoutes } from '../features/todo/routes'; +import { Home } from '../pages'; + +function buildRoutes() { + return [{ path: '/home', element: }, ...todoRoutes]; +} + +const routes = buildRoutes(); + +export const router = createBrowserRouter(routes); +`, + + // A function that makes its table from data returns no literal to read. + 'src/computed/App.jsx': `import { useRoutes } from 'react-router-dom'; +import { pageList } from './pages'; + +function buildRoutes(pages) { + return pages.map((p) => ({ path: p.path, element: p.element })); +} + +export default function App() { + const routes = buildRoutes(pageList); + return useRoutes(routes); +} +`, + 'src/computed/pages.jsx': `import { HelpIcon } from '../icons'; + +export const pageList = [{ path: '/computed', element: }]; +`, +}; + +describe("react-router: a table a function returns, handed over through a local (Medusa's admin dashboard)", () => { + let root: string; + let cg: CodeGraph; + beforeAll(async () => { + ({ root, cg } = await indexProject(MEDUSA)); + }, 60_000); + afterAll(() => { + cg?.close(); + if (root) fs.rmSync(root, { recursive: true, force: true }); + }); + + it('reads the table getRouteMap returns, each lazy route bound to the page its module hands React Router', () => { + expect(routeBindings(cg, 'admin/')).toEqual(MEDUSA_BINDINGS); + }); + + it('keeps the routes in the file that writes them', () => { + const home = cg.getNodesByKind('route').find((r) => r.name === '/')!; + expect(home.filePath).toBe('admin/src/dashboard-app/routes/get-route.map.tsx'); + expect(home.startLine).toBe(22); + }); + + it('follows an edit to the table, and drops the routes when the router is handed something else', async () => { + writeFiles(root, { 'admin/src/dashboard-app/routes/get-route.map.tsx': routeMap(ORDERS) }); + await cg.sync(); + expect(routeBindings(cg, 'admin/')).toEqual( + [...MEDUSA_BINDINGS, '/orders -> Orders', '/orders ~> MainLayout', '/orders ~> ProtectedRoute'].sort()); + + writeFiles(root, { 'admin/src/dashboard-app/dashboard-app.tsx': MEDUSA_APP.replace(/getRouteMap\(\{[\s\S]*?\}\);/, '[];') }); + await cg.sync(); + expect(routeNames(cg, 'admin/')).toEqual([]); + + writeFiles(root, { 'admin/src/dashboard-app/dashboard-app.tsx': MEDUSA_APP }); + await cg.sync(); + expect(routeNames(cg, 'admin/')).toEqual(['/', '/login', '/orders', '/products', '/products/create', '/settings']); + }, 60_000); +}); + +describe('react-router: the other ways a call hands the router its table, and what stays no table', () => { + let root: string; + let cg: CodeGraph; + beforeAll(async () => { + ({ root, cg } = await indexProject(SHAPES)); + }, 60_000); + afterAll(() => { + cg?.close(); + if (root) fs.rmSync(root, { recursive: true, force: true }); + }); + + it("reads the table of the `routes` in the router's own scope, never another function's menu", () => { + expect(routeBindings(cg, 'src/scoped/')).toEqual(['/ -> Home', '/account -> Account']); + }); + + it('reads the imported table a use names, past a same-named local in another function', () => { + expect(routeBindings(cg, 'src/shadow/')).toEqual(['/landing -> Landing']); + }); + + it('reads an exported table that a call makes, as a named or a default export', () => { + expect(routeBindings(cg, 'src/exported/')).toEqual(['/dashboard -> Dashboard']); + expect(routeBindings(cg, 'src/default/')).toEqual(['/reports -> Reports']); + }); + + it('reads the table an awaited call returns', () => { + expect(routeBindings(cg, 'src/awaited/')).toEqual(['/me -> Account']); + }); + + it('reads the tables a router file names inside the table its own function returns', () => { + expect(routeBindings(cg, 'src/features/')).toEqual(['/todos -> TodoList']); + expect(routeBindings(cg, 'src/local/')).toEqual(['/home -> Home']); + }); + + it('makes no route of a menu, nor of a table a function computes from data', () => { + const all = cg.getNodesByKind('route').map((r) => r.name); + for (const p of ['/help', '/billing', '/computed']) expect(all).not.toContain(p); + }); +}); diff --git a/__tests__/react-router-outlet-routes.test.ts b/__tests__/react-router-outlet-routes.test.ts new file mode 100644 index 0000000000..3558e2fb0f --- /dev/null +++ b/__tests__/react-router-outlet-routes.test.ts @@ -0,0 +1,206 @@ +/** + * A React Router route that renders `` renders the routes inside it + * and nothing of its own: a route object with no element does exactly that, + * so `element: `, `Component: Outlet` and a `lazy` loader that hands + * back `{ Component: Outlet }` (Medusa's `:id` routes, which import their page + * module only for its `loader` and breadcrumb) are no page and no layout. JSX + * routes already read `element={}` this way. + * + * Before, a route object's `` was its component: every route inside + * it got a `layout:Outlet` reference, which links nothing (the Medusa and + * Mercur dashboards each had 81 such failed refs). And a loader returning + * `{ Component: Outlet }` read as "can't tell", so the route fell back to the + * module the loader imports: its page became the layout of every route + * inside, a detail page drawn around its own sibling routes. + */ +import { describe, it, expect, beforeAll, afterAll } from 'vitest'; +import * as fs from 'fs'; +import * as os from 'os'; +import * as path from 'path'; +import { CodeGraph } from '../src'; + +const page = (name: string, extra = ''): string => + `${extra}export function Component() {\n return
${name}
;\n}\n`; + +const FILES: Record = { + 'package.json': JSON.stringify({ name: 'admin', dependencies: { react: '^18', 'react-router-dom': '^6' } }), + 'src/Shell.tsx': `import { Outlet } from 'react-router-dom';\n\nexport function Shell() {\n return
;\n}\n`, + 'src/router.tsx': `import { createBrowserRouter, Outlet } from 'react-router-dom'; +import { Shell } from './Shell'; + +export const router = createBrowserRouter([ + { + element: , + children: [ + { + path: '/regions', + element: , + children: [ + { path: '', lazy: () => import('./pages/region-list') }, + { path: 'create', lazy: () => import('./pages/region-create') }, + ], + }, + { + path: '/products', + Component: Outlet, + children: [{ index: true, lazy: () => import('./pages/product-list') }], + }, + { + path: '/products/:id', + lazy: async () => { + const { loader } = await import('./pages/product-detail'); + return { Component: Outlet, loader }; + }, + children: [ + { path: '', lazy: () => import('./pages/product-detail') }, + { path: 'variants/:variant_id', lazy: () => import('./pages/variant-detail') }, + ], + }, + { + path: '/orders', + lazy: async () => { + const { loader } = await import('./pages/order-list'); + return { element: , loader }; + }, + children: [ + { index: true, lazy: () => import('./pages/order-list') }, + { path: 'new', lazy: () => import('./pages/order-create') }, + ], + }, + // Addresses the shell draws itself: routes of their own, with no page. + { path: '/approvals', element: }, + { path: '/agents/:agentId', Component: Outlet }, + ], + }, +]); +`, + // React Router's error-boundaries example: a `path: ''` route that renders an + // only to hold an errorElement, at its parent's address. + 'src/errors/router.tsx': `import { createBrowserRouter, Outlet } from 'react-router-dom'; +import { Layout, Project, RootErrorBoundary } from './routes'; + +export const router = createBrowserRouter([ + { + path: '/', + element: , + children: [ + { + path: '', + element: , + errorElement: , + children: [{ path: 'projects/:projectId', element: }], + }, + ], + }, +]); +`, + 'src/errors/routes.tsx': `import { Outlet } from 'react-router-dom'; + +export function Layout() { + return
; +} + +export function Project() { + return
Project
; +} + +export function RootErrorBoundary() { + return
Error
; +} +`, + 'src/Nav.tsx': `import { useNavigate } from 'react-router-dom'; + +export function Nav() { + const navigate = useNavigate(); + const openApprovals = () => navigate('/approvals'); + const openAgent = (id: string) => navigate(\`/agents/\${id}\`); + return ; +} +`, + 'src/pages/region-list.tsx': page('RegionList'), + 'src/pages/region-create.tsx': page('RegionCreate'), + 'src/pages/product-list.tsx': page('ProductList'), + 'src/pages/product-detail.tsx': page('ProductDetail', 'export async function loader() {\n return null;\n}\n\n'), + 'src/pages/variant-detail.tsx': page('VariantDetail'), + 'src/pages/order-list.tsx': page('OrderList', 'export async function loader() {\n return null;\n}\n\n'), + 'src/pages/order-create.tsx': page('OrderCreate'), +}; + +/** `path -> page` for what each route renders, `path ~> layout` for each layout around it; a page is named by its file. */ +function routeBindings(cg: CodeGraph): string[] { + return cg.getNodesByKind('route').flatMap((r) => cg.getOutgoingEdges(r.id) + .filter((e) => e.kind === 'references') + .map((e) => { + const target = cg.getNode(e.target)!; + const name = target.name === 'Component' ? path.basename(target.filePath, '.tsx') : target.name; + return `${r.name} ${(e.metadata as Record | undefined)?.layout ? '~>' : '->'} ${name}`; + })) + .sort(); +} + +describe('react-router: a route that renders renders nothing of its own', () => { + let root: string; + let cg: CodeGraph; + beforeAll(async () => { + root = fs.mkdtempSync(path.join(os.tmpdir(), 'cg-rr-outlet-')); + for (const [rel, content] of Object.entries(FILES)) { + fs.mkdirSync(path.dirname(path.join(root, rel)), { recursive: true }); + fs.writeFileSync(path.join(root, rel), content); + } + cg = await CodeGraph.init(root, { index: true }); + }, 60_000); + afterAll(() => { + cg?.close(); + if (root) fs.rmSync(root, { recursive: true, force: true }); + }); + + it('binds each address to its page, inside the layouts that render something', () => { + expect(routeBindings(cg)).toEqual([ + // The `path: ''` route groups its children at `/`, where Layout stays the page. + '/ -> Layout', + // A route that renders only is still an address: no page, its layouts kept. + '/agents/:agentId ~> Shell', + '/approvals ~> Shell', + '/orders -> order-list', + '/orders ~> Shell', + '/orders/new -> order-create', + '/orders/new ~> Shell', + '/products -> product-list', + '/products ~> Shell', + '/products/:id -> product-detail', + '/products/:id ~> Shell', + // Not inside product-detail: its route hands React Router `Component: Outlet`. + '/products/:id/variants/:variant_id -> variant-detail', + '/products/:id/variants/:variant_id ~> Shell', + '/projects/:projectId -> Project', + '/projects/:projectId ~> Layout', + '/regions -> region-list', + '/regions ~> Shell', + '/regions/create -> region-create', + '/regions/create ~> Shell', + ]); + }); + + it('keeps an address no route inside claims, and the navigation that leads there', () => { + const routes = cg.getNodesByKind('route').map((r) => r.name).sort(); + // `/products/:id`, `/regions` and `/orders` stay single routes: the page inside claims each + // address. So does `/`: the `path: ''` route under Layout is no route of its own. + expect(routes).toEqual([ + '/', '/agents/:agentId', '/approvals', '/orders', '/orders/new', '/products', '/products/:id', + '/products/:id/variants/:variant_id', '/projects/:projectId', '/regions', '/regions/create', + ]); + const navigations = cg.getNodesByKind('route').flatMap((r) => cg.getIncomingEdges(r.id) + .filter((e) => e.kind === 'navigates') + .map((e) => `${cg.getNode(e.source)?.name} -> ${r.name}`)) + .sort(); + expect(navigations).toEqual(['openAgent -> /agents/:agentId', 'openApprovals -> /approvals']); + }); + + it('leaves no route reference to Outlet behind', () => { + const db = (cg as any).db.db; + const refs = db.prepare( + "SELECT reference_name AS name FROM unresolved_refs WHERE from_node_id LIKE 'route:%' AND reference_name IN ('Outlet', 'layout:Outlet')" + ).all() as Array<{ name: string }>; + expect(refs).toEqual([]); + }); +}); diff --git a/__tests__/sync-barrel-renamed-reexport.test.ts b/__tests__/sync-barrel-renamed-reexport.test.ts new file mode 100644 index 0000000000..aa04f0bddd --- /dev/null +++ b/__tests__/sync-barrel-renamed-reexport.test.ts @@ -0,0 +1,182 @@ +/** + * A sync relinks an import that reaches a module through a barrel which passes + * it on under another name, once an edit gives the module what is imported. + * + * matx's `app/components/index.js` says `export { default as MatxLoading } + * from './MatxLoading'`, and `MatxSuspense.jsx` imports `{ MatxLoading }` from + * the barrel. While `MatxLoading.jsx` has no default export, the import and + * the calls through it fail, parked under the name they use: `MatxLoading`. + * When an edit adds `export default function Loading`, a sync retries what + * waits for the names the file now declares (`Loading`) and what waits under + * the barrel's module key, and neither is `MatxLoading`. Only a fresh index + * linked them. The same holds for `export { Spinner as AppSpinner } from`. + * + * When something else in the project is named `MatxLoading`, the import does + * not fail while the module lacks it: a name match takes it there. The edit's + * rebind re-opens the edges into what the file now declares (`Loading`), not + * into another `MatxLoading`, so that edge stayed too (vben's `alert`, which + * its alert barrel passes on from `vbenAlert`, stayed on the `alert.vue` + * component). + * + * The barrel also passes on `Card` under the name `Card.js` declares, which + * the retry by the changed names and the rebind already relink: the fixture + * keeps it so they go on doing so. + */ +import { describe, it, expect, afterEach } from 'vitest'; +import * as fs from 'fs'; +import * as os from 'os'; +import * as path from 'path'; +import CodeGraph from '../src/index'; + +type Files = Record; + +const IMPORTERS: Files = { + 'package.json': JSON.stringify({ name: 'app', dependencies: { react: '^18' } }), + 'src/components/index.js': + "export { default as MatxLoading } from './MatxLoading';\n" + + "export { Spinner as AppSpinner } from './Spinner';\n" + + "export { Card } from './Card';\n", + 'src/components/MatxSuspense.js': + "import { MatxLoading, AppSpinner, Card } from '.';\n" + + 'export function suspense() {\n MatxLoading();\n Card();\n return AppSpinner();\n}\n', +}; + +const MODULES: Files = { + 'src/components/MatxLoading.js': 'export default function Loading() {\n return null;\n}\n', + 'src/components/Spinner.js': 'export function Spinner() {\n return null;\n}\n', + 'src/components/Card.js': 'export function Card() {\n return null;\n}\n', +}; + +/** What a fresh index links from `suspense` through the barrel. */ +const CALLS = [ + 'suspense -> src/components/Card.js::Card', + 'suspense -> src/components/MatxLoading.js::Loading', + 'suspense -> src/components/Spinner.js::Spinner', +]; + +let roots: string[] = []; +let graphs: CodeGraph[] = []; + +afterEach(() => { + for (const graph of graphs) graph.close(); + graphs = []; + for (const root of roots) fs.rmSync(root, { recursive: true, force: true, maxRetries: 5 }); + roots = []; +}); + +function tempRoot(): string { + const root = fs.mkdtempSync(path.join(os.tmpdir(), 'cg-sync-barrel-rename-')); + roots.push(root); + return root; +} + +function write(root: string, files: Files): void { + for (const [file, text] of Object.entries(files)) { + fs.mkdirSync(path.dirname(path.join(root, file)), { recursive: true }); + fs.writeFileSync(path.join(root, file), text); + } +} + +async function index(root: string): Promise { + const graph = await CodeGraph.init(root, { index: true }); + graphs.push(graph); + return graph; +} + +/** Every edge, by its ends' natural keys, with where it is written and how it resolved. */ +function edgesOf(graph: CodeGraph): string[] { + const keys = new Map( + graph.getFiles() + .flatMap((file) => graph.getNodesInFile(file.path)) + .map((n) => [n.id, `${n.kind} ${n.filePath}:${n.qualifiedName}:${n.startLine}`] as const) + ); + return graph.getOutgoingEdgesFrom([...keys.keys()]) + .map((e) => `${e.kind} ${keys.get(e.source)} -> ${keys.get(e.target) ?? e.target} @${e.line}:${e.column} ${JSON.stringify(e.metadata ?? {})}`) + .sort(); +} + +/** The calls `suspense` makes, as `suspense -> ::`. */ +function callsOf(graph: CodeGraph): string[] { + const suspense = graph.getNodesInFile('src/components/MatxSuspense.js').find((n) => n.name === 'suspense'); + if (!suspense) return []; + return graph.getCallees(suspense.id).map((c) => `suspense -> ${c.node.filePath}::${c.node.name}`).sort(); +} + +async function fullIndexOf(files: Files): Promise { + const root = tempRoot(); + write(root, files); + return edgesOf(await index(root)); +} + +describe('sync relinks an import a barrel passes on under another name', () => { + it('when an edit gives the module what is imported', async () => { + const root = tempRoot(); + write(root, IMPORTERS); + write(root, Object.fromEntries(Object.keys(MODULES).map((file) => [file, 'export const placeholder = 1;\n']))); + const graph = await index(root); + expect(callsOf(graph)).toEqual([]); + + write(root, MODULES); + const result = await graph.sync(); + expect(result.filesModified).toBe(Object.keys(MODULES).length); + expect(result.filesAdded).toBe(0); + expect(callsOf(graph)).toEqual(CALLS); + expect(edgesOf(graph)).toEqual(await fullIndexOf({ ...IMPORTERS, ...MODULES })); + }, 120_000); + + it('when the module is added after its importers', async () => { + const root = tempRoot(); + write(root, IMPORTERS); + const graph = await index(root); + expect(callsOf(graph)).toEqual([]); + + write(root, MODULES); + const result = await graph.sync(); + expect(result.filesAdded).toBe(Object.keys(MODULES).length); + expect(callsOf(graph)).toEqual(CALLS); + expect(edgesOf(graph)).toEqual(await fullIndexOf({ ...IMPORTERS, ...MODULES })); + }, 120_000); +}); + +/** Declarations elsewhere named as the barrel passes the modules on. */ +const NAMESAKES: Files = { + 'src/legacy/MatxLoading.js': 'export function MatxLoading() {\n return 1;\n}\n', + 'src/legacy/AppSpinner.js': 'export function AppSpinner() {\n return 1;\n}\n', + 'src/legacy/Card.js': 'export function Card() {\n return 1;\n}\n', +}; + +/** Where a name match takes the imports while the modules lack them. */ +const NAMESAKE_CALLS = [ + 'suspense -> src/legacy/AppSpinner.js::AppSpinner', + 'suspense -> src/legacy/Card.js::Card', + 'suspense -> src/legacy/MatxLoading.js::MatxLoading', +]; + +describe('sync relinks an import a barrel passes on under another name that a namesake took', () => { + it('when an edit gives the module what is imported', async () => { + const root = tempRoot(); + write(root, { ...IMPORTERS, ...NAMESAKES }); + write(root, Object.fromEntries(Object.keys(MODULES).map((file) => [file, 'export const placeholder = 1;\n']))); + const graph = await index(root); + expect(callsOf(graph)).toEqual(NAMESAKE_CALLS); + + write(root, MODULES); + const result = await graph.sync(); + expect(result.filesModified).toBe(Object.keys(MODULES).length); + expect(callsOf(graph)).toEqual(CALLS); + expect(edgesOf(graph)).toEqual(await fullIndexOf({ ...IMPORTERS, ...NAMESAKES, ...MODULES })); + }, 120_000); + + it('when the module is added after its importers', async () => { + const root = tempRoot(); + write(root, { ...IMPORTERS, ...NAMESAKES }); + const graph = await index(root); + expect(callsOf(graph)).toEqual(NAMESAKE_CALLS); + + write(root, MODULES); + const result = await graph.sync(); + expect(result.filesAdded).toBe(Object.keys(MODULES).length); + expect(callsOf(graph)).toEqual(CALLS); + expect(edgesOf(graph)).toEqual(await fullIndexOf({ ...IMPORTERS, ...NAMESAKES, ...MODULES })); + }, 120_000); +}); diff --git a/__tests__/sync-import-retry-crowded-key.test.ts b/__tests__/sync-import-retry-crowded-key.test.ts new file mode 100644 index 0000000000..d315aa5f1b --- /dev/null +++ b/__tests__/sync-import-retry-crowded-key.test.ts @@ -0,0 +1,129 @@ +/** + * A sync links an import of a file that appears later, even when the key the + * import waits under is one a popular import shares. + * + * Sync looks a failed import up by what an added file can be imported as — its + * name, its stem, its folder — and skips a key more than 500 failed imports + * share, as noise one file cannot answer. But a path import is parked under + * its path's stem, which a package's imports share with every file of that + * name: `utils` is the stem of every `jotai/utils` and `@scope/pkg/utils` as + * much as of a project's own `./utils`, and `assert` the name of every + * binding of `import * as assert from 'assert'`. In a large project those + * crowded the key past the ceiling, so the project's own `utils.ts`, added + * after its importers were indexed or restored after a delete, never linked + * until the importers changed or the project was re-indexed. + */ +import { describe, it, expect, afterEach } from 'vitest'; +import * as fs from 'fs'; +import * as os from 'os'; +import * as path from 'path'; +import CodeGraph from '../src/index'; + +interface Case { + name: string; + initial: Record; + added: Record; + /** `imports` edges the sync must make: ` -> `. */ + expected: string[]; +} + +/** One file importing `count` package modules whose paths all end in `/utils`. */ +function packageUtils(count: number): string { + return Array.from({ length: count }, (_, i) => `import 'kit${i}/utils';\n`).join(''); +} + +const CASES: Case[] = [ + { + name: "a project's utils.ts among package subpaths named utils", + initial: { + 'package.json': JSON.stringify({ name: 'app', dependencies: Object.fromEntries(Array.from({ length: 520 }, (_, i) => [`kit${i}`, '1.0.0'])) }), + 'src/vendor.ts': packageUtils(520), + 'src/settings/view.ts': "import { format } from './utils';\nexport const view = () => format();\n", + 'src/settings/panel/list.ts': "import { format } from '../utils';\nexport const list = () => format();\n", + }, + added: { 'src/settings/utils.ts': "export function format() { return ''; }\n" }, + expected: [ + 'src/settings/view.ts -> file src/settings/utils.ts', + 'src/settings/panel/list.ts -> file src/settings/utils.ts', + ], + }, + { + name: "a project's assert.ts among bindings of the assert package", + initial: { + 'package.json': JSON.stringify({ name: 'app', devDependencies: { assert: '2.0.0' } }), + // Each statement is a module reference to the package and a binding, + // both waiting under `assert`: 520 in all. + 'test/all.test.ts': Array.from({ length: 260 }, () => "import * as assert from 'assert';\n").join('') + 'assert.ok(true);\n', + 'src/common/strings.ts': "import { ok } from './assert';\nexport const check = (s: string) => ok(s.length > 0);\n", + }, + added: { 'src/common/assert.ts': 'export function ok(value: boolean) { return value; }\n' }, + expected: ['src/common/strings.ts -> file src/common/assert.ts'], + }, + { + // bitwarden imports its `account.service` from 724 files: not noise at all. + name: 'a file more than 500 imports name', + initial: Object.fromEntries(Array.from({ length: 510 }, (_, i) => [ + `src/features/f${i}.ts`, + `import { format } from '../shared/utils';\nexport const f${i} = () => format();\n`, + ])), + added: { 'src/shared/utils.ts': "export function format() { return ''; }\n" }, + expected: ['src/features/f0.ts -> file src/shared/utils.ts', 'src/features/f509.ts -> file src/shared/utils.ts'], + }, +]; + +const roots: string[] = []; +const graphs: CodeGraph[] = []; + +afterEach(() => { + // Close before removing: a held database makes the unlink EBUSY on Windows. + for (const graph of graphs.splice(0)) graph.destroy(); + for (const dir of roots.splice(0)) fs.rmSync(dir, { recursive: true, force: true }); +}); + +function tempRoot(): string { + const dir = fs.mkdtempSync(path.join(os.tmpdir(), 'cg-crowded-key-')); + roots.push(dir); + return dir; +} + +function write(root: string, files: Record): void { + for (const [rel, content] of Object.entries(files)) { + fs.mkdirSync(path.dirname(path.join(root, rel)), { recursive: true }); + fs.writeFileSync(path.join(root, rel), content); + } +} + +/** Every `imports` edge between two files of the project: ` -> `. */ +function fileImports(graph: CodeGraph): string[] { + const edges = new Set(); + for (const file of graph.getFiles()) { + const ids = graph.getNodesInFile(file.path).map((n) => n.id); + for (const edge of graph.getOutgoingEdgesFrom(ids, ['imports'])) { + const target = graph.getNode(edge.target); + if (target && target.filePath !== file.path) edges.add(`${file.path} -> ${target.kind} ${target.filePath}`); + } + } + return [...edges].sort(); +} + +describe('sync links an import under a key a popular import crowds', () => { + it.each(CASES)('$name', async (c) => { + const root = tempRoot(); + write(root, c.initial); + const graph = await CodeGraph.init(root, { index: true }); + graphs.push(graph); + for (const edge of c.expected) expect(fileImports(graph)).not.toContain(edge); + + write(root, c.added); + expect((await graph.sync()).filesAdded).toBe(Object.keys(c.added).length); + const synced = fileImports(graph); + expect(synced).toEqual(expect.arrayContaining(c.expected)); + + // A fresh index of the same tree, in a folder of its own, links the same. + const fresh = tempRoot(); + write(fresh, { ...c.initial, ...c.added }); + const oracle = await CodeGraph.init(fresh, { index: true }); + graphs.push(oracle); + expect(synced).toEqual(fileImports(oracle)); + }, 120_000); +}); diff --git a/__tests__/sync-import-retry.test.ts b/__tests__/sync-import-retry.test.ts index 04b093ca17..f1d372e10b 100644 --- a/__tests__/sync-import-retry.test.ts +++ b/__tests__/sync-import-retry.test.ts @@ -81,6 +81,17 @@ const CASES: Case[] = [ from: 'a.js', expected: ['file side.js', 'file def.js', 'file req.js', 'file lib/index.js'], }, + { + // A folder further up than the one above names it only through where it + // is written, so it waits under no key of the file that appears. + name: 'TypeScript (a folder further up)', + initial: { + 'src/a/b/c/m.ts': "import { x } from '../..';\nimport { y } from '../../';\nimport { z } from '../../..';\nexport const v = [x, y, z];\n", + }, + added: { 'src/a/index.ts': 'export const x = 1;\nexport const y = 2;\n', 'src/index.ts': 'export const z = 3;\n' }, + from: 'src/a/b/c/m.ts', + expected: ['file src/a/index.ts', 'file src/index.ts'], + }, { name: 'C', initial: { 'src/main.c': '#include "a/b.h"\n#include "c.h"\n#include \nint main(void) { return 0; }\n' }, @@ -362,6 +373,20 @@ describe('getRetryableFailedImports', () => { expect(names(queries.getRetryableFailedImports(['b', 'b.dart'], [], 2))).toEqual(['b.dart']); expect(queries.getRetryableFailedImports(['b'], [], 3)).toHaveLength(3); }); + + it('looks a key past the ceiling through for the imports that could name an added file', () => { + const queries = setup(); + const only = (...accepted: string[]) => (ref: { referenceName: string }) => accepted.includes(ref.referenceName); + // Three imports wait under `b`, one more than the ceiling. + expect(names(queries.getRetryableFailedImports(['b'], [], 2, [], undefined, only('../b.dart')))).toEqual(['../b.dart']); + // What the test accepts is no noise: the module ceiling holds it. + expect(names(queries.getRetryableFailedImports(['b'], [], 1, [], 2, only('../b.dart', 'src/b.dart')))).toEqual(['../b.dart', 'src/b.dart']); + expect(queries.getRetryableFailedImports(['b'], [], 1, [], 1, only('../b.dart', 'src/b.dart'))).toEqual([]); + // A key within the ceiling is retried whole, whatever the test says. + expect(queries.getRetryableFailedImports(['b'], [], 3, [], undefined, only())).toHaveLength(3); + // A namespace waits for its node, not a file: the test is not asked. + expect(names(queries.getRetryableFailedImports([], ['Foo.Bar'], 0, [], undefined, only('Foo.Bar')))).toEqual([]); + }); }); describe('schema v18', () => { @@ -420,6 +445,9 @@ describe('schema v18', () => { const prepare = vi.spyOn(db!.getDb(), 'prepare'); // The fixture's tails are old ones: `dart` finds a row by tail, `c.h` by name. expect(queries.getRetryableFailedImports(['dart', 'c.h'], ['Foo.Bar'])).toHaveLength(2); + // A key past the ceiling is read whole for `couldName` to look through: at + // a ceiling of 0 both keys are, and what it accepts is retried. + expect(queries.getRetryableFailedImports(['dart', 'c.h'], [], 0, [], undefined, () => true)).toHaveLength(2); const lookups = prepare.mock.calls.map(([sql]) => sql as string).filter((sql) => sql.includes("reference_kind = 'imports'")); prepare.mockRestore(); expect(lookups.length).toBeGreaterThan(0); diff --git a/__tests__/sync-typed-local-member-retry.test.ts b/__tests__/sync-typed-local-member-retry.test.ts new file mode 100644 index 0000000000..a49a184d80 --- /dev/null +++ b/__tests__/sync-typed-local-member-retry.test.ts @@ -0,0 +1,235 @@ +/** + * A sync links a member call on a local typed by an imported class once the + * class's module appears. + * + * `const cache = new LRUCache(2)` after `import { LRUCache } + * from './lru-cache'`, then `cache.get(key)`: a fresh index reads the local's + * declaration and links the call to `LRUCache.get` (folo's lru-cache tests, + * milo-ui's `astCache.get`). The same holds for an annotated local, a typed + * parameter and a class imported by default or through a namespace. While the + * module was missing or empty the call failed, and it was parked under its + * member's name, `get`, which more failed calls share than the retry's + * ceiling: a sync that brought the class back never retried it. + * + * Such a call is now parked under the key of the module the type's binding + * imports, as #2630 parks a member of the binding itself, and keeps its + * member's name as a key under that name's ceiling. + */ +import { describe, it, expect, afterEach } from 'vitest'; +import * as fs from 'fs'; +import * as os from 'os'; +import * as path from 'path'; +import CodeGraph from '../src/index'; +import { DatabaseConnection, getDatabasePath } from '../src/db'; + +type Files = Record; + +/** 501 failed `get` calls on a receiver nothing declares: `get` is past the retry's ceiling. */ +const NOISE = `export function noise() {\n${Array.from({ length: 501 }, (_, i) => ` extApi.get(${i});`).join('\n')}\n}\n`; + +/** The files that call members of locals typed by a class they import. */ +const CALLERS: Files = { + 'package.json': JSON.stringify({ name: 'app' }), + 'src/use-new.ts': "import { LRUCache } from './lru-cache';\nexport function a() {\n const cache = new LRUCache(10);\n cache.set('k', 1);\n return cache.get('k');\n}\n", + 'src/use-annotated.ts': "import { LRUCache } from './lru-cache';\nexport function b(make: () => LRUCache) {\n const cache: LRUCache = make();\n return cache.get('k');\n}\n", + 'src/use-param.ts': "import { LRUCache } from './lru-cache';\nexport function c(cache: LRUCache) {\n return cache.get('k');\n}\n", + 'src/use-namespace.ts': "import * as lib from './lru-cache';\nexport function g() {\n const cache = new lib.LRUCache(3);\n return cache.get('k');\n}\n", + 'src/use-default.ts': "import Store from './store';\nexport function e() {\n const s = new Store();\n return s.get();\n}\n", + // A call on an element that shares the array's name: the element's class. + 'src/use-each.ts': "import { LRUCache } from './lru-cache';\nexport function h(cs: LRUCache[]) {\n cs.forEach((cs) => cs.get('k'));\n}\n", + // One of the class's properties, which resolution reads as the class. + 'src/use-prop.ts': "import { LRUCache } from './lru-cache';\nexport function i(max: LRUCache['max']) {\n return max.toFixed(0);\n}\n", + 'src/noise.ts': NOISE, +}; + +const MODULES: Files = { + 'src/lru-cache.ts': 'export class LRUCache {\n constructor(private max: number) {}\n get(key: K): V | undefined { return undefined; }\n set(key: K, value: V) { return this; }\n}\n', + 'src/store.ts': 'export default class Store {\n get() { return 1; }\n}\n', +}; + +/** What a full index links: `: -> ::`. */ +const LINKS = [ + 'cache.get: calls src/use-annotated.ts -> method src/lru-cache.ts::LRUCache::get', + 'cache.get: calls src/use-namespace.ts -> method src/lru-cache.ts::LRUCache::get', + 'cache.get: calls src/use-new.ts -> method src/lru-cache.ts::LRUCache::get', + 'cache.get: calls src/use-param.ts -> method src/lru-cache.ts::LRUCache::get', + 'cache.set: calls src/use-new.ts -> method src/lru-cache.ts::LRUCache::set', + 'cs.get: calls src/use-each.ts -> method src/lru-cache.ts::LRUCache::get', + 's.get: calls src/use-default.ts -> method src/store.ts::Store::get', +]; + +let roots: string[] = []; +let graphs: CodeGraph[] = []; + +afterEach(() => { + for (const graph of graphs) graph.close(); + graphs = []; + for (const root of roots) fs.rmSync(root, { recursive: true, force: true }); + roots = []; +}); + +function tempRoot(): string { + const root = fs.mkdtempSync(path.join(os.tmpdir(), 'cg-sync-typed-local-')); + roots.push(root); + return root; +} + +function write(root: string, files: Files): void { + for (const [file, text] of Object.entries(files)) { + fs.mkdirSync(path.dirname(path.join(root, file)), { recursive: true }); + fs.writeFileSync(path.join(root, file), text); + } +} + +async function index(root: string): Promise { + const graph = await CodeGraph.init(root, { index: true }); + graphs.push(graph); + return graph; +} + +/** Every edge, by its ends' natural keys, with where it is written and how it resolved. */ +function edgesOf(graph: CodeGraph): string[] { + const keys = new Map( + graph.getFiles() + .flatMap((file) => graph.getNodesInFile(file.path)) + .map((n) => [n.id, `${n.kind} ${n.filePath}:${n.qualifiedName}:${n.startLine}`] as const) + ); + return graph.getOutgoingEdgesFrom([...keys.keys()]) + .map((e) => `${e.kind} ${keys.get(e.source)} -> ${keys.get(e.target) ?? e.target} @${e.line}:${e.column} ${JSON.stringify(e.metadata ?? {})}`) + .sort(); +} + +/** The calls on a lowercase local's member (`cache.get`): `: -> ::`. */ +function localMemberLinksOf(graph: CodeGraph): string[] { + const ids = graph.getFiles().flatMap((file) => graph.getNodesInFile(file.path)).map((n) => n.id); + const links: string[] = []; + for (const edge of graph.getOutgoingEdgesFrom(ids, ['calls'])) { + const ref = edge.metadata?.refName; + if (typeof ref !== 'string' || !/^[a-z]\w*\.\w+$/.test(ref) || ref.startsWith('extApi.')) continue; + const source = graph.getNode(edge.source)!; + const target = graph.getNode(edge.target)!; + links.push(`${ref}: ${edge.kind} ${source.filePath} -> ${target.kind} ${target.filePath}::${target.qualifiedName}`); + } + return [...new Set(links)].sort(); +} + +/** The final tree, indexed from scratch in a folder of its own: what the sync has to match. */ +async function fullIndexOf(files: Files): Promise { + const root = tempRoot(); + write(root, files); + return edgesOf(await index(root)); +} + +describe('sync links a member call on a local typed by an imported class', () => { + it('when the class\'s module is added after the callers', async () => { + const root = tempRoot(); + write(root, CALLERS); + const graph = await index(root); + expect(localMemberLinksOf(graph)).toEqual([]); + + write(root, MODULES); + const result = await graph.sync(); + // The callers did not change: only the retry of their parked refs links them. + expect(result.filesAdded).toBe(Object.keys(MODULES).length); + expect(result.filesModified).toBe(0); + expect(localMemberLinksOf(graph)).toEqual(LINKS); + expect(edgesOf(graph)).toEqual(await fullIndexOf({ ...CALLERS, ...MODULES })); + expect(graph.getPendingReferenceCount()).toBe(0); + }, 120_000); + + it('when the class\'s module comes back after it was deleted', async () => { + const root = tempRoot(); + write(root, { ...CALLERS, ...MODULES }); + const graph = await index(root); + expect(localMemberLinksOf(graph)).toEqual(LINKS); + + for (const file of Object.keys(MODULES)) fs.rmSync(path.join(root, file)); + expect((await graph.sync()).filesRemoved).toBe(Object.keys(MODULES).length); + expect(localMemberLinksOf(graph)).toEqual([]); + + write(root, MODULES); + expect((await graph.sync()).filesAdded).toBe(Object.keys(MODULES).length); + expect(localMemberLinksOf(graph)).toEqual(LINKS); + expect(edgesOf(graph)).toEqual(await fullIndexOf({ ...CALLERS, ...MODULES })); + }, 120_000); + + it('when an edit gives the module the class', async () => { + const root = tempRoot(); + write(root, CALLERS); + write(root, Object.fromEntries(Object.keys(MODULES).map((file) => [file, 'export const placeholder = 1;\n']))); + const graph = await index(root); + + write(root, MODULES); + const result = await graph.sync(); + expect(result.filesModified).toBe(Object.keys(MODULES).length); + expect(result.filesAdded).toBe(0); + expect(localMemberLinksOf(graph)).toEqual(LINKS); + expect(edgesOf(graph)).toEqual(await fullIndexOf({ ...CALLERS, ...MODULES })); + }, 120_000); +}); + +describe('a failed member call on a typed local', () => { + it('waits for the module of the class its declaration imports, and every other one keeps its own tail', async () => { + const root = tempRoot(); + write(root, { + ...CALLERS, + // A local of a built-in type, of a package's, of a type the file + // declares itself and one a factory returns: none waits for a module of + // the project. Nor does a local or a parameter declared as an array of + // an imported class, whose array methods are the array's, or a method of + // `this` passed as a value, which resolution looks up in the enclosing + // class, whatever `this` is declared as. + 'src/other.ts': + "import { createCache, LRUCache } from './factory';\n" + + "import QuickLRU from 'quick-lru';\n" + + 'class Local { get() { return 1; } }\n' + + 'export function run() {\n' + + ' const seen = new Map();\n' + + " seen.get('k');\n" + + ' const pkg = new QuickLRU();\n' + + " pkg.get('k');\n" + + ' const mine: Local = new Local();\n' + + ' mine.peek();\n' + + ' const made = createCache();\n' + + " made.get('k');\n" + + ' const caches: LRUCache[] = [];\n' + + ' caches.push(made);\n' + + '}\n' + + 'export function each(all: LRUCache[]) {\n' + + ' return all.map((c) => c);\n' + + '}\n' + + 'export function bound(this: LRUCache) {\n' + + " return ['k'].map(this.peek);\n" + + '}\n', + }); + (await CodeGraph.init(root, { index: true })).close(); + + const db = DatabaseConnection.open(getDatabasePath(root)); + try { + const rows = db.getDb() + .prepare("SELECT reference_name AS name, file_path AS file, name_tail AS tail FROM unresolved_refs WHERE status = 'failed' AND reference_kind IN ('calls', 'function_ref')") + .all() as Array<{ name: string; file: string; tail: string }>; + const tails = (file: string, name: string) => [...new Set(rows.filter((r) => r.file === file && r.name === name).map((r) => r.tail))]; + + expect(tails('src/use-new.ts', 'cache.get')).toEqual(['module:lru-cache']); + expect(tails('src/use-new.ts', 'cache.set')).toEqual(['module:lru-cache']); + expect(tails('src/use-annotated.ts', 'cache.get')).toEqual(['module:lru-cache']); + expect(tails('src/use-param.ts', 'cache.get')).toEqual(['module:lru-cache']); + expect(tails('src/use-namespace.ts', 'cache.get')).toEqual(['module:lru-cache']); + expect(tails('src/use-default.ts', 's.get')).toEqual(['module:store']); + expect(tails('src/use-each.ts', 'cs.get')).toEqual(['module:lru-cache']); + expect(tails('src/use-each.ts', 'cs.forEach')).toEqual(['forEach']); + expect(tails('src/use-prop.ts', 'max.toFixed')).toEqual(['module:lru-cache']); + + expect(tails('src/other.ts', 'seen.get')).toEqual(['get']); + expect(tails('src/other.ts', 'pkg.get')).toEqual(['get']); + expect(tails('src/other.ts', 'mine.peek')).toEqual(['peek']); + expect(tails('src/other.ts', 'made.get')).toEqual(['get']); + expect(tails('src/other.ts', 'caches.push')).toEqual(['push']); + expect(tails('src/other.ts', 'all.map')).toEqual(['map']); + expect(tails('src/other.ts', 'this.peek')).toEqual(['peek']); + } finally { + db.close(); + } + }, 60_000); +}); diff --git a/__tests__/ts-abstract-methods.test.ts b/__tests__/ts-abstract-methods.test.ts new file mode 100644 index 0000000000..ac7aaddb70 --- /dev/null +++ b/__tests__/ts-abstract-methods.test.ts @@ -0,0 +1,84 @@ +/** + * A TypeScript abstract method (`abstract send(path: string): Promise;`) + * is indexed as a method of its class, as an interface's method signature is. + * + * Neither extractor read `abstract_method_signature`, so an abstract class + * used as a dependency-injection token, like bitwarden's `abstract class + * ApiService` in `libs/common/src/abstractions`, had none of its methods in + * the graph. A call through a field of that type then linked to whichever + * class of the same name declared the method, such as the browser app's + * `I18nService` for a library's `this.i18nService.t()`. + * + * Runs against the native kernel (when built) and the wasm extractor, which + * must agree. + */ +import { describe, it, expect, beforeEach, afterEach } from 'vitest'; +import * as fs from 'fs'; +import * as os from 'os'; +import * as path from 'path'; +import { CodeGraph } from '../src'; + +const FILES: Record = { + 'package.json': JSON.stringify({ name: 'app' }), + 'src/abstractions/api.service.ts': + 'export abstract class ApiService {\n' + + ' abstract send(method: string, path: string): Promise;\n' + + ' protected abstract nativeFetch(request: Request): Promise;\n' + + ' ping() {\n return 1;\n }\n' + + '}\n', + 'src/services/api.service.ts': + "import { ApiService as ApiServiceAbstraction } from '../abstractions/api.service';\n" + + 'export class ApiService implements ApiServiceAbstraction {\n' + + ' send(method: string, path: string) {\n return Promise.resolve(method + path);\n }\n' + + ' nativeFetch(request: Request) {\n return fetch(request);\n }\n' + + ' ping() {\n return 2;\n }\n' + + '}\n', + 'src/app/sync.ts': + "import { ApiService } from '../abstractions/api.service';\n" + + 'export class SyncService {\n' + + ' constructor(private readonly apiService: ApiService) {}\n' + + " run() {\n return this.apiService.send('GET', '/sync');\n }\n" + + '}\n', +}; + +describe('a TypeScript abstract method', () => { + let root = ''; + let cg: CodeGraph | undefined; + let kernel: string | undefined; + + beforeEach(() => { + root = fs.mkdtempSync(path.join(os.tmpdir(), 'cg-ts-abstract-methods-')); + for (const [rel, content] of Object.entries(FILES)) { + fs.mkdirSync(path.dirname(path.join(root, rel)), { recursive: true }); + fs.writeFileSync(path.join(root, rel), content); + } + kernel = process.env.CODEGRAPH_KERNEL; + }); + + afterEach(() => { + cg?.close(); + cg = undefined; + fs.rmSync(root, { recursive: true, force: true }); + if (kernel === undefined) delete process.env.CODEGRAPH_KERNEL; + else process.env.CODEGRAPH_KERNEL = kernel; + }); + + it.each(['default', 'wasm'])('is a method of its class, and what a call through the abstract type links to (%s)', async (backend) => { + if (backend === 'wasm') process.env.CODEGRAPH_KERNEL = '0'; + else delete process.env.CODEGRAPH_KERNEL; + cg = await CodeGraph.init(root, { index: true }); + const graph = cg; + const declared = graph.getNodesInFile('src/abstractions/api.service.ts') + .filter((n) => n.kind === 'method' || n.kind === 'function') + .map((n) => `${n.kind} ${n.qualifiedName}`) + .sort(); + expect(declared).toEqual(['method ApiService::nativeFetch', 'method ApiService::ping', 'method ApiService::send']); + + const run = graph.getNodesInFile('src/app/sync.ts').find((n) => n.qualifiedName === 'SyncService::run')!; + const calls = graph.getOutgoingEdgesFrom([run.id], ['calls']).map((e) => { + const target = graph.getNode(e.target)!; + return `${target.filePath}::${target.qualifiedName}`; + }); + expect(calls).toEqual(['src/abstractions/api.service.ts::ApiService::send']); + }, 60_000); +}); diff --git a/__tests__/ts-array-annotated-receivers.test.ts b/__tests__/ts-array-annotated-receivers.test.ts new file mode 100644 index 0000000000..cd3aabfdb4 --- /dev/null +++ b/__tests__/ts-array-annotated-receivers.test.ts @@ -0,0 +1,309 @@ +/** + * A call on a TypeScript local or parameter annotated as an array of a class + * is the array's method, not the class's. + * + * `items: Item[]` was read as an `Item`, because the annotation's capture + * stopped at `[`, so `items.find(…)` linked to `Item.find` whenever the class + * declares a method of that name: on vscode, `distinctElements.find(…)` on + * an `ExplorerItem[]` reached `ExplorerItem.find`, and `ranges.map(…)` on an + * `OffsetRange[]` reached `OffsetRange.map`. A method arrays don't have can + * only be called on an element that shares the array's name, as in + * `d.forEach(d => d.dispose())`, and that one keeps the element's type. + * + * A local annotated as one of a type's properties (`editor: + * IChatWidget['inputEditor']`) was read as that type too, so its calls + * reached the type's methods of the same name, or none. It has the type the + * property is declared with, an array of it the same way; one whose type + * isn't written in the project (`Parameters[0]`) links to nothing, + * and the call isn't matched by its name either. + */ +import { describe, it, expect, afterEach } from 'vitest'; +import * as fs from 'fs'; +import * as os from 'os'; +import * as path from 'path'; +import CodeGraph from '../src/index'; + +let roots: string[] = []; +let graphs: CodeGraph[] = []; + +afterEach(() => { + for (const graph of graphs) graph.close(); + graphs = []; + for (const root of roots) fs.rmSync(root, { recursive: true, force: true }); + roots = []; +}); + +/** Index `files` and return each call edge as ` -> `. */ +async function callsOf(files: Record, withFiles = false): Promise { + const root = fs.mkdtempSync(path.join(os.tmpdir(), 'cg-ts-array-recv-')); + roots.push(root); + for (const [file, text] of Object.entries(files)) { + fs.mkdirSync(path.dirname(path.join(root, file)), { recursive: true }); + fs.writeFileSync(path.join(root, file), text); + } + const graph = await CodeGraph.init(root, { index: true }); + graphs.push(graph); + const nodes = graph.getFiles().flatMap((f) => graph.getNodesInFile(f.path)); + const byId = new Map(nodes.map((n) => [n.id, n])); + return graph.getOutgoingEdgesFrom(nodes.map((n) => n.id), ['calls']) + .map((e) => { + const source = byId.get(e.source); + const target = byId.get(e.target); + return withFiles + ? `${source?.filePath}: ${e.metadata?.refName} -> ${target?.filePath}::${target?.qualifiedName}` + : `${e.metadata?.refName} -> ${target?.qualifiedName}`; + }) + .sort(); +} + +const CLASSES = { + 'package.json': JSON.stringify({ name: 'app' }), + 'src/item.ts': + 'export class Item {\n' + + ' find(key: string) { return key; }\n' + + ' push(value: number) { return value; }\n' + + ' flush() { return 0; }\n' + + '}\n' + + 'export class Repository {\n' + + ' save(value: T) { return value; }\n' + + ' find(id: string) { return id; }\n' + + '}\n', + // The one project method named `findLast`, on an unrelated class. + 'src/stack.ts': 'export class Stack {\n findLast() { return 1; }\n}\n', +}; + +describe('a call on a TypeScript local annotated as an array of a class', () => { + it('links to no method of the element class', async () => { + const calls = await callsOf({ + ...CLASSES, + 'src/use.ts': + "import { Item } from './item';\n" + + 'export function first(items: Item[]) {\n' + + " return items.find((i) => i !== undefined);\n" + + '}\n' + + 'export function fill() {\n' + + ' const list: Item[] = [];\n' + + ' list.push(new Item());\n' + + ' return list;\n' + + '}\n' + + 'export function spaced(all: Item [], grid: Item[][]) {\n' + + " all.find((i) => i !== undefined);\n" + + ' return grid.push([]);\n' + + '}\n', + }); + expect(calls.filter((c) => /^(items|list|all|grid)\./.test(c))).toEqual([]); + }, 60_000); + + it("is not matched to another class's method by the call's name instead", async () => { + const calls = await callsOf({ + ...CLASSES, + 'src/use.ts': + "import { Item } from './item';\n" + + 'export function last(all: Item[]) {\n' + + ' return all.findLast((i) => i !== undefined);\n' + + '}\n', + }); + expect(calls.filter((c) => c.startsWith('all.'))).toEqual([]); + }, 60_000); + + it('does the same for an array of a generic class', async () => { + const calls = await callsOf({ + ...CLASSES, + 'src/use.ts': + "import { Repository } from './item';\n" + + 'export function saveAll(repos: Repository[], value: string) {\n' + + ' repos.forEach((r) => r.save(value));\n' + + " return repos.find((r) => r !== undefined);\n" + + '}\n', + }); + expect(calls.filter((c) => c.startsWith('repos.'))).toEqual([]); + }, 60_000); + + it("still links a method arrays don't have to the element's class: the call is on an element of the same name", async () => { + // vscode's `d.forEach(d => d.dispose())` on an `IDisposable[]`, and + // `extensions.map(extensions => extensions.syncInstalledExtensionsWithGallery(…))`. + const calls = await callsOf({ + ...CLASSES, + 'src/use.ts': + "import { Item } from './item';\n" + + 'export function flushAll(d: Item[]) {\n' + + ' d.forEach((d) => d.flush());\n' + + '}\n', + }); + expect(calls.filter((c) => c.startsWith('d.'))).toEqual(['d.flush -> Item::flush']); + }, 60_000); + + it('still links a call on a local annotated as the class, generic or not', async () => { + const calls = await callsOf({ + ...CLASSES, + 'src/use.ts': + "import { Item, Repository } from './item';\n" + + 'export function one(item: Item, repo: Repository) {\n' + + " repo.find('x');\n" + + " return item.find('k');\n" + + '}\n', + }); + expect(calls).toEqual(['item.find -> Item::find', 'repo.find -> Repository::find']); + }, 60_000); +}); + +describe("a call on a TypeScript local annotated as one of a type's properties", () => { + it('links to the method of the type that property is declared with', async () => { + // vscode's `editor: IChatWidget['inputEditor']`, then `editor.executeEdits(…)`. + const calls = await callsOf({ + ...CLASSES, + 'src/widget.ts': + 'export class CodeEditor {\n executeEdits() { return true; }\n}\n' + + 'export interface Widget {\n readonly inputEditor: CodeEditor;\n}\n' + + // Another `executeEdits`, so the method's name alone picks neither. + 'export class DiffEditor {\n executeEdits() { return false; }\n}\n', + 'src/use.ts': + "import { Widget } from './widget';\n" + + "export function edit(ed: Widget['inputEditor']) {\n" + + ' return ed.executeEdits();\n' + + '}\n', + }); + expect(calls.filter((c) => c.startsWith('ed.'))).toEqual(['ed.executeEdits -> CodeEditor::executeEdits']); + }, 60_000); + + it('links to that type rather than to a method of the type it indexes', async () => { + // vscode's `visibility: ISessionChatPillVisibilityService['pullRequests']`, + // then `visibility.isVisible(…)`, which reached the service's own `isVisible`. + const calls = await callsOf({ + ...CLASSES, + 'src/service.ts': + 'export class Visibility {\n isVisible() { return true; }\n}\n' + + 'export class VisibilityService {\n readonly pullRequests: Visibility = new Visibility();\n isVisible() { return false; }\n}\n', + 'src/use.ts': + "import { VisibilityService } from './service';\n" + + "export function shown(visibility: VisibilityService['pullRequests']) {\n" + + ' return visibility.isVisible();\n' + + '}\n', + }); + expect(calls.filter((c) => c.startsWith('visibility.'))).toEqual(['visibility.isVisible -> Visibility::isVisible']); + }, 60_000); + + it("links to nothing when the property's type lacks the method, not to a guess", async () => { + // The property is declared as an intersection, whose head names no + // `isVisible`: neither the indexed type's own method nor one found by + // the receiver's name, like `VisibilityService.isVisible`, is the call's. + const calls = await callsOf({ + ...CLASSES, + 'src/service.ts': + 'export interface Filter {\n showAll(): boolean;\n}\n' + + 'export class VisibilityService {\n readonly pullRequests!: Filter & { isVisible(): boolean };\n isVisible() { return false; }\n}\n', + 'src/use.ts': + "import { VisibilityService } from './service';\n" + + "export function shown(visibility: VisibilityService['pullRequests']) {\n" + + ' return visibility.isVisible();\n' + + '}\n', + }); + expect(calls.filter((c) => c.startsWith('visibility.'))).toEqual([]); + }, 60_000); + + it("links an array property's own methods to nothing", async () => { + // excalidraw's `groupIds: ExcalidrawElement["groupIds"]`, then `groupIds.filter(…)`. + const calls = await callsOf({ + ...CLASSES, + 'src/element.ts': 'export class Element {\n groupIds: string[] = [];\n filter() { return this; }\n}\n', + 'src/use.ts': + "import { Element } from './element';\n" + + "export function without(groupIds: Element['groupIds'], id: string) {\n" + + ' return groupIds.filter((g) => g !== id);\n' + + '}\n', + }); + expect(calls.filter((c) => c.startsWith('groupIds.'))).toEqual([]); + }, 60_000); + + it("links to the class the property's file imports, when several share its name", async () => { + // vscode's `disposables: ComponentFixtureContext['disposableStore']` + // reached copilot's vendored `DisposableStore`, not the one the + // fixture context's file imports. + const editors = { + 'src/one/editor.ts': 'export class CodeEditor {\n executeEdits() { return 1; }\n}\n', + 'src/two/editor.ts': 'export class CodeEditor {\n executeEdits() { return 2; }\n}\n', + }; + const calls = await callsOf({ + ...CLASSES, + ...editors, + 'src/widget-one.ts': "import { CodeEditor } from './one/editor';\nexport interface WidgetOne {\n readonly inputEditor: CodeEditor;\n}\n", + 'src/widget-two.ts': "import { CodeEditor } from './two/editor';\nexport interface WidgetTwo {\n readonly inputEditor: CodeEditor;\n}\n", + 'src/use-one.ts': + "import { WidgetOne } from './widget-one';\n" + + "export function edit(ed: WidgetOne['inputEditor']) {\n return ed.executeEdits();\n}\n", + 'src/use-two.ts': + "import { WidgetTwo } from './widget-two';\n" + + "export function edit(ed: WidgetTwo['inputEditor']) {\n return ed.executeEdits();\n}\n", + }, true); + expect(calls.filter((c) => c.includes('ed.'))).toEqual([ + 'src/use-one.ts: ed.executeEdits -> src/one/editor.ts::CodeEditor::executeEdits', + 'src/use-two.ts: ed.executeEdits -> src/two/editor.ts::CodeEditor::executeEdits', + ]); + }, 60_000); + + it('reads the property off the indexed type the call\'s file imports, and a class its file declares', async () => { + // Two `Widget`s, each declaring its own `CodeEditor` beside it. + const widget = (n: number) => + `export class CodeEditor {\n executeEdits() { return ${n}; }\n}\n` + + 'export interface Widget {\n readonly inputEditor: CodeEditor;\n}\n'; + const calls = await callsOf({ + ...CLASSES, + 'src/a/widget.ts': widget(1), + 'src/b/widget.ts': widget(2), + 'src/use-a.ts': + "import { Widget } from './a/widget';\n" + + "export function edit(ed: Widget['inputEditor']) {\n return ed.executeEdits();\n}\n", + 'src/use-b.ts': + "import type { Widget } from './b/widget';\n" + + "export function edit(ed: Widget['inputEditor']) {\n return ed.executeEdits();\n}\n", + }, true); + expect(calls.filter((c) => c.includes('ed.'))).toEqual([ + 'src/use-a.ts: ed.executeEdits -> src/a/widget.ts::CodeEditor::executeEdits', + 'src/use-b.ts: ed.executeEdits -> src/b/widget.ts::CodeEditor::executeEdits', + ]); + }, 60_000); + + it("reads one whose property's type isn't written there, a getter's, as the type it indexes, as before", async () => { + // vscode's `let mockPty: { onCommandExecuted: Emitter['event'] }` + // sits nearer `onCommandExecuted.fire(…)` than the local's own `let + // onCommandExecuted: Emitter`; `event` is a getter of `Emitter`, and + // the `event: T` of its `fire(event: T)` names no type. + const calls = await callsOf({ + ...CLASSES, + 'src/emitter.ts': + 'export class Emitter {\n' + + ' get event() { return (listener: (e: T) => void) => listener; }\n' + + ' fire(event: T) { return event; }\n' + + '}\n', + 'src/use.test.ts': + "import { Emitter } from './emitter';\n" + + 'declare function suite(name: string, body: () => void): void;\n' + + "suite('pty', () => {\n" + + ' let onDone: Emitter;\n' + + ' let pty: {\n' + + " onDone: Emitter['event'];\n" + + ' };\n' + + " suite('fires', () => {\n" + + ' onDone.fire(1);\n' + + ' });\n' + + '});\n', + }); + expect(calls.filter((c) => c.startsWith('onDone.'))).toEqual(['onDone.fire -> Emitter::fire']); + }, 60_000); + + it("is not matched to a method by the call's name when the property's type isn't written in the project", async () => { + // vscode's `invocation: Parameters[0]`: + // left untyped, the receiver's name alone would pick `Logger.info`. + const calls = await callsOf({ + ...CLASSES, + 'src/logger.ts': 'export class Logger {\n info(message: string) { return message; }\n}\n', + 'src/use.ts': + "import { Logger } from './logger';\n" + + 'function make(logger: Logger) { return logger; }\n' + + 'export function log(logger: Parameters[0]) {\n' + + " return logger.info('x');\n" + + '}\n', + }); + expect(calls.filter((c) => c.startsWith('logger.'))).toEqual([]); + }, 60_000); +}); diff --git a/__tests__/ts-dollar-method-calls.test.ts b/__tests__/ts-dollar-method-calls.test.ts new file mode 100644 index 0000000000..e0a58ab48b --- /dev/null +++ b/__tests__/ts-dollar-method-calls.test.ts @@ -0,0 +1,127 @@ +/** + * A TypeScript or JavaScript call to a method whose name carries a `$` goes + * through the receiver's type like any other method call: bitwarden's + * `this.organizationService.organizations$(userId)` on its abstract + * `OrganizationService`, and vscode's RPC + * `this._proxy.$acceptModelChanged(…)` on a `MainThread…Shape` interface. + * + * The method-call pattern took the method name as `\w+`, which has no `$`, + * so such a call matched no method-call shape and linked nothing. + */ +import { describe, it, expect, afterEach } from 'vitest'; +import * as fs from 'fs'; +import * as os from 'os'; +import * as path from 'path'; +import CodeGraph from '../src/index'; + +let roots: string[] = []; +let graphs: CodeGraph[] = []; + +afterEach(() => { + for (const graph of graphs) graph.close(); + graphs = []; + for (const root of roots) fs.rmSync(root, { recursive: true, force: true }); + roots = []; +}); + +/** Index `files` and return each call edge as `: -> ::`. */ +async function callsOf(files: Record): Promise { + const root = fs.mkdtempSync(path.join(os.tmpdir(), 'cg-ts-dollar-')); + roots.push(root); + for (const [file, text] of Object.entries(files)) { + fs.mkdirSync(path.dirname(path.join(root, file)), { recursive: true }); + fs.writeFileSync(path.join(root, file), text); + } + const graph = await CodeGraph.init(root, { index: true }); + graphs.push(graph); + const nodes = graph.getFiles().flatMap((f) => graph.getNodesInFile(f.path)); + const byId = new Map(nodes.map((n) => [n.id, n])); + return graph.getOutgoingEdgesFrom(nodes.map((n) => n.id), ['calls']) + .map((e) => { + const target = byId.get(e.target); + return `${byId.get(e.source)?.filePath}: ${e.metadata?.refName} -> ${target?.filePath}::${target?.qualifiedName}`; + }) + .sort(); +} + +describe('a call to a method whose name has a $', () => { + it("reaches the method of a field's or a parameter's class", async () => { + const calls = await callsOf({ + 'package.json': JSON.stringify({ name: 'app' }), + 'src/common/organization.service.ts': + 'export abstract class OrganizationService {\n abstract organizations$(userId: string): string[];\n}\n', + 'src/legacy/organization.service.ts': + 'export class OrganizationService {\n organizations$(userId: string) {\n return [userId];\n }\n}\n', + 'src/app/vault.component.ts': + "import { OrganizationService } from '../common/organization.service';\n" + + 'export class VaultComponent {\n constructor(private readonly organizationService: OrganizationService) {}\n' + + " load() {\n return this.organizationService.organizations$('u');\n }\n}\n" + + "export function load(service: OrganizationService) {\n return service.organizations$('u');\n}\n", + }); + expect(calls.filter((c) => c.includes('organizations$'))).toEqual([ + 'src/app/vault.component.ts: service.organizations$ -> src/common/organization.service.ts::OrganizationService::organizations$', + 'src/app/vault.component.ts: this.organizationService.organizations$ -> src/common/organization.service.ts::OrganizationService::organizations$', + ]); + }, 60_000); + + it("reaches an RPC proxy's method on the interface the field is declared with", async () => { + const calls = await callsOf({ + 'package.json': JSON.stringify({ name: 'app' }), + 'src/api/extHost.protocol.ts': 'export interface MainThreadDocumentsShape {\n $acceptModelChanged(uri: string): void;\n}\n', + 'src/api/extHostDocuments.ts': + "import { MainThreadDocumentsShape } from './extHost.protocol';\n" + + 'export class ExtHostDocuments {\n constructor(private readonly _proxy: MainThreadDocumentsShape) {}\n' + + " change() {\n this._proxy.$acceptModelChanged('a');\n }\n}\n", + }); + expect(calls.filter((c) => c.includes('$acceptModelChanged'))).toEqual([ + 'src/api/extHostDocuments.ts: this._proxy.$acceptModelChanged -> src/api/extHost.protocol.ts::MainThreadDocumentsShape::$acceptModelChanged', + ]); + }, 60_000); + + it('is linked by a sync that adds the class after the caller', async () => { + const caller = { + 'package.json': JSON.stringify({ name: 'app' }), + 'src/app/vault.component.ts': + "import { OrganizationService } from '../common/organization.service';\n" + + "export function load(service: OrganizationService) {\n return service.organizations$('u');\n}\n", + }; + const service = { + 'src/common/organization.service.ts': + 'export abstract class OrganizationService {\n abstract organizations$(userId: string): string[];\n}\n', + }; + const write = (root: string, files: Record) => { + for (const [file, text] of Object.entries(files)) { + fs.mkdirSync(path.dirname(path.join(root, file)), { recursive: true }); + fs.writeFileSync(path.join(root, file), text); + } + }; + const root = fs.mkdtempSync(path.join(os.tmpdir(), 'cg-ts-dollar-sync-')); + roots.push(root); + write(root, caller); + const graph = await CodeGraph.init(root, { index: true }); + graphs.push(graph); + const links = () => { + const nodes = graph.getFiles().flatMap((f) => graph.getNodesInFile(f.path)); + return graph.getOutgoingEdgesFrom(nodes.map((n) => n.id), ['calls']) + .map((e) => `${e.metadata?.refName} -> ${graph.getNode(e.target)?.qualifiedName}`); + }; + expect(links()).toEqual([]); + + write(root, service); + expect((await graph.sync()).filesAdded).toBe(1); + expect(links()).toEqual(['service.organizations$ -> OrganizationService::organizations$']); + expect(graph.getPendingReferenceCount()).toBe(0); + }, 120_000); + + it("links nothing when the field's class and its bases don't declare it", async () => { + const calls = await callsOf({ + 'package.json': JSON.stringify({ name: 'app' }), + 'src/state/store.ts': 'export class Store {\n get(key: string) {\n return key;\n }\n}\n', + 'src/state/other.ts': 'export class Other {\n state$() {\n return 1;\n }\n}\n', + 'src/app/view.ts': + "import { Store } from '../state/store';\n" + + 'export class View {\n private readonly store = new Store();\n run() {\n return this.store.state$();\n }\n}\n', + }); + expect(calls.filter((c) => c.includes('state$'))).toEqual([]); + }, 60_000); +}); diff --git a/__tests__/ts-generic-class-heads.test.ts b/__tests__/ts-generic-class-heads.test.ts new file mode 100644 index 0000000000..855026965b --- /dev/null +++ b/__tests__/ts-generic-class-heads.test.ts @@ -0,0 +1,117 @@ +/** + * A TypeScript class whose head opens a type parameter list with a + * constraint, like vscode's `class EditorPane extends Composite`, extends the class after its type + * parameters, not the constraint's type. + * + * The head was read up to its first `extends`, which there is the + * constraint: `EditorPane` read as extending `object` (so nothing), + * `MultiWindowParts` as extending + * `IMultiWindowPart`. Fields, wrapper methods and static methods a class + * inherits through such a head were then missed, or found on the wrong + * class. + */ +import { describe, it, expect, afterEach } from 'vitest'; +import * as fs from 'fs'; +import * as os from 'os'; +import * as path from 'path'; +import CodeGraph from '../src/index'; + +let roots: string[] = []; +let graphs: CodeGraph[] = []; + +afterEach(() => { + for (const graph of graphs) graph.close(); + graphs = []; + for (const root of roots) fs.rmSync(root, { recursive: true, force: true }); + roots = []; +}); + +/** Index `files` and return each call edge as `: -> ::`. */ +async function callsOf(files: Record): Promise { + const root = fs.mkdtempSync(path.join(os.tmpdir(), 'cg-ts-generic-heads-')); + roots.push(root); + for (const [file, text] of Object.entries(files)) { + fs.mkdirSync(path.dirname(path.join(root, file)), { recursive: true }); + fs.writeFileSync(path.join(root, file), text); + } + const graph = await CodeGraph.init(root, { index: true }); + graphs.push(graph); + const nodes = graph.getFiles().flatMap((f) => graph.getNodesInFile(f.path)); + const byId = new Map(nodes.map((n) => [n.id, n])); + return graph.getOutgoingEdgesFrom(nodes.map((n) => n.id), ['calls']) + .map((e) => { + const target = byId.get(e.target); + return `${byId.get(e.source)?.filePath}: ${e.metadata?.refName} -> ${target?.filePath}::${target?.qualifiedName}`; + }) + .sort(); +} + +/** vscode's lifecycle wrappers, the `Emitter` the app imports, and a decoy `Emitter` nearer the app. */ +const LIFECYCLE = { + 'package.json': JSON.stringify({ name: 'app' }), + 'src/base/lifecycle.ts': + 'export interface IDisposable {\n dispose(): void;\n}\n' + + 'export class DisposableStore implements IDisposable {\n add(o: T): T {\n return o;\n }\n dispose() {}\n}\n' + + 'export abstract class Disposable implements IDisposable {\n' + + ' protected readonly _store = new DisposableStore();\n' + + ' protected _register(o: T): T {\n return this._store.add(o);\n }\n' + + ' dispose() {}\n' + + '}\n', + 'src/base/event.ts': 'export class Emitter {\n fire(event?: T) {\n return event;\n }\n dispose() {}\n}\n', + 'src/app/legacy/event.ts': 'export class Emitter {\n fire() {\n return 0;\n }\n dispose() {}\n}\n', +}; + +describe('a TypeScript class whose head constrains a type parameter', () => { + it('extends the class after its type parameters, for a wrapper it inherits', async () => { + const calls = await callsOf({ + ...LIFECYCLE, + 'src/app/pane.ts': + "import { Disposable } from '../base/lifecycle';\n" + + 'export abstract class Pane extends Disposable {\n protected memento?: MementoType;\n}\n', + 'src/app/editor.ts': + "import { Pane } from './pane';\nimport { Emitter } from '../base/event';\n" + + 'export class Editor extends Pane<{ zoom: number }> {\n' + + ' private readonly _onDidChange = this._register(new Emitter());\n' + + ' run() {\n this._onDidChange.fire();\n }\n' + + '}\n', + }); + expect(calls.filter((c) => c.includes('.fire'))).toEqual(['src/app/editor.ts: this._onDidChange.fire -> src/base/event.ts::Emitter::fire']); + }, 60_000); + + it('extends the class after its type parameters, for a field it inherits, not the constraint', async () => { + const calls = await callsOf({ + 'package.json': JSON.stringify({ name: 'app' }), + 'src/store.ts': 'export class Store {\n add(v: number) {\n return v;\n }\n}\n', + // The constraint's class declares a `store` of another type with an `add`. + 'src/part.ts': 'export class Ledger {\n add(v: number) {\n return -v;\n }\n}\nexport class Part {\n protected readonly store = new Ledger();\n}\n', + 'src/root.ts': "import { Store } from './store';\nexport class Root {\n protected readonly store = new Store();\n}\n", + 'src/parts.ts': + "import { Part } from './part';\nimport { Root } from './root';\n" + + 'export class Parts extends Root {\n protected parts: T[] = [];\n}\n', + 'src/main.ts': + "import { Parts } from './parts';\nimport { Part } from './part';\n" + + 'export class MainParts extends Parts {\n run() {\n return this.store.add(1);\n }\n}\n', + }); + expect(calls.filter((c) => c.includes('this.store.add'))).toEqual(['src/main.ts: this.store.add -> src/store.ts::Store::add']); + }, 60_000); + + it('reads a head that runs over several lines, below a decorator, with an arrow type in a constraint', async () => { + const calls = await callsOf({ + ...LIFECYCLE, + 'src/app/decorate.ts': 'export function Decorate(options: object) {\n return (target: unknown) => target;\n}\n', + 'src/app/view.ts': + "import { Disposable } from '../base/lifecycle';\nimport { Decorate } from './decorate';\n" + + "@Decorate({ host: { class: 'view' } })\n" + + 'export class View<\n Render extends (value: string) => void,\n State extends object = object\n>\n extends Disposable {\n' + + ' protected render?: Render;\n}\n', + 'src/app/panel.ts': + "import { View } from './view';\nimport { Emitter } from '../base/event';\n" + + 'export class Panel extends View<(value: string) => void> {\n' + + ' private readonly _onDidShow = this._register(new Emitter());\n' + + ' show() {\n this._onDidShow.fire();\n }\n' + + '}\n', + }); + expect(calls.filter((c) => c.includes('.fire'))).toEqual(['src/app/panel.ts: this._onDidShow.fire -> src/base/event.ts::Emitter::fire']); + }, 60_000); +}); diff --git a/__tests__/ts-imported-type-receivers.test.ts b/__tests__/ts-imported-type-receivers.test.ts new file mode 100644 index 0000000000..0f2064a868 --- /dev/null +++ b/__tests__/ts-imported-type-receivers.test.ts @@ -0,0 +1,235 @@ +/** + * A call on a TypeScript/JavaScript value whose type the file imports links + * to the method of the class the import names, when several classes share + * the name. + * + * Typed calls broke a tie between same-named classes only by the call site's + * own file, then took the first declaration indexed: on vscode, calls in + * `src/vs/` on a `DisposableStore` imported from `vs/base/common/lifecycle` + * reached copilot's vendored copy under `extensions/copilot/src/util/vs/`, + * and on an `Emitter` a copilot test fixture's. `this.` calls broke + * it by folder nearness, which took react-native's Jest mock of + * `NativeEventEmitter` over the class beside it. Java and Kotlin already + * followed the import (#314). + */ +import { describe, it, expect, afterEach } from 'vitest'; +import * as fs from 'fs'; +import * as os from 'os'; +import * as path from 'path'; +import CodeGraph from '../src/index'; + +let roots: string[] = []; +let graphs: CodeGraph[] = []; + +afterEach(() => { + for (const graph of graphs) graph.close(); + graphs = []; + for (const root of roots) fs.rmSync(root, { recursive: true, force: true }); + roots = []; +}); + +/** Index `files` and return each call edge as `: -> ::`. */ +async function callsOf(files: Record): Promise { + const root = fs.mkdtempSync(path.join(os.tmpdir(), 'cg-ts-imported-recv-')); + roots.push(root); + for (const [file, text] of Object.entries(files)) { + fs.mkdirSync(path.dirname(path.join(root, file)), { recursive: true }); + fs.writeFileSync(path.join(root, file), text); + } + const graph = await CodeGraph.init(root, { index: true }); + graphs.push(graph); + const nodes = graph.getFiles().flatMap((f) => graph.getNodesInFile(f.path)); + const byId = new Map(nodes.map((n) => [n.id, n])); + return graph.getOutgoingEdgesFrom(nodes.map((n) => n.id), ['calls']) + .map((e) => { + const target = byId.get(e.target); + return `${byId.get(e.source)?.filePath}: ${e.metadata?.refName} -> ${target?.filePath}::${target?.qualifiedName}`; + }) + .sort(); +} + +/** Two classes named `Store`, each with the same methods. */ +const STORES = { + 'package.json': JSON.stringify({ name: 'app' }), + 'src/one/store.ts': + 'export class Base {\n reset() { return 1; }\n}\n' + + 'export class Store extends Base {\n add(v: number) { return v; }\n}\n', + 'src/two/store.ts': + 'export class Base {\n reset() { return 2; }\n}\n' + + 'export class Store extends Base {\n add(v: number) { return -v; }\n}\n', + 'src/two/index.ts': "export { Store } from './store';\n", +}; + +describe('a call on a TypeScript value whose type the file imports', () => { + it("links to the imported class's method, whichever of the same-named classes it is", async () => { + const calls = await callsOf({ + ...STORES, + 'src/use-one.ts': + "import { Store } from './one/store';\n" + + 'export function a(s: Store) {\n return s.add(1);\n}\n', + 'src/use-two.ts': + "import { Store } from './two/store';\n" + + 'export function b(s: Store) {\n return s.add(2);\n}\n', + }); + expect(calls.filter((c) => c.includes('s.add'))).toEqual([ + 'src/use-one.ts: s.add -> src/one/store.ts::Store::add', + 'src/use-two.ts: s.add -> src/two/store.ts::Store::add', + ]); + }, 60_000); + + it('follows the import through a re-export, a type-only import and a namespace import', async () => { + const calls = await callsOf({ + ...STORES, + 'src/use-barrel.ts': + "import { Store } from './two';\n" + + 'export function b(s: Store) {\n return s.add(2);\n}\n', + 'src/use-type.ts': + "import type { Store } from './two/store';\n" + + 'export function t(s: Store) {\n return s.add(3);\n}\n', + 'src/use-ns.ts': + "import * as two from './two/store';\n" + + 'export function n() {\n const s = new two.Store();\n return s.add(4);\n}\n', + }); + expect(calls.filter((c) => c.includes('s.add'))).toEqual([ + 'src/use-barrel.ts: s.add -> src/two/store.ts::Store::add', + 'src/use-ns.ts: s.add -> src/two/store.ts::Store::add', + 'src/use-type.ts: s.add -> src/two/store.ts::Store::add', + ]); + }, 60_000); + + it("links an inherited method to the base class declared beside the imported class", async () => { + const calls = await callsOf({ + ...STORES, + 'src/use-two.ts': + "import { Store } from './two/store';\n" + + 'export function b(s: Store) {\n return s.reset();\n}\n', + }); + expect(calls.filter((c) => c.includes('s.reset'))).toEqual(['src/use-two.ts: s.reset -> src/two/store.ts::Base::reset']); + }, 60_000); + + it("links a `this.` call to the method of the class its file imports", async () => { + // Both stores are as near the caller's directory, so nearness alone + // picks the first path, `src/one`. + const calls = await callsOf({ + ...STORES, + 'src/user.ts': + "import { Store } from './two/store';\n" + + 'export class User {\n' + + ' constructor(private readonly store: Store) {}\n' + + ' run() {\n return this.store.add(3);\n }\n' + + '}\n', + }); + expect(calls.filter((c) => c.includes('this.store.add'))).toEqual(['src/user.ts: this.store.add -> src/two/store.ts::Store::add']); + }, 60_000); + + it("follows the call's own file's import when the field is read off a same-named class elsewhere", async () => { + // vscode's copilot `MockPromptsService` declares its emitter as + // `this._register(new Emitter())`, which isn't read, so its field + // is read off the workbench's `MockPromptsService`, which imports the + // other `Emitter`. + const calls = await callsOf({ + ...STORES, + 'src/app/mock.ts': + "import { Store } from '../two/store';\n" + + 'const wrap = (value: T) => value;\n' + + 'export class Mock {\n' + + ' private readonly store = wrap(new Store());\n' + + ' run() {\n return this.store.add(1);\n }\n' + + '}\n', + 'src/other/mock.ts': + "import { Store } from '../one/store';\n" + + 'export class Mock {\n' + + ' private readonly store = new Store();\n' + + ' run() {\n return this.store.add(2);\n }\n' + + '}\n', + }); + expect(calls.filter((c) => c.includes('this.store.add'))).toEqual([ + 'src/app/mock.ts: this.store.add -> src/two/store.ts::Store::add', + 'src/other/mock.ts: this.store.add -> src/one/store.ts::Store::add', + ]); + }, 60_000); + + it('does the same in JavaScript, for `new` of an imported or required class', async () => { + const calls = await callsOf({ + 'package.json': JSON.stringify({ name: 'app' }), + 'lib/one/store.js': 'export class Store {\n add(v) { return v; }\n}\n', + 'lib/two/store.js': 'export class Store {\n add(v) { return -v; }\n}\n', + 'lib/use-new.js': + "import { Store } from './two/store';\n" + + 'export function n() {\n const s = new Store();\n return s.add(5);\n}\n', + 'lib/use-require.js': + "const { Store } = require('./two/store');\n" + + 'function r() {\n const s = new Store();\n return s.add(6);\n}\n' + + 'module.exports = { r };\n', + }); + expect(calls.filter((c) => c.includes('s.add'))).toEqual([ + 'lib/use-new.js: s.add -> lib/two/store.js::Store::add', + 'lib/use-require.js: s.add -> lib/two/store.js::Store::add', + ]); + }, 60_000); + + it("still prefers a class the call's own file declares", async () => { + const calls = await callsOf({ + ...STORES, + 'src/own.ts': + 'class Store {\n add(v: number) { return v * 2; }\n}\n' + + 'export function o(s: Store) {\n return s.add(7);\n}\n', + }); + expect(calls.filter((c) => c.includes('s.add'))).toEqual(['src/own.ts: s.add -> src/own.ts::Store::add']); + }, 60_000); +}); + +describe('a call on a value another file exports, whose class that file imports', () => { + it("links to the class the value's file imports, whichever of the same-named classes it is", async () => { + // `import { store } from './state'; store.add(…)` with + // `export const store = new Store()` in `state.ts`. + const calls = await callsOf({ + ...STORES, + 'src/state-one.ts': "import { Store } from './one/store';\nexport const store = new Store();\n", + 'src/state-two.ts': "import { Store } from './two/store';\nexport const store: Store = new Store();\n", + 'src/use-one.ts': "import { store } from './state-one';\nexport function a() {\n return store.add(1);\n}\n", + 'src/use-two.ts': "import { store } from './state-two';\nexport function b() {\n return store.add(2);\n}\n", + }); + expect(calls.filter((c) => c.includes('store.add'))).toEqual([ + 'src/use-one.ts: store.add -> src/one/store.ts::Store::add', + 'src/use-two.ts: store.add -> src/two/store.ts::Store::add', + ]); + }, 60_000); + + it('links to the class the value\'s own file declares', async () => { + const own = (n: number) => + `export class Store {\n add(v: number) { return v * ${n}; }\n}\n` + + 'export const store = new Store();\n'; + const calls = await callsOf({ + ...STORES, + 'src/own-a.ts': own(3), + 'src/own-b.ts': own(4), + 'src/use-a.ts': "import { store } from './own-a';\nexport function a() {\n return store.add(1);\n}\n", + 'src/use-b.ts': "import { store } from './own-b';\nexport function b() {\n return store.add(2);\n}\n", + }); + expect(calls.filter((c) => c.includes('store.add'))).toEqual([ + 'src/use-a.ts: store.add -> src/own-a.ts::Store::add', + 'src/use-b.ts: store.add -> src/own-b.ts::Store::add', + ]); + }, 60_000); +}); + +describe('a call in a Vue component on a value another file exports', () => { + it("links to the class the value's file imports", async () => { + const vue = (state: string) => + '\n' + + `\n`; + const calls = await callsOf({ + ...STORES, + 'package.json': JSON.stringify({ name: 'app', dependencies: { vue: '^3.4.0' } }), + 'src/state-one.ts': "import { Store } from './one/store';\nexport const store = new Store();\n", + 'src/state-two.ts': "import { Store } from './two/store';\nexport const store = new Store();\n", + 'src/One.vue': vue('state-one'), + 'src/Two.vue': vue('state-two'), + }); + expect(calls.filter((c) => c.includes('store.add'))).toEqual([ + 'src/One.vue: store.add -> src/one/store.ts::Store::add', + 'src/Two.vue: store.add -> src/two/store.ts::Store::add', + ]); + }, 60_000); +}); diff --git a/__tests__/ts-injected-receivers.test.ts b/__tests__/ts-injected-receivers.test.ts new file mode 100644 index 0000000000..fce681023b --- /dev/null +++ b/__tests__/ts-injected-receivers.test.ts @@ -0,0 +1,172 @@ +/** + * A TypeScript field or local set from a dependency-injection call that + * hands back an instance of the class it is given has that class's type: + * Angular's `private readonly dataService = inject(DataService)`, and + * vscode's `this._register(this.instantiationService.createInstance(Widget, + * …))` or `const widget = this.instantiationService.createInstance(Widget)`. + * + * Neither was read, so calls through them linked nowhere, or by name alone: + * on bitwarden and ghostfolio thousands of `this..()` calls + * sat on `inject(X)` fields. Only Angular's `inject` counts (Vue's + * `inject(key)` returns whatever was provided under the key), and only a + * `createInstance` the project declares to return an `InstanceType` of its + * argument. + */ +import { describe, it, expect, afterEach } from 'vitest'; +import * as fs from 'fs'; +import * as os from 'os'; +import * as path from 'path'; +import CodeGraph from '../src/index'; + +let roots: string[] = []; +let graphs: CodeGraph[] = []; + +afterEach(() => { + for (const graph of graphs) graph.close(); + graphs = []; + for (const root of roots) fs.rmSync(root, { recursive: true, force: true }); + roots = []; +}); + +/** Index `files` and return each call edge as `: -> ::`. */ +async function callsOf(files: Record): Promise { + const root = fs.mkdtempSync(path.join(os.tmpdir(), 'cg-ts-injected-')); + roots.push(root); + for (const [file, text] of Object.entries(files)) { + fs.mkdirSync(path.dirname(path.join(root, file)), { recursive: true }); + fs.writeFileSync(path.join(root, file), text); + } + const graph = await CodeGraph.init(root, { index: true }); + graphs.push(graph); + const nodes = graph.getFiles().flatMap((f) => graph.getNodesInFile(f.path)); + const byId = new Map(nodes.map((n) => [n.id, n])); + return graph.getOutgoingEdgesFrom(nodes.map((n) => n.id), ['calls']) + .map((e) => { + const target = byId.get(e.target); + return `${byId.get(e.source)?.filePath}: ${e.metadata?.refName} -> ${target?.filePath}::${target?.qualifiedName}`; + }) + .sort(); +} + +/** The service the app injects, and a decoy of the same name nearer the component. */ +const SERVICES = { + 'src/app/data.service.ts': 'export class DataService {\n fetchInfo() {\n return 1;\n }\n}\n', + 'src/app/components/legacy/data.service.ts': 'export class DataService {\n fetchInfo() {\n return 2;\n }\n}\n', +}; + +/** vscode's lifecycle and instantiation service, and widgets: the imported one and a nearer decoy. */ +const WORKBENCH = { + 'package.json': JSON.stringify({ name: 'app' }), + 'src/base/lifecycle.ts': + 'export interface IDisposable {\n dispose(): void;\n}\n' + + 'export abstract class Disposable implements IDisposable {\n' + + ' protected _register(o: T): T {\n return o;\n }\n' + + ' dispose() {}\n' + + '}\n', + 'src/platform/instantiation.ts': + 'export interface IInstantiationService {\n' + + ' createInstance unknown, R extends InstanceType>(ctor: Ctor, ...args: unknown[]): R;\n' + + '}\n', + 'src/browser/widget.ts': 'export class Widget {\n layout() {}\n dispose() {}\n}\n', + 'src/browser/parts/legacy/widget.ts': 'export class Widget {\n layout() {}\n dispose() {}\n}\n', +}; + +describe('a TypeScript receiver a dependency-injection call sets up', () => { + it("has the class Angular's inject(X) is given", async () => { + const calls = await callsOf({ + 'package.json': JSON.stringify({ name: 'app', dependencies: { '@angular/core': '^18.0.0' } }), + ...SERVICES, + 'src/app/components/app.component.ts': + "import { inject } from '@angular/core';\nimport { DataService } from '../data.service';\n" + + 'export class AppComponent {\n' + + ' private readonly dataService = inject(DataService);\n' + + ' private readonly maybe = inject(DataService, { optional: true });\n' + + ' ngOnInit() {\n this.dataService.fetchInfo();\n this.maybe.fetchInfo();\n }\n' + + '}\n' + + 'export function load() {\n const service = inject(DataService);\n return service.fetchInfo();\n}\n', + }); + expect(calls.filter((c) => c.includes('fetchInfo'))).toEqual([ + 'src/app/components/app.component.ts: service.fetchInfo -> src/app/data.service.ts::DataService::fetchInfo', + 'src/app/components/app.component.ts: this.dataService.fetchInfo -> src/app/data.service.ts::DataService::fetchInfo', + 'src/app/components/app.component.ts: this.maybe.fetchInfo -> src/app/data.service.ts::DataService::fetchInfo', + ]); + }, 60_000); + + it("has the type inject's type argument names, for a token that isn't a class", async () => { + // bitwarden's `protected params = inject(DIALOG_DATA)`. + const calls = await callsOf({ + 'package.json': JSON.stringify({ name: 'app', dependencies: { '@angular/core': '^18.0.0', '@angular/cdk': '^18.0.0' } }), + 'src/app/params.ts': 'export interface DialogParams {\n onContinue(): void;\n}\n', + 'src/app/legacy/params.ts': 'export interface DialogParams {\n onContinue(): void;\n}\n', + 'src/app/dialog.component.ts': + "import { inject } from '@angular/core';\nimport { DIALOG_DATA } from '@angular/cdk/dialog';\nimport { DialogParams } from './params';\n" + + 'export class DialogComponent {\n' + + ' protected params = inject(DIALOG_DATA);\n' + + ' ok() {\n this.params.onContinue();\n const local = inject(DIALOG_DATA);\n local.onContinue();\n }\n' + + '}\n', + }); + expect(calls.filter((c) => c.includes('onContinue'))).toEqual([ + 'src/app/dialog.component.ts: local.onContinue -> src/app/params.ts::DialogParams::onContinue', + 'src/app/dialog.component.ts: this.params.onContinue -> src/app/params.ts::DialogParams::onContinue', + ]); + }, 60_000); + + it("doesn't read a field set from an inject that isn't Angular's", async () => { + const calls = await callsOf({ + 'package.json': JSON.stringify({ name: 'app', dependencies: { vue: '^3.0.0' } }), + ...SERVICES, + 'src/app/components/app.store.ts': + "import { inject } from 'vue';\nimport { DataService } from '../data.service';\n" + + 'export class AppStore {\n' + + ' private readonly dataService = inject(DataService);\n' + + ' load() {\n return this.dataService.fetchInfo();\n }\n' + + '}\n', + }); + expect(calls.filter((c) => c.includes('this.dataService.fetchInfo'))).toEqual([]); + }, 60_000); + + it('has the class an instantiation service that returns its InstanceType is given', async () => { + const calls = await callsOf({ + ...WORKBENCH, + 'src/browser/parts/view.ts': + "import { Disposable } from '../../base/lifecycle';\n" + + "import { IInstantiationService } from '../../platform/instantiation';\n" + + "import { Widget } from '../widget';\n" + + 'export class View extends Disposable {\n' + + ' private readonly widget = this._register(this.instantiationService.createInstance(Widget));\n' + + ' private readonly plain = this.instantiationService.createInstance(Widget);\n' + + ' constructor(private readonly instantiationService: IInstantiationService) {\n super();\n }\n' + + ' run() {\n this.widget.layout();\n this.plain.layout();\n const local = this.instantiationService.createInstance(Widget);\n local.layout();\n }\n' + + '}\n' + + // A member of what it hands back is that member's type, not the class's. + 'class Accessor {\n widget!: Widget;\n}\n' + + 'export function check(instantiationService: IInstantiationService) {\n' + + ' let widget: Widget;\n' + + ' widget = instantiationService.createInstance(Accessor).widget;\n' + + ' return widget.dispose();\n' + + '}\n', + }); + expect(calls.filter((c) => c.includes('layout') || c.includes('widget.dispose'))).toEqual([ + 'src/browser/parts/view.ts: local.layout -> src/browser/widget.ts::Widget::layout', + 'src/browser/parts/view.ts: this.plain.layout -> src/browser/widget.ts::Widget::layout', + 'src/browser/parts/view.ts: this.widget.layout -> src/browser/widget.ts::Widget::layout', + 'src/browser/parts/view.ts: widget.dispose -> src/browser/widget.ts::Widget::dispose', + ]); + }, 60_000); + + it("doesn't read a field from a createInstance the project doesn't declare to return its argument's instance", async () => { + const calls = await callsOf({ + ...WORKBENCH, + 'src/platform/instantiation.ts': 'export interface IFactory {\n createInstance(name: unknown): unknown;\n}\n', + 'src/browser/parts/view.ts': + "import { IFactory } from '../../platform/instantiation';\n" + + "import { Widget } from '../widget';\n" + + 'export class View {\n' + + ' private readonly plain = this.factory.createInstance(Widget);\n' + + ' constructor(private readonly factory: IFactory) {}\n' + + ' run() {\n this.plain.layout();\n }\n' + + '}\n', + }); + expect(calls.filter((c) => c.includes('this.plain.layout'))).toEqual([]); + }, 60_000); +}); diff --git a/__tests__/ts-known-class-methods.test.ts b/__tests__/ts-known-class-methods.test.ts new file mode 100644 index 0000000000..7c4b6b18c2 --- /dev/null +++ b/__tests__/ts-known-class-methods.test.ts @@ -0,0 +1,156 @@ +/** + * A TypeScript call on a field or a local whose class its file's import + * names reaches that class's method, or the method of a class it extends as + * that class's own file names it, and never a same-named class elsewhere. + * + * When the class didn't declare the method itself, the call went to any + * class with the method and the right name: vscode's `this._storage.dispose` + * (`Storage extends Disposable`) reached a test fixture's `Disposable`, and + * Copilot's `Emitter extends lsp.Emitter`, whose `fire` is the package's, + * reached a test fixture's `Emitter::fire`. An interface's call through the + * interface it extends, like `this.logService.trace()` on `ILogService + * extends ILogger`, linked nowhere. + */ +import { describe, it, expect, afterEach } from 'vitest'; +import * as fs from 'fs'; +import * as os from 'os'; +import * as path from 'path'; +import CodeGraph from '../src/index'; + +let roots: string[] = []; +let graphs: CodeGraph[] = []; + +afterEach(() => { + for (const graph of graphs) graph.close(); + graphs = []; + for (const root of roots) fs.rmSync(root, { recursive: true, force: true }); + roots = []; +}); + +/** Index `files` and return each call edge as `: -> ::`. */ +async function callsOf(files: Record): Promise { + const root = fs.mkdtempSync(path.join(os.tmpdir(), 'cg-ts-known-class-')); + roots.push(root); + for (const [file, text] of Object.entries(files)) { + fs.mkdirSync(path.dirname(path.join(root, file)), { recursive: true }); + fs.writeFileSync(path.join(root, file), text); + } + const graph = await CodeGraph.init(root, { index: true }); + graphs.push(graph); + const nodes = graph.getFiles().flatMap((f) => graph.getNodesInFile(f.path)); + const byId = new Map(nodes.map((n) => [n.id, n])); + return graph.getOutgoingEdgesFrom(nodes.map((n) => n.id), ['calls']) + .map((e) => { + const target = byId.get(e.target); + return `${byId.get(e.source)?.filePath}: ${e.metadata?.refName} -> ${target?.filePath}::${target?.qualifiedName}`; + }) + .sort(); +} + +describe('a call on a value of a class its file names', () => { + it("reaches the method the class inherits from the base its own file imports, not the call's file's namesake", async () => { + const calls = await callsOf({ + 'package.json': JSON.stringify({ name: 'app' }), + 'src/base/lifecycle.ts': 'export class Disposable {\n dispose() {\n return 1;\n }\n}\n', + 'src/base/storage.ts': + "import { Disposable } from './lifecycle';\nexport class Storage extends Disposable {\n get(key: string) {\n return key;\n }\n}\n", + 'src/app/main.ts': + "import { Storage } from '../base/storage';\n" + + 'class Disposable {\n dispose() {\n return 2;\n }\n}\n' + + 'export class Main {\n private readonly _storage = new Storage();\n private readonly local = new Disposable();\n' + + ' close() {\n this._storage.dispose();\n }\n}\n' + + 'export function shut(storage: Storage) {\n return storage.dispose();\n}\n', + }); + expect(calls.filter((c) => c.includes('dispose'))).toEqual([ + 'src/app/main.ts: storage.dispose -> src/base/lifecycle.ts::Disposable::dispose', + 'src/app/main.ts: this._storage.dispose -> src/base/lifecycle.ts::Disposable::dispose', + ]); + }, 60_000); + + it("links nothing when the method is the class's package base's, whatever project class shares the names", async () => { + const calls = await callsOf({ + 'package.json': JSON.stringify({ name: 'app', dependencies: { 'ext-lsp': '^1.0.0' } }), + 'src/util/event.ts': + "import * as lsp from 'ext-lsp';\nexport class Emitter extends lsp.Emitter {\n get size() {\n return 0;\n }\n}\n", + 'src/fixtures/testbed/events.ts': 'export class Emitter {\n fire() {\n return 0;\n }\n}\n', + 'src/app/model.ts': + "import { Emitter } from '../util/event';\n" + + 'export class Model {\n private readonly _onDidChange = new Emitter();\n run() {\n this._onDidChange.fire();\n }\n}\n', + }); + expect(calls.filter((c) => c.includes('.fire'))).toEqual([]); + }, 60_000); + + it('links nothing when neither the class nor anything it extends declares the method', async () => { + const calls = await callsOf({ + 'package.json': JSON.stringify({ name: 'app' }), + 'src/one/widget.ts': 'export class Base {\n show() {}\n}\nexport class Widget extends Base {\n hide() {}\n}\n', + 'src/two/widget.ts': 'export class Widget {\n focus() {}\n}\n', + 'src/app/view.ts': + "import { Widget } from '../one/widget';\n" + + 'export class View {\n private readonly widget = new Widget();\n run() {\n this.widget.show();\n this.widget.focus();\n }\n}\n', + }); + expect(calls.filter((c) => c.includes('this.widget.'))).toEqual(['src/app/view.ts: this.widget.show -> src/one/widget.ts::Base::show']); + }, 60_000); + + it('reaches a method an interface inherits from the interface it extends', async () => { + // vscode's `ILogService` is also a constant: `createDecorator('logService')`. + const calls = await callsOf({ + 'package.json': JSON.stringify({ name: 'app' }), + 'src/platform/log.ts': + 'function createDecorator(id: string): T {\n return id as unknown as T;\n}\n' + + 'export interface ILogger {\n trace(message: string): void;\n}\n' + + "export const ILogService = createDecorator('logService');\n" + + 'export interface ILogService extends ILogger {\n flush(): void;\n}\n', + 'src/app/legacy/log.ts': 'export interface ILogger {\n trace(message: string): void;\n}\n', + 'src/app/service.ts': + "import { ILogService } from '../platform/log';\n" + + 'export class Service {\n constructor(private readonly logService: ILogService) {}\n' + + " run() {\n this.logService.trace('a');\n this.logService.flush();\n }\n}\n", + }); + expect(calls.filter((c) => c.includes('this.logService.'))).toEqual([ + 'src/app/service.ts: this.logService.flush -> src/platform/log.ts::ILogService::flush', + 'src/app/service.ts: this.logService.trace -> src/platform/log.ts::ILogger::trace', + ]); + }, 60_000); + + it('reaches the class an import renames on the way, not a namesake of the local name', async () => { + // bitwarden's `export { MessageSender as MessagingService } from "@bitwarden/messaging"`. + const calls = await callsOf({ + 'package.json': JSON.stringify({ name: 'app' }), + 'src/messaging/sender.ts': 'export abstract class MessageSender {\n abstract send(command: string): void;\n}\n', + 'src/common/messaging.service.ts': "export { MessageSender as MessagingService } from '../messaging/sender';\n", + 'src/desktop/electron-messaging.service.ts': 'export class MessagingService {\n send(command: string) {\n return command;\n }\n}\n', + 'src/desktop/settings.component.ts': + "import { MessagingService } from '../common/messaging.service';\n" + + 'export class SettingsComponent {\n constructor(private readonly messagingService: MessagingService) {}\n' + + " save() {\n this.messagingService.send('saved');\n }\n}\n", + }); + expect(calls.filter((c) => c.includes('this.messagingService.send'))).toEqual([ + 'src/desktop/settings.component.ts: this.messagingService.send -> src/messaging/sender.ts::MessageSender::send', + ]); + }, 60_000); + + it('reaches it through an interface another file extends, whose import also names a constant', async () => { + // vscode's `ITerminalLogService extends ILogService`, `ILogService` both + // an interface and its `createDecorator` constant. + const calls = await callsOf({ + 'package.json': JSON.stringify({ name: 'app' }), + 'src/platform/log.ts': + 'function createDecorator(id: string): T {\n return id as unknown as T;\n}\n' + + 'export interface ILogger {\n trace(message: string): void;\n}\n' + + "export const ILogService = createDecorator('logService');\n" + + 'export interface ILogService extends ILogger {\n flush(): void;\n}\n', + 'src/app/legacy/log.ts': 'export interface ILogger {\n trace(message: string): void;\n}\n', + 'src/terminal/terminal.ts': + "import { ILogService } from '../platform/log';\n" + + 'export interface ITerminalLogService extends ILogService {\n logTerminal(): void;\n}\n', + 'src/terminal/service.ts': + "import { ITerminalLogService } from './terminal';\n" + + 'export class TerminalService {\n constructor(private readonly _logService: ITerminalLogService) {}\n' + + " run() {\n this._logService.trace('a');\n }\n}\n", + }); + expect(calls.filter((c) => c.includes('this._logService.'))).toEqual([ + 'src/terminal/service.ts: this._logService.trace -> src/platform/log.ts::ILogger::trace', + ]); + }, 60_000); +}); diff --git a/__tests__/ts-this-field-bases.test.ts b/__tests__/ts-this-field-bases.test.ts new file mode 100644 index 0000000000..b62b495238 --- /dev/null +++ b/__tests__/ts-this-field-bases.test.ts @@ -0,0 +1,207 @@ +/** + * A TypeScript/JavaScript `this.` call on a field a base class + * declares links through that base, the class its subclass's file names. + * + * A field the calling class doesn't declare was read off any same-named + * class elsewhere, and never off the classes it extends: on vscode, the + * browser `FileDialogService`'s `this.openerService` was typed by the + * electron `FileDialogService`, and a field another app's same-named class + * declares could type it however that app did. Now the calling class's + * bases come first, and a same-named class elsewhere only when the call's + * file imports or declares the type it gives the field. + * + * A type the declaring file imports from a package outside the project has + * no project method, which typed locals follow too: microsoft- + * authentication's `TelemetryReporter` from `@vscode/extension-telemetry` + * reached another extension's interface of that name. + */ +import { describe, it, expect, afterEach } from 'vitest'; +import * as fs from 'fs'; +import * as os from 'os'; +import * as path from 'path'; +import CodeGraph from '../src/index'; + +let roots: string[] = []; +let graphs: CodeGraph[] = []; + +afterEach(() => { + for (const graph of graphs) graph.close(); + graphs = []; + for (const root of roots) fs.rmSync(root, { recursive: true, force: true }); + roots = []; +}); + +/** Index `files` and return each call edge as `: -> ::`. */ +async function callsOf(files: Record): Promise { + const root = fs.mkdtempSync(path.join(os.tmpdir(), 'cg-ts-field-bases-')); + roots.push(root); + for (const [file, text] of Object.entries(files)) { + fs.mkdirSync(path.dirname(path.join(root, file)), { recursive: true }); + fs.writeFileSync(path.join(root, file), text); + } + const graph = await CodeGraph.init(root, { index: true }); + graphs.push(graph); + const nodes = graph.getFiles().flatMap((f) => graph.getNodesInFile(f.path)); + const byId = new Map(nodes.map((n) => [n.id, n])); + return graph.getOutgoingEdgesFrom(nodes.map((n) => n.id), ['calls']) + .map((e) => { + const target = byId.get(e.target); + return `${byId.get(e.source)?.filePath}: ${e.metadata?.refName} -> ${target?.filePath}::${target?.qualifiedName}`; + }) + .sort(); +} + +/** Two classes named `Store`, each with the same methods. */ +const STORES = { + 'package.json': JSON.stringify({ name: 'app' }), + 'src/one/store.ts': 'export class Store {\n add(v: number) { return v; }\n}\n', + 'src/two/store.ts': 'export class Store {\n add(v: number) { return -v; }\n}\n', +}; + +describe('a this. call on a field a class it extends declares', () => { + it('reads the field off the base its file imports, and its type off the import there', async () => { + const calls = await callsOf({ + ...STORES, + 'src/base.ts': "import { Store } from './two/store';\nexport class Base {\n protected readonly store = new Store();\n}\n", + 'src/child.ts': + "import { Base } from './base';\n" + + 'export class Child extends Base {\n run() {\n return this.store.add(1);\n }\n}\n', + }); + expect(calls.filter((c) => c.includes('this.store.add'))).toEqual(['src/child.ts: this.store.add -> src/two/store.ts::Store::add']); + }, 60_000); + + it("reads the field's type off a class the base's own file declares", async () => { + const calls = await callsOf({ + ...STORES, + // A folder that sorts after `one` and `two`, so folder nearness, which + // ties, would pick another `Store`. + 'src/zeta/base.ts': + 'export class Store {\n add(v: number) { return v * 10; }\n}\n' + + 'export class Base {\n protected readonly store = new Store();\n}\n', + 'src/child.ts': + "import { Base } from './zeta/base';\n" + + 'export class Child extends Base {\n run() {\n return this.store.add(1);\n }\n}\n', + }); + expect(calls.filter((c) => c.includes('this.store.add'))).toEqual(['src/child.ts: this.store.add -> src/zeta/base.ts::Store::add']); + }, 60_000); + + it('follows an aliased import to a base of the same name', async () => { + // vscode's sessions `EditorPart extends` the workbench's `EditorPart`. + const calls = await callsOf({ + ...STORES, + 'src/workbench/part.ts': "import { Store } from '../two/store';\nexport class Part {\n protected readonly store: Store = new Store();\n}\n", + 'src/sessions/part.ts': + "import { Part as BasePart } from '../workbench/part';\n" + + 'export class Part extends BasePart {\n run() {\n return this.store.add(2);\n }\n}\n', + }); + expect(calls.filter((c) => c.includes('this.store.add'))).toEqual(['src/sessions/part.ts: this.store.add -> src/two/store.ts::Store::add']); + }, 60_000); + + it('reads it off a base many classes up, as vscode editors inherit `_store` from `Disposable`', async () => { + const files: Record = { + ...STORES, + 'src/base.ts': "import { Store } from './two/store';\nexport class Base {\n protected readonly store = new Store();\n}\n", + }; + let parent = ['Base', './base']; + for (const name of ['L1', 'L2', 'L3', 'L4', 'L5']) { + files[`src/${name.toLowerCase()}.ts`] = `import { ${parent[0]} } from '${parent[1]}';\nexport class ${name} extends ${parent[0]} {}\n`; + parent = [name, `./${name.toLowerCase()}`]; + } + const calls = await callsOf({ + ...files, + 'src/child.ts': "import { L5 } from './l5';\nexport class Child extends L5 {\n run() {\n return this.store.add(1);\n }\n}\n", + }); + expect(calls.filter((c) => c.includes('this.store.add'))).toEqual(['src/child.ts: this.store.add -> src/two/store.ts::Store::add']); + }, 60_000); + + it("doesn't read the field off an unrelated class of the same name whose type the call's file doesn't name", async () => { + const calls = await callsOf({ + ...STORES, + 'src/app-a/service.ts': "import { Store } from '../one/store';\nexport class Service {\n private readonly store = new Store();\n}\n", + 'src/app-b/service.ts': + 'const makeStore = () => ({ add: (v: number) => v });\n' + + 'export class Service {\n private readonly store = makeStore();\n run() {\n return this.store.add(3);\n }\n}\n', + }); + expect(calls.filter((c) => c.includes('this.store.add'))).toEqual([]); + }, 60_000); + + it('still reads it off a same-named class elsewhere whose type the call\'s file imports', async () => { + // The calling class's own declaration goes through a wrapper the reader + // can't vouch for (`wrap` declares no return type); the same-named + // class elsewhere declares the field. + const calls = await callsOf({ + ...STORES, + 'src/app/mock.ts': + "import { Store } from '../two/store';\n" + + 'const wrap = (value: T) => value;\n' + + 'export class Mock {\n' + + ' private readonly store = wrap(new Store());\n' + + ' run() {\n return this.store.add(1);\n }\n' + + '}\n', + 'src/other/mock.ts': + "import { Store } from '../one/store';\n" + + 'export class Mock {\n private readonly store = new Store();\n}\n', + }); + expect(calls.filter((c) => c.includes('this.store.add'))).toEqual(['src/app/mock.ts: this.store.add -> src/two/store.ts::Store::add']); + }, 60_000); +}); + +describe('a call on a value whose type a package outside the project gives', () => { + it("links to no project class that shares the type's name", async () => { + const calls = await callsOf({ + 'package.json': JSON.stringify({ name: 'app', dependencies: { 'ext-telemetry': '^1.0.0' } }), + 'src/other.ts': 'export interface TelemetryReporter {\n sendTelemetryEvent(name: string): void;\n}\n', + 'src/reporter.ts': + "import TelemetryReporter from 'ext-telemetry';\n" + + 'export class Reporter {\n' + + ' protected reporter: TelemetryReporter;\n' + + ' constructor() {\n this.reporter = new TelemetryReporter();\n }\n' + + " send() {\n this.reporter.sendTelemetryEvent('a');\n }\n" + + '}\n' + + "export class Sub extends Reporter {\n more() {\n this.reporter.sendTelemetryEvent('b');\n }\n}\n", + 'src/local.ts': + "import TelemetryReporter from 'ext-telemetry';\n" + + "export function f() {\n const r = new TelemetryReporter();\n return r.sendTelemetryEvent('c');\n}\n", + }); + expect(calls.filter((c) => c.includes('sendTelemetryEvent'))).toEqual([]); + }, 60_000); + + it('still links to the declaration a project file gives the package', async () => { + // vscode's `src/typings/copilot-api.d.ts` declares `@vscode/copilot-api`. + const calls = await callsOf({ + 'package.json': JSON.stringify({ name: 'app', dependencies: { 'ext-api': '^1.0.0' } }), + 'src/typings/ext-api.d.ts': "declare module 'ext-api' {\n export class ApiClient {\n update(): void;\n }\n}\n", + 'src/other.ts': 'export class ApiClient {\n update() { return 1; }\n}\n', + 'src/use.ts': + "import { ApiClient } from 'ext-api';\n" + + 'export class Service {\n private readonly client: ApiClient = new ApiClient();\n' + + ' run() {\n return this.client.update();\n }\n}\n' + + 'export function f() {\n const api = new ApiClient();\n return api.update();\n}\n', + }); + expect(calls.filter((c) => c.includes('.update'))).toEqual([ + 'src/use.ts: api.update -> src/typings/ext-api.d.ts::ApiClient::update', + 'src/use.ts: this.client.update -> src/typings/ext-api.d.ts::ApiClient::update', + ]); + }, 60_000); + + it('does the same for a Flow libdef, and for a `node:` import of the module a libdef declares', async () => { + // react-native's `flow-typed/npm/tinybench_v4.1.x.js` declares + // `tinybench`, and `flow-typed/environment/node.js` Node's modules. + const calls = await callsOf({ + 'package.json': JSON.stringify({ name: 'app', dependencies: { 'ext-bench': '^1.0.0' } }), + 'flow-typed/npm/ext-bench.js': "/**\n * @flow strict\n */\ndeclare module 'ext-bench' {\n declare export class Bench {\n run(): void;\n }\n}\n", + 'flow-typed/environment/node.d.ts': "declare module 'timers' {\n export class Timeout {\n refresh(): Timeout;\n }\n}\n", + 'src/other.js': 'export class Bench {\n run() { return 1; }\n}\nexport class Timeout {\n refresh() { return this; }\n}\n', + 'src/use.js': + "import { Bench } from 'ext-bench';\n" + + 'export function b() {\n const bench = new Bench();\n return bench.run();\n}\n', + 'src/timer.ts': + "import { Timeout } from 'node:timers';\n" + + 'export function t(timeout: Timeout) {\n return timeout.refresh();\n}\n', + }); + expect(calls.filter((c) => c.includes('bench.run') || c.includes('timeout.refresh'))).toEqual([ + 'src/timer.ts: timeout.refresh -> flow-typed/environment/node.d.ts::Timeout::refresh', + 'src/use.js: bench.run -> flow-typed/npm/ext-bench.js::Bench::run', + ]); + }, 60_000); +}); diff --git a/__tests__/ts-wrapped-field-initializers.test.ts b/__tests__/ts-wrapped-field-initializers.test.ts new file mode 100644 index 0000000000..3df78619b2 --- /dev/null +++ b/__tests__/ts-wrapped-field-initializers.test.ts @@ -0,0 +1,233 @@ +/** + * A TypeScript `this.` call on a field initialized through a wrapper + * that hands back its argument — vscode's `this._register(new Emitter())` + * and `this._store.add(new Emitter())` — links through the wrapped class. + * + * The field reader knew `field: T`, `field: typeof X` and `field = new X()`, + * so vscode's most common declaration, `private readonly _onDidChange = + * this._register(new Emitter())`, gave the field no type and its + * `fire()` calls linked nowhere. A wrapper counts only when its own + * declaration returns its argument (`_register(o: T): + * T`) and its call ends the statement: `this.box(value)` may return a box of + * it, and `this._register(new DomEmitter(…)).event` a member of it. + */ +import { describe, it, expect, afterEach } from 'vitest'; +import * as fs from 'fs'; +import * as os from 'os'; +import * as path from 'path'; +import CodeGraph from '../src/index'; + +let roots: string[] = []; +let graphs: CodeGraph[] = []; + +afterEach(() => { + for (const graph of graphs) graph.close(); + graphs = []; + for (const root of roots) fs.rmSync(root, { recursive: true, force: true }); + roots = []; +}); + +/** Index `files` and return each call edge as `: -> ::`. */ +async function callsOf(files: Record): Promise { + const root = fs.mkdtempSync(path.join(os.tmpdir(), 'cg-ts-wrapped-fields-')); + roots.push(root); + for (const [file, text] of Object.entries(files)) { + fs.mkdirSync(path.dirname(path.join(root, file)), { recursive: true }); + fs.writeFileSync(path.join(root, file), text); + } + const graph = await CodeGraph.init(root, { index: true }); + graphs.push(graph); + const nodes = graph.getFiles().flatMap((f) => graph.getNodesInFile(f.path)); + const byId = new Map(nodes.map((n) => [n.id, n])); + return graph.getOutgoingEdgesFrom(nodes.map((n) => n.id), ['calls']) + .map((e) => { + const target = byId.get(e.target); + return `${byId.get(e.source)?.filePath}: ${e.metadata?.refName} -> ${target?.filePath}::${target?.qualifiedName}`; + }) + .sort(); +} + +/** + * vscode's lifecycle wrappers, the `Emitter` the app imports, and a decoy + * `Emitter` nearer the app (`src/app/legacy`) that a guess by method name or + * folder would pick. + */ +const LIFECYCLE = { + 'package.json': JSON.stringify({ name: 'app' }), + 'src/base/lifecycle.ts': + 'export interface IDisposable {\n dispose(): void;\n}\n' + + 'export class DisposableStore implements IDisposable {\n' + + ' private readonly items: IDisposable[] = [];\n' + + ' add(o: T): T {\n this.items.push(o);\n return o;\n }\n' + + ' dispose() {}\n' + + '}\n' + + 'export abstract class Disposable implements IDisposable {\n' + + ' protected readonly _store = new DisposableStore();\n' + + ' protected _register(o: T): T {\n return this._store.add(o);\n }\n' + + ' dispose() {}\n' + + '}\n', + 'src/base/event.ts': 'export class Emitter {\n fire(event?: T) {\n return event;\n }\n dispose() {}\n}\n', + 'src/app/legacy/event.ts': 'export class Emitter {\n fire() {\n return 0;\n }\n dispose() {}\n}\n', +}; + +const IMPORTS = "import { Disposable, DisposableStore } from '../base/lifecycle';\nimport { Emitter } from '../base/event';\n"; + +describe('a this. call on a field a wrapper initializes', () => { + it('reads `this._register(new X())` as an X when the inherited `_register` returns its argument', async () => { + const calls = await callsOf({ + ...LIFECYCLE, + 'src/app/model.ts': + IMPORTS + + 'export class Model extends Disposable {\n' + + ' private readonly _onDidChange = this._register(new Emitter());\n' + + ' private readonly _onDidMove = this._register(new Emitter(\n' + + ' ));\n' + + ' private readonly _onDidOpen;\n' + + ' constructor() {\n super();\n this._onDidOpen = this._register(new Emitter());\n }\n' + + " change() {\n this._onDidChange.fire('a');\n this._onDidMove.fire(1);\n this._onDidOpen.fire();\n }\n" + + '}\n', + }); + expect(calls.filter((c) => c.includes('.fire'))).toEqual([ + 'src/app/model.ts: this._onDidChange.fire -> src/base/event.ts::Emitter::fire', + 'src/app/model.ts: this._onDidMove.fire -> src/base/event.ts::Emitter::fire', + 'src/app/model.ts: this._onDidOpen.fire -> src/base/event.ts::Emitter::fire', + ]); + }, 60_000); + + it('reads `this..add(new X())` through the class the store field is declared as', async () => { + const calls = await callsOf({ + ...LIFECYCLE, + 'src/app/view.ts': + IMPORTS + + 'export class View extends Disposable {\n' + + ' private readonly _disposables = new DisposableStore();\n' + + ' private readonly _onDidShow = this._store.add(new Emitter());\n' + + ' private readonly _onDidHide = this._disposables.add(new Emitter());\n' + + ' show() {\n this._onDidShow.fire();\n }\n' + + ' hide() {\n this._onDidHide.fire();\n }\n' + + '}\n', + }); + expect(calls.filter((c) => c.includes('.fire'))).toEqual([ + 'src/app/view.ts: this._onDidHide.fire -> src/base/event.ts::Emitter::fire', + 'src/app/view.ts: this._onDidShow.fire -> src/base/event.ts::Emitter::fire', + ]); + }, 60_000); + + it('finds the wrapper and the store as many classes up as vscode editors inherit them from `Disposable`', async () => { + // `… extends EditorPane extends Composite extends Component extends Themable extends Disposable` + const chain = ['Themable', 'Component', 'Composite', 'Pane', 'EditorPane']; + const files: Record = { ...LIFECYCLE }; + chain.forEach((name, i) => { + const base = i === 0 ? ['Disposable', '../base/lifecycle'] : [chain[i - 1]!, `./${chain[i - 1]!.toLowerCase()}`]; + files[`src/app/${name.toLowerCase()}.ts`] = `import { ${base[0]} } from '${base[1]}';\nexport class ${name} extends ${base[0]} {}\n`; + }); + const calls = await callsOf({ + ...files, + 'src/app/editor.ts': + "import { EditorPane } from './editorpane';\nimport { Emitter } from '../base/event';\n" + + 'export class Editor extends EditorPane {\n' + + ' private readonly _onDidChange = this._register(new Emitter());\n' + + ' private readonly _onDidShow = this._store.add(new Emitter());\n' + + ' run() {\n this._onDidChange.fire();\n this._onDidShow.fire();\n }\n' + + '}\n', + }); + // `_onDidShow` needs `_store` found on `Disposable` too. + expect(calls.filter((c) => c.includes('.fire'))).toEqual([ + 'src/app/editor.ts: this._onDidChange.fire -> src/base/event.ts::Emitter::fire', + 'src/app/editor.ts: this._onDidShow.fire -> src/base/event.ts::Emitter::fire', + ]); + }, 60_000); + + it('reads them in files with CRLF line endings, as a Windows checkout has', async () => { + const files: Record = { + ...LIFECYCLE, + 'src/app/model.ts': + IMPORTS + + 'class DomEmitter {\n readonly event = (listener: () => void) => listener;\n dispose() {}\n}\n' + + 'export class Model extends Disposable {\n' + + ' private readonly _onDidChange = this._register(new Emitter());\n' + + ' private readonly _onDidShow = this._store.add(new Emitter());\n' + + ' private readonly _onDidHide = this._register(new Emitter())\n' + + ' private readonly onKeyDown = this._register(new DomEmitter()).event;\n' + + " change() {\n this._onDidChange.fire('a');\n this._onDidShow.fire();\n this._onDidHide.fire();\n this.onKeyDown.dispose();\n }\n" + + '}\n', + }; + const calls = await callsOf(Object.fromEntries(Object.entries(files).map(([file, text]) => [file, text.replace(/\n/g, '\r\n')]))); + expect(calls.filter((c) => c.includes('.fire') || c.includes('.dispose'))).toEqual([ + 'src/app/model.ts: this._onDidChange.fire -> src/base/event.ts::Emitter::fire', + 'src/app/model.ts: this._onDidHide.fire -> src/base/event.ts::Emitter::fire', + 'src/app/model.ts: this._onDidShow.fire -> src/base/event.ts::Emitter::fire', + ]); + }, 60_000); + + it("doesn't read a wrapper whose declaration doesn't return its argument", async () => { + const calls = await callsOf({ + ...LIFECYCLE, + 'src/app/box.ts': + IMPORTS + + 'class Box {\n constructor(readonly value: T) {}\n}\n' + + 'class Widget {\n fire() {}\n}\n' + + 'class FancyWidget extends Widget {\n fire() {}\n}\n' + + 'export class Holder extends Disposable {\n' + + ' private readonly _boxed = this.box(new Emitter());\n' + + ' private readonly _kept = this.keep(new Emitter());\n' + + ' private readonly _widget = this.replace(new FancyWidget());\n' + + ' private readonly items = new Set>();\n' + + ' private readonly _set = this.items.add(new Emitter());\n' + + ' private box(value: T): Box {\n return new Box(value);\n }\n' + + ' private keep(value: T) {\n return value;\n }\n' + + // Typed with a class, not a type parameter of its own: another Widget may come back. + ' private replace(widget: Widget): Widget {\n return widget instanceof FancyWidget ? new Widget() : widget;\n }\n' + + " run() {\n this._boxed.fire('a');\n this._kept.fire('b');\n this._widget.fire();\n this._set.fire('c');\n }\n" + + '}\n', + 'src/app/plain.ts': + "import { Emitter } from '../base/event';\n" + + 'export class Plain {\n' + + ' private readonly _onDidChange = this._register(new Emitter());\n' + + ' run() {\n this._onDidChange.fire();\n }\n' + + '}\n', + }); + expect(calls.filter((c) => c.includes('.fire'))).toEqual([]); + }, 60_000); + + it("doesn't read the wrapped class when a member of what the wrapper returns is taken", async () => { + const calls = await callsOf({ + ...LIFECYCLE, + 'src/app/input.ts': + IMPORTS + + 'class DomEmitter {\n readonly event = (listener: () => void) => listener;\n dispose() {}\n}\n' + + 'export class Input extends Disposable {\n' + + ' private readonly onKeyDown = this._register(new DomEmitter()).event;\n' + + ' private readonly onKeyUp = this._register(new DomEmitter())\n .event;\n' + + ' run() {\n this.onKeyDown.dispose();\n this.onKeyUp.dispose();\n }\n' + + '}\n', + }); + expect(calls.filter((c) => c.includes('.dispose'))).toEqual([]); + }, 60_000); + + it("looks a base class's supertype up where that class is written, not at the calling line", async () => { + // `wrap`'s parameter shares the supertype's name and its function spans + // line 5, the line of the call in model.ts. + const calls = await callsOf({ + ...LIFECYCLE, + 'src/base/store.ts': + "import { Emitter } from './event';\n" + + 'export class Store extends Emitter {}\n' + + 'export function wrap(Emitter: number) {\n' + + ' const unused = 1;\n' + + ' return Emitter + unused;\n' + + '}\n', + 'src/app/model.ts': + "import { Store } from '../base/store';\n" + + 'export class Model {\n' + + ' private readonly store: Store = new Store();\n' + + ' run() {\n' + + ' this.store.fire();\n' + + ' }\n' + + '}\n', + }); + expect(calls.filter((c) => c.includes('.fire'))).toEqual([ + 'src/app/model.ts: this.store.fire -> src/base/event.ts::Emitter::fire', + ]); + }, 60_000); +}); diff --git a/__tests__/tsconfig-baseurl-imports.test.ts b/__tests__/tsconfig-baseurl-imports.test.ts new file mode 100644 index 0000000000..47e2ebad63 --- /dev/null +++ b/__tests__/tsconfig-baseurl-imports.test.ts @@ -0,0 +1,447 @@ +/** + * Bare specifiers that name a project file through the importing app's own + * tsconfig / jsconfig: a `baseUrl` with no `paths` (berry, matx) or a + * catch-all `"*": ["./src/*"]` (mantis). CRA and Vite admin templates write + * nearly every cross-file import this way (`import MainLayout from + * 'layout/MainLayout'`), and each one used to be taken for an npm package: + * the import stayed unresolved and its names linked by bare-name matching, + * often into another app of the same repository. + * + * Locked in: + * - the importing app's own config decides (two apps, two baseUrls) + * - only an indexed file binds; a specifier that names none stays unresolved + * - a package the app's package.json declares, or a Node built-in, never + * binds to a same-named project folder or file, also under a root `"*"` + * - a route's `lazy(() => import('views/x'))` renders `views/x/index.jsx`, + * and the layout around it links through the same kind of import + * - a class extending one imported this way keeps its `extends` edge + */ +import { describe, it, expect, beforeAll, afterAll } from 'vitest'; +import * as fs from 'fs'; +import * as os from 'os'; +import * as path from 'path'; +import { CodeGraph } from '../src'; +import { resolveImportPath } from '../src/resolution/import-resolver'; +import type { AliasMap } from '../src/resolution/path-aliases'; +import type { ResolutionContext } from '../src/resolution'; + +const ROOT = path.join(os.tmpdir(), 'cg-baseurl-stub'); + +function stubContext(files: string[], opts: { + nearest?: (fromFile: string) => AliasMap | null; + project?: AliasMap | null; + declared?: string[]; + noPackageCheck?: boolean; +}): ResolutionContext { + const set = new Set(files); + return { + getNodesInFile: () => [], + getNodesByName: () => [], + getNodesByQualifiedName: () => [], + getNodesByKind: () => [], + fileExists: (p: string) => set.has(p), + readFile: () => null, + getProjectRoot: () => ROOT, + getAllFiles: () => files, + getImportMappings: () => [], + getNearestAliases: opts.nearest ?? (() => null), + getProjectAliases: () => opts.project ?? null, + ...(opts.noPackageCheck ? {} : { isDeclaredPackage: (source: string) => (opts.declared ?? []).includes(source.split('/')[0]!) }), + } as unknown as ResolutionContext; +} + +const baseUrlOnly = (dir: string): AliasMap => ({ baseUrl: path.join(ROOT, dir), declaresBaseUrl: true, patterns: [] }); + +describe('resolving a bare specifier through the app’s own config', () => { + it('reads a nested app’s baseUrl, down to an index.jsx (berry)', () => { + const files = ['vite/src/routes/MainRoutes.jsx', 'vite/src/layout/MainLayout/index.jsx', 'vite/src/views/dashboard/Default/index.jsx']; + const ctx = stubContext(files, { nearest: (f) => (f.startsWith('vite/') ? baseUrlOnly('vite/src') : null) }); + expect(resolveImportPath('layout/MainLayout', 'vite/src/routes/MainRoutes.jsx', 'jsx', ctx)).toBe('vite/src/layout/MainLayout/index.jsx'); + // A route table resolves a lazily loaded module as TypeScript, whatever it is written in. + expect(resolveImportPath('views/dashboard/Default', 'vite/src/routes/MainRoutes.jsx', 'typescript', ctx)).toBe('vite/src/views/dashboard/Default/index.jsx'); + }); + + it('reads a catch-all "*" from the config’s directory (mantis)', () => { + const star: AliasMap = { + baseUrl: path.join(ROOT, 'vite'), + declaresBaseUrl: false, + patterns: [{ prefix: '', suffix: '', hasWildcard: true, replacements: ['./src/*'] }], + }; + const ctx = stubContext(['vite/src/routes/LoginRoutes.jsx', 'vite/src/pages/auth/Register.jsx'], { nearest: () => star }); + expect(resolveImportPath('pages/auth/Register', 'vite/src/routes/LoginRoutes.jsx', 'jsx', ctx)).toBe('vite/src/pages/auth/Register.jsx'); + }); + + it('reads the root jsconfig when no nearer config has one (matx)', () => { + const ctx = stubContext(['src/app/routes.jsx', 'src/app/views/dashboard/Analytics.jsx'], { project: baseUrlOnly('src') }); + expect(resolveImportPath('app/views/dashboard/Analytics', 'src/app/routes.jsx', 'jsx', ctx)).toBe('src/app/views/dashboard/Analytics.jsx'); + }); + + it('uses the importing app’s baseUrl, not another app’s', () => { + const files = ['vite/src/views/Page.jsx', 'vite/src/utils/format.js', 'remix/app/routes/index.jsx', 'remix/app/utils/format.js']; + const ctx = stubContext(files, { + nearest: (f) => (f.startsWith('vite/') ? baseUrlOnly('vite/src') : f.startsWith('remix/') ? baseUrlOnly('remix/app') : null), + }); + expect(resolveImportPath('utils/format', 'vite/src/views/Page.jsx', 'jsx', ctx)).toBe('vite/src/utils/format.js'); + expect(resolveImportPath('utils/format', 'remix/app/routes/index.jsx', 'jsx', ctx)).toBe('remix/app/utils/format.js'); + }); + + it('never binds a declared package to a same-named project folder', () => { + const files = ['src/hooks/useSearch.js', 'src/lodash/index.js']; + expect(resolveImportPath('lodash', 'src/hooks/useSearch.js', 'javascript', stubContext(files, { project: baseUrlOnly('src'), declared: ['lodash'] }))).toBeNull(); + // Only the declaration keeps it out: the same folder is the project's when nothing declares `lodash`. + expect(resolveImportPath('lodash', 'src/hooks/useSearch.js', 'javascript', stubContext(files, { project: baseUrlOnly('src') }))).toBe('src/lodash/index.js'); + // A context that cannot tell packages apart resolves nothing this way. + expect(resolveImportPath('lodash', 'src/hooks/useSearch.js', 'javascript', stubContext(files, { project: baseUrlOnly('src'), noPackageCheck: true }))).toBeNull(); + }); + + it('lets a declared package reach a declaration file the project keeps for it, never a module', () => { + // cord-field's shape: `"*": ["./typings/*"]` holds types for untyped packages. + const typings: AliasMap = { + baseUrl: path.join(ROOT, 'src'), + declaresBaseUrl: true, + patterns: [{ prefix: '', suffix: '', hasWildcard: true, replacements: ['./typings/*'] }], + }; + const files = ['src/scenes/Page.tsx', 'src/typings/legacy-widgets.d.ts', 'src/axios/index.ts']; + const ctx = stubContext(files, { project: typings, declared: ['legacy-widgets', 'axios'] }); + expect(resolveImportPath('legacy-widgets', 'src/scenes/Page.tsx', 'tsx', ctx)).toBe('src/typings/legacy-widgets.d.ts'); + // `baseUrl` reads `src/axios/index.ts`, the app's own wrapper: the package stays the package. + expect(resolveImportPath('axios', 'src/scenes/Page.tsx', 'tsx', ctx)).toBeNull(); + }); + + it('leaves a specifier that names no project file unresolved', () => { + const ctx = stubContext(['src/App.jsx'], { project: baseUrlOnly('src') }); + expect(resolveImportPath('react', 'src/App.jsx', 'jsx', ctx)).toBeNull(); + expect(resolveImportPath('virtual:pwa-register', 'src/App.jsx', 'jsx', ctx)).toBeNull(); + }); + + it('binds only a file the index holds, not a folder or node_modules on disk', () => { + // `fileExists` falls back to the disk: true for `src/assets` (a folder) and + // for a package installed under a `"*"` target like `node_modules/*`. + const onDisk = new Set(['src/App.jsx', 'src/assets', 'node_modules/history/index.js']); + const indexed = new Set(['src/App.jsx']); + const star: AliasMap = { + baseUrl: ROOT, + declaresBaseUrl: true, + patterns: [{ prefix: '', suffix: '', hasWildcard: true, replacements: ['src/*', 'node_modules/*'] }], + }; + const ctx = { + ...stubContext([...indexed], { project: star }), + fileExists: (p: string) => onDisk.has(p), + isIndexedFile: (p: string) => indexed.has(p), + } as unknown as ResolutionContext; + expect(resolveImportPath('assets', 'src/App.jsx', 'jsx', ctx)).toBeNull(); + expect(resolveImportPath('history', 'src/App.jsx', 'jsx', ctx)).toBeNull(); + }); + + it('does not read bare specifiers from a config with paths but no baseUrl', () => { + const atOnly: AliasMap = { + baseUrl: ROOT, + declaresBaseUrl: false, + patterns: [{ prefix: '@/', suffix: '', hasWildcard: true, replacements: ['./src/*'] }], + }; + const ctx = stubContext(['src/App.jsx', 'components/Button.jsx', 'src/components/Button.jsx'], { project: atOnly }); + expect(resolveImportPath('components/Button', 'src/App.jsx', 'jsx', ctx)).toBeNull(); + expect(resolveImportPath('@/components/Button', 'src/App.jsx', 'jsx', ctx)).toBe('src/components/Button.jsx'); + }); +}); + +function writeTree(root: string, files: Record): void { + for (const [rel, content] of Object.entries(files)) { + fs.mkdirSync(path.dirname(path.join(root, rel)), { recursive: true }); + fs.writeFileSync(path.join(root, rel), content); + } +} + +describe('two admin apps with their own baseUrl (berry shape)', () => { + let root = ''; + let cg: CodeGraph; + + beforeAll(async () => { + root = fs.mkdtempSync(path.join(os.tmpdir(), 'cg-baseurl-apps-')); + writeTree(root, { + 'package.json': JSON.stringify({ name: 'admin-templates', private: true }), + 'vite/package.json': JSON.stringify({ name: 'vite-app', dependencies: { react: '^18', 'react-router-dom': '^6', lodash: '^4' } }), + 'vite/jsconfig.json': JSON.stringify({ compilerOptions: { baseUrl: 'src', jsx: 'react-jsx' } }), + 'vite/src/routes/index.jsx': `import { createBrowserRouter } from 'react-router-dom'; +import MainRoutes from './MainRoutes'; + +const router = createBrowserRouter([MainRoutes]); + +export default router; +`, + 'vite/src/routes/MainRoutes.jsx': `import { lazy } from 'react'; + +import MainLayout from 'layout/MainLayout'; +import Loadable from 'ui-component/Loadable'; + +const DashboardDefault = Loadable(lazy(() => import('views/dashboard/Default'))); + +const MainRoutes = { + path: '/', + element: , + children: [ + { + path: 'dashboard', + element: + } + ] +}; + +export default MainRoutes; +`, + 'vite/src/layout/MainLayout/index.jsx': `export default function MainLayout() { + return
; +} +`, + 'vite/src/ui-component/Loadable.jsx': `export default function Loadable(Component) { + return (props) => ; +} +`, + 'vite/src/views/dashboard/Default/index.jsx': `import { formatDate } from 'utils/format'; + +export default function Dashboard() { + return
{formatDate(new Date())}
; +} +`, + 'vite/src/utils/format.js': `export function formatDate(d) { + return String(d); +} +`, + // A one-segment specifier, and a binding named like another module. + 'vite/src/config.js': `export const DEFAULT_THEME_MODE = 'system'; +export const themes = ['light', 'dark']; +`, + 'vite/src/themes/index.jsx': `export default function ThemeCustomization({ children }) { + return children; +} +`, + 'vite/src/layout/Customization/index.jsx': `import { DEFAULT_THEME_MODE, themes } from 'config'; + +export default function Customization() { + return themes.includes(DEFAULT_THEME_MODE); +} +`, + // A folder named like a dependency, and a file named like a Node built-in. + 'vite/src/lodash/index.js': `export function debounce(fn) { + return fn; +} +`, + 'vite/src/events.js': `export class EventEmitter {} +`, + 'vite/src/hooks/useSearch.js': `import { debounce } from 'lodash'; +import { EventEmitter } from 'events'; + +export function useSearch() { + return debounce(() => new EventEmitter()); +} +`, + 'vite/src/components/BasePanel.js': `export default class BasePanel {} +`, + 'vite/src/components/Panel.js': `import BasePanel from 'components/BasePanel'; + +export class Panel extends BasePanel {} +`, + 'remix/package.json': JSON.stringify({ name: 'remix-app', dependencies: { react: '^18' } }), + 'remix/jsconfig.json': JSON.stringify({ compilerOptions: { baseUrl: 'app' } }), + 'remix/app/utils/format.js': `export function formatDate(d) { + return d.toISOString(); +} +`, + 'remix/app/routes/index.jsx': `import { formatDate } from 'utils/format'; + +export default function Index() { + return formatDate(new Date()); +} +`, + }); + cg = await CodeGraph.init(root, { index: true }); + }); + + afterAll(() => { + cg?.close(); + if (root) fs.rmSync(root, { recursive: true, force: true, maxRetries: 5 }); + }); + + /** The files `file`'s nodes import, by path. */ + const importedFiles = (file: string): string[] => + cg.getOutgoingEdgesFrom(cg.getNodesInFile(file).map((n) => n.id)) + .filter((e) => e.kind === 'imports') + .map((e) => cg.getNode(e.target)!.filePath); + + /** What `file`'s import of `ref` (a module specifier or a binding) links to, as `kind:name@path`. */ + const importTargets = (file: string, ref: string): string[] => + cg.getOutgoingEdgesFrom(cg.getNodesInFile(file).map((n) => n.id)) + .filter((e) => e.kind === 'imports' && (e.metadata as Record | undefined)?.refName === ref) + .map((e) => `${cg.getNode(e.target)!.kind}:${cg.getNode(e.target)!.name}@${cg.getNode(e.target)!.filePath}`); + + const routeLinks = (name: string, layout: boolean): string[] => { + const route = cg.getNodesByKind('route').find((r) => r.name === name); + if (!route) return []; + return cg.getOutgoingEdges(route.id) + .filter((e) => e.kind === 'references' && Boolean((e.metadata as Record | undefined)?.layout) === layout) + .map((e) => `${cg.getNode(e.target)!.name}@${cg.getNode(e.target)!.filePath}`); + }; + + it('links an import written from baseUrl to the file it names', () => { + const file = 'vite/src/routes/MainRoutes.jsx'; + expect(importTargets(file, 'layout/MainLayout')).toEqual(['file:index.jsx@vite/src/layout/MainLayout/index.jsx']); + expect(importTargets(file, 'ui-component/Loadable')).toEqual(['file:Loadable.jsx@vite/src/ui-component/Loadable.jsx']); + }); + + it('links a one-segment module, and reads a binding named like another module as the binding', () => { + const file = 'vite/src/layout/Customization/index.jsx'; + expect(importTargets(file, 'config')).toEqual(['file:config.js@vite/src/config.js']); + expect(importTargets(file, 'themes')).toEqual(['constant:themes@vite/src/config.js']); + expect(importedFiles(file)).not.toContain('vite/src/themes/index.jsx'); + }); + + it('calls the importing app’s own function, not the other app’s namesake', () => { + const callees = (fn: string, file: string) => { + const node = cg.getNodesInFile(file).find((n) => n.name === fn)!; + return cg.getCallees(node.id).map((c) => c.node.filePath); + }; + expect(callees('Dashboard', 'vite/src/views/dashboard/Default/index.jsx')).toContain('vite/src/utils/format.js'); + expect(callees('Dashboard', 'vite/src/views/dashboard/Default/index.jsx')).not.toContain('remix/app/utils/format.js'); + expect(callees('Index', 'remix/app/routes/index.jsx')).toContain('remix/app/utils/format.js'); + expect(callees('Index', 'remix/app/routes/index.jsx')).not.toContain('vite/src/utils/format.js'); + }); + + it('renders a lazily loaded page and the layout around it', () => { + expect(routeLinks('/dashboard', false)).toEqual(['Dashboard@vite/src/views/dashboard/Default/index.jsx']); + expect(routeLinks('/dashboard', true)).toEqual(['MainLayout@vite/src/layout/MainLayout/index.jsx']); + }); + + it('keeps a declared package and a Node built-in out of same-named project files', () => { + const imported = importedFiles('vite/src/hooks/useSearch.js'); + expect(imported).not.toContain('vite/src/lodash/index.js'); + expect(imported).not.toContain('vite/src/events.js'); + }); + + it('keeps the extends edge of a class whose base is imported from baseUrl', () => { + const panel = cg.getNodesInFile('vite/src/components/Panel.js').find((n) => n.name === 'Panel')!; + const supers = cg.getOutgoingEdges(panel.id).filter((e) => e.kind === 'extends').map((e) => cg.getNode(e.target)!.filePath); + expect(supers).toEqual(['vite/src/components/BasePanel.js']); + }); +}); + +describe('a root catch-all "*" beside a folder named like a dependency', () => { + let root = ''; + let cg: CodeGraph; + + beforeAll(async () => { + root = fs.mkdtempSync(path.join(os.tmpdir(), 'cg-baseurl-star-')); + writeTree(root, { + 'package.json': JSON.stringify({ name: 'star-app', dependencies: { axios: '^1', react: '^18' } }), + 'jsconfig.json': JSON.stringify({ compilerOptions: { paths: { '*': ['./src/*'] } } }), + // The app's own configured client, in a folder named after the package it wraps. + 'src/axios/index.js': `import axios from 'axios'; + +const instance = axios.create({ baseURL: '/api' }); + +export default instance; +`, + 'src/components/Button.jsx': `export default function Button() { + return