@suss/resolution 0.27.0 → 0.29.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 +4 -4
- package/dist/index.cjs +824 -352
- package/dist/index.d.cts +242 -2
- package/dist/index.d.ts +242 -2
- package/dist/index.js +463 -2
- package/package.json +2 -2
package/dist/index.d.cts
CHANGED
|
@@ -1,5 +1,72 @@
|
|
|
1
1
|
import * as _suss_datalog from '@suss/datalog';
|
|
2
|
-
import { Database, Atom, Tuple, Proof, Rule } from '@suss/datalog';
|
|
2
|
+
import { Database, OnDemandRules, Atom, Tuple, Proof, Rule } from '@suss/datalog';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* What a call's callee is, and when the rules settle on nothing, why.
|
|
6
|
+
*
|
|
7
|
+
* `resolves` comes back with a function and stays quiet otherwise, and a
|
|
8
|
+
* caller recording a gap needs the quiet cases told apart: a method on
|
|
9
|
+
* what a caller passed in is a different stop from a method on a value
|
|
10
|
+
* this run never read. So when the rules settle nothing, this walks down
|
|
11
|
+
* the facts the value was built from, one construct at a time, until it
|
|
12
|
+
* meets something that says where the value came from.
|
|
13
|
+
*
|
|
14
|
+
* Both halves are here because every language emits the same facts and
|
|
15
|
+
* meets the same stops. The words for an outcome stay with a language.
|
|
16
|
+
*/
|
|
17
|
+
|
|
18
|
+
/** What a value a call is made through turns out to be. */
|
|
19
|
+
type CalleeOutcome =
|
|
20
|
+
/** One function in this run. */
|
|
21
|
+
{
|
|
22
|
+
readonly kind: "function";
|
|
23
|
+
readonly key: string;
|
|
24
|
+
}
|
|
25
|
+
/** One object in this run, which is a class where a language writes classes as objects. */
|
|
26
|
+
| {
|
|
27
|
+
readonly kind: "object";
|
|
28
|
+
readonly key: string;
|
|
29
|
+
}
|
|
30
|
+
/** More than one, so no single answer, and `sources` tells them apart. */
|
|
31
|
+
| {
|
|
32
|
+
readonly kind: "severalSources";
|
|
33
|
+
readonly sources: readonly string[];
|
|
34
|
+
}
|
|
35
|
+
/** A parameter, whose key is here so a caller can say whose parameter it is. */
|
|
36
|
+
| {
|
|
37
|
+
readonly kind: "callerSupplied";
|
|
38
|
+
readonly key: string;
|
|
39
|
+
}
|
|
40
|
+
/** Something a dependency built, or a name from a module this run never read. */
|
|
41
|
+
| {
|
|
42
|
+
readonly kind: "outsideRun";
|
|
43
|
+
}
|
|
44
|
+
/** Built in this run by something the rules could not follow through. */
|
|
45
|
+
| {
|
|
46
|
+
readonly kind: "unsettled";
|
|
47
|
+
}
|
|
48
|
+
/** Nothing in this run says anything about it. */
|
|
49
|
+
| {
|
|
50
|
+
readonly kind: "undeclared";
|
|
51
|
+
};
|
|
52
|
+
/**
|
|
53
|
+
* What each of these callees is. One batch, so evaluation runs per wave
|
|
54
|
+
* rather than per callee. A language whose adapter states rules of its
|
|
55
|
+
* own passes the program those rules were built into, so this runs over
|
|
56
|
+
* the same evaluation state the rest of that run uses.
|
|
57
|
+
*/
|
|
58
|
+
declare function calleeOutcomes(db: Database, keys: readonly string[], program?: OnDemandRules): Map<string, CalleeOutcome>;
|
|
59
|
+
/** What one callee is, for a caller with a single key in hand. */
|
|
60
|
+
declare function calleeOutcomeOf(db: Database, key: string, program?: OnDemandRules): CalleeOutcome;
|
|
61
|
+
/**
|
|
62
|
+
* Whether this run says anything at all about the key: it is a value
|
|
63
|
+
* itself, or something built it. A key that fails this settles on
|
|
64
|
+
* nothing, and asking anyway adds a `wanted` fact that every later
|
|
65
|
+
* question has to derive over, so a caller with a batch of keys and a
|
|
66
|
+
* cheap question about each one puts this in front of the batch.
|
|
67
|
+
*/
|
|
68
|
+
declare function couldBeSettled(db: Database, key: string): boolean;
|
|
69
|
+
declare function writtenSourcesOf(db: Database, key: string): string[];
|
|
3
70
|
|
|
4
71
|
/** The tuples of one relation, as strings, which is all a case compares. */
|
|
5
72
|
type FactsOf = (relation: string) => string[][];
|
|
@@ -148,6 +215,84 @@ declare function mountPathsOf(edges: MountEdges, childId: string): readonly stri
|
|
|
148
215
|
*/
|
|
149
216
|
declare function agreedMountPrefix(edges: MountEdges, childId: string): string | null;
|
|
150
217
|
|
|
218
|
+
/**
|
|
219
|
+
* Where a name is read, over whatever parse tree an adapter hands in.
|
|
220
|
+
*
|
|
221
|
+
* `valueLeftByWrites` needs to know whether a name's writes run once each
|
|
222
|
+
* in source order, and that answer comes from the tree: every write has to
|
|
223
|
+
* be a statement of the scope's own list, and nothing before the last of
|
|
224
|
+
* them may read the name. The walk is the same in every language, so it
|
|
225
|
+
* lives here and each adapter passes a description of its grammar.
|
|
226
|
+
*
|
|
227
|
+
* A description says four things: which node types spell a name, which
|
|
228
|
+
* of them open a body that runs later, how to enumerate a node's
|
|
229
|
+
* children, and which spellings of a name are reads rather than writes or
|
|
230
|
+
* declarations. Nothing here touches a parser.
|
|
231
|
+
*/
|
|
232
|
+
/** The parts of a parse-tree node these walks read. */
|
|
233
|
+
interface ReadNode {
|
|
234
|
+
readonly type: string;
|
|
235
|
+
readonly text: string;
|
|
236
|
+
readonly startIndex: number;
|
|
237
|
+
}
|
|
238
|
+
/** What one language says about finding reads of a name in its trees. */
|
|
239
|
+
interface NameReads<N extends ReadNode> {
|
|
240
|
+
/** The node types a name is spelled with. Ruby has two, one of them `@name`. */
|
|
241
|
+
nameTypes: ReadonlySet<string>;
|
|
242
|
+
/**
|
|
243
|
+
* The types that open a body running later than the statements around
|
|
244
|
+
* it, so a function, a class, or a Ruby block. A read in there happens
|
|
245
|
+
* when something calls or enters the body, not where it is written.
|
|
246
|
+
*/
|
|
247
|
+
laterBodies: ReadonlySet<string>;
|
|
248
|
+
/** A node's children, in source order. */
|
|
249
|
+
childrenOf: (node: N) => N[];
|
|
250
|
+
/**
|
|
251
|
+
* Whether a node spelling the name reads it, rather than being written
|
|
252
|
+
* to, declared, or spelled as somebody else's member.
|
|
253
|
+
*/
|
|
254
|
+
isRead: (node: N) => boolean;
|
|
255
|
+
}
|
|
256
|
+
/** What one language says about which part of a chained expression is read first. */
|
|
257
|
+
interface ChainReads<N extends ReadNode> {
|
|
258
|
+
/** The node types a name is spelled with. Ruby has two, one of them `@name`. */
|
|
259
|
+
nameTypes: ReadonlySet<string>;
|
|
260
|
+
/**
|
|
261
|
+
* The part of an expression read before the rest of it, so a call's
|
|
262
|
+
* callee or a member read's object, or null when nothing is read before
|
|
263
|
+
* this node.
|
|
264
|
+
*/
|
|
265
|
+
readFirst: (node: N) => N | null;
|
|
266
|
+
}
|
|
267
|
+
/** One write to a name, in the order it is written. */
|
|
268
|
+
interface OrderedWrite<N extends ReadNode> {
|
|
269
|
+
/** The node whose position orders this write among the scope's others. */
|
|
270
|
+
at: N;
|
|
271
|
+
/** Whether the write is a statement of the scope's own statement list. */
|
|
272
|
+
direct: boolean;
|
|
273
|
+
}
|
|
274
|
+
/**
|
|
275
|
+
* Whether the writes run once each, in the order they are written.
|
|
276
|
+
*
|
|
277
|
+
* They do when every one of them is a statement of the scope's own list.
|
|
278
|
+
* That list runs through once, top to bottom: nothing repeats and nothing
|
|
279
|
+
* is skipped. A write inside a branch, a loop, a block or a nested
|
|
280
|
+
* definition runs when something reaches it, and how many times is not a
|
|
281
|
+
* question this reads.
|
|
282
|
+
*
|
|
283
|
+
* The last write also has to be the one every read sees, so a read before
|
|
284
|
+
* it makes the answer depend on where the reader is, which the rules
|
|
285
|
+
* cannot express.
|
|
286
|
+
*/
|
|
287
|
+
declare function writesRunInOrder<N extends ReadNode>(scope: N | null, name: string, writes: readonly OrderedWrite<N>[], rules: NameReads<N>): boolean;
|
|
288
|
+
/**
|
|
289
|
+
* Whether reading this expression starts by reading `name`, through
|
|
290
|
+
* however many calls, member reads and parentheses. That is what makes
|
|
291
|
+
* `query = query.filter(x)` a write narrowing what the other writes gave
|
|
292
|
+
* the name rather than one replacing it.
|
|
293
|
+
*/
|
|
294
|
+
declare function startsAtName<N extends ReadNode>(node: N, name: string, rules: ChainReads<N>): boolean;
|
|
295
|
+
|
|
151
296
|
/**
|
|
152
297
|
* The tree-sitter adapters key a node by its file and byte span,
|
|
153
298
|
* `file:start-end`. This finds the node a key refers to again, for an
|
|
@@ -167,6 +312,52 @@ interface SpannedNode<N> {
|
|
|
167
312
|
*/
|
|
168
313
|
declare function nodeOfKey<N extends SpannedNode<N>>(rootsByFile: ReadonlyMap<string, N>, key: string): N | null;
|
|
169
314
|
|
|
315
|
+
/**
|
|
316
|
+
* The rules an adapter evaluates, and how a question is put to them.
|
|
317
|
+
*
|
|
318
|
+
* A demand-rewritten rule set is named by its shape, so two adapters
|
|
319
|
+
* that build the same array share one evaluation state and clearing
|
|
320
|
+
* under one of them resets the other. Every adapter builds its program
|
|
321
|
+
* here instead, and a language that states rules of its own gets one
|
|
322
|
+
* program of its own to pass around.
|
|
323
|
+
*/
|
|
324
|
+
|
|
325
|
+
/**
|
|
326
|
+
* The facts that say somebody is asking. Each seeds one family of
|
|
327
|
+
* questions, and none of them is derived, so these are what a caller
|
|
328
|
+
* adds and what it takes back once it has read the answer.
|
|
329
|
+
*/
|
|
330
|
+
declare const ASKING_RELATIONS: readonly string[];
|
|
331
|
+
/**
|
|
332
|
+
* The shared rules, whatever the language states of its own, and the
|
|
333
|
+
* questions, rewritten so a relation is derived only where a question
|
|
334
|
+
* reaches it. Built once per language and kept, because the rewrite
|
|
335
|
+
* does not depend on the facts.
|
|
336
|
+
*
|
|
337
|
+
* `SUSS_RESOLUTION_ON_DEMAND=0` runs the same rules unrestricted. Both
|
|
338
|
+
* settings give the same answers; they differ in how much never gets
|
|
339
|
+
* derived at all.
|
|
340
|
+
*/
|
|
341
|
+
declare function resolutionProgram(languageRules?: readonly Rule[]): OnDemandRules;
|
|
342
|
+
/**
|
|
343
|
+
* What a caller takes back once it has read an answer: the question and
|
|
344
|
+
* every relation derived under it. Empty when nothing is demand-driven,
|
|
345
|
+
* since then the answers themselves are what clearing would remove.
|
|
346
|
+
*/
|
|
347
|
+
declare function queryFacts(program: OnDemandRules): readonly string[];
|
|
348
|
+
/**
|
|
349
|
+
* Ask about these values, derive, and take the question back.
|
|
350
|
+
*
|
|
351
|
+
* Asking about everything in a project costs seconds on a large one and
|
|
352
|
+
* settles questions nobody has, so a caller lists the keys it needs. The
|
|
353
|
+
* answers stay in the database; the question and the chain that settled
|
|
354
|
+
* it go, so the next question does not derive over every question asked
|
|
355
|
+
* before it. What has already been asked is remembered, so asking twice
|
|
356
|
+
* costs nothing. That wants every fact in the database before the first
|
|
357
|
+
* question, which is how each adapter reads a project.
|
|
358
|
+
*/
|
|
359
|
+
declare function askResolution(db: Database, keys: Iterable<string>, asking?: string, program?: OnDemandRules): void;
|
|
360
|
+
|
|
170
361
|
/**
|
|
171
362
|
* The result shape a why session hands back, shared by every language
|
|
172
363
|
* adapter so the CLI reads one type regardless of which adapter
|
|
@@ -243,6 +434,55 @@ declare function singleAnswers(rows: Iterable<Tuple>, placeholders?: ReadonlySet
|
|
|
243
434
|
/** The keys an adapter marked `placeholderValue`, for passing to `singleAnswers`. */
|
|
244
435
|
declare function placeholderValues(db: Database): ReadonlySet<string>;
|
|
245
436
|
|
|
437
|
+
/**
|
|
438
|
+
* What a name written more than once comes down to.
|
|
439
|
+
*
|
|
440
|
+
* Each adapter reads writes out of a different parser, so the reading
|
|
441
|
+
* stays with the adapter and the decision lives here, over a
|
|
442
|
+
* description of the writes that nothing parser-shaped reaches. While
|
|
443
|
+
* each adapter decided for itself, the same source resolved in one
|
|
444
|
+
* language and not in another.
|
|
445
|
+
*
|
|
446
|
+
* Whether the writes run in order is a question about statement
|
|
447
|
+
* structure, and `writesRunInOrder` works that out beside this.
|
|
448
|
+
*/
|
|
449
|
+
/** One write to a name, in the order it is written. */
|
|
450
|
+
interface NameWrite {
|
|
451
|
+
/**
|
|
452
|
+
* The key of the value written, or null when the write states no
|
|
453
|
+
* value of its own, as `count += 1` and `index++` do.
|
|
454
|
+
*/
|
|
455
|
+
value: string | null;
|
|
456
|
+
/** Whether a later write is expected to replace this value: `null`, `undefined`, `None`, `nil`. */
|
|
457
|
+
placeholder: boolean;
|
|
458
|
+
/**
|
|
459
|
+
* The value's source text when it is built where it is written, so a
|
|
460
|
+
* call, a `new`, or an object or array literal. Null otherwise.
|
|
461
|
+
*/
|
|
462
|
+
construction: string | null;
|
|
463
|
+
/**
|
|
464
|
+
* Whether the value is a call on the name being written, `query =
|
|
465
|
+
* query.filter(x)`, which leaves the name what the other writes gave
|
|
466
|
+
* it with a method applied. A call returning something of another kind
|
|
467
|
+
* is not told apart, and a narrowing written through a second name,
|
|
468
|
+
* `tmp = query.limit(1)` then `query = tmp`, is not recognized.
|
|
469
|
+
*/
|
|
470
|
+
narrowsName: boolean;
|
|
471
|
+
}
|
|
472
|
+
/**
|
|
473
|
+
* The value a name comes down to, or null when the writes leave it
|
|
474
|
+
* undecided.
|
|
475
|
+
*
|
|
476
|
+
* With `ordered`, every write runs once in the order it is written and
|
|
477
|
+
* nothing reads the name in between, so the last write is what a reader
|
|
478
|
+
* sees. Otherwise the writes are candidates the caller cannot order,
|
|
479
|
+
* and they settle the name only when they all build the same thing.
|
|
480
|
+
*
|
|
481
|
+
* A write with no value of its own puts a hole in the sequence, and then
|
|
482
|
+
* no write can be called the last one. A narrowing write is set aside.
|
|
483
|
+
*/
|
|
484
|
+
declare function valueLeftByWrites(writes: readonly NameWrite[], ordered: boolean): string | null;
|
|
485
|
+
|
|
246
486
|
/**
|
|
247
487
|
* The single expression a value was written as, once the caller has
|
|
248
488
|
* asked the rules about `key`. A call to a project function is asked
|
|
@@ -299,4 +539,4 @@ declare const RESOLUTION_QUESTIONS: _suss_datalog.Rule[];
|
|
|
299
539
|
/** The relations `RESOLUTION_QUESTIONS` answers into. */
|
|
300
540
|
declare const ANSWER_RELATIONS: string[];
|
|
301
541
|
|
|
302
|
-
export { ANSWER_RELATIONS, type CaseFiles, type ContractCase, type ContractOptions, type DescribeAtom, type ExplainOptions, type ExplainResolvedKeyOptions, type ExplainStats, FACT_CONTRACT_CASES, type FactsOf, type MountEdge, type MountEdges, NAMESPACE_IMPORT, NAMESPACE_IMPORT_NAME, RESOLUTION_QUESTIONS, RESOLUTION_RULES, RESULT_STEP, type ResolutionExplanation, type ResolutionStep, type SpannedNode, type StepContext, type StepPhrase, VALUE_STEP, type ValueLocation, type WhyExplained, agreedMountPrefix, checkFactContract, explainResolutionProof, explainResolvedKey, joinMountedPath, mountPathsOf, nodeOfKey, placeholderValues, renderExplanation, singleAnswers, writtenValueOf };
|
|
542
|
+
export { ANSWER_RELATIONS, ASKING_RELATIONS, type CalleeOutcome, type CaseFiles, type ChainReads, type ContractCase, type ContractOptions, type DescribeAtom, type ExplainOptions, type ExplainResolvedKeyOptions, type ExplainStats, FACT_CONTRACT_CASES, type FactsOf, type MountEdge, type MountEdges, NAMESPACE_IMPORT, NAMESPACE_IMPORT_NAME, type NameReads, type NameWrite, type OrderedWrite, RESOLUTION_QUESTIONS, RESOLUTION_RULES, RESULT_STEP, type ReadNode, type ResolutionExplanation, type ResolutionStep, type SpannedNode, type StepContext, type StepPhrase, VALUE_STEP, type ValueLocation, type WhyExplained, agreedMountPrefix, askResolution, calleeOutcomeOf, calleeOutcomes, checkFactContract, couldBeSettled, explainResolutionProof, explainResolvedKey, joinMountedPath, mountPathsOf, nodeOfKey, placeholderValues, queryFacts, renderExplanation, resolutionProgram, singleAnswers, startsAtName, valueLeftByWrites, writesRunInOrder, writtenSourcesOf, writtenValueOf };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,72 @@
|
|
|
1
1
|
import * as _suss_datalog from '@suss/datalog';
|
|
2
|
-
import { Database, Atom, Tuple, Proof, Rule } from '@suss/datalog';
|
|
2
|
+
import { Database, OnDemandRules, Atom, Tuple, Proof, Rule } from '@suss/datalog';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* What a call's callee is, and when the rules settle on nothing, why.
|
|
6
|
+
*
|
|
7
|
+
* `resolves` comes back with a function and stays quiet otherwise, and a
|
|
8
|
+
* caller recording a gap needs the quiet cases told apart: a method on
|
|
9
|
+
* what a caller passed in is a different stop from a method on a value
|
|
10
|
+
* this run never read. So when the rules settle nothing, this walks down
|
|
11
|
+
* the facts the value was built from, one construct at a time, until it
|
|
12
|
+
* meets something that says where the value came from.
|
|
13
|
+
*
|
|
14
|
+
* Both halves are here because every language emits the same facts and
|
|
15
|
+
* meets the same stops. The words for an outcome stay with a language.
|
|
16
|
+
*/
|
|
17
|
+
|
|
18
|
+
/** What a value a call is made through turns out to be. */
|
|
19
|
+
type CalleeOutcome =
|
|
20
|
+
/** One function in this run. */
|
|
21
|
+
{
|
|
22
|
+
readonly kind: "function";
|
|
23
|
+
readonly key: string;
|
|
24
|
+
}
|
|
25
|
+
/** One object in this run, which is a class where a language writes classes as objects. */
|
|
26
|
+
| {
|
|
27
|
+
readonly kind: "object";
|
|
28
|
+
readonly key: string;
|
|
29
|
+
}
|
|
30
|
+
/** More than one, so no single answer, and `sources` tells them apart. */
|
|
31
|
+
| {
|
|
32
|
+
readonly kind: "severalSources";
|
|
33
|
+
readonly sources: readonly string[];
|
|
34
|
+
}
|
|
35
|
+
/** A parameter, whose key is here so a caller can say whose parameter it is. */
|
|
36
|
+
| {
|
|
37
|
+
readonly kind: "callerSupplied";
|
|
38
|
+
readonly key: string;
|
|
39
|
+
}
|
|
40
|
+
/** Something a dependency built, or a name from a module this run never read. */
|
|
41
|
+
| {
|
|
42
|
+
readonly kind: "outsideRun";
|
|
43
|
+
}
|
|
44
|
+
/** Built in this run by something the rules could not follow through. */
|
|
45
|
+
| {
|
|
46
|
+
readonly kind: "unsettled";
|
|
47
|
+
}
|
|
48
|
+
/** Nothing in this run says anything about it. */
|
|
49
|
+
| {
|
|
50
|
+
readonly kind: "undeclared";
|
|
51
|
+
};
|
|
52
|
+
/**
|
|
53
|
+
* What each of these callees is. One batch, so evaluation runs per wave
|
|
54
|
+
* rather than per callee. A language whose adapter states rules of its
|
|
55
|
+
* own passes the program those rules were built into, so this runs over
|
|
56
|
+
* the same evaluation state the rest of that run uses.
|
|
57
|
+
*/
|
|
58
|
+
declare function calleeOutcomes(db: Database, keys: readonly string[], program?: OnDemandRules): Map<string, CalleeOutcome>;
|
|
59
|
+
/** What one callee is, for a caller with a single key in hand. */
|
|
60
|
+
declare function calleeOutcomeOf(db: Database, key: string, program?: OnDemandRules): CalleeOutcome;
|
|
61
|
+
/**
|
|
62
|
+
* Whether this run says anything at all about the key: it is a value
|
|
63
|
+
* itself, or something built it. A key that fails this settles on
|
|
64
|
+
* nothing, and asking anyway adds a `wanted` fact that every later
|
|
65
|
+
* question has to derive over, so a caller with a batch of keys and a
|
|
66
|
+
* cheap question about each one puts this in front of the batch.
|
|
67
|
+
*/
|
|
68
|
+
declare function couldBeSettled(db: Database, key: string): boolean;
|
|
69
|
+
declare function writtenSourcesOf(db: Database, key: string): string[];
|
|
3
70
|
|
|
4
71
|
/** The tuples of one relation, as strings, which is all a case compares. */
|
|
5
72
|
type FactsOf = (relation: string) => string[][];
|
|
@@ -148,6 +215,84 @@ declare function mountPathsOf(edges: MountEdges, childId: string): readonly stri
|
|
|
148
215
|
*/
|
|
149
216
|
declare function agreedMountPrefix(edges: MountEdges, childId: string): string | null;
|
|
150
217
|
|
|
218
|
+
/**
|
|
219
|
+
* Where a name is read, over whatever parse tree an adapter hands in.
|
|
220
|
+
*
|
|
221
|
+
* `valueLeftByWrites` needs to know whether a name's writes run once each
|
|
222
|
+
* in source order, and that answer comes from the tree: every write has to
|
|
223
|
+
* be a statement of the scope's own list, and nothing before the last of
|
|
224
|
+
* them may read the name. The walk is the same in every language, so it
|
|
225
|
+
* lives here and each adapter passes a description of its grammar.
|
|
226
|
+
*
|
|
227
|
+
* A description says four things: which node types spell a name, which
|
|
228
|
+
* of them open a body that runs later, how to enumerate a node's
|
|
229
|
+
* children, and which spellings of a name are reads rather than writes or
|
|
230
|
+
* declarations. Nothing here touches a parser.
|
|
231
|
+
*/
|
|
232
|
+
/** The parts of a parse-tree node these walks read. */
|
|
233
|
+
interface ReadNode {
|
|
234
|
+
readonly type: string;
|
|
235
|
+
readonly text: string;
|
|
236
|
+
readonly startIndex: number;
|
|
237
|
+
}
|
|
238
|
+
/** What one language says about finding reads of a name in its trees. */
|
|
239
|
+
interface NameReads<N extends ReadNode> {
|
|
240
|
+
/** The node types a name is spelled with. Ruby has two, one of them `@name`. */
|
|
241
|
+
nameTypes: ReadonlySet<string>;
|
|
242
|
+
/**
|
|
243
|
+
* The types that open a body running later than the statements around
|
|
244
|
+
* it, so a function, a class, or a Ruby block. A read in there happens
|
|
245
|
+
* when something calls or enters the body, not where it is written.
|
|
246
|
+
*/
|
|
247
|
+
laterBodies: ReadonlySet<string>;
|
|
248
|
+
/** A node's children, in source order. */
|
|
249
|
+
childrenOf: (node: N) => N[];
|
|
250
|
+
/**
|
|
251
|
+
* Whether a node spelling the name reads it, rather than being written
|
|
252
|
+
* to, declared, or spelled as somebody else's member.
|
|
253
|
+
*/
|
|
254
|
+
isRead: (node: N) => boolean;
|
|
255
|
+
}
|
|
256
|
+
/** What one language says about which part of a chained expression is read first. */
|
|
257
|
+
interface ChainReads<N extends ReadNode> {
|
|
258
|
+
/** The node types a name is spelled with. Ruby has two, one of them `@name`. */
|
|
259
|
+
nameTypes: ReadonlySet<string>;
|
|
260
|
+
/**
|
|
261
|
+
* The part of an expression read before the rest of it, so a call's
|
|
262
|
+
* callee or a member read's object, or null when nothing is read before
|
|
263
|
+
* this node.
|
|
264
|
+
*/
|
|
265
|
+
readFirst: (node: N) => N | null;
|
|
266
|
+
}
|
|
267
|
+
/** One write to a name, in the order it is written. */
|
|
268
|
+
interface OrderedWrite<N extends ReadNode> {
|
|
269
|
+
/** The node whose position orders this write among the scope's others. */
|
|
270
|
+
at: N;
|
|
271
|
+
/** Whether the write is a statement of the scope's own statement list. */
|
|
272
|
+
direct: boolean;
|
|
273
|
+
}
|
|
274
|
+
/**
|
|
275
|
+
* Whether the writes run once each, in the order they are written.
|
|
276
|
+
*
|
|
277
|
+
* They do when every one of them is a statement of the scope's own list.
|
|
278
|
+
* That list runs through once, top to bottom: nothing repeats and nothing
|
|
279
|
+
* is skipped. A write inside a branch, a loop, a block or a nested
|
|
280
|
+
* definition runs when something reaches it, and how many times is not a
|
|
281
|
+
* question this reads.
|
|
282
|
+
*
|
|
283
|
+
* The last write also has to be the one every read sees, so a read before
|
|
284
|
+
* it makes the answer depend on where the reader is, which the rules
|
|
285
|
+
* cannot express.
|
|
286
|
+
*/
|
|
287
|
+
declare function writesRunInOrder<N extends ReadNode>(scope: N | null, name: string, writes: readonly OrderedWrite<N>[], rules: NameReads<N>): boolean;
|
|
288
|
+
/**
|
|
289
|
+
* Whether reading this expression starts by reading `name`, through
|
|
290
|
+
* however many calls, member reads and parentheses. That is what makes
|
|
291
|
+
* `query = query.filter(x)` a write narrowing what the other writes gave
|
|
292
|
+
* the name rather than one replacing it.
|
|
293
|
+
*/
|
|
294
|
+
declare function startsAtName<N extends ReadNode>(node: N, name: string, rules: ChainReads<N>): boolean;
|
|
295
|
+
|
|
151
296
|
/**
|
|
152
297
|
* The tree-sitter adapters key a node by its file and byte span,
|
|
153
298
|
* `file:start-end`. This finds the node a key refers to again, for an
|
|
@@ -167,6 +312,52 @@ interface SpannedNode<N> {
|
|
|
167
312
|
*/
|
|
168
313
|
declare function nodeOfKey<N extends SpannedNode<N>>(rootsByFile: ReadonlyMap<string, N>, key: string): N | null;
|
|
169
314
|
|
|
315
|
+
/**
|
|
316
|
+
* The rules an adapter evaluates, and how a question is put to them.
|
|
317
|
+
*
|
|
318
|
+
* A demand-rewritten rule set is named by its shape, so two adapters
|
|
319
|
+
* that build the same array share one evaluation state and clearing
|
|
320
|
+
* under one of them resets the other. Every adapter builds its program
|
|
321
|
+
* here instead, and a language that states rules of its own gets one
|
|
322
|
+
* program of its own to pass around.
|
|
323
|
+
*/
|
|
324
|
+
|
|
325
|
+
/**
|
|
326
|
+
* The facts that say somebody is asking. Each seeds one family of
|
|
327
|
+
* questions, and none of them is derived, so these are what a caller
|
|
328
|
+
* adds and what it takes back once it has read the answer.
|
|
329
|
+
*/
|
|
330
|
+
declare const ASKING_RELATIONS: readonly string[];
|
|
331
|
+
/**
|
|
332
|
+
* The shared rules, whatever the language states of its own, and the
|
|
333
|
+
* questions, rewritten so a relation is derived only where a question
|
|
334
|
+
* reaches it. Built once per language and kept, because the rewrite
|
|
335
|
+
* does not depend on the facts.
|
|
336
|
+
*
|
|
337
|
+
* `SUSS_RESOLUTION_ON_DEMAND=0` runs the same rules unrestricted. Both
|
|
338
|
+
* settings give the same answers; they differ in how much never gets
|
|
339
|
+
* derived at all.
|
|
340
|
+
*/
|
|
341
|
+
declare function resolutionProgram(languageRules?: readonly Rule[]): OnDemandRules;
|
|
342
|
+
/**
|
|
343
|
+
* What a caller takes back once it has read an answer: the question and
|
|
344
|
+
* every relation derived under it. Empty when nothing is demand-driven,
|
|
345
|
+
* since then the answers themselves are what clearing would remove.
|
|
346
|
+
*/
|
|
347
|
+
declare function queryFacts(program: OnDemandRules): readonly string[];
|
|
348
|
+
/**
|
|
349
|
+
* Ask about these values, derive, and take the question back.
|
|
350
|
+
*
|
|
351
|
+
* Asking about everything in a project costs seconds on a large one and
|
|
352
|
+
* settles questions nobody has, so a caller lists the keys it needs. The
|
|
353
|
+
* answers stay in the database; the question and the chain that settled
|
|
354
|
+
* it go, so the next question does not derive over every question asked
|
|
355
|
+
* before it. What has already been asked is remembered, so asking twice
|
|
356
|
+
* costs nothing. That wants every fact in the database before the first
|
|
357
|
+
* question, which is how each adapter reads a project.
|
|
358
|
+
*/
|
|
359
|
+
declare function askResolution(db: Database, keys: Iterable<string>, asking?: string, program?: OnDemandRules): void;
|
|
360
|
+
|
|
170
361
|
/**
|
|
171
362
|
* The result shape a why session hands back, shared by every language
|
|
172
363
|
* adapter so the CLI reads one type regardless of which adapter
|
|
@@ -243,6 +434,55 @@ declare function singleAnswers(rows: Iterable<Tuple>, placeholders?: ReadonlySet
|
|
|
243
434
|
/** The keys an adapter marked `placeholderValue`, for passing to `singleAnswers`. */
|
|
244
435
|
declare function placeholderValues(db: Database): ReadonlySet<string>;
|
|
245
436
|
|
|
437
|
+
/**
|
|
438
|
+
* What a name written more than once comes down to.
|
|
439
|
+
*
|
|
440
|
+
* Each adapter reads writes out of a different parser, so the reading
|
|
441
|
+
* stays with the adapter and the decision lives here, over a
|
|
442
|
+
* description of the writes that nothing parser-shaped reaches. While
|
|
443
|
+
* each adapter decided for itself, the same source resolved in one
|
|
444
|
+
* language and not in another.
|
|
445
|
+
*
|
|
446
|
+
* Whether the writes run in order is a question about statement
|
|
447
|
+
* structure, and `writesRunInOrder` works that out beside this.
|
|
448
|
+
*/
|
|
449
|
+
/** One write to a name, in the order it is written. */
|
|
450
|
+
interface NameWrite {
|
|
451
|
+
/**
|
|
452
|
+
* The key of the value written, or null when the write states no
|
|
453
|
+
* value of its own, as `count += 1` and `index++` do.
|
|
454
|
+
*/
|
|
455
|
+
value: string | null;
|
|
456
|
+
/** Whether a later write is expected to replace this value: `null`, `undefined`, `None`, `nil`. */
|
|
457
|
+
placeholder: boolean;
|
|
458
|
+
/**
|
|
459
|
+
* The value's source text when it is built where it is written, so a
|
|
460
|
+
* call, a `new`, or an object or array literal. Null otherwise.
|
|
461
|
+
*/
|
|
462
|
+
construction: string | null;
|
|
463
|
+
/**
|
|
464
|
+
* Whether the value is a call on the name being written, `query =
|
|
465
|
+
* query.filter(x)`, which leaves the name what the other writes gave
|
|
466
|
+
* it with a method applied. A call returning something of another kind
|
|
467
|
+
* is not told apart, and a narrowing written through a second name,
|
|
468
|
+
* `tmp = query.limit(1)` then `query = tmp`, is not recognized.
|
|
469
|
+
*/
|
|
470
|
+
narrowsName: boolean;
|
|
471
|
+
}
|
|
472
|
+
/**
|
|
473
|
+
* The value a name comes down to, or null when the writes leave it
|
|
474
|
+
* undecided.
|
|
475
|
+
*
|
|
476
|
+
* With `ordered`, every write runs once in the order it is written and
|
|
477
|
+
* nothing reads the name in between, so the last write is what a reader
|
|
478
|
+
* sees. Otherwise the writes are candidates the caller cannot order,
|
|
479
|
+
* and they settle the name only when they all build the same thing.
|
|
480
|
+
*
|
|
481
|
+
* A write with no value of its own puts a hole in the sequence, and then
|
|
482
|
+
* no write can be called the last one. A narrowing write is set aside.
|
|
483
|
+
*/
|
|
484
|
+
declare function valueLeftByWrites(writes: readonly NameWrite[], ordered: boolean): string | null;
|
|
485
|
+
|
|
246
486
|
/**
|
|
247
487
|
* The single expression a value was written as, once the caller has
|
|
248
488
|
* asked the rules about `key`. A call to a project function is asked
|
|
@@ -299,4 +539,4 @@ declare const RESOLUTION_QUESTIONS: _suss_datalog.Rule[];
|
|
|
299
539
|
/** The relations `RESOLUTION_QUESTIONS` answers into. */
|
|
300
540
|
declare const ANSWER_RELATIONS: string[];
|
|
301
541
|
|
|
302
|
-
export { ANSWER_RELATIONS, type CaseFiles, type ContractCase, type ContractOptions, type DescribeAtom, type ExplainOptions, type ExplainResolvedKeyOptions, type ExplainStats, FACT_CONTRACT_CASES, type FactsOf, type MountEdge, type MountEdges, NAMESPACE_IMPORT, NAMESPACE_IMPORT_NAME, RESOLUTION_QUESTIONS, RESOLUTION_RULES, RESULT_STEP, type ResolutionExplanation, type ResolutionStep, type SpannedNode, type StepContext, type StepPhrase, VALUE_STEP, type ValueLocation, type WhyExplained, agreedMountPrefix, checkFactContract, explainResolutionProof, explainResolvedKey, joinMountedPath, mountPathsOf, nodeOfKey, placeholderValues, renderExplanation, singleAnswers, writtenValueOf };
|
|
542
|
+
export { ANSWER_RELATIONS, ASKING_RELATIONS, type CalleeOutcome, type CaseFiles, type ChainReads, type ContractCase, type ContractOptions, type DescribeAtom, type ExplainOptions, type ExplainResolvedKeyOptions, type ExplainStats, FACT_CONTRACT_CASES, type FactsOf, type MountEdge, type MountEdges, NAMESPACE_IMPORT, NAMESPACE_IMPORT_NAME, type NameReads, type NameWrite, type OrderedWrite, RESOLUTION_QUESTIONS, RESOLUTION_RULES, RESULT_STEP, type ReadNode, type ResolutionExplanation, type ResolutionStep, type SpannedNode, type StepContext, type StepPhrase, VALUE_STEP, type ValueLocation, type WhyExplained, agreedMountPrefix, askResolution, calleeOutcomeOf, calleeOutcomes, checkFactContract, couldBeSettled, explainResolutionProof, explainResolvedKey, joinMountedPath, mountPathsOf, nodeOfKey, placeholderValues, queryFacts, renderExplanation, resolutionProgram, singleAnswers, startsAtName, valueLeftByWrites, writesRunInOrder, writtenSourcesOf, writtenValueOf };
|