@formspec/build 0.1.0-alpha.32 → 0.1.0-alpha.34
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/analyzer/class-analyzer.d.ts +23 -4
- package/dist/analyzer/class-analyzer.d.ts.map +1 -1
- package/dist/analyzer/program.d.ts +3 -3
- package/dist/analyzer/program.d.ts.map +1 -1
- package/dist/analyzer/tsdoc-parser.d.ts +6 -3
- package/dist/analyzer/tsdoc-parser.d.ts.map +1 -1
- package/dist/browser.cjs +65 -7
- package/dist/browser.cjs.map +1 -1
- package/dist/browser.js +68 -4
- package/dist/browser.js.map +1 -1
- package/dist/build-alpha.d.ts +17 -0
- package/dist/build-beta.d.ts +17 -0
- package/dist/build-internal.d.ts +17 -0
- package/dist/build.d.ts +17 -0
- package/dist/cli.cjs +483 -211
- package/dist/cli.cjs.map +1 -1
- package/dist/cli.js +466 -186
- package/dist/cli.js.map +1 -1
- package/dist/extensions/registry.d.ts.map +1 -1
- package/dist/generators/class-schema.d.ts +4 -1
- package/dist/generators/class-schema.d.ts.map +1 -1
- package/dist/generators/discovered-schema.d.ts.map +1 -1
- package/dist/generators/mixed-authoring.d.ts.map +1 -1
- package/dist/index.cjs +478 -207
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +465 -186
- package/dist/index.js.map +1 -1
- package/dist/internals.cjs +421 -165
- package/dist/internals.cjs.map +1 -1
- package/dist/internals.d.ts +1 -1
- package/dist/internals.d.ts.map +1 -1
- package/dist/internals.js +427 -163
- package/dist/internals.js.map +1 -1
- package/package.json +4 -4
package/dist/internals.cjs
CHANGED
|
@@ -805,7 +805,7 @@ function createFormSpecTSDocConfig(extensionTagNames = []) {
|
|
|
805
805
|
})
|
|
806
806
|
);
|
|
807
807
|
}
|
|
808
|
-
for (const tagName of ["displayName", "format", "placeholder"]) {
|
|
808
|
+
for (const tagName of ["apiName", "displayName", "format", "placeholder"]) {
|
|
809
809
|
config.addTagDefinition(
|
|
810
810
|
new import_tsdoc.TSDocTagDefinition({
|
|
811
811
|
tagName: "@" + tagName,
|
|
@@ -839,6 +839,16 @@ function sharedTagValueOptions(options) {
|
|
|
839
839
|
};
|
|
840
840
|
}
|
|
841
841
|
var SYNTHETIC_TYPE_FORMAT_FLAGS = ts.TypeFormatFlags.NoTruncation | ts.TypeFormatFlags.UseAliasDefinedOutsideCurrentScope;
|
|
842
|
+
function getExtensionTypeNames(registry) {
|
|
843
|
+
if (registry === void 0) {
|
|
844
|
+
return /* @__PURE__ */ new Set();
|
|
845
|
+
}
|
|
846
|
+
return new Set(
|
|
847
|
+
registry.extensions.flatMap(
|
|
848
|
+
(ext) => (ext.types ?? []).flatMap((t) => t.tsTypeNames ?? [t.typeName])
|
|
849
|
+
)
|
|
850
|
+
);
|
|
851
|
+
}
|
|
842
852
|
function collectImportedNames(sourceFile) {
|
|
843
853
|
const importedNames = /* @__PURE__ */ new Set();
|
|
844
854
|
for (const statement of sourceFile.statements) {
|
|
@@ -878,6 +888,9 @@ function isNonReferenceIdentifier(node) {
|
|
|
878
888
|
return false;
|
|
879
889
|
}
|
|
880
890
|
function statementReferencesImportedName(statement, importedNames) {
|
|
891
|
+
if (importedNames.size === 0) {
|
|
892
|
+
return false;
|
|
893
|
+
}
|
|
881
894
|
let referencesImportedName = false;
|
|
882
895
|
const visit = (node) => {
|
|
883
896
|
if (referencesImportedName) {
|
|
@@ -892,14 +905,17 @@ function statementReferencesImportedName(statement, importedNames) {
|
|
|
892
905
|
visit(statement);
|
|
893
906
|
return referencesImportedName;
|
|
894
907
|
}
|
|
895
|
-
function buildSupportingDeclarations(sourceFile) {
|
|
908
|
+
function buildSupportingDeclarations(sourceFile, extensionTypeNames) {
|
|
896
909
|
const importedNames = collectImportedNames(sourceFile);
|
|
910
|
+
const importedNamesToSkip = new Set(
|
|
911
|
+
[...importedNames].filter((name) => !extensionTypeNames.has(name))
|
|
912
|
+
);
|
|
897
913
|
return sourceFile.statements.filter((statement) => {
|
|
898
914
|
if (ts.isImportDeclaration(statement)) return false;
|
|
899
915
|
if (ts.isImportEqualsDeclaration(statement)) return false;
|
|
900
916
|
if (ts.isExportDeclaration(statement) && statement.moduleSpecifier !== void 0)
|
|
901
917
|
return false;
|
|
902
|
-
if (
|
|
918
|
+
if (statementReferencesImportedName(statement, importedNamesToSkip)) {
|
|
903
919
|
return false;
|
|
904
920
|
}
|
|
905
921
|
return true;
|
|
@@ -1156,6 +1172,14 @@ function buildCompilerBackedConstraintDiagnostics(node, sourceFile, tagName, par
|
|
|
1156
1172
|
extensionId: extension.extensionId,
|
|
1157
1173
|
...extension.constraintTags !== void 0 ? {
|
|
1158
1174
|
constraintTags: extension.constraintTags.map((tag) => ({ tagName: tag.tagName }))
|
|
1175
|
+
} : {},
|
|
1176
|
+
...extension.metadataSlots !== void 0 ? {
|
|
1177
|
+
metadataSlots: extension.metadataSlots
|
|
1178
|
+
} : {},
|
|
1179
|
+
...extension.types !== void 0 ? {
|
|
1180
|
+
customTypes: extension.types.map((t) => ({
|
|
1181
|
+
tsTypeNames: t.tsTypeNames ?? [t.typeName]
|
|
1182
|
+
}))
|
|
1159
1183
|
} : {}
|
|
1160
1184
|
}))
|
|
1161
1185
|
} : {}
|
|
@@ -1177,7 +1201,10 @@ var parseResultCache = /* @__PURE__ */ new Map();
|
|
|
1177
1201
|
function getParser(options) {
|
|
1178
1202
|
const extensionTagNames = [
|
|
1179
1203
|
...options?.extensionRegistry?.extensions.flatMap(
|
|
1180
|
-
(extension) => (extension.constraintTags ?? []).map((tag) => tag.tagName)
|
|
1204
|
+
(extension) => (extension.constraintTags ?? []).map((tag) => (0, import_internal.normalizeFormSpecTagName)(tag.tagName))
|
|
1205
|
+
) ?? [],
|
|
1206
|
+
...options?.extensionRegistry?.extensions.flatMap(
|
|
1207
|
+
(extension) => (extension.metadataSlots ?? []).map((slot) => (0, import_internal.normalizeFormSpecTagName)(slot.tagName))
|
|
1181
1208
|
) ?? []
|
|
1182
1209
|
].sort();
|
|
1183
1210
|
const cacheKey = extensionTagNames.join("|");
|
|
@@ -1197,7 +1224,16 @@ function getExtensionRegistryCacheKey(registry) {
|
|
|
1197
1224
|
(extension) => JSON.stringify({
|
|
1198
1225
|
extensionId: extension.extensionId,
|
|
1199
1226
|
typeNames: extension.types?.map((type) => type.typeName) ?? [],
|
|
1200
|
-
constraintTags: extension.constraintTags?.map((tag) => tag.tagName) ?? []
|
|
1227
|
+
constraintTags: extension.constraintTags?.map((tag) => (0, import_internal.normalizeFormSpecTagName)(tag.tagName)) ?? [],
|
|
1228
|
+
metadataSlots: extension.metadataSlots?.map((slot) => ({
|
|
1229
|
+
tagName: (0, import_internal.normalizeFormSpecTagName)(slot.tagName),
|
|
1230
|
+
declarationKinds: [...slot.declarationKinds].sort(),
|
|
1231
|
+
allowBare: slot.allowBare !== false,
|
|
1232
|
+
qualifiers: (slot.qualifiers ?? []).map((qualifier) => ({
|
|
1233
|
+
qualifier: qualifier.qualifier,
|
|
1234
|
+
...qualifier.sourceQualifier !== void 0 ? { sourceQualifier: qualifier.sourceQualifier } : {}
|
|
1235
|
+
})).sort((left, right) => left.qualifier.localeCompare(right.qualifier))
|
|
1236
|
+
})) ?? []
|
|
1201
1237
|
})
|
|
1202
1238
|
).join("|");
|
|
1203
1239
|
}
|
|
@@ -1232,7 +1268,8 @@ function parseTSDocTags(node, file = "", options) {
|
|
|
1232
1268
|
const rawTextTags = [];
|
|
1233
1269
|
const sourceFile = node.getSourceFile();
|
|
1234
1270
|
const sourceText = sourceFile.getFullText();
|
|
1235
|
-
const
|
|
1271
|
+
const extensionTypeNames = getExtensionTypeNames(options?.extensionRegistry);
|
|
1272
|
+
const supportingDeclarations = buildSupportingDeclarations(sourceFile, extensionTypeNames);
|
|
1236
1273
|
const commentRanges = ts.getLeadingCommentRanges(sourceText, node.getFullStart());
|
|
1237
1274
|
const rawTextFallbacks = collectRawTextFallbacks(node, file);
|
|
1238
1275
|
if (commentRanges) {
|
|
@@ -1640,6 +1677,9 @@ function extractDefaultValueAnnotation(initializer, file = "") {
|
|
|
1640
1677
|
function isObjectType(type) {
|
|
1641
1678
|
return !!(type.flags & ts3.TypeFlags.Object);
|
|
1642
1679
|
}
|
|
1680
|
+
function isIntersectionType(type) {
|
|
1681
|
+
return !!(type.flags & ts3.TypeFlags.Intersection);
|
|
1682
|
+
}
|
|
1643
1683
|
function isTypeReference(type) {
|
|
1644
1684
|
return !!(type.flags & ts3.TypeFlags.Object) && !!(type.objectFlags & ts3.ObjectFlags.Reference);
|
|
1645
1685
|
}
|
|
@@ -1660,76 +1700,54 @@ function makeParseOptions(extensionRegistry, fieldType, checker, subjectType, ho
|
|
|
1660
1700
|
...hostType !== void 0 && { hostType }
|
|
1661
1701
|
};
|
|
1662
1702
|
}
|
|
1663
|
-
function
|
|
1664
|
-
return
|
|
1665
|
-
|
|
1666
|
-
|
|
1667
|
-
|
|
1668
|
-
let displayName;
|
|
1669
|
-
let apiNamePlural;
|
|
1670
|
-
let displayNamePlural;
|
|
1671
|
-
for (const tag of getLeadingParsedTags(node)) {
|
|
1672
|
-
const value = tag.argumentText.trim();
|
|
1673
|
-
if (value === "") {
|
|
1674
|
-
continue;
|
|
1675
|
-
}
|
|
1676
|
-
if (tag.normalizedTagName === "apiName") {
|
|
1677
|
-
if (tag.target === null) {
|
|
1678
|
-
apiName ??= value;
|
|
1679
|
-
} else if (tag.target.kind === "variant") {
|
|
1680
|
-
if (tag.target.rawText === "singular") {
|
|
1681
|
-
apiName ??= value;
|
|
1682
|
-
} else if (tag.target.rawText === "plural") {
|
|
1683
|
-
apiNamePlural ??= value;
|
|
1684
|
-
}
|
|
1685
|
-
}
|
|
1686
|
-
continue;
|
|
1687
|
-
}
|
|
1688
|
-
if (tag.normalizedTagName === "displayName") {
|
|
1689
|
-
if (tag.target === null) {
|
|
1690
|
-
displayName ??= value;
|
|
1691
|
-
} else if (tag.target.kind === "variant") {
|
|
1692
|
-
if (tag.target.rawText === "singular") {
|
|
1693
|
-
displayName ??= value;
|
|
1694
|
-
} else if (tag.target.rawText === "plural") {
|
|
1695
|
-
displayNamePlural ??= value;
|
|
1696
|
-
}
|
|
1697
|
-
}
|
|
1698
|
-
}
|
|
1699
|
-
}
|
|
1700
|
-
const resolvedApiName = makeExplicitScalarMetadata(apiName);
|
|
1701
|
-
const resolvedDisplayName = makeExplicitScalarMetadata(displayName);
|
|
1702
|
-
const resolvedApiNamePlural = makeExplicitScalarMetadata(apiNamePlural);
|
|
1703
|
-
const resolvedDisplayNamePlural = makeExplicitScalarMetadata(displayNamePlural);
|
|
1704
|
-
const metadata = {
|
|
1705
|
-
...resolvedApiName !== void 0 && { apiName: resolvedApiName },
|
|
1706
|
-
...resolvedDisplayName !== void 0 && { displayName: resolvedDisplayName },
|
|
1707
|
-
...resolvedApiNamePlural !== void 0 && { apiNamePlural: resolvedApiNamePlural },
|
|
1708
|
-
...resolvedDisplayNamePlural !== void 0 && {
|
|
1709
|
-
displayNamePlural: resolvedDisplayNamePlural
|
|
1710
|
-
}
|
|
1703
|
+
function createAnalyzerMetadataPolicy(input, discriminator) {
|
|
1704
|
+
return {
|
|
1705
|
+
raw: input,
|
|
1706
|
+
normalized: normalizeMetadataPolicy(input),
|
|
1707
|
+
discriminator
|
|
1711
1708
|
};
|
|
1712
|
-
return Object.keys(metadata).length === 0 ? void 0 : metadata;
|
|
1713
1709
|
}
|
|
1714
|
-
function resolveNodeMetadata(metadataPolicy, declarationKind, logicalName, node, buildContext) {
|
|
1715
|
-
const
|
|
1716
|
-
|
|
1717
|
-
|
|
1718
|
-
|
|
1719
|
-
|
|
1720
|
-
|
|
1721
|
-
|
|
1722
|
-
|
|
1723
|
-
|
|
1724
|
-
|
|
1725
|
-
|
|
1726
|
-
|
|
1727
|
-
getDeclarationMetadataPolicy(metadataPolicy, declarationKind),
|
|
1728
|
-
makeMetadataContext("tsdoc", declarationKind, logicalName, buildContext)
|
|
1710
|
+
function resolveNodeMetadata(metadataPolicy, declarationKind, logicalName, node, checker, extensionRegistry, buildContext) {
|
|
1711
|
+
const analysis = (0, import_internal2.analyzeMetadataForNodeWithChecker)({
|
|
1712
|
+
checker,
|
|
1713
|
+
node,
|
|
1714
|
+
logicalName,
|
|
1715
|
+
metadata: metadataPolicy.raw,
|
|
1716
|
+
extensions: extensionRegistry?.extensions,
|
|
1717
|
+
...buildContext !== void 0 && { buildContext }
|
|
1718
|
+
});
|
|
1719
|
+
const resolvedMetadata = analysis?.resolvedMetadata;
|
|
1720
|
+
const declarationPolicy = getDeclarationMetadataPolicy(
|
|
1721
|
+
metadataPolicy.normalized,
|
|
1722
|
+
declarationKind
|
|
1729
1723
|
);
|
|
1724
|
+
if (resolvedMetadata?.apiName === void 0 && declarationPolicy.apiName.mode === "require-explicit") {
|
|
1725
|
+
throw new Error(
|
|
1726
|
+
`Metadata policy requires explicit apiName for ${declarationKind} "${logicalName}" on the tsdoc surface.`
|
|
1727
|
+
);
|
|
1728
|
+
}
|
|
1729
|
+
if (resolvedMetadata?.displayName === void 0 && declarationPolicy.displayName.mode === "require-explicit") {
|
|
1730
|
+
throw new Error(
|
|
1731
|
+
`Metadata policy requires explicit displayName for ${declarationKind} "${logicalName}" on the tsdoc surface.`
|
|
1732
|
+
);
|
|
1733
|
+
}
|
|
1734
|
+
if (resolvedMetadata?.apiNamePlural === void 0 && declarationPolicy.apiName.pluralization.mode === "require-explicit") {
|
|
1735
|
+
throw new Error(
|
|
1736
|
+
`Metadata policy requires explicit apiNamePlural for ${declarationKind} "${logicalName}" on the tsdoc surface.`
|
|
1737
|
+
);
|
|
1738
|
+
}
|
|
1739
|
+
if (resolvedMetadata?.displayNamePlural === void 0 && declarationPolicy.displayName.pluralization.mode === "require-explicit") {
|
|
1740
|
+
throw new Error(
|
|
1741
|
+
`Metadata policy requires explicit displayNamePlural for ${declarationKind} "${logicalName}" on the tsdoc surface.`
|
|
1742
|
+
);
|
|
1743
|
+
}
|
|
1744
|
+
return resolvedMetadata;
|
|
1730
1745
|
}
|
|
1731
|
-
function analyzeClassToIR(classDecl, checker, file = "", extensionRegistry, metadataPolicy) {
|
|
1732
|
-
const normalizedMetadataPolicy =
|
|
1746
|
+
function analyzeClassToIR(classDecl, checker, file = "", extensionRegistry, metadataPolicy, discriminatorOptions) {
|
|
1747
|
+
const normalizedMetadataPolicy = createAnalyzerMetadataPolicy(
|
|
1748
|
+
metadataPolicy,
|
|
1749
|
+
discriminatorOptions
|
|
1750
|
+
);
|
|
1733
1751
|
const name = classDecl.name?.text ?? "AnonymousClass";
|
|
1734
1752
|
const fields = [];
|
|
1735
1753
|
const fieldLayouts = [];
|
|
@@ -1784,12 +1802,20 @@ function analyzeClassToIR(classDecl, checker, file = "", extensionRegistry, meta
|
|
|
1784
1802
|
diagnostics,
|
|
1785
1803
|
normalizedMetadataPolicy
|
|
1786
1804
|
);
|
|
1787
|
-
const metadata = resolveNodeMetadata(
|
|
1805
|
+
const metadata = resolveNodeMetadata(
|
|
1806
|
+
normalizedMetadataPolicy,
|
|
1807
|
+
"type",
|
|
1808
|
+
name,
|
|
1809
|
+
classDecl,
|
|
1788
1810
|
checker,
|
|
1789
|
-
|
|
1790
|
-
|
|
1791
|
-
|
|
1792
|
-
|
|
1811
|
+
extensionRegistry,
|
|
1812
|
+
{
|
|
1813
|
+
checker,
|
|
1814
|
+
declaration: classDecl,
|
|
1815
|
+
subjectType: classType,
|
|
1816
|
+
hostType: classType
|
|
1817
|
+
}
|
|
1818
|
+
);
|
|
1793
1819
|
return {
|
|
1794
1820
|
name,
|
|
1795
1821
|
...metadata !== void 0 && { metadata },
|
|
@@ -1802,8 +1828,11 @@ function analyzeClassToIR(classDecl, checker, file = "", extensionRegistry, meta
|
|
|
1802
1828
|
staticMethods
|
|
1803
1829
|
};
|
|
1804
1830
|
}
|
|
1805
|
-
function analyzeInterfaceToIR(interfaceDecl, checker, file = "", extensionRegistry, metadataPolicy) {
|
|
1806
|
-
const normalizedMetadataPolicy =
|
|
1831
|
+
function analyzeInterfaceToIR(interfaceDecl, checker, file = "", extensionRegistry, metadataPolicy, discriminatorOptions) {
|
|
1832
|
+
const normalizedMetadataPolicy = createAnalyzerMetadataPolicy(
|
|
1833
|
+
metadataPolicy,
|
|
1834
|
+
discriminatorOptions
|
|
1835
|
+
);
|
|
1807
1836
|
const name = interfaceDecl.name.text;
|
|
1808
1837
|
const fields = [];
|
|
1809
1838
|
const typeRegistry = {};
|
|
@@ -1845,12 +1874,20 @@ function analyzeInterfaceToIR(interfaceDecl, checker, file = "", extensionRegist
|
|
|
1845
1874
|
normalizedMetadataPolicy
|
|
1846
1875
|
);
|
|
1847
1876
|
const fieldLayouts = specializedFields.map(() => ({}));
|
|
1848
|
-
const metadata = resolveNodeMetadata(
|
|
1877
|
+
const metadata = resolveNodeMetadata(
|
|
1878
|
+
normalizedMetadataPolicy,
|
|
1879
|
+
"type",
|
|
1880
|
+
name,
|
|
1881
|
+
interfaceDecl,
|
|
1849
1882
|
checker,
|
|
1850
|
-
|
|
1851
|
-
|
|
1852
|
-
|
|
1853
|
-
|
|
1883
|
+
extensionRegistry,
|
|
1884
|
+
{
|
|
1885
|
+
checker,
|
|
1886
|
+
declaration: interfaceDecl,
|
|
1887
|
+
subjectType: interfaceType,
|
|
1888
|
+
hostType: interfaceType
|
|
1889
|
+
}
|
|
1890
|
+
);
|
|
1854
1891
|
return {
|
|
1855
1892
|
name,
|
|
1856
1893
|
...metadata !== void 0 && { metadata },
|
|
@@ -1863,19 +1900,31 @@ function analyzeInterfaceToIR(interfaceDecl, checker, file = "", extensionRegist
|
|
|
1863
1900
|
staticMethods: []
|
|
1864
1901
|
};
|
|
1865
1902
|
}
|
|
1866
|
-
function analyzeTypeAliasToIR(typeAlias, checker, file = "", extensionRegistry, metadataPolicy) {
|
|
1867
|
-
|
|
1903
|
+
function analyzeTypeAliasToIR(typeAlias, checker, file = "", extensionRegistry, metadataPolicy, discriminatorOptions) {
|
|
1904
|
+
const members = getObjectLikeTypeAliasMembers(typeAlias.type);
|
|
1905
|
+
if (members === null) {
|
|
1868
1906
|
const sourceFile = typeAlias.getSourceFile();
|
|
1869
1907
|
const { line } = sourceFile.getLineAndCharacterOfPosition(typeAlias.getStart());
|
|
1870
1908
|
const kindDesc = ts3.SyntaxKind[typeAlias.type.kind] ?? "unknown";
|
|
1871
1909
|
return {
|
|
1872
1910
|
ok: false,
|
|
1873
|
-
error: `Type alias "${typeAlias.name.text}" at line ${String(line + 1)} is not an object type
|
|
1911
|
+
error: `Type alias "${typeAlias.name.text}" at line ${String(line + 1)} is not an object-like type alias (found ${kindDesc})`
|
|
1874
1912
|
};
|
|
1875
1913
|
}
|
|
1876
|
-
const
|
|
1877
|
-
|
|
1914
|
+
const normalizedMetadataPolicy = createAnalyzerMetadataPolicy(
|
|
1915
|
+
metadataPolicy,
|
|
1916
|
+
discriminatorOptions
|
|
1917
|
+
);
|
|
1878
1918
|
const name = typeAlias.name.text;
|
|
1919
|
+
const duplicatePropertyNames = findDuplicateObjectLikeTypeAliasPropertyNames(members);
|
|
1920
|
+
if (duplicatePropertyNames.length > 0) {
|
|
1921
|
+
const sourceFile = typeAlias.getSourceFile();
|
|
1922
|
+
const { line } = sourceFile.getLineAndCharacterOfPosition(typeAlias.getStart());
|
|
1923
|
+
return {
|
|
1924
|
+
ok: false,
|
|
1925
|
+
error: `Type alias "${name}" at line ${String(line + 1)} contains duplicate property names across object-like members: ${duplicatePropertyNames.join(", ")}`
|
|
1926
|
+
};
|
|
1927
|
+
}
|
|
1879
1928
|
const fields = [];
|
|
1880
1929
|
const typeRegistry = {};
|
|
1881
1930
|
const diagnostics = [];
|
|
@@ -1888,7 +1937,7 @@ function analyzeTypeAliasToIR(typeAlias, checker, file = "", extensionRegistry,
|
|
|
1888
1937
|
const annotations = [...typeAliasDoc.annotations];
|
|
1889
1938
|
diagnostics.push(...typeAliasDoc.diagnostics);
|
|
1890
1939
|
const visiting = /* @__PURE__ */ new Set();
|
|
1891
|
-
for (const member of
|
|
1940
|
+
for (const member of members) {
|
|
1892
1941
|
if (ts3.isPropertySignature(member)) {
|
|
1893
1942
|
const fieldNode = analyzeInterfacePropertyToIR(
|
|
1894
1943
|
member,
|
|
@@ -1915,12 +1964,20 @@ function analyzeTypeAliasToIR(typeAlias, checker, file = "", extensionRegistry,
|
|
|
1915
1964
|
diagnostics,
|
|
1916
1965
|
normalizedMetadataPolicy
|
|
1917
1966
|
);
|
|
1918
|
-
const metadata = resolveNodeMetadata(
|
|
1967
|
+
const metadata = resolveNodeMetadata(
|
|
1968
|
+
normalizedMetadataPolicy,
|
|
1969
|
+
"type",
|
|
1970
|
+
name,
|
|
1971
|
+
typeAlias,
|
|
1919
1972
|
checker,
|
|
1920
|
-
|
|
1921
|
-
|
|
1922
|
-
|
|
1923
|
-
|
|
1973
|
+
extensionRegistry,
|
|
1974
|
+
{
|
|
1975
|
+
checker,
|
|
1976
|
+
declaration: typeAlias,
|
|
1977
|
+
subjectType: aliasType,
|
|
1978
|
+
hostType: aliasType
|
|
1979
|
+
}
|
|
1980
|
+
);
|
|
1924
1981
|
return {
|
|
1925
1982
|
ok: true,
|
|
1926
1983
|
analysis: {
|
|
@@ -1989,15 +2046,43 @@ function isNullishSemanticType(type) {
|
|
|
1989
2046
|
}
|
|
1990
2047
|
return type.isUnion() && type.types.some((member) => isNullishSemanticType(member));
|
|
1991
2048
|
}
|
|
1992
|
-
function isStringLikeSemanticType(type) {
|
|
2049
|
+
function isStringLikeSemanticType(type, checker, seen = /* @__PURE__ */ new Set()) {
|
|
2050
|
+
if (seen.has(type)) {
|
|
2051
|
+
return false;
|
|
2052
|
+
}
|
|
2053
|
+
seen.add(type);
|
|
1993
2054
|
if (type.flags & ts3.TypeFlags.StringLike) {
|
|
1994
2055
|
return true;
|
|
1995
2056
|
}
|
|
1996
2057
|
if (type.isUnion()) {
|
|
1997
|
-
return type.types.length > 0 && type.types.every((member) => isStringLikeSemanticType(member));
|
|
2058
|
+
return type.types.length > 0 && type.types.every((member) => isStringLikeSemanticType(member, checker, seen));
|
|
2059
|
+
}
|
|
2060
|
+
const baseConstraint = checker.getBaseConstraintOfType(type);
|
|
2061
|
+
if (baseConstraint !== void 0 && baseConstraint !== type) {
|
|
2062
|
+
return isStringLikeSemanticType(baseConstraint, checker, seen);
|
|
1998
2063
|
}
|
|
1999
2064
|
return false;
|
|
2000
2065
|
}
|
|
2066
|
+
function getObjectLikeTypeAliasMembers(typeNode) {
|
|
2067
|
+
if (ts3.isParenthesizedTypeNode(typeNode)) {
|
|
2068
|
+
return getObjectLikeTypeAliasMembers(typeNode.type);
|
|
2069
|
+
}
|
|
2070
|
+
if (ts3.isTypeLiteralNode(typeNode)) {
|
|
2071
|
+
return [...typeNode.members];
|
|
2072
|
+
}
|
|
2073
|
+
if (ts3.isIntersectionTypeNode(typeNode)) {
|
|
2074
|
+
const members = [];
|
|
2075
|
+
for (const intersectionMember of typeNode.types) {
|
|
2076
|
+
const resolvedMembers = getObjectLikeTypeAliasMembers(intersectionMember);
|
|
2077
|
+
if (resolvedMembers === null) {
|
|
2078
|
+
return null;
|
|
2079
|
+
}
|
|
2080
|
+
members.push(...resolvedMembers);
|
|
2081
|
+
}
|
|
2082
|
+
return members;
|
|
2083
|
+
}
|
|
2084
|
+
return null;
|
|
2085
|
+
}
|
|
2001
2086
|
function extractDiscriminatorDirective(node, file, diagnostics) {
|
|
2002
2087
|
const discriminatorTags = getLeadingParsedTags(node).filter(
|
|
2003
2088
|
(tag) => tag.normalizedTagName === "discriminator"
|
|
@@ -2104,7 +2189,7 @@ function validateDiscriminatorDirective(node, checker, file, diagnostics) {
|
|
|
2104
2189
|
);
|
|
2105
2190
|
return null;
|
|
2106
2191
|
}
|
|
2107
|
-
if (!isStringLikeSemanticType(property.type)) {
|
|
2192
|
+
if (!isStringLikeSemanticType(property.type, checker)) {
|
|
2108
2193
|
diagnostics.push(
|
|
2109
2194
|
makeAnalysisDiagnostic(
|
|
2110
2195
|
"TYPE_MISMATCH",
|
|
@@ -2131,8 +2216,8 @@ function getConcreteTypeArgumentForDiscriminator(node, subjectType, checker, typ
|
|
|
2131
2216
|
const localTypeParameter = node.typeParameters?.[typeParameterIndex];
|
|
2132
2217
|
return localTypeParameter === void 0 ? null : checker.getTypeAtLocation(localTypeParameter);
|
|
2133
2218
|
}
|
|
2134
|
-
function resolveLiteralDiscriminatorPropertyValue(boundType,
|
|
2135
|
-
const propertySymbol = boundType.getProperty(
|
|
2219
|
+
function resolveLiteralDiscriminatorPropertyValue(boundType, propertyName, checker, provenance, diagnostics) {
|
|
2220
|
+
const propertySymbol = boundType.getProperty(propertyName);
|
|
2136
2221
|
if (propertySymbol === void 0) {
|
|
2137
2222
|
return void 0;
|
|
2138
2223
|
}
|
|
@@ -2163,6 +2248,9 @@ function resolveLiteralDiscriminatorPropertyValue(boundType, fieldName, checker,
|
|
|
2163
2248
|
}
|
|
2164
2249
|
return void 0;
|
|
2165
2250
|
}
|
|
2251
|
+
function getDiscriminatorIdentityPropertyNames(fieldName) {
|
|
2252
|
+
return fieldName === "object" ? ["object"] : [fieldName, "object"];
|
|
2253
|
+
}
|
|
2166
2254
|
function resolveDiscriminatorApiName(boundType, checker, metadataPolicy) {
|
|
2167
2255
|
const declaration = resolveNamedDiscriminatorDeclaration(boundType, checker);
|
|
2168
2256
|
if (declaration === null) {
|
|
@@ -2173,6 +2261,8 @@ function resolveDiscriminatorApiName(boundType, checker, metadataPolicy) {
|
|
|
2173
2261
|
"type",
|
|
2174
2262
|
getDiscriminatorLogicalName(boundType, declaration, checker),
|
|
2175
2263
|
declaration,
|
|
2264
|
+
checker,
|
|
2265
|
+
void 0,
|
|
2176
2266
|
{
|
|
2177
2267
|
checker,
|
|
2178
2268
|
declaration,
|
|
@@ -2181,6 +2271,10 @@ function resolveDiscriminatorApiName(boundType, checker, metadataPolicy) {
|
|
|
2181
2271
|
);
|
|
2182
2272
|
return metadata?.apiName;
|
|
2183
2273
|
}
|
|
2274
|
+
function applyDiscriminatorApiNamePrefix(value, discriminatorOptions) {
|
|
2275
|
+
const prefix = discriminatorOptions?.apiNamePrefix;
|
|
2276
|
+
return prefix === void 0 || prefix === "" ? value : `${prefix}${value}`;
|
|
2277
|
+
}
|
|
2184
2278
|
function resolveNamedDiscriminatorDeclaration(type, checker, seen = /* @__PURE__ */ new Set()) {
|
|
2185
2279
|
if (seen.has(type)) {
|
|
2186
2280
|
return null;
|
|
@@ -2235,22 +2329,27 @@ function resolveDiscriminatorValue(boundType, fieldName, checker, provenance, di
|
|
|
2235
2329
|
return null;
|
|
2236
2330
|
}
|
|
2237
2331
|
}
|
|
2238
|
-
const
|
|
2239
|
-
|
|
2240
|
-
|
|
2241
|
-
|
|
2242
|
-
|
|
2243
|
-
|
|
2244
|
-
|
|
2245
|
-
|
|
2246
|
-
|
|
2332
|
+
for (const identityPropertyName of getDiscriminatorIdentityPropertyNames(fieldName)) {
|
|
2333
|
+
const literalIdentityValue = resolveLiteralDiscriminatorPropertyValue(
|
|
2334
|
+
boundType,
|
|
2335
|
+
identityPropertyName,
|
|
2336
|
+
checker,
|
|
2337
|
+
provenance,
|
|
2338
|
+
diagnostics
|
|
2339
|
+
);
|
|
2340
|
+
if (literalIdentityValue === null) {
|
|
2341
|
+
return null;
|
|
2342
|
+
}
|
|
2343
|
+
if (literalIdentityValue !== void 0) {
|
|
2344
|
+
return literalIdentityValue;
|
|
2345
|
+
}
|
|
2247
2346
|
}
|
|
2248
2347
|
const apiName = resolveDiscriminatorApiName(boundType, checker, metadataPolicy);
|
|
2249
2348
|
if (apiName?.source === "explicit") {
|
|
2250
|
-
return apiName.value;
|
|
2349
|
+
return applyDiscriminatorApiNamePrefix(apiName.value, metadataPolicy.discriminator);
|
|
2251
2350
|
}
|
|
2252
2351
|
if (apiName?.source === "inferred") {
|
|
2253
|
-
return apiName.value;
|
|
2352
|
+
return applyDiscriminatorApiNamePrefix(apiName.value, metadataPolicy.discriminator);
|
|
2254
2353
|
}
|
|
2255
2354
|
diagnostics.push(
|
|
2256
2355
|
makeAnalysisDiagnostic(
|
|
@@ -2313,15 +2412,20 @@ function buildInstantiatedReferenceName(baseName, typeArguments, checker) {
|
|
|
2313
2412
|
return renderedArguments.length === 0 ? baseName : `${baseName}__${renderedArguments.join("__")}`;
|
|
2314
2413
|
}
|
|
2315
2414
|
function extractReferenceTypeArguments(type, checker, file, typeRegistry, visiting, sourceNode, metadataPolicy, extensionRegistry, diagnostics) {
|
|
2316
|
-
const
|
|
2317
|
-
if (
|
|
2415
|
+
const sourceTypeNode = sourceNode === void 0 ? void 0 : extractTypeNodeFromSource(sourceNode);
|
|
2416
|
+
if (sourceTypeNode === void 0) {
|
|
2318
2417
|
return [];
|
|
2319
2418
|
}
|
|
2320
|
-
const
|
|
2321
|
-
|
|
2419
|
+
const unwrapParentheses = (typeNode) => ts3.isParenthesizedTypeNode(typeNode) ? unwrapParentheses(typeNode.type) : typeNode;
|
|
2420
|
+
const directTypeNode = unwrapParentheses(sourceTypeNode);
|
|
2421
|
+
const referenceTypeNode = ts3.isTypeReferenceNode(directTypeNode) ? directTypeNode : (() => {
|
|
2422
|
+
const resolvedTypeNode = resolveAliasedTypeNode(directTypeNode, checker);
|
|
2423
|
+
return ts3.isTypeReferenceNode(resolvedTypeNode) ? resolvedTypeNode : null;
|
|
2424
|
+
})();
|
|
2425
|
+
if (referenceTypeNode?.typeArguments === void 0) {
|
|
2322
2426
|
return [];
|
|
2323
2427
|
}
|
|
2324
|
-
return
|
|
2428
|
+
return referenceTypeNode.typeArguments.map((argumentNode) => {
|
|
2325
2429
|
const argumentType = checker.getTypeFromTypeNode(argumentNode);
|
|
2326
2430
|
return {
|
|
2327
2431
|
tsType: argumentType,
|
|
@@ -2409,12 +2513,20 @@ function analyzeFieldToIR(prop, checker, file, typeRegistry, visiting, diagnosti
|
|
|
2409
2513
|
annotations.push(defaultAnnotation);
|
|
2410
2514
|
}
|
|
2411
2515
|
({ type, annotations } = applyEnumMemberDisplayNames(type, annotations));
|
|
2412
|
-
const metadata = resolveNodeMetadata(
|
|
2516
|
+
const metadata = resolveNodeMetadata(
|
|
2517
|
+
metadataPolicy,
|
|
2518
|
+
"field",
|
|
2519
|
+
name,
|
|
2520
|
+
prop,
|
|
2413
2521
|
checker,
|
|
2414
|
-
|
|
2415
|
-
|
|
2416
|
-
|
|
2417
|
-
|
|
2522
|
+
extensionRegistry,
|
|
2523
|
+
{
|
|
2524
|
+
checker,
|
|
2525
|
+
declaration: prop,
|
|
2526
|
+
subjectType: tsType,
|
|
2527
|
+
hostType
|
|
2528
|
+
}
|
|
2529
|
+
);
|
|
2418
2530
|
return {
|
|
2419
2531
|
kind: "field",
|
|
2420
2532
|
name,
|
|
@@ -2427,10 +2539,10 @@ function analyzeFieldToIR(prop, checker, file, typeRegistry, visiting, diagnosti
|
|
|
2427
2539
|
};
|
|
2428
2540
|
}
|
|
2429
2541
|
function analyzeInterfacePropertyToIR(prop, checker, file, typeRegistry, visiting, diagnostics, hostType, metadataPolicy, extensionRegistry) {
|
|
2430
|
-
|
|
2542
|
+
const name = getAnalyzableObjectLikePropertyName(prop.name);
|
|
2543
|
+
if (name === null) {
|
|
2431
2544
|
return null;
|
|
2432
2545
|
}
|
|
2433
|
-
const name = prop.name.text;
|
|
2434
2546
|
const tsType = checker.getTypeAtLocation(prop);
|
|
2435
2547
|
const optional = prop.questionToken !== void 0;
|
|
2436
2548
|
const provenance = provenanceForNode(prop, file);
|
|
@@ -2461,12 +2573,20 @@ function analyzeInterfacePropertyToIR(prop, checker, file, typeRegistry, visitin
|
|
|
2461
2573
|
let annotations = [];
|
|
2462
2574
|
annotations.push(...docResult.annotations);
|
|
2463
2575
|
({ type, annotations } = applyEnumMemberDisplayNames(type, annotations));
|
|
2464
|
-
const metadata = resolveNodeMetadata(
|
|
2576
|
+
const metadata = resolveNodeMetadata(
|
|
2577
|
+
metadataPolicy,
|
|
2578
|
+
"field",
|
|
2579
|
+
name,
|
|
2580
|
+
prop,
|
|
2465
2581
|
checker,
|
|
2466
|
-
|
|
2467
|
-
|
|
2468
|
-
|
|
2469
|
-
|
|
2582
|
+
extensionRegistry,
|
|
2583
|
+
{
|
|
2584
|
+
checker,
|
|
2585
|
+
declaration: prop,
|
|
2586
|
+
subjectType: tsType,
|
|
2587
|
+
hostType
|
|
2588
|
+
}
|
|
2589
|
+
);
|
|
2470
2590
|
return {
|
|
2471
2591
|
kind: "field",
|
|
2472
2592
|
name,
|
|
@@ -2478,6 +2598,31 @@ function analyzeInterfacePropertyToIR(prop, checker, file, typeRegistry, visitin
|
|
|
2478
2598
|
provenance
|
|
2479
2599
|
};
|
|
2480
2600
|
}
|
|
2601
|
+
function findDuplicateObjectLikeTypeAliasPropertyNames(members) {
|
|
2602
|
+
const seen = /* @__PURE__ */ new Set();
|
|
2603
|
+
const duplicates = /* @__PURE__ */ new Set();
|
|
2604
|
+
for (const member of members) {
|
|
2605
|
+
if (!ts3.isPropertySignature(member)) {
|
|
2606
|
+
continue;
|
|
2607
|
+
}
|
|
2608
|
+
const name = getAnalyzableObjectLikePropertyName(member.name);
|
|
2609
|
+
if (name === null) {
|
|
2610
|
+
continue;
|
|
2611
|
+
}
|
|
2612
|
+
if (seen.has(name)) {
|
|
2613
|
+
duplicates.add(name);
|
|
2614
|
+
continue;
|
|
2615
|
+
}
|
|
2616
|
+
seen.add(name);
|
|
2617
|
+
}
|
|
2618
|
+
return [...duplicates].sort();
|
|
2619
|
+
}
|
|
2620
|
+
function getAnalyzableObjectLikePropertyName(name) {
|
|
2621
|
+
if (!ts3.isIdentifier(name)) {
|
|
2622
|
+
return null;
|
|
2623
|
+
}
|
|
2624
|
+
return name.text;
|
|
2625
|
+
}
|
|
2481
2626
|
function applyEnumMemberDisplayNames(type, annotations) {
|
|
2482
2627
|
if (!annotations.some(
|
|
2483
2628
|
(annotation) => annotation.annotationKind === "displayName" && annotation.value.trim().startsWith(":")
|
|
@@ -2595,7 +2740,7 @@ function getTypeNodeRegistrationName(typeNode) {
|
|
|
2595
2740
|
}
|
|
2596
2741
|
return null;
|
|
2597
2742
|
}
|
|
2598
|
-
function resolveTypeNode(type, checker, file, typeRegistry, visiting, sourceNode, metadataPolicy =
|
|
2743
|
+
function resolveTypeNode(type, checker, file, typeRegistry, visiting, sourceNode, metadataPolicy = createAnalyzerMetadataPolicy(void 0), extensionRegistry, diagnostics) {
|
|
2599
2744
|
const customType = resolveRegisteredCustomType(sourceNode, extensionRegistry, checker);
|
|
2600
2745
|
if (customType) {
|
|
2601
2746
|
return customType;
|
|
@@ -2670,6 +2815,23 @@ function resolveTypeNode(type, checker, file, typeRegistry, visiting, sourceNode
|
|
|
2670
2815
|
diagnostics
|
|
2671
2816
|
);
|
|
2672
2817
|
}
|
|
2818
|
+
if (isIntersectionType(type)) {
|
|
2819
|
+
const sourceTypeNode = sourceNode === void 0 ? void 0 : extractTypeNodeFromSource(sourceNode);
|
|
2820
|
+
const resolvedSourceTypeNode = sourceTypeNode === void 0 ? void 0 : resolveAliasedTypeNode(sourceTypeNode, checker);
|
|
2821
|
+
if (resolvedSourceTypeNode !== void 0 && getObjectLikeTypeAliasMembers(resolvedSourceTypeNode) !== null) {
|
|
2822
|
+
return resolveObjectType(
|
|
2823
|
+
type,
|
|
2824
|
+
checker,
|
|
2825
|
+
file,
|
|
2826
|
+
typeRegistry,
|
|
2827
|
+
visiting,
|
|
2828
|
+
sourceNode,
|
|
2829
|
+
metadataPolicy,
|
|
2830
|
+
extensionRegistry,
|
|
2831
|
+
diagnostics
|
|
2832
|
+
);
|
|
2833
|
+
}
|
|
2834
|
+
}
|
|
2673
2835
|
if (isObjectType(type)) {
|
|
2674
2836
|
return resolveObjectType(
|
|
2675
2837
|
type,
|
|
@@ -2685,7 +2847,7 @@ function resolveTypeNode(type, checker, file, typeRegistry, visiting, sourceNode
|
|
|
2685
2847
|
}
|
|
2686
2848
|
return { kind: "primitive", primitiveKind: "string" };
|
|
2687
2849
|
}
|
|
2688
|
-
function tryResolveNamedPrimitiveAlias(type, checker, file, typeRegistry, visiting, sourceNode, metadataPolicy =
|
|
2850
|
+
function tryResolveNamedPrimitiveAlias(type, checker, file, typeRegistry, visiting, sourceNode, metadataPolicy = createAnalyzerMetadataPolicy(void 0), extensionRegistry, diagnostics) {
|
|
2689
2851
|
if (!(type.flags & (ts3.TypeFlags.String | ts3.TypeFlags.Number | ts3.TypeFlags.BigInt | ts3.TypeFlags.BigIntLiteral | ts3.TypeFlags.Boolean | ts3.TypeFlags.Null))) {
|
|
2690
2852
|
return null;
|
|
2691
2853
|
}
|
|
@@ -2705,11 +2867,19 @@ function tryResolveNamedPrimitiveAlias(type, checker, file, typeRegistry, visiti
|
|
|
2705
2867
|
file,
|
|
2706
2868
|
makeParseOptions(extensionRegistry)
|
|
2707
2869
|
);
|
|
2708
|
-
const metadata = resolveNodeMetadata(
|
|
2870
|
+
const metadata = resolveNodeMetadata(
|
|
2871
|
+
metadataPolicy,
|
|
2872
|
+
"type",
|
|
2873
|
+
aliasName,
|
|
2874
|
+
aliasDecl,
|
|
2709
2875
|
checker,
|
|
2710
|
-
|
|
2711
|
-
|
|
2712
|
-
|
|
2876
|
+
extensionRegistry,
|
|
2877
|
+
{
|
|
2878
|
+
checker,
|
|
2879
|
+
declaration: aliasDecl,
|
|
2880
|
+
subjectType: aliasType
|
|
2881
|
+
}
|
|
2882
|
+
);
|
|
2713
2883
|
typeRegistry[aliasName] = {
|
|
2714
2884
|
name: aliasName,
|
|
2715
2885
|
...metadata !== void 0 && { metadata },
|
|
@@ -2748,7 +2918,7 @@ function shouldEmitPrimitiveAliasDefinition(typeNode, checker) {
|
|
|
2748
2918
|
const resolved = checker.getTypeFromTypeNode(aliasDecl.type);
|
|
2749
2919
|
return !!(resolved.flags & (ts3.TypeFlags.String | ts3.TypeFlags.Number | ts3.TypeFlags.BigInt | ts3.TypeFlags.BigIntLiteral | ts3.TypeFlags.Boolean | ts3.TypeFlags.Null));
|
|
2750
2920
|
}
|
|
2751
|
-
function resolveAliasedPrimitiveTarget(type, checker, file, typeRegistry, visiting, metadataPolicy =
|
|
2921
|
+
function resolveAliasedPrimitiveTarget(type, checker, file, typeRegistry, visiting, metadataPolicy = createAnalyzerMetadataPolicy(void 0), extensionRegistry, diagnostics) {
|
|
2752
2922
|
const nestedAliasDecl = type.aliasSymbol?.declarations?.find(ts3.isTypeAliasDeclaration);
|
|
2753
2923
|
if (nestedAliasDecl !== void 0) {
|
|
2754
2924
|
return resolveAliasedPrimitiveTarget(
|
|
@@ -2774,7 +2944,7 @@ function resolveAliasedPrimitiveTarget(type, checker, file, typeRegistry, visiti
|
|
|
2774
2944
|
diagnostics
|
|
2775
2945
|
);
|
|
2776
2946
|
}
|
|
2777
|
-
function resolveUnionType(type, checker, file, typeRegistry, visiting, sourceNode, metadataPolicy =
|
|
2947
|
+
function resolveUnionType(type, checker, file, typeRegistry, visiting, sourceNode, metadataPolicy = createAnalyzerMetadataPolicy(void 0), extensionRegistry, diagnostics) {
|
|
2778
2948
|
const typeName = getNamedTypeName(type);
|
|
2779
2949
|
const namedDecl = getNamedTypeDeclaration(type);
|
|
2780
2950
|
if (typeName && typeName in typeRegistry) {
|
|
@@ -2809,11 +2979,19 @@ function resolveUnionType(type, checker, file, typeRegistry, visiting, sourceNod
|
|
|
2809
2979
|
return result;
|
|
2810
2980
|
}
|
|
2811
2981
|
const annotations = namedDecl ? extractJSDocAnnotationNodes(namedDecl, file, makeParseOptions(extensionRegistry)) : void 0;
|
|
2812
|
-
const metadata = namedDecl !== void 0 ? resolveNodeMetadata(
|
|
2982
|
+
const metadata = namedDecl !== void 0 ? resolveNodeMetadata(
|
|
2983
|
+
metadataPolicy,
|
|
2984
|
+
"type",
|
|
2985
|
+
typeName,
|
|
2986
|
+
namedDecl,
|
|
2813
2987
|
checker,
|
|
2814
|
-
|
|
2815
|
-
|
|
2816
|
-
|
|
2988
|
+
extensionRegistry,
|
|
2989
|
+
{
|
|
2990
|
+
checker,
|
|
2991
|
+
declaration: namedDecl,
|
|
2992
|
+
subjectType: type
|
|
2993
|
+
}
|
|
2994
|
+
) : void 0;
|
|
2817
2995
|
typeRegistry[typeName] = {
|
|
2818
2996
|
name: typeName,
|
|
2819
2997
|
...metadata !== void 0 && { metadata },
|
|
@@ -2898,7 +3076,7 @@ function resolveUnionType(type, checker, file, typeRegistry, visiting, sourceNod
|
|
|
2898
3076
|
}
|
|
2899
3077
|
return registerNamed({ kind: "union", members });
|
|
2900
3078
|
}
|
|
2901
|
-
function resolveArrayType(type, checker, file, typeRegistry, visiting, sourceNode, metadataPolicy =
|
|
3079
|
+
function resolveArrayType(type, checker, file, typeRegistry, visiting, sourceNode, metadataPolicy = createAnalyzerMetadataPolicy(void 0), extensionRegistry, diagnostics) {
|
|
2902
3080
|
const typeArgs = isTypeReference(type) ? type.typeArguments : void 0;
|
|
2903
3081
|
const elementType = typeArgs?.[0];
|
|
2904
3082
|
const elementSourceNode = extractArrayElementTypeNode(sourceNode, checker);
|
|
@@ -2915,7 +3093,7 @@ function resolveArrayType(type, checker, file, typeRegistry, visiting, sourceNod
|
|
|
2915
3093
|
) : { kind: "primitive", primitiveKind: "string" };
|
|
2916
3094
|
return { kind: "array", items };
|
|
2917
3095
|
}
|
|
2918
|
-
function tryResolveRecordType(type, checker, file, typeRegistry, visiting, metadataPolicy =
|
|
3096
|
+
function tryResolveRecordType(type, checker, file, typeRegistry, visiting, metadataPolicy = createAnalyzerMetadataPolicy(void 0), extensionRegistry, diagnostics) {
|
|
2919
3097
|
if (type.getProperties().length > 0) {
|
|
2920
3098
|
return null;
|
|
2921
3099
|
}
|
|
@@ -2976,7 +3154,7 @@ function shouldEmitResolvedObjectProperty(property, declaration) {
|
|
|
2976
3154
|
}
|
|
2977
3155
|
return true;
|
|
2978
3156
|
}
|
|
2979
|
-
function resolveObjectType(type, checker, file, typeRegistry, visiting, sourceNode, metadataPolicy =
|
|
3157
|
+
function resolveObjectType(type, checker, file, typeRegistry, visiting, sourceNode, metadataPolicy = createAnalyzerMetadataPolicy(void 0), extensionRegistry, diagnostics) {
|
|
2980
3158
|
const collectedDiagnostics = diagnostics ?? [];
|
|
2981
3159
|
const typeName = getNamedTypeName(type);
|
|
2982
3160
|
const namedTypeName = typeName ?? void 0;
|
|
@@ -3033,7 +3211,7 @@ function resolveObjectType(type, checker, file, typeRegistry, visiting, sourceNo
|
|
|
3033
3211
|
};
|
|
3034
3212
|
}
|
|
3035
3213
|
}
|
|
3036
|
-
const recordNode = tryResolveRecordType(
|
|
3214
|
+
const recordNode = isObjectType(type) ? tryResolveRecordType(
|
|
3037
3215
|
type,
|
|
3038
3216
|
checker,
|
|
3039
3217
|
file,
|
|
@@ -3042,7 +3220,7 @@ function resolveObjectType(type, checker, file, typeRegistry, visiting, sourceNo
|
|
|
3042
3220
|
metadataPolicy,
|
|
3043
3221
|
extensionRegistry,
|
|
3044
3222
|
collectedDiagnostics
|
|
3045
|
-
);
|
|
3223
|
+
) : null;
|
|
3046
3224
|
if (recordNode) {
|
|
3047
3225
|
visiting.delete(type);
|
|
3048
3226
|
if (registryTypeName !== void 0 && shouldRegisterNamedType) {
|
|
@@ -3052,11 +3230,19 @@ function resolveObjectType(type, checker, file, typeRegistry, visiting, sourceNo
|
|
|
3052
3230
|
return recordNode;
|
|
3053
3231
|
}
|
|
3054
3232
|
const annotations = namedDecl ? extractJSDocAnnotationNodes(namedDecl, file, makeParseOptions(extensionRegistry)) : void 0;
|
|
3055
|
-
const metadata = namedDecl !== void 0 ? resolveNodeMetadata(
|
|
3233
|
+
const metadata = namedDecl !== void 0 ? resolveNodeMetadata(
|
|
3234
|
+
metadataPolicy,
|
|
3235
|
+
"type",
|
|
3236
|
+
registryTypeName,
|
|
3237
|
+
namedDecl,
|
|
3056
3238
|
checker,
|
|
3057
|
-
|
|
3058
|
-
|
|
3059
|
-
|
|
3239
|
+
extensionRegistry,
|
|
3240
|
+
{
|
|
3241
|
+
checker,
|
|
3242
|
+
declaration: namedDecl,
|
|
3243
|
+
subjectType: type
|
|
3244
|
+
}
|
|
3245
|
+
) : void 0;
|
|
3060
3246
|
typeRegistry[registryTypeName] = {
|
|
3061
3247
|
name: registryTypeName,
|
|
3062
3248
|
...metadata !== void 0 && { metadata },
|
|
@@ -3152,11 +3338,19 @@ function resolveObjectType(type, checker, file, typeRegistry, visiting, sourceNo
|
|
|
3152
3338
|
};
|
|
3153
3339
|
if (registryTypeName !== void 0 && shouldRegisterNamedType) {
|
|
3154
3340
|
const annotations = namedDecl ? extractJSDocAnnotationNodes(namedDecl, file, makeParseOptions(extensionRegistry)) : void 0;
|
|
3155
|
-
const metadata = namedDecl !== void 0 ? resolveNodeMetadata(
|
|
3341
|
+
const metadata = namedDecl !== void 0 ? resolveNodeMetadata(
|
|
3342
|
+
metadataPolicy,
|
|
3343
|
+
"type",
|
|
3344
|
+
registryTypeName,
|
|
3345
|
+
namedDecl,
|
|
3156
3346
|
checker,
|
|
3157
|
-
|
|
3158
|
-
|
|
3159
|
-
|
|
3347
|
+
extensionRegistry,
|
|
3348
|
+
{
|
|
3349
|
+
checker,
|
|
3350
|
+
declaration: namedDecl,
|
|
3351
|
+
subjectType: type
|
|
3352
|
+
}
|
|
3353
|
+
) : void 0;
|
|
3160
3354
|
typeRegistry[registryTypeName] = {
|
|
3161
3355
|
name: registryTypeName,
|
|
3162
3356
|
...metadata !== void 0 && { metadata },
|
|
@@ -3223,9 +3417,10 @@ function getNamedTypeFieldNodeInfoMap(type, checker, file, typeRegistry, visitin
|
|
|
3223
3417
|
);
|
|
3224
3418
|
}
|
|
3225
3419
|
const typeAliasDecl = declarations.find(ts3.isTypeAliasDeclaration);
|
|
3226
|
-
|
|
3420
|
+
const typeAliasMembers = typeAliasDecl === void 0 ? null : getObjectLikeTypeAliasMembers(typeAliasDecl.type);
|
|
3421
|
+
if (typeAliasDecl && typeAliasMembers !== null) {
|
|
3227
3422
|
return buildFieldNodeInfoMap(
|
|
3228
|
-
|
|
3423
|
+
typeAliasMembers,
|
|
3229
3424
|
checker,
|
|
3230
3425
|
file,
|
|
3231
3426
|
typeRegistry,
|
|
@@ -3516,7 +3711,7 @@ function findInterfaceByName(sourceFile, interfaceName) {
|
|
|
3516
3711
|
function findTypeAliasByName(sourceFile, aliasName) {
|
|
3517
3712
|
return findNodeByName(sourceFile, aliasName, ts4.isTypeAliasDeclaration, (n) => n.name.text);
|
|
3518
3713
|
}
|
|
3519
|
-
function analyzeNamedTypeToIRFromProgramContext(ctx, filePath, typeName, extensionRegistry, metadataPolicy) {
|
|
3714
|
+
function analyzeNamedTypeToIRFromProgramContext(ctx, filePath, typeName, extensionRegistry, metadataPolicy, discriminatorOptions) {
|
|
3520
3715
|
const analysisFilePath = path.resolve(filePath);
|
|
3521
3716
|
const classDecl = findClassByName(ctx.sourceFile, typeName);
|
|
3522
3717
|
if (classDecl !== null) {
|
|
@@ -3525,7 +3720,8 @@ function analyzeNamedTypeToIRFromProgramContext(ctx, filePath, typeName, extensi
|
|
|
3525
3720
|
ctx.checker,
|
|
3526
3721
|
analysisFilePath,
|
|
3527
3722
|
extensionRegistry,
|
|
3528
|
-
metadataPolicy
|
|
3723
|
+
metadataPolicy,
|
|
3724
|
+
discriminatorOptions
|
|
3529
3725
|
);
|
|
3530
3726
|
}
|
|
3531
3727
|
const interfaceDecl = findInterfaceByName(ctx.sourceFile, typeName);
|
|
@@ -3535,7 +3731,8 @@ function analyzeNamedTypeToIRFromProgramContext(ctx, filePath, typeName, extensi
|
|
|
3535
3731
|
ctx.checker,
|
|
3536
3732
|
analysisFilePath,
|
|
3537
3733
|
extensionRegistry,
|
|
3538
|
-
metadataPolicy
|
|
3734
|
+
metadataPolicy,
|
|
3735
|
+
discriminatorOptions
|
|
3539
3736
|
);
|
|
3540
3737
|
}
|
|
3541
3738
|
const typeAlias = findTypeAliasByName(ctx.sourceFile, typeName);
|
|
@@ -3545,7 +3742,8 @@ function analyzeNamedTypeToIRFromProgramContext(ctx, filePath, typeName, extensi
|
|
|
3545
3742
|
ctx.checker,
|
|
3546
3743
|
analysisFilePath,
|
|
3547
3744
|
extensionRegistry,
|
|
3548
|
-
metadataPolicy
|
|
3745
|
+
metadataPolicy,
|
|
3746
|
+
discriminatorOptions
|
|
3549
3747
|
);
|
|
3550
3748
|
if (result.ok) {
|
|
3551
3749
|
return result.analysis;
|
|
@@ -4659,13 +4857,29 @@ function formatLocation(location) {
|
|
|
4659
4857
|
}
|
|
4660
4858
|
|
|
4661
4859
|
// src/extensions/registry.ts
|
|
4860
|
+
var import_internals5 = require("@formspec/core/internals");
|
|
4861
|
+
var import_internal4 = require("@formspec/analysis/internal");
|
|
4862
|
+
var BUILTIN_METADATA_TAGS = /* @__PURE__ */ new Set(["apiName", "displayName"]);
|
|
4863
|
+
function buildConstraintTagSources(extensions) {
|
|
4864
|
+
return extensions.map((extension) => ({
|
|
4865
|
+
extensionId: extension.extensionId,
|
|
4866
|
+
...extension.constraintTags !== void 0 ? {
|
|
4867
|
+
constraintTags: extension.constraintTags.map((tag) => ({
|
|
4868
|
+
tagName: (0, import_internal4.normalizeFormSpecTagName)(tag.tagName)
|
|
4869
|
+
}))
|
|
4870
|
+
} : {}
|
|
4871
|
+
}));
|
|
4872
|
+
}
|
|
4662
4873
|
function createExtensionRegistry(extensions) {
|
|
4874
|
+
const reservedTagSources = buildConstraintTagSources(extensions);
|
|
4663
4875
|
const typeMap = /* @__PURE__ */ new Map();
|
|
4664
4876
|
const typeNameMap = /* @__PURE__ */ new Map();
|
|
4665
4877
|
const constraintMap = /* @__PURE__ */ new Map();
|
|
4666
4878
|
const constraintTagMap = /* @__PURE__ */ new Map();
|
|
4667
4879
|
const builtinBroadeningMap = /* @__PURE__ */ new Map();
|
|
4668
4880
|
const annotationMap = /* @__PURE__ */ new Map();
|
|
4881
|
+
const metadataSlotMap = /* @__PURE__ */ new Map();
|
|
4882
|
+
const metadataTagMap = /* @__PURE__ */ new Map();
|
|
4669
4883
|
for (const ext of extensions) {
|
|
4670
4884
|
if (ext.types !== void 0) {
|
|
4671
4885
|
for (const type of ext.types) {
|
|
@@ -4708,10 +4922,11 @@ function createExtensionRegistry(extensions) {
|
|
|
4708
4922
|
}
|
|
4709
4923
|
if (ext.constraintTags !== void 0) {
|
|
4710
4924
|
for (const tag of ext.constraintTags) {
|
|
4711
|
-
|
|
4712
|
-
|
|
4925
|
+
const canonicalTagName = (0, import_internal4.normalizeFormSpecTagName)(tag.tagName);
|
|
4926
|
+
if (constraintTagMap.has(canonicalTagName)) {
|
|
4927
|
+
throw new Error(`Duplicate custom constraint tag: "@${canonicalTagName}"`);
|
|
4713
4928
|
}
|
|
4714
|
-
constraintTagMap.set(
|
|
4929
|
+
constraintTagMap.set(canonicalTagName, {
|
|
4715
4930
|
extensionId: ext.extensionId,
|
|
4716
4931
|
registration: tag
|
|
4717
4932
|
});
|
|
@@ -4726,20 +4941,61 @@ function createExtensionRegistry(extensions) {
|
|
|
4726
4941
|
annotationMap.set(qualifiedId, annotation);
|
|
4727
4942
|
}
|
|
4728
4943
|
}
|
|
4944
|
+
if (ext.metadataSlots !== void 0) {
|
|
4945
|
+
for (const slot of ext.metadataSlots) {
|
|
4946
|
+
if (metadataSlotMap.has(slot.slotId)) {
|
|
4947
|
+
throw new Error(`Duplicate metadata slot ID: "${slot.slotId}"`);
|
|
4948
|
+
}
|
|
4949
|
+
metadataSlotMap.set(slot.slotId, true);
|
|
4950
|
+
const canonicalTagName = (0, import_internal4.normalizeFormSpecTagName)(slot.tagName);
|
|
4951
|
+
if (slot.allowBare === false && (slot.qualifiers?.length ?? 0) === 0) {
|
|
4952
|
+
throw new Error(
|
|
4953
|
+
`Metadata tag "@${canonicalTagName}" must allow bare usage or declare at least one qualifier.`
|
|
4954
|
+
);
|
|
4955
|
+
}
|
|
4956
|
+
if (metadataTagMap.has(canonicalTagName)) {
|
|
4957
|
+
throw new Error(`Duplicate metadata tag: "@${canonicalTagName}"`);
|
|
4958
|
+
}
|
|
4959
|
+
if (BUILTIN_METADATA_TAGS.has(canonicalTagName)) {
|
|
4960
|
+
throw new Error(
|
|
4961
|
+
`Metadata tag "@${canonicalTagName}" conflicts with built-in metadata tags.`
|
|
4962
|
+
);
|
|
4963
|
+
}
|
|
4964
|
+
if (constraintTagMap.has(canonicalTagName)) {
|
|
4965
|
+
throw new Error(
|
|
4966
|
+
`Metadata tag "@${canonicalTagName}" conflicts with existing FormSpec tag "@${canonicalTagName}".`
|
|
4967
|
+
);
|
|
4968
|
+
}
|
|
4969
|
+
if (Object.hasOwn(import_internals5.BUILTIN_CONSTRAINT_DEFINITIONS, (0, import_internals5.normalizeConstraintTagName)(canonicalTagName))) {
|
|
4970
|
+
throw new Error(
|
|
4971
|
+
`Metadata tag "@${canonicalTagName}" conflicts with existing FormSpec tag "@${(0, import_internals5.normalizeConstraintTagName)(canonicalTagName)}".`
|
|
4972
|
+
);
|
|
4973
|
+
}
|
|
4974
|
+
const existingTag = (0, import_internal4.getTagDefinition)(canonicalTagName, reservedTagSources);
|
|
4975
|
+
if (existingTag !== null) {
|
|
4976
|
+
throw BUILTIN_METADATA_TAGS.has(existingTag.canonicalName) ? new Error(
|
|
4977
|
+
`Metadata tag "@${canonicalTagName}" conflicts with built-in metadata tags.`
|
|
4978
|
+
) : new Error(
|
|
4979
|
+
`Metadata tag "@${canonicalTagName}" conflicts with existing FormSpec tag "@${existingTag.canonicalName}".`
|
|
4980
|
+
);
|
|
4981
|
+
}
|
|
4982
|
+
metadataTagMap.set(canonicalTagName, true);
|
|
4983
|
+
}
|
|
4984
|
+
}
|
|
4729
4985
|
}
|
|
4730
4986
|
return {
|
|
4731
4987
|
extensions,
|
|
4732
4988
|
findType: (typeId) => typeMap.get(typeId),
|
|
4733
4989
|
findTypeByName: (typeName) => typeNameMap.get(typeName),
|
|
4734
4990
|
findConstraint: (constraintId) => constraintMap.get(constraintId),
|
|
4735
|
-
findConstraintTag: (tagName) => constraintTagMap.get(tagName),
|
|
4991
|
+
findConstraintTag: (tagName) => constraintTagMap.get((0, import_internal4.normalizeFormSpecTagName)(tagName)),
|
|
4736
4992
|
findBuiltinConstraintBroadening: (typeId, tagName) => builtinBroadeningMap.get(`${typeId}:${tagName}`),
|
|
4737
4993
|
findAnnotation: (annotationId) => annotationMap.get(annotationId)
|
|
4738
4994
|
};
|
|
4739
4995
|
}
|
|
4740
4996
|
|
|
4741
4997
|
// src/generators/method-schema.ts
|
|
4742
|
-
var
|
|
4998
|
+
var import_internals6 = require("@formspec/core/internals");
|
|
4743
4999
|
function typeToJsonSchema(type, checker) {
|
|
4744
5000
|
const typeRegistry = {};
|
|
4745
5001
|
const visiting = /* @__PURE__ */ new Set();
|
|
@@ -4764,7 +5020,7 @@ function typeToJsonSchema(type, checker) {
|
|
|
4764
5020
|
const fieldProvenance = { surface: "tsdoc", file: "", line: 0, column: 0 };
|
|
4765
5021
|
const ir = {
|
|
4766
5022
|
kind: "form-ir",
|
|
4767
|
-
irVersion:
|
|
5023
|
+
irVersion: import_internals6.IR_VERSION,
|
|
4768
5024
|
elements: [
|
|
4769
5025
|
{
|
|
4770
5026
|
kind: "field",
|