tstyche 5.0.2 → 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.
@@ -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;
@@ -955,7 +955,13 @@ class Store {
955
955
  if (!Version.isSatisfiedWith(packageVersion, "5.3")) {
956
956
  modulePath = Path.resolve(modulePath, "../tsserverlibrary.js");
957
957
  }
958
- compilerInstance = await Store.#loadPatchedModule(modulePath);
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
+ }
959
965
  Store.#compilerInstanceCache.set(tag, compilerInstance);
960
966
  Store.#compilerInstanceCache.set(compilerInstance.version, compilerInstance);
961
967
  }
@@ -1101,6 +1107,12 @@ class Options {
1101
1107
  group: 2,
1102
1108
  name: "help",
1103
1109
  },
1110
+ {
1111
+ brand: "boolean",
1112
+ description: "Use the patch-based implementation of the '.toBe()' matcher.",
1113
+ group: 4,
1114
+ name: "legacyToBe",
1115
+ },
1104
1116
  {
1105
1117
  brand: "true",
1106
1118
  description: "Print the list of supported versions of the 'typescript' package and exit.",
@@ -1591,6 +1603,7 @@ const defaultOptions = {
1591
1603
  checkSuppressedErrors: true,
1592
1604
  failFast: false,
1593
1605
  fixtureFileMatch: ["**/__fixtures__/*.{ts,tsx}", "**/fixtures/*.{ts,tsx}"],
1606
+ legacyToBe: false,
1594
1607
  plugins: [],
1595
1608
  rejectAnyType: true,
1596
1609
  rejectNeverType: true,
@@ -4350,14 +4363,37 @@ class ExpectDiagnosticText {
4350
4363
  }
4351
4364
  }
4352
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
+
4353
4389
  class MatchWorker {
4354
4390
  assertionNode;
4355
4391
  #compiler;
4356
4392
  #signatureCache = new Map();
4357
4393
  typeChecker;
4358
- constructor(compiler, typeChecker, assertionNode) {
4394
+ constructor(compiler, program, assertionNode) {
4359
4395
  this.#compiler = compiler;
4360
- this.typeChecker = typeChecker;
4396
+ this.typeChecker = program.getTypeChecker();
4361
4397
  this.assertionNode = assertionNode;
4362
4398
  }
4363
4399
  checkIsAssignableTo(sourceNode, targetNode) {
@@ -4436,7 +4472,7 @@ class MatchWorker {
4436
4472
  function isStringOrNumberLiteralType(compiler, type) {
4437
4473
  return !!(type.flags & compiler.TypeFlags.StringOrNumberLiteral);
4438
4474
  }
4439
- function isUnionType(compiler, type) {
4475
+ function isUnionType$1(compiler, type) {
4440
4476
  return !!(type.flags & compiler.TypeFlags.Union);
4441
4477
  }
4442
4478
  function isUniqueSymbolType(compiler, type) {
@@ -4446,9 +4482,9 @@ function isUniqueSymbolType(compiler, type) {
4446
4482
  class ToAcceptProps {
4447
4483
  #compiler;
4448
4484
  #typeChecker;
4449
- constructor(compiler, typeChecker) {
4485
+ constructor(compiler, program) {
4450
4486
  this.#compiler = compiler;
4451
- this.#typeChecker = typeChecker;
4487
+ this.#typeChecker = program.getTypeChecker();
4452
4488
  }
4453
4489
  #explain(matchWorker, sourceNode, targetNode) {
4454
4490
  const isExpression = nodeBelongsToArgumentList(this.#compiler, sourceNode);
@@ -4505,7 +4541,7 @@ class ToAcceptProps {
4505
4541
  }
4506
4542
  return true;
4507
4543
  };
4508
- if (sourceType != null && isUnionType(this.#compiler, sourceType)) {
4544
+ if (sourceType != null && isUnionType$1(this.#compiler, sourceType)) {
4509
4545
  return sourceType.types.some((sourceType) => check(sourceType, targetType));
4510
4546
  }
4511
4547
  return check(sourceType, targetType);
@@ -4573,7 +4609,7 @@ class ToAcceptProps {
4573
4609
  }
4574
4610
  return { diagnostics, isMatch: false };
4575
4611
  };
4576
- if (sourceType != null && isUnionType(this.#compiler, sourceType)) {
4612
+ if (sourceType != null && isUnionType$1(this.#compiler, sourceType)) {
4577
4613
  let accumulator = [];
4578
4614
  const isMatch = sourceType.types.some((sourceType) => {
4579
4615
  const text = matchWorker.assertionNode.isNot
@@ -4627,25 +4663,460 @@ class ToAcceptProps {
4627
4663
  }
4628
4664
  }
4629
4665
 
4630
- class RelationMatcherBase {
4631
- explain(matchWorker, sourceNode, targetNode) {
4632
- const sourceTypeText = matchWorker.getTypeText(sourceNode);
4633
- const targetTypeText = matchWorker.getTypeText(targetNode);
4634
- const text = matchWorker.assertionNode.isNot
4635
- ? this.explainText(sourceTypeText, targetTypeText)
4636
- : this.explainNotText(sourceTypeText, targetTypeText);
4637
- const origin = DiagnosticOrigin.fromNode(targetNode, matchWorker.assertionNode);
4638
- 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;
4639
5105
  }
4640
5106
  }
4641
5107
 
4642
5108
  class ToBe extends RelationMatcherBase {
5109
+ #structure;
5110
+ constructor(compiler, program) {
5111
+ super();
5112
+ this.#structure = new Structure(compiler, program);
5113
+ }
4643
5114
  explainText = ExpectDiagnosticText.isTheSame;
4644
5115
  explainNotText = ExpectDiagnosticText.isNotTheSame;
4645
5116
  match(matchWorker, sourceNode, targetNode) {
4646
5117
  return {
4647
5118
  explain: () => this.explain(matchWorker, sourceNode, targetNode),
4648
- isMatch: matchWorker.checkIsIdenticalTo(sourceNode, targetNode),
5119
+ isMatch: this.#structure.compare(matchWorker.getType(sourceNode), matchWorker.getType(targetNode)),
4649
5120
  };
4650
5121
  }
4651
5122
  }
@@ -4974,8 +5445,8 @@ class ToRaiseError {
4974
5445
 
4975
5446
  class ExpectService {
4976
5447
  #compiler;
5448
+ #program;
4977
5449
  #reject;
4978
- #typeChecker;
4979
5450
  toAcceptProps;
4980
5451
  toBe;
4981
5452
  toBeApplicable;
@@ -4985,12 +5456,12 @@ class ExpectService {
4985
5456
  toBeConstructableWith;
4986
5457
  toHaveProperty;
4987
5458
  toRaiseError;
4988
- constructor(compiler, typeChecker, reject) {
5459
+ constructor(compiler, program, reject, resolvedConfig) {
4989
5460
  this.#compiler = compiler;
5461
+ this.#program = program;
4990
5462
  this.#reject = reject;
4991
- this.#typeChecker = typeChecker;
4992
- this.toAcceptProps = new ToAcceptProps(compiler, typeChecker);
4993
- this.toBe = new ToBe();
5463
+ this.toAcceptProps = new ToAcceptProps(compiler, program);
5464
+ this.toBe = resolvedConfig.legacyToBe ? new LegacyToBe() : new ToBe(compiler, program);
4994
5465
  this.toBeApplicable = new ToBeApplicable(compiler);
4995
5466
  this.toBeAssignableFrom = new ToBeAssignableFrom();
4996
5467
  this.toBeAssignableTo = new ToBeAssignableTo();
@@ -5004,7 +5475,7 @@ class ExpectService {
5004
5475
  if (!argumentOrTypeArgumentIsProvided("source", "Source", assertionNode.source[0], assertionNode.node.expression, onDiagnostics)) {
5005
5476
  return;
5006
5477
  }
5007
- const matchWorker = new MatchWorker(this.#compiler, this.#typeChecker, assertionNode);
5478
+ const matchWorker = new MatchWorker(this.#compiler, this.#program, assertionNode);
5008
5479
  if (!(matcherNameText === "toRaiseError" && assertionNode.isNot === false) &&
5009
5480
  this.#reject.argumentType([
5010
5481
  ["source", assertionNode.source[0]],
@@ -5068,9 +5539,9 @@ class Reject {
5068
5539
  #compiler;
5069
5540
  #rejectedArgumentTypes = new Set();
5070
5541
  #typeChecker;
5071
- constructor(compiler, typeChecker, resolvedConfig) {
5542
+ constructor(compiler, program, resolvedConfig) {
5072
5543
  this.#compiler = compiler;
5073
- this.#typeChecker = typeChecker;
5544
+ this.#typeChecker = program.getTypeChecker();
5074
5545
  if (resolvedConfig?.rejectAnyType) {
5075
5546
  this.#rejectedArgumentTypes.add("any");
5076
5547
  }
@@ -5227,15 +5698,15 @@ class TestTreeWalker {
5227
5698
  #position;
5228
5699
  #resolvedConfig;
5229
5700
  #whenService;
5230
- constructor(compiler, typeChecker, resolvedConfig, onFileDiagnostics, options) {
5701
+ constructor(compiler, program, resolvedConfig, onFileDiagnostics, options) {
5231
5702
  this.#compiler = compiler;
5232
5703
  this.#resolvedConfig = resolvedConfig;
5233
5704
  this.#onFileDiagnostics = onFileDiagnostics;
5234
5705
  this.#cancellationToken = options.cancellationToken;
5235
5706
  this.#hasOnly = options.hasOnly || resolvedConfig.only != null || options.position != null;
5236
5707
  this.#position = options.position;
5237
- const reject = new Reject(compiler, typeChecker, resolvedConfig);
5238
- this.#expectService = new ExpectService(compiler, typeChecker, reject);
5708
+ const reject = new Reject(compiler, program, resolvedConfig);
5709
+ this.#expectService = new ExpectService(compiler, program, reject, resolvedConfig);
5239
5710
  this.#whenService = new WhenService(reject, onFileDiagnostics);
5240
5711
  }
5241
5712
  async #resolveRunMode(flags, node) {
@@ -5425,9 +5896,8 @@ class FileRunner {
5425
5896
  }
5426
5897
  const semanticDiagnostics = languageService?.getSemanticDiagnostics(file.path);
5427
5898
  const program = languageService?.getProgram();
5428
- const typeChecker = program?.getTypeChecker();
5429
5899
  const sourceFile = program?.getSourceFile(file.path);
5430
- if (!sourceFile) {
5900
+ if (!program || !sourceFile) {
5431
5901
  return;
5432
5902
  }
5433
5903
  const directiveRanges = Directive.getDirectiveRanges(this.#compiler, sourceFile);
@@ -5451,7 +5921,7 @@ class FileRunner {
5451
5921
  }
5452
5922
  const testTree = this.#collectService.createTestTree(sourceFile, semanticDiagnostics);
5453
5923
  this.#suppressedService.match(testTree);
5454
- return { runModeFlags, testTree, typeChecker };
5924
+ return { runModeFlags, testTree, program };
5455
5925
  }
5456
5926
  async #run(file, fileResult, cancellationToken) {
5457
5927
  if (!existsSync(file.path)) {
@@ -5469,7 +5939,7 @@ class FileRunner {
5469
5939
  const onFileDiagnostics = (diagnostics) => {
5470
5940
  this.#onDiagnostics(diagnostics, fileResult);
5471
5941
  };
5472
- const testTreeWalker = new TestTreeWalker(this.#compiler, facts.typeChecker, this.#resolvedConfig, onFileDiagnostics, {
5942
+ const testTreeWalker = new TestTreeWalker(this.#compiler, facts.program, this.#resolvedConfig, onFileDiagnostics, {
5473
5943
  cancellationToken,
5474
5944
  hasOnly: facts.testTree.hasOnly,
5475
5945
  position: file.position,
@@ -5481,7 +5951,7 @@ class FileRunner {
5481
5951
  class Runner {
5482
5952
  #eventEmitter = new EventEmitter();
5483
5953
  #resolvedConfig;
5484
- static version = "5.0.2";
5954
+ static version = "6.0.0-beta.0";
5485
5955
  constructor(resolvedConfig) {
5486
5956
  this.#resolvedConfig = resolvedConfig;
5487
5957
  }
@@ -5538,7 +6008,7 @@ class Runner {
5538
6008
  for (const target of this.#resolvedConfig.target) {
5539
6009
  const targetResult = new TargetResult(target, files);
5540
6010
  EventEmitter.dispatch(["target:start", { result: targetResult }]);
5541
- const compiler = await Store.load(target);
6011
+ const compiler = await Store.load(target, { notPatched: !this.#resolvedConfig.legacyToBe });
5542
6012
  if (compiler) {
5543
6013
  const fileRunner = new FileRunner(compiler, this.#resolvedConfig);
5544
6014
  for (const file of files) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "tstyche",
3
- "version": "5.0.2",
3
+ "version": "6.0.0-beta.0",
4
4
  "description": "Everything You Need for Type Testing.",
5
5
  "keywords": [
6
6
  "typescript",