tstyche 5.0.2 → 6.0.0-beta.1

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) {
@@ -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);
@@ -4627,25 +4663,486 @@ 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 getIndexSignatures(type, compiler, typeChecker) {
4670
+ if (type.flags & compiler.TypeFlags.Intersection) {
4671
+ return type.types.flatMap((type) => getIndexSignatures(type, compiler, typeChecker));
4672
+ }
4673
+ return typeChecker.getIndexInfosOfType(type);
4674
+ }
4675
+ function getSignatures(type, kind, compiler, typeChecker) {
4676
+ if (type.flags & compiler.TypeFlags.Intersection) {
4677
+ return type.types.flatMap((type) => getSignatures(type, kind, compiler, typeChecker));
4678
+ }
4679
+ return typeChecker.getSignaturesOfType(type, kind);
4680
+ }
4681
+ function getTypeParameterModifiers(typeParameter, compiler) {
4682
+ if (!typeParameter.symbol.declarations) {
4683
+ return compiler.ModifierFlags.None;
4684
+ }
4685
+ return (typeParameter.symbol.declarations.reduce((modifiers, declaration) => modifiers | compiler.getEffectiveModifierFlags(declaration), compiler.ModifierFlags.None) &
4686
+ (compiler.ModifierFlags.In | compiler.ModifierFlags.Out | compiler.ModifierFlags.Const));
4687
+ }
4688
+ function getTargetSymbol(symbol, compiler) {
4689
+ return isCheckFlagSet(symbol, compiler.CheckFlags.Instantiated, compiler)
4690
+ ? symbol.links.target
4691
+ : symbol;
4692
+ }
4693
+ function isCheckFlagSet(symbol, flag, compiler) {
4694
+ return !!(symbol.flags & compiler.SymbolFlags.Transient && symbol.links.checkFlags & flag);
4695
+ }
4696
+ function isSymbolFromDefaultLibrary(symbol, program) {
4697
+ return !!symbol.declarations?.every((declaration) => program.isSourceFileDefaultLibrary(declaration.getSourceFile()));
4698
+ }
4699
+ function length(array) {
4700
+ return array?.length ?? 0;
4701
+ }
4702
+
4703
+ function getParameterFactsFromTuple(type, position, compiler) {
4704
+ return {
4705
+ isOptional: !!(type.target.elementFlags[position] & compiler.ElementFlags.Optional),
4706
+ isRest: !!(type.target.elementFlags[position] & compiler.ElementFlags.Rest),
4707
+ getType: (typeChecker) => typeChecker.getTypeArguments(type)[position],
4708
+ };
4709
+ }
4710
+ function getParameterFacts(signature, parameterIndex, compiler, typeChecker) {
4711
+ if (parameterIndex >= signature.parameters.length - 1 && compiler.hasRestParameter(signature.getDeclaration())) {
4712
+ const restType = typeChecker.getTypeOfSymbol(signature.parameters.at(-1));
4713
+ if (typeChecker.isTupleType(restType)) {
4714
+ const fixedLength = signature.parameters.length - 1;
4715
+ return getParameterFactsFromTuple(restType, parameterIndex - fixedLength, compiler);
4716
+ }
4717
+ }
4718
+ const parameter = signature.parameters[parameterIndex];
4719
+ return {
4720
+ isOptional: isOptionalParameter(parameter, compiler),
4721
+ isRest: isRestParameter(parameter, compiler),
4722
+ getType: (typeChecker) => typeChecker.getParameterType(signature, parameterIndex),
4723
+ };
4724
+ }
4725
+ function getParameterCount(signature, compiler, typeChecker) {
4726
+ if (signature.declaration != null && compiler.hasRestParameter(signature.declaration)) {
4727
+ const restType = typeChecker.getTypeOfSymbol(signature.parameters.at(-1));
4728
+ if (typeChecker.isTupleType(restType)) {
4729
+ return signature.parameters.length + typeChecker.getTypeArguments(restType).length - 1;
4730
+ }
4731
+ }
4732
+ return signature.parameters.length;
4733
+ }
4734
+ function isOptionalParameter(symbol, compiler) {
4735
+ return (symbol.valueDeclaration != null &&
4736
+ compiler.isParameter(symbol.valueDeclaration) &&
4737
+ (symbol.valueDeclaration.questionToken != null || symbol.valueDeclaration.initializer != null));
4738
+ }
4739
+ function isRestParameter(symbol, compiler) {
4740
+ return (symbol.valueDeclaration != null &&
4741
+ compiler.isParameter(symbol.valueDeclaration) &&
4742
+ symbol.valueDeclaration.dotDotDotToken != null);
4743
+ }
4744
+
4745
+ function getPropertyType(symbol, compiler, compilerOptions, typeChecker) {
4746
+ const type = typeChecker.getTypeOfSymbol(symbol);
4747
+ if (compilerOptions.exactOptionalPropertyTypes && isOptionalProperty(symbol, compiler)) {
4748
+ if (type.flags & compiler.TypeFlags.Union) {
4749
+ const filteredType = type.types.filter((type) => !("debugIntrinsicName" in type && type.debugIntrinsicName === "missing"));
4750
+ if (filteredType.length === type.types.length) {
4751
+ return type;
4752
+ }
4753
+ if (filteredType.length === 1) {
4754
+ return filteredType.at(0);
4755
+ }
4756
+ return { ...type, types: filteredType };
4757
+ }
4758
+ }
4759
+ return type;
4760
+ }
4761
+ function isOptionalProperty(symbol, compiler) {
4762
+ return !!(symbol.flags & compiler.SymbolFlags.Optional);
4763
+ }
4764
+ function isReadonlyProperty(symbol, compiler) {
4765
+ return !!(isCheckFlagSet(symbol, compiler.CheckFlags.Readonly, compiler) ||
4766
+ (symbol.flags & compiler.SymbolFlags.Property &&
4767
+ compiler.getDeclarationModifierFlagsFromSymbol(symbol) & compiler.ModifierFlags.Readonly) ||
4768
+ (symbol.flags & compiler.SymbolFlags.Accessor && !(symbol.flags & compiler.SymbolFlags.SetAccessor)));
4769
+ }
4770
+
4771
+ class SeenService {
4772
+ #cache = new Map();
4773
+ memoized(a, b, compare) {
4774
+ const key = [a.id, b.id].sort().join(":");
4775
+ const result = this.#cache.get(key);
4776
+ if (result !== undefined) {
4777
+ return result !== 2;
4778
+ }
4779
+ this.#cache.set(key, 0);
4780
+ const isSame = compare();
4781
+ this.#cache.set(key, isSame ? 1 : 2);
4782
+ return isSame;
4783
+ }
4784
+ }
4785
+
4786
+ class Structure {
4787
+ #compiler;
4788
+ #compilerOptions;
4789
+ #program;
4790
+ #seen = new SeenService();
4791
+ #typeChecker;
4792
+ constructor(compiler, program) {
4793
+ this.#compiler = compiler;
4794
+ this.#compilerOptions = program.getCompilerOptions();
4795
+ this.#program = program;
4796
+ this.#typeChecker = program.getTypeChecker();
4797
+ }
4798
+ #compareMaybeNullish(a, b) {
4799
+ if (a != null && b != null) {
4800
+ return this.compare(a, b);
4801
+ }
4802
+ return !a && !b;
4803
+ }
4804
+ #compareTypeOfSymbol(a, b) {
4805
+ const aTypeOfSymbol = a && this.#typeChecker.getTypeOfSymbol(a);
4806
+ const bTypeOfSymbol = b && this.#typeChecker.getTypeOfSymbol(b);
4807
+ return this.#compareMaybeNullish(aTypeOfSymbol, bTypeOfSymbol);
4808
+ }
4809
+ compare(a, b) {
4810
+ a = this.#normalize(a);
4811
+ b = this.#normalize(b);
4812
+ if (a.id === b.id) {
4813
+ return true;
4814
+ }
4815
+ if (a.flags & this.#compiler.TypeFlags.Any) {
4816
+ return !!(b.flags & this.#compiler.TypeFlags.Any);
4817
+ }
4818
+ if (a.flags & this.#compiler.TypeFlags.Never) {
4819
+ return !!(b.flags & this.#compiler.TypeFlags.Never);
4820
+ }
4821
+ if (a.flags & this.#compiler.TypeFlags.Undefined) {
4822
+ return !!(b.flags & this.#compiler.TypeFlags.Undefined);
4823
+ }
4824
+ if ((a.flags | b.flags) & this.#compiler.TypeFlags.Intersection) {
4825
+ return (((a.flags & b.flags & this.#compiler.TypeFlags.Intersection) !== 0 &&
4826
+ this.compareIntersections(a, b)) ||
4827
+ (((a.flags & b.flags) | this.#compiler.TypeFlags.StructuredType) !== 0 &&
4828
+ this.#seen.memoized(a, b, () => this.compareStructuredTypes(a, b))));
4829
+ }
4830
+ if ((a.flags | b.flags) & this.#compiler.TypeFlags.Union) {
4831
+ if (a.flags & b.flags & this.#compiler.TypeFlags.Union) {
4832
+ return this.compareUnions(a, b);
4833
+ }
4834
+ return false;
4835
+ }
4836
+ if ((a.flags | b.flags) & this.#compiler.TypeFlags.Object) {
4837
+ if (a.flags & b.flags & this.#compiler.TypeFlags.Object) {
4838
+ return this.#seen.memoized(a, b, () => this.compareObjects(a, b));
4839
+ }
4840
+ return false;
4841
+ }
4842
+ if ((a.flags | b.flags) & this.#compiler.TypeFlags.TypeParameter) {
4843
+ if (a.flags & b.flags & this.#compiler.TypeFlags.TypeParameter) {
4844
+ return this.compareTypeParameters(a, b);
4845
+ }
4846
+ return false;
4847
+ }
4848
+ if ((a.flags | b.flags) & this.#compiler.TypeFlags.Index) {
4849
+ if (a.flags & b.flags & this.#compiler.TypeFlags.Index) {
4850
+ return this.compare(a.type, b.type);
4851
+ }
4852
+ return false;
4853
+ }
4854
+ if ((a.flags | b.flags) & this.#compiler.TypeFlags.IndexedAccess) {
4855
+ if (a.flags & b.flags & this.#compiler.TypeFlags.IndexedAccess) {
4856
+ return this.compareIndexedAccessTypes(a, b);
4857
+ }
4858
+ return false;
4859
+ }
4860
+ if ((a.flags | b.flags) & this.#compiler.TypeFlags.Conditional) {
4861
+ if (a.flags & b.flags & this.#compiler.TypeFlags.Conditional) {
4862
+ return this.compareConditionalTypes(a, b);
4863
+ }
4864
+ return false;
4865
+ }
4866
+ if ((a.flags | b.flags) & this.#compiler.TypeFlags.Substitution) {
4867
+ if (a.flags & b.flags & this.#compiler.TypeFlags.Substitution) {
4868
+ return this.compareSubstitutionTypes(a, b);
4869
+ }
4870
+ return false;
4871
+ }
4872
+ return false;
4873
+ }
4874
+ compareIntersections(a, b) {
4875
+ if (a.types.length !== b.types.length) {
4876
+ return false;
4877
+ }
4878
+ return a.types.every((aType, i) => this.compare(aType, b.types[i]));
4879
+ }
4880
+ compareUnions(a, b) {
4881
+ if (a.types.length !== b.types.length) {
4882
+ return false;
4883
+ }
4884
+ return a.types.every((aType) => b.types.some((bType) => this.compare(aType, bType)));
4885
+ }
4886
+ compareObjects(a, b) {
4887
+ if (a.objectFlags & b.objectFlags & this.#compiler.ObjectFlags.Reference) {
4888
+ const isSame = this.compareTypeReferences(a, b);
4889
+ if (isSame != null) {
4890
+ return isSame;
4891
+ }
4892
+ }
4893
+ return this.compareStructuredTypes(a, b);
4894
+ }
4895
+ compareTypeReferences(a, b) {
4896
+ if ((a.target.objectFlags | b.target.objectFlags) & this.#compiler.ObjectFlags.Tuple) {
4897
+ if (a.target.objectFlags & b.target.objectFlags & this.#compiler.ObjectFlags.Tuple) {
4898
+ return this.compareTuples(a, b);
4899
+ }
4900
+ return false;
4901
+ }
4902
+ if ((a.objectFlags | b.objectFlags) & this.#compiler.ObjectFlags.Class) {
4903
+ return this.compareStructuredTypes(a, b);
4904
+ }
4905
+ if (!this.#compareTypeOfSymbol(a.symbol, b.symbol)) {
4906
+ if (isSymbolFromDefaultLibrary(a.symbol, this.#program) || isSymbolFromDefaultLibrary(b.symbol, this.#program)) {
4907
+ return false;
4908
+ }
4909
+ return;
4910
+ }
4911
+ if (length(a.typeArguments) !== length(b.typeArguments)) {
4912
+ return false;
4913
+ }
4914
+ return ensureArray(a.typeArguments).every((type, i) => this.compare(type, ensureArray(b.typeArguments)[i]));
4915
+ }
4916
+ compareTuples(a, b) {
4917
+ if (a.target.readonly !== b.target.readonly) {
4918
+ return false;
4919
+ }
4920
+ const aTypeArguments = this.#typeChecker.getTypeArguments(a);
4921
+ const bTypeArguments = this.#typeChecker.getTypeArguments(b);
4922
+ if (length(aTypeArguments) !== length(bTypeArguments)) {
4923
+ return false;
4924
+ }
4925
+ for (let i = 0; i < aTypeArguments.length; i++) {
4926
+ if (a.target.elementFlags[i] !== b.target.elementFlags[i]) {
4927
+ return false;
4928
+ }
4929
+ if (!this.compare(aTypeArguments[i], bTypeArguments[i])) {
4930
+ return false;
4931
+ }
4932
+ }
4933
+ return true;
4934
+ }
4935
+ compareStructuredTypes(a, b) {
4936
+ if (!this.compareProperties(a, b)) {
4937
+ return false;
4938
+ }
4939
+ if (!this.compareSignatures(a, b, this.#compiler.SignatureKind.Call)) {
4940
+ return false;
4941
+ }
4942
+ if (!this.compareSignatures(a, b, this.#compiler.SignatureKind.Construct)) {
4943
+ return false;
4944
+ }
4945
+ if (!this.compareIndexSignatures(a, b)) {
4946
+ return false;
4947
+ }
4948
+ return true;
4949
+ }
4950
+ compareProperties(a, b) {
4951
+ const aProperties = this.#typeChecker.getPropertiesOfType(a);
4952
+ const bProperties = this.#typeChecker.getPropertiesOfType(b);
4953
+ if (aProperties.length !== bProperties.length) {
4954
+ return false;
4955
+ }
4956
+ for (const aProperty of aProperties) {
4957
+ const bProperty = bProperties.find((bProperty) => bProperty.escapedName === aProperty.escapedName);
4958
+ if (!bProperty) {
4959
+ return false;
4960
+ }
4961
+ if (aProperty === bProperty) {
4962
+ continue;
4963
+ }
4964
+ const aAccessibility = this.#compiler.getDeclarationModifierFlagsFromSymbol(aProperty) &
4965
+ this.#compiler.ModifierFlags.NonPublicAccessibilityModifier;
4966
+ const bAccessibility = this.#compiler.getDeclarationModifierFlagsFromSymbol(bProperty) &
4967
+ this.#compiler.ModifierFlags.NonPublicAccessibilityModifier;
4968
+ if (aAccessibility !== bAccessibility) {
4969
+ return false;
4970
+ }
4971
+ if (aAccessibility) {
4972
+ if (getTargetSymbol(aProperty, this.#compiler) !== getTargetSymbol(bProperty, this.#compiler)) {
4973
+ return false;
4974
+ }
4975
+ }
4976
+ if (isOptionalProperty(aProperty, this.#compiler) !== isOptionalProperty(bProperty, this.#compiler)) {
4977
+ return false;
4978
+ }
4979
+ if (isReadonlyProperty(aProperty, this.#compiler) !== isReadonlyProperty(bProperty, this.#compiler)) {
4980
+ return false;
4981
+ }
4982
+ const aType = getPropertyType(aProperty, this.#compiler, this.#compilerOptions, this.#typeChecker);
4983
+ const bType = getPropertyType(bProperty, this.#compiler, this.#compilerOptions, this.#typeChecker);
4984
+ if (!this.compare(aType, bType)) {
4985
+ return false;
4986
+ }
4987
+ }
4988
+ return true;
4989
+ }
4990
+ compareSignatures(a, b, kind) {
4991
+ const aSignatures = getSignatures(a, kind, this.#compiler, this.#typeChecker);
4992
+ const bSignatures = getSignatures(b, kind, this.#compiler, this.#typeChecker);
4993
+ if (aSignatures.length !== bSignatures.length) {
4994
+ return false;
4995
+ }
4996
+ for (let i = 0; i < aSignatures.length; i++) {
4997
+ if (!this.#compareSignature(aSignatures[i], bSignatures[i])) {
4998
+ return false;
4999
+ }
5000
+ }
5001
+ return true;
5002
+ }
5003
+ #compareSignature(a, b) {
5004
+ if (length(a.typeParameters) !== length(b.typeParameters)) {
5005
+ return false;
5006
+ }
5007
+ if (a.typeParameters != null && b.typeParameters != null) {
5008
+ for (let i = 0; i < a.typeParameters.length; i++) {
5009
+ if (!this.compareTypeParameters(a.typeParameters[i], b.typeParameters[i])) {
5010
+ return false;
5011
+ }
5012
+ }
5013
+ }
5014
+ if (!this.#compareTypeOfSymbol(a.thisParameter, b.thisParameter)) {
5015
+ return false;
5016
+ }
5017
+ if (!this.compareParameters(a, b)) {
5018
+ return false;
5019
+ }
5020
+ if (!this.compare(this.#typeChecker.getReturnTypeOfSignature(a), this.#typeChecker.getReturnTypeOfSignature(b))) {
5021
+ return false;
5022
+ }
5023
+ const aTypePredicate = this.#typeChecker.getTypePredicateOfSignature(a);
5024
+ const bTypePredicate = this.#typeChecker.getTypePredicateOfSignature(b);
5025
+ if (aTypePredicate?.kind !== bTypePredicate?.kind ||
5026
+ !this.#compareMaybeNullish(aTypePredicate?.type, bTypePredicate?.type)) {
5027
+ return false;
5028
+ }
5029
+ return true;
5030
+ }
5031
+ compareParameters(a, b) {
5032
+ const aParametersCount = getParameterCount(a, this.#compiler, this.#typeChecker);
5033
+ const bParametersCount = getParameterCount(b, this.#compiler, this.#typeChecker);
5034
+ if (aParametersCount !== bParametersCount) {
5035
+ return false;
5036
+ }
5037
+ for (let i = 0; i < aParametersCount; i++) {
5038
+ const aParameter = getParameterFacts(a, i, this.#compiler, this.#typeChecker);
5039
+ const bParameter = getParameterFacts(b, i, this.#compiler, this.#typeChecker);
5040
+ if (aParameter.isOptional !== bParameter.isOptional) {
5041
+ return false;
5042
+ }
5043
+ if (aParameter.isRest !== bParameter.isRest) {
5044
+ return false;
5045
+ }
5046
+ if (!this.compare(aParameter.getType(this.#typeChecker), bParameter.getType(this.#typeChecker))) {
5047
+ return false;
5048
+ }
5049
+ }
5050
+ return true;
5051
+ }
5052
+ compareIndexSignatures(a, b) {
5053
+ const aSignatures = getIndexSignatures(a, this.#compiler, this.#typeChecker);
5054
+ const bSignatures = getIndexSignatures(b, this.#compiler, this.#typeChecker);
5055
+ if (aSignatures.length !== bSignatures.length) {
5056
+ return false;
5057
+ }
5058
+ for (let i = 0; i < aSignatures.length; i++) {
5059
+ if (aSignatures[i].isReadonly !== bSignatures[i].isReadonly) {
5060
+ return false;
5061
+ }
5062
+ if (!this.compare(aSignatures[i].keyType, bSignatures[i].keyType)) {
5063
+ return false;
5064
+ }
5065
+ if (!this.compare(aSignatures[i].type, bSignatures[i].type)) {
5066
+ return false;
5067
+ }
5068
+ }
5069
+ return true;
5070
+ }
5071
+ compareTypeParameters(a, b) {
5072
+ if (getTypeParameterModifiers(a, this.#compiler) !== getTypeParameterModifiers(b, this.#compiler)) {
5073
+ return false;
5074
+ }
5075
+ if (!this.#compareMaybeNullish(this.#typeChecker.getBaseConstraintOfType(a), this.#typeChecker.getBaseConstraintOfType(b))) {
5076
+ return false;
5077
+ }
5078
+ if (!this.#compareMaybeNullish(this.#typeChecker.getDefaultFromTypeParameter(a), this.#typeChecker.getDefaultFromTypeParameter(b))) {
5079
+ return false;
5080
+ }
5081
+ return true;
5082
+ }
5083
+ compareIndexedAccessTypes(a, b) {
5084
+ if (!this.compare(a.objectType, b.objectType)) {
5085
+ return false;
5086
+ }
5087
+ if (!this.compare(a.indexType, b.indexType)) {
5088
+ return false;
5089
+ }
5090
+ return true;
5091
+ }
5092
+ compareConditionalTypes(a, b) {
5093
+ if (!this.compare(a.checkType, b.checkType)) {
5094
+ return false;
5095
+ }
5096
+ if (!this.compare(a.extendsType, b.extendsType)) {
5097
+ return false;
5098
+ }
5099
+ if (!this.compare(this.#typeChecker.getTypeAtLocation(a.root.node.trueType), this.#typeChecker.getTypeAtLocation(b.root.node.trueType))) {
5100
+ return false;
5101
+ }
5102
+ if (!this.compare(this.#typeChecker.getTypeAtLocation(a.root.node.falseType), this.#typeChecker.getTypeAtLocation(b.root.node.falseType))) {
5103
+ return false;
5104
+ }
5105
+ return true;
5106
+ }
5107
+ compareSubstitutionTypes(a, b) {
5108
+ if (!this.compare(a.baseType, b.baseType)) {
5109
+ return false;
5110
+ }
5111
+ if (!this.compare(a.constraint, b.constraint)) {
5112
+ return false;
5113
+ }
5114
+ return true;
5115
+ }
5116
+ #normalize(type) {
5117
+ if (type.flags & this.#compiler.TypeFlags.Freshable && type.freshType === type) {
5118
+ return type.regularType;
5119
+ }
5120
+ if (type.flags & this.#compiler.TypeFlags.Substitution &&
5121
+ type.constraint.flags & this.#compiler.TypeFlags.Unknown) {
5122
+ return type.baseType;
5123
+ }
5124
+ if (type.flags & this.#compiler.TypeFlags.UnionOrIntersection) {
5125
+ const candidateType = this.#normalize(type.types[0]);
5126
+ if (type.types.every((t) => this.compare(this.#normalize(t), candidateType))) {
5127
+ return candidateType;
5128
+ }
5129
+ }
5130
+ return type;
4639
5131
  }
4640
5132
  }
4641
5133
 
4642
5134
  class ToBe extends RelationMatcherBase {
5135
+ #structure;
5136
+ constructor(compiler, program) {
5137
+ super();
5138
+ this.#structure = new Structure(compiler, program);
5139
+ }
4643
5140
  explainText = ExpectDiagnosticText.isTheSame;
4644
5141
  explainNotText = ExpectDiagnosticText.isNotTheSame;
4645
5142
  match(matchWorker, sourceNode, targetNode) {
4646
5143
  return {
4647
5144
  explain: () => this.explain(matchWorker, sourceNode, targetNode),
4648
- isMatch: matchWorker.checkIsIdenticalTo(sourceNode, targetNode),
5145
+ isMatch: this.#structure.compare(matchWorker.getType(sourceNode), matchWorker.getType(targetNode)),
4649
5146
  };
4650
5147
  }
4651
5148
  }
@@ -4974,8 +5471,8 @@ class ToRaiseError {
4974
5471
 
4975
5472
  class ExpectService {
4976
5473
  #compiler;
5474
+ #program;
4977
5475
  #reject;
4978
- #typeChecker;
4979
5476
  toAcceptProps;
4980
5477
  toBe;
4981
5478
  toBeApplicable;
@@ -4985,12 +5482,12 @@ class ExpectService {
4985
5482
  toBeConstructableWith;
4986
5483
  toHaveProperty;
4987
5484
  toRaiseError;
4988
- constructor(compiler, typeChecker, reject) {
5485
+ constructor(compiler, program, reject, resolvedConfig) {
4989
5486
  this.#compiler = compiler;
5487
+ this.#program = program;
4990
5488
  this.#reject = reject;
4991
- this.#typeChecker = typeChecker;
4992
- this.toAcceptProps = new ToAcceptProps(compiler, typeChecker);
4993
- this.toBe = new ToBe();
5489
+ this.toAcceptProps = new ToAcceptProps(compiler, program);
5490
+ this.toBe = resolvedConfig.legacyToBe ? new LegacyToBe() : new ToBe(compiler, program);
4994
5491
  this.toBeApplicable = new ToBeApplicable(compiler);
4995
5492
  this.toBeAssignableFrom = new ToBeAssignableFrom();
4996
5493
  this.toBeAssignableTo = new ToBeAssignableTo();
@@ -5004,7 +5501,7 @@ class ExpectService {
5004
5501
  if (!argumentOrTypeArgumentIsProvided("source", "Source", assertionNode.source[0], assertionNode.node.expression, onDiagnostics)) {
5005
5502
  return;
5006
5503
  }
5007
- const matchWorker = new MatchWorker(this.#compiler, this.#typeChecker, assertionNode);
5504
+ const matchWorker = new MatchWorker(this.#compiler, this.#program, assertionNode);
5008
5505
  if (!(matcherNameText === "toRaiseError" && assertionNode.isNot === false) &&
5009
5506
  this.#reject.argumentType([
5010
5507
  ["source", assertionNode.source[0]],
@@ -5068,9 +5565,9 @@ class Reject {
5068
5565
  #compiler;
5069
5566
  #rejectedArgumentTypes = new Set();
5070
5567
  #typeChecker;
5071
- constructor(compiler, typeChecker, resolvedConfig) {
5568
+ constructor(compiler, program, resolvedConfig) {
5072
5569
  this.#compiler = compiler;
5073
- this.#typeChecker = typeChecker;
5570
+ this.#typeChecker = program.getTypeChecker();
5074
5571
  if (resolvedConfig?.rejectAnyType) {
5075
5572
  this.#rejectedArgumentTypes.add("any");
5076
5573
  }
@@ -5227,15 +5724,15 @@ class TestTreeWalker {
5227
5724
  #position;
5228
5725
  #resolvedConfig;
5229
5726
  #whenService;
5230
- constructor(compiler, typeChecker, resolvedConfig, onFileDiagnostics, options) {
5727
+ constructor(compiler, program, resolvedConfig, onFileDiagnostics, options) {
5231
5728
  this.#compiler = compiler;
5232
5729
  this.#resolvedConfig = resolvedConfig;
5233
5730
  this.#onFileDiagnostics = onFileDiagnostics;
5234
5731
  this.#cancellationToken = options.cancellationToken;
5235
5732
  this.#hasOnly = options.hasOnly || resolvedConfig.only != null || options.position != null;
5236
5733
  this.#position = options.position;
5237
- const reject = new Reject(compiler, typeChecker, resolvedConfig);
5238
- this.#expectService = new ExpectService(compiler, typeChecker, reject);
5734
+ const reject = new Reject(compiler, program, resolvedConfig);
5735
+ this.#expectService = new ExpectService(compiler, program, reject, resolvedConfig);
5239
5736
  this.#whenService = new WhenService(reject, onFileDiagnostics);
5240
5737
  }
5241
5738
  async #resolveRunMode(flags, node) {
@@ -5425,9 +5922,8 @@ class FileRunner {
5425
5922
  }
5426
5923
  const semanticDiagnostics = languageService?.getSemanticDiagnostics(file.path);
5427
5924
  const program = languageService?.getProgram();
5428
- const typeChecker = program?.getTypeChecker();
5429
5925
  const sourceFile = program?.getSourceFile(file.path);
5430
- if (!sourceFile) {
5926
+ if (!program || !sourceFile) {
5431
5927
  return;
5432
5928
  }
5433
5929
  const directiveRanges = Directive.getDirectiveRanges(this.#compiler, sourceFile);
@@ -5451,7 +5947,7 @@ class FileRunner {
5451
5947
  }
5452
5948
  const testTree = this.#collectService.createTestTree(sourceFile, semanticDiagnostics);
5453
5949
  this.#suppressedService.match(testTree);
5454
- return { runModeFlags, testTree, typeChecker };
5950
+ return { runModeFlags, testTree, program };
5455
5951
  }
5456
5952
  async #run(file, fileResult, cancellationToken) {
5457
5953
  if (!existsSync(file.path)) {
@@ -5469,7 +5965,7 @@ class FileRunner {
5469
5965
  const onFileDiagnostics = (diagnostics) => {
5470
5966
  this.#onDiagnostics(diagnostics, fileResult);
5471
5967
  };
5472
- const testTreeWalker = new TestTreeWalker(this.#compiler, facts.typeChecker, this.#resolvedConfig, onFileDiagnostics, {
5968
+ const testTreeWalker = new TestTreeWalker(this.#compiler, facts.program, this.#resolvedConfig, onFileDiagnostics, {
5473
5969
  cancellationToken,
5474
5970
  hasOnly: facts.testTree.hasOnly,
5475
5971
  position: file.position,
@@ -5481,7 +5977,7 @@ class FileRunner {
5481
5977
  class Runner {
5482
5978
  #eventEmitter = new EventEmitter();
5483
5979
  #resolvedConfig;
5484
- static version = "5.0.2";
5980
+ static version = "6.0.0-beta.1";
5485
5981
  constructor(resolvedConfig) {
5486
5982
  this.#resolvedConfig = resolvedConfig;
5487
5983
  }
@@ -5538,7 +6034,7 @@ class Runner {
5538
6034
  for (const target of this.#resolvedConfig.target) {
5539
6035
  const targetResult = new TargetResult(target, files);
5540
6036
  EventEmitter.dispatch(["target:start", { result: targetResult }]);
5541
- const compiler = await Store.load(target);
6037
+ const compiler = await Store.load(target, { notPatched: !this.#resolvedConfig.legacyToBe });
5542
6038
  if (compiler) {
5543
6039
  const fileRunner = new FileRunner(compiler, this.#resolvedConfig);
5544
6040
  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.1",
4
4
  "description": "Everything You Need for Type Testing.",
5
5
  "keywords": [
6
6
  "typescript",