@suss/adapter-ruby 0.33.1 → 0.34.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +10 -10
- package/dist/index.cjs +5679 -1641
- package/dist/index.d.cts +727 -399
- package/dist/index.d.ts +727 -399
- package/dist/index.js +5679 -1588
- package/grammar/README.md +23 -21
- package/package.json +9 -9
package/dist/index.d.ts
CHANGED
|
@@ -1,15 +1,25 @@
|
|
|
1
1
|
import { Database } from '@suss/datalog';
|
|
2
2
|
import { Tree, Node } from 'web-tree-sitter';
|
|
3
3
|
export { Node as RbNode, Tree as RbTree } from 'web-tree-sitter';
|
|
4
|
-
import { TypeShape, Effect, BehavioralSummary } from '@suss/behavioral-ir';
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
4
|
+
import { TypeShape, RequestSpellingMetadata, Effect, BehavioralSummary } from '@suss/behavioral-ir';
|
|
5
|
+
import { UnwrapsByName, WhyExplained } from '@suss/resolution';
|
|
6
|
+
import { RawCodeStructure, TimingReport, ExtractionReport, CacheDiagnostic, ExtractorOptions, DeclaredModule, KeptParses } from '@suss/extractor';
|
|
7
7
|
import { Value } from '@suss/values';
|
|
8
8
|
|
|
9
9
|
/**
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
*
|
|
10
|
+
* Loads the Ruby grammar into web-tree-sitter and parses source with it.
|
|
11
|
+
*
|
|
12
|
+
* tree-sitter runs as WASM, so the package needs no native build step.
|
|
13
|
+
* The rest of the adapter never imports `web-tree-sitter` directly. It
|
|
14
|
+
* goes through `parseRuby` and the node helpers, so moving to a different
|
|
15
|
+
* Ruby grammar would change only this module. The Python adapter's
|
|
16
|
+
* parser works the same way.
|
|
17
|
+
*/
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Uses a new `Parser` for every call, so two parses running at once never
|
|
21
|
+
* share one parser's mutable `language` field. The compiled `Language` is
|
|
22
|
+
* loaded once per process and shared.
|
|
13
23
|
*/
|
|
14
24
|
declare function parseRuby(source: string): Promise<Tree>;
|
|
15
25
|
/**
|
|
@@ -38,40 +48,44 @@ declare function bodyStatements(body: Node): Node[];
|
|
|
38
48
|
* included; the caller descends into that one itself.
|
|
39
49
|
*/
|
|
40
50
|
declare function nestedStatements(stmt: Node): Node[];
|
|
41
|
-
/**
|
|
51
|
+
/** A pack's declaration of one body-block call, with its optional flags defaulted. */
|
|
42
52
|
interface BodyBlockKind {
|
|
43
|
-
/** Whether the library
|
|
53
|
+
/** Whether the library offers the call only to modules. In a class, a call of the same name is something else. */
|
|
44
54
|
readonly moduleOnly: boolean;
|
|
45
|
-
/** Whether a `def` in the block
|
|
55
|
+
/** Whether a `def` in the block defines a method on the class itself instead of on an instance. */
|
|
46
56
|
readonly definesClassMethods: boolean;
|
|
47
57
|
}
|
|
48
58
|
/**
|
|
49
|
-
* The calls
|
|
50
|
-
*
|
|
51
|
-
*
|
|
59
|
+
* The calls whose block runs as part of the surrounding class or module
|
|
60
|
+
* body, keyed by the call's name as a project writes it. Ruby has no such
|
|
61
|
+
* call of its own, so this is empty unless a pack declares one.
|
|
52
62
|
*/
|
|
53
63
|
type BodyBlocks = ReadonlyMap<string, BodyBlockKind>;
|
|
54
|
-
/**
|
|
64
|
+
/** Whether a call's block configures the call itself, so its statements are not part of the body. */
|
|
55
65
|
type BlockConfigures = (call: Node) => boolean;
|
|
56
66
|
/**
|
|
57
67
|
* Every statement a body runs, in source order. Ruby runs a class body
|
|
58
|
-
* like any other code, so a declaration can
|
|
59
|
-
*
|
|
60
|
-
*
|
|
68
|
+
* like any other code, so a declaration can be inside an `if`, an `.each`
|
|
69
|
+
* block, a `begin` or a `class_eval`. Reading only the body's direct
|
|
70
|
+
* children would miss those without any sign.
|
|
61
71
|
*
|
|
62
|
-
* `blockConfigures`
|
|
63
|
-
* `field :x, String do argument :q, String end` declares an
|
|
64
|
-
*
|
|
72
|
+
* `blockConfigures` picks out the calls whose block is not part of the
|
|
73
|
+
* body. `field :x, String do argument :q, String end` declares an
|
|
74
|
+
* argument on the field, so that block is skipped.
|
|
65
75
|
*/
|
|
66
76
|
declare function runStatements(body: Node, blockConfigures?: BlockConfigures): Node[];
|
|
67
77
|
/** The text inside a plain string node, with the quotes removed. A string with interpolation returns null. */
|
|
68
78
|
declare function stringLiteralValue(node: Node): string | null;
|
|
69
|
-
/**
|
|
79
|
+
/** A `simple_symbol`'s name without its leading colon, or null for any other node. */
|
|
70
80
|
declare function symbolValue(node: Node): string | null;
|
|
71
|
-
/** A `pair`
|
|
81
|
+
/** A `pair` key's name when it is written as `key:`, or null for a key written as a string or an expression. */
|
|
72
82
|
declare function hashKeySymbolName(node: Node): string | null;
|
|
73
83
|
declare function booleanLiteralValue(node: Node): boolean | null;
|
|
74
|
-
/**
|
|
84
|
+
/**
|
|
85
|
+
* A call's arguments, split into positional and keyword. tree-sitter puts
|
|
86
|
+
* keyword arguments in the argument list as `pair` nodes, with no hash
|
|
87
|
+
* node around them. Only keys written as `key:` are read.
|
|
88
|
+
*/
|
|
75
89
|
interface CallArgs {
|
|
76
90
|
positional: Node[];
|
|
77
91
|
keyword: Record<string, Node>;
|
|
@@ -79,83 +93,95 @@ interface CallArgs {
|
|
|
79
93
|
declare function readCallArgs(argumentList: Node | null): CallArgs;
|
|
80
94
|
|
|
81
95
|
/**
|
|
82
|
-
* Finds the file
|
|
96
|
+
* Finds the file that defines a constant.
|
|
83
97
|
*
|
|
84
|
-
* A Ruby codebase
|
|
85
|
-
*
|
|
86
|
-
* constant's
|
|
98
|
+
* A Ruby codebase finds that file by a naming convention, with no load
|
|
99
|
+
* graph a static reader could follow. So the adapter builds one path from
|
|
100
|
+
* the constant's name and looks for it under the configured root and the
|
|
87
101
|
* directories Rails autoloads from. No other spelling is tried.
|
|
88
102
|
*/
|
|
89
|
-
/** A pack picks a convention by name, and
|
|
103
|
+
/** A pack picks a convention by name, and `PATH_CONVENTIONS` maps each name to its code. */
|
|
90
104
|
type ConstantPathConvention = "railsUnderscore";
|
|
91
105
|
/**
|
|
92
|
-
*
|
|
93
|
-
*
|
|
94
|
-
* project registers
|
|
95
|
-
*
|
|
96
|
-
* `activity_pub`.
|
|
106
|
+
* A port of ActiveSupport's `String#underscore`, which Rails autoloading
|
|
107
|
+
* runs a constant path through. The inflector treats an acronym the
|
|
108
|
+
* project registers as one word, so with `ActivityPub` registered the
|
|
109
|
+
* path is `activitypub` and never `activity_pub`.
|
|
97
110
|
*/
|
|
98
111
|
declare function underscoreConstantPath(qualifiedName: string, acronyms?: readonly string[]): string;
|
|
99
112
|
/**
|
|
100
|
-
*
|
|
101
|
-
*
|
|
102
|
-
*
|
|
103
|
-
*
|
|
104
|
-
* the
|
|
113
|
+
* What constant lookups have read from the disk during one run. A run
|
|
114
|
+
* looks the same names up many times, and files do not change while it
|
|
115
|
+
* reads them, so each directory list and each answer is read once. Each
|
|
116
|
+
* run makes its own, so the MCP server and watch mode see a file added
|
|
117
|
+
* since the last run.
|
|
118
|
+
*/
|
|
119
|
+
interface ConstantFileCache {
|
|
120
|
+
/** The directories a constant is looked for in under each root, in the order they are tried. */
|
|
121
|
+
readonly autoloadDirectories: Map<string, readonly string[]>;
|
|
122
|
+
/** The file each root and relative path resolved to, or null. */
|
|
123
|
+
readonly resolved: Map<string, string | null>;
|
|
124
|
+
}
|
|
125
|
+
declare function createConstantFileCache(): ConstantFileCache;
|
|
126
|
+
/**
|
|
127
|
+
* The file that defines a constant under `root`, or null when there is
|
|
128
|
+
* none. Rails autoloads from every directory directly under `app`, and
|
|
129
|
+
* from each `concerns` directory under those, so `ApplicationController`
|
|
130
|
+
* is `app/controllers/application_controller.rb` and `Archivable` can be
|
|
131
|
+
* `app/models/concerns/archivable.rb`. The root is tried first, then the
|
|
132
|
+
* directories under it in name order, then their `concerns` directories
|
|
133
|
+
* in the same order. Rails' own autoload glob lists them in that order.
|
|
105
134
|
*/
|
|
106
|
-
declare function resolveConstantFile(root: string, qualifiedName: string, convention: ConstantPathConvention, acronyms?: readonly string[]): string | null;
|
|
135
|
+
declare function resolveConstantFile(root: string, qualifiedName: string, convention: ConstantPathConvention, acronyms?: readonly string[], cache?: ConstantFileCache): string | null;
|
|
107
136
|
|
|
108
137
|
/**
|
|
109
|
-
* The
|
|
138
|
+
* The methods a class defines under a name the source computes.
|
|
110
139
|
*
|
|
111
140
|
* `KEYS.each { |key| define_method(key) { ... } }` defines one method
|
|
112
141
|
* per element of `KEYS`, and a reader of `def` nodes sees none of them.
|
|
113
|
-
*
|
|
114
|
-
*
|
|
142
|
+
* Knowing the names lets a lookup for any other name continue up the
|
|
143
|
+
* ancestry instead of stopping at the class.
|
|
115
144
|
*
|
|
116
|
-
*
|
|
117
|
-
*
|
|
118
|
-
*
|
|
119
|
-
*
|
|
145
|
+
* The calls and their name expressions come in as `definesMethodFrom`
|
|
146
|
+
* and `nameTurnsOn` facts, so this module never reads source itself. Each
|
|
147
|
+
* name goes through the shared value evaluator, which follows names and
|
|
148
|
+
* constants across the whole run. A name that settles only in part
|
|
120
149
|
* becomes a pattern the whole name has to match.
|
|
121
150
|
*/
|
|
122
151
|
|
|
123
152
|
/** What the dynamic definitions in one class define. */
|
|
124
153
|
interface DefinedNames {
|
|
125
|
-
/** Every name
|
|
154
|
+
/** Every name a dynamic definition settled on. */
|
|
126
155
|
readonly names: ReadonlySet<string>;
|
|
127
|
-
/**
|
|
156
|
+
/** One pattern per name that settled only in part. A name matching one may be defined by the class. */
|
|
128
157
|
readonly patterns: readonly RegExp[];
|
|
129
|
-
/** Whether
|
|
158
|
+
/** Whether any definition's name settled on nothing at all. */
|
|
130
159
|
readonly unreadable: boolean;
|
|
131
160
|
}
|
|
132
|
-
/**
|
|
161
|
+
/** What each class defines dynamically, keyed by the class node's value fact key. */
|
|
133
162
|
type DynamicNames = ReadonlyMap<string, DefinedNames>;
|
|
134
163
|
|
|
135
164
|
/**
|
|
136
165
|
* Resolves Ruby constant paths against lexical nesting.
|
|
137
166
|
*
|
|
138
|
-
* A compound
|
|
139
|
-
*
|
|
140
|
-
* compound name `class` or `module` opens. `require` is never
|
|
141
|
-
* because Rails autoloads by naming convention
|
|
142
|
-
*
|
|
143
|
-
* keeps whatever name the source wrote and callers treat it as unresolved.
|
|
167
|
+
* A compound reference such as `Data::Record` is read as absolute. A bare
|
|
168
|
+
* name is relative to the nesting it is written inside, and so is a
|
|
169
|
+
* compound name that `class` or `module` opens. `require` is never
|
|
170
|
+
* resolved, because Rails autoloads by naming convention. A constant that
|
|
171
|
+
* nesting alone cannot qualify keeps the name the source wrote.
|
|
144
172
|
*
|
|
145
|
-
* Ruby's
|
|
146
|
-
* of the chain
|
|
147
|
-
*
|
|
148
|
-
*
|
|
149
|
-
* name, as in `module Api; class Types::CampaignType; end; end`, Ruby still
|
|
150
|
-
* looks up through `Api` inside that body. That matters, because a bare
|
|
151
|
-
* reference in there is resolved by trying each level of the chain, and dropping
|
|
152
|
-
* `Api` would miss a class the file itself defines.
|
|
173
|
+
* Ruby's `Module.nesting` puts each newly opened class or module on the
|
|
174
|
+
* front of the chain, whether its name was bare or compound. Inside
|
|
175
|
+
* `module Api; class Types::CampaignType`, a bare reference is still
|
|
176
|
+
* looked up through `Api`.
|
|
153
177
|
*/
|
|
154
178
|
|
|
155
179
|
/**
|
|
156
|
-
* Qualifies a name against the innermost level of `nesting`
|
|
157
|
-
*
|
|
158
|
-
*
|
|
180
|
+
* Qualifies a name against the innermost level of `nesting` only, which
|
|
181
|
+
* gives the name a `class` or `module` keyword defines. Returns null for
|
|
182
|
+
* a computed expression or a variable, which callers treat as
|
|
183
|
+
* unresolved. To find the class a reference refers to, use
|
|
184
|
+
* `constantRefCandidates`.
|
|
159
185
|
*/
|
|
160
186
|
declare function qualifyConstantRef(node: Node, nesting: readonly string[]): string | null;
|
|
161
187
|
interface ClassInfo {
|
|
@@ -182,11 +208,18 @@ interface ClassInfo {
|
|
|
182
208
|
declare function walkClasses(root: Node, visit: (info: ClassInfo) => void): void;
|
|
183
209
|
/** The same walk including `module` declarations, for a lookup that has to reach a module's own methods. */
|
|
184
210
|
declare function walkDefinitions(root: Node, visit: (info: ClassInfo) => void): void;
|
|
185
|
-
/** A pack picks a
|
|
211
|
+
/** A pack picks a convention by name, and `TYPE_NAME_CONVENTIONS` maps each name to its code. */
|
|
186
212
|
type GraphqlTypeNameConvention = "stripTypeSuffix";
|
|
187
|
-
/**
|
|
213
|
+
/** The GraphQL type name the convention derives from a class name. A name a class sets for itself is not read. */
|
|
188
214
|
declare function graphqlTypeNameFromQualified(qualifiedName: string, convention: GraphqlTypeNameConvention): string;
|
|
189
215
|
|
|
216
|
+
/**
|
|
217
|
+
* The ancestor chain a lookup walks to find the method behind a class,
|
|
218
|
+
* in the order Ruby's `Module#ancestors` gives. A reopened class is one
|
|
219
|
+
* place in the chain, an included module's own chain goes in as a unit,
|
|
220
|
+
* and an ancestor already in the chain is not added again.
|
|
221
|
+
*/
|
|
222
|
+
|
|
190
223
|
/** One class or module body a walk reached, with the definitions its own file makes, since a bare constant is shadowed per file. */
|
|
191
224
|
interface ReachedBody {
|
|
192
225
|
info: ClassInfo;
|
|
@@ -214,7 +247,7 @@ type AncestorEntry = {
|
|
|
214
247
|
};
|
|
215
248
|
/** A class and everything it inherits from, in Ruby's own method-lookup order. */
|
|
216
249
|
type Ancestry = readonly AncestorEntry[];
|
|
217
|
-
/** What reading a class body
|
|
250
|
+
/** What reading a class body needs besides the body: the run's facts, and what the packs declare about blocks written in one. */
|
|
218
251
|
interface BodyReading {
|
|
219
252
|
readonly facts?: Database | undefined;
|
|
220
253
|
readonly bodyBlocks?: BodyBlocks | undefined;
|
|
@@ -233,6 +266,8 @@ interface AncestorLookup {
|
|
|
233
266
|
* ends a walk with nothing left unfollowed.
|
|
234
267
|
*/
|
|
235
268
|
ancestryRootClassNames: readonly string[];
|
|
269
|
+
/** What this run's constant lookups have already read from the disk. */
|
|
270
|
+
constantFiles: ConstantFileCache;
|
|
236
271
|
parsedFile(absPath: string): Promise<Node | null>;
|
|
237
272
|
/**
|
|
238
273
|
* The blocks the file being read defines under a name, consulted
|
|
@@ -250,19 +285,18 @@ declare function reachDefinition(qualifiedName: string, lookup: AncestorLookup):
|
|
|
250
285
|
declare function ancestryOf(name: string, blocks: readonly ReachedBody[], lookup: AncestorLookup): Promise<Ancestry>;
|
|
251
286
|
/** What searching an ancestry for one method name came to. */
|
|
252
287
|
type MethodLookup =
|
|
253
|
-
/** `block` is
|
|
288
|
+
/** `block` is the ancestor body the method is written in, which gives a caller its file. */
|
|
254
289
|
{
|
|
255
290
|
type: "found";
|
|
256
291
|
method: Node;
|
|
257
292
|
block: ReachedBody;
|
|
258
293
|
}
|
|
259
294
|
/**
|
|
260
|
-
* `reason`
|
|
261
|
-
* `cause`
|
|
262
|
-
*
|
|
263
|
-
*
|
|
264
|
-
*
|
|
265
|
-
* name this reader could not read.
|
|
295
|
+
* `reason` finishes the sentence "could be answered by a method ...".
|
|
296
|
+
* `cause` gives the reason as a value, for a caller deciding whether
|
|
297
|
+
* to look further. `unreadAncestor` is a base whose file the run could
|
|
298
|
+
* not open, and `dynamicDefine` is a `define_method` call that defines
|
|
299
|
+
* this name or whose own name did not settle.
|
|
266
300
|
*/
|
|
267
301
|
| {
|
|
268
302
|
type: "unsettled";
|
|
@@ -283,56 +317,240 @@ declare function inheritedStatements(ancestry: Ancestry, blockConfigures?: Block
|
|
|
283
317
|
}>;
|
|
284
318
|
|
|
285
319
|
/**
|
|
286
|
-
* The
|
|
320
|
+
* The contract a Ruby pack implements.
|
|
287
321
|
*
|
|
288
|
-
*
|
|
289
|
-
*
|
|
290
|
-
*
|
|
291
|
-
*
|
|
322
|
+
* Each language adapter keeps its own pack contract until a second
|
|
323
|
+
* implementation shows which parts can be shared. Anything a library
|
|
324
|
+
* defines, such as its call names, keywords and scalars, comes in as pack
|
|
325
|
+
* data. This package hardcodes none of it.
|
|
292
326
|
*/
|
|
293
327
|
|
|
294
328
|
interface RubyPack {
|
|
295
329
|
name: string;
|
|
296
330
|
/**
|
|
297
|
-
*
|
|
298
|
-
*
|
|
299
|
-
*
|
|
300
|
-
*
|
|
301
|
-
* edit whether or not it declares a version of its own.
|
|
331
|
+
* Part of the cache key. Bump it on any change that affects discovered
|
|
332
|
+
* units or extracted summaries. The CLI also adds a hash of the loaded
|
|
333
|
+
* pack file and its config to the key, so a pack run through the CLI
|
|
334
|
+
* re-extracts after an edit even when it declares no version.
|
|
302
335
|
*/
|
|
303
336
|
version?: string;
|
|
304
337
|
/**
|
|
305
|
-
* Files
|
|
306
|
-
*
|
|
307
|
-
*
|
|
308
|
-
* so an edit to one of them re-extracts instead of handing back the
|
|
309
|
-
* previous answer.
|
|
338
|
+
* Files outside the walked `.rb` set whose content this pack reads,
|
|
339
|
+
* given the files the run is about to walk. Their content goes into the
|
|
340
|
+
* cache key, so editing one of them forces a re-extract.
|
|
310
341
|
*/
|
|
311
342
|
discoveryInputs?: (files: readonly string[]) => string[];
|
|
312
|
-
/** Wire protocol for the
|
|
343
|
+
/** Wire protocol for the boundary bindings the pack produces, e.g. "http-graphql". */
|
|
313
344
|
protocol: string;
|
|
314
345
|
discovery: RubyDiscoveryPattern[];
|
|
315
|
-
/** The calls the library
|
|
346
|
+
/** The calls the library offers a project for making a request. */
|
|
316
347
|
clients?: RbClientCall[];
|
|
317
|
-
/**
|
|
348
|
+
/** The library's model calls that read or write the database. */
|
|
318
349
|
storage?: RbStoragePattern[];
|
|
319
|
-
/** The calls the library
|
|
350
|
+
/** The calls the library offers for sending the store a statement the project wrote itself. */
|
|
320
351
|
rawSql?: RbRawSqlPattern[];
|
|
321
|
-
/**
|
|
352
|
+
/**
|
|
353
|
+
* The methods an action calls with no receiver to read the request,
|
|
354
|
+
* such as Rails' `params` and `request`. An action is handed no
|
|
355
|
+
* parameter for the request, so without these a value read off one is
|
|
356
|
+
* not known to come from the request.
|
|
357
|
+
*/
|
|
358
|
+
requestAccessors?: string[];
|
|
359
|
+
/** Where an action reads each part of the request, recorded on every action the pack finds. */
|
|
360
|
+
requestSpelling?: RequestSpellingMetadata;
|
|
361
|
+
/** Calls that read a model through a batching loader, where the model is an argument instead of the receiver. */
|
|
322
362
|
loaders?: RbLoaderPattern[];
|
|
323
|
-
/** Calls
|
|
363
|
+
/** Calls in a class or module body whose block runs as part of that body. */
|
|
324
364
|
bodyBlocks?: RbBodyBlock[];
|
|
325
|
-
/**
|
|
365
|
+
/** Words and rules the project added to the library's inflector. They are tried before the adapter's defaults. */
|
|
326
366
|
inflections?: RbInflections;
|
|
367
|
+
/** Methods the library offers that hand back the argument at `argument`, keyed on the module the callee comes from. */
|
|
368
|
+
transparentWrappers?: UnwrapsByName[];
|
|
369
|
+
/** How the library builds test records from named factories. */
|
|
370
|
+
factories?: RbFactories[];
|
|
371
|
+
/** How a class-based test runner declares tests, as Minitest does. */
|
|
372
|
+
testClasses?: RbTestClasses[];
|
|
373
|
+
/** How the library writes a test, so each one becomes a `test` unit a PRD scenario can list under `coveredBy`. */
|
|
374
|
+
tests?: RbTestCases[];
|
|
375
|
+
}
|
|
376
|
+
/**
|
|
377
|
+
* Tests written as nested blocks, the way RSpec writes them:
|
|
378
|
+
* `describe Order do; it "cancels" do ... end; end`. Each example is a
|
|
379
|
+
* `test` unit whose name is its group titles and its own. Every call
|
|
380
|
+
* listed here is one the library defines; the adapter reads the nesting.
|
|
381
|
+
*/
|
|
382
|
+
interface RbTestCases {
|
|
383
|
+
/** Base names of the files the runner loads, where `*` matches any run of characters: `*_spec.rb`. */
|
|
384
|
+
filePatterns: string[];
|
|
385
|
+
/** The constant a top-level group may be opened on, `RSpec` in `RSpec.describe`. */
|
|
386
|
+
receiver: string;
|
|
387
|
+
/** Calls that open a group of examples: `describe`, `context`. */
|
|
388
|
+
groupNames: string[];
|
|
389
|
+
/** Calls that open a group whose examples do not run: `xdescribe`, `xcontext`. */
|
|
390
|
+
skippedGroupNames: string[];
|
|
391
|
+
/** Calls that open a group other groups include by name, whose examples belong to whoever includes them: `shared_examples`. */
|
|
392
|
+
sharedGroupNames: string[];
|
|
393
|
+
/** Calls that include a shared group by name into the group they are written in: `it_behaves_like`, `include_context`. */
|
|
394
|
+
sharedIncludes: RbSharedInclude[];
|
|
395
|
+
/** Calls that declare one example: `it`, `specify`. */
|
|
396
|
+
exampleNames: string[];
|
|
397
|
+
/** Calls that declare an example that does not run: `xit`, `skip`. */
|
|
398
|
+
skippedExampleNames: string[];
|
|
399
|
+
/** Calls that, written as a statement in an example or a `before` block, mark the example as not run: `skip`, `pending`. */
|
|
400
|
+
skipStatements: string[];
|
|
401
|
+
/** Metadata keys that mark a group or an example as not run, written `:skip` or `skip: true`. */
|
|
402
|
+
skipMetadata: string[];
|
|
403
|
+
/** Hooks whose block runs before every example in the group: `before`. */
|
|
404
|
+
beforeHooks: string[];
|
|
405
|
+
/** Calls that define a value an example reads by name, run when it is first read: `let`. */
|
|
406
|
+
lazyValues: string[];
|
|
407
|
+
/** The same, run before every example whether it reads the value or not: `let!`. */
|
|
408
|
+
eagerValues: string[];
|
|
409
|
+
/** Calls that define the group's subject, lazily and eagerly: `subject`, `subject!`. */
|
|
410
|
+
subjectNames: {
|
|
411
|
+
lazy: string[];
|
|
412
|
+
eager: string[];
|
|
413
|
+
};
|
|
414
|
+
/** Calls an example makes on itself to read the subject: `subject`, `is_expected`. */
|
|
415
|
+
subjectReads: string[];
|
|
416
|
+
/** The one of those that gives back the subject itself: `subject`. A group given a class has that class's `new` as its subject unless it says otherwise. */
|
|
417
|
+
subjectValue: string;
|
|
418
|
+
/** The call that gives back the class the nearest group around was given: `described_class`. */
|
|
419
|
+
describedClass: string;
|
|
420
|
+
/**
|
|
421
|
+
* Methods the library gives an example to call on itself to check or
|
|
422
|
+
* set something up, such as `expect`, `eq` and `allow`. A call made
|
|
423
|
+
* through one is no call into project code.
|
|
424
|
+
*/
|
|
425
|
+
runnerMethods: string[];
|
|
426
|
+
/** The matchers the library makes up from a predicate method, as `be_cancelled` calls `cancelled?` on what the expectation is about. */
|
|
427
|
+
predicateMatchers: RbPredicateMatcher[];
|
|
428
|
+
/** How an example states an expectation, which a predicate matcher is given to. */
|
|
429
|
+
expectations: RbExpectations;
|
|
430
|
+
/** How the library replaces something for the length of an example. */
|
|
431
|
+
mocks: RbTestMocks;
|
|
432
|
+
/** Read only these files, matched on whole path segments from the end. Left out, every file matching `filePatterns` is read. */
|
|
433
|
+
files?: string[];
|
|
434
|
+
}
|
|
435
|
+
/**
|
|
436
|
+
* Tests written as a class, the way Minitest and Rails' test cases write
|
|
437
|
+
* them: a class that extends one of `baseClassNames`, with a method per
|
|
438
|
+
* test or a `test "..." do` block per test. Each becomes a `test` unit
|
|
439
|
+
* named by the class and then the test's method name.
|
|
440
|
+
*/
|
|
441
|
+
interface RbTestClasses {
|
|
442
|
+
/** Base names of the files the runner loads, where `*` matches any run of characters: `*_test.rb`. */
|
|
443
|
+
filePatterns: string[];
|
|
444
|
+
/** The library's test case classes, as a project writes them: `Minitest::Test`, `ActiveSupport::TestCase`. */
|
|
445
|
+
baseClassNames: string[];
|
|
446
|
+
/** What a test method's name starts with: `test_`. */
|
|
447
|
+
testMethodPrefix: string;
|
|
448
|
+
/** Calls that declare a test as a block, given its description: `test`. */
|
|
449
|
+
testBlockMethods: string[];
|
|
450
|
+
/** How the library turns a block test's description into the method it defines: `test_` in front, each run of spaces as `_`. */
|
|
451
|
+
blockTestName: {
|
|
452
|
+
prefix: string;
|
|
453
|
+
spacesAs: string;
|
|
454
|
+
};
|
|
455
|
+
/** Calls whose block runs before each test: `setup`. */
|
|
456
|
+
setupBlockMethods: string[];
|
|
457
|
+
/** Methods the runner calls before each test: `setup`. */
|
|
458
|
+
setupMethodNames: string[];
|
|
459
|
+
/** Calls that, written as a statement in a test, mark it as not run: `skip`. */
|
|
460
|
+
skipStatements: string[];
|
|
461
|
+
/** Prefixes of the checks the runner gives a test, which call no project code: `assert`, `refute`. */
|
|
462
|
+
assertionPrefixes: string[];
|
|
463
|
+
/** Calls that replace a method on the object they are called on, given its name first: `stub`, `stubs`, `expects`. */
|
|
464
|
+
stubMethods: string[];
|
|
465
|
+
/** Read only these files, matched on whole path segments from the end. */
|
|
466
|
+
files?: string[];
|
|
467
|
+
}
|
|
468
|
+
/**
|
|
469
|
+
* How a test data library builds a record from a factory it looks up by
|
|
470
|
+
* name, so a value a test builds with `create(:order)` or
|
|
471
|
+
* `Fabricate(:order)` is known to be one of the factory's class. The
|
|
472
|
+
* adapter reads the definitions wherever the run finds them, and the
|
|
473
|
+
* builds in the files it reads as tests.
|
|
474
|
+
*/
|
|
475
|
+
interface RbFactories {
|
|
476
|
+
/** Calls that define a factory, given its name first: `factory`, `Fabricator`. */
|
|
477
|
+
definitionMethods: string[];
|
|
478
|
+
/** Keywords a definition gives its class under, as a constant or a string: `class`, `class_name`. */
|
|
479
|
+
classKeywords: string[];
|
|
480
|
+
/** Keywords a definition gives the factory it builds on under: `parent`, `from`. A name no factory has is read as a class. */
|
|
481
|
+
parentKeywords: string[];
|
|
482
|
+
/** Whether a definition written in another's block builds on it, as a nested FactoryBot factory does. */
|
|
483
|
+
nestedDefinitionsInherit: boolean;
|
|
484
|
+
/** Calls that build one record from the factory their first argument names. */
|
|
485
|
+
builders: RbFactoryBuilder[];
|
|
486
|
+
}
|
|
487
|
+
/** One build call: `create`, or `Fabricate.build` with `receiver` set. */
|
|
488
|
+
interface RbFactoryBuilder {
|
|
489
|
+
method: string;
|
|
490
|
+
/** The constant the call is made on, when it is made on one. */
|
|
491
|
+
receiver?: string;
|
|
492
|
+
}
|
|
493
|
+
/**
|
|
494
|
+
* A matcher the library makes up from a predicate method: a matcher
|
|
495
|
+
* written `prefix` and a name calls `methodPrefix`, that name and
|
|
496
|
+
* `methodSuffix` on the value the expectation is about, so `be_local`
|
|
497
|
+
* calls `local?` and `have_key` calls `has_key?`.
|
|
498
|
+
*/
|
|
499
|
+
interface RbPredicateMatcher {
|
|
500
|
+
prefix: string;
|
|
501
|
+
methodPrefix: string;
|
|
502
|
+
methodSuffix: string;
|
|
503
|
+
}
|
|
504
|
+
/**
|
|
505
|
+
* How an example states an expectation: `expect(order).to be_open`, on
|
|
506
|
+
* the argument of a `starts` call, or `is_expected.to be_open`, on the
|
|
507
|
+
* subject through `onSubject`. `runs` are the calls given the matcher.
|
|
508
|
+
*/
|
|
509
|
+
interface RbExpectations {
|
|
510
|
+
starts: string[];
|
|
511
|
+
onSubject: string;
|
|
512
|
+
runs: string[];
|
|
513
|
+
}
|
|
514
|
+
/**
|
|
515
|
+
* One way a group includes a shared group. With `nestedTitle`, the shared
|
|
516
|
+
* examples run in a group of their own titled that and then the shared
|
|
517
|
+
* group's name, as `it_behaves_like "x"` runs them under "behaves like x".
|
|
518
|
+
* Without it they run in the including group itself.
|
|
519
|
+
*/
|
|
520
|
+
interface RbSharedInclude {
|
|
521
|
+
method: string;
|
|
522
|
+
nestedTitle?: string;
|
|
327
523
|
}
|
|
328
524
|
/**
|
|
329
|
-
* The
|
|
330
|
-
*
|
|
331
|
-
*
|
|
332
|
-
*
|
|
525
|
+
* The library's mock spellings. `allow(Order).to receive(:cancel)`
|
|
526
|
+
* replaces one method: `targets` opens it, `expectations` joins it, and
|
|
527
|
+
* `messages` says which method. `stub_const("Order", ...)` replaces a
|
|
528
|
+
* whole constant. A double is a fake object the test hands over, and it
|
|
529
|
+
* replaces nothing the test would otherwise reach unless the test makes
|
|
530
|
+
* it the constant with `constantDoubleMethod`.
|
|
531
|
+
*/
|
|
532
|
+
interface RbTestMocks {
|
|
533
|
+
/** `allow`, `expect`, `allow_any_instance_of`. */
|
|
534
|
+
targets: string[];
|
|
535
|
+
/** `to`. */
|
|
536
|
+
expectations: string[];
|
|
537
|
+
/** `receive`, `receive_messages`. */
|
|
538
|
+
messages: string[];
|
|
539
|
+
/** `stub_const`. */
|
|
540
|
+
constantStubs: string[];
|
|
541
|
+
/** `instance_double`, `class_double`. */
|
|
542
|
+
doubles: string[];
|
|
543
|
+
/** `as_stubbed_const`, which makes a double the constant it stands in for. */
|
|
544
|
+
constantDoubleMethod: string;
|
|
545
|
+
}
|
|
546
|
+
/**
|
|
547
|
+
* The words and rules a project registered with its library's inflector.
|
|
548
|
+
* Where a project writes them depends on the library, so the pack reads
|
|
549
|
+
* them and passes the result here. The adapter applies them the same way
|
|
550
|
+
* for every library.
|
|
333
551
|
*/
|
|
334
552
|
interface RbInflections {
|
|
335
|
-
/** Words a constant name keeps
|
|
553
|
+
/** Words a constant name keeps in capitals: with `API`, `api_token` becomes `APIToken`. */
|
|
336
554
|
acronyms?: string[];
|
|
337
555
|
/** A plural and the singular it comes from: `["people", "person"]`. */
|
|
338
556
|
irregular?: Array<[plural: string, singular: string]>;
|
|
@@ -342,26 +560,26 @@ interface RbInflections {
|
|
|
342
560
|
singular?: Array<[rule: string, replacement: string]>;
|
|
343
561
|
}
|
|
344
562
|
/**
|
|
345
|
-
* A receiverless call
|
|
346
|
-
*
|
|
347
|
-
*
|
|
348
|
-
*
|
|
563
|
+
* A receiverless call in a class or module body whose block runs as part
|
|
564
|
+
* of that body, so what the block declares belongs to the class. Ruby has
|
|
565
|
+
* no such call of its own. When no pack declares one, every block is read
|
|
566
|
+
* as an ordinary block.
|
|
349
567
|
*/
|
|
350
568
|
interface RbBodyBlock {
|
|
351
569
|
/** The call as a project writes it, `included`. */
|
|
352
570
|
name: string;
|
|
353
|
-
/** Set when the library
|
|
571
|
+
/** Set when the library offers the call only to modules, as with a concern's `included`. */
|
|
354
572
|
moduleOnly?: boolean;
|
|
355
|
-
/** Set when a `def` in the block
|
|
573
|
+
/** Set when a `def` in the block defines a method on the class itself instead of on an instance. */
|
|
356
574
|
definesClassMethods?: boolean;
|
|
357
575
|
}
|
|
358
576
|
/**
|
|
359
|
-
* The calls a library
|
|
360
|
-
* that makes one
|
|
361
|
-
*
|
|
577
|
+
* The calls a library offers a project for making a request. A method
|
|
578
|
+
* that makes one becomes a client unit, bound to the request method and
|
|
579
|
+
* path of the call.
|
|
362
580
|
*/
|
|
363
581
|
interface RbClientCall {
|
|
364
|
-
/** The constant the calls
|
|
582
|
+
/** The constant the calls are made on, as a project writes it: `Faraday`, `Net::HTTP`. */
|
|
365
583
|
constantName: string;
|
|
366
584
|
/** Method names that state the request method themselves: `get` means GET. */
|
|
367
585
|
verbMethodNames: Record<string, string>;
|
|
@@ -372,11 +590,11 @@ interface RbClientCall {
|
|
|
372
590
|
};
|
|
373
591
|
/** Methods on the constant that build a value taking the same calls, `new` for a Faraday connection. */
|
|
374
592
|
receiverBuilders?: string[];
|
|
375
|
-
/** The keyword
|
|
593
|
+
/** The keyword a builder takes its base URL under. The base URL goes in front of the path of each call on the built value. */
|
|
376
594
|
builderUrlKeyword?: string;
|
|
377
|
-
/**
|
|
595
|
+
/** The members of the response object, so a test on one of them counts as a test on the status. */
|
|
378
596
|
response?: RbClientResponse;
|
|
379
|
-
/** A call that sends a request object built
|
|
597
|
+
/** A call that sends a request object built separately. Net::HTTP sends any request with a body this way. */
|
|
380
598
|
requestObject?: {
|
|
381
599
|
/** The method that takes the request object, `request`. */
|
|
382
600
|
attribute: string;
|
|
@@ -387,9 +605,9 @@ interface RbClientCall {
|
|
|
387
605
|
};
|
|
388
606
|
}
|
|
389
607
|
/**
|
|
390
|
-
* The members a library's response object
|
|
391
|
-
*
|
|
392
|
-
*
|
|
608
|
+
* The members of a library's response object. A test on one of them shows
|
|
609
|
+
* which statuses the caller handles, and the checker compares that with
|
|
610
|
+
* what the provider sends.
|
|
393
611
|
*/
|
|
394
612
|
interface RbClientResponse {
|
|
395
613
|
/** Members whose value is the status: `status` for Faraday, `code` for Net::HTTP. */
|
|
@@ -402,16 +620,17 @@ interface RbClientResponse {
|
|
|
402
620
|
failureDelivery?: "response" | "exception";
|
|
403
621
|
}
|
|
404
622
|
/**
|
|
405
|
-
* Ruby
|
|
406
|
-
* inherits from. A model is
|
|
407
|
-
*
|
|
623
|
+
* Ruby code declares no return types, so a call is matched by what its
|
|
624
|
+
* receiver inherits from. A model is any class whose ancestry reaches one
|
|
625
|
+
* of `baseClasses`, including through a base class the project declares
|
|
626
|
+
* in between.
|
|
408
627
|
*
|
|
409
|
-
* `reads` and `writes`
|
|
410
|
-
*
|
|
411
|
-
*
|
|
628
|
+
* `reads` and `writes` list every database call the library makes. A
|
|
629
|
+
* method in neither list belongs to the project or the language, and the
|
|
630
|
+
* reach walk follows it.
|
|
412
631
|
*/
|
|
413
632
|
interface RbStoragePattern {
|
|
414
|
-
/** Base classes the library
|
|
633
|
+
/** Base classes the library provides for models, `ActiveRecord::Base` for Rails. */
|
|
415
634
|
baseClasses: string[];
|
|
416
635
|
/** Methods the library defines that change what is stored. */
|
|
417
636
|
writes: string[];
|
|
@@ -421,146 +640,152 @@ interface RbStoragePattern {
|
|
|
421
640
|
givesBack: string[];
|
|
422
641
|
/**
|
|
423
642
|
* Methods on the model that take a statement the project wrote itself,
|
|
424
|
-
* and where each one takes it. The tables come from the statement
|
|
425
|
-
*
|
|
426
|
-
*
|
|
643
|
+
* and where each one takes it. The tables come from the statement
|
|
644
|
+
* instead of the model's own container, and the statement is read in
|
|
645
|
+
* the dialect of `storageSystem`.
|
|
427
646
|
*/
|
|
428
647
|
statements?: Record<string, RbArgumentPlace>;
|
|
429
648
|
/** The token the library writes where a bind value goes, ActiveRecord's `?`. */
|
|
430
649
|
bindPlaceholder?: string;
|
|
431
|
-
/** The methods the library runs
|
|
650
|
+
/** The methods the library runs by itself around a write, as registered by `after_commit :sync_search`. */
|
|
432
651
|
callbacks?: RbModelCallbacks;
|
|
433
|
-
/** Methods that pick rows by the primary key when
|
|
652
|
+
/** Methods that pick rows by the primary key when given a positional argument, and that key's column. */
|
|
434
653
|
byPrimaryKey?: RbPrimaryKeyLookup;
|
|
435
654
|
/** Read methods whose symbol arguments are the columns they ask for. */
|
|
436
655
|
columnArguments?: string[];
|
|
437
|
-
/**
|
|
656
|
+
/** The calls a model uses to declare an association with another model, when the library has them. */
|
|
438
657
|
associations?: RbAssociationCalls;
|
|
439
|
-
/**
|
|
658
|
+
/**
|
|
659
|
+
* The calls a model body makes to define a class method from a lambda,
|
|
660
|
+
* as `scope :recent, -> { order(:created_at) }` defines `recent`. The
|
|
661
|
+
* first argument is the method's name and the lambda after it runs.
|
|
662
|
+
*/
|
|
663
|
+
scopes?: string[];
|
|
664
|
+
/** Which database is behind the connection. The project decides this, so the pack passes it in. */
|
|
440
665
|
storageSystem: "postgresql" | "mysql" | "sqlite";
|
|
441
666
|
}
|
|
442
667
|
/**
|
|
443
|
-
* A library whose calls take SQL the project wrote,
|
|
444
|
-
*
|
|
445
|
-
*
|
|
446
|
-
* chain starts at `constantName`, one of `clientBuilders`
|
|
447
|
-
* client, and `addressing` calls narrow that client to
|
|
448
|
-
*
|
|
668
|
+
* A library whose calls take SQL the project wrote, instead of building
|
|
669
|
+
* it from a model. Ruby code declares no types, so the adapter finds the
|
|
670
|
+
* receiver's type by following it back to the library call that produced
|
|
671
|
+
* it. The chain starts at `constantName`, one of `clientBuilders` returns
|
|
672
|
+
* a client, and `addressing` calls narrow that client to part of the store
|
|
673
|
+
* before the statement or row call.
|
|
449
674
|
*/
|
|
450
675
|
interface RbRawSqlPattern {
|
|
451
676
|
/** The constant the library's calls start at, `PG` or `Google::Cloud::Bigquery`. */
|
|
452
677
|
constantName: string;
|
|
453
678
|
/**
|
|
454
|
-
* Base classes whose subclasses
|
|
455
|
-
* constant does, `ActiveRecord::Base` for Rails.
|
|
456
|
-
*
|
|
457
|
-
*
|
|
679
|
+
* Base classes whose subclasses return a client the same way the
|
|
680
|
+
* constant does, `ActiveRecord::Base` for Rails. `Account.connection`
|
|
681
|
+
* and a bare `connection` inside the model reach the same store as the
|
|
682
|
+
* base class itself.
|
|
458
683
|
*/
|
|
459
684
|
baseClasses?: string[];
|
|
460
|
-
/** Methods on that constant that
|
|
685
|
+
/** Methods on that constant that return a client, `connect` for the pg gem. */
|
|
461
686
|
clientBuilders: string[];
|
|
462
|
-
/** Calls that narrow a client to part of the store and
|
|
687
|
+
/** Calls that narrow a client to part of the store and return a value the later calls are made on. */
|
|
463
688
|
addressing?: Record<string, RbAddressingCall>;
|
|
464
689
|
/** Calls that take a statement, and where each one takes it. */
|
|
465
690
|
statements?: Record<string, RbArgumentPlace>;
|
|
466
|
-
/** The token the library writes where a bind value goes, when
|
|
691
|
+
/** The token the library writes where a bind value goes, when the dialect's parser does not read it. */
|
|
467
692
|
bindPlaceholder?: string;
|
|
468
693
|
/** Calls that read or write rows of an addressed container with no statement, `insert` on a BigQuery table. */
|
|
469
694
|
rowCalls?: Record<string, RbRowCall>;
|
|
470
|
-
/** Which store is behind the calls, in
|
|
695
|
+
/** Which store is behind the calls, in OpenTelemetry's semantic convention names: `postgresql`, `gcp.bigquery`. */
|
|
471
696
|
storageSystem: string;
|
|
472
697
|
/**
|
|
473
|
-
* Which dialect the statements are written in
|
|
474
|
-
*
|
|
475
|
-
*
|
|
476
|
-
* tables without
|
|
698
|
+
* Which dialect the statements are written in. This can differ from the
|
|
699
|
+
* store: BigQuery's store is `gcp.bigquery` and its dialect is
|
|
700
|
+
* `bigquery`. There is no default, because a wrong dialect would read
|
|
701
|
+
* the wrong tables without any warning.
|
|
477
702
|
*/
|
|
478
703
|
dialect: string;
|
|
479
|
-
/**
|
|
704
|
+
/** The namespace the calls reach when neither the chain nor the table name gives one. Defaults to "default". */
|
|
480
705
|
scope?: string;
|
|
481
706
|
}
|
|
482
|
-
/** A call that
|
|
707
|
+
/** A call that selects which part of the store the later calls reach, `bigquery.dataset("core")`. */
|
|
483
708
|
interface RbAddressingCall extends RbArgumentPlace {
|
|
484
|
-
/** Which part of the address this call
|
|
709
|
+
/** Which part of the address this call gives. */
|
|
485
710
|
says: "scope" | "container";
|
|
486
711
|
}
|
|
487
712
|
/** A call that reads or writes rows without a statement. */
|
|
488
713
|
interface RbRowCall {
|
|
489
714
|
kind: "read" | "write";
|
|
490
715
|
/**
|
|
491
|
-
* Where the call
|
|
492
|
-
*
|
|
493
|
-
* `table.insert(rows)` and `dataset.insert("accounts", rows)`.
|
|
494
|
-
*
|
|
495
|
-
*
|
|
716
|
+
* Where the call can take the container, for a library that offers the
|
|
717
|
+
* same call on the container and one level above it: BigQuery's
|
|
718
|
+
* `table.insert(rows)` and `dataset.insert("accounts", rows)`. When this
|
|
719
|
+
* argument does not settle on a string, as with a rows argument, the
|
|
720
|
+
* chain's own container is used.
|
|
496
721
|
*/
|
|
497
722
|
container?: RbArgumentPlace;
|
|
498
723
|
}
|
|
499
|
-
/** Where a call
|
|
724
|
+
/** Where a call takes one of its arguments. When a call passes it both ways, the keyword wins. */
|
|
500
725
|
interface RbArgumentPlace {
|
|
501
726
|
/** The index of the positional argument. */
|
|
502
727
|
at: number;
|
|
503
|
-
/** The keyword the argument
|
|
728
|
+
/** The keyword the argument can be passed under instead. */
|
|
504
729
|
keyword?: string;
|
|
505
730
|
}
|
|
506
|
-
/** Which methods take the primary key positionally, and what that column is called. */
|
|
507
731
|
/**
|
|
508
|
-
* The methods a model registers in its
|
|
509
|
-
*
|
|
510
|
-
*
|
|
732
|
+
* The methods a model registers in its class body for the library to
|
|
733
|
+
* run when a write happens. A body that writes through the model runs
|
|
734
|
+
* them too, so their effects belong to that body.
|
|
511
735
|
*
|
|
512
|
-
*
|
|
513
|
-
*
|
|
514
|
-
*
|
|
736
|
+
* Both tables are keyed by the library's own event names: a write method
|
|
737
|
+
* lists the events it fires, and a registering call lists the events it
|
|
738
|
+
* covers.
|
|
515
739
|
*/
|
|
516
740
|
interface RbModelCallbacks {
|
|
517
|
-
/** Each write method the pattern declares, and the events it
|
|
741
|
+
/** Each write method the pattern declares, and the events it fires. */
|
|
518
742
|
eventOf: Record<string, string[]>;
|
|
519
|
-
/** Each class-body call that registers a callback, and the events it covers when the call
|
|
743
|
+
/** Each class-body call that registers a callback, and the events it covers when the call does not narrow them. */
|
|
520
744
|
registeredBy: Record<string, string[]>;
|
|
521
745
|
/** The keyword that narrows one registration to some of those events, `on`. */
|
|
522
746
|
eventKeyword: string;
|
|
523
747
|
}
|
|
748
|
+
/** Which methods take the primary key positionally, and what that column is called. */
|
|
524
749
|
interface RbPrimaryKeyLookup {
|
|
525
750
|
methods: string[];
|
|
526
|
-
/** The column the library uses unless a model
|
|
751
|
+
/** The column the library uses unless a model sets another. */
|
|
527
752
|
column: string;
|
|
528
753
|
}
|
|
529
754
|
/**
|
|
530
|
-
* The class-body calls a
|
|
531
|
-
*
|
|
532
|
-
*
|
|
533
|
-
*
|
|
534
|
-
*
|
|
755
|
+
* The class-body calls a model uses to declare an association, and the
|
|
756
|
+
* keyword that gives the target class. The calls are split into two
|
|
757
|
+
* lists because a plural call's target is the singularised association
|
|
758
|
+
* name, and a singular call's target is the name as written. Only the
|
|
759
|
+
* library knows which of its calls is which.
|
|
535
760
|
*/
|
|
536
761
|
interface RbAssociationCalls {
|
|
537
762
|
/** Calls written in the singular, `belongs_to :account` and `has_one :profile`. */
|
|
538
763
|
singular: string[];
|
|
539
764
|
/** Calls written in the plural, `has_many :statuses`. */
|
|
540
765
|
plural: string[];
|
|
541
|
-
/** The keyword
|
|
766
|
+
/** The keyword that gives the target class's name explicitly, `class_name`. */
|
|
542
767
|
classNameKeyword: string;
|
|
543
768
|
}
|
|
544
769
|
/**
|
|
545
|
-
* A loader that batches reads of a model
|
|
546
|
-
* dataloader
|
|
547
|
-
* a constant argument, so the read is recorded against that
|
|
548
|
-
*
|
|
549
|
-
* pack in the run
|
|
770
|
+
* A loader that batches reads of a model for the caller, such as
|
|
771
|
+
* graphql-ruby's dataloader. The call that picks what to load gets the
|
|
772
|
+
* model as a constant argument, so the read is recorded against that
|
|
773
|
+
* model as if the call were made on it. A storage pattern from another
|
|
774
|
+
* pack in the run decides whether the constant is a model at all.
|
|
550
775
|
*/
|
|
551
776
|
interface RbLoaderPattern {
|
|
552
|
-
/** The receiverless call that
|
|
777
|
+
/** The receiverless call that returns the loader, `dataloader`. */
|
|
553
778
|
loader: string;
|
|
554
779
|
/** The method on the loader that picks a source and its arguments, `with`. */
|
|
555
780
|
pick: string;
|
|
556
781
|
/** The methods on a picked source that perform the read, `load` and `load_all`. */
|
|
557
782
|
reads: string[];
|
|
558
|
-
/** Receiverless calls that pick and read in one,
|
|
783
|
+
/** Receiverless calls that pick and read in one call, with the model among the arguments: `dataload` and `dataload_record`. */
|
|
559
784
|
shortcuts: string[];
|
|
560
785
|
/**
|
|
561
786
|
* Where `pick` takes the project's own source class, and the method
|
|
562
|
-
* the library runs on it. The read happens in that method, so
|
|
563
|
-
* reaches
|
|
787
|
+
* the library runs on it. The read happens in that method, so whatever
|
|
788
|
+
* it reaches is reported on every body that loads through it.
|
|
564
789
|
*/
|
|
565
790
|
source?: RbLoaderSource;
|
|
566
791
|
}
|
|
@@ -572,73 +797,78 @@ interface RbLoaderSource {
|
|
|
572
797
|
method: string;
|
|
573
798
|
}
|
|
574
799
|
type RubyDiscoveryPattern = GraphqlObjectFields | ControllerActions;
|
|
575
|
-
/**
|
|
800
|
+
/**
|
|
801
|
+
* A class whose ancestry reaches one of `baseClassNames` or
|
|
802
|
+
* `ancestryRootClassNames` is a controller, and every instance method it
|
|
803
|
+
* defines directly is an action. `routeFor` binds each action to the
|
|
804
|
+
* method and path the project's routing gives it. An action `routeFor`
|
|
805
|
+
* has no route for is still discovered, with no boundary binding.
|
|
806
|
+
*/
|
|
576
807
|
interface ControllerActions {
|
|
577
808
|
type: "controllerActions";
|
|
578
|
-
/**
|
|
809
|
+
/** Bases a project's controllers extend, such as `ApplicationController`. A base is not itself a controller. */
|
|
579
810
|
baseClassNames: string[];
|
|
580
|
-
/** The directory a bare superclass name is looked up under, the project's
|
|
811
|
+
/** The directory a bare superclass name is looked up under, which depends on the project's layout. */
|
|
581
812
|
root: string;
|
|
582
813
|
pathConvention: ConstantPathConvention;
|
|
583
|
-
/** Acronyms the project registers with the inflector
|
|
814
|
+
/** Acronyms the project registers with the inflector. The path convention keeps each one as one word: `ActivityPub` becomes `activitypub`. */
|
|
584
815
|
acronyms?: string[];
|
|
585
816
|
/** The library's own classes a project's controller chain ends at. A class extending one directly is a controller too. */
|
|
586
817
|
ancestryRootClassNames: string[];
|
|
587
|
-
/**
|
|
818
|
+
/** The status a response gets when the action does not set one. */
|
|
588
819
|
defaultStatusCode: number;
|
|
589
|
-
/** The receiverless calls
|
|
820
|
+
/** The receiverless calls an action uses to send a status. Without them, every action reports the default. */
|
|
590
821
|
responseStatusCalls?: RbStatusCall[];
|
|
591
|
-
/** The number
|
|
822
|
+
/** The number for each status name the library accepts in place of a number. For Rails this is Rack's symbol table. */
|
|
592
823
|
statusCodeNames?: Record<string, number>;
|
|
593
824
|
/**
|
|
594
|
-
*
|
|
595
|
-
*
|
|
596
|
-
*
|
|
597
|
-
*
|
|
598
|
-
* so a receiverless call to one of them is left off that list.
|
|
825
|
+
* Methods every controller inherits from the library, which for Rails
|
|
826
|
+
* are `params`, `render` and the rest of what `ActionController` mixes
|
|
827
|
+
* in. Nothing in the project defines them, so a receiverless call to
|
|
828
|
+
* one is left off the action's effect list.
|
|
599
829
|
*/
|
|
600
830
|
inheritedMethodNames?: string[];
|
|
601
|
-
/** Absolute path of the file this pattern
|
|
831
|
+
/** Absolute path of the routes file this pattern read, used in the gap `routingGaps` can report. */
|
|
602
832
|
routesFile: string;
|
|
603
|
-
/** The method and path
|
|
833
|
+
/** The method and path the project's routing gives one controller action, or null when it has none. */
|
|
604
834
|
routeFor: (controllerQualifiedName: string, actionName: string) => {
|
|
605
835
|
method: string;
|
|
606
836
|
path: string;
|
|
607
837
|
} | null;
|
|
608
|
-
/** One message
|
|
838
|
+
/** One message for each kind of routing declaration the pattern could not read. Calling it again returns the same list. */
|
|
609
839
|
routingGaps?: () => readonly string[];
|
|
610
|
-
/** The class-level calls
|
|
840
|
+
/** The class-level calls that run one of the controller's own methods around its actions, Rails' `before_action` and `rescue_from`. */
|
|
611
841
|
filters?: RbControllerFilter[];
|
|
612
842
|
}
|
|
613
843
|
/**
|
|
614
|
-
* A call
|
|
615
|
-
*
|
|
616
|
-
*
|
|
617
|
-
*
|
|
844
|
+
* A class-body call that registers a method for the library to run around
|
|
845
|
+
* a controller's actions. A class inherits what its ancestors register, so
|
|
846
|
+
* a filter on `ApplicationController` applies to every action in the
|
|
847
|
+
* project.
|
|
618
848
|
*/
|
|
619
849
|
interface RbControllerFilter {
|
|
620
850
|
/** The call as a controller writes it, `before_action`. */
|
|
621
851
|
name: string;
|
|
622
852
|
/**
|
|
623
|
-
* Where the call
|
|
853
|
+
* Where the call takes the method: `argument` for the leading symbol
|
|
624
854
|
* of `before_action :require_login`, `withKeyword` for the `with:` of
|
|
625
855
|
* `rescue_from ActiveRecord::RecordNotFound, with: :not_found`.
|
|
626
856
|
*/
|
|
627
857
|
methodFrom: "argument" | "withKeyword";
|
|
628
858
|
/** Set when the library runs the method only for an action that raised, as `rescue_from` does. */
|
|
629
859
|
onThrow?: boolean;
|
|
630
|
-
/** The
|
|
860
|
+
/** The call that removes the filter again, `skip_before_action` for `before_action`. */
|
|
631
861
|
skippedBy?: string;
|
|
632
|
-
/** The keywords that
|
|
862
|
+
/** The keywords that limit a filter to some of the actions, Rails' `only` and `except`. */
|
|
633
863
|
actionKeywords?: {
|
|
634
864
|
include: string;
|
|
635
865
|
exclude: string;
|
|
636
866
|
};
|
|
637
867
|
}
|
|
638
868
|
/**
|
|
639
|
-
*
|
|
640
|
-
* the status.
|
|
641
|
-
* as
|
|
869
|
+
* A call an action makes to send a response, and where that call takes
|
|
870
|
+
* the status. When a call passes the status both ways the keyword wins,
|
|
871
|
+
* as in Rails for `head :ok, status: :created`.
|
|
642
872
|
*/
|
|
643
873
|
interface RbStatusCall {
|
|
644
874
|
/** The call's own name as an action writes it, `render` for Rails. */
|
|
@@ -648,54 +878,54 @@ interface RbStatusCall {
|
|
|
648
878
|
/** The index of the positional argument giving the status, 0 for Rails' `head :no_content`. */
|
|
649
879
|
statusArgument?: number;
|
|
650
880
|
/**
|
|
651
|
-
* The status this call sends when the action
|
|
652
|
-
* `redirect_to` sends 302
|
|
653
|
-
*
|
|
881
|
+
* The status this call sends when the action passes none. Rails'
|
|
882
|
+
* `redirect_to` sends 302, while `render` sends the controller default,
|
|
883
|
+
* so a default declared here takes precedence over `defaultStatusCode`.
|
|
654
884
|
*/
|
|
655
885
|
defaultStatusCode?: number;
|
|
656
886
|
}
|
|
657
887
|
/** A class or module whose ancestry reaches one of `baseClassNames` declares GraphQL fields through DSL calls in its own body. */
|
|
658
888
|
interface GraphqlObjectFields {
|
|
659
889
|
type: "graphqlObjectFields";
|
|
660
|
-
/** The base classes the library
|
|
890
|
+
/** The base classes the library's generator writes. The walk follows a project's own intermediate bases, so config only needs to add a base with a different name. */
|
|
661
891
|
baseClassNames: string[];
|
|
662
|
-
/** The directory a wiring keyword's referenced class is looked up under
|
|
892
|
+
/** The directory a wiring keyword's referenced class is looked up under, which depends on the project's layout. */
|
|
663
893
|
root: string;
|
|
664
894
|
pathConvention: ConstantPathConvention;
|
|
665
|
-
/** Acronyms the project registers with the inflector
|
|
895
|
+
/** Acronyms the project registers with the inflector. The path convention keeps each one as one word. */
|
|
666
896
|
acronyms?: string[];
|
|
667
897
|
/** The DSL call declaring one schema field in an object type's body. */
|
|
668
898
|
fieldCallName: string;
|
|
669
899
|
/** The DSL call declaring a referenced class's own return type. */
|
|
670
900
|
typeCallName: string;
|
|
671
901
|
argumentCallName: string;
|
|
672
|
-
/** Keywords whose value
|
|
902
|
+
/** Keywords whose value is a class to read the declared contract from, one hop away. They are tried in the order listed. */
|
|
673
903
|
wiringKeywords: string[];
|
|
674
|
-
/** The method a wired class defines to resolve the field it is wired to.
|
|
904
|
+
/** The method a wired class defines to resolve the field it is wired to. */
|
|
675
905
|
resolverMethodName: string;
|
|
676
|
-
/** The library's own classes that a project's class chain ends at.
|
|
906
|
+
/** The library's own classes that a project's class chain ends at. */
|
|
677
907
|
ancestryRootClassNames: string[];
|
|
678
|
-
/**
|
|
908
|
+
/** The keyword on an argument call that says whether the argument is required. */
|
|
679
909
|
requiredKeyword: string;
|
|
680
|
-
/**
|
|
910
|
+
/** Whether an argument is required when its call does not pass the required keyword. */
|
|
681
911
|
requiredDefault: boolean;
|
|
682
912
|
/** The keyword that overrides `camelizeDefault` for a single name. */
|
|
683
913
|
camelizeKeyword: string;
|
|
684
|
-
/** Whether a
|
|
914
|
+
/** Whether a snake_case symbol is exposed in camelCase when the call does not say. */
|
|
685
915
|
camelizeDefault: boolean;
|
|
686
|
-
/**
|
|
916
|
+
/** The scalar names the library accepts in a type position, and the shape of each. List only the library's own. */
|
|
687
917
|
scalars: Record<string, TypeShape>;
|
|
688
|
-
/** Module prefixes
|
|
918
|
+
/** Module prefixes a project can write in front of those scalar names when it spells out the full path. */
|
|
689
919
|
scalarNamePrefixes: string[];
|
|
690
920
|
typeNameConvention: GraphqlTypeNameConvention;
|
|
691
921
|
/**
|
|
692
922
|
* A base class that changes a mutation's wire contract. When a wired
|
|
693
|
-
* class's ancestry reaches `ancestorClassName`, the library wraps
|
|
694
|
-
*
|
|
923
|
+
* class's ancestry reaches `ancestorClassName`, the library wraps every
|
|
924
|
+
* declared argument into one input-object argument called
|
|
695
925
|
* `argumentName` and adds `extraFields` to it. graphql-ruby's
|
|
696
|
-
* RelayClassicMutation
|
|
697
|
-
*
|
|
698
|
-
*
|
|
926
|
+
* RelayClassicMutation does this: on the wire the mutation takes a
|
|
927
|
+
* single required `input`, whose fields are the declared arguments plus
|
|
928
|
+
* an optional `clientMutationId`.
|
|
699
929
|
*/
|
|
700
930
|
argumentWrapping?: {
|
|
701
931
|
ancestorClassName: string;
|
|
@@ -708,79 +938,166 @@ interface GraphqlObjectFields {
|
|
|
708
938
|
}
|
|
709
939
|
|
|
710
940
|
/**
|
|
711
|
-
*
|
|
941
|
+
* Finds the calls in a Ruby body that read or write the database.
|
|
712
942
|
*
|
|
713
|
-
*
|
|
714
|
-
*
|
|
715
|
-
*
|
|
716
|
-
*
|
|
717
|
-
*
|
|
718
|
-
* why ancestry.
|
|
943
|
+
* A call is database work when the pack lists its method as a read or a
|
|
944
|
+
* write, the class behind its receiver reaches a base class the pack
|
|
945
|
+
* lists, and the project does not declare that method itself. A chain
|
|
946
|
+
* counts once, at the outermost call the library defines. Every other
|
|
947
|
+
* call is left to the reach walk.
|
|
719
948
|
*
|
|
720
|
-
* The class
|
|
721
|
-
*
|
|
722
|
-
*
|
|
949
|
+
* The receiver's class comes from the constant bindings when the chain
|
|
950
|
+
* starts at a constant, and from the resolution rules otherwise. Loader
|
|
951
|
+
* calls and raw SQL calls are reported through here as well.
|
|
723
952
|
*/
|
|
724
953
|
|
|
725
954
|
interface RbStorageOptions {
|
|
726
955
|
readonly facts: Database;
|
|
727
956
|
readonly patterns: readonly RbStoragePattern[];
|
|
728
957
|
readonly loaders?: readonly RbLoaderPattern[];
|
|
729
|
-
/**
|
|
958
|
+
/** The pack declarations for calls that take SQL the project wrote itself. */
|
|
730
959
|
readonly rawSql?: readonly RbRawSqlPattern[];
|
|
960
|
+
/** Told the value each effect's columns are given, when somebody listens. */
|
|
961
|
+
readonly statesSlots?: (effect: Effect, slots: readonly SlotValue[]) => void;
|
|
962
|
+
}
|
|
963
|
+
/** A column a storage effect writes or picks rows by, and the value passed for it. */
|
|
964
|
+
interface SlotValue {
|
|
965
|
+
slot: "field" | "selector";
|
|
966
|
+
name: string;
|
|
967
|
+
value: Node;
|
|
731
968
|
}
|
|
732
969
|
/**
|
|
733
970
|
* Whether the recognizer records this call as database work, so a walk
|
|
734
|
-
*
|
|
735
|
-
* written in, which
|
|
971
|
+
* does not need to report it as a gap. `enclosing` is the method the call
|
|
972
|
+
* is written in, which keeps one method's locals apart from another's.
|
|
736
973
|
*/
|
|
737
974
|
declare function storageClaims(call: Node, file: string, options: RbStorageOptions, enclosing?: Node | null): boolean;
|
|
738
975
|
/**
|
|
739
|
-
* The database work a body does, one effect per chain
|
|
740
|
-
*
|
|
741
|
-
*
|
|
742
|
-
* `enclosing` is the method the calls
|
|
976
|
+
* The database work a body does, one effect per chain, so
|
|
977
|
+
* `Order.where(id: 1).first` counts once. `file` is the absolute path the
|
|
978
|
+
* calls were read from, which the constant bindings are keyed on.
|
|
979
|
+
* `enclosing` is the method the calls are in, or null outside one.
|
|
743
980
|
*/
|
|
744
981
|
declare function storageEffects(calls: readonly Node[], file: string, options: RbStorageOptions, enclosing?: Node | null): Effect[];
|
|
745
982
|
|
|
746
|
-
/**
|
|
983
|
+
/**
|
|
984
|
+
* The calls a body makes, as invocation effects. A call written under an
|
|
985
|
+
* `if` records that test as a precondition, and the IR treats a call
|
|
986
|
+
* with preconditions as one that does not always run.
|
|
987
|
+
*/
|
|
988
|
+
|
|
989
|
+
/** Methods the pack says the library defines, so a receiverless call to one of them is not project work. */
|
|
747
990
|
type InheritedMethods = ReadonlySet<string>;
|
|
748
991
|
|
|
749
|
-
/**
|
|
992
|
+
/**
|
|
993
|
+
* The shared groups a run's test files define, and where each one is
|
|
994
|
+
* included. RSpec's `shared_examples "x"` is written once, often in a
|
|
995
|
+
* support file, and `it_behaves_like "x"` in a spec runs its examples
|
|
996
|
+
* there. An include finds its shared group by name, in its own file
|
|
997
|
+
* first and then anywhere in the run.
|
|
998
|
+
*
|
|
999
|
+
* A name read inside a shared group that the group does not define
|
|
1000
|
+
* comes from whoever includes it. The value facts key such a name on
|
|
1001
|
+
* the shared group, and `emitSharedGroupBinds` binds it to what each
|
|
1002
|
+
* include site has under that name. Two includers that give it two
|
|
1003
|
+
* values leave it unsettled, since which one ran is not known.
|
|
1004
|
+
*/
|
|
1005
|
+
|
|
1006
|
+
interface SharedDefinition {
|
|
1007
|
+
readonly file: string;
|
|
1008
|
+
readonly call: Node;
|
|
1009
|
+
readonly name: string;
|
|
1010
|
+
}
|
|
1011
|
+
interface IncludeSite {
|
|
1012
|
+
readonly file: string;
|
|
1013
|
+
readonly call: Node;
|
|
1014
|
+
/** The groups around the include, outermost first. */
|
|
1015
|
+
readonly groups: readonly Node[];
|
|
1016
|
+
/** Whether the shared examples run in a group of their own, as `it_behaves_like` runs them. */
|
|
1017
|
+
readonly nested: boolean;
|
|
1018
|
+
readonly definition: SharedDefinition;
|
|
1019
|
+
}
|
|
1020
|
+
/** A test file and the pattern that reads it. */
|
|
1021
|
+
interface PatternedFile {
|
|
1022
|
+
readonly file: string;
|
|
1023
|
+
readonly root: Node;
|
|
1024
|
+
readonly pattern: RbTestCases;
|
|
1025
|
+
}
|
|
1026
|
+
declare class SharedGroupIndex {
|
|
1027
|
+
private readonly db;
|
|
1028
|
+
private readonly definitions;
|
|
1029
|
+
private readonly definitionsByNode;
|
|
1030
|
+
private readonly sitesByNode;
|
|
1031
|
+
private readonly sitesByDefinition;
|
|
1032
|
+
private readonly filesByTree;
|
|
1033
|
+
constructor(db: Database, files: readonly PatternedFile[]);
|
|
1034
|
+
/** The include this call makes, or null when it makes none or names no shared group the run defines. */
|
|
1035
|
+
includedAt(call: Node): IncludeSite | null;
|
|
1036
|
+
/** The shared group this call defines, or null. */
|
|
1037
|
+
definitionAt(call: Node): SharedDefinition | null;
|
|
1038
|
+
includersOf(definition: SharedDefinition): readonly IncludeSite[];
|
|
1039
|
+
/** The file a node from a test or support file is written in. */
|
|
1040
|
+
fileOf(node: Node): string | null;
|
|
1041
|
+
private recordIncludes;
|
|
1042
|
+
private recordInclude;
|
|
1043
|
+
private nameOf;
|
|
1044
|
+
private noteRead;
|
|
1045
|
+
}
|
|
1046
|
+
|
|
1047
|
+
/**
|
|
1048
|
+
* Discovers the units a Ruby file defines: GraphQL fields declared through
|
|
1049
|
+
* a class DSL, controller actions, and client calls.
|
|
1050
|
+
*
|
|
1051
|
+
* A field's boundary binding and declared contract come from the
|
|
1052
|
+
* arguments of its own DSL call. A field written with one of the pack's
|
|
1053
|
+
* wiring keywords declares no type of its own, so its contract and the
|
|
1054
|
+
* method behind it are read from the class the keyword points at, one hop
|
|
1055
|
+
* away. DESIGN.md describes what a field's summary says about the method
|
|
1056
|
+
* behind it and where the reading stops.
|
|
1057
|
+
*/
|
|
1058
|
+
|
|
1059
|
+
/**
|
|
1060
|
+
* What one run has read from the disk: parsed files by absolute path, so
|
|
1061
|
+
* a class that several fields refer to is only parsed once, and what its
|
|
1062
|
+
* constant lookups have found.
|
|
1063
|
+
*/
|
|
750
1064
|
interface FileCache {
|
|
751
1065
|
get(absPath: string): Promise<Node | null>;
|
|
1066
|
+
readonly constantFiles: ConstantFileCache;
|
|
752
1067
|
}
|
|
753
|
-
declare function createFileCache(parse: (source: string) => Promise<Node>, readFile: (absPath: string) => string | null): FileCache;
|
|
1068
|
+
declare function createFileCache(parse: (source: string, absPath: string) => Promise<Node>, readFile: (absPath: string) => string | null): FileCache;
|
|
754
1069
|
/**
|
|
755
|
-
* What
|
|
756
|
-
*
|
|
757
|
-
*
|
|
1070
|
+
* What reading a method body needs from the run's packs. Any options
|
|
1071
|
+
* object that has these fields, `DiscoveryOptions` among them, can be
|
|
1072
|
+
* passed straight through.
|
|
758
1073
|
*/
|
|
759
1074
|
interface BodyReadOptions {
|
|
760
|
-
/** The run's
|
|
1075
|
+
/** The run's facts, which the value evaluator reads names through. Absent in a test that builds one file by hand. */
|
|
761
1076
|
readonly facts?: Database | undefined;
|
|
762
|
-
/**
|
|
1077
|
+
/** The storage patterns that decide whether a call reads or writes the database. Absent when no pack declares any. */
|
|
763
1078
|
readonly storage?: RbStorageOptions | undefined;
|
|
764
|
-
/** The methods
|
|
1079
|
+
/** The methods the run's packs declare their libraries define. Calls to them are left off an effect list. */
|
|
765
1080
|
readonly inheritedMethods?: InheritedMethods | undefined;
|
|
766
|
-
/** The calls
|
|
1081
|
+
/** The calls whose block the run's packs declare runs as part of the surrounding body. */
|
|
767
1082
|
readonly bodyBlocks?: BodyBlocks | undefined;
|
|
768
|
-
/**
|
|
1083
|
+
/** The methods each class defines under a name computed at run time, by class key. */
|
|
769
1084
|
readonly dynamicNames?: DynamicNames | undefined;
|
|
770
1085
|
}
|
|
771
1086
|
interface DiscoveryOptions extends BodyReadOptions {
|
|
772
1087
|
packs: RubyPack[];
|
|
773
1088
|
/** Repo-relative or absolute path recorded on each summary's `location.file`. */
|
|
774
1089
|
filePath: string;
|
|
775
|
-
/** Absolute path of the file being read, for
|
|
1090
|
+
/** Absolute path of the file being read, used for `ReachedBody.file`. Falls back to `filePath` for a source that is not on disk. */
|
|
776
1091
|
absoluteFile?: string;
|
|
777
|
-
/**
|
|
1092
|
+
/** The `location.file` to record for another file, needed when a controller's filters come from an ancestor in another file. */
|
|
778
1093
|
displayPathOf?: (absolute: string) => string;
|
|
779
1094
|
cache: FileCache;
|
|
780
|
-
/** Called once
|
|
1095
|
+
/** Called once for each discovered unit whose body is a method, so the reach walk can start from it. */
|
|
781
1096
|
onReachSeed?: (raw: RawCodeStructure, seed: ReachSeed) => void;
|
|
1097
|
+
/** The shared groups the run's test files define, when a pack reads tests. */
|
|
1098
|
+
sharedGroups?: SharedGroupIndex | undefined;
|
|
782
1099
|
}
|
|
783
|
-
/** The method behind a discovered unit
|
|
1100
|
+
/** The method behind a discovered unit, and where it is, so the reach walk can start there as it does at any `def`. */
|
|
784
1101
|
interface ReachSeed {
|
|
785
1102
|
readonly file: string;
|
|
786
1103
|
readonly node: Node;
|
|
@@ -790,16 +1107,16 @@ interface ReachSeed {
|
|
|
790
1107
|
declare function discoverUnits(root: Node, options: DiscoveryOptions): Promise<RawCodeStructure[]>;
|
|
791
1108
|
|
|
792
1109
|
/**
|
|
793
|
-
*
|
|
1110
|
+
* Reads association declarations such as `has_many :statuses` out of a
|
|
1111
|
+
* model's body.
|
|
794
1112
|
*
|
|
795
|
-
* A pack says which calls declare an association. The target is the
|
|
796
|
-
*
|
|
797
|
-
*
|
|
798
|
-
*
|
|
799
|
-
*
|
|
800
|
-
*
|
|
801
|
-
*
|
|
802
|
-
* before it reaches `Status`.
|
|
1113
|
+
* A pack says which calls declare an association. The target is the class
|
|
1114
|
+
* `class_name:` gives, or the association's name put through the
|
|
1115
|
+
* inflections when the call gives none. The source never writes that
|
|
1116
|
+
* inflected name, so each declaration gets a constant reference of its
|
|
1117
|
+
* own, and the constant bindings settle it from the model's nesting. A
|
|
1118
|
+
* `has_many :statuses` inside `Admin::Account` reaches `Admin::Status`
|
|
1119
|
+
* before `Status`.
|
|
803
1120
|
*/
|
|
804
1121
|
|
|
805
1122
|
/** One association a class or module body declares. */
|
|
@@ -812,11 +1129,17 @@ interface AssociationDeclaration {
|
|
|
812
1129
|
readonly target: ConstantReference;
|
|
813
1130
|
}
|
|
814
1131
|
|
|
815
|
-
/**
|
|
1132
|
+
/**
|
|
1133
|
+
* Binds each Ruby constant reference to the definition behind it. Ruby
|
|
1134
|
+
* has no imports, so there is no `imports` fact to follow, and a
|
|
1135
|
+
* reference is bound directly to its definition.
|
|
1136
|
+
*/
|
|
1137
|
+
|
|
1138
|
+
/** A constant definition, which every file in the run can see, under its qualified name. */
|
|
816
1139
|
interface ConstantDefinition {
|
|
817
1140
|
readonly qualifiedName: string;
|
|
818
1141
|
readonly key: string;
|
|
819
|
-
/** `class
|
|
1142
|
+
/** A `class` or `module` declaration, which any file may reopen, or an `X = ...` assignment. */
|
|
820
1143
|
readonly kind: "declaration" | "assignment";
|
|
821
1144
|
}
|
|
822
1145
|
/** A constant read somewhere, with the nesting it was read inside. */
|
|
@@ -831,69 +1154,79 @@ interface FileConstants {
|
|
|
831
1154
|
readonly filePath: string;
|
|
832
1155
|
readonly definitions: readonly ConstantDefinition[];
|
|
833
1156
|
readonly references: readonly ConstantReference[];
|
|
834
|
-
/** Empty unless a pack in the run
|
|
1157
|
+
/** Empty unless a pack in the run declares association calls. */
|
|
835
1158
|
readonly associations: readonly AssociationDeclaration[];
|
|
836
1159
|
}
|
|
837
1160
|
/**
|
|
838
|
-
* Every constant this file defines and every one it reads
|
|
839
|
-
* the nesting
|
|
840
|
-
*
|
|
841
|
-
*
|
|
1161
|
+
* Every constant this file defines and every one it reads, in one walk
|
|
1162
|
+
* that tracks the nesting as it goes. An association's target is
|
|
1163
|
+
* collected here too, because the inflected name has no node in the
|
|
1164
|
+
* source and only the nesting says which class it means.
|
|
842
1165
|
*/
|
|
843
1166
|
declare function collectFileConstants(filePath: string, root: Node, associationCalls?: readonly RbAssociationCalls[], inflections?: RbInflections): FileConstants;
|
|
844
1167
|
/**
|
|
845
|
-
*
|
|
846
|
-
* looking outwards from the nesting it was read inside the way Ruby
|
|
1168
|
+
* Binds every constant read anywhere in the run to its definition,
|
|
1169
|
+
* looking outwards from the nesting it was read inside, the way Ruby
|
|
1170
|
+
* does.
|
|
847
1171
|
*
|
|
848
|
-
* `binds(refKey, defKey)`
|
|
849
|
-
*
|
|
850
|
-
*
|
|
1172
|
+
* `binds(refKey, defKey)` records the binding. `importsFile(from, to)`
|
|
1173
|
+
* records the same link between the two files, since reading a constant
|
|
1174
|
+
* another file defines is the nearest thing Ruby has to an import.
|
|
851
1175
|
*
|
|
852
|
-
* `declaresAssociation` is emitted here
|
|
853
|
-
* target is one of
|
|
854
|
-
* together.
|
|
1176
|
+
* `declaresAssociation` is emitted here too, because an association's
|
|
1177
|
+
* target is one of these references and the shared rules join the two.
|
|
855
1178
|
*/
|
|
856
1179
|
declare function emitConstantBindings(db: Database, perFile: Iterable<FileConstants>): void;
|
|
857
1180
|
|
|
858
1181
|
/**
|
|
859
|
-
*
|
|
1182
|
+
* Emits the value facts that the rules in `@suss/resolution` join, for a
|
|
1183
|
+
* Ruby file. The relations and their columns are defined by that package.
|
|
1184
|
+
* The package DESIGN.md describes where Ruby differs from the other
|
|
1185
|
+
* adapters: names keyed on their scope, a bare name that runs a method,
|
|
1186
|
+
* mixins recorded as `extends`, and instance variables as class properties.
|
|
1187
|
+
*/
|
|
1188
|
+
|
|
1189
|
+
/**
|
|
1190
|
+
* A node's key across the whole run. It includes the end offset because a
|
|
860
1191
|
* call and its receiver start at the same offset.
|
|
861
1192
|
*/
|
|
862
1193
|
declare function nodeId(filePath: string, node: Node): string;
|
|
863
1194
|
/**
|
|
864
|
-
* The key
|
|
865
|
-
*
|
|
866
|
-
* the
|
|
1195
|
+
* The key to ask the rules about when reading this expression. `enclosing`
|
|
1196
|
+
* is the method the expression is written in, or null outside one.
|
|
1197
|
+
* `parent` is the node the expression is written in, when the caller has
|
|
1198
|
+
* it, since reading a node's parent off the tree costs a walk from the root.
|
|
867
1199
|
*
|
|
868
|
-
* Two
|
|
869
|
-
*
|
|
870
|
-
*
|
|
871
|
-
* call itself.
|
|
1200
|
+
* Two kinds of name are keyed on their node instead of on the name. The
|
|
1201
|
+
* tree has no node for the `receiver.method` part of a call, so the
|
|
1202
|
+
* callee is keyed on the method name's node. A bare name that Ruby runs
|
|
1203
|
+
* as a method is the call itself.
|
|
872
1204
|
*/
|
|
873
|
-
declare function readKey(filePath: string, written: Node, enclosing: Node | null): string;
|
|
1205
|
+
declare function readKey(filePath: string, written: Node, enclosing: Node | null, parent?: Node | null): string;
|
|
874
1206
|
/**
|
|
875
|
-
*
|
|
876
|
-
* so
|
|
1207
|
+
* Walks a file and emits its value facts. Each method is walked on its
|
|
1208
|
+
* own, so the returns and calls in a body are recorded against the method
|
|
1209
|
+
* they are written in.
|
|
877
1210
|
*/
|
|
878
|
-
declare function emitValueFacts(db: Database, filePath: string, root: Node, bodyBlocks?: BodyBlocks): void;
|
|
1211
|
+
declare function emitValueFacts(db: Database, filePath: string, root: Node, bodyBlocks?: BodyBlocks, scopeCalls?: ReadonlySet<string>): void;
|
|
879
1212
|
|
|
880
1213
|
/**
|
|
881
|
-
* The session behind `suss ask why` on a Ruby project
|
|
882
|
-
*
|
|
883
|
-
*
|
|
884
|
-
*
|
|
1214
|
+
* The session behind `suss ask why` on a Ruby project. It parses every
|
|
1215
|
+
* file under the root with tree-sitter, finds the expression a question
|
|
1216
|
+
* points at, and renders the witness proof of what that expression
|
|
1217
|
+
* resolved to through `@suss/resolution`'s phrases.
|
|
885
1218
|
*
|
|
886
|
-
* It
|
|
887
|
-
*
|
|
888
|
-
*
|
|
889
|
-
*
|
|
890
|
-
* file it came from, since a node alone does not say which file
|
|
891
|
-
* parsed it.
|
|
1219
|
+
* It emits its facts through the same `RunFacts` an extraction over the
|
|
1220
|
+
* same packs uses, and keeps a location for every fact key so each atom
|
|
1221
|
+
* of a proof can point back at source. A handle pairs a tree-sitter node
|
|
1222
|
+
* with its file, since a node alone does not say which file it came from.
|
|
892
1223
|
*/
|
|
893
1224
|
|
|
894
1225
|
interface RubyWhySessionOptions {
|
|
895
|
-
/** The project root
|
|
1226
|
+
/** The project root. Paths in every answer are relative to it. */
|
|
896
1227
|
dir: string;
|
|
1228
|
+
/** The packs the extraction ran with. A hop only a pack declares, such as `Account.find` giving back an Account, is explained only when that pack is here. */
|
|
1229
|
+
packs?: readonly RubyPack[];
|
|
897
1230
|
}
|
|
898
1231
|
/** A found node, paired with the file it was parsed from. */
|
|
899
1232
|
interface RubyValueHandle {
|
|
@@ -918,8 +1251,8 @@ declare class RubyWhySession {
|
|
|
918
1251
|
findCallee(file: string, startLine: number, endLine: number, calleeText: string): RubyValueHandle | null;
|
|
919
1252
|
/**
|
|
920
1253
|
* Why `value` resolves to what it does: the witness proof, flattened
|
|
921
|
-
* to the chain and rendered. Null when the value does not resolve,
|
|
922
|
-
*
|
|
1254
|
+
* to the chain and rendered. Null when the value does not resolve, and
|
|
1255
|
+
* the caller reports that itself.
|
|
923
1256
|
*/
|
|
924
1257
|
explain(value: RubyValueHandle, options?: {
|
|
925
1258
|
maxDepth?: number;
|
|
@@ -927,38 +1260,59 @@ declare class RubyWhySession {
|
|
|
927
1260
|
private locate;
|
|
928
1261
|
private rootOf;
|
|
929
1262
|
private pathOf;
|
|
930
|
-
/** A file path
|
|
1263
|
+
/** A file path relative to the root, or unchanged when it is outside the root. */
|
|
931
1264
|
private displayPath;
|
|
932
1265
|
}
|
|
933
1266
|
|
|
934
1267
|
/**
|
|
935
|
-
*
|
|
936
|
-
*
|
|
937
|
-
*
|
|
938
|
-
*
|
|
939
|
-
*
|
|
940
|
-
* `entry` reuses the existing relation name and shape, where the unit
|
|
941
|
-
* is a pack-discovered entry point, so a Ruby-discovered field is an
|
|
942
|
-
* entry the same way a Python route or a TypeScript handler is.
|
|
1268
|
+
* One evaluator per project, over the parsed files and the resolution
|
|
1269
|
+
* facts. A reader passes in a node and gets back the abstract value it
|
|
1270
|
+
* comes down to. A route path or a prefix is then built from that value,
|
|
1271
|
+
* so every way of writing it gives the same result.
|
|
943
1272
|
*
|
|
944
|
-
*
|
|
945
|
-
* file
|
|
946
|
-
*
|
|
1273
|
+
* The facts key a node by file and span, so the evaluator keeps every
|
|
1274
|
+
* file's root to find the node a fact refers to. Without facts, as in a
|
|
1275
|
+
* unit test or when a routes file is read on its own, the evaluator
|
|
1276
|
+
* still follows names within the file through the engine's own scope
|
|
1277
|
+
* walk.
|
|
947
1278
|
*/
|
|
948
1279
|
|
|
1280
|
+
interface EvaluatedFile {
|
|
1281
|
+
readonly file: string;
|
|
1282
|
+
readonly root: Node;
|
|
1283
|
+
}
|
|
1284
|
+
interface ProjectNodes {
|
|
1285
|
+
readonly files: readonly EvaluatedFile[];
|
|
1286
|
+
/** Every method definition by its node key, for a resolved callee. */
|
|
1287
|
+
readonly definitions: ReadonlyMap<string, Node>;
|
|
1288
|
+
}
|
|
1289
|
+
/** Registers the parsed project, so reads through `db` can follow the facts back to nodes. */
|
|
1290
|
+
declare function bindEvaluator(db: Database, nodes: ProjectNodes): void;
|
|
1291
|
+
/** Values to use for the parameters of the block or method around `node`, as a caller would supply them. */
|
|
1292
|
+
type ParameterBindings = ReadonlyMap<string, string>;
|
|
949
1293
|
/**
|
|
950
|
-
* The
|
|
951
|
-
*
|
|
952
|
-
*
|
|
1294
|
+
* The abstract value `node` comes down to, through the facts when `db`
|
|
1295
|
+
* was bound. With a site, the value when its receiver is the instance
|
|
1296
|
+
* that site made. That evaluation is not memoized.
|
|
1297
|
+
*/
|
|
1298
|
+
declare function evaluatedValue(node: Node, db?: Database, bindings?: ParameterBindings, site?: string): Value;
|
|
1299
|
+
/** The one string `node` comes down to, or null when it does not settle on one. */
|
|
1300
|
+
declare function stringValueOf(node: Node, db?: Database, bindings?: ParameterBindings): string | null;
|
|
1301
|
+
/** Every method a file defines, keyed the way the facts key it, for `bindEvaluator`. */
|
|
1302
|
+
declare function methodDefinitionsIn(file: string, root: Node): Map<string, Node>;
|
|
1303
|
+
|
|
1304
|
+
/**
|
|
1305
|
+
* Runs the Ruby adapter over a project: discovers units, emits summaries
|
|
1306
|
+
* in the shared IR, and emits facts.
|
|
1307
|
+
*
|
|
1308
|
+
* It parses every file it is given, emits the run's facts into one
|
|
1309
|
+
* shared `Database`, runs discovery over each file, walks what each unit
|
|
1310
|
+
* reaches, and hands every unit to `assembleSummary` from
|
|
1311
|
+
* `@suss/extractor`. The Python and TypeScript adapters use the same
|
|
1312
|
+
* assembly step, so gap detection is shared across all three languages.
|
|
1313
|
+
* With a cache, a run after an edit replays the files and methods whose
|
|
1314
|
+
* inputs did not change, through the records in `reuse.ts`.
|
|
953
1315
|
*/
|
|
954
|
-
declare function unitKey(filePath: string, range: {
|
|
955
|
-
start: number;
|
|
956
|
-
end: number;
|
|
957
|
-
}, name: string): string;
|
|
958
|
-
declare function emitEntryFact(db: Database, filePath: string, range: {
|
|
959
|
-
start: number;
|
|
960
|
-
end: number;
|
|
961
|
-
}, name: string): void;
|
|
962
1316
|
|
|
963
1317
|
interface ExtractRubyOptions {
|
|
964
1318
|
/** Absolute paths of the files to parse and extract. */
|
|
@@ -976,9 +1330,22 @@ interface ExtractRubyOptions {
|
|
|
976
1330
|
onCacheDiagnostic?: (diagnostic: CacheDiagnostic) => void;
|
|
977
1331
|
/** Absolute. `<projectRoot>/.suss/cache` by default; `null` turns it off. */
|
|
978
1332
|
cacheDir?: string | null;
|
|
979
|
-
/**
|
|
1333
|
+
/** How to handle gaps. Composing a controller's filters into its actions can add one. */
|
|
980
1334
|
gapHandling?: ExtractorOptions["gapHandling"];
|
|
1335
|
+
/** The modules the project lists in `suss.json`, with absolute paths. */
|
|
1336
|
+
modules?: readonly DeclaredModule[];
|
|
1337
|
+
/** Parses an earlier run in this process left, for a file whose text is unchanged. */
|
|
1338
|
+
keptParses?: KeptRubyParses;
|
|
981
1339
|
}
|
|
1340
|
+
type KeptRubyParses = KeptParses<Node>;
|
|
1341
|
+
/** A holder for parses between runs, which frees each tree it lets go of. */
|
|
1342
|
+
declare function keptRubyParses(): KeptRubyParses;
|
|
1343
|
+
/**
|
|
1344
|
+
* Parses these files into `kept` before any run needs them. A run served
|
|
1345
|
+
* whole from the cache parses nothing, so a process that keeps parses
|
|
1346
|
+
* calls this while nobody is waiting.
|
|
1347
|
+
*/
|
|
1348
|
+
declare function parseRubyAhead(files: readonly string[], kept: KeptRubyParses): Promise<void>;
|
|
982
1349
|
interface ExtractRubyResult {
|
|
983
1350
|
summaries: BehavioralSummary[];
|
|
984
1351
|
facts: Database;
|
|
@@ -991,25 +1358,24 @@ interface FileFactsOptions {
|
|
|
991
1358
|
}
|
|
992
1359
|
/**
|
|
993
1360
|
* The facts for a single parsed file, with the evaluator bound to them,
|
|
994
|
-
* for a caller
|
|
995
|
-
*
|
|
996
|
-
*
|
|
997
|
-
*
|
|
998
|
-
* resolves there and never here.
|
|
1361
|
+
* for a caller with one file and no project, such as a pack's tests. The
|
|
1362
|
+
* rules need facts to work out what built a receiver. A project run emits
|
|
1363
|
+
* the same facts for every file at once, so a name defined in another
|
|
1364
|
+
* file resolves there but not here.
|
|
999
1365
|
*/
|
|
1000
1366
|
declare function factsForFile(options: FileFactsOptions): Database;
|
|
1001
1367
|
declare function extractRubyProject(options: ExtractRubyOptions): Promise<ExtractRubyResult>;
|
|
1002
|
-
/** Every `.rb` file under `root`,
|
|
1368
|
+
/** Every `.rb` file under `root`, sorted, skipping vendored, temporary and VCS directories. */
|
|
1003
1369
|
declare function findRubyFiles(root: string): string[];
|
|
1004
1370
|
|
|
1005
1371
|
/**
|
|
1006
1372
|
* Evidence for drafting a graphql-ruby `extends-base` dependency stub:
|
|
1007
|
-
* every `require
|
|
1008
|
-
* project class whose superclass is spelled from it.
|
|
1009
|
-
* only recognizes a class
|
|
1010
|
-
*
|
|
1011
|
-
*
|
|
1012
|
-
*
|
|
1373
|
+
* every `require` or `require_relative` of the requested package, and
|
|
1374
|
+
* every project class whose superclass name is spelled from it.
|
|
1375
|
+
* Discovery only recognizes a class by the literal names in
|
|
1376
|
+
* `baseClassNames`, so a project's own base under a renamed namespace,
|
|
1377
|
+
* or a class that extends the library's class directly, has to be
|
|
1378
|
+
* listed by its exact name.
|
|
1013
1379
|
*/
|
|
1014
1380
|
interface RubyRequireSite {
|
|
1015
1381
|
target: string;
|
|
@@ -1043,68 +1409,30 @@ declare function rubyStubEvidence(options: RubyStubEvidenceOptions): Promise<Rub
|
|
|
1043
1409
|
interface TypeReadContext {
|
|
1044
1410
|
/** The `Module.nesting` chain in effect, innermost first. */
|
|
1045
1411
|
nesting: readonly string[];
|
|
1046
|
-
/** Every class the surrounding file defines, by qualified name
|
|
1412
|
+
/** Every class the surrounding file defines, by qualified name. A project class shadows a scalar with the same name. */
|
|
1047
1413
|
knownClasses: ReadonlySet<string>;
|
|
1048
1414
|
scalars: Readonly<Record<string, TypeShape>>;
|
|
1049
1415
|
scalarNamePrefixes: readonly string[];
|
|
1050
1416
|
typeNameConvention: GraphqlTypeNameConvention;
|
|
1051
1417
|
}
|
|
1052
1418
|
/**
|
|
1053
|
-
*
|
|
1054
|
-
*
|
|
1419
|
+
* Returns null when the type cannot be read, and the field then abstains.
|
|
1420
|
+
* A caller must not fall back to `unknown`, because that would report a
|
|
1421
|
+
* contract nobody declared.
|
|
1055
1422
|
*
|
|
1056
|
-
* A bare `constant` is checked against `ctx.nesting` before the scalar
|
|
1057
|
-
* because a project class at
|
|
1058
|
-
*
|
|
1059
|
-
* shadowed, so it skips that check.
|
|
1423
|
+
* A bare `constant` is checked against `ctx.nesting` before the scalar
|
|
1424
|
+
* table, because Ruby finds a project class at any level of
|
|
1425
|
+
* `Module.nesting` first. A compound `scope_resolution` path is absolute
|
|
1426
|
+
* and cannot be shadowed, so it skips that check.
|
|
1060
1427
|
*/
|
|
1061
1428
|
declare function typeShapeFromNode(node: Node, ctx: TypeReadContext): TypeShape | null;
|
|
1062
1429
|
|
|
1063
1430
|
/**
|
|
1064
|
-
*
|
|
1065
|
-
*
|
|
1066
|
-
*
|
|
1067
|
-
*
|
|
1068
|
-
*
|
|
1069
|
-
* The facts key a node by file and span, so the evaluator keeps every
|
|
1070
|
-
* file's root to find the node a fact refers to. Without facts,
|
|
1071
|
-
* which is how a unit test or a routes file on its own runs, the
|
|
1072
|
-
* evaluator still follows names within the file through the engine's
|
|
1073
|
-
* own scope walk.
|
|
1074
|
-
*/
|
|
1075
|
-
|
|
1076
|
-
interface EvaluatedFile {
|
|
1077
|
-
readonly file: string;
|
|
1078
|
-
readonly root: Node;
|
|
1079
|
-
}
|
|
1080
|
-
interface ProjectNodes {
|
|
1081
|
-
readonly files: readonly EvaluatedFile[];
|
|
1082
|
-
/** Every method definition by its node key, for a resolved callee. */
|
|
1083
|
-
readonly definitions: ReadonlyMap<string, Node>;
|
|
1084
|
-
}
|
|
1085
|
-
/** Register the parsed project, so reads through `db` can follow the facts back to nodes. */
|
|
1086
|
-
declare function bindEvaluator(db: Database, nodes: ProjectNodes): void;
|
|
1087
|
-
/** Strings to read for the parameters of the block or method `node` is written in, the way a caller would supply them. */
|
|
1088
|
-
type ParameterBindings = ReadonlyMap<string, string>;
|
|
1089
|
-
/**
|
|
1090
|
-
* The abstract value `node` comes down to, through the facts when `db`
|
|
1091
|
-
* was bound. With a site, what it comes down to when the receiver
|
|
1092
|
-
* behind it is the instance that site made; that run is not memoized.
|
|
1093
|
-
*/
|
|
1094
|
-
declare function evaluatedValue(node: Node, db?: Database, bindings?: ParameterBindings, site?: string): Value;
|
|
1095
|
-
/** The one string `node` comes down to, or null when it does not settle on one. */
|
|
1096
|
-
declare function stringValueOf(node: Node, db?: Database, bindings?: ParameterBindings): string | null;
|
|
1097
|
-
/** Every method a file defines, keyed the way the facts key it, for `bindEvaluator`. */
|
|
1098
|
-
declare function methodDefinitionsIn(file: string, root: Node): Map<string, Node>;
|
|
1099
|
-
|
|
1100
|
-
/**
|
|
1101
|
-
* version.ts: this adapter's own half of the cache key.
|
|
1102
|
-
*
|
|
1103
|
-
* `ADAPTER_VERSION` is the hand-bumped semver. Bump it on any change
|
|
1104
|
-
* that affects extraction output: IR shape, discovery semantics,
|
|
1105
|
-
* terminal classification, anything that would invalidate previously
|
|
1106
|
-
* cached summaries.
|
|
1431
|
+
* The adapter's part of the cache key. Bump `ADAPTER_VERSION` by hand on
|
|
1432
|
+
* any change to extraction output, such as a change to the IR, to which
|
|
1433
|
+
* units are discovered, or to how a terminal is classified. A summary
|
|
1434
|
+
* cached under the old version is then thrown away.
|
|
1107
1435
|
*/
|
|
1108
1436
|
declare const ADAPTER_VERSION = "0.1.0";
|
|
1109
1437
|
|
|
1110
|
-
export { ADAPTER_VERSION, type AncestorEntry, type AncestorLookup, type Ancestry, type CallArgs, type ClassInfo, type ConstantPathConvention, type ControllerActions, type DiscoveryOptions, type EvaluatedFile, type ExtractRubyOptions, type ExtractRubyResult, type FileCache, type FileConstants, type FileFactsOptions, type GraphqlObjectFields, type GraphqlTypeNameConvention, type MethodLookup, type ParameterBindings, type ProjectNodes, type Range, type RbAddressingCall, type RbArgumentPlace, type RbBodyBlock, type RbInflections, type RbRawSqlPattern, type RbRowCall, type RbStatusCall, type RbStorageOptions, type RbStoragePattern, type ReachedBody, type RubyDiscoveryPattern, type RubyExtendsSite, type RubyPack, type RubyRequireSite, type RubyStubEvidence, type RubyStubEvidenceOptions, type RubyValueHandle, RubyWhySession, type RubyWhySessionOptions, type TypeReadContext, ancestryOf, bindEvaluator, bodyStatements, booleanLiteralValue, collectFileConstants, createFileCache, discoverUnits, emitConstantBindings,
|
|
1438
|
+
export { ADAPTER_VERSION, type AncestorEntry, type AncestorLookup, type Ancestry, type CallArgs, type ClassInfo, type ConstantFileCache, type ConstantPathConvention, type ControllerActions, type DiscoveryOptions, type EvaluatedFile, type ExtractRubyOptions, type ExtractRubyResult, type FileCache, type FileConstants, type FileFactsOptions, type GraphqlObjectFields, type GraphqlTypeNameConvention, type KeptRubyParses, type MethodLookup, type ParameterBindings, type ProjectNodes, type Range, type RbAddressingCall, type RbArgumentPlace, type RbBodyBlock, type RbExpectations, type RbFactories, type RbFactoryBuilder, type RbInflections, type RbPredicateMatcher, type RbRawSqlPattern, type RbRowCall, type RbSharedInclude, type RbStatusCall, type RbStorageOptions, type RbStoragePattern, type RbTestCases, type RbTestClasses, type RbTestMocks, type ReachedBody, type RubyDiscoveryPattern, type RubyExtendsSite, type RubyPack, type RubyRequireSite, type RubyStubEvidence, type RubyStubEvidenceOptions, type RubyValueHandle, RubyWhySession, type RubyWhySessionOptions, type TypeReadContext, ancestryOf, bindEvaluator, bodyStatements, booleanLiteralValue, collectFileConstants, createConstantFileCache, createFileCache, discoverUnits, emitConstantBindings, emitValueFacts, evaluatedValue, extractRubyProject, factsForFile, field, findRubyFiles, graphqlTypeNameFromQualified, hashKeySymbolName, inheritedStatements, keptRubyParses, methodDefinitionsIn, methodInAncestry, nestedStatements, nodeId, parseRuby, parseRubyAhead, parseRubySync, preloadRubyGrammar, qualifyConstantRef, reachDefinition, readCallArgs, readKey, resolveConstantFile, rubyStubEvidence, runStatements, storageClaims, storageEffects, stringLiteralValue, stringValueOf, symbolValue, typeShapeFromNode, underscoreConstantPath, walkClasses, walkDefinitions };
|