@suss/resolution 0.28.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/dist/index.cjs CHANGED
@@ -34,6 +34,7 @@ __export(index_exports, {
34
34
  calleeOutcomeOf: () => calleeOutcomeOf,
35
35
  calleeOutcomes: () => calleeOutcomes,
36
36
  checkFactContract: () => checkFactContract,
37
+ couldBeSettled: () => couldBeSettled,
37
38
  explainResolutionProof: () => explainResolutionProof,
38
39
  explainResolvedKey: () => explainResolvedKey,
39
40
  joinMountedPath: () => joinMountedPath,
@@ -152,6 +153,9 @@ function askAboutSources(db, keys, program) {
152
153
  wave = next;
153
154
  }
154
155
  }
156
+ function couldBeSettled(db, key) {
157
+ return db.has("func", [key]) || db.has("objectValue", [key]) || sourcesOf(db, key).length > 0;
158
+ }
155
159
  function sourcesOf(db, key) {
156
160
  const base = db.lookup("readsProperty", 0, key)[0];
157
161
  if (base !== void 0) {
@@ -584,6 +588,38 @@ var DEFAULT_PHRASES = {
584
588
  ]
585
589
  };
586
590
  },
591
+ "declared finder": ({ tuple, premises, describe }) => {
592
+ const method = String(premises[1].tuple[2]);
593
+ const base = String(premises[4].tuple[0]);
594
+ return {
595
+ reason: `${describe(tuple[0])} calls ${method} on ${describe(tuple[1])}, which gives back one of it`,
596
+ assumptions: [
597
+ `a pack declares that ${method} on a class extending ${base} gives back one of that class`
598
+ ]
599
+ };
600
+ },
601
+ "declared argument finder": ({ tuple, premises, describe }) => {
602
+ const method = String(premises[1].tuple[2]);
603
+ const position = String(premises[2].tuple[1]);
604
+ const base = String(premises[3].tuple[0]);
605
+ return {
606
+ reason: `${describe(tuple[0])} calls ${method} with ${describe(tuple[1])} at argument ${position}, which gives back one of it`,
607
+ assumptions: [
608
+ `a pack declares that ${method} with a class extending ${base} at argument ${position} gives back one of that class`
609
+ ]
610
+ };
611
+ },
612
+ "declared import finder": ({ tuple, premises, describe }) => {
613
+ const module2 = String(premises[1].tuple[1]);
614
+ const name = String(premises[1].tuple[2]);
615
+ const position = String(premises[2].tuple[2]);
616
+ return {
617
+ reason: `${describe(tuple[0])} calls ${name} from ${module2} with ${describe(tuple[1])} at argument ${position}, which gives back one of it`,
618
+ assumptions: [
619
+ `a pack declares that ${name} from ${module2} gives back one of the class at argument ${position}`
620
+ ]
621
+ };
622
+ },
587
623
  "call result": ({ tuple, premises, describe, inline }) => {
588
624
  const invokes = premises[0];
589
625
  const invoked = invokes.tuple[1];
@@ -1070,6 +1106,57 @@ var RESOLUTION_RULES = [
1070
1106
  ],
1071
1107
  "class instance"
1072
1108
  ),
1109
+ // A finder the library declares, keyed on the base a pack named so a
1110
+ // project class with a method of the same name on another hierarchy is
1111
+ // left alone. The DESIGN says what a chain of them composes into.
1112
+ (0, import_datalog4.rule)(
1113
+ "stepsTo",
1114
+ [(0, import_datalog4.variable)("r"), (0, import_datalog4.variable)("cls"), VALUE_STEP],
1115
+ [
1116
+ (0, import_datalog4.lit)("call", (0, import_datalog4.variable)("r"), (0, import_datalog4.variable)("c")),
1117
+ (0, import_datalog4.lit)("readsProperty", (0, import_datalog4.variable)("c"), (0, import_datalog4.variable)("o"), (0, import_datalog4.variable)("m")),
1118
+ (0, import_datalog4.lit)("objectOf", (0, import_datalog4.variable)("o"), (0, import_datalog4.variable)("cls")),
1119
+ (0, import_datalog4.lit)("objectValue", (0, import_datalog4.variable)("cls")),
1120
+ // Before `libraryBase`, so the demand rewrite asks it with the base
1121
+ // bound and walks an ancestry only for a method a pack declared.
1122
+ (0, import_datalog4.lit)("givesBackOne", (0, import_datalog4.variable)("n"), (0, import_datalog4.variable)("m")),
1123
+ (0, import_datalog4.lit)("libraryBase", (0, import_datalog4.variable)("cls"), (0, import_datalog4.variable)("n"))
1124
+ ],
1125
+ "declared finder"
1126
+ ),
1127
+ // The same word, for a library that takes the class as an argument
1128
+ // instead of as the receiver. The argument having to reach the base a
1129
+ // pack named is what keeps an unrelated `get` out.
1130
+ (0, import_datalog4.rule)(
1131
+ "stepsTo",
1132
+ [(0, import_datalog4.variable)("r"), (0, import_datalog4.variable)("cls"), VALUE_STEP],
1133
+ [
1134
+ (0, import_datalog4.lit)("call", (0, import_datalog4.variable)("r"), (0, import_datalog4.variable)("c")),
1135
+ (0, import_datalog4.lit)("readsProperty", (0, import_datalog4.variable)("c"), (0, import_datalog4.variable)("o"), (0, import_datalog4.variable)("m")),
1136
+ (0, import_datalog4.lit)("callArg", (0, import_datalog4.variable)("r"), (0, import_datalog4.variable)("k"), (0, import_datalog4.variable)("a")),
1137
+ // Before `libraryBase`, so the demand rewrite asks it with the base
1138
+ // bound and walks an ancestry only for a method a pack declared.
1139
+ (0, import_datalog4.lit)("givesBackOneOfArgument", (0, import_datalog4.variable)("n"), (0, import_datalog4.variable)("m"), (0, import_datalog4.variable)("k")),
1140
+ (0, import_datalog4.lit)("objectOf", (0, import_datalog4.variable)("a"), (0, import_datalog4.variable)("cls")),
1141
+ (0, import_datalog4.lit)("libraryBase", (0, import_datalog4.variable)("cls"), (0, import_datalog4.variable)("n"))
1142
+ ],
1143
+ "declared argument finder"
1144
+ ),
1145
+ // The same again for a function called on its own rather than read off
1146
+ // anything, keyed on the module it was imported from so a project
1147
+ // function spelled the same way is not mistaken for it.
1148
+ (0, import_datalog4.rule)(
1149
+ "stepsTo",
1150
+ [(0, import_datalog4.variable)("r"), (0, import_datalog4.variable)("cls"), VALUE_STEP],
1151
+ [
1152
+ (0, import_datalog4.lit)("call", (0, import_datalog4.variable)("r"), (0, import_datalog4.variable)("c")),
1153
+ (0, import_datalog4.lit)("comesFrom", (0, import_datalog4.variable)("c"), (0, import_datalog4.variable)("mod"), (0, import_datalog4.variable)("n")),
1154
+ (0, import_datalog4.lit)("givesBackOneOfImport", (0, import_datalog4.variable)("mod"), (0, import_datalog4.variable)("n"), (0, import_datalog4.variable)("k")),
1155
+ (0, import_datalog4.lit)("callArg", (0, import_datalog4.variable)("r"), (0, import_datalog4.variable)("k"), (0, import_datalog4.variable)("a")),
1156
+ (0, import_datalog4.lit)("objectOf", (0, import_datalog4.variable)("a"), (0, import_datalog4.variable)("cls"))
1157
+ ],
1158
+ "declared import finder"
1159
+ ),
1073
1160
  // Wrapper transparency, derived: calling a factory that returns a
1074
1161
  // function which calls its parameter k steps to argument k.
1075
1162
  (0, import_datalog4.rule)(
@@ -1343,6 +1430,32 @@ var RESOLUTION_RULES = [
1343
1430
  (0, import_datalog4.lit)("contains", (0, import_datalog4.variable)("baseCls"), (0, import_datalog4.variable)("n"), (0, import_datalog4.variable)("held"))
1344
1431
  ]
1345
1432
  ),
1433
+ // The library base a class's ancestry arrives at, however many of a
1434
+ // project's own classes sit in between. A base the run declares has a
1435
+ // node to keep walking from; one it does not has only a name.
1436
+ (0, import_datalog4.rule)("libraryBase", [(0, import_datalog4.variable)("c"), (0, import_datalog4.variable)("n")], [(0, import_datalog4.lit)("extendsNamed", (0, import_datalog4.variable)("c"), (0, import_datalog4.variable)("n"))]),
1437
+ (0, import_datalog4.rule)(
1438
+ "libraryBase",
1439
+ [(0, import_datalog4.variable)("c"), (0, import_datalog4.variable)("n")],
1440
+ [
1441
+ (0, import_datalog4.lit)("extends", (0, import_datalog4.variable)("c"), (0, import_datalog4.variable)("x")),
1442
+ (0, import_datalog4.lit)("comesTo", (0, import_datalog4.variable)("x"), (0, import_datalog4.variable)("b")),
1443
+ (0, import_datalog4.lit)("libraryBase", (0, import_datalog4.variable)("b"), (0, import_datalog4.variable)("n"))
1444
+ ]
1445
+ ),
1446
+ // A base a library hands back from a call rather than exporting as a
1447
+ // class, SQLAlchemy's `Base = declarative_base()`. The walk stops at
1448
+ // the call, so the function it called is the name to match on.
1449
+ (0, import_datalog4.rule)(
1450
+ "libraryBase",
1451
+ [(0, import_datalog4.variable)("c"), (0, import_datalog4.variable)("n")],
1452
+ [
1453
+ (0, import_datalog4.lit)("extends", (0, import_datalog4.variable)("c"), (0, import_datalog4.variable)("x")),
1454
+ (0, import_datalog4.lit)("isWrittenAs", (0, import_datalog4.variable)("x"), (0, import_datalog4.variable)("r")),
1455
+ (0, import_datalog4.lit)("call", (0, import_datalog4.variable)("r"), (0, import_datalog4.variable)("cc")),
1456
+ (0, import_datalog4.lit)("comesFrom", (0, import_datalog4.variable)("cc"), (0, import_datalog4.variable)("m"), (0, import_datalog4.variable)("n"))
1457
+ ]
1458
+ ),
1346
1459
  // Which function a factory returns, and which of its parameters that
1347
1460
  // function calls: together they are what makes it a wrapper.
1348
1461
  (0, import_datalog4.rule)(
@@ -1691,6 +1804,17 @@ var RESOLUTION_QUESTIONS = [
1691
1804
  [(0, import_datalog4.variable)("c"), (0, import_datalog4.variable)("n")],
1692
1805
  [(0, import_datalog4.lit)("ancestryChain", (0, import_datalog4.variable)("c"), (0, import_datalog4.variable)("b")), (0, import_datalog4.lit)("extendsNamed", (0, import_datalog4.variable)("b"), (0, import_datalog4.variable)("n"))]
1693
1806
  ),
1807
+ // Each method the same chain declares, so a caller that settled a
1808
+ // receiver on a class can tell a method the project writes itself
1809
+ // from one only the library provides.
1810
+ (0, import_datalog4.rule)(
1811
+ "wantedDeclaredName",
1812
+ [(0, import_datalog4.variable)("c"), (0, import_datalog4.variable)("n")],
1813
+ [
1814
+ (0, import_datalog4.lit)("ancestryChain", (0, import_datalog4.variable)("c"), (0, import_datalog4.variable)("b")),
1815
+ (0, import_datalog4.lit)("holdsProperty", (0, import_datalog4.variable)("b"), (0, import_datalog4.variable)("n"), (0, import_datalog4.variable)("held"))
1816
+ ]
1817
+ ),
1694
1818
  (0, import_datalog4.rule)("anchorChain", [(0, import_datalog4.variable)("x"), (0, import_datalog4.variable)("x")], [(0, import_datalog4.lit)("wantedAnchor", (0, import_datalog4.variable)("x"))]),
1695
1819
  (0, import_datalog4.rule)(
1696
1820
  "anchorChain",
@@ -1754,6 +1878,7 @@ var ANSWER_RELATIONS = [
1754
1878
  calleeOutcomeOf,
1755
1879
  calleeOutcomes,
1756
1880
  checkFactContract,
1881
+ couldBeSettled,
1757
1882
  explainResolutionProof,
1758
1883
  explainResolvedKey,
1759
1884
  joinMountedPath,
package/dist/index.d.cts CHANGED
@@ -58,6 +58,14 @@ type CalleeOutcome =
58
58
  declare function calleeOutcomes(db: Database, keys: readonly string[], program?: OnDemandRules): Map<string, CalleeOutcome>;
59
59
  /** What one callee is, for a caller with a single key in hand. */
60
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;
61
69
  declare function writtenSourcesOf(db: Database, key: string): string[];
62
70
 
63
71
  /** The tuples of one relation, as strings, which is all a case compares. */
@@ -531,4 +539,4 @@ declare const RESOLUTION_QUESTIONS: _suss_datalog.Rule[];
531
539
  /** The relations `RESOLUTION_QUESTIONS` answers into. */
532
540
  declare const ANSWER_RELATIONS: string[];
533
541
 
534
- 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, explainResolutionProof, explainResolvedKey, joinMountedPath, mountPathsOf, nodeOfKey, placeholderValues, queryFacts, renderExplanation, resolutionProgram, singleAnswers, startsAtName, valueLeftByWrites, writesRunInOrder, writtenSourcesOf, 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
@@ -58,6 +58,14 @@ type CalleeOutcome =
58
58
  declare function calleeOutcomes(db: Database, keys: readonly string[], program?: OnDemandRules): Map<string, CalleeOutcome>;
59
59
  /** What one callee is, for a caller with a single key in hand. */
60
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;
61
69
  declare function writtenSourcesOf(db: Database, key: string): string[];
62
70
 
63
71
  /** The tuples of one relation, as strings, which is all a case compares. */
@@ -531,4 +539,4 @@ declare const RESOLUTION_QUESTIONS: _suss_datalog.Rule[];
531
539
  /** The relations `RESOLUTION_QUESTIONS` answers into. */
532
540
  declare const ANSWER_RELATIONS: string[];
533
541
 
534
- 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, explainResolutionProof, explainResolvedKey, joinMountedPath, mountPathsOf, nodeOfKey, placeholderValues, queryFacts, renderExplanation, resolutionProgram, singleAnswers, startsAtName, valueLeftByWrites, writesRunInOrder, writtenSourcesOf, 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.js CHANGED
@@ -98,6 +98,9 @@ function askAboutSources(db, keys, program) {
98
98
  wave = next;
99
99
  }
100
100
  }
101
+ function couldBeSettled(db, key) {
102
+ return db.has("func", [key]) || db.has("objectValue", [key]) || sourcesOf(db, key).length > 0;
103
+ }
101
104
  function sourcesOf(db, key) {
102
105
  const base = db.lookup("readsProperty", 0, key)[0];
103
106
  if (base !== void 0) {
@@ -530,6 +533,38 @@ var DEFAULT_PHRASES = {
530
533
  ]
531
534
  };
532
535
  },
536
+ "declared finder": ({ tuple, premises, describe }) => {
537
+ const method = String(premises[1].tuple[2]);
538
+ const base = String(premises[4].tuple[0]);
539
+ return {
540
+ reason: `${describe(tuple[0])} calls ${method} on ${describe(tuple[1])}, which gives back one of it`,
541
+ assumptions: [
542
+ `a pack declares that ${method} on a class extending ${base} gives back one of that class`
543
+ ]
544
+ };
545
+ },
546
+ "declared argument finder": ({ tuple, premises, describe }) => {
547
+ const method = String(premises[1].tuple[2]);
548
+ const position = String(premises[2].tuple[1]);
549
+ const base = String(premises[3].tuple[0]);
550
+ return {
551
+ reason: `${describe(tuple[0])} calls ${method} with ${describe(tuple[1])} at argument ${position}, which gives back one of it`,
552
+ assumptions: [
553
+ `a pack declares that ${method} with a class extending ${base} at argument ${position} gives back one of that class`
554
+ ]
555
+ };
556
+ },
557
+ "declared import finder": ({ tuple, premises, describe }) => {
558
+ const module = String(premises[1].tuple[1]);
559
+ const name = String(premises[1].tuple[2]);
560
+ const position = String(premises[2].tuple[2]);
561
+ return {
562
+ reason: `${describe(tuple[0])} calls ${name} from ${module} with ${describe(tuple[1])} at argument ${position}, which gives back one of it`,
563
+ assumptions: [
564
+ `a pack declares that ${name} from ${module} gives back one of the class at argument ${position}`
565
+ ]
566
+ };
567
+ },
533
568
  "call result": ({ tuple, premises, describe, inline }) => {
534
569
  const invokes = premises[0];
535
570
  const invoked = invokes.tuple[1];
@@ -1016,6 +1051,57 @@ var RESOLUTION_RULES = [
1016
1051
  ],
1017
1052
  "class instance"
1018
1053
  ),
1054
+ // A finder the library declares, keyed on the base a pack named so a
1055
+ // project class with a method of the same name on another hierarchy is
1056
+ // left alone. The DESIGN says what a chain of them composes into.
1057
+ rule(
1058
+ "stepsTo",
1059
+ [v("r"), v("cls"), VALUE_STEP],
1060
+ [
1061
+ lit("call", v("r"), v("c")),
1062
+ lit("readsProperty", v("c"), v("o"), v("m")),
1063
+ lit("objectOf", v("o"), v("cls")),
1064
+ lit("objectValue", v("cls")),
1065
+ // Before `libraryBase`, so the demand rewrite asks it with the base
1066
+ // bound and walks an ancestry only for a method a pack declared.
1067
+ lit("givesBackOne", v("n"), v("m")),
1068
+ lit("libraryBase", v("cls"), v("n"))
1069
+ ],
1070
+ "declared finder"
1071
+ ),
1072
+ // The same word, for a library that takes the class as an argument
1073
+ // instead of as the receiver. The argument having to reach the base a
1074
+ // pack named is what keeps an unrelated `get` out.
1075
+ rule(
1076
+ "stepsTo",
1077
+ [v("r"), v("cls"), VALUE_STEP],
1078
+ [
1079
+ lit("call", v("r"), v("c")),
1080
+ lit("readsProperty", v("c"), v("o"), v("m")),
1081
+ lit("callArg", v("r"), v("k"), v("a")),
1082
+ // Before `libraryBase`, so the demand rewrite asks it with the base
1083
+ // bound and walks an ancestry only for a method a pack declared.
1084
+ lit("givesBackOneOfArgument", v("n"), v("m"), v("k")),
1085
+ lit("objectOf", v("a"), v("cls")),
1086
+ lit("libraryBase", v("cls"), v("n"))
1087
+ ],
1088
+ "declared argument finder"
1089
+ ),
1090
+ // The same again for a function called on its own rather than read off
1091
+ // anything, keyed on the module it was imported from so a project
1092
+ // function spelled the same way is not mistaken for it.
1093
+ rule(
1094
+ "stepsTo",
1095
+ [v("r"), v("cls"), VALUE_STEP],
1096
+ [
1097
+ lit("call", v("r"), v("c")),
1098
+ lit("comesFrom", v("c"), v("mod"), v("n")),
1099
+ lit("givesBackOneOfImport", v("mod"), v("n"), v("k")),
1100
+ lit("callArg", v("r"), v("k"), v("a")),
1101
+ lit("objectOf", v("a"), v("cls"))
1102
+ ],
1103
+ "declared import finder"
1104
+ ),
1019
1105
  // Wrapper transparency, derived: calling a factory that returns a
1020
1106
  // function which calls its parameter k steps to argument k.
1021
1107
  rule(
@@ -1289,6 +1375,32 @@ var RESOLUTION_RULES = [
1289
1375
  lit("contains", v("baseCls"), v("n"), v("held"))
1290
1376
  ]
1291
1377
  ),
1378
+ // The library base a class's ancestry arrives at, however many of a
1379
+ // project's own classes sit in between. A base the run declares has a
1380
+ // node to keep walking from; one it does not has only a name.
1381
+ rule("libraryBase", [v("c"), v("n")], [lit("extendsNamed", v("c"), v("n"))]),
1382
+ rule(
1383
+ "libraryBase",
1384
+ [v("c"), v("n")],
1385
+ [
1386
+ lit("extends", v("c"), v("x")),
1387
+ lit("comesTo", v("x"), v("b")),
1388
+ lit("libraryBase", v("b"), v("n"))
1389
+ ]
1390
+ ),
1391
+ // A base a library hands back from a call rather than exporting as a
1392
+ // class, SQLAlchemy's `Base = declarative_base()`. The walk stops at
1393
+ // the call, so the function it called is the name to match on.
1394
+ rule(
1395
+ "libraryBase",
1396
+ [v("c"), v("n")],
1397
+ [
1398
+ lit("extends", v("c"), v("x")),
1399
+ lit("isWrittenAs", v("x"), v("r")),
1400
+ lit("call", v("r"), v("cc")),
1401
+ lit("comesFrom", v("cc"), v("m"), v("n"))
1402
+ ]
1403
+ ),
1292
1404
  // Which function a factory returns, and which of its parameters that
1293
1405
  // function calls: together they are what makes it a wrapper.
1294
1406
  rule(
@@ -1637,6 +1749,17 @@ var RESOLUTION_QUESTIONS = [
1637
1749
  [v("c"), v("n")],
1638
1750
  [lit("ancestryChain", v("c"), v("b")), lit("extendsNamed", v("b"), v("n"))]
1639
1751
  ),
1752
+ // Each method the same chain declares, so a caller that settled a
1753
+ // receiver on a class can tell a method the project writes itself
1754
+ // from one only the library provides.
1755
+ rule(
1756
+ "wantedDeclaredName",
1757
+ [v("c"), v("n")],
1758
+ [
1759
+ lit("ancestryChain", v("c"), v("b")),
1760
+ lit("holdsProperty", v("b"), v("n"), v("held"))
1761
+ ]
1762
+ ),
1640
1763
  rule("anchorChain", [v("x"), v("x")], [lit("wantedAnchor", v("x"))]),
1641
1764
  rule(
1642
1765
  "anchorChain",
@@ -1699,6 +1822,7 @@ export {
1699
1822
  calleeOutcomeOf,
1700
1823
  calleeOutcomes,
1701
1824
  checkFactContract,
1825
+ couldBeSettled,
1702
1826
  explainResolutionProof,
1703
1827
  explainResolvedKey,
1704
1828
  joinMountedPath,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@suss/resolution",
3
- "version": "0.28.0",
3
+ "version": "0.29.0",
4
4
  "type": "module",
5
5
  "description": "The rules suss uses to follow a name in TypeScript, Python or Ruby to the function it comes down to.",
6
6
  "keywords": [
@@ -56,6 +56,6 @@
56
56
  "access": "public"
57
57
  },
58
58
  "dependencies": {
59
- "@suss/datalog": "0.28.0"
59
+ "@suss/datalog": "0.29.0"
60
60
  }
61
61
  }