@formspec/build 0.1.0-alpha.58 → 0.1.0-alpha.61

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.
Files changed (51) hide show
  1. package/dist/analyzer/builtin-brands.d.ts +10 -7
  2. package/dist/analyzer/builtin-brands.d.ts.map +1 -1
  3. package/dist/analyzer/class-analyzer.d.ts +30 -1
  4. package/dist/analyzer/class-analyzer.d.ts.map +1 -1
  5. package/dist/analyzer/jsdoc-constraints.d.ts +0 -6
  6. package/dist/analyzer/jsdoc-constraints.d.ts.map +1 -1
  7. package/dist/analyzer/tsdoc-parser.d.ts +2 -5
  8. package/dist/analyzer/tsdoc-parser.d.ts.map +1 -1
  9. package/dist/browser.cjs +127 -32
  10. package/dist/browser.cjs.map +1 -1
  11. package/dist/browser.js +130 -33
  12. package/dist/browser.js.map +1 -1
  13. package/dist/build-alpha.d.ts +432 -12
  14. package/dist/build-beta.d.ts +400 -12
  15. package/dist/build-internal.d.ts +463 -12
  16. package/dist/build.d.ts +400 -12
  17. package/dist/canonicalize/chain-dsl-canonicalizer.d.ts +2 -1
  18. package/dist/canonicalize/chain-dsl-canonicalizer.d.ts.map +1 -1
  19. package/dist/canonicalize/tsdoc-canonicalizer.d.ts +2 -1
  20. package/dist/canonicalize/tsdoc-canonicalizer.d.ts.map +1 -1
  21. package/dist/cli.cjs +610 -629
  22. package/dist/cli.cjs.map +1 -1
  23. package/dist/cli.js +573 -586
  24. package/dist/cli.js.map +1 -1
  25. package/dist/extensions/registry.d.ts +19 -1
  26. package/dist/extensions/registry.d.ts.map +1 -1
  27. package/dist/extensions/resolve-custom-type.d.ts.map +1 -1
  28. package/dist/extensions/ts-type-utils.d.ts +0 -11
  29. package/dist/extensions/ts-type-utils.d.ts.map +1 -1
  30. package/dist/generators/class-schema.d.ts.map +1 -1
  31. package/dist/generators/method-schema.d.ts +3 -2
  32. package/dist/generators/method-schema.d.ts.map +1 -1
  33. package/dist/index.cjs +600 -618
  34. package/dist/index.cjs.map +1 -1
  35. package/dist/index.d.ts +12 -0
  36. package/dist/index.d.ts.map +1 -1
  37. package/dist/index.js +571 -583
  38. package/dist/index.js.map +1 -1
  39. package/dist/internals.cjs +573 -591
  40. package/dist/internals.cjs.map +1 -1
  41. package/dist/internals.js +540 -552
  42. package/dist/internals.js.map +1 -1
  43. package/dist/metadata/index.d.ts +1 -4
  44. package/dist/metadata/index.d.ts.map +1 -1
  45. package/dist/metadata/policy.d.ts +2 -6
  46. package/dist/metadata/policy.d.ts.map +1 -1
  47. package/dist/metadata/resolve.d.ts +3 -2
  48. package/dist/metadata/resolve.d.ts.map +1 -1
  49. package/dist/ui-schema/schema.d.ts +11 -28
  50. package/dist/ui-schema/schema.d.ts.map +1 -1
  51. package/package.json +7 -7
package/dist/internals.js CHANGED
@@ -791,25 +791,27 @@ function wrapInConditional(field, layout, provenance) {
791
791
  }
792
792
 
793
793
  // src/analyzer/program.ts
794
- import * as ts7 from "typescript";
794
+ import * as ts6 from "typescript";
795
795
  import * as path from "path";
796
796
 
797
797
  // src/analyzer/class-analyzer.ts
798
- import * as ts6 from "typescript";
798
+ import * as ts5 from "typescript";
799
799
  import {
800
800
  analyzeMetadataForNodeWithChecker,
801
801
  parseCommentBlock
802
802
  } from "@formspec/analysis/internal";
803
803
 
804
804
  // src/analyzer/jsdoc-constraints.ts
805
- import * as ts5 from "typescript";
805
+ import * as ts4 from "typescript";
806
806
 
807
807
  // src/analyzer/tsdoc-parser.ts
