tstyche 5.0.1 → 6.0.0-beta.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/build/index.cjs CHANGED
@@ -1,8 +1,8 @@
1
1
  'use strict';
2
2
 
3
- function doNothing() {
3
+ function noop() {
4
4
  }
5
- const noopChain = new Proxy(doNothing, {
5
+ const noopChain = new Proxy(noop, {
6
6
  apply() {
7
7
  return noopChain;
8
8
  },
@@ -14,7 +14,7 @@ const noopChain = new Proxy(doNothing, {
14
14
  exports.describe = noopChain;
15
15
  exports.expect = noopChain;
16
16
  exports.it = noopChain;
17
- exports.omit = doNothing;
18
- exports.pick = doNothing;
17
+ exports.omit = noop;
18
+ exports.pick = noop;
19
19
  exports.test = noopChain;
20
20
  exports.when = noopChain;
package/build/index.js CHANGED
@@ -1,6 +1,6 @@
1
- function doNothing() {
1
+ function noop() {
2
2
  }
3
- const noopChain = new Proxy(doNothing, {
3
+ const noopChain = new Proxy(noop, {
4
4
  apply() {
5
5
  return noopChain;
6
6
  },
@@ -9,4 +9,4 @@ const noopChain = new Proxy(doNothing, {
9
9
  },
10
10
  });
11
11
 
12
- export { noopChain as describe, noopChain as expect, noopChain as it, doNothing as omit, doNothing as pick, noopChain as test, noopChain as when };
12
+ export { noopChain as describe, noopChain as expect, noopChain as it, noop as omit, noop as pick, noopChain as test, noopChain as when };
@@ -158,6 +158,7 @@ interface ConfigFileOptions {
158
158
  checkSuppressedErrors?: boolean;
159
159
  failFast?: boolean;
160
160
  fixtureFileMatch?: Array<string>;
161
+ legacyToBe?: boolean;
161
162
  plugins?: Array<string>;
162
163
  rejectAnyType?: boolean;
163
164
  rejectNeverType?: boolean;
@@ -719,7 +720,9 @@ declare class Store {
719
720
  #private;
720
721
  static manifest: Manifest | undefined;
721
722
  static fetch(tag: string): Promise<void>;
722
- static load(tag: string): Promise<typeof ts | undefined>;
723
+ static load(tag: string, options?: {
724
+ notPatched?: boolean;
725
+ }): Promise<typeof ts | undefined>;
723
726
  static open(): Promise<void>;
724
727
  static prune(): Promise<void>;
725
728
  static update(): Promise<void>;
package/build/tstyche.js CHANGED
@@ -924,7 +924,7 @@ class Store {
924
924
  }
925
925
  await Store.#packageService.ensure(version, Store.manifest);
926
926
  }
927
- static async load(tag) {
927
+ static async load(tag, options) {
928
928
  let compilerInstance = Store.#compilerInstanceCache.get(tag);
929
929
  if (compilerInstance != null) {
930
930
  return compilerInstance;
@@ -950,24 +950,28 @@ class Store {
950
950
  }
951
951
  }
952
952
  if (modulePath != null) {
953
- compilerInstance = await Store.#loadModule(modulePath);
953
+ const packageConfigText = await fs.readFile(Path.resolve(modulePath, "../../package.json"), { encoding: "utf8" });
954
+ const { version: packageVersion } = JSON.parse(packageConfigText);
955
+ if (!Version.isSatisfiedWith(packageVersion, "5.3")) {
956
+ modulePath = Path.resolve(modulePath, "../tsserverlibrary.js");
957
+ }
958
+ if (options?.notPatched) {
959
+ const moduleSpecifier = pathToFileURL(modulePath).toString();
960
+ compilerInstance = (await import(moduleSpecifier)).default;
961
+ }
962
+ else {
963
+ compilerInstance = await Store.#loadPatchedModule(modulePath);
964
+ }
954
965
  Store.#compilerInstanceCache.set(tag, compilerInstance);
955
966
  Store.#compilerInstanceCache.set(compilerInstance.version, compilerInstance);
956
967
  }
957
968
  return compilerInstance;
958
969
  }
959
- static async #loadModule(modulePath) {
970
+ static async #loadPatchedModule(modulePath) {
971
+ const sourceText = await fs.readFile(modulePath, { encoding: "utf8" });
972
+ const compiledWrapper = vm.compileFunction(sourceText.replace("return checker;", "return { ...checker, isTypeIdenticalTo };"), ["exports", "require", "module", "__filename", "__dirname"], { filename: modulePath });
960
973
  const exports$1 = {};
961
974
  const module = { exports: exports$1 };
962
- const packageConfigText = await fs.readFile(Path.resolve(modulePath, "../../package.json"), { encoding: "utf8" });
963
- const { version: packageVersion } = JSON.parse(packageConfigText);
964
- if (!Version.isSatisfiedWith(packageVersion, "5.3")) {
965
- modulePath = Path.resolve(modulePath, "../tsserverlibrary.js");
966
- }
967
- const sourceText = await fs.readFile(modulePath, { encoding: "utf8" });
968
- const toExpose = ["isTypeIdenticalTo"];
969
- const modifiedSourceText = sourceText.replace("return checker;", `return { ...checker, ${toExpose.join(", ")} };`);
970
- const compiledWrapper = vm.compileFunction(modifiedSourceText, ["exports", "require", "module", "__filename", "__dirname"], { filename: modulePath });
971
975
  compiledWrapper(exports$1, createRequire(modulePath), module, modulePath, Path.dirname(modulePath));
972
976
  return module.exports;
973
977
  }
@@ -1103,6 +1107,12 @@ class Options {
1103
1107
  group: 2,
1104
1108
  name: "help",
1105
1109
  },
1110
+ {
1111
+ brand: "boolean",
1112
+ description: "Use the patch-based implementation of the '.toBe()' matcher.",
1113
+ group: 4,
1114
+ name: "legacyToBe",
1115
+ },
1106
1116
  {
1107
1117
  brand: "true",
1108
1118
  description: "Print the list of supported versions of the 'typescript' package and exit.",
@@ -1593,6 +1603,7 @@ const defaultOptions = {
1593
1603
  checkSuppressedErrors: true,
1594
1604
  failFast: false,
1595
1605
  fixtureFileMatch: ["**/__fixtures__/*.{ts,tsx}", "**/fixtures/*.{ts,tsx}"],
1606
+ legacyToBe: false,
1596
1607
  plugins: [],
1597
1608
  rejectAnyType: true,
1598
1609
  rejectNeverType: true,
@@ -3045,14 +3056,18 @@ class Select {
3045
3056
  const entries = await fs.readdir(targetPath, { withFileTypes: true });
3046
3057
  for (const entry of entries) {
3047
3058
  let entryMeta = entry;
3048
- if (entry.isSymbolicLink()) {
3049
- entryMeta = await fs.stat([targetPath, entry.name].join("/"));
3050
- }
3051
- if (entryMeta.isDirectory()) {
3052
- directories.push(entry.name);
3059
+ try {
3060
+ if (entry.isSymbolicLink()) {
3061
+ entryMeta = await fs.stat([targetPath, entry.name].join("/"));
3062
+ }
3063
+ if (entryMeta.isDirectory()) {
3064
+ directories.push(entry.name);
3065
+ }
3066
+ else if (entryMeta.isFile()) {
3067
+ files.push(entry.name);
3068
+ }
3053
3069
  }
3054
- else if (entryMeta.isFile()) {
3055
- files.push(entry.name);
3070
+ catch {
3056
3071
  }
3057
3072
  }
3058
3073
  }
@@ -4348,14 +4363,37 @@ class ExpectDiagnosticText {
4348
4363
  }
4349
4364
  }
4350
4365
 
4366
+ class RelationMatcherBase {
4367
+ explain(matchWorker, sourceNode, targetNode) {
4368
+ const sourceTypeText = matchWorker.getTypeText(sourceNode);
4369
+ const targetTypeText = matchWorker.getTypeText(targetNode);
4370
+ const text = matchWorker.assertionNode.isNot
4371
+ ? this.explainText(sourceTypeText, targetTypeText)
4372
+ : this.explainNotText(sourceTypeText, targetTypeText);
4373
+ const origin = DiagnosticOrigin.fromNode(targetNode, matchWorker.assertionNode);
4374
+ return [Diagnostic.error(text, origin)];
4375
+ }
4376
+ }
4377
+
4378
+ class LegacyToBe extends RelationMatcherBase {
4379
+ explainText = ExpectDiagnosticText.isTheSame;
4380
+ explainNotText = ExpectDiagnosticText.isNotTheSame;
4381
+ match(matchWorker, sourceNode, targetNode) {
4382
+ return {
4383
+ explain: () => this.explain(matchWorker, sourceNode, targetNode),
4384
+ isMatch: matchWorker.checkIsIdenticalTo(sourceNode, targetNode),
4385
+ };
4386
+ }
4387
+ }
4388
+
4351
4389
  class MatchWorker {
4352
4390
  assertionNode;
4353
4391
  #compiler;
4354
4392
  #signatureCache = new Map();
4355
4393
  typeChecker;
4356
- constructor(compiler, typeChecker, assertionNode) {
4394
+ constructor(compiler, program, assertionNode) {
4357
4395
  this.#compiler = compiler;
4358
- this.typeChecker = typeChecker;
4396
+ this.typeChecker = program.getTypeChecker();
4359
4397
  this.assertionNode = assertionNode;
4360
4398
  }
4361
4399
  checkIsAssignableTo(sourceNode, targetNode) {
@@ -4434,7 +4472,7 @@ class MatchWorker {
4434
4472
  function isStringOrNumberLiteralType(compiler, type) {
4435
4473
  return !!(type.flags & compiler.TypeFlags.StringOrNumberLiteral);
4436
4474
  }
4437
- function isUnionType(compiler, type) {
4475
+ function isUnionType$1(compiler, type) {
4438
4476
  return !!(type.flags & compiler.TypeFlags.Union);
4439
4477
  }
4440
4478
  function isUniqueSymbolType(compiler, type) {
@@ -4444,9 +4482,9 @@ function isUniqueSymbolType(compiler, type) {
4444
4482
  class ToAcceptProps {
4445
4483
  #compiler;
4446
4484
  #typeChecker;
4447
- constructor(compiler, typeChecker) {
4485
+ constructor(compiler, program) {
4448
4486
  this.#compiler = compiler;
4449
- this.#typeChecker = typeChecker;
4487
+ this.#typeChecker = program.getTypeChecker();
4450
4488
  }
4451
4489
  #explain(matchWorker, sourceNode, targetNode) {
4452
4490
  const isExpression = nodeBelongsToArgumentList(this.#compiler, sourceNode);
@@ -4503,7 +4541,7 @@ class ToAcceptProps {
4503
4541
  }
4504
4542
  return true;
4505
4543
  };
4506
- if (sourceType != null && isUnionType(this.#compiler, sourceType)) {
4544
+ if (sourceType != null && isUnionType$1(this.#compiler, sourceType)) {
4507
4545
  return sourceType.types.some((sourceType) => check(sourceType, targetType));
4508
4546
  }
4509
4547
  return check(sourceType, targetType);
@@ -4571,7 +4609,7 @@ class ToAcceptProps {
4571
4609
  }
4572
4610
  return { diagnostics, isMatch: false };
4573
4611
  };
4574
- if (sourceType != null && isUnionType(this.#compiler, sourceType)) {
4612
+ if (sourceType != null && isUnionType$1(this.#compiler, sourceType)) {
4575
4613
  let accumulator = [];
4576
4614
  const isMatch = sourceType.types.some((sourceType) => {
4577
4615
  const text = matchWorker.assertionNode.isNot
@@ -4625,25 +4663,460 @@ class ToAcceptProps {
4625
4663
  }
4626
4664
  }
4627
4665
 
4628
- class RelationMatcherBase {
4629
- explain(matchWorker, sourceNode, targetNode) {
4630
- const sourceTypeText = matchWorker.getTypeText(sourceNode);
4631
- const targetTypeText = matchWorker.getTypeText(targetNode);
4632
- const text = matchWorker.assertionNode.isNot
4633
- ? this.explainText(sourceTypeText, targetTypeText)
4634
- : this.explainNotText(sourceTypeText, targetTypeText);
4635
- const origin = DiagnosticOrigin.fromNode(targetNode, matchWorker.assertionNode);
4636
- return [Diagnostic.error(text, origin)];
4666
+ function ensureArray(input) {
4667
+ return input ?? [];
4668
+ }
4669
+ function length(array) {
4670
+ return array?.length ?? 0;
4671
+ }
4672
+
4673
+ function isClass(type, compiler) {
4674
+ return !!(type.objectFlags & compiler.ObjectFlags.Class);
4675
+ }
4676
+ function isConditionalType(type, compiler) {
4677
+ return !!(type.flags & compiler.TypeFlags.Conditional);
4678
+ }
4679
+ function isFreshLiteralType(type, compiler) {
4680
+ return !!(type.flags & compiler.TypeFlags.Freshable) && type.freshType === type;
4681
+ }
4682
+ function isIntersectionType(type, compiler) {
4683
+ return !!(type.flags & compiler.TypeFlags.Intersection);
4684
+ }
4685
+ function isNoInferType(type, compiler) {
4686
+ return !!(type.flags & compiler.TypeFlags.Substitution &&
4687
+ type.constraint.flags & compiler.TypeFlags.Unknown);
4688
+ }
4689
+ function isObjectType(type, compiler) {
4690
+ return !!(type.flags & compiler.TypeFlags.Object);
4691
+ }
4692
+ function isUnionType(type, compiler) {
4693
+ return !!(type.flags & compiler.TypeFlags.Union);
4694
+ }
4695
+ function isTupleType(type, compiler) {
4696
+ return !!(type.objectFlags & compiler.ObjectFlags.Tuple);
4697
+ }
4698
+ function isTupleTypeReference(type, compiler) {
4699
+ return isObjectType(type, compiler) && isTypeReference(type, compiler) && isTupleType(type.target, compiler);
4700
+ }
4701
+ function isTypeParameter(type, compiler) {
4702
+ return !!(type.flags & compiler.TypeFlags.TypeParameter);
4703
+ }
4704
+ function isTypeReference(type, compiler) {
4705
+ return !!(type.objectFlags & compiler.ObjectFlags.Reference);
4706
+ }
4707
+
4708
+ function getParameterFactsFromTuple(type, position, compiler) {
4709
+ return {
4710
+ isOptional: !!(type.target.elementFlags[position] & compiler.ElementFlags.Optional),
4711
+ isRest: !!(type.target.elementFlags[position] & compiler.ElementFlags.Rest),
4712
+ getType: (typeChecker) => typeChecker.getTypeArguments(type)[position],
4713
+ };
4714
+ }
4715
+ function getParameterFacts(signature, position, compiler, typeChecker) {
4716
+ if (position >= signature.parameters.length - 1 && compiler.hasRestParameter(signature.getDeclaration())) {
4717
+ const restType = typeChecker.getTypeOfSymbol(signature.parameters.at(-1));
4718
+ if (isTupleTypeReference(restType, compiler)) {
4719
+ const fixedLength = signature.parameters.length - 1;
4720
+ return getParameterFactsFromTuple(restType, position - fixedLength, compiler);
4721
+ }
4722
+ }
4723
+ const parameter = signature.parameters[position];
4724
+ const isRest = isRestParameter(parameter, compiler);
4725
+ return {
4726
+ isOptional: isOptionalParameter(parameter, compiler),
4727
+ isRest,
4728
+ getType: (typeChecker) => getParameterType(parameter, signature, isRest, compiler, typeChecker),
4729
+ };
4730
+ }
4731
+ function getParameterType(parameter, signature, isRest, compiler, typeChecker) {
4732
+ const type = typeChecker.getTypeOfSymbolAtLocation(parameter, signature.declaration);
4733
+ if (isRest && isObjectType(type, compiler) && isTypeReference(type, compiler)) {
4734
+ return typeChecker.getTypeArguments(type).at(0);
4735
+ }
4736
+ return type;
4737
+ }
4738
+ function getParameterCount(signature, compiler, typeChecker) {
4739
+ if (hasRestParameter(signature, compiler)) {
4740
+ const restType = typeChecker.getTypeOfSymbol(signature.parameters.at(-1));
4741
+ if (isTupleTypeReference(restType, compiler)) {
4742
+ return signature.parameters.length + typeChecker.getTypeArguments(restType).length - 1;
4743
+ }
4744
+ }
4745
+ return signature.parameters.length;
4746
+ }
4747
+ function hasRestParameter(signature, compiler) {
4748
+ return signature.declaration != null && compiler.hasRestParameter(signature.declaration);
4749
+ }
4750
+ function isOptionalParameter(symbol, compiler) {
4751
+ return (symbol.valueDeclaration != null &&
4752
+ compiler.isParameter(symbol.valueDeclaration) &&
4753
+ (symbol.valueDeclaration.questionToken != null || symbol.valueDeclaration.initializer != null));
4754
+ }
4755
+ function isRestParameter(symbol, compiler) {
4756
+ return (symbol.valueDeclaration != null &&
4757
+ compiler.isParameter(symbol.valueDeclaration) &&
4758
+ symbol.valueDeclaration.dotDotDotToken != null);
4759
+ }
4760
+
4761
+ function getTargetSymbol(symbol, compiler) {
4762
+ return isCheckFlagSet(symbol, compiler.CheckFlags.Instantiated, compiler)
4763
+ ? symbol.links.target
4764
+ : symbol;
4765
+ }
4766
+ function isCheckFlagSet(symbol, flag, compiler) {
4767
+ return !!(symbol.flags & compiler.SymbolFlags.Transient && symbol.links.checkFlags & flag);
4768
+ }
4769
+ function isSymbolFromDefaultLibrary(symbol, program) {
4770
+ if (!symbol.declarations) {
4771
+ return false;
4772
+ }
4773
+ return symbol.declarations.every((declaration) => program.isSourceFileDefaultLibrary(declaration.getSourceFile()));
4774
+ }
4775
+
4776
+ function getPropertyType(symbol, compiler, compilerOptions, typeChecker) {
4777
+ const type = typeChecker.getTypeOfSymbol(symbol);
4778
+ if (compilerOptions.exactOptionalPropertyTypes && isOptionalProperty(symbol, compiler)) {
4779
+ if (isUnionType(type, compiler)) {
4780
+ type.types = type.types.filter((type) => !("debugIntrinsicName" in type && type.debugIntrinsicName === "missing"));
4781
+ if (type.types.length === 1) {
4782
+ return type.types.at(0);
4783
+ }
4784
+ }
4785
+ }
4786
+ return type;
4787
+ }
4788
+ function isOptionalProperty(symbol, compiler) {
4789
+ return !!(symbol.flags & compiler.SymbolFlags.Optional);
4790
+ }
4791
+ function isReadonlyProperty(symbol, compiler) {
4792
+ return !!(isCheckFlagSet(symbol, compiler.CheckFlags.Readonly, compiler) ||
4793
+ (symbol.flags & compiler.SymbolFlags.Property &&
4794
+ compiler.getDeclarationModifierFlagsFromSymbol(symbol) & compiler.ModifierFlags.Readonly) ||
4795
+ (symbol.flags & compiler.SymbolFlags.Accessor && !(symbol.flags & compiler.SymbolFlags.SetAccessor)));
4796
+ }
4797
+
4798
+ class Structure {
4799
+ #compiler;
4800
+ #compilerOptions;
4801
+ #program;
4802
+ #resultCache = new Map();
4803
+ #typeChecker;
4804
+ constructor(compiler, program) {
4805
+ this.#compiler = compiler;
4806
+ this.#compilerOptions = program.getCompilerOptions();
4807
+ this.#program = program;
4808
+ this.#typeChecker = program.getTypeChecker();
4809
+ }
4810
+ #compareMaybeNullish(a, b) {
4811
+ if (a != null && b != null) {
4812
+ return this.compare(a, b);
4813
+ }
4814
+ return !a && !b;
4815
+ }
4816
+ #compareTypeOfSymbol(a, b) {
4817
+ const aTypeOfSymbol = a && this.#typeChecker.getTypeOfSymbol(a);
4818
+ const bTypeOfSymbol = b && this.#typeChecker.getTypeOfSymbol(b);
4819
+ return this.#compareMaybeNullish(aTypeOfSymbol, bTypeOfSymbol);
4820
+ }
4821
+ compare(a, b) {
4822
+ a = this.#normalize(a);
4823
+ b = this.#normalize(b);
4824
+ if (a === b) {
4825
+ return true;
4826
+ }
4827
+ if (a.flags & this.#compiler.TypeFlags.Any) {
4828
+ return !!(b.flags & this.#compiler.TypeFlags.Any);
4829
+ }
4830
+ if (a.flags & this.#compiler.TypeFlags.Never) {
4831
+ return !!(b.flags & this.#compiler.TypeFlags.Never);
4832
+ }
4833
+ if (a.flags & this.#compiler.TypeFlags.Undefined) {
4834
+ return !!(b.flags & this.#compiler.TypeFlags.Undefined);
4835
+ }
4836
+ if (isIntersectionType(a, this.#compiler) || isIntersectionType(b, this.#compiler)) {
4837
+ if (isIntersectionType(a, this.#compiler) &&
4838
+ isIntersectionType(b, this.#compiler) &&
4839
+ a.types.length === b.types.length &&
4840
+ a.types.every((aType, i) => this.compare(aType, b.types[i]))) {
4841
+ return true;
4842
+ }
4843
+ return (this.compareProperties(a, b) &&
4844
+ this.compareSignatures(a, b, this.#compiler.SignatureKind.Call) &&
4845
+ this.compareSignatures(a, b, this.#compiler.SignatureKind.Construct) &&
4846
+ this.compareIndexSignatures(a, b));
4847
+ }
4848
+ if (isUnionType(a, this.#compiler) || isUnionType(b, this.#compiler)) {
4849
+ if (isUnionType(a, this.#compiler) && isUnionType(b, this.#compiler)) {
4850
+ return this.compareUnions(a, b);
4851
+ }
4852
+ return false;
4853
+ }
4854
+ if (isTupleTypeReference(a, this.#compiler) || isTupleTypeReference(b, this.#compiler)) {
4855
+ if (isTupleTypeReference(a, this.#compiler) && isTupleTypeReference(b, this.#compiler)) {
4856
+ return this.compareTuples(a, b);
4857
+ }
4858
+ return false;
4859
+ }
4860
+ if (isTypeParameter(a, this.#compiler) || isTypeParameter(b, this.#compiler)) {
4861
+ if (isTypeParameter(a, this.#compiler) && isTypeParameter(b, this.#compiler)) {
4862
+ return this.compareTypeParameter(a, b);
4863
+ }
4864
+ return false;
4865
+ }
4866
+ if (isConditionalType(a, this.#compiler) || isConditionalType(b, this.#compiler)) {
4867
+ if (isConditionalType(a, this.#compiler) && isConditionalType(b, this.#compiler)) {
4868
+ return this.compareConditionalTypes(a, b);
4869
+ }
4870
+ return false;
4871
+ }
4872
+ if (isObjectType(a, this.#compiler) || isObjectType(b, this.#compiler)) {
4873
+ if (isObjectType(a, this.#compiler) && isObjectType(b, this.#compiler)) {
4874
+ return this.compareObjects(a, b);
4875
+ }
4876
+ return false;
4877
+ }
4878
+ return false;
4879
+ }
4880
+ compareConditionalTypes(a, b) {
4881
+ return (this.compare(a.checkType, b.checkType) &&
4882
+ this.compare(a.extendsType, b.extendsType) &&
4883
+ this.compare(this.#typeChecker.getTypeAtLocation(a.root.node.trueType), this.#typeChecker.getTypeAtLocation(b.root.node.trueType)) &&
4884
+ this.compare(this.#typeChecker.getTypeAtLocation(a.root.node.falseType), this.#typeChecker.getTypeAtLocation(b.root.node.falseType)));
4885
+ }
4886
+ compareIndexSignatures(a, b) {
4887
+ const aSignatures = this.#getIndexSignatures(a);
4888
+ const bSignatures = this.#getIndexSignatures(b);
4889
+ if (aSignatures.length !== bSignatures.length) {
4890
+ return false;
4891
+ }
4892
+ for (let i = 0; i < aSignatures.length; i++) {
4893
+ if (aSignatures[i].isReadonly !== bSignatures[i].isReadonly) {
4894
+ return false;
4895
+ }
4896
+ if (!this.compare(aSignatures[i].keyType, bSignatures[i].keyType)) {
4897
+ return false;
4898
+ }
4899
+ if (!this.compare(aSignatures[i].type, bSignatures[i].type)) {
4900
+ return false;
4901
+ }
4902
+ }
4903
+ return true;
4904
+ }
4905
+ compareProperties(a, b) {
4906
+ const aProperties = this.#typeChecker.getPropertiesOfType(a);
4907
+ const bProperties = this.#typeChecker.getPropertiesOfType(b);
4908
+ if (aProperties.length !== bProperties.length) {
4909
+ return false;
4910
+ }
4911
+ for (const aProperty of aProperties) {
4912
+ const bProperty = bProperties.find((bProperty) => bProperty.escapedName === aProperty.escapedName);
4913
+ if (!bProperty) {
4914
+ return false;
4915
+ }
4916
+ if (aProperty === bProperty) {
4917
+ continue;
4918
+ }
4919
+ const aAccessibility = this.#compiler.getDeclarationModifierFlagsFromSymbol(aProperty) &
4920
+ this.#compiler.ModifierFlags.NonPublicAccessibilityModifier;
4921
+ const bAccessibility = this.#compiler.getDeclarationModifierFlagsFromSymbol(bProperty) &
4922
+ this.#compiler.ModifierFlags.NonPublicAccessibilityModifier;
4923
+ if (aAccessibility !== bAccessibility) {
4924
+ return false;
4925
+ }
4926
+ if (aAccessibility) {
4927
+ if (getTargetSymbol(aProperty, this.#compiler) !== getTargetSymbol(bProperty, this.#compiler)) {
4928
+ return false;
4929
+ }
4930
+ }
4931
+ if (isOptionalProperty(aProperty, this.#compiler) !== isOptionalProperty(bProperty, this.#compiler)) {
4932
+ return false;
4933
+ }
4934
+ if (isReadonlyProperty(aProperty, this.#compiler) !== isReadonlyProperty(bProperty, this.#compiler)) {
4935
+ return false;
4936
+ }
4937
+ const aType = getPropertyType(aProperty, this.#compiler, this.#compilerOptions, this.#typeChecker);
4938
+ const bType = getPropertyType(bProperty, this.#compiler, this.#compilerOptions, this.#typeChecker);
4939
+ if (!this.compare(aType, bType)) {
4940
+ return false;
4941
+ }
4942
+ }
4943
+ return true;
4944
+ }
4945
+ compareObjects(a, b) {
4946
+ const key = this.#getCacheKey(a, b);
4947
+ const result = this.#resultCache.get(key);
4948
+ if (result != null) {
4949
+ return result !== 2;
4950
+ }
4951
+ this.#resultCache.set(key, 0);
4952
+ if (isTypeReference(a, this.#compiler) &&
4953
+ !isClass(a, this.#compiler) &&
4954
+ isTypeReference(b, this.#compiler) &&
4955
+ !isClass(b, this.#compiler)) {
4956
+ const isSame = this.compareTypeReferences(a, b);
4957
+ if (isSame != null) {
4958
+ this.#resultCache.set(key, isSame ? 1 : 2);
4959
+ return isSame;
4960
+ }
4961
+ }
4962
+ const isSame = this.compareProperties(a, b) &&
4963
+ this.compareSignatures(a, b, this.#compiler.SignatureKind.Call) &&
4964
+ this.compareSignatures(a, b, this.#compiler.SignatureKind.Construct) &&
4965
+ this.compareIndexSignatures(a, b);
4966
+ this.#resultCache.set(key, isSame ? 1 : 2);
4967
+ return isSame;
4968
+ }
4969
+ compareSignatures(a, b, kind) {
4970
+ const aSignatures = this.#getSignatures(a, kind);
4971
+ const bSignatures = this.#getSignatures(b, kind);
4972
+ if (length(aSignatures) !== length(bSignatures)) {
4973
+ return false;
4974
+ }
4975
+ for (let i = 0; i < aSignatures.length; i++) {
4976
+ if (!this.compareSignature(aSignatures[i], bSignatures[i])) {
4977
+ return false;
4978
+ }
4979
+ }
4980
+ return true;
4981
+ }
4982
+ compareSignature(a, b) {
4983
+ if (length(a.typeParameters) !== length(b.typeParameters)) {
4984
+ return false;
4985
+ }
4986
+ if (a.typeParameters != null && b.typeParameters != null) {
4987
+ for (let i = 0; i < a.typeParameters.length; i++) {
4988
+ if (!this.compareTypeParameter(a.typeParameters[i], b.typeParameters[i])) {
4989
+ return false;
4990
+ }
4991
+ }
4992
+ }
4993
+ if (!this.#compareTypeOfSymbol(a.thisParameter, b.thisParameter)) {
4994
+ return false;
4995
+ }
4996
+ if (!this.compareParameters(a, b)) {
4997
+ return false;
4998
+ }
4999
+ if (!this.compare(this.#typeChecker.getReturnTypeOfSignature(a), this.#typeChecker.getReturnTypeOfSignature(b))) {
5000
+ return false;
5001
+ }
5002
+ const aTypePredicate = this.#typeChecker.getTypePredicateOfSignature(a);
5003
+ const bTypePredicate = this.#typeChecker.getTypePredicateOfSignature(b);
5004
+ if (aTypePredicate?.kind !== bTypePredicate?.kind ||
5005
+ !this.#compareMaybeNullish(aTypePredicate?.type, bTypePredicate?.type)) {
5006
+ return false;
5007
+ }
5008
+ return true;
5009
+ }
5010
+ compareParameters(a, b) {
5011
+ const aParametersCount = getParameterCount(a, this.#compiler, this.#typeChecker);
5012
+ const bParametersCount = getParameterCount(b, this.#compiler, this.#typeChecker);
5013
+ if (aParametersCount !== bParametersCount) {
5014
+ return false;
5015
+ }
5016
+ for (let i = 0; i < aParametersCount; i++) {
5017
+ const aParameter = getParameterFacts(a, i, this.#compiler, this.#typeChecker);
5018
+ const bParameter = getParameterFacts(b, i, this.#compiler, this.#typeChecker);
5019
+ if (aParameter.isOptional !== bParameter.isOptional) {
5020
+ return false;
5021
+ }
5022
+ if (aParameter.isRest !== bParameter.isRest) {
5023
+ return false;
5024
+ }
5025
+ if (!this.compare(aParameter.getType(this.#typeChecker), bParameter.getType(this.#typeChecker))) {
5026
+ return false;
5027
+ }
5028
+ }
5029
+ return true;
5030
+ }
5031
+ compareTuples(a, b) {
5032
+ if (a.target.readonly !== b.target.readonly) {
5033
+ return false;
5034
+ }
5035
+ const aTypeArguments = this.#typeChecker.getTypeArguments(a);
5036
+ const bTypeArguments = this.#typeChecker.getTypeArguments(b);
5037
+ if (length(aTypeArguments) !== length(bTypeArguments)) {
5038
+ return false;
5039
+ }
5040
+ for (let i = 0; i < aTypeArguments.length; i++) {
5041
+ if (a.target.elementFlags[i] !== b.target.elementFlags[i]) {
5042
+ return false;
5043
+ }
5044
+ if (!this.compare(aTypeArguments[i], bTypeArguments[i])) {
5045
+ return false;
5046
+ }
5047
+ }
5048
+ return true;
5049
+ }
5050
+ compareTypeParameter(a, b) {
5051
+ if (!this.#compareMaybeNullish(this.#typeChecker.getBaseConstraintOfType(a), this.#typeChecker.getBaseConstraintOfType(b)) ||
5052
+ !this.#compareMaybeNullish(this.#typeChecker.getDefaultFromTypeParameter(a), this.#typeChecker.getDefaultFromTypeParameter(b))) {
5053
+ return false;
5054
+ }
5055
+ return true;
5056
+ }
5057
+ compareTypeReferences(a, b) {
5058
+ if (!this.#compareTypeOfSymbol(a.symbol, b.symbol)) {
5059
+ if (isSymbolFromDefaultLibrary(a.symbol, this.#program) || isSymbolFromDefaultLibrary(b.symbol, this.#program)) {
5060
+ return false;
5061
+ }
5062
+ return;
5063
+ }
5064
+ if (length(a.typeArguments) !== length(b.typeArguments)) {
5065
+ return false;
5066
+ }
5067
+ return ensureArray(a.typeArguments).every((type, i) => this.compare(type, ensureArray(b.typeArguments)[i]));
5068
+ }
5069
+ compareUnions(a, b) {
5070
+ if (a.types.length !== b.types.length) {
5071
+ return false;
5072
+ }
5073
+ return (a.types.every((aType) => b.types.some((bType) => this.compare(aType, bType))) &&
5074
+ b.types.every((bType) => a.types.some((aType) => this.compare(bType, aType))));
5075
+ }
5076
+ #getCacheKey(a, b) {
5077
+ return [a.id, b.id].sort().join(":");
5078
+ }
5079
+ #getSignatures(type, kind) {
5080
+ if (isIntersectionType(type, this.#compiler)) {
5081
+ return type.types.flatMap((type) => this.#getSignatures(type, kind));
5082
+ }
5083
+ return this.#typeChecker.getSignaturesOfType(type, kind);
5084
+ }
5085
+ #getIndexSignatures(type) {
5086
+ if (isIntersectionType(type, this.#compiler)) {
5087
+ return type.types.flatMap((type) => this.#getIndexSignatures(type));
5088
+ }
5089
+ return this.#typeChecker.getIndexInfosOfType(type);
5090
+ }
5091
+ #normalize(type) {
5092
+ if (isFreshLiteralType(type, this.#compiler)) {
5093
+ return type.regularType;
5094
+ }
5095
+ if (isNoInferType(type, this.#compiler)) {
5096
+ return type.baseType;
5097
+ }
5098
+ if (isUnionType(type, this.#compiler) || isIntersectionType(type, this.#compiler)) {
5099
+ const candidateType = this.#normalize(type.types[0]);
5100
+ if (type.types.every((type) => this.compare(this.#normalize(type), candidateType))) {
5101
+ return candidateType;
5102
+ }
5103
+ }
5104
+ return type;
4637
5105
  }
4638
5106
  }
4639
5107
 
4640
5108
  class ToBe extends RelationMatcherBase {
5109
+ #structure;
5110
+ constructor(compiler, program) {
5111
+ super();
5112
+ this.#structure = new Structure(compiler, program);
5113
+ }
4641
5114
  explainText = ExpectDiagnosticText.isTheSame;
4642
5115
  explainNotText = ExpectDiagnosticText.isNotTheSame;
4643
5116
  match(matchWorker, sourceNode, targetNode) {
4644
5117
  return {
4645
5118
  explain: () => this.explain(matchWorker, sourceNode, targetNode),
4646
- isMatch: matchWorker.checkIsIdenticalTo(sourceNode, targetNode),
5119
+ isMatch: this.#structure.compare(matchWorker.getType(sourceNode), matchWorker.getType(targetNode)),
4647
5120
  };
4648
5121
  }
4649
5122
  }
@@ -4972,8 +5445,8 @@ class ToRaiseError {
4972
5445
 
4973
5446
  class ExpectService {
4974
5447
  #compiler;
5448
+ #program;
4975
5449
  #reject;
4976
- #typeChecker;
4977
5450
  toAcceptProps;
4978
5451
  toBe;
4979
5452
  toBeApplicable;
@@ -4983,12 +5456,12 @@ class ExpectService {
4983
5456
  toBeConstructableWith;
4984
5457
  toHaveProperty;
4985
5458
  toRaiseError;
4986
- constructor(compiler, typeChecker, reject) {
5459
+ constructor(compiler, program, reject, resolvedConfig) {
4987
5460
  this.#compiler = compiler;
5461
+ this.#program = program;
4988
5462
  this.#reject = reject;
4989
- this.#typeChecker = typeChecker;
4990
- this.toAcceptProps = new ToAcceptProps(compiler, typeChecker);
4991
- this.toBe = new ToBe();
5463
+ this.toAcceptProps = new ToAcceptProps(compiler, program);
5464
+ this.toBe = resolvedConfig.legacyToBe ? new LegacyToBe() : new ToBe(compiler, program);
4992
5465
  this.toBeApplicable = new ToBeApplicable(compiler);
4993
5466
  this.toBeAssignableFrom = new ToBeAssignableFrom();
4994
5467
  this.toBeAssignableTo = new ToBeAssignableTo();
@@ -5002,7 +5475,7 @@ class ExpectService {
5002
5475
  if (!argumentOrTypeArgumentIsProvided("source", "Source", assertionNode.source[0], assertionNode.node.expression, onDiagnostics)) {
5003
5476
  return;
5004
5477
  }
5005
- const matchWorker = new MatchWorker(this.#compiler, this.#typeChecker, assertionNode);
5478
+ const matchWorker = new MatchWorker(this.#compiler, this.#program, assertionNode);
5006
5479
  if (!(matcherNameText === "toRaiseError" && assertionNode.isNot === false) &&
5007
5480
  this.#reject.argumentType([
5008
5481
  ["source", assertionNode.source[0]],
@@ -5066,9 +5539,9 @@ class Reject {
5066
5539
  #compiler;
5067
5540
  #rejectedArgumentTypes = new Set();
5068
5541
  #typeChecker;
5069
- constructor(compiler, typeChecker, resolvedConfig) {
5542
+ constructor(compiler, program, resolvedConfig) {
5070
5543
  this.#compiler = compiler;
5071
- this.#typeChecker = typeChecker;
5544
+ this.#typeChecker = program.getTypeChecker();
5072
5545
  if (resolvedConfig?.rejectAnyType) {
5073
5546
  this.#rejectedArgumentTypes.add("any");
5074
5547
  }
@@ -5225,15 +5698,15 @@ class TestTreeWalker {
5225
5698
  #position;
5226
5699
  #resolvedConfig;
5227
5700
  #whenService;
5228
- constructor(compiler, typeChecker, resolvedConfig, onFileDiagnostics, options) {
5701
+ constructor(compiler, program, resolvedConfig, onFileDiagnostics, options) {
5229
5702
  this.#compiler = compiler;
5230
5703
  this.#resolvedConfig = resolvedConfig;
5231
5704
  this.#onFileDiagnostics = onFileDiagnostics;
5232
5705
  this.#cancellationToken = options.cancellationToken;
5233
5706
  this.#hasOnly = options.hasOnly || resolvedConfig.only != null || options.position != null;
5234
5707
  this.#position = options.position;
5235
- const reject = new Reject(compiler, typeChecker, resolvedConfig);
5236
- this.#expectService = new ExpectService(compiler, typeChecker, reject);
5708
+ const reject = new Reject(compiler, program, resolvedConfig);
5709
+ this.#expectService = new ExpectService(compiler, program, reject, resolvedConfig);
5237
5710
  this.#whenService = new WhenService(reject, onFileDiagnostics);
5238
5711
  }
5239
5712
  async #resolveRunMode(flags, node) {
@@ -5423,9 +5896,8 @@ class FileRunner {
5423
5896
  }
5424
5897
  const semanticDiagnostics = languageService?.getSemanticDiagnostics(file.path);
5425
5898
  const program = languageService?.getProgram();
5426
- const typeChecker = program?.getTypeChecker();
5427
5899
  const sourceFile = program?.getSourceFile(file.path);
5428
- if (!sourceFile) {
5900
+ if (!program || !sourceFile) {
5429
5901
  return;
5430
5902
  }
5431
5903
  const directiveRanges = Directive.getDirectiveRanges(this.#compiler, sourceFile);
@@ -5449,7 +5921,7 @@ class FileRunner {
5449
5921
  }
5450
5922
  const testTree = this.#collectService.createTestTree(sourceFile, semanticDiagnostics);
5451
5923
  this.#suppressedService.match(testTree);
5452
- return { runModeFlags, testTree, typeChecker };
5924
+ return { runModeFlags, testTree, program };
5453
5925
  }
5454
5926
  async #run(file, fileResult, cancellationToken) {
5455
5927
  if (!existsSync(file.path)) {
@@ -5467,7 +5939,7 @@ class FileRunner {
5467
5939
  const onFileDiagnostics = (diagnostics) => {
5468
5940
  this.#onDiagnostics(diagnostics, fileResult);
5469
5941
  };
5470
- const testTreeWalker = new TestTreeWalker(this.#compiler, facts.typeChecker, this.#resolvedConfig, onFileDiagnostics, {
5942
+ const testTreeWalker = new TestTreeWalker(this.#compiler, facts.program, this.#resolvedConfig, onFileDiagnostics, {
5471
5943
  cancellationToken,
5472
5944
  hasOnly: facts.testTree.hasOnly,
5473
5945
  position: file.position,
@@ -5479,7 +5951,7 @@ class FileRunner {
5479
5951
  class Runner {
5480
5952
  #eventEmitter = new EventEmitter();
5481
5953
  #resolvedConfig;
5482
- static version = "5.0.1";
5954
+ static version = "6.0.0-beta.0";
5483
5955
  constructor(resolvedConfig) {
5484
5956
  this.#resolvedConfig = resolvedConfig;
5485
5957
  }
@@ -5536,7 +6008,7 @@ class Runner {
5536
6008
  for (const target of this.#resolvedConfig.target) {
5537
6009
  const targetResult = new TargetResult(target, files);
5538
6010
  EventEmitter.dispatch(["target:start", { result: targetResult }]);
5539
- const compiler = await Store.load(target);
6011
+ const compiler = await Store.load(target, { notPatched: !this.#resolvedConfig.legacyToBe });
5540
6012
  if (compiler) {
5541
6013
  const fileRunner = new FileRunner(compiler, this.#resolvedConfig);
5542
6014
  for (const file of files) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "tstyche",
3
- "version": "5.0.1",
3
+ "version": "6.0.0-beta.0",
4
4
  "description": "Everything You Need for Type Testing.",
5
5
  "keywords": [
6
6
  "typescript",