@formspec/build 0.1.0-alpha.32 → 0.1.0-alpha.33
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 +5 -1
- package/dist/analyzer/class-analyzer.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/cli.cjs +317 -165
- package/dist/cli.cjs.map +1 -1
- package/dist/cli.js +300 -140
- package/dist/cli.js.map +1 -1
- package/dist/extensions/registry.d.ts.map +1 -1
- package/dist/generators/discovered-schema.d.ts.map +1 -1
- package/dist/index.cjs +312 -161
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +299 -140
- package/dist/index.js.map +1 -1
- package/dist/internals.cjs +270 -127
- package/dist/internals.cjs.map +1 -1
- package/dist/internals.js +276 -125
- package/dist/internals.js.map +1 -1
- package/package.json +4 -4
package/dist/internals.js
CHANGED
|
@@ -730,6 +730,7 @@ import * as path from "path";
|
|
|
730
730
|
// src/analyzer/class-analyzer.ts
|
|
731
731
|
import * as ts3 from "typescript";
|
|
732
732
|
import {
|
|
733
|
+
analyzeMetadataForNodeWithChecker,
|
|
733
734
|
parseCommentBlock as parseCommentBlock2
|
|
734
735
|
} from "@formspec/analysis/internal";
|
|
735
736
|
|
|
@@ -743,6 +744,7 @@ import {
|
|
|
743
744
|
extractPathTarget as extractSharedPathTarget,
|
|
744
745
|
getTagDefinition,
|
|
745
746
|
hasTypeSemanticCapability,
|
|
747
|
+
normalizeFormSpecTagName,
|
|
746
748
|
parseConstraintTagValue,
|
|
747
749
|
parseDefaultValueTagValue,
|
|
748
750
|
resolveDeclarationPlacement,
|
|
@@ -779,7 +781,7 @@ function createFormSpecTSDocConfig(extensionTagNames = []) {
|
|
|
779
781
|
})
|
|
780
782
|
);
|
|
781
783
|
}
|
|
782
|
-
for (const tagName of ["displayName", "format", "placeholder"]) {
|
|
784
|
+
for (const tagName of ["apiName", "displayName", "format", "placeholder"]) {
|
|
783
785
|
config.addTagDefinition(
|
|
784
786
|
new TSDocTagDefinition({
|
|
785
787
|
tagName: "@" + tagName,
|
|
@@ -813,6 +815,16 @@ function sharedTagValueOptions(options) {
|
|
|
813
815
|
};
|
|
814
816
|
}
|
|
815
817
|
var SYNTHETIC_TYPE_FORMAT_FLAGS = ts.TypeFormatFlags.NoTruncation | ts.TypeFormatFlags.UseAliasDefinedOutsideCurrentScope;
|
|
818
|
+
function getExtensionTypeNames(registry) {
|
|
819
|
+
if (registry === void 0) {
|
|
820
|
+
return /* @__PURE__ */ new Set();
|
|
821
|
+
}
|
|
822
|
+
return new Set(
|
|
823
|
+
registry.extensions.flatMap(
|
|
824
|
+
(ext) => (ext.types ?? []).flatMap((t) => t.tsTypeNames ?? [t.typeName])
|
|
825
|
+
)
|
|
826
|
+
);
|
|
827
|
+
}
|
|
816
828
|
function collectImportedNames(sourceFile) {
|
|
817
829
|
const importedNames = /* @__PURE__ */ new Set();
|
|
818
830
|
for (const statement of sourceFile.statements) {
|
|
@@ -852,6 +864,9 @@ function isNonReferenceIdentifier(node) {
|
|
|
852
864
|
return false;
|
|
853
865
|
}
|
|
854
866
|
function statementReferencesImportedName(statement, importedNames) {
|
|
867
|
+
if (importedNames.size === 0) {
|
|
868
|
+
return false;
|
|
869
|
+
}
|
|
855
870
|
let referencesImportedName = false;
|
|
856
871
|
const visit = (node) => {
|
|
857
872
|
if (referencesImportedName) {
|
|
@@ -866,14 +881,17 @@ function statementReferencesImportedName(statement, importedNames) {
|
|
|
866
881
|
visit(statement);
|
|
867
882
|
return referencesImportedName;
|
|
868
883
|
}
|
|
869
|
-
function buildSupportingDeclarations(sourceFile) {
|
|
884
|
+
function buildSupportingDeclarations(sourceFile, extensionTypeNames) {
|
|
870
885
|
const importedNames = collectImportedNames(sourceFile);
|
|
886
|
+
const importedNamesToSkip = new Set(
|
|
887
|
+
[...importedNames].filter((name) => !extensionTypeNames.has(name))
|
|
888
|
+
);
|
|
871
889
|
return sourceFile.statements.filter((statement) => {
|
|
872
890
|
if (ts.isImportDeclaration(statement)) return false;
|
|
873
891
|
if (ts.isImportEqualsDeclaration(statement)) return false;
|
|
874
892
|
if (ts.isExportDeclaration(statement) && statement.moduleSpecifier !== void 0)
|
|
875
893
|
return false;
|
|
876
|
-
if (
|
|
894
|
+
if (statementReferencesImportedName(statement, importedNamesToSkip)) {
|
|
877
895
|
return false;
|
|
878
896
|
}
|
|
879
897
|
return true;
|
|
@@ -1130,6 +1148,14 @@ function buildCompilerBackedConstraintDiagnostics(node, sourceFile, tagName, par
|
|
|
1130
1148
|
extensionId: extension.extensionId,
|
|
1131
1149
|
...extension.constraintTags !== void 0 ? {
|
|
1132
1150
|
constraintTags: extension.constraintTags.map((tag) => ({ tagName: tag.tagName }))
|
|
1151
|
+
} : {},
|
|
1152
|
+
...extension.metadataSlots !== void 0 ? {
|
|
1153
|
+
metadataSlots: extension.metadataSlots
|
|
1154
|
+
} : {},
|
|
1155
|
+
...extension.types !== void 0 ? {
|
|
1156
|
+
customTypes: extension.types.map((t) => ({
|
|
1157
|
+
tsTypeNames: t.tsTypeNames ?? [t.typeName]
|
|
1158
|
+
}))
|
|
1133
1159
|
} : {}
|
|
1134
1160
|
}))
|
|
1135
1161
|
} : {}
|
|
@@ -1151,7 +1177,10 @@ var parseResultCache = /* @__PURE__ */ new Map();
|
|
|
1151
1177
|
function getParser(options) {
|
|
1152
1178
|
const extensionTagNames = [
|
|
1153
1179
|
...options?.extensionRegistry?.extensions.flatMap(
|
|
1154
|
-
(extension) => (extension.constraintTags ?? []).map((tag) => tag.tagName)
|
|
1180
|
+
(extension) => (extension.constraintTags ?? []).map((tag) => normalizeFormSpecTagName(tag.tagName))
|
|
1181
|
+
) ?? [],
|
|
1182
|
+
...options?.extensionRegistry?.extensions.flatMap(
|
|
1183
|
+
(extension) => (extension.metadataSlots ?? []).map((slot) => normalizeFormSpecTagName(slot.tagName))
|
|
1155
1184
|
) ?? []
|
|
1156
1185
|
].sort();
|
|
1157
1186
|
const cacheKey = extensionTagNames.join("|");
|
|
@@ -1171,7 +1200,16 @@ function getExtensionRegistryCacheKey(registry) {
|
|
|
1171
1200
|
(extension) => JSON.stringify({
|
|
1172
1201
|
extensionId: extension.extensionId,
|
|
1173
1202
|
typeNames: extension.types?.map((type) => type.typeName) ?? [],
|
|
1174
|
-
constraintTags: extension.constraintTags?.map((tag) => tag.tagName) ?? []
|
|
1203
|
+
constraintTags: extension.constraintTags?.map((tag) => normalizeFormSpecTagName(tag.tagName)) ?? [],
|
|
1204
|
+
metadataSlots: extension.metadataSlots?.map((slot) => ({
|
|
1205
|
+
tagName: normalizeFormSpecTagName(slot.tagName),
|
|
1206
|
+
declarationKinds: [...slot.declarationKinds].sort(),
|
|
1207
|
+
allowBare: slot.allowBare !== false,
|
|
1208
|
+
qualifiers: (slot.qualifiers ?? []).map((qualifier) => ({
|
|
1209
|
+
qualifier: qualifier.qualifier,
|
|
1210
|
+
...qualifier.sourceQualifier !== void 0 ? { sourceQualifier: qualifier.sourceQualifier } : {}
|
|
1211
|
+
})).sort((left, right) => left.qualifier.localeCompare(right.qualifier))
|
|
1212
|
+
})) ?? []
|
|
1175
1213
|
})
|
|
1176
1214
|
).join("|");
|
|
1177
1215
|
}
|
|
@@ -1206,7 +1244,8 @@ function parseTSDocTags(node, file = "", options) {
|
|
|
1206
1244
|
const rawTextTags = [];
|
|
1207
1245
|
const sourceFile = node.getSourceFile();
|
|
1208
1246
|
const sourceText = sourceFile.getFullText();
|
|
1209
|
-
const
|
|
1247
|
+
const extensionTypeNames = getExtensionTypeNames(options?.extensionRegistry);
|
|
1248
|
+
const supportingDeclarations = buildSupportingDeclarations(sourceFile, extensionTypeNames);
|
|
1210
1249
|
const commentRanges = ts.getLeadingCommentRanges(sourceText, node.getFullStart());
|
|
1211
1250
|
const rawTextFallbacks = collectRawTextFallbacks(node, file);
|
|
1212
1251
|
if (commentRanges) {
|
|
@@ -1634,76 +1673,50 @@ function makeParseOptions(extensionRegistry, fieldType, checker, subjectType, ho
|
|
|
1634
1673
|
...hostType !== void 0 && { hostType }
|
|
1635
1674
|
};
|
|
1636
1675
|
}
|
|
1637
|
-
function
|
|
1638
|
-
return
|
|
1639
|
-
|
|
1640
|
-
|
|
1641
|
-
let apiName;
|
|
1642
|
-
let displayName;
|
|
1643
|
-
let apiNamePlural;
|
|
1644
|
-
let displayNamePlural;
|
|
1645
|
-
for (const tag of getLeadingParsedTags(node)) {
|
|
1646
|
-
const value = tag.argumentText.trim();
|
|
1647
|
-
if (value === "") {
|
|
1648
|
-
continue;
|
|
1649
|
-
}
|
|
1650
|
-
if (tag.normalizedTagName === "apiName") {
|
|
1651
|
-
if (tag.target === null) {
|
|
1652
|
-
apiName ??= value;
|
|
1653
|
-
} else if (tag.target.kind === "variant") {
|
|
1654
|
-
if (tag.target.rawText === "singular") {
|
|
1655
|
-
apiName ??= value;
|
|
1656
|
-
} else if (tag.target.rawText === "plural") {
|
|
1657
|
-
apiNamePlural ??= value;
|
|
1658
|
-
}
|
|
1659
|
-
}
|
|
1660
|
-
continue;
|
|
1661
|
-
}
|
|
1662
|
-
if (tag.normalizedTagName === "displayName") {
|
|
1663
|
-
if (tag.target === null) {
|
|
1664
|
-
displayName ??= value;
|
|
1665
|
-
} else if (tag.target.kind === "variant") {
|
|
1666
|
-
if (tag.target.rawText === "singular") {
|
|
1667
|
-
displayName ??= value;
|
|
1668
|
-
} else if (tag.target.rawText === "plural") {
|
|
1669
|
-
displayNamePlural ??= value;
|
|
1670
|
-
}
|
|
1671
|
-
}
|
|
1672
|
-
}
|
|
1673
|
-
}
|
|
1674
|
-
const resolvedApiName = makeExplicitScalarMetadata(apiName);
|
|
1675
|
-
const resolvedDisplayName = makeExplicitScalarMetadata(displayName);
|
|
1676
|
-
const resolvedApiNamePlural = makeExplicitScalarMetadata(apiNamePlural);
|
|
1677
|
-
const resolvedDisplayNamePlural = makeExplicitScalarMetadata(displayNamePlural);
|
|
1678
|
-
const metadata = {
|
|
1679
|
-
...resolvedApiName !== void 0 && { apiName: resolvedApiName },
|
|
1680
|
-
...resolvedDisplayName !== void 0 && { displayName: resolvedDisplayName },
|
|
1681
|
-
...resolvedApiNamePlural !== void 0 && { apiNamePlural: resolvedApiNamePlural },
|
|
1682
|
-
...resolvedDisplayNamePlural !== void 0 && {
|
|
1683
|
-
displayNamePlural: resolvedDisplayNamePlural
|
|
1684
|
-
}
|
|
1676
|
+
function createAnalyzerMetadataPolicy(input) {
|
|
1677
|
+
return {
|
|
1678
|
+
raw: input,
|
|
1679
|
+
normalized: normalizeMetadataPolicy(input)
|
|
1685
1680
|
};
|
|
1686
|
-
return Object.keys(metadata).length === 0 ? void 0 : metadata;
|
|
1687
1681
|
}
|
|
1688
|
-
function resolveNodeMetadata(metadataPolicy, declarationKind, logicalName, node, buildContext) {
|
|
1689
|
-
const
|
|
1690
|
-
|
|
1691
|
-
|
|
1692
|
-
|
|
1693
|
-
|
|
1694
|
-
|
|
1695
|
-
|
|
1696
|
-
|
|
1697
|
-
|
|
1698
|
-
|
|
1699
|
-
|
|
1700
|
-
|
|
1701
|
-
getDeclarationMetadataPolicy(metadataPolicy, declarationKind),
|
|
1702
|
-
makeMetadataContext("tsdoc", declarationKind, logicalName, buildContext)
|
|
1682
|
+
function resolveNodeMetadata(metadataPolicy, declarationKind, logicalName, node, checker, extensionRegistry, buildContext) {
|
|
1683
|
+
const analysis = analyzeMetadataForNodeWithChecker({
|
|
1684
|
+
checker,
|
|
1685
|
+
node,
|
|
1686
|
+
logicalName,
|
|
1687
|
+
metadata: metadataPolicy.raw,
|
|
1688
|
+
extensions: extensionRegistry?.extensions,
|
|
1689
|
+
...buildContext !== void 0 && { buildContext }
|
|
1690
|
+
});
|
|
1691
|
+
const resolvedMetadata = analysis?.resolvedMetadata;
|
|
1692
|
+
const declarationPolicy = getDeclarationMetadataPolicy(
|
|
1693
|
+
metadataPolicy.normalized,
|
|
1694
|
+
declarationKind
|
|
1703
1695
|
);
|
|
1696
|
+
if (resolvedMetadata?.apiName === void 0 && declarationPolicy.apiName.mode === "require-explicit") {
|
|
1697
|
+
throw new Error(
|
|
1698
|
+
`Metadata policy requires explicit apiName for ${declarationKind} "${logicalName}" on the tsdoc surface.`
|
|
1699
|
+
);
|
|
1700
|
+
}
|
|
1701
|
+
if (resolvedMetadata?.displayName === void 0 && declarationPolicy.displayName.mode === "require-explicit") {
|
|
1702
|
+
throw new Error(
|
|
1703
|
+
`Metadata policy requires explicit displayName for ${declarationKind} "${logicalName}" on the tsdoc surface.`
|
|
1704
|
+
);
|
|
1705
|
+
}
|
|
1706
|
+
if (resolvedMetadata?.apiNamePlural === void 0 && declarationPolicy.apiName.pluralization.mode === "require-explicit") {
|
|
1707
|
+
throw new Error(
|
|
1708
|
+
`Metadata policy requires explicit apiNamePlural for ${declarationKind} "${logicalName}" on the tsdoc surface.`
|
|
1709
|
+
);
|
|
1710
|
+
}
|
|
1711
|
+
if (resolvedMetadata?.displayNamePlural === void 0 && declarationPolicy.displayName.pluralization.mode === "require-explicit") {
|
|
1712
|
+
throw new Error(
|
|
1713
|
+
`Metadata policy requires explicit displayNamePlural for ${declarationKind} "${logicalName}" on the tsdoc surface.`
|
|
1714
|
+
);
|
|
1715
|
+
}
|
|
1716
|
+
return resolvedMetadata;
|
|
1704
1717
|
}
|
|
1705
1718
|
function analyzeClassToIR(classDecl, checker, file = "", extensionRegistry, metadataPolicy) {
|
|
1706
|
-
const normalizedMetadataPolicy =
|
|
1719
|
+
const normalizedMetadataPolicy = createAnalyzerMetadataPolicy(metadataPolicy);
|
|
1707
1720
|
const name = classDecl.name?.text ?? "AnonymousClass";
|
|
1708
1721
|
const fields = [];
|
|
1709
1722
|
const fieldLayouts = [];
|
|
@@ -1758,12 +1771,20 @@ function analyzeClassToIR(classDecl, checker, file = "", extensionRegistry, meta
|
|
|
1758
1771
|
diagnostics,
|
|
1759
1772
|
normalizedMetadataPolicy
|
|
1760
1773
|
);
|
|
1761
|
-
const metadata = resolveNodeMetadata(
|
|
1774
|
+
const metadata = resolveNodeMetadata(
|
|
1775
|
+
normalizedMetadataPolicy,
|
|
1776
|
+
"type",
|
|
1777
|
+
name,
|
|
1778
|
+
classDecl,
|
|
1762
1779
|
checker,
|
|
1763
|
-
|
|
1764
|
-
|
|
1765
|
-
|
|
1766
|
-
|
|
1780
|
+
extensionRegistry,
|
|
1781
|
+
{
|
|
1782
|
+
checker,
|
|
1783
|
+
declaration: classDecl,
|
|
1784
|
+
subjectType: classType,
|
|
1785
|
+
hostType: classType
|
|
1786
|
+
}
|
|
1787
|
+
);
|
|
1767
1788
|
return {
|
|
1768
1789
|
name,
|
|
1769
1790
|
...metadata !== void 0 && { metadata },
|
|
@@ -1777,7 +1798,7 @@ function analyzeClassToIR(classDecl, checker, file = "", extensionRegistry, meta
|
|
|
1777
1798
|
};
|
|
1778
1799
|
}
|
|
1779
1800
|
function analyzeInterfaceToIR(interfaceDecl, checker, file = "", extensionRegistry, metadataPolicy) {
|
|
1780
|
-
const normalizedMetadataPolicy =
|
|
1801
|
+
const normalizedMetadataPolicy = createAnalyzerMetadataPolicy(metadataPolicy);
|
|
1781
1802
|
const name = interfaceDecl.name.text;
|
|
1782
1803
|
const fields = [];
|
|
1783
1804
|
const typeRegistry = {};
|
|
@@ -1819,12 +1840,20 @@ function analyzeInterfaceToIR(interfaceDecl, checker, file = "", extensionRegist
|
|
|
1819
1840
|
normalizedMetadataPolicy
|
|
1820
1841
|
);
|
|
1821
1842
|
const fieldLayouts = specializedFields.map(() => ({}));
|
|
1822
|
-
const metadata = resolveNodeMetadata(
|
|
1843
|
+
const metadata = resolveNodeMetadata(
|
|
1844
|
+
normalizedMetadataPolicy,
|
|
1845
|
+
"type",
|
|
1846
|
+
name,
|
|
1847
|
+
interfaceDecl,
|
|
1823
1848
|
checker,
|
|
1824
|
-
|
|
1825
|
-
|
|
1826
|
-
|
|
1827
|
-
|
|
1849
|
+
extensionRegistry,
|
|
1850
|
+
{
|
|
1851
|
+
checker,
|
|
1852
|
+
declaration: interfaceDecl,
|
|
1853
|
+
subjectType: interfaceType,
|
|
1854
|
+
hostType: interfaceType
|
|
1855
|
+
}
|
|
1856
|
+
);
|
|
1828
1857
|
return {
|
|
1829
1858
|
name,
|
|
1830
1859
|
...metadata !== void 0 && { metadata },
|
|
@@ -1848,7 +1877,7 @@ function analyzeTypeAliasToIR(typeAlias, checker, file = "", extensionRegistry,
|
|
|
1848
1877
|
};
|
|
1849
1878
|
}
|
|
1850
1879
|
const typeLiteral = typeAlias.type;
|
|
1851
|
-
const normalizedMetadataPolicy =
|
|
1880
|
+
const normalizedMetadataPolicy = createAnalyzerMetadataPolicy(metadataPolicy);
|
|
1852
1881
|
const name = typeAlias.name.text;
|
|
1853
1882
|
const fields = [];
|
|
1854
1883
|
const typeRegistry = {};
|
|
@@ -1889,12 +1918,20 @@ function analyzeTypeAliasToIR(typeAlias, checker, file = "", extensionRegistry,
|
|
|
1889
1918
|
diagnostics,
|
|
1890
1919
|
normalizedMetadataPolicy
|
|
1891
1920
|
);
|
|
1892
|
-
const metadata = resolveNodeMetadata(
|
|
1921
|
+
const metadata = resolveNodeMetadata(
|
|
1922
|
+
normalizedMetadataPolicy,
|
|
1923
|
+
"type",
|
|
1924
|
+
name,
|
|
1925
|
+
typeAlias,
|
|
1893
1926
|
checker,
|
|
1894
|
-
|
|
1895
|
-
|
|
1896
|
-
|
|
1897
|
-
|
|
1927
|
+
extensionRegistry,
|
|
1928
|
+
{
|
|
1929
|
+
checker,
|
|
1930
|
+
declaration: typeAlias,
|
|
1931
|
+
subjectType: aliasType,
|
|
1932
|
+
hostType: aliasType
|
|
1933
|
+
}
|
|
1934
|
+
);
|
|
1898
1935
|
return {
|
|
1899
1936
|
ok: true,
|
|
1900
1937
|
analysis: {
|
|
@@ -2147,6 +2184,8 @@ function resolveDiscriminatorApiName(boundType, checker, metadataPolicy) {
|
|
|
2147
2184
|
"type",
|
|
2148
2185
|
getDiscriminatorLogicalName(boundType, declaration, checker),
|
|
2149
2186
|
declaration,
|
|
2187
|
+
checker,
|
|
2188
|
+
void 0,
|
|
2150
2189
|
{
|
|
2151
2190
|
checker,
|
|
2152
2191
|
declaration,
|
|
@@ -2383,12 +2422,20 @@ function analyzeFieldToIR(prop, checker, file, typeRegistry, visiting, diagnosti
|
|
|
2383
2422
|
annotations.push(defaultAnnotation);
|
|
2384
2423
|
}
|
|
2385
2424
|
({ type, annotations } = applyEnumMemberDisplayNames(type, annotations));
|
|
2386
|
-
const metadata = resolveNodeMetadata(
|
|
2425
|
+
const metadata = resolveNodeMetadata(
|
|
2426
|
+
metadataPolicy,
|
|
2427
|
+
"field",
|
|
2428
|
+
name,
|
|
2429
|
+
prop,
|
|
2387
2430
|
checker,
|
|
2388
|
-
|
|
2389
|
-
|
|
2390
|
-
|
|
2391
|
-
|
|
2431
|
+
extensionRegistry,
|
|
2432
|
+
{
|
|
2433
|
+
checker,
|
|
2434
|
+
declaration: prop,
|
|
2435
|
+
subjectType: tsType,
|
|
2436
|
+
hostType
|
|
2437
|
+
}
|
|
2438
|
+
);
|
|
2392
2439
|
return {
|
|
2393
2440
|
kind: "field",
|
|
2394
2441
|
name,
|
|
@@ -2435,12 +2482,20 @@ function analyzeInterfacePropertyToIR(prop, checker, file, typeRegistry, visitin
|
|
|
2435
2482
|
let annotations = [];
|
|
2436
2483
|
annotations.push(...docResult.annotations);
|
|
2437
2484
|
({ type, annotations } = applyEnumMemberDisplayNames(type, annotations));
|
|
2438
|
-
const metadata = resolveNodeMetadata(
|
|
2485
|
+
const metadata = resolveNodeMetadata(
|
|
2486
|
+
metadataPolicy,
|
|
2487
|
+
"field",
|
|
2488
|
+
name,
|
|
2489
|
+
prop,
|
|
2439
2490
|
checker,
|
|
2440
|
-
|
|
2441
|
-
|
|
2442
|
-
|
|
2443
|
-
|
|
2491
|
+
extensionRegistry,
|
|
2492
|
+
{
|
|
2493
|
+
checker,
|
|
2494
|
+
declaration: prop,
|
|
2495
|
+
subjectType: tsType,
|
|
2496
|
+
hostType
|
|
2497
|
+
}
|
|
2498
|
+
);
|
|
2444
2499
|
return {
|
|
2445
2500
|
kind: "field",
|
|
2446
2501
|
name,
|
|
@@ -2569,7 +2624,7 @@ function getTypeNodeRegistrationName(typeNode) {
|
|
|
2569
2624
|
}
|
|
2570
2625
|
return null;
|
|
2571
2626
|
}
|
|
2572
|
-
function resolveTypeNode(type, checker, file, typeRegistry, visiting, sourceNode, metadataPolicy =
|
|
2627
|
+
function resolveTypeNode(type, checker, file, typeRegistry, visiting, sourceNode, metadataPolicy = createAnalyzerMetadataPolicy(void 0), extensionRegistry, diagnostics) {
|
|
2573
2628
|
const customType = resolveRegisteredCustomType(sourceNode, extensionRegistry, checker);
|
|
2574
2629
|
if (customType) {
|
|
2575
2630
|
return customType;
|
|
@@ -2659,7 +2714,7 @@ function resolveTypeNode(type, checker, file, typeRegistry, visiting, sourceNode
|
|
|
2659
2714
|
}
|
|
2660
2715
|
return { kind: "primitive", primitiveKind: "string" };
|
|
2661
2716
|
}
|
|
2662
|
-
function tryResolveNamedPrimitiveAlias(type, checker, file, typeRegistry, visiting, sourceNode, metadataPolicy =
|
|
2717
|
+
function tryResolveNamedPrimitiveAlias(type, checker, file, typeRegistry, visiting, sourceNode, metadataPolicy = createAnalyzerMetadataPolicy(void 0), extensionRegistry, diagnostics) {
|
|
2663
2718
|
if (!(type.flags & (ts3.TypeFlags.String | ts3.TypeFlags.Number | ts3.TypeFlags.BigInt | ts3.TypeFlags.BigIntLiteral | ts3.TypeFlags.Boolean | ts3.TypeFlags.Null))) {
|
|
2664
2719
|
return null;
|
|
2665
2720
|
}
|
|
@@ -2679,11 +2734,19 @@ function tryResolveNamedPrimitiveAlias(type, checker, file, typeRegistry, visiti
|
|
|
2679
2734
|
file,
|
|
2680
2735
|
makeParseOptions(extensionRegistry)
|
|
2681
2736
|
);
|
|
2682
|
-
const metadata = resolveNodeMetadata(
|
|
2737
|
+
const metadata = resolveNodeMetadata(
|
|
2738
|
+
metadataPolicy,
|
|
2739
|
+
"type",
|
|
2740
|
+
aliasName,
|
|
2741
|
+
aliasDecl,
|
|
2683
2742
|
checker,
|
|
2684
|
-
|
|
2685
|
-
|
|
2686
|
-
|
|
2743
|
+
extensionRegistry,
|
|
2744
|
+
{
|
|
2745
|
+
checker,
|
|
2746
|
+
declaration: aliasDecl,
|
|
2747
|
+
subjectType: aliasType
|
|
2748
|
+
}
|
|
2749
|
+
);
|
|
2687
2750
|
typeRegistry[aliasName] = {
|
|
2688
2751
|
name: aliasName,
|
|
2689
2752
|
...metadata !== void 0 && { metadata },
|
|
@@ -2722,7 +2785,7 @@ function shouldEmitPrimitiveAliasDefinition(typeNode, checker) {
|
|
|
2722
2785
|
const resolved = checker.getTypeFromTypeNode(aliasDecl.type);
|
|
2723
2786
|
return !!(resolved.flags & (ts3.TypeFlags.String | ts3.TypeFlags.Number | ts3.TypeFlags.BigInt | ts3.TypeFlags.BigIntLiteral | ts3.TypeFlags.Boolean | ts3.TypeFlags.Null));
|
|
2724
2787
|
}
|
|
2725
|
-
function resolveAliasedPrimitiveTarget(type, checker, file, typeRegistry, visiting, metadataPolicy =
|
|
2788
|
+
function resolveAliasedPrimitiveTarget(type, checker, file, typeRegistry, visiting, metadataPolicy = createAnalyzerMetadataPolicy(void 0), extensionRegistry, diagnostics) {
|
|
2726
2789
|
const nestedAliasDecl = type.aliasSymbol?.declarations?.find(ts3.isTypeAliasDeclaration);
|
|
2727
2790
|
if (nestedAliasDecl !== void 0) {
|
|
2728
2791
|
return resolveAliasedPrimitiveTarget(
|
|
@@ -2748,7 +2811,7 @@ function resolveAliasedPrimitiveTarget(type, checker, file, typeRegistry, visiti
|
|
|
2748
2811
|
diagnostics
|
|
2749
2812
|
);
|
|
2750
2813
|
}
|
|
2751
|
-
function resolveUnionType(type, checker, file, typeRegistry, visiting, sourceNode, metadataPolicy =
|
|
2814
|
+
function resolveUnionType(type, checker, file, typeRegistry, visiting, sourceNode, metadataPolicy = createAnalyzerMetadataPolicy(void 0), extensionRegistry, diagnostics) {
|
|
2752
2815
|
const typeName = getNamedTypeName(type);
|
|
2753
2816
|
const namedDecl = getNamedTypeDeclaration(type);
|
|
2754
2817
|
if (typeName && typeName in typeRegistry) {
|
|
@@ -2783,11 +2846,19 @@ function resolveUnionType(type, checker, file, typeRegistry, visiting, sourceNod
|
|
|
2783
2846
|
return result;
|
|
2784
2847
|
}
|
|
2785
2848
|
const annotations = namedDecl ? extractJSDocAnnotationNodes(namedDecl, file, makeParseOptions(extensionRegistry)) : void 0;
|
|
2786
|
-
const metadata = namedDecl !== void 0 ? resolveNodeMetadata(
|
|
2849
|
+
const metadata = namedDecl !== void 0 ? resolveNodeMetadata(
|
|
2850
|
+
metadataPolicy,
|
|
2851
|
+
"type",
|
|
2852
|
+
typeName,
|
|
2853
|
+
namedDecl,
|
|
2787
2854
|
checker,
|
|
2788
|
-
|
|
2789
|
-
|
|
2790
|
-
|
|
2855
|
+
extensionRegistry,
|
|
2856
|
+
{
|
|
2857
|
+
checker,
|
|
2858
|
+
declaration: namedDecl,
|
|
2859
|
+
subjectType: type
|
|
2860
|
+
}
|
|
2861
|
+
) : void 0;
|
|
2791
2862
|
typeRegistry[typeName] = {
|
|
2792
2863
|
name: typeName,
|
|
2793
2864
|
...metadata !== void 0 && { metadata },
|
|
@@ -2872,7 +2943,7 @@ function resolveUnionType(type, checker, file, typeRegistry, visiting, sourceNod
|
|
|
2872
2943
|
}
|
|
2873
2944
|
return registerNamed({ kind: "union", members });
|
|
2874
2945
|
}
|
|
2875
|
-
function resolveArrayType(type, checker, file, typeRegistry, visiting, sourceNode, metadataPolicy =
|
|
2946
|
+
function resolveArrayType(type, checker, file, typeRegistry, visiting, sourceNode, metadataPolicy = createAnalyzerMetadataPolicy(void 0), extensionRegistry, diagnostics) {
|
|
2876
2947
|
const typeArgs = isTypeReference(type) ? type.typeArguments : void 0;
|
|
2877
2948
|
const elementType = typeArgs?.[0];
|
|
2878
2949
|
const elementSourceNode = extractArrayElementTypeNode(sourceNode, checker);
|
|
@@ -2889,7 +2960,7 @@ function resolveArrayType(type, checker, file, typeRegistry, visiting, sourceNod
|
|
|
2889
2960
|
) : { kind: "primitive", primitiveKind: "string" };
|
|
2890
2961
|
return { kind: "array", items };
|
|
2891
2962
|
}
|
|
2892
|
-
function tryResolveRecordType(type, checker, file, typeRegistry, visiting, metadataPolicy =
|
|
2963
|
+
function tryResolveRecordType(type, checker, file, typeRegistry, visiting, metadataPolicy = createAnalyzerMetadataPolicy(void 0), extensionRegistry, diagnostics) {
|
|
2893
2964
|
if (type.getProperties().length > 0) {
|
|
2894
2965
|
return null;
|
|
2895
2966
|
}
|
|
@@ -2950,7 +3021,7 @@ function shouldEmitResolvedObjectProperty(property, declaration) {
|
|
|
2950
3021
|
}
|
|
2951
3022
|
return true;
|
|
2952
3023
|
}
|
|
2953
|
-
function resolveObjectType(type, checker, file, typeRegistry, visiting, sourceNode, metadataPolicy =
|
|
3024
|
+
function resolveObjectType(type, checker, file, typeRegistry, visiting, sourceNode, metadataPolicy = createAnalyzerMetadataPolicy(void 0), extensionRegistry, diagnostics) {
|
|
2954
3025
|
const collectedDiagnostics = diagnostics ?? [];
|
|
2955
3026
|
const typeName = getNamedTypeName(type);
|
|
2956
3027
|
const namedTypeName = typeName ?? void 0;
|
|
@@ -3026,11 +3097,19 @@ function resolveObjectType(type, checker, file, typeRegistry, visiting, sourceNo
|
|
|
3026
3097
|
return recordNode;
|
|
3027
3098
|
}
|
|
3028
3099
|
const annotations = namedDecl ? extractJSDocAnnotationNodes(namedDecl, file, makeParseOptions(extensionRegistry)) : void 0;
|
|
3029
|
-
const metadata = namedDecl !== void 0 ? resolveNodeMetadata(
|
|
3100
|
+
const metadata = namedDecl !== void 0 ? resolveNodeMetadata(
|
|
3101
|
+
metadataPolicy,
|
|
3102
|
+
"type",
|
|
3103
|
+
registryTypeName,
|
|
3104
|
+
namedDecl,
|
|
3030
3105
|
checker,
|
|
3031
|
-
|
|
3032
|
-
|
|
3033
|
-
|
|
3106
|
+
extensionRegistry,
|
|
3107
|
+
{
|
|
3108
|
+
checker,
|
|
3109
|
+
declaration: namedDecl,
|
|
3110
|
+
subjectType: type
|
|
3111
|
+
}
|
|
3112
|
+
) : void 0;
|
|
3034
3113
|
typeRegistry[registryTypeName] = {
|
|
3035
3114
|
name: registryTypeName,
|
|
3036
3115
|
...metadata !== void 0 && { metadata },
|
|
@@ -3126,11 +3205,19 @@ function resolveObjectType(type, checker, file, typeRegistry, visiting, sourceNo
|
|
|
3126
3205
|
};
|
|
3127
3206
|
if (registryTypeName !== void 0 && shouldRegisterNamedType) {
|
|
3128
3207
|
const annotations = namedDecl ? extractJSDocAnnotationNodes(namedDecl, file, makeParseOptions(extensionRegistry)) : void 0;
|
|
3129
|
-
const metadata = namedDecl !== void 0 ? resolveNodeMetadata(
|
|
3208
|
+
const metadata = namedDecl !== void 0 ? resolveNodeMetadata(
|
|
3209
|
+
metadataPolicy,
|
|
3210
|
+
"type",
|
|
3211
|
+
registryTypeName,
|
|
3212
|
+
namedDecl,
|
|
3130
3213
|
checker,
|
|
3131
|
-
|
|
3132
|
-
|
|
3133
|
-
|
|
3214
|
+
extensionRegistry,
|
|
3215
|
+
{
|
|
3216
|
+
checker,
|
|
3217
|
+
declaration: namedDecl,
|
|
3218
|
+
subjectType: type
|
|
3219
|
+
}
|
|
3220
|
+
) : void 0;
|
|
3134
3221
|
typeRegistry[registryTypeName] = {
|
|
3135
3222
|
name: registryTypeName,
|
|
3136
3223
|
...metadata !== void 0 && { metadata },
|
|
@@ -4635,13 +4722,35 @@ function formatLocation(location) {
|
|
|
4635
4722
|
}
|
|
4636
4723
|
|
|
4637
4724
|
// src/extensions/registry.ts
|
|
4725
|
+
import {
|
|
4726
|
+
BUILTIN_CONSTRAINT_DEFINITIONS as BUILTIN_CONSTRAINT_DEFINITIONS2,
|
|
4727
|
+
normalizeConstraintTagName as normalizeConstraintTagName2
|
|
4728
|
+
} from "@formspec/core/internals";
|
|
4729
|
+
import {
|
|
4730
|
+
getTagDefinition as getTagDefinition2,
|
|
4731
|
+
normalizeFormSpecTagName as normalizeFormSpecTagName2
|
|
4732
|
+
} from "@formspec/analysis/internal";
|
|
4733
|
+
var BUILTIN_METADATA_TAGS = /* @__PURE__ */ new Set(["apiName", "displayName"]);
|
|
4734
|
+
function buildConstraintTagSources(extensions) {
|
|
4735
|
+
return extensions.map((extension) => ({
|
|
4736
|
+
extensionId: extension.extensionId,
|
|
4737
|
+
...extension.constraintTags !== void 0 ? {
|
|
4738
|
+
constraintTags: extension.constraintTags.map((tag) => ({
|
|
4739
|
+
tagName: normalizeFormSpecTagName2(tag.tagName)
|
|
4740
|
+
}))
|
|
4741
|
+
} : {}
|
|
4742
|
+
}));
|
|
4743
|
+
}
|
|
4638
4744
|
function createExtensionRegistry(extensions) {
|
|
4745
|
+
const reservedTagSources = buildConstraintTagSources(extensions);
|
|
4639
4746
|
const typeMap = /* @__PURE__ */ new Map();
|
|
4640
4747
|
const typeNameMap = /* @__PURE__ */ new Map();
|
|
4641
4748
|
const constraintMap = /* @__PURE__ */ new Map();
|
|
4642
4749
|
const constraintTagMap = /* @__PURE__ */ new Map();
|
|
4643
4750
|
const builtinBroadeningMap = /* @__PURE__ */ new Map();
|
|
4644
4751
|
const annotationMap = /* @__PURE__ */ new Map();
|
|
4752
|
+
const metadataSlotMap = /* @__PURE__ */ new Map();
|
|
4753
|
+
const metadataTagMap = /* @__PURE__ */ new Map();
|
|
4645
4754
|
for (const ext of extensions) {
|
|
4646
4755
|
if (ext.types !== void 0) {
|
|
4647
4756
|
for (const type of ext.types) {
|
|
@@ -4684,10 +4793,11 @@ function createExtensionRegistry(extensions) {
|
|
|
4684
4793
|
}
|
|
4685
4794
|
if (ext.constraintTags !== void 0) {
|
|
4686
4795
|
for (const tag of ext.constraintTags) {
|
|
4687
|
-
|
|
4688
|
-
|
|
4796
|
+
const canonicalTagName = normalizeFormSpecTagName2(tag.tagName);
|
|
4797
|
+
if (constraintTagMap.has(canonicalTagName)) {
|
|
4798
|
+
throw new Error(`Duplicate custom constraint tag: "@${canonicalTagName}"`);
|
|
4689
4799
|
}
|
|
4690
|
-
constraintTagMap.set(
|
|
4800
|
+
constraintTagMap.set(canonicalTagName, {
|
|
4691
4801
|
extensionId: ext.extensionId,
|
|
4692
4802
|
registration: tag
|
|
4693
4803
|
});
|
|
@@ -4702,13 +4812,54 @@ function createExtensionRegistry(extensions) {
|
|
|
4702
4812
|
annotationMap.set(qualifiedId, annotation);
|
|
4703
4813
|
}
|
|
4704
4814
|
}
|
|
4815
|
+
if (ext.metadataSlots !== void 0) {
|
|
4816
|
+
for (const slot of ext.metadataSlots) {
|
|
4817
|
+
if (metadataSlotMap.has(slot.slotId)) {
|
|
4818
|
+
throw new Error(`Duplicate metadata slot ID: "${slot.slotId}"`);
|
|
4819
|
+
}
|
|
4820
|
+
metadataSlotMap.set(slot.slotId, true);
|
|
4821
|
+
const canonicalTagName = normalizeFormSpecTagName2(slot.tagName);
|
|
4822
|
+
if (slot.allowBare === false && (slot.qualifiers?.length ?? 0) === 0) {
|
|
4823
|
+
throw new Error(
|
|
4824
|
+
`Metadata tag "@${canonicalTagName}" must allow bare usage or declare at least one qualifier.`
|
|
4825
|
+
);
|
|
4826
|
+
}
|
|
4827
|
+
if (metadataTagMap.has(canonicalTagName)) {
|
|
4828
|
+
throw new Error(`Duplicate metadata tag: "@${canonicalTagName}"`);
|
|
4829
|
+
}
|
|
4830
|
+
if (BUILTIN_METADATA_TAGS.has(canonicalTagName)) {
|
|
4831
|
+
throw new Error(
|
|
4832
|
+
`Metadata tag "@${canonicalTagName}" conflicts with built-in metadata tags.`
|
|
4833
|
+
);
|
|
4834
|
+
}
|
|
4835
|
+
if (constraintTagMap.has(canonicalTagName)) {
|
|
4836
|
+
throw new Error(
|
|
4837
|
+
`Metadata tag "@${canonicalTagName}" conflicts with existing FormSpec tag "@${canonicalTagName}".`
|
|
4838
|
+
);
|
|
4839
|
+
}
|
|
4840
|
+
if (Object.hasOwn(BUILTIN_CONSTRAINT_DEFINITIONS2, normalizeConstraintTagName2(canonicalTagName))) {
|
|
4841
|
+
throw new Error(
|
|
4842
|
+
`Metadata tag "@${canonicalTagName}" conflicts with existing FormSpec tag "@${normalizeConstraintTagName2(canonicalTagName)}".`
|
|
4843
|
+
);
|
|
4844
|
+
}
|
|
4845
|
+
const existingTag = getTagDefinition2(canonicalTagName, reservedTagSources);
|
|
4846
|
+
if (existingTag !== null) {
|
|
4847
|
+
throw BUILTIN_METADATA_TAGS.has(existingTag.canonicalName) ? new Error(
|
|
4848
|
+
`Metadata tag "@${canonicalTagName}" conflicts with built-in metadata tags.`
|
|
4849
|
+
) : new Error(
|
|
4850
|
+
`Metadata tag "@${canonicalTagName}" conflicts with existing FormSpec tag "@${existingTag.canonicalName}".`
|
|
4851
|
+
);
|
|
4852
|
+
}
|
|
4853
|
+
metadataTagMap.set(canonicalTagName, true);
|
|
4854
|
+
}
|
|
4855
|
+
}
|
|
4705
4856
|
}
|
|
4706
4857
|
return {
|
|
4707
4858
|
extensions,
|
|
4708
4859
|
findType: (typeId) => typeMap.get(typeId),
|
|
4709
4860
|
findTypeByName: (typeName) => typeNameMap.get(typeName),
|
|
4710
4861
|
findConstraint: (constraintId) => constraintMap.get(constraintId),
|
|
4711
|
-
findConstraintTag: (tagName) => constraintTagMap.get(tagName),
|
|
4862
|
+
findConstraintTag: (tagName) => constraintTagMap.get(normalizeFormSpecTagName2(tagName)),
|
|
4712
4863
|
findBuiltinConstraintBroadening: (typeId, tagName) => builtinBroadeningMap.get(`${typeId}:${tagName}`),
|
|
4713
4864
|
findAnnotation: (annotationId) => annotationMap.get(annotationId)
|
|
4714
4865
|
};
|