808
- import * as ts4 from "typescript";
808
+ import * as ts3 from "typescript";
809
809
  import {
810
- checkSyntheticTagApplication,
810
+ _capabilityLabel,
811
+ _supportsConstraintCapability,
811
812
  choosePreferredPayloadText,
812
813
  extractPathTarget as extractSharedPathTarget,
814
+ getBroadenedCustomTypeId,
813
815
  getTagDefinition,
814
816
  hasTypeSemanticCapability,
815
817
  normalizeFormSpecTagName,
@@ -832,25 +834,10 @@ import { noopLogger } from "@formspec/core";
832
834
 
833
835
  // src/extensions/resolve-custom-type.ts
834
836
  import * as ts2 from "typescript";
835
- import { stripNullishUnion } from "@formspec/analysis/internal";
837
+ import { _collectBrandIdentifiers, stripNullishUnion } from "@formspec/analysis/internal";
836
838
 
837
839
  // src/extensions/ts-type-utils.ts
838
840
  import * as ts from "typescript";
839
- function collectBrandIdentifiers(type) {
840
- if (!type.isIntersection()) {
841
- return [];
842
- }
843
- const brands = [];
844
- for (const prop of type.getProperties()) {
845
- const decl = prop.valueDeclaration ?? prop.declarations?.[0];
846
- if (decl === void 0) continue;
847
- if (!ts.isPropertySignature(decl) && !ts.isPropertyDeclaration(decl)) continue;
848
- if (!ts.isComputedPropertyName(decl.name)) continue;
849
- if (!ts.isIdentifier(decl.name.expression)) continue;
850
- brands.push(decl.name.expression.text);
851
- }
852
- return brands;
853
- }
854
841
  function resolveCanonicalSymbol(type, checker) {
855
842
  const raw = type.aliasSymbol ?? type.getSymbol();
856
843
  if (raw === void 0) return void 0;
@@ -935,7 +922,7 @@ function resolveCustomTypeFromTsType(type, checker, registry, sourceNode) {
935
922
  return bySymbol;
936
923
  }
937
924
  }
938
- for (const brand of collectBrandIdentifiers(stripped)) {
925
+ for (const brand of _collectBrandIdentifiers(stripped)) {
939
926
  const byBrand = registry.findTypeByBrand(brand);
940
927
  if (byBrand !== void 0) {
941
928
  return byBrand;
@@ -948,171 +935,51 @@ function customTypeIdFromLookup(result) {
948
935
  }
949
936
 
950
937
  // src/analyzer/builtin-brands.ts
951
- import * as ts3 from "typescript";
952
- function isIntegerBrandedType(type) {
953
- if (!type.isIntersection()) return false;
954
- if (!type.types.some((member) => !!(member.flags & ts3.TypeFlags.Number))) return false;
955
- return collectBrandIdentifiers(type).includes("__integerBrand");
956
- }
938
+ import { _isIntegerBrandedType } from "@formspec/analysis/internal";
957
939
 
958
940
  // src/analyzer/tsdoc-parser.ts
959
941
  import {
942
+ _emitSetupDiagnostics,
960
943
  getBuildLogger,
961
944
  getBroadeningLogger,
962
- getSyntheticLogger,
963
945
  getTypedParserLogger,
946
+ extractEffectiveArgumentText,
947
+ mapTypedParserDiagnosticCode,
964
948
  parseTagArgument,
965
949
  describeTypeKind,
966
950
  elapsedMicros,
967
951
  nowMicros,
968
952
  logTagApplication
969
953
  } from "@formspec/analysis/internal";
970
- function sharedTagValueOptions(options) {
954
+ function sharedTagValueOptions(options, pathResolvedCustomTypeId) {
971
955
  return {
972
956
  ...options?.extensionRegistry !== void 0 ? { registry: options.extensionRegistry } : {},
973
- ...options?.fieldType !== void 0 ? { fieldType: options.fieldType } : {}
974
- };
975
- }
976
- var SYNTHETIC_TYPE_FORMAT_FLAGS = ts4.TypeFormatFlags.NoTruncation | ts4.TypeFormatFlags.UseAliasDefinedOutsideCurrentScope;
977
- function getExtensionTypeNames(registry) {
978
- if (registry === void 0) {
979
- return /* @__PURE__ */ new Set();
980
- }
981
- return new Set(
982
- registry.extensions.flatMap(
983
- (ext) => (ext.types ?? []).flatMap((t) => t.tsTypeNames ?? [t.typeName])
984
- )
985
- );
986
- }
987
- function collectImportedNames(sourceFile) {
988
- const importedNames = /* @__PURE__ */ new Set();
989
- for (const statement of sourceFile.statements) {
990
- if (ts4.isImportDeclaration(statement) && statement.importClause !== void 0) {
991
- const clause = statement.importClause;
992
- if (clause.name !== void 0) {
993
- importedNames.add(clause.name.text);
994
- }
995
- if (clause.namedBindings !== void 0) {
996
- if (ts4.isNamedImports(clause.namedBindings)) {
997
- for (const specifier of clause.namedBindings.elements) {
998
- importedNames.add(specifier.name.text);
999
- }
1000
- } else if (ts4.isNamespaceImport(clause.namedBindings)) {
1001
- importedNames.add(clause.namedBindings.name.text);
1002
- }
1003
- }
1004
- continue;
1005
- }
1006
- if (ts4.isImportEqualsDeclaration(statement)) {
1007
- importedNames.add(statement.name.text);
1008
- }
1009
- }
1010
- return importedNames;
1011
- }
1012
- function isNonReferenceIdentifier(node) {
1013
- const parent = node.parent;
1014
- if ((ts4.isBindingElement(parent) || ts4.isClassDeclaration(parent) || ts4.isEnumDeclaration(parent) || ts4.isEnumMember(parent) || ts4.isFunctionDeclaration(parent) || ts4.isFunctionExpression(parent) || ts4.isImportClause(parent) || ts4.isImportEqualsDeclaration(parent) || ts4.isImportSpecifier(parent) || ts4.isInterfaceDeclaration(parent) || ts4.isMethodDeclaration(parent) || ts4.isMethodSignature(parent) || ts4.isModuleDeclaration(parent) || ts4.isNamespaceExport(parent) || ts4.isNamespaceImport(parent) || ts4.isParameter(parent) || ts4.isPropertyDeclaration(parent) || ts4.isPropertySignature(parent) || ts4.isSetAccessorDeclaration(parent) || ts4.isGetAccessorDeclaration(parent) || ts4.isTypeAliasDeclaration(parent) || ts4.isTypeParameterDeclaration(parent) || ts4.isVariableDeclaration(parent)) && parent.name === node) {
1015
- return true;
1016
- }
1017
- if ((ts4.isPropertyAssignment(parent) || ts4.isPropertyAccessExpression(parent)) && parent.name === node) {
1018
- return true;
1019
- }
1020
- if (ts4.isQualifiedName(parent) && parent.right === node) {
1021
- return true;
1022
- }
1023
- return false;
1024
- }
1025
- function astReferencesImportedName(root, importedNames) {
1026
- if (importedNames.size === 0) {
1027
- return false;
1028
- }
1029
- let found = false;
1030
- const visit = (node) => {
1031
- if (found) return;
1032
- if (ts4.isIdentifier(node) && importedNames.has(node.text) && !isNonReferenceIdentifier(node)) {
1033
- found = true;
1034
- return;
1035
- }
1036
- ts4.forEachChild(node, visit);
957
+ ...options?.fieldType !== void 0 ? { fieldType: options.fieldType } : {},
958
+ ...pathResolvedCustomTypeId !== void 0 ? { pathResolvedCustomTypeId } : {}
1037
959
  };
1038
- visit(root);
1039
- return found;
1040
960
  }
1041
- function getObjectMembers(statement) {
1042
- if (ts4.isInterfaceDeclaration(statement)) {
1043
- return statement.members;
1044
- }
1045
- if (ts4.isTypeLiteralNode(statement.type)) {
1046
- return statement.type.members;
1047
- }
1048
- return void 0;
961
+ function customTypeIdForResolvedType(resolvedType, checker, registry) {
962
+ if (registry === void 0) return void 0;
963
+ const lookup = resolveCustomTypeFromTsType(resolvedType, checker, registry);
964
+ return lookup === null ? void 0 : customTypeIdFromLookup(lookup);
1049
965
  }
1050
- function rewriteImportedMemberTypes(statement, sourceFile, importedNames) {
1051
- const members = getObjectMembers(statement);
1052
- if (members === void 0) {
1053
- return null;
1054
- }
1055
- const replacements = [];
1056
- for (const member of members) {
1057
- if (!ts4.isPropertySignature(member)) {
1058
- if (astReferencesImportedName(member, importedNames)) {
1059
- return null;
1060
- }
1061
- continue;
1062
- }
1063
- const typeAnnotation = member.type;
1064
- if (typeAnnotation === void 0) continue;
1065
- if (astReferencesImportedName(typeAnnotation, importedNames)) {
1066
- replacements.push({
1067
- start: typeAnnotation.getStart(sourceFile),
1068
- end: typeAnnotation.getEnd()
1069
- });
1070
- }
1071
- }
1072
- if (replacements.length === 0) {
1073
- return statement.getText(sourceFile);
1074
- }
1075
- const stmtStart = statement.getStart(sourceFile);
1076
- let result = statement.getText(sourceFile);
1077
- for (const { start, end } of [...replacements].reverse()) {
1078
- result = result.slice(0, start - stmtStart) + "unknown" + result.slice(end - stmtStart);
966
+ function resolvePathTargetCustomTypeId(parsedTag, subjectType, checker, registry) {
967
+ if (parsedTag === null) return void 0;
968
+ const target = parsedTag.target;
969
+ if (target?.kind !== "path" || !target.valid || target.path === null) {
970
+ return void 0;
1079
971
  }
1080
- return result;
1081
- }
1082
- function buildSupportingDeclarations(sourceFile, extensionTypeNames) {
1083
- const importedNames = collectImportedNames(sourceFile);
1084
- const importedNamesToSkip = new Set(
1085
- [...importedNames].filter((name) => !extensionTypeNames.has(name))
1086
- );
1087
- const result = [];
1088
- for (const statement of sourceFile.statements) {
1089
- if (ts4.isImportDeclaration(statement)) continue;
1090
- if (ts4.isImportEqualsDeclaration(statement)) continue;
1091
- if (ts4.isExportDeclaration(statement) && statement.moduleSpecifier !== void 0) continue;
1092
- if (!astReferencesImportedName(statement, importedNamesToSkip)) {
1093
- result.push(statement.getText(sourceFile));
1094
- continue;
1095
- }
1096
- if (ts4.isInterfaceDeclaration(statement) || ts4.isTypeAliasDeclaration(statement)) {
1097
- const rewritten = rewriteImportedMemberTypes(statement, sourceFile, importedNamesToSkip);
1098
- if (rewritten !== null) {
1099
- result.push(rewritten);
1100
- }
1101
- }
972
+ if (subjectType === void 0 || checker === void 0) {
973
+ return void 0;
1102
974
  }
1103
- return result;
1104
- }
1105
- function pushUniqueCompilerDiagnostics(target, additions) {
1106
- for (const diagnostic of additions) {
1107
- if ((diagnostic.code === "UNSUPPORTED_CUSTOM_TYPE_OVERRIDE" || diagnostic.code === "SYNTHETIC_SETUP_FAILURE") && target.some(
1108
- (existing) => existing.code === diagnostic.code && existing.message === diagnostic.message
1109
- )) {
1110
- continue;
1111
- }
1112
- target.push(diagnostic);
975
+ const resolution = resolvePathTargetType(subjectType, checker, target.path.segments);
976
+ if (resolution.kind !== "resolved") {
977
+ return void 0;
1113
978
  }
979
+ return customTypeIdForResolvedType(resolution.type, checker, registry);
1114
980
  }
1115
- function processConstraintTag(tagName, text, parsedTag, provenance, node, sourceFile, supportingDeclarations, options, constraints, diagnostics) {
981
+ var TYPE_FORMAT_FLAGS = ts3.TypeFormatFlags.NoTruncation | ts3.TypeFormatFlags.UseAliasDefinedOutsideCurrentScope;
982
+ function processConstraintTag(tagName, text, parsedTag, provenance, node, sourceFile, options, constraints, diagnostics) {
1116
983
  const compilerDiagnostics = buildCompilerBackedConstraintDiagnostics(
1117
984
  node,
1118
985
  sourceFile,
@@ -1120,74 +987,30 @@ function processConstraintTag(tagName, text, parsedTag, provenance, node, source
1120
987
  parsedTag,
1121
988
  text,
1122
989
  provenance,
1123
- supportingDeclarations,
1124
990
  options
1125
991
  );
1126
992
  if (compilerDiagnostics.length > 0) {
1127
- pushUniqueCompilerDiagnostics(diagnostics, compilerDiagnostics);
993
+ diagnostics.push(...compilerDiagnostics);
1128
994
  return;
1129
995
  }
996
+ const pathResolvedCustomTypeId = resolvePathTargetCustomTypeId(
997
+ parsedTag,
998
+ options?.subjectType,
999
+ options?.checker,
1000
+ options?.extensionRegistry
1001
+ );
1130
1002
  const constraintNode = parseConstraintTagValue(
1131
1003
  tagName,
1132
1004
  text,
1133
1005
  provenance,
1134
- sharedTagValueOptions(options)
1006
+ sharedTagValueOptions(options, pathResolvedCustomTypeId)
1135
1007
  );
1136
1008
  if (constraintNode) {
1137
1009
  constraints.push(constraintNode);
1138
1010
  }
1139
1011
  }
1140
- function renderSyntheticArgumentExpression(valueKind, argumentText) {
1141
- const trimmed = argumentText.trim();
1142
- if (trimmed === "") {
1143
- return null;
1144
- }
1145
- switch (valueKind) {
1146
- case "number":
1147
- case "integer":
1148
- case "signedInteger":
1149
- if (trimmed === "Infinity" || trimmed === "-Infinity" || trimmed === "NaN") {
1150
- return trimmed;
1151
- }
1152
- return Number.isFinite(Number(trimmed)) ? trimmed : JSON.stringify(trimmed);
1153
- case "string":
1154
- return JSON.stringify(argumentText);
1155
- case "json":
1156
- try {
1157
- JSON.parse(trimmed);
1158
- return `(${trimmed})`;
1159
- } catch {
1160
- return JSON.stringify(trimmed);
1161
- }
1162
- case "boolean":
1163
- return trimmed === "true" || trimmed === "false" ? trimmed : JSON.stringify(trimmed);
1164
- case "condition":
1165
- return "undefined as unknown as FormSpecCondition";
1166
- case null:
1167
- return null;
1168
- default: {
1169
- return String(valueKind);
1170
- }
1171
- }
1172
- }
1173
- function getArrayElementType(type, checker) {
1174
- if (!checker.isArrayType(type)) {
1175
- return null;
1176
- }
1177
- return checker.getTypeArguments(type)[0] ?? null;
1178
- }
1179
1012
  function supportsConstraintCapability(type, checker, capability) {
1180
- if (capability === void 0) {
1181
- return true;
1182
- }
1183
- if (hasTypeSemanticCapability(type, checker, capability)) {
1184
- return true;
1185
- }
1186
- if (capability === "string-like") {
1187
- const itemType = getArrayElementType(type, checker);
1188
- return itemType !== null && hasTypeSemanticCapability(itemType, checker, capability);
1189
- }
1190
- return false;
1013
+ return _supportsConstraintCapability(capability, type, checker);
1191
1014
  }
1192
1015
  var MAX_HINT_CANDIDATES = 5;
1193
1016
  var MAX_HINT_DEPTH = 3;
@@ -1196,7 +1019,7 @@ function stripHintNullishUnion(type) {
1196
1019
  return type;
1197
1020
  }
1198
1021
  const nonNullish = type.types.filter(
1199
- (member) => (member.flags & (ts4.TypeFlags.Null | ts4.TypeFlags.Undefined)) === 0
1022
+ (member) => (member.flags & (ts3.TypeFlags.Null | ts3.TypeFlags.Undefined)) === 0
1200
1023
  );
1201
1024
  if (nonNullish.length === 1 && nonNullish[0] !== void 0) {
1202
1025
  return nonNullish[0];
@@ -1212,10 +1035,10 @@ function isUserEmittableHintProperty(property, declaration) {
1212
1035
  }
1213
1036
  if ("name" in declaration && declaration.name !== void 0) {
1214
1037
  const name = declaration.name;
1215
- if (ts4.isComputedPropertyName(name) || ts4.isPrivateIdentifier(name)) {
1038
+ if (ts3.isComputedPropertyName(name) || ts3.isPrivateIdentifier(name)) {
1216
1039
  return false;
1217
1040
  }
1218
- if (!ts4.isIdentifier(name) && !ts4.isStringLiteral(name) && !ts4.isNumericLiteral(name)) {
1041
+ if (!ts3.isIdentifier(name) && !ts3.isStringLiteral(name) && !ts3.isNumericLiteral(name)) {
1219
1042
  return false;
1220
1043
  }
1221
1044
  }
@@ -1314,53 +1137,11 @@ function placementLabel(placement) {
1314
1137
  }
1315
1138
  }
1316
1139
  }
1317
- function capabilityLabel(capability) {
1318
- switch (capability) {
1319
- case "numeric-comparable":
1320
- return "number";
1321
- case "string-like":
1322
- return "string";
1323
- case "array-like":
1324
- return "array";
1325
- case "enum-member-addressable":
1326
- return "enum";
1327
- case "json-like":
1328
- return "JSON-compatible";
1329
- case "object-like":
1330
- return "object";
1331
- case "condition-like":
1332
- return "conditional";
1333
- case void 0:
1334
- return "compatible";
1335
- default:
1336
- return capability;
1337
- }
1338
- }
1339
- function getBroadenedCustomTypeId(fieldType) {
1340
- if (fieldType?.kind === "custom") {
1341
- return fieldType.typeId;
1342
- }
1343
- if (fieldType?.kind !== "union") {
1344
- return void 0;
1345
- }
1346
- const customMembers = fieldType.members.filter(
1347
- (member) => member.kind === "custom"
1348
- );
1349
- if (customMembers.length !== 1) {
1350
- return void 0;
1351
- }
1352
- const nonCustomMembers = fieldType.members.filter((member) => member.kind !== "custom");
1353
- const allOtherMembersAreNull = nonCustomMembers.every(
1354
- (member) => member.kind === "primitive" && member.primitiveKind === "null"
1355
- );
1356
- const customMember = customMembers[0];
1357
- return allOtherMembersAreNull && customMember !== void 0 ? customMember.typeId : void 0;
1358
- }
1359
1140
  function hasBuiltinConstraintBroadening(tagName, options) {
1360
1141
  const broadenedTypeId = getBroadenedCustomTypeId(options?.fieldType);
1361
1142
  return broadenedTypeId !== void 0 && options?.extensionRegistry?.findBuiltinConstraintBroadening(broadenedTypeId, tagName) !== void 0;
1362
1143
  }
1363
- function buildCompilerBackedConstraintDiagnostics(node, sourceFile, tagName, parsedTag, rawText, provenance, supportingDeclarations, options) {
1144
+ function buildCompilerBackedConstraintDiagnostics(node, sourceFile, tagName, parsedTag, rawText, provenance, options) {
1364
1145
  if (!isBuiltinConstraintName(tagName)) {
1365
1146
  return [];
1366
1147
  }
@@ -1380,16 +1161,14 @@ function buildCompilerBackedConstraintDiagnostics(node, sourceFile, tagName, par
1380
1161
  const nonNullPlacement = placement;
1381
1162
  const log = getBuildLogger();
1382
1163
  const broadeningLog = getBroadeningLogger();
1383
- const syntheticLog = getSyntheticLogger();
1384
1164
  const typedParserLog = getTypedParserLogger();
1385
1165
  const logsEnabled = log !== noopLogger || broadeningLog !== noopLogger;
1386
- const syntheticTraceEnabled = syntheticLog !== noopLogger;
1387
1166
  const typedParserTraceEnabled = typedParserLog !== noopLogger;
1388
1167
  const logStart = logsEnabled ? nowMicros() : 0;
1389
1168
  const subjectTypeKind = logsEnabled ? describeTypeKind(subjectType, checker) : "";
1390
- function emit(outcome, result2) {
1169
+ function emit(outcome, result) {
1391
1170
  if (!logsEnabled) {
1392
- return result2;
1171
+ return result;
1393
1172
  }
1394
1173
  const entry = {
1395
1174
  consumer: "build",
@@ -1403,7 +1182,7 @@ function buildCompilerBackedConstraintDiagnostics(node, sourceFile, tagName, par
1403
1182
  if (outcome === "bypass" || outcome === "D1" || outcome === "D2") {
1404
1183
  logTagApplication(broadeningLog, entry);
1405
1184
  }
1406
- return result2;
1185
+ return result;
1407
1186
  }
1408
1187
  if (!definition.placements.includes(placement)) {
1409
1188
  return emit("A-reject", [
@@ -1447,7 +1226,7 @@ function buildCompilerBackedConstraintDiagnostics(node, sourceFile, tagName, par
1447
1226
  ]);
1448
1227
  }
1449
1228
  if (resolution.kind === "unresolvable") {
1450
- const actualType = checker.typeToString(resolution.type, node, SYNTHETIC_TYPE_FORMAT_FLAGS);
1229
+ const actualType = checker.typeToString(resolution.type, node, TYPE_FORMAT_FLAGS);
1451
1230
  return emit("B-reject", [
1452
1231
  makeDiagnostic(
1453
1232
  "TYPE_MISMATCH",
@@ -1461,21 +1240,21 @@ function buildCompilerBackedConstraintDiagnostics(node, sourceFile, tagName, par
1461
1240
  }
1462
1241
  const hasBroadening = (() => {
1463
1242
  if (target === null) {
1464
- if (isIntegerBrandedType(stripNullishUnion2(subjectType)) && definition.capabilities.includes("numeric-comparable")) {
1243
+ if (_isIntegerBrandedType(stripNullishUnion2(subjectType)) && definition.capabilities[0] === "numeric-comparable") {
1465
1244
  return true;
1466
1245
  }
1467
1246
  return hasBuiltinConstraintBroadening(tagName, options);
1468
1247
  }
1469
1248
  const registry = options?.extensionRegistry;
1470
1249
  if (registry === void 0) return false;
1471
- const resolved = resolveCustomTypeFromTsType(evaluatedType, checker, registry);
1472
- return resolved !== null && registry.findBuiltinConstraintBroadening(customTypeIdFromLookup(resolved), tagName) !== void 0;
1250
+ const typeId = customTypeIdForResolvedType(evaluatedType, checker, registry);
1251
+ return typeId !== void 0 && registry.findBuiltinConstraintBroadening(typeId, tagName) !== void 0;
1473
1252
  })();
1474
1253
  if (!hasBroadening) {
1475
1254
  const requiredCapability = definition.capabilities[0];
1476
1255
  if (requiredCapability !== void 0 && !supportsConstraintCapability(evaluatedType, checker, requiredCapability)) {
1477
- const actualType = checker.typeToString(evaluatedType, node, SYNTHETIC_TYPE_FORMAT_FLAGS);
1478
- const baseMessage = `Target "${targetLabel}": constraint "${tagName}" is only valid on ${capabilityLabel(requiredCapability)} targets, but field type is "${actualType}"`;
1256
+ const actualType = checker.typeToString(evaluatedType, node, TYPE_FORMAT_FLAGS);
1257
+ const baseMessage = `Target "${targetLabel}": constraint "${tagName}" is only valid on ${_capabilityLabel(requiredCapability)} targets, but field type is "${actualType}"`;
1479
1258
  const hint = target === null ? buildPathTargetHint(
1480
1259
  subjectType,
1481
1260
  checker,
@@ -1492,10 +1271,10 @@ function buildCompilerBackedConstraintDiagnostics(node, sourceFile, tagName, par
1492
1271
  ]);
1493
1272
  }
1494
1273
  }
1495
- const effectiveArgumentText = parsedTag !== null ? parseTagSyntax(tagName, rawText).argumentText : rawText;
1496
1274
  if (hasBroadening) {
1497
1275
  return emit("bypass", []);
1498
1276
  }
1277
+ const effectiveArgumentText = extractEffectiveArgumentText(tagName, rawText, parsedTag);
1499
1278
  const typedParseResult = parseTagArgument(tagName, effectiveArgumentText, "build");
1500
1279
  if (!typedParseResult.ok) {
1501
1280
  if (typedParserTraceEnabled) {
@@ -1508,23 +1287,7 @@ function buildCompilerBackedConstraintDiagnostics(node, sourceFile, tagName, par
1508
1287
  diagnosticCode: typedParseResult.diagnostic.code
1509
1288
  });
1510
1289
  }
1511
- let mappedCode;
1512
- switch (typedParseResult.diagnostic.code) {
1513
- case "MISSING_TAG_ARGUMENT":
1514
- mappedCode = "MISSING_TAG_ARGUMENT";
1515
- break;
1516
- case "INVALID_TAG_ARGUMENT":
1517
- mappedCode = "INVALID_TAG_ARGUMENT";
1518
- break;
1519
- case "UNKNOWN_TAG":
1520
- throw new Error(
1521
- `Unexpected UNKNOWN_TAG from parseTagArgument("${tagName}") \u2014 tag was resolved via getTagDefinition.`
1522
- );
1523
- default: {
1524
- const _exhaustive = typedParseResult.diagnostic.code;
1525
- throw new Error(`Unknown diagnostic code: ${String(_exhaustive)}`);
1526
- }
1527
- }
1290
+ const mappedCode = mapTypedParserDiagnosticCode(typedParseResult.diagnostic.code, tagName);
1528
1291
  return emit("C-reject", [
1529
1292
  makeDiagnostic(mappedCode, typedParseResult.diagnostic.message, provenance)
1530
1293
  ]);
@@ -1539,68 +1302,7 @@ function buildCompilerBackedConstraintDiagnostics(node, sourceFile, tagName, par
1539
1302
  valueKind: typedParseResult.value.kind
1540
1303
  });
1541
1304
  }
1542
- const argumentExpression = renderSyntheticArgumentExpression(
1543
- definition.valueKind,
1544
- effectiveArgumentText
1545
- );
1546
- const subjectTypeText = checker.typeToString(subjectType, node, SYNTHETIC_TYPE_FORMAT_FLAGS);
1547
- const hostType = options?.hostType ?? subjectType;
1548
- const hostTypeText = checker.typeToString(hostType, node, SYNTHETIC_TYPE_FORMAT_FLAGS);
1549
- if (syntheticTraceEnabled) {
1550
- syntheticLog.trace("invoking synthetic checker", {
1551
- consumer: "build",
1552
- tag: tagName,
1553
- placement,
1554
- subjectTypeKind,
1555
- subjectTypeText
1556
- });
1557
- }
1558
- const result = checkSyntheticTagApplication({
1559
- tagName,
1560
- placement,
1561
- hostType: hostTypeText,
1562
- subjectType: subjectTypeText,
1563
- ...target?.kind === "path" ? { target: { kind: "path", text: target.rawText } } : {},
1564
- ...argumentExpression !== null ? { argumentExpression } : {},
1565
- supportingDeclarations,
1566
- ...options?.extensionRegistry !== void 0 ? {
1567
- extensions: options.extensionRegistry.extensions.map((extension) => ({
1568
- extensionId: extension.extensionId,
1569
- ...extension.constraintTags !== void 0 ? {
1570
- constraintTags: extension.constraintTags.map((tag) => ({ tagName: tag.tagName }))
1571
- } : {},
1572
- ...extension.metadataSlots !== void 0 ? {
1573
- metadataSlots: extension.metadataSlots
1574
- } : {},
1575
- ...extension.types !== void 0 ? {
1576
- customTypes: extension.types.map((t) => ({
1577
- tsTypeNames: t.tsTypeNames ?? [t.typeName]
1578
- }))
1579
- } : {}
1580
- }))
1581
- } : {}
1582
- });
1583
- if (result.diagnostics.length === 0) {
1584
- return emit("C-pass", []);
1585
- }
1586
- const setupDiagnostic = result.diagnostics.find((diagnostic) => diagnostic.kind !== "typescript");
1587
- if (setupDiagnostic !== void 0) {
1588
- return emit("C-reject", [
1589
- makeDiagnostic(
1590
- setupDiagnostic.kind === "unsupported-custom-type-override" ? "UNSUPPORTED_CUSTOM_TYPE_OVERRIDE" : "SYNTHETIC_SETUP_FAILURE",
1591
- setupDiagnostic.message,
1592
- provenance
1593
- )
1594
- ]);
1595
- }
1596
- const expectedLabel = definition.valueKind === null ? "compatible argument" : capabilityLabel(definition.valueKind);
1597
- return emit("C-reject", [
1598
- makeDiagnostic(
1599
- "TYPE_MISMATCH",
1600
- `Tag "@${tagName}" received an invalid argument for ${expectedLabel}.`,
1601
- provenance
1602
- )
1603
- ]);
1305
+ return emit("C-pass", []);
1604
1306
  }
1605
1307
  var parseResultCache = /* @__PURE__ */ new Map();
1606
1308
  function getExtensionTagNames(options) {
@@ -1644,8 +1346,8 @@ function getParseCacheKey(node, file, options) {
1644
1346
  start: node.getFullStart(),
1645
1347
  end: node.getEnd(),
1646
1348
  fieldType: options?.fieldType ?? null,
1647
- subjectType: checker !== void 0 && options?.subjectType !== void 0 ? checker.typeToString(options.subjectType, node, SYNTHETIC_TYPE_FORMAT_FLAGS) : null,
1648
- hostType: checker !== void 0 && options?.hostType !== void 0 ? checker.typeToString(options.hostType, node, SYNTHETIC_TYPE_FORMAT_FLAGS) : null,
1349
+ subjectType: checker !== void 0 && options?.subjectType !== void 0 ? checker.typeToString(options.subjectType, node, TYPE_FORMAT_FLAGS) : null,
1350
+ hostType: checker !== void 0 && options?.hostType !== void 0 ? checker.typeToString(options.hostType, node, TYPE_FORMAT_FLAGS) : null,
1649
1351
  extensions: getExtensionRegistryCacheKey(options?.extensionRegistry)
1650
1352
  });
1651
1353
  }
@@ -1655,6 +1357,16 @@ function parseTSDocTags(node, file = "", options) {
1655
1357
  if (cached !== void 0) {
1656
1358
  return cached;
1657
1359
  }
1360
+ const setupDiags = options?.extensionRegistry?.setupDiagnostics;
1361
+ if (setupDiags !== void 0 && setupDiags.length > 0) {
1362
+ const result2 = {
1363
+ constraints: [],
1364
+ annotations: [],
1365
+ diagnostics: _emitSetupDiagnostics(setupDiags, file)
1366
+ };
1367
+ parseResultCache.set(cacheKey, result2);
1368
+ return result2;
1369
+ }
1658
1370
  const constraints = [];
1659
1371
  const annotations = [];
1660
1372
  const diagnostics = [];
@@ -1664,14 +1376,12 @@ function parseTSDocTags(node, file = "", options) {
1664
1376
  let placeholderProvenance;
1665
1377
  const sourceFile = node.getSourceFile();
1666
1378
  const sourceText = sourceFile.getFullText();
1667
- const extensionTypeNames = getExtensionTypeNames(options?.extensionRegistry);
1668
- const supportingDeclarations = buildSupportingDeclarations(sourceFile, extensionTypeNames);
1669
- const commentRanges = ts4.getLeadingCommentRanges(sourceText, node.getFullStart());
1379
+ const commentRanges = ts3.getLeadingCommentRanges(sourceText, node.getFullStart());
1670
1380
  const rawTextFallbacks = collectRawTextFallbacks(node, file);
1671
1381
  const extensionTagNames = getExtensionTagNames(options);
1672
1382
  if (commentRanges) {
1673
1383
  for (const range of commentRanges) {
1674
- if (range.kind !== ts4.SyntaxKind.MultiLineCommentTrivia) {
1384
+ if (range.kind !== ts3.SyntaxKind.MultiLineCommentTrivia) {
1675
1385
  continue;
1676
1386
  }
1677
1387
  const commentText = sourceText.substring(range.pos, range.end);
@@ -1730,7 +1440,6 @@ function parseTSDocTags(node, file = "", options) {
1730
1440
  provenance2,
1731
1441
  node,
1732
1442
  sourceFile,
1733
- supportingDeclarations,
1734
1443
  options,
1735
1444
  constraints,
1736
1445
  diagnostics
@@ -1748,7 +1457,6 @@ function parseTSDocTags(node, file = "", options) {
1748
1457
  provenance,
1749
1458
  node,
1750
1459
  sourceFile,
1751
- supportingDeclarations,
1752
1460
  options,
1753
1461
  constraints,
1754
1462
  diagnostics
@@ -1812,7 +1520,6 @@ function parseTSDocTags(node, file = "", options) {
1812
1520
  provenance,
1813
1521
  node,
1814
1522
  sourceFile,
1815
- supportingDeclarations,
1816
1523
  options,
1817
1524
  constraints,
1818
1525
  diagnostics
@@ -1828,10 +1535,10 @@ function extractDisplayNameMetadata(node) {
1828
1535
  const memberDisplayNames = /* @__PURE__ */ new Map();
1829
1536
  const sourceFile = node.getSourceFile();
1830
1537
  const sourceText = sourceFile.getFullText();
1831
- const commentRanges = ts4.getLeadingCommentRanges(sourceText, node.getFullStart());
1538
+ const commentRanges = ts3.getLeadingCommentRanges(sourceText, node.getFullStart());
1832
1539
  if (commentRanges) {
1833
1540
  for (const range of commentRanges) {
1834
- if (range.kind !== ts4.SyntaxKind.MultiLineCommentTrivia) continue;
1541
+ if (range.kind !== ts3.SyntaxKind.MultiLineCommentTrivia) continue;
1835
1542
  const commentText = sourceText.substring(range.pos, range.end);
1836
1543
  if (!commentText.startsWith("/**")) continue;
1837
1544
  const unified = parseUnifiedComment(commentText);
@@ -1856,7 +1563,7 @@ function extractDisplayNameMetadata(node) {
1856
1563
  }
1857
1564
  function collectRawTextFallbacks(node, file) {
1858
1565
  const fallbacks = /* @__PURE__ */ new Map();
1859
- for (const tag of ts4.getJSDocTags(node)) {
1566
+ for (const tag of ts3.getJSDocTags(node)) {
1860
1567
  const tagName = normalizeConstraintTagName(tag.tagName.text);
1861
1568
  if (!TAGS_REQUIRING_RAW_TEXT.has(tagName)) continue;
1862
1569
  const commentText = getTagCommentText(tag)?.trim() ?? "";
@@ -1911,7 +1618,7 @@ function getTagCommentText(tag) {
1911
1618
  if (typeof tag.comment === "string") {
1912
1619
  return tag.comment;
1913
1620
  }
1914
- return ts4.getTextOfJSDocComment(tag.comment);
1621
+ return ts3.getTextOfJSDocComment(tag.comment);
1915
1622
  }
1916
1623
 
1917
1624
  // src/analyzer/jsdoc-constraints.ts
@@ -1929,18 +1636,18 @@ function extractJSDocAnnotationNodes(node, file = "", options) {
1929
1636
  function extractDefaultValueAnnotation(initializer, file = "") {
1930
1637
  if (!initializer) return null;
1931
1638
  let value;
1932
- if (ts5.isStringLiteral(initializer)) {
1639
+ if (ts4.isStringLiteral(initializer)) {
1933
1640
  value = initializer.text;
1934
- } else if (ts5.isNumericLiteral(initializer)) {
1641
+ } else if (ts4.isNumericLiteral(initializer)) {
1935
1642
  value = Number(initializer.text);
1936
- } else if (initializer.kind === ts5.SyntaxKind.TrueKeyword) {
1643
+ } else if (initializer.kind === ts4.SyntaxKind.TrueKeyword) {
1937
1644
  value = true;
1938
- } else if (initializer.kind === ts5.SyntaxKind.FalseKeyword) {
1645
+ } else if (initializer.kind === ts4.SyntaxKind.FalseKeyword) {
1939
1646
  value = false;
1940
- } else if (initializer.kind === ts5.SyntaxKind.NullKeyword) {
1647
+ } else if (initializer.kind === ts4.SyntaxKind.NullKeyword) {
1941
1648
  value = null;
1942
- } else if (ts5.isPrefixUnaryExpression(initializer)) {
1943
- if (initializer.operator === ts5.SyntaxKind.MinusToken && ts5.isNumericLiteral(initializer.operand)) {
1649
+ } else if (ts4.isPrefixUnaryExpression(initializer)) {
1650
+ if (initializer.operator === ts4.SyntaxKind.MinusToken && ts4.isNumericLiteral(initializer.operand)) {
1944
1651
  value = -Number(initializer.operand.text);
1945
1652
  }
1946
1653
  }
@@ -1962,28 +1669,28 @@ function extractDefaultValueAnnotation(initializer, file = "") {
1962
1669
 
1963
1670
  // src/analyzer/class-analyzer.ts
1964
1671
  function isObjectType(type) {
1965
- return !!(type.flags & ts6.TypeFlags.Object);
1672
+ return !!(type.flags & ts5.TypeFlags.Object);
1966
1673
  }
1967
1674
  function isIntersectionType(type) {
1968
- return !!(type.flags & ts6.TypeFlags.Intersection);
1675
+ return !!(type.flags & ts5.TypeFlags.Intersection);
1969
1676
  }
1970
1677
  function isResolvableObjectLikeAliasTypeNode(typeNode) {
1971
- if (ts6.isParenthesizedTypeNode(typeNode)) {
1678
+ if (ts5.isParenthesizedTypeNode(typeNode)) {
1972
1679
  return isResolvableObjectLikeAliasTypeNode(typeNode.type);
1973
1680
  }
1974
- if (ts6.isTypeLiteralNode(typeNode) || ts6.isTypeReferenceNode(typeNode)) {
1681
+ if (ts5.isTypeLiteralNode(typeNode) || ts5.isTypeReferenceNode(typeNode)) {
1975
1682
  return true;
1976
1683
  }
1977
- return ts6.isIntersectionTypeNode(typeNode) && typeNode.types.length > 0 && typeNode.types.every((member) => isResolvableObjectLikeAliasTypeNode(member));
1684
+ return ts5.isIntersectionTypeNode(typeNode) && typeNode.types.length > 0 && typeNode.types.every((member) => isResolvableObjectLikeAliasTypeNode(member));
1978
1685
  }
1979
1686
  function isSemanticallyPlainObjectLikeType(type, checker) {
1980
1687
  if (isIntersectionType(type)) {
1981
1688
  return type.types.length > 0 && type.types.every((member) => isSemanticallyPlainObjectLikeType(member, checker));
1982
1689
  }
1983
- return isObjectType(type) && checker.getSignaturesOfType(type, ts6.SignatureKind.Call).length === 0 && checker.getSignaturesOfType(type, ts6.SignatureKind.Construct).length === 0 && !checker.isArrayType(type) && !checker.isTupleType(type);
1690
+ return isObjectType(type) && checker.getSignaturesOfType(type, ts5.SignatureKind.Call).length === 0 && checker.getSignaturesOfType(type, ts5.SignatureKind.Construct).length === 0 && !checker.isArrayType(type) && !checker.isTupleType(type);
1984
1691
  }
1985
1692
  function isTypeReference(type) {
1986
- return !!(type.flags & ts6.TypeFlags.Object) && !!(type.objectFlags & ts6.ObjectFlags.Reference);
1693
+ return !!(type.flags & ts5.TypeFlags.Object) && !!(type.objectFlags & ts5.ObjectFlags.Reference);
1987
1694
  }
1988
1695
  var RESOLVING_TYPE_PLACEHOLDER = {
1989
1696
  kind: "object",
@@ -2009,6 +1716,21 @@ function createAnalyzerMetadataPolicy(input, discriminator) {
2009
1716
  discriminator
2010
1717
  };
2011
1718
  }
1719
+ var DEDUPLICATABLE_DIAGNOSTIC_CODES = /* @__PURE__ */ new Set([
1720
+ "SYNTHETIC_SETUP_FAILURE",
1721
+ "UNSUPPORTED_CUSTOM_TYPE_OVERRIDE"
1722
+ ]);
1723
+ function deduplicateDiagnostics(diagnostics) {
1724
+ if (diagnostics.length <= 1) return diagnostics;
1725
+ const seen = /* @__PURE__ */ new Set();
1726
+ return diagnostics.filter((d) => {
1727
+ if (!DEDUPLICATABLE_DIAGNOSTIC_CODES.has(d.code)) return true;
1728
+ const key = `${d.code}\0${d.message}`;
1729
+ if (seen.has(key)) return false;
1730
+ seen.add(key);
1731
+ return true;
1732
+ });
1733
+ }
2012
1734
  function resolveNodeMetadata(metadataPolicy, declarationKind, logicalName, node, checker, extensionRegistry, buildContext) {
2013
1735
  const analysis = analyzeMetadataForNodeWithChecker({
2014
1736
  checker,
@@ -2045,10 +1767,121 @@ function resolveNodeMetadata(metadataPolicy, declarationKind, logicalName, node,
2045
1767
  }
2046
1768
  return resolvedMetadata;
2047
1769
  }
1770
+ var INHERITABLE_TYPE_ANNOTATION_KINDS = /* @__PURE__ */ new Set(["format"]);
1771
+ function getInheritableAnnotationStringValue(annotation) {
1772
+ if (annotation.annotationKind === "format") return annotation.value;
1773
+ return void 0;
1774
+ }
1775
+ function isOverridingInheritableAnnotation(annotation) {
1776
+ const value = getInheritableAnnotationStringValue(annotation);
1777
+ if (value === void 0) return true;
1778
+ return value.trim().length > 0;
1779
+ }
1780
+ function collectInheritedTypeAnnotations(derivedDecl, existingAnnotations, checker, extensionRegistry) {
1781
+ const existingKinds = new Set(
1782
+ existingAnnotations.filter(isOverridingInheritableAnnotation).map((a) => a.annotationKind)
1783
+ );
1784
+ const needed = /* @__PURE__ */ new Set();
1785
+ for (const kind of INHERITABLE_TYPE_ANNOTATION_KINDS) {
1786
+ if (!existingKinds.has(kind)) needed.add(kind);
1787
+ }
1788
+ if (needed.size === 0) return [];
1789
+ const inherited = [];
1790
+ const seen = /* @__PURE__ */ new Set([derivedDecl]);
1791
+ const queue = [];
1792
+ const resolveSymbolTarget = (sym) => {
1793
+ if ((sym.flags & ts5.SymbolFlags.Alias) === 0) return sym;
1794
+ try {
1795
+ return checker.getAliasedSymbol(sym);
1796
+ } catch {
1797
+ return sym;
1798
+ }
1799
+ };
1800
+ const isObjectShapedTypeAlias = (alias) => {
1801
+ const type = checker.getTypeFromTypeNode(alias.type);
1802
+ if ((type.flags & ts5.TypeFlags.Object) !== 0) return true;
1803
+ if (type.isIntersection()) return true;
1804
+ return false;
1805
+ };
1806
+ const enqueueCandidate = (baseDecl, fromTypeAliasRhs) => {
1807
+ if (seen.has(baseDecl)) return;
1808
+ if (ts5.isClassDeclaration(baseDecl) || ts5.isInterfaceDeclaration(baseDecl)) {
1809
+ seen.add(baseDecl);
1810
+ queue.push(baseDecl);
1811
+ return;
1812
+ }
1813
+ if (ts5.isTypeAliasDeclaration(baseDecl)) {
1814
+ if (!fromTypeAliasRhs && !isObjectShapedTypeAlias(baseDecl)) return;
1815
+ seen.add(baseDecl);
1816
+ queue.push(baseDecl);
1817
+ }
1818
+ };
1819
+ const enqueueBasesOf = (decl) => {
1820
+ if (ts5.isTypeAliasDeclaration(decl)) {
1821
+ const rhs = decl.type;
1822
+ if (!ts5.isTypeReferenceNode(rhs)) return;
1823
+ const sym = checker.getSymbolAtLocation(rhs.typeName);
1824
+ if (!sym) return;
1825
+ const target = resolveSymbolTarget(sym);
1826
+ for (const baseDecl of target.declarations ?? []) {
1827
+ enqueueCandidate(
1828
+ baseDecl,
1829
+ /*fromTypeAliasRhs*/
1830
+ true
1831
+ );
1832
+ }
1833
+ return;
1834
+ }
1835
+ const heritageClauses = decl.heritageClauses;
1836
+ if (!heritageClauses) return;
1837
+ for (const clause of heritageClauses) {
1838
+ if (clause.token !== ts5.SyntaxKind.ExtendsKeyword) continue;
1839
+ for (const typeExpr of clause.types) {
1840
+ const sym = checker.getSymbolAtLocation(typeExpr.expression);
1841
+ if (!sym) continue;
1842
+ const target = resolveSymbolTarget(sym);
1843
+ for (const baseDecl of target.declarations ?? []) {
1844
+ enqueueCandidate(
1845
+ baseDecl,
1846
+ /*fromTypeAliasRhs*/
1847
+ false
1848
+ );
1849
+ }
1850
+ }
1851
+ }
1852
+ };
1853
+ enqueueBasesOf(derivedDecl);
1854
+ for (let queueIndex = 0; queueIndex < queue.length && needed.size > 0; queueIndex++) {
1855
+ const baseDecl = queue[queueIndex];
1856
+ if (baseDecl === void 0) continue;
1857
+ const baseFile = baseDecl.getSourceFile().fileName;
1858
+ const baseAnnotations = extractJSDocAnnotationNodes(
1859
+ baseDecl,
1860
+ baseFile,
1861
+ makeParseOptions(extensionRegistry)
1862
+ );
1863
+ for (const annotation of baseAnnotations) {
1864
+ if (!needed.has(annotation.annotationKind)) continue;
1865
+ if (!isOverridingInheritableAnnotation(annotation)) continue;
1866
+ inherited.push(annotation);
1867
+ needed.delete(annotation.annotationKind);
1868
+ }
1869
+ if (needed.size > 0) {
1870
+ enqueueBasesOf(baseDecl);
1871
+ }
1872
+ }
1873
+ return inherited;
1874
+ }
1875
+ function extractNamedTypeAnnotations(namedDecl, checker, file, extensionRegistry) {
1876
+ const local = extractJSDocAnnotationNodes(namedDecl, file, makeParseOptions(extensionRegistry));
1877
+ const inherited = collectInheritedTypeAnnotations(namedDecl, local, checker, extensionRegistry);
1878
+ if (inherited.length === 0) return [...local];
1879
+ return [...local, ...inherited];
1880
+ }
2048
1881
  function analyzeDeclarationRootInfo(declaration, checker, file = "", extensionRegistry, metadataPolicy) {
2049
1882
  const normalizedMetadataPolicy = createAnalyzerMetadataPolicy(metadataPolicy);
2050
1883
  const declarationType = checker.getTypeAtLocation(declaration);
2051
- const logicalName = ts6.isClassDeclaration(declaration) ? declaration.name?.text ?? "AnonymousClass" : declaration.name.text;
1884
+ const logicalName = ts5.isClassDeclaration(declaration) ? declaration.name?.text ?? "AnonymousClass" : declaration.name.text;
2052
1885
  const docResult = extractJSDocParseResult(
2053
1886
  declaration,
2054
1887
  file,
@@ -2090,13 +1923,19 @@ function analyzeClassToIR(classDecl, checker, file = "", extensionRegistry, meta
2090
1923
  file,
2091
1924
  makeParseOptions(extensionRegistry, void 0, checker, classType, classType)
2092
1925
  );
2093
- const annotations = [...classDoc.annotations];
1926
+ const inheritedClassAnnotations = collectInheritedTypeAnnotations(
1927
+ classDecl,
1928
+ classDoc.annotations,
1929
+ checker,
1930
+ extensionRegistry
1931
+ );
1932
+ const annotations = [...classDoc.annotations, ...inheritedClassAnnotations];
2094
1933
  diagnostics.push(...classDoc.diagnostics);
2095
1934
  const visiting = /* @__PURE__ */ new Set();
2096
1935
  const instanceMethods = [];
2097
1936
  const staticMethods = [];
2098
1937
  for (const member of classDecl.members) {
2099
- if (ts6.isPropertyDeclaration(member)) {
1938
+ if (ts5.isPropertyDeclaration(member)) {
2100
1939
  const fieldNode = analyzeFieldToIR(
2101
1940
  member,
2102
1941
  checker,
@@ -2112,10 +1951,10 @@ function analyzeClassToIR(classDecl, checker, file = "", extensionRegistry, meta
2112
1951
  fields.push(fieldNode);
2113
1952
  fieldLayouts.push({});
2114
1953
  }
2115
- } else if (ts6.isMethodDeclaration(member)) {
1954
+ } else if (ts5.isMethodDeclaration(member)) {
2116
1955
  const methodInfo = analyzeMethod(member, checker);
2117
1956
  if (methodInfo) {
2118
- const isStatic = member.modifiers?.some((m) => m.kind === ts6.SyntaxKind.StaticKeyword);
1957
+ const isStatic = member.modifiers?.some((m) => m.kind === ts5.SyntaxKind.StaticKeyword);
2119
1958
  if (isStatic) {
2120
1959
  staticMethods.push(methodInfo);
2121
1960
  } else {
@@ -2147,6 +1986,7 @@ function analyzeClassToIR(classDecl, checker, file = "", extensionRegistry, meta
2147
1986
  hostType: classType
2148
1987
  }
2149
1988
  );
1989
+ const deduplicatedDiagnostics = deduplicateDiagnostics(diagnostics);
2150
1990
  return {
2151
1991
  name,
2152
1992
  ...metadata !== void 0 && { metadata },
@@ -2154,7 +1994,7 @@ function analyzeClassToIR(classDecl, checker, file = "", extensionRegistry, meta
2154
1994
  fieldLayouts,
2155
1995
  typeRegistry,
2156
1996
  ...annotations.length > 0 && { annotations },
2157
- ...diagnostics.length > 0 && { diagnostics },
1997
+ ...deduplicatedDiagnostics.length > 0 && { diagnostics: deduplicatedDiagnostics },
2158
1998
  instanceMethods,
2159
1999
  staticMethods
2160
2000
  };
@@ -2174,11 +2014,20 @@ function analyzeInterfaceToIR(interfaceDecl, checker, file = "", extensionRegist
2174
2014
  file,
2175
2015
  makeParseOptions(extensionRegistry, void 0, checker, interfaceType, interfaceType)
2176
2016
  );
2177
- const annotations = [...interfaceDoc.annotations];
2017
+ const inheritedInterfaceAnnotations = collectInheritedTypeAnnotations(
2018
+ interfaceDecl,
2019
+ interfaceDoc.annotations,
2020
+ checker,
2021
+ extensionRegistry
2022
+ );
2023
+ const annotations = [
2024
+ ...interfaceDoc.annotations,
2025
+ ...inheritedInterfaceAnnotations
2026
+ ];
2178
2027
  diagnostics.push(...interfaceDoc.diagnostics);
2179
2028
  const visiting = /* @__PURE__ */ new Set();
2180
2029
  for (const member of interfaceDecl.members) {
2181
- if (ts6.isPropertySignature(member)) {
2030
+ if (ts5.isPropertySignature(member)) {
2182
2031
  const fieldNode = analyzeInterfacePropertyToIR(
2183
2032
  member,
2184
2033
  checker,
@@ -2219,6 +2068,7 @@ function analyzeInterfaceToIR(interfaceDecl, checker, file = "", extensionRegist
2219
2068
  hostType: interfaceType
2220
2069
  }
2221
2070
  );
2071
+ const deduplicatedDiagnostics = deduplicateDiagnostics(diagnostics);
2222
2072
  return {
2223
2073
  name,
2224
2074
  ...metadata !== void 0 && { metadata },
@@ -2226,7 +2076,7 @@ function analyzeInterfaceToIR(interfaceDecl, checker, file = "", extensionRegist
2226
2076
  fieldLayouts,
2227
2077
  typeRegistry,
2228
2078
  ...annotations.length > 0 && { annotations },
2229
- ...diagnostics.length > 0 && { diagnostics },
2079
+ ...deduplicatedDiagnostics.length > 0 && { diagnostics: deduplicatedDiagnostics },
2230
2080
  instanceMethods: [],
2231
2081
  staticMethods: []
2232
2082
  };
@@ -2236,7 +2086,7 @@ function analyzeTypeAliasToIR(typeAlias, checker, file = "", extensionRegistry,
2236
2086
  if (members === null) {
2237
2087
  const sourceFile = typeAlias.getSourceFile();
2238
2088
  const { line } = sourceFile.getLineAndCharacterOfPosition(typeAlias.getStart());
2239
- const kindDesc = ts6.SyntaxKind[typeAlias.type.kind] ?? "unknown";
2089
+ const kindDesc = ts5.SyntaxKind[typeAlias.type.kind] ?? "unknown";
2240
2090
  return {
2241
2091
  ok: false,
2242
2092
  kind: "not-object-like",
@@ -2271,7 +2121,7 @@ function analyzeTypeAliasToIR(typeAlias, checker, file = "", extensionRegistry,
2271
2121
  diagnostics.push(...typeAliasDoc.diagnostics);
2272
2122
  const visiting = /* @__PURE__ */ new Set();
2273
2123
  for (const member of members) {
2274
- if (ts6.isPropertySignature(member)) {
2124
+ if (ts5.isPropertySignature(member)) {
2275
2125
  const fieldNode = analyzeInterfacePropertyToIR(
2276
2126
  member,
2277
2127
  checker,
@@ -2311,6 +2161,7 @@ function analyzeTypeAliasToIR(typeAlias, checker, file = "", extensionRegistry,
2311
2161
  hostType: aliasType
2312
2162
  }
2313
2163
  );
2164
+ const deduplicatedDiagnostics = deduplicateDiagnostics(diagnostics);
2314
2165
  return {
2315
2166
  ok: true,
2316
2167
  analysis: {
@@ -2320,7 +2171,7 @@ function analyzeTypeAliasToIR(typeAlias, checker, file = "", extensionRegistry,
2320
2171
  fieldLayouts: specializedFields.map(() => ({})),
2321
2172
  typeRegistry,
2322
2173
  ...annotations.length > 0 && { annotations },
2323
- ...diagnostics.length > 0 && { diagnostics },
2174
+ ...deduplicatedDiagnostics.length > 0 && { diagnostics: deduplicatedDiagnostics },
2324
2175
  instanceMethods: [],
2325
2176
  staticMethods: []
2326
2177
  }
@@ -2338,13 +2189,13 @@ function makeAnalysisDiagnostic(code, message, primaryLocation, relatedLocations
2338
2189
  function getLeadingParsedTags(node) {
2339
2190
  const sourceFile = node.getSourceFile();
2340
2191
  const sourceText = sourceFile.getFullText();
2341
- const commentRanges = ts6.getLeadingCommentRanges(sourceText, node.getFullStart());
2192
+ const commentRanges = ts5.getLeadingCommentRanges(sourceText, node.getFullStart());
2342
2193
  if (commentRanges === void 0) {
2343
2194
  return [];
2344
2195
  }
2345
2196
  const parsedTags = [];
2346
2197
  for (const range of commentRanges) {
2347
- if (range.kind !== ts6.SyntaxKind.MultiLineCommentTrivia) {
2198
+ if (range.kind !== ts5.SyntaxKind.MultiLineCommentTrivia) {
2348
2199
  continue;
2349
2200
  }
2350
2201
  const commentText = sourceText.slice(range.pos, range.end);
@@ -2362,19 +2213,19 @@ function resolveDiscriminatorProperty(node, checker, fieldName) {
2362
2213
  return null;
2363
2214
  }
2364
2215
  const declaration = propertySymbol.valueDeclaration ?? propertySymbol.declarations?.find(
2365
- (candidate) => ts6.isPropertyDeclaration(candidate) || ts6.isPropertySignature(candidate)
2216
+ (candidate) => ts5.isPropertyDeclaration(candidate) || ts5.isPropertySignature(candidate)
2366
2217
  ) ?? propertySymbol.declarations?.[0];
2367
2218
  return {
2368
2219
  declaration,
2369
2220
  type: checker.getTypeOfSymbolAtLocation(propertySymbol, declaration ?? node),
2370
- optional: !!(propertySymbol.flags & ts6.SymbolFlags.Optional) || declaration !== void 0 && "questionToken" in declaration && declaration.questionToken !== void 0
2221
+ optional: !!(propertySymbol.flags & ts5.SymbolFlags.Optional) || declaration !== void 0 && "questionToken" in declaration && declaration.questionToken !== void 0
2371
2222
  };
2372
2223
  }
2373
2224
  function isLocalTypeParameterName(node, typeParameterName) {
2374
2225
  return node.typeParameters?.some((typeParameter) => typeParameter.name.text === typeParameterName) ?? false;
2375
2226
  }
2376
2227
  function isNullishSemanticType(type) {
2377
- if (type.flags & (ts6.TypeFlags.Null | ts6.TypeFlags.Undefined | ts6.TypeFlags.Void | ts6.TypeFlags.Unknown | ts6.TypeFlags.Any)) {
2228
+ if (type.flags & (ts5.TypeFlags.Null | ts5.TypeFlags.Undefined | ts5.TypeFlags.Void | ts5.TypeFlags.Unknown | ts5.TypeFlags.Any)) {
2378
2229
  return true;
2379
2230
  }
2380
2231
  return type.isUnion() && type.types.some((member) => isNullishSemanticType(member));
@@ -2384,7 +2235,7 @@ function isStringLikeSemanticType(type, checker, seen = /* @__PURE__ */ new Set(
2384
2235
  return false;
2385
2236
  }
2386
2237
  seen.add(type);
2387
- if (type.flags & ts6.TypeFlags.StringLike) {
2238
+ if (type.flags & ts5.TypeFlags.StringLike) {
2388
2239
  return true;
2389
2240
  }
2390
2241
  if (type.isUnion()) {
@@ -2397,13 +2248,13 @@ function isStringLikeSemanticType(type, checker, seen = /* @__PURE__ */ new Set(
2397
2248
  return false;
2398
2249
  }
2399
2250
  function getObjectLikeTypeAliasMembers(typeNode) {
2400
- if (ts6.isParenthesizedTypeNode(typeNode)) {
2251
+ if (ts5.isParenthesizedTypeNode(typeNode)) {
2401
2252
  return getObjectLikeTypeAliasMembers(typeNode.type);
2402
2253
  }
2403
- if (ts6.isTypeLiteralNode(typeNode)) {
2254
+ if (ts5.isTypeLiteralNode(typeNode)) {
2404
2255
  return [...typeNode.members];
2405
2256
  }
2406
- if (ts6.isIntersectionTypeNode(typeNode)) {
2257
+ if (ts5.isIntersectionTypeNode(typeNode)) {
2407
2258
  const members = [];
2408
2259
  for (const intersectionMember of typeNode.types) {
2409
2260
  const resolvedMembers = getObjectLikeTypeAliasMembers(intersectionMember);
@@ -2566,7 +2417,7 @@ function resolveLiteralDiscriminatorPropertyValue(boundType, propertyName, check
2566
2417
  }
2567
2418
  if (propertyType.isUnion()) {
2568
2419
  const nonNullMembers = propertyType.types.filter(
2569
- (member) => !(member.flags & (ts6.TypeFlags.Null | ts6.TypeFlags.Undefined))
2420
+ (member) => !(member.flags & (ts5.TypeFlags.Null | ts5.TypeFlags.Undefined))
2570
2421
  );
2571
2422
  if (nonNullMembers.length > 0 && nonNullMembers.every((member) => member.isStringLiteral())) {
2572
2423
  diagnostics.push(
@@ -2615,13 +2466,13 @@ function resolveNamedDiscriminatorDeclaration(type, checker, seen = /* @__PURE__
2615
2466
  seen.add(type);
2616
2467
  const symbol = type.aliasSymbol ?? type.getSymbol();
2617
2468
  if (symbol !== void 0) {
2618
- const aliased = symbol.flags & ts6.SymbolFlags.Alias ? checker.getAliasedSymbol(symbol) : void 0;
2469
+ const aliased = symbol.flags & ts5.SymbolFlags.Alias ? checker.getAliasedSymbol(symbol) : void 0;
2619
2470
  const targetSymbol = aliased ?? symbol;
2620
2471
  const declaration = targetSymbol.declarations?.find(
2621
- (candidate) => ts6.isClassDeclaration(candidate) || ts6.isInterfaceDeclaration(candidate) || ts6.isTypeAliasDeclaration(candidate) || ts6.isEnumDeclaration(candidate)
2472
+ (candidate) => ts5.isClassDeclaration(candidate) || ts5.isInterfaceDeclaration(candidate) || ts5.isTypeAliasDeclaration(candidate) || ts5.isEnumDeclaration(candidate)
2622
2473
  );
2623
2474
  if (declaration !== void 0) {
2624
- if (ts6.isTypeAliasDeclaration(declaration) && ts6.isTypeReferenceNode(declaration.type) && checker.getTypeFromTypeNode(declaration.type) !== type) {
2475
+ if (ts5.isTypeAliasDeclaration(declaration) && ts5.isTypeReferenceNode(declaration.type) && checker.getTypeFromTypeNode(declaration.type) !== type) {
2625
2476
  return resolveNamedDiscriminatorDeclaration(
2626
2477
  checker.getTypeFromTypeNode(declaration.type),
2627
2478
  checker,
@@ -2649,7 +2500,7 @@ function resolveDiscriminatorValue(boundType, fieldName, checker, provenance, di
2649
2500
  }
2650
2501
  if (boundType.isUnion()) {
2651
2502
  const nonNullMembers = boundType.types.filter(
2652
- (member) => !(member.flags & (ts6.TypeFlags.Null | ts6.TypeFlags.Undefined))
2503
+ (member) => !(member.flags & (ts5.TypeFlags.Null | ts5.TypeFlags.Undefined))
2653
2504
  );
2654
2505
  if (nonNullMembers.every((member) => member.isStringLiteral())) {
2655
2506
  diagnostics.push(
@@ -2694,7 +2545,7 @@ function resolveDiscriminatorValue(boundType, fieldName, checker, provenance, di
2694
2545
  return null;
2695
2546
  }
2696
2547
  function getDeclarationName(node) {
2697
- if (ts6.isClassDeclaration(node) || ts6.isInterfaceDeclaration(node) || ts6.isTypeAliasDeclaration(node) || ts6.isEnumDeclaration(node)) {
2548
+ if (ts5.isClassDeclaration(node) || ts5.isInterfaceDeclaration(node) || ts5.isTypeAliasDeclaration(node) || ts5.isEnumDeclaration(node)) {
2698
2549
  return node.name?.text ?? "anonymous";
2699
2550
  }
2700
2551
  return "anonymous";
@@ -2749,11 +2600,11 @@ function extractReferenceTypeArguments(type, checker, file, typeRegistry, visiti
2749
2600
  if (sourceTypeNode === void 0) {
2750
2601
  return [];
2751
2602
  }
2752
- const unwrapParentheses = (typeNode) => ts6.isParenthesizedTypeNode(typeNode) ? unwrapParentheses(typeNode.type) : typeNode;
2603
+ const unwrapParentheses = (typeNode) => ts5.isParenthesizedTypeNode(typeNode) ? unwrapParentheses(typeNode.type) : typeNode;
2753
2604
  const directTypeNode = unwrapParentheses(sourceTypeNode);
2754
- const referenceTypeNode = ts6.isTypeReferenceNode(directTypeNode) ? directTypeNode : (() => {
2605
+ const referenceTypeNode = ts5.isTypeReferenceNode(directTypeNode) ? directTypeNode : (() => {
2755
2606
  const resolvedTypeNode = resolveAliasedTypeNode(directTypeNode, checker);
2756
- return ts6.isTypeReferenceNode(resolvedTypeNode) ? resolvedTypeNode : null;
2607
+ return ts5.isTypeReferenceNode(resolvedTypeNode) ? resolvedTypeNode : null;
2757
2608
  })();
2758
2609
  if (referenceTypeNode?.typeArguments === void 0) {
2759
2610
  return [];
@@ -2761,7 +2612,7 @@ function extractReferenceTypeArguments(type, checker, file, typeRegistry, visiti
2761
2612
  return referenceTypeNode.typeArguments.map((argumentNode) => {
2762
2613
  const argumentType = checker.getTypeFromTypeNode(argumentNode);
2763
2614
  const baseSymbol = argumentType.aliasSymbol ?? argumentType.getSymbol();
2764
- const argumentSymbol = baseSymbol !== void 0 && baseSymbol.flags & ts6.SymbolFlags.Alias ? checker.getAliasedSymbol(baseSymbol) : baseSymbol;
2615
+ const argumentSymbol = baseSymbol !== void 0 && baseSymbol.flags & ts5.SymbolFlags.Alias ? checker.getAliasedSymbol(baseSymbol) : baseSymbol;
2765
2616
  const argumentDecl = argumentSymbol?.declarations?.[0];
2766
2617
  if (argumentDecl !== void 0 && argumentDecl.getSourceFile().fileName !== file) {
2767
2618
  const argumentName = argumentSymbol?.getName() ?? baseSymbol?.getName();
@@ -2824,7 +2675,7 @@ function applyDiscriminatorToObjectProperties(properties, node, subjectType, che
2824
2675
  );
2825
2676
  }
2826
2677
  function analyzeFieldToIR(prop, checker, file, typeRegistry, visiting, diagnostics, hostType, metadataPolicy, extensionRegistry) {
2827
- if (!ts6.isIdentifier(prop.name)) {
2678
+ if (!ts5.isIdentifier(prop.name)) {
2828
2679
  return null;
2829
2680
  }
2830
2681
  const name = prop.name.text;
@@ -2951,7 +2802,7 @@ function findDuplicateObjectLikeTypeAliasPropertyNames(members) {
2951
2802
  const seen = /* @__PURE__ */ new Set();
2952
2803
  const duplicates = /* @__PURE__ */ new Set();
2953
2804
  for (const member of members) {
2954
- if (!ts6.isPropertySignature(member)) {
2805
+ if (!ts5.isPropertySignature(member)) {
2955
2806
  continue;
2956
2807
  }
2957
2808
  const name = getAnalyzableObjectLikePropertyName(member.name);
@@ -2967,7 +2818,7 @@ function findDuplicateObjectLikeTypeAliasPropertyNames(members) {
2967
2818
  return [...duplicates].sort();
2968
2819
  }
2969
2820
  function getAnalyzableObjectLikePropertyName(name) {
2970
- if (ts6.isIdentifier(name) || ts6.isStringLiteral(name) || ts6.isNumericLiteral(name)) {
2821
+ if (ts5.isIdentifier(name) || ts5.isStringLiteral(name) || ts5.isNumericLiteral(name)) {
2971
2822
  return name.text;
2972
2823
  }
2973
2824
  return null;
@@ -3062,28 +2913,28 @@ function resolveTypeNode(type, checker, file, typeRegistry, visiting, sourceNode
3062
2913
  if (primitiveAlias) {
3063
2914
  return primitiveAlias;
3064
2915
  }
3065
- if (isIntegerBrandedType(type)) {
2916
+ if (_isIntegerBrandedType(type)) {
3066
2917
  return { kind: "primitive", primitiveKind: "integer" };
3067
2918
  }
3068
- if (type.flags & ts6.TypeFlags.String) {
2919
+ if (type.flags & ts5.TypeFlags.String) {
3069
2920
  return { kind: "primitive", primitiveKind: "string" };
3070
2921
  }
3071
- if (type.flags & ts6.TypeFlags.Number) {
2922
+ if (type.flags & ts5.TypeFlags.Number) {
3072
2923
  return { kind: "primitive", primitiveKind: "number" };
3073
2924
  }
3074
- if (type.flags & (ts6.TypeFlags.BigInt | ts6.TypeFlags.BigIntLiteral)) {
2925
+ if (type.flags & (ts5.TypeFlags.BigInt | ts5.TypeFlags.BigIntLiteral)) {
3075
2926
  return { kind: "primitive", primitiveKind: "bigint" };
3076
2927
  }
3077
- if (type.flags & ts6.TypeFlags.Boolean) {
2928
+ if (type.flags & ts5.TypeFlags.Boolean) {
3078
2929
  return { kind: "primitive", primitiveKind: "boolean" };
3079
2930
  }
3080
- if (type.flags & ts6.TypeFlags.Null) {
2931
+ if (type.flags & ts5.TypeFlags.Null) {
3081
2932
  return { kind: "primitive", primitiveKind: "null" };
3082
2933
  }
3083
- if (type.flags & ts6.TypeFlags.Undefined) {
2934
+ if (type.flags & ts5.TypeFlags.Undefined) {
3084
2935
  return { kind: "primitive", primitiveKind: "null" };
3085
2936
  }
3086
- if (type.flags & ts6.TypeFlags.Void) {
2937
+ if (type.flags & ts5.TypeFlags.Void) {
3087
2938
  return { kind: "primitive", primitiveKind: "null" };
3088
2939
  }
3089
2940
  if (type.isStringLiteral()) {
@@ -3170,10 +3021,10 @@ function resolveTypeNode(type, checker, file, typeRegistry, visiting, sourceNode
3170
3021
  return { kind: "primitive", primitiveKind: "string" };
3171
3022
  }
3172
3023
  function tryResolveNamedPrimitiveAlias(type, checker, file, typeRegistry, visiting, sourceNode, metadataPolicy = createAnalyzerMetadataPolicy(void 0), extensionRegistry, diagnostics) {
3173
- if (!(type.flags & (ts6.TypeFlags.String | ts6.TypeFlags.Number | ts6.TypeFlags.BigInt | ts6.TypeFlags.BigIntLiteral | ts6.TypeFlags.Boolean | ts6.TypeFlags.Null)) && !isIntegerBrandedType(type)) {
3024
+ if (!(type.flags & (ts5.TypeFlags.String | ts5.TypeFlags.Number | ts5.TypeFlags.BigInt | ts5.TypeFlags.BigIntLiteral | ts5.TypeFlags.Boolean | ts5.TypeFlags.Null)) && !_isIntegerBrandedType(type)) {
3174
3025
  return null;
3175
3026
  }
3176
- const aliasDecl = type.aliasSymbol?.declarations?.find(ts6.isTypeAliasDeclaration) ?? getReferencedTypeAliasDeclaration(sourceNode, checker);
3027
+ const aliasDecl = type.aliasSymbol?.declarations?.find(ts5.isTypeAliasDeclaration) ?? getReferencedTypeAliasDeclaration(sourceNode, checker);
3177
3028
  if (!aliasDecl) {
3178
3029
  return null;
3179
3030
  }
@@ -3184,11 +3035,18 @@ function tryResolveNamedPrimitiveAlias(type, checker, file, typeRegistry, visiti
3184
3035
  ...extractJSDocConstraintNodes(aliasDecl, file, makeParseOptions(extensionRegistry)),
3185
3036
  ...extractTypeAliasConstraintNodes(aliasDecl.type, checker, file, extensionRegistry)
3186
3037
  ];
3187
- const annotations = extractJSDocAnnotationNodes(
3038
+ const localAnnotations = extractJSDocAnnotationNodes(
3188
3039
  aliasDecl,
3189
3040
  file,
3190
3041
  makeParseOptions(extensionRegistry)
3191
3042
  );
3043
+ const inheritedAnnotations = collectInheritedTypeAnnotations(
3044
+ aliasDecl,
3045
+ localAnnotations,
3046
+ checker,
3047
+ extensionRegistry
3048
+ );
3049
+ const annotations = [...localAnnotations, ...inheritedAnnotations];
3192
3050
  const metadata = resolveNodeMetadata(
3193
3051
  metadataPolicy,
3194
3052
  "type",
@@ -3223,8 +3081,8 @@ function tryResolveNamedPrimitiveAlias(type, checker, file, typeRegistry, visiti
3223
3081
  return { kind: "reference", name: aliasName, typeArguments: [] };
3224
3082
  }
3225
3083
  function getReferencedTypeAliasDeclaration(sourceNode, checker) {
3226
- const typeNode = sourceNode && (ts6.isPropertyDeclaration(sourceNode) || ts6.isPropertySignature(sourceNode) || ts6.isParameter(sourceNode)) ? sourceNode.type : void 0;
3227
- if (!typeNode || !ts6.isTypeReferenceNode(typeNode)) {
3084
+ const typeNode = sourceNode && (ts5.isPropertyDeclaration(sourceNode) || ts5.isPropertySignature(sourceNode) || ts5.isParameter(sourceNode)) ? sourceNode.type : void 0;
3085
+ if (!typeNode || !ts5.isTypeReferenceNode(typeNode)) {
3228
3086
  return void 0;
3229
3087
  }
3230
3088
  return getTypeAliasDeclarationFromTypeReference(typeNode, checker);
@@ -3245,7 +3103,7 @@ function resolveNamedTypeWithSourceRecovery(type, sourceNode, checker) {
3245
3103
  return { typeName: refAliasDecl.name.text, namedDecl: refAliasDecl };
3246
3104
  }
3247
3105
  function shouldEmitPrimitiveAliasDefinition(typeNode, checker) {
3248
- if (!ts6.isTypeReferenceNode(typeNode)) {
3106
+ if (!ts5.isTypeReferenceNode(typeNode)) {
3249
3107
  return false;
3250
3108
  }
3251
3109
  const aliasDecl = getTypeAliasDeclarationFromTypeReference(typeNode, checker);
@@ -3253,10 +3111,10 @@ function shouldEmitPrimitiveAliasDefinition(typeNode, checker) {
3253
3111
  return false;
3254
3112
  }
3255
3113
  const resolved = checker.getTypeFromTypeNode(aliasDecl.type);
3256
- return !!(resolved.flags & (ts6.TypeFlags.String | ts6.TypeFlags.Number | ts6.TypeFlags.BigInt | ts6.TypeFlags.BigIntLiteral | ts6.TypeFlags.Boolean | ts6.TypeFlags.Null));
3114
+ return !!(resolved.flags & (ts5.TypeFlags.String | ts5.TypeFlags.Number | ts5.TypeFlags.BigInt | ts5.TypeFlags.BigIntLiteral | ts5.TypeFlags.Boolean | ts5.TypeFlags.Null));
3257
3115
  }
3258
3116
  function resolveAliasedPrimitiveTarget(type, checker, file, typeRegistry, visiting, metadataPolicy = createAnalyzerMetadataPolicy(void 0), extensionRegistry, diagnostics, visitedAliases = /* @__PURE__ */ new Set()) {
3259
- const nestedAliasDecl = type.aliasSymbol?.declarations?.find(ts6.isTypeAliasDeclaration);
3117
+ const nestedAliasDecl = type.aliasSymbol?.declarations?.find(ts5.isTypeAliasDeclaration);
3260
3118
  if (nestedAliasDecl !== void 0 && !visitedAliases.has(nestedAliasDecl)) {
3261
3119
  visitedAliases.add(nestedAliasDecl);
3262
3120
  return resolveAliasedPrimitiveTarget(
@@ -3271,22 +3129,22 @@ function resolveAliasedPrimitiveTarget(type, checker, file, typeRegistry, visiti
3271
3129
  visitedAliases
3272
3130
  );
3273
3131
  }
3274
- if (isIntegerBrandedType(type)) {
3132
+ if (_isIntegerBrandedType(type)) {
3275
3133
  return { kind: "primitive", primitiveKind: "integer" };
3276
3134
  }
3277
- if (type.flags & ts6.TypeFlags.String) {
3135
+ if (type.flags & ts5.TypeFlags.String) {
3278
3136
  return { kind: "primitive", primitiveKind: "string" };
3279
3137
  }
3280
- if (type.flags & ts6.TypeFlags.Number) {
3138
+ if (type.flags & ts5.TypeFlags.Number) {
3281
3139
  return { kind: "primitive", primitiveKind: "number" };
3282
3140
  }
3283
- if (type.flags & (ts6.TypeFlags.BigInt | ts6.TypeFlags.BigIntLiteral)) {
3141
+ if (type.flags & (ts5.TypeFlags.BigInt | ts5.TypeFlags.BigIntLiteral)) {
3284
3142
  return { kind: "primitive", primitiveKind: "bigint" };
3285
3143
  }
3286
- if (type.flags & ts6.TypeFlags.Boolean) {
3144
+ if (type.flags & ts5.TypeFlags.Boolean) {
3287
3145
  return { kind: "primitive", primitiveKind: "boolean" };
3288
3146
  }
3289
- if (type.flags & ts6.TypeFlags.Null) {
3147
+ if (type.flags & ts5.TypeFlags.Null) {
3290
3148
  return { kind: "primitive", primitiveKind: "null" };
3291
3149
  }
3292
3150
  return resolveTypeNode(
@@ -3306,7 +3164,7 @@ function resolveUnionType(type, checker, file, typeRegistry, visiting, sourceNod
3306
3164
  let typeName = null;
3307
3165
  let namedDecl;
3308
3166
  if (recovered !== null) {
3309
- const recoveredAliasDecl = ts6.isTypeAliasDeclaration(recovered.namedDecl) ? recovered.namedDecl : void 0;
3167
+ const recoveredAliasDecl = ts5.isTypeAliasDeclaration(recovered.namedDecl) ? recovered.namedDecl : void 0;
3310
3168
  if (recoveredAliasDecl !== void 0) {
3311
3169
  const aliasUnderlyingType = checker.getTypeFromTypeNode(recoveredAliasDecl.type);
3312
3170
  const isNonGeneric = recoveredAliasDecl.typeParameters === void 0 || recoveredAliasDecl.typeParameters.length === 0;
@@ -3328,13 +3186,13 @@ function resolveUnionType(type, checker, file, typeRegistry, visiting, sourceNod
3328
3186
  (memberTypeNode) => !isNullishTypeNode(resolveAliasedTypeNode(memberTypeNode, checker))
3329
3187
  );
3330
3188
  const nonNullTypes = allTypes.filter(
3331
- (memberType) => !(memberType.flags & (ts6.TypeFlags.Null | ts6.TypeFlags.Undefined))
3189
+ (memberType) => !(memberType.flags & (ts5.TypeFlags.Null | ts5.TypeFlags.Undefined))
3332
3190
  );
3333
3191
  const nonNullMembers = nonNullTypes.map((memberType, index) => ({
3334
3192
  memberType,
3335
3193
  sourceNode: nonNullSourceNodes.length === nonNullTypes.length ? nonNullSourceNodes[index] : void 0
3336
3194
  }));
3337
- const hasNull = allTypes.some((t) => t.flags & ts6.TypeFlags.Null);
3195
+ const hasNull = allTypes.some((t) => t.flags & ts5.TypeFlags.Null);
3338
3196
  const memberDisplayNames = /* @__PURE__ */ new Map();
3339
3197
  if (namedDecl) {
3340
3198
  for (const [value, label] of extractDisplayNameMetadata(namedDecl).memberDisplayNames) {
@@ -3354,7 +3212,7 @@ function resolveUnionType(type, checker, file, typeRegistry, visiting, sourceNod
3354
3212
  if (existing !== void 0 && existing.type !== RESOLVING_TYPE_PLACEHOLDER) {
3355
3213
  return { kind: "reference", name: typeName, typeArguments: [] };
3356
3214
  }
3357
- const annotations = namedDecl ? extractJSDocAnnotationNodes(namedDecl, file, makeParseOptions(extensionRegistry)) : void 0;
3215
+ const annotations = namedDecl ? extractNamedTypeAnnotations(namedDecl, checker, file, extensionRegistry) : void 0;
3358
3216
  const metadata = namedDecl !== void 0 ? resolveNodeMetadata(
3359
3217
  metadataPolicy,
3360
3218
  "type",
@@ -3381,7 +3239,7 @@ function resolveUnionType(type, checker, file, typeRegistry, visiting, sourceNod
3381
3239
  const displayName = memberDisplayNames.get(String(value));
3382
3240
  return displayName !== void 0 ? { value, displayName } : { value };
3383
3241
  });
3384
- const isBooleanUnion2 = nonNullTypes.length === 2 && nonNullTypes.every((t) => t.flags & ts6.TypeFlags.BooleanLiteral);
3242
+ const isBooleanUnion2 = nonNullTypes.length === 2 && nonNullTypes.every((t) => t.flags & ts5.TypeFlags.BooleanLiteral);
3385
3243
  if (isBooleanUnion2) {
3386
3244
  const boolNode = { kind: "primitive", primitiveKind: "boolean" };
3387
3245
  const result = hasNull ? {
@@ -3473,7 +3331,7 @@ function tryResolveRecordType(type, checker, file, typeRegistry, visiting, metad
3473
3331
  if (type.getProperties().length > 0) {
3474
3332
  return null;
3475
3333
  }
3476
- const indexInfo = checker.getIndexInfoOfType(type, ts6.IndexKind.String);
3334
+ const indexInfo = checker.getIndexInfoOfType(type, ts5.IndexKind.String);
3477
3335
  if (!indexInfo) {
3478
3336
  return null;
3479
3337
  }
@@ -3521,20 +3379,53 @@ function shouldEmitResolvedObjectProperty(property, declaration) {
3521
3379
  }
3522
3380
  if (declaration !== void 0 && "name" in declaration && declaration.name !== void 0) {
3523
3381
  const name = declaration.name;
3524
- if (ts6.isComputedPropertyName(name) || ts6.isPrivateIdentifier(name)) {
3382
+ if (ts5.isComputedPropertyName(name) || ts5.isPrivateIdentifier(name)) {
3525
3383
  return false;
3526
3384
  }
3527
- if (!ts6.isIdentifier(name) && !ts6.isStringLiteral(name) && !ts6.isNumericLiteral(name)) {
3385
+ if (!ts5.isIdentifier(name) && !ts5.isStringLiteral(name) && !ts5.isNumericLiteral(name)) {
3528
3386
  return false;
3529
3387
  }
3530
3388
  }
3531
3389
  return true;
3532
3390
  }
3391
+ function getPassThroughTypeAliasFromSourceNode(sourceNode, checker, extensionRegistry, resolvedTypeName) {
3392
+ const aliasDecl = getReferencedTypeAliasDeclaration(sourceNode, checker);
3393
+ if (!aliasDecl) return void 0;
3394
+ const aliasName = aliasDecl.name.text;
3395
+ if (aliasName === resolvedTypeName) return void 0;
3396
+ if (!ts5.isTypeReferenceNode(aliasDecl.type)) return void 0;
3397
+ if (!hasInheritableTypeAnnotation(aliasDecl, checker, extensionRegistry)) {
3398
+ return void 0;
3399
+ }
3400
+ return { aliasName, aliasDecl };
3401
+ }
3402
+ function hasInheritableTypeAnnotation(aliasDecl, checker, extensionRegistry) {
3403
+ const file = aliasDecl.getSourceFile().fileName;
3404
+ const local = extractJSDocAnnotationNodes(aliasDecl, file, makeParseOptions(extensionRegistry));
3405
+ for (const annotation of local) {
3406
+ if (!INHERITABLE_TYPE_ANNOTATION_KINDS.has(annotation.annotationKind)) continue;
3407
+ if (!isOverridingInheritableAnnotation(annotation)) continue;
3408
+ return true;
3409
+ }
3410
+ const inherited = collectInheritedTypeAnnotations(aliasDecl, local, checker, extensionRegistry);
3411
+ for (const annotation of inherited) {
3412
+ if (INHERITABLE_TYPE_ANNOTATION_KINDS.has(annotation.annotationKind)) return true;
3413
+ }
3414
+ return false;
3415
+ }
3533
3416
  function resolveObjectType(type, checker, file, typeRegistry, visiting, sourceNode, metadataPolicy = createAnalyzerMetadataPolicy(void 0), extensionRegistry, diagnostics) {
3534
3417
  const collectedDiagnostics = diagnostics ?? [];
3535
3418
  const typeName = getNamedTypeName(type);
3536
3419
  const namedTypeName = typeName ?? void 0;
3537
3420
  const namedDecl = getNamedTypeDeclaration(type);
3421
+ const passThroughAlias = getPassThroughTypeAliasFromSourceNode(
3422
+ sourceNode,
3423
+ checker,
3424
+ extensionRegistry,
3425
+ namedTypeName
3426
+ );
3427
+ const effectiveTypeName = passThroughAlias?.aliasName ?? namedTypeName;
3428
+ const effectiveNamedDecl = passThroughAlias?.aliasDecl ?? namedDecl;
3538
3429
  const referenceTypeArguments = extractReferenceTypeArguments(
3539
3430
  type,
3540
3431
  checker,
@@ -3546,13 +3437,13 @@ function resolveObjectType(type, checker, file, typeRegistry, visiting, sourceNo
3546
3437
  extensionRegistry,
3547
3438
  collectedDiagnostics
3548
3439
  );
3549
- const instantiatedTypeName = namedTypeName !== void 0 && referenceTypeArguments.length > 0 ? buildInstantiatedReferenceName(
3550
- namedTypeName,
3440
+ const instantiatedTypeName = effectiveTypeName !== void 0 && referenceTypeArguments.length > 0 ? buildInstantiatedReferenceName(
3441
+ effectiveTypeName,
3551
3442
  referenceTypeArguments.map((argument) => argument.tsType),
3552
3443
  checker
3553
3444
  ) : void 0;
3554
- const registryTypeName = instantiatedTypeName ?? namedTypeName;
3555
- const shouldRegisterNamedType = registryTypeName !== void 0 && !(registryTypeName === "Record" && namedDecl?.getSourceFile().fileName !== file);
3445
+ const registryTypeName = instantiatedTypeName ?? effectiveTypeName;
3446
+ const shouldRegisterNamedType = registryTypeName !== void 0 && !(registryTypeName === "Record" && effectiveNamedDecl?.getSourceFile().fileName !== file);
3556
3447
  const clearNamedTypeRegistration = () => {
3557
3448
  if (registryTypeName === void 0 || !shouldRegisterNamedType) {
3558
3449
  return;
@@ -3573,7 +3464,7 @@ function resolveObjectType(type, checker, file, typeRegistry, visiting, sourceNo
3573
3464
  typeRegistry[registryTypeName] = {
3574
3465
  name: registryTypeName,
3575
3466
  type: RESOLVING_TYPE_PLACEHOLDER,
3576
- provenance: provenanceForDeclaration(namedDecl, file)
3467
+ provenance: provenanceForDeclaration(effectiveNamedDecl, file)
3577
3468
  };
3578
3469
  }
3579
3470
  visiting.add(type);
@@ -3605,17 +3496,17 @@ function resolveObjectType(type, checker, file, typeRegistry, visiting, sourceNo
3605
3496
  clearNamedTypeRegistration();
3606
3497
  return recordNode;
3607
3498
  }
3608
- const annotations = namedDecl ? extractJSDocAnnotationNodes(namedDecl, file, makeParseOptions(extensionRegistry)) : void 0;
3609
- const metadata = namedDecl !== void 0 ? resolveNodeMetadata(
3499
+ const annotations = effectiveNamedDecl ? extractNamedTypeAnnotations(effectiveNamedDecl, checker, file, extensionRegistry) : void 0;
3500
+ const metadata = effectiveNamedDecl !== void 0 ? resolveNodeMetadata(
3610
3501
  metadataPolicy,
3611
3502
  "type",
3612
3503
  registryTypeName,
3613
- namedDecl,
3504
+ effectiveNamedDecl,
3614
3505
  checker,
3615
3506
  extensionRegistry,
3616
3507
  {
3617
3508
  checker,
3618
- declaration: namedDecl,
3509
+ declaration: effectiveNamedDecl,
3619
3510
  subjectType: type
3620
3511
  }
3621
3512
  ) : void 0;
@@ -3624,7 +3515,7 @@ function resolveObjectType(type, checker, file, typeRegistry, visiting, sourceNo
3624
3515
  ...metadata !== void 0 && { metadata },
3625
3516
  type: recordNode,
3626
3517
  ...annotations !== void 0 && annotations.length > 0 && { annotations },
3627
- provenance: provenanceForDeclaration(namedDecl, file)
3518
+ provenance: provenanceForDeclaration(effectiveNamedDecl, file)
3628
3519
  };
3629
3520
  return {
3630
3521
  kind: "reference",
@@ -3650,7 +3541,7 @@ function resolveObjectType(type, checker, file, typeRegistry, visiting, sourceNo
3650
3541
  if (!declaration) continue;
3651
3542
  if (!shouldEmitResolvedObjectProperty(prop, declaration)) continue;
3652
3543
  const propType = checker.getTypeOfSymbolAtLocation(prop, declaration);
3653
- const optional = !!(prop.flags & ts6.SymbolFlags.Optional);
3544
+ const optional = !!(prop.flags & ts5.SymbolFlags.Optional);
3654
3545
  const propTypeNode = resolveTypeNode(
3655
3546
  propType,
3656
3547
  checker,
@@ -3663,7 +3554,7 @@ function resolveObjectType(type, checker, file, typeRegistry, visiting, sourceNo
3663
3554
  collectedDiagnostics
3664
3555
  );
3665
3556
  const fieldNodeInfo = fieldInfoMap?.get(prop.name);
3666
- const inlineFieldNodeInfo = fieldNodeInfo === void 0 ? ts6.isPropertySignature(declaration) ? analyzeInterfacePropertyToIR(
3557
+ const inlineFieldNodeInfo = fieldNodeInfo === void 0 ? ts5.isPropertySignature(declaration) ? analyzeInterfacePropertyToIR(
3667
3558
  declaration,
3668
3559
  checker,
3669
3560
  file,
@@ -3673,7 +3564,7 @@ function resolveObjectType(type, checker, file, typeRegistry, visiting, sourceNo
3673
3564
  type,
3674
3565
  metadataPolicy,
3675
3566
  extensionRegistry
3676
- ) : ts6.isPropertyDeclaration(declaration) ? analyzeFieldToIR(
3567
+ ) : ts5.isPropertyDeclaration(declaration) ? analyzeFieldToIR(
3677
3568
  declaration,
3678
3569
  checker,
3679
3570
  file,
@@ -3701,9 +3592,9 @@ function resolveObjectType(type, checker, file, typeRegistry, visiting, sourceNo
3701
3592
  visiting.delete(type);
3702
3593
  const objectNode = {
3703
3594
  kind: "object",
3704
- properties: namedDecl !== void 0 && (ts6.isClassDeclaration(namedDecl) || ts6.isInterfaceDeclaration(namedDecl) || ts6.isTypeAliasDeclaration(namedDecl)) ? applyDiscriminatorToObjectProperties(
3595
+ properties: effectiveNamedDecl !== void 0 && (ts5.isClassDeclaration(effectiveNamedDecl) || ts5.isInterfaceDeclaration(effectiveNamedDecl) || ts5.isTypeAliasDeclaration(effectiveNamedDecl)) ? applyDiscriminatorToObjectProperties(
3705
3596
  properties,
3706
- namedDecl,
3597
+ effectiveNamedDecl,
3707
3598
  type,
3708
3599
  checker,
3709
3600
  file,
@@ -3713,17 +3604,17 @@ function resolveObjectType(type, checker, file, typeRegistry, visiting, sourceNo
3713
3604
  additionalProperties: true
3714
3605
  };
3715
3606
  if (registryTypeName !== void 0 && shouldRegisterNamedType) {
3716
- const annotations = namedDecl ? extractJSDocAnnotationNodes(namedDecl, file, makeParseOptions(extensionRegistry)) : void 0;
3717
- const metadata = namedDecl !== void 0 ? resolveNodeMetadata(
3607
+ const annotations = effectiveNamedDecl ? extractNamedTypeAnnotations(effectiveNamedDecl, checker, file, extensionRegistry) : void 0;
3608
+ const metadata = effectiveNamedDecl !== void 0 ? resolveNodeMetadata(
3718
3609
  metadataPolicy,
3719
3610
  "type",
3720
3611
  registryTypeName,
3721
- namedDecl,
3612
+ effectiveNamedDecl,
3722
3613
  checker,
3723
3614
  extensionRegistry,
3724
3615
  {
3725
3616
  checker,
3726
- declaration: namedDecl,
3617
+ declaration: effectiveNamedDecl,
3727
3618
  subjectType: type
3728
3619
  }
3729
3620
  ) : void 0;
@@ -3732,7 +3623,7 @@ function resolveObjectType(type, checker, file, typeRegistry, visiting, sourceNo
3732
3623
  ...metadata !== void 0 && { metadata },
3733
3624
  type: objectNode,
3734
3625
  ...annotations !== void 0 && annotations.length > 0 && { annotations },
3735
- provenance: provenanceForDeclaration(namedDecl, file)
3626
+ provenance: provenanceForDeclaration(effectiveNamedDecl, file)
3736
3627
  };
3737
3628
  return {
3738
3629
  kind: "reference",
@@ -3749,12 +3640,12 @@ function getNamedTypeFieldNodeInfoMap(type, checker, file, typeRegistry, visitin
3749
3640
  for (const symbol of symbols) {
3750
3641
  const declarations = symbol.declarations;
3751
3642
  if (!declarations) continue;
3752
- const classDecl = declarations.find(ts6.isClassDeclaration);
3643
+ const classDecl = declarations.find(ts5.isClassDeclaration);
3753
3644
  if (classDecl) {
3754
3645
  const map = /* @__PURE__ */ new Map();
3755
3646
  const hostType = checker.getTypeAtLocation(classDecl);
3756
3647
  for (const member of classDecl.members) {
3757
- if (ts6.isPropertyDeclaration(member) && ts6.isIdentifier(member.name)) {
3648
+ if (ts5.isPropertyDeclaration(member) && ts5.isIdentifier(member.name)) {
3758
3649
  const fieldNode = analyzeFieldToIR(
3759
3650
  member,
3760
3651
  checker,
@@ -3778,7 +3669,7 @@ function getNamedTypeFieldNodeInfoMap(type, checker, file, typeRegistry, visitin
3778
3669
  }
3779
3670
  return map;
3780
3671
  }
3781
- const interfaceDecl = declarations.find(ts6.isInterfaceDeclaration);
3672
+ const interfaceDecl = declarations.find(ts5.isInterfaceDeclaration);
3782
3673
  if (interfaceDecl) {
3783
3674
  return buildFieldNodeInfoMap(
3784
3675
  interfaceDecl.members,
@@ -3792,7 +3683,7 @@ function getNamedTypeFieldNodeInfoMap(type, checker, file, typeRegistry, visitin
3792
3683
  extensionRegistry
3793
3684
  );
3794
3685
  }
3795
- const typeAliasDecl = declarations.find(ts6.isTypeAliasDeclaration);
3686
+ const typeAliasDecl = declarations.find(ts5.isTypeAliasDeclaration);
3796
3687
  const typeAliasMembers = typeAliasDecl === void 0 ? null : getObjectLikeTypeAliasMembers(typeAliasDecl.type);
3797
3688
  if (typeAliasDecl && typeAliasMembers !== null) {
3798
3689
  return buildFieldNodeInfoMap(
@@ -3816,10 +3707,10 @@ function extractArrayElementTypeNode(sourceNode, checker) {
3816
3707
  return void 0;
3817
3708
  }
3818
3709
  const resolvedTypeNode = resolveAliasedTypeNode(typeNode, checker);
3819
- if (ts6.isArrayTypeNode(resolvedTypeNode)) {
3710
+ if (ts5.isArrayTypeNode(resolvedTypeNode)) {
3820
3711
  return resolvedTypeNode.elementType;
3821
3712
  }
3822
- if (ts6.isTypeReferenceNode(resolvedTypeNode) && ts6.isIdentifier(resolvedTypeNode.typeName) && resolvedTypeNode.typeName.text === "Array" && resolvedTypeNode.typeArguments?.[0]) {
3713
+ if (ts5.isTypeReferenceNode(resolvedTypeNode) && ts5.isIdentifier(resolvedTypeNode.typeName) && resolvedTypeNode.typeName.text === "Array" && resolvedTypeNode.typeArguments?.[0]) {
3823
3714
  return resolvedTypeNode.typeArguments[0];
3824
3715
  }
3825
3716
  return void 0;
@@ -3830,13 +3721,13 @@ function extractUnionMemberTypeNodes(sourceNode, checker) {
3830
3721
  return [];
3831
3722
  }
3832
3723
  const resolvedTypeNode = resolveAliasedTypeNode(typeNode, checker);
3833
- return ts6.isUnionTypeNode(resolvedTypeNode) ? [...resolvedTypeNode.types] : [];
3724
+ return ts5.isUnionTypeNode(resolvedTypeNode) ? [...resolvedTypeNode.types] : [];
3834
3725
  }
3835
3726
  function resolveAliasedTypeNode(typeNode, checker, visited = /* @__PURE__ */ new Set()) {
3836
- if (ts6.isParenthesizedTypeNode(typeNode)) {
3727
+ if (ts5.isParenthesizedTypeNode(typeNode)) {
3837
3728
  return resolveAliasedTypeNode(typeNode.type, checker, visited);
3838
3729
  }
3839
- if (!ts6.isTypeReferenceNode(typeNode) || !ts6.isIdentifier(typeNode.typeName)) {
3730
+ if (!ts5.isTypeReferenceNode(typeNode) || !ts5.isIdentifier(typeNode.typeName)) {
3840
3731
  return typeNode;
3841
3732
  }
3842
3733
  const aliasDecl = getTypeAliasDeclarationFromTypeReference(typeNode, checker);
@@ -3847,15 +3738,15 @@ function resolveAliasedTypeNode(typeNode, checker, visited = /* @__PURE__ */ new
3847
3738
  return resolveAliasedTypeNode(aliasDecl.type, checker, visited);
3848
3739
  }
3849
3740
  function isNullishTypeNode(typeNode) {
3850
- if (typeNode.kind === ts6.SyntaxKind.NullKeyword || typeNode.kind === ts6.SyntaxKind.UndefinedKeyword) {
3741
+ if (typeNode.kind === ts5.SyntaxKind.NullKeyword || typeNode.kind === ts5.SyntaxKind.UndefinedKeyword) {
3851
3742
  return true;
3852
3743
  }
3853
- return ts6.isLiteralTypeNode(typeNode) && (typeNode.literal.kind === ts6.SyntaxKind.NullKeyword || typeNode.literal.kind === ts6.SyntaxKind.UndefinedKeyword);
3744
+ return ts5.isLiteralTypeNode(typeNode) && (typeNode.literal.kind === ts5.SyntaxKind.NullKeyword || typeNode.literal.kind === ts5.SyntaxKind.UndefinedKeyword);
3854
3745
  }
3855
3746
  function buildFieldNodeInfoMap(members, checker, file, typeRegistry, visiting, metadataPolicy, hostType, diagnostics, extensionRegistry) {
3856
3747
  const map = /* @__PURE__ */ new Map();
3857
3748
  for (const member of members) {
3858
- if (ts6.isPropertySignature(member)) {
3749
+ if (ts5.isPropertySignature(member)) {
3859
3750
  const fieldNode = analyzeInterfacePropertyToIR(
3860
3751
  member,
3861
3752
  checker,
@@ -3881,7 +3772,7 @@ function buildFieldNodeInfoMap(members, checker, file, typeRegistry, visiting, m
3881
3772
  }
3882
3773
  var MAX_ALIAS_CHAIN_DEPTH = 8;
3883
3774
  function extractTypeAliasConstraintNodes(typeNode, checker, file, extensionRegistry, depth = 0) {
3884
- if (!ts6.isTypeReferenceNode(typeNode)) return [];
3775
+ if (!ts5.isTypeReferenceNode(typeNode)) return [];
3885
3776
  if (depth >= MAX_ALIAS_CHAIN_DEPTH) {
3886
3777
  const aliasName = typeNode.typeName.getText();
3887
3778
  throw new Error(
@@ -3890,7 +3781,7 @@ function extractTypeAliasConstraintNodes(typeNode, checker, file, extensionRegis
3890
3781
  }
3891
3782
  const aliasDecl = getTypeAliasDeclarationFromTypeReference(typeNode, checker);
3892
3783
  if (!aliasDecl) return [];
3893
- if (ts6.isTypeLiteralNode(aliasDecl.type)) return [];
3784
+ if (ts5.isTypeLiteralNode(aliasDecl.type)) return [];
3894
3785
  const aliasFieldType = resolveTypeNode(
3895
3786
  checker.getTypeAtLocation(aliasDecl.type),
3896
3787
  checker,
@@ -3934,14 +3825,14 @@ function getNamedTypeName(type) {
3934
3825
  const symbol = type.getSymbol();
3935
3826
  if (symbol?.declarations) {
3936
3827
  const decl = symbol.declarations[0];
3937
- if (decl && (ts6.isClassDeclaration(decl) || ts6.isInterfaceDeclaration(decl) || ts6.isTypeAliasDeclaration(decl))) {
3938
- const name = ts6.isClassDeclaration(decl) ? decl.name?.text : decl.name.text;
3828
+ if (decl && (ts5.isClassDeclaration(decl) || ts5.isInterfaceDeclaration(decl) || ts5.isTypeAliasDeclaration(decl))) {
3829
+ const name = ts5.isClassDeclaration(decl) ? decl.name?.text : decl.name.text;
3939
3830
  if (name) return name;
3940
3831
  }
3941
3832
  }
3942
3833
  const aliasSymbol = type.aliasSymbol;
3943
3834
  if (aliasSymbol?.declarations) {
3944
- const aliasDecl = aliasSymbol.declarations.find(ts6.isTypeAliasDeclaration);
3835
+ const aliasDecl = aliasSymbol.declarations.find(ts5.isTypeAliasDeclaration);
3945
3836
  if (aliasDecl) {
3946
3837
  return aliasDecl.name.text;
3947
3838
  }
@@ -3952,24 +3843,24 @@ function getNamedTypeDeclaration(type) {
3952
3843
  const symbol = type.getSymbol();
3953
3844
  if (symbol?.declarations) {
3954
3845
  const decl = symbol.declarations[0];
3955
- if (decl && (ts6.isClassDeclaration(decl) || ts6.isInterfaceDeclaration(decl) || ts6.isTypeAliasDeclaration(decl))) {
3846
+ if (decl && (ts5.isClassDeclaration(decl) || ts5.isInterfaceDeclaration(decl) || ts5.isTypeAliasDeclaration(decl))) {
3956
3847
  return decl;
3957
3848
  }
3958
3849
  }
3959
3850
  const aliasSymbol = type.aliasSymbol;
3960
3851
  if (aliasSymbol?.declarations) {
3961
- return aliasSymbol.declarations.find(ts6.isTypeAliasDeclaration);
3852
+ return aliasSymbol.declarations.find(ts5.isTypeAliasDeclaration);
3962
3853
  }
3963
3854
  return void 0;
3964
3855
  }
3965
3856
  function analyzeMethod(method, checker) {
3966
- if (!ts6.isIdentifier(method.name)) {
3857
+ if (!ts5.isIdentifier(method.name)) {
3967
3858
  return null;
3968
3859
  }
3969
3860
  const name = method.name.text;
3970
3861
  const parameters = [];
3971
3862
  for (const param of method.parameters) {
3972
- if (ts6.isIdentifier(param.name)) {
3863
+ if (ts5.isIdentifier(param.name)) {
3973
3864
  const paramInfo = analyzeParameter(param, checker);
3974
3865
  parameters.push(paramInfo);
3975
3866
  }
@@ -3980,7 +3871,7 @@ function analyzeMethod(method, checker) {
3980
3871
  return { name, parameters, returnTypeNode, returnType };
3981
3872
  }
3982
3873
  function analyzeParameter(param, checker) {
3983
- const name = ts6.isIdentifier(param.name) ? param.name.text : "param";
3874
+ const name = ts5.isIdentifier(param.name) ? param.name.text : "param";
3984
3875
  const typeNode = param.type;
3985
3876
  const type = checker.getTypeAtLocation(param);
3986
3877
  const formSpecExportName = detectFormSpecReference(typeNode);
@@ -3989,15 +3880,15 @@ function analyzeParameter(param, checker) {
3989
3880
  }
3990
3881
  function detectFormSpecReference(typeNode) {
3991
3882
  if (!typeNode) return null;
3992
- if (!ts6.isTypeReferenceNode(typeNode)) return null;
3993
- const typeName = ts6.isIdentifier(typeNode.typeName) ? typeNode.typeName.text : ts6.isQualifiedName(typeNode.typeName) ? typeNode.typeName.right.text : null;
3883
+ if (!ts5.isTypeReferenceNode(typeNode)) return null;
3884
+ const typeName = ts5.isIdentifier(typeNode.typeName) ? typeNode.typeName.text : ts5.isQualifiedName(typeNode.typeName) ? typeNode.typeName.right.text : null;
3994
3885
  if (typeName !== "InferSchema" && typeName !== "InferFormSchema") return null;
3995
3886
  const typeArg = typeNode.typeArguments?.[0];
3996
- if (!typeArg || !ts6.isTypeQueryNode(typeArg)) return null;
3997
- if (ts6.isIdentifier(typeArg.exprName)) {
3887
+ if (!typeArg || !ts5.isTypeQueryNode(typeArg)) return null;
3888
+ if (ts5.isIdentifier(typeArg.exprName)) {
3998
3889
  return typeArg.exprName.text;
3999
3890
  }
4000
- if (ts6.isQualifiedName(typeArg.exprName)) {
3891
+ if (ts5.isQualifiedName(typeArg.exprName)) {
4001
3892
  return typeArg.exprName.right.text;
4002
3893
  }
4003
3894
  return null;
@@ -4019,23 +3910,23 @@ function createProgramContextFromProgram(program, filePath) {
4019
3910
  function createProgramContext(filePath, additionalFiles) {
4020
3911
  const absolutePath = path.resolve(filePath);
4021
3912
  const fileDir = path.dirname(absolutePath);
4022
- const configPath = ts7.findConfigFile(fileDir, ts7.sys.fileExists.bind(ts7.sys), "tsconfig.json");
3913
+ const configPath = ts6.findConfigFile(fileDir, ts6.sys.fileExists.bind(ts6.sys), "tsconfig.json");
4023
3914
  let compilerOptions;
4024
3915
  let fileNames;
4025
3916
  if (configPath) {
4026
- const configFile = ts7.readConfigFile(configPath, ts7.sys.readFile.bind(ts7.sys));
3917
+ const configFile = ts6.readConfigFile(configPath, ts6.sys.readFile.bind(ts6.sys));
4027
3918
  if (configFile.error) {
4028
3919
  throw new Error(
4029
- `Error reading tsconfig.json: ${ts7.flattenDiagnosticMessageText(configFile.error.messageText, "\n")}`
3920
+ `Error reading tsconfig.json: ${ts6.flattenDiagnosticMessageText(configFile.error.messageText, "\n")}`
4030
3921
  );
4031
3922
  }
4032
- const parsed = ts7.parseJsonConfigFileContent(
3923
+ const parsed = ts6.parseJsonConfigFileContent(
4033
3924
  configFile.config,
4034
- ts7.sys,
3925
+ ts6.sys,
4035
3926
  path.dirname(configPath)
4036
3927
  );
4037
3928
  if (parsed.errors.length > 0) {
4038
- const errorMessages = parsed.errors.map((e) => ts7.flattenDiagnosticMessageText(e.messageText, "\n")).join("\n");
3929
+ const errorMessages = parsed.errors.map((e) => ts6.flattenDiagnosticMessageText(e.messageText, "\n")).join("\n");
4039
3930
  throw new Error(`Error parsing tsconfig.json: ${errorMessages}`);
4040
3931
  }
4041
3932
  compilerOptions = parsed.options;
@@ -4043,9 +3934,9 @@ function createProgramContext(filePath, additionalFiles) {
4043
3934
  fileNames = [.../* @__PURE__ */ new Set([...parsed.fileNames, absolutePath, ...normalizedAdditional])];
4044
3935
  } else {
4045
3936
  compilerOptions = {
4046
- target: ts7.ScriptTarget.ES2022,
4047
- module: ts7.ModuleKind.NodeNext,
4048
- moduleResolution: ts7.ModuleResolutionKind.NodeNext,
3937
+ target: ts6.ScriptTarget.ES2022,
3938
+ module: ts6.ModuleKind.NodeNext,
3939
+ moduleResolution: ts6.ModuleResolutionKind.NodeNext,
4049
3940
  strict: true,
4050
3941
  skipLibCheck: true,
4051
3942
  declaration: true
@@ -4053,7 +3944,7 @@ function createProgramContext(filePath, additionalFiles) {
4053
3944
  const normalizedAdditional = (additionalFiles ?? []).map((f) => path.resolve(f));
4054
3945
  fileNames = [.../* @__PURE__ */ new Set([absolutePath, ...normalizedAdditional])];
4055
3946
  }
4056
- const program = ts7.createProgram(fileNames, compilerOptions);
3947
+ const program = ts6.createProgram(fileNames, compilerOptions);
4057
3948
  const sourceFile = program.getSourceFile(absolutePath);
4058
3949
  if (!sourceFile) {
4059
3950
  throw new Error(`Could not find source file: ${absolutePath}`);
@@ -4072,19 +3963,19 @@ function findNodeByName(sourceFile, name, predicate, getName) {
4072
3963
  result = node;
4073
3964
  return;
4074
3965
  }
4075
- ts7.forEachChild(node, visit);
3966
+ ts6.forEachChild(node, visit);
4076
3967
  }
4077
3968
  visit(sourceFile);
4078
3969
  return result;
4079
3970
  }
4080
3971
  function findClassByName(sourceFile, className) {
4081
- return findNodeByName(sourceFile, className, ts7.isClassDeclaration, (n) => n.name?.text);
3972
+ return findNodeByName(sourceFile, className, ts6.isClassDeclaration, (n) => n.name?.text);
4082
3973
  }
4083
3974
  function findInterfaceByName(sourceFile, interfaceName) {
4084
- return findNodeByName(sourceFile, interfaceName, ts7.isInterfaceDeclaration, (n) => n.name.text);
3975
+ return findNodeByName(sourceFile, interfaceName, ts6.isInterfaceDeclaration, (n) => n.name.text);
4085
3976
  }
4086
3977
  function findTypeAliasByName(sourceFile, aliasName) {
4087
- return findNodeByName(sourceFile, aliasName, ts7.isTypeAliasDeclaration, (n) => n.name.text);
3978
+ return findNodeByName(sourceFile, aliasName, ts6.isTypeAliasDeclaration, (n) => n.name.text);
4088
3979
  }
4089
3980
  function getResolvedObjectRootType(rootType, typeRegistry) {
4090
3981
  if (rootType.kind === "object") {
@@ -4124,22 +4015,22 @@ function createResolvedObjectAliasAnalysis(name, rootType, typeRegistry, rootInf
4124
4015
  };
4125
4016
  }
4126
4017
  function containsTypeReferenceInObjectLikeAlias(typeNode) {
4127
- if (ts7.isParenthesizedTypeNode(typeNode)) {
4018
+ if (ts6.isParenthesizedTypeNode(typeNode)) {
4128
4019
  return containsTypeReferenceInObjectLikeAlias(typeNode.type);
4129
4020
  }
4130
- if (ts7.isTypeReferenceNode(typeNode)) {
4021
+ if (ts6.isTypeReferenceNode(typeNode)) {
4131
4022
  return true;
4132
4023
  }
4133
- return ts7.isIntersectionTypeNode(typeNode) && typeNode.types.some((member) => containsTypeReferenceInObjectLikeAlias(member));
4024
+ return ts6.isIntersectionTypeNode(typeNode) && typeNode.types.some((member) => containsTypeReferenceInObjectLikeAlias(member));
4134
4025
  }
4135
4026
  function collectFallbackAliasMemberPropertyNames(typeNode, checker) {
4136
- if (ts7.isParenthesizedTypeNode(typeNode)) {
4027
+ if (ts6.isParenthesizedTypeNode(typeNode)) {
4137
4028
  return collectFallbackAliasMemberPropertyNames(typeNode.type, checker);
4138
4029
  }
4139
- if (ts7.isTypeLiteralNode(typeNode)) {
4030
+ if (ts6.isTypeLiteralNode(typeNode)) {
4140
4031
  const propertyNames = [];
4141
4032
  for (const member of typeNode.members) {
4142
- if (!ts7.isPropertySignature(member)) {
4033
+ if (!ts6.isPropertySignature(member)) {
4143
4034
  continue;
4144
4035
  }
4145
4036
  const propertyName = getAnalyzableObjectLikePropertyName(member.name);
@@ -4149,13 +4040,13 @@ function collectFallbackAliasMemberPropertyNames(typeNode, checker) {
4149
4040
  }
4150
4041
  return propertyNames;
4151
4042
  }
4152
- if (ts7.isTypeReferenceNode(typeNode)) {
4043
+ if (ts6.isTypeReferenceNode(typeNode)) {
4153
4044
  return checker.getTypeFromTypeNode(typeNode).getProperties().map((property) => property.getName());
4154
4045
  }
4155
4046
  return null;
4156
4047
  }
4157
4048
  function findFallbackAliasDuplicatePropertyNames(typeNode, checker) {
4158
- if (!ts7.isIntersectionTypeNode(typeNode)) {
4049
+ if (!ts6.isIntersectionTypeNode(typeNode)) {
4159
4050
  return [];
4160
4051
  }
4161
4052
  const seen = /* @__PURE__ */ new Set();
@@ -4345,7 +4236,7 @@ function makeFileProvenance(filePath) {
4345
4236
  }
4346
4237
 
4347
4238
  // src/generators/class-schema.ts
4348
- import * as ts9 from "typescript";
4239
+ import * as ts8 from "typescript";
4349
4240
 
4350
4241
  // src/metadata/collision-guards.ts
4351
4242
  function assertUniqueSerializedNames(entries, scope) {
@@ -4514,7 +4405,7 @@ function generateJsonSchemaFromIR(ir, options) {
4514
4405
  applyConstraints(ctx.defs[schemaName], typeDef.constraints, ctx);
4515
4406
  }
4516
4407
  if (typeDef.annotations && typeDef.annotations.length > 0) {
4517
- applyAnnotations(ctx.defs[schemaName], typeDef.annotations, ctx);
4408
+ applyAnnotations(ctx.defs[schemaName], typeDef.annotations, ctx, typeDef.type);
4518
4409
  }
4519
4410
  }
4520
4411
  const properties = {};
@@ -4587,7 +4478,7 @@ function generateFieldSchema(field, ctx) {
4587
4478
  }
4588
4479
  }
4589
4480
  applyResolvedMetadata(schema, field.metadata);
4590
- applyAnnotations(schema, rootAnnotations, ctx);
4481
+ applyAnnotations(schema, rootAnnotations, ctx, field.type);
4591
4482
  if (itemStringSchema !== void 0) {
4592
4483
  applyAnnotations(itemStringSchema, itemAnnotations, ctx);
4593
4484
  }
@@ -4630,32 +4521,36 @@ function applyPathTargetedConstraints(schema, pathConstraints, ctx, typeNode) {
4630
4521
  return schema;
4631
4522
  }
4632
4523
  if (schema.$ref) {
4633
- const { $ref, ...rest } = schema;
4634
- const refPart = { $ref };
4635
- const overridePart = {
4636
- properties: propertyOverrides,
4637
- ...rest
4524
+ return {
4525
+ ...schema,
4526
+ properties: propertyOverrides
4638
4527
  };
4639
- return { allOf: [refPart, overridePart] };
4640
4528
  }
4641
4529
  if (schema.type === "object" && schema.properties) {
4642
- const missingOverrides = {};
4643
4530
  for (const [target, overrideSchema] of Object.entries(propertyOverrides)) {
4644
- if (schema.properties[target]) {
4645
- mergeSchemaOverride(schema.properties[target], overrideSchema);
4646
- } else {
4647
- missingOverrides[target] = overrideSchema;
4531
+ if (Object.hasOwn(schema.properties, target)) {
4532
+ const existing = schema.properties[target];
4533
+ if (existing) {
4534
+ mergeSchemaOverride(existing, overrideSchema);
4535
+ continue;
4536
+ }
4648
4537
  }
4538
+ Object.defineProperty(schema.properties, target, {
4539
+ value: overrideSchema,
4540
+ writable: true,
4541
+ enumerable: true,
4542
+ configurable: true
4543
+ });
4649
4544
  }
4650
- if (Object.keys(missingOverrides).length === 0) {
4651
- return schema;
4652
- }
4653
- return {
4654
- allOf: [schema, { properties: missingOverrides }]
4655
- };
4545
+ return schema;
4656
4546
  }
4657
4547
  if (schema.allOf) {
4658
- schema.allOf = [...schema.allOf, { properties: propertyOverrides }];
4548
+ const overrideMember = { properties: propertyOverrides };
4549
+ const flattened = tryFlattenAllOfToSiblings(schema, overrideMember);
4550
+ if (flattened !== void 0) {
4551
+ return flattened;
4552
+ }
4553
+ schema.allOf = [...schema.allOf, overrideMember];
4659
4554
  return schema;
4660
4555
  }
4661
4556
  return schema;
@@ -4768,7 +4663,7 @@ function generatePropertySchema(prop, ctx) {
4768
4663
  const schema = generateTypeNode(prop.type, ctx);
4769
4664
  applyConstraints(schema, prop.constraints, ctx);
4770
4665
  applyResolvedMetadata(schema, prop.metadata);
4771
- applyAnnotations(schema, prop.annotations, ctx);
4666
+ applyAnnotations(schema, prop.annotations, ctx, prop.type);
4772
4667
  return schema;
4773
4668
  }
4774
4669
  function generateUnionType(type, ctx) {
@@ -4871,13 +4766,20 @@ function buildPropertyOverrides(pathConstraints, typeNode, ctx) {
4871
4766
  grouped.push(constraint);
4872
4767
  byTarget.set(target, grouped);
4873
4768
  }
4874
- const overrides = {};
4769
+ const overrides = /* @__PURE__ */ Object.create(null);
4875
4770
  for (const [target, constraints] of byTarget) {
4876
- overrides[resolveSerializedPropertyName(target, typeNode, ctx)] = buildPathOverrideSchema(
4771
+ const resolvedName = resolveSerializedPropertyName(target, typeNode, ctx);
4772
+ const schema = buildPathOverrideSchema(
4877
4773
  constraints.map(stripLeadingPathSegment),
4878
4774
  resolveTargetTypeNode(target, typeNode, ctx),
4879
4775
  ctx
4880
4776
  );
4777
+ Object.defineProperty(overrides, resolvedName, {
4778
+ value: schema,
4779
+ writable: true,
4780
+ enumerable: true,
4781
+ configurable: true
4782
+ });
4881
4783
  }
4882
4784
  return overrides;
4883
4785
  }
@@ -4904,6 +4806,34 @@ function buildPathOverrideSchema(constraints, typeNode, ctx) {
4904
4806
  schema.properties = buildPropertyOverrides(nestedConstraints, effectiveType, ctx);
4905
4807
  return schema;
4906
4808
  }
4809
+ function tryFlattenAllOfToSiblings(schema, overrideMember) {
4810
+ if (schema.allOf?.length !== 1) {
4811
+ return void 0;
4812
+ }
4813
+ const [soleMember] = schema.allOf;
4814
+ if (soleMember === void 0) {
4815
+ return void 0;
4816
+ }
4817
+ const { allOf: _allOf, ...outerRest } = schema;
4818
+ const outerKeys = new Set(Object.keys(outerRest));
4819
+ const memberKeys = new Set(Object.keys(soleMember));
4820
+ const overrideKeys = new Set(Object.keys(overrideMember));
4821
+ for (const key of memberKeys) {
4822
+ if (outerKeys.has(key) || overrideKeys.has(key)) {
4823
+ return void 0;
4824
+ }
4825
+ }
4826
+ for (const key of overrideKeys) {
4827
+ if (outerKeys.has(key)) {
4828
+ return void 0;
4829
+ }
4830
+ }
4831
+ return {
4832
+ ...outerRest,
4833
+ ...soleMember,
4834
+ ...overrideMember
4835
+ };
4836
+ }
4907
4837
  function mergeSchemaOverride(target, override) {
4908
4838
  const nullableValueBranch = getNullableUnionValueSchema(target);
4909
4839
  if (nullableValueBranch !== void 0) {
@@ -4911,11 +4841,16 @@ function mergeSchemaOverride(target, override) {
4911
4841
  return;
4912
4842
  }
4913
4843
  if (override.properties !== void 0) {
4914
- const mergedProperties = target.properties ?? {};
4844
+ const mergedProperties = target.properties ?? /* @__PURE__ */ Object.create(null);
4915
4845
  for (const [name, propertyOverride] of Object.entries(override.properties)) {
4916
- const existing = mergedProperties[name];
4846
+ const existing = Object.hasOwn(mergedProperties, name) ? mergedProperties[name] : void 0;
4917
4847
  if (existing === void 0) {
4918
- mergedProperties[name] = propertyOverride;
4848
+ Object.defineProperty(mergedProperties, name, {
4849
+ value: propertyOverride,
4850
+ writable: true,
4851
+ enumerable: true,
4852
+ configurable: true
4853
+ });
4919
4854
  } else {
4920
4855
  mergeSchemaOverride(existing, propertyOverride);
4921
4856
  }
@@ -4933,7 +4868,12 @@ function mergeSchemaOverride(target, override) {
4933
4868
  if (key === "properties" || key === "items") {
4934
4869
  continue;
4935
4870
  }
4936
- target[key] = value;
4871
+ Object.defineProperty(target, key, {
4872
+ value,
4873
+ writable: true,
4874
+ enumerable: true,
4875
+ configurable: true
4876
+ });
4937
4877
  }
4938
4878
  }
4939
4879
  function stripLeadingPathSegment(constraint) {
@@ -5033,7 +4973,7 @@ function applyConstraints(schema, constraints, ctx) {
5033
4973
  }
5034
4974
  }
5035
4975
  }
5036
- function applyAnnotations(schema, annotations, ctx) {
4976
+ function applyAnnotations(schema, annotations, ctx, typeNode) {
5037
4977
  for (const annotation of annotations) {
5038
4978
  switch (annotation.annotationKind) {
5039
4979
  case "displayName":
@@ -5046,7 +4986,7 @@ function applyAnnotations(schema, annotations, ctx) {
5046
4986
  schema[`${ctx.vendorPrefix}-remarks`] = annotation.value;
5047
4987
  break;
5048
4988
  case "defaultValue":
5049
- schema.default = annotation.value;
4989
+ schema.default = coerceDefaultValue(annotation.value, typeNode, schema, ctx);
5050
4990
  break;
5051
4991
  case "format":
5052
4992
  schema.format = annotation.value;
@@ -5071,6 +5011,34 @@ function applyAnnotations(schema, annotations, ctx) {
5071
5011
  }
5072
5012
  }
5073
5013
  }
5014
+ function coerceDefaultValue(value, typeNode, emittedSchema, ctx) {
5015
+ if (typeNode?.kind !== "custom") {
5016
+ return value;
5017
+ }
5018
+ const registration = ctx.extensionRegistry?.findType(typeNode.typeId);
5019
+ if (registration === void 0) {
5020
+ return value;
5021
+ }
5022
+ if (registration.serializeDefault !== void 0) {
5023
+ return registration.serializeDefault(value, typeNode.payload);
5024
+ }
5025
+ const declaredType = emittedSchema["type"];
5026
+ if (declaredType === "string" && typeof value !== "string") {
5027
+ if (typeof value === "number") {
5028
+ if (!Number.isFinite(value)) {
5029
+ return value;
5030
+ }
5031
+ return String(value);
5032
+ }
5033
+ if (typeof value === "boolean") {
5034
+ return String(value);
5035
+ }
5036
+ if (typeof value === "bigint") {
5037
+ return value.toString();
5038
+ }
5039
+ }
5040
+ return value;
5041
+ }
5074
5042
  function generateCustomType(type, ctx) {
5075
5043
  const registration = ctx.extensionRegistry?.findType(type.typeId);
5076
5044
  if (registration === void 0) {
@@ -5203,7 +5171,9 @@ import {
5203
5171
  import {
5204
5172
  getTagDefinition as getTagDefinition2,
5205
5173
  normalizeFormSpecTagName as normalizeFormSpecTagName2,
5206
- getSyntheticLogger as getSyntheticLogger2
5174
+ getRegistryLogger,
5175
+ _validateExtensionSetup,
5176
+ logSetupDiagnostics
5207
5177
  } from "@formspec/analysis/internal";
5208
5178
  var BUILTIN_METADATA_TAGS = /* @__PURE__ */ new Set(["apiName", "displayName"]);
5209
5179
  function buildConstraintTagSources(extensions) {
@@ -5213,16 +5183,32 @@ function buildConstraintTagSources(extensions) {
5213
5183
  constraintTags: extension.constraintTags.map((tag) => ({
5214
5184
  tagName: normalizeFormSpecTagName2(tag.tagName)
5215
5185
  }))
5186
+ } : {},
5187
+ // Include customTypes so _validateExtensionSetup can check tsTypeNames for
5188
+ // unsupported built-in overrides and invalid identifier patterns.
5189
+ ...extension.types !== void 0 ? {
5190
+ customTypes: extension.types.map((type) => ({
5191
+ // tsTypeNames: deprecated in favour of symbol-based detection, but
5192
+ // still required for name-based validation in _validateExtensionSetup
5193
+ // until the bridge is fully retired (see §synthetic-checker-retirement §4C).
5194
+ tsTypeNames: type.tsTypeNames ?? [type.typeName]
5195
+ }))
5216
5196
  } : {}
5217
5197
  }));
5218
5198
  }
5219
5199
  function createExtensionRegistry(extensions) {
5220
- const registryLog = getSyntheticLogger2();
5200
+ const registryLog = getRegistryLogger();
5221
5201
  registryLog.debug("createExtensionRegistry: constructing", {
5222
5202
  extensionCount: extensions.length,
5223
5203
  extensionIds: extensions.map((e) => e.extensionId)
5224
5204
  });
5225
- const reservedTagSources = buildConstraintTagSources(extensions);
5205
+ const extensionTagSources = buildConstraintTagSources(extensions);
5206
+ const setupDiagnostics = _validateExtensionSetup(extensionTagSources);
5207
+ logSetupDiagnostics(registryLog, {
5208
+ diagnosticCount: setupDiagnostics.length,
5209
+ codes: setupDiagnostics.map((d) => d.kind)
5210
+ });
5211
+ const reservedTagSources = extensionTagSources;
5226
5212
  let symbolMap = /* @__PURE__ */ new Map();
5227
5213
  const typeMap = /* @__PURE__ */ new Map();
5228
5214
  const typeNameMap = /* @__PURE__ */ new Map();
@@ -5359,10 +5345,12 @@ function createExtensionRegistry(extensions) {
5359
5345
  constraintTagCount: constraintTagMap.size,
5360
5346
  broadeningCount: builtinBroadeningMap.size,
5361
5347
  annotationCount: annotationMap.size,
5362
- metadataSlotCount: metadataSlotMap.size
5348
+ metadataSlotCount: metadataSlotMap.size,
5349
+ setupDiagnosticCount: setupDiagnostics.length
5363
5350
  });
5364
5351
  return {
5365
5352
  extensions,
5353
+ setupDiagnostics,
5366
5354
  findType: (typeId) => typeMap.get(typeId),
5367
5355
  findTypeByName: (typeName) => typeNameMap.get(typeName),
5368
5356
  findTypeByBrand: (brand) => brandMap.get(brand),
@@ -5378,7 +5366,7 @@ function createExtensionRegistry(extensions) {
5378
5366
  }
5379
5367
 
5380
5368
  // src/extensions/symbol-registry.ts
5381
- import * as ts8 from "typescript";
5369
+ import * as ts7 from "typescript";
5382
5370
  import * as path2 from "path";
5383
5371
 
5384
5372
  // src/ui-schema/schema.ts
@@ -5771,7 +5759,7 @@ function formatLocation(location) {
5771
5759
  }
5772
5760
  function resolveStaticOptions(options) {
5773
5761
  const legacyRegistry = options.extensionRegistry;
5774
- const configRegistry = legacyRegistry === void 0 && options.config?.extensions !== void 0 ? createExtensionRegistry(options.config.extensions) : void 0;
5762
+ const configRegistry = legacyRegistry === void 0 && options.config?.extensions !== void 0 && options.config.extensions.length > 0 ? createExtensionRegistry(options.config.extensions) : void 0;
5775
5763
  return {
5776
5764
  extensionRegistry: legacyRegistry ?? configRegistry,
5777
5765
  // eslint-disable-next-line @typescript-eslint/no-deprecated -- migration bridge reads deprecated fields