@formspec/build 0.1.0-alpha.8 → 0.1.0-alpha.9
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/README.md +14 -14
- package/dist/__tests__/analyzer-edge-cases.test.d.ts +13 -0
- package/dist/__tests__/analyzer-edge-cases.test.d.ts.map +1 -0
- package/dist/__tests__/analyzer-edge-cases.test.js +376 -0
- package/dist/__tests__/analyzer-edge-cases.test.js.map +1 -0
- package/dist/__tests__/analyzer.test.d.ts +5 -0
- package/dist/__tests__/analyzer.test.d.ts.map +1 -0
- package/dist/__tests__/analyzer.test.js +190 -0
- package/dist/__tests__/analyzer.test.js.map +1 -0
- package/dist/__tests__/cli.test.js.map +1 -1
- package/dist/__tests__/codegen.test.d.ts +5 -0
- package/dist/__tests__/codegen.test.d.ts.map +1 -0
- package/dist/__tests__/codegen.test.js +506 -0
- package/dist/__tests__/codegen.test.js.map +1 -0
- package/dist/__tests__/decorator-pipeline.test.d.ts +11 -0
- package/dist/__tests__/decorator-pipeline.test.d.ts.map +1 -0
- package/dist/__tests__/decorator-pipeline.test.js +460 -0
- package/dist/__tests__/decorator-pipeline.test.js.map +1 -0
- package/dist/__tests__/edge-cases.test.js +1 -3
- package/dist/__tests__/edge-cases.test.js.map +1 -1
- package/dist/__tests__/fixtures/edge-cases.d.ts +110 -0
- package/dist/__tests__/fixtures/edge-cases.d.ts.map +1 -0
- package/dist/__tests__/fixtures/edge-cases.js +137 -0
- package/dist/__tests__/fixtures/edge-cases.js.map +1 -0
- package/dist/__tests__/fixtures/example-a-builtins.d.ts +12 -0
- package/dist/__tests__/fixtures/example-a-builtins.d.ts.map +1 -0
- package/dist/__tests__/fixtures/example-a-builtins.js +100 -0
- package/dist/__tests__/fixtures/example-a-builtins.js.map +1 -0
- package/dist/__tests__/fixtures/example-b-decorators.d.ts +5 -0
- package/dist/__tests__/fixtures/example-b-decorators.d.ts.map +1 -0
- package/dist/__tests__/fixtures/example-b-decorators.js +5 -0
- package/dist/__tests__/fixtures/example-b-decorators.js.map +1 -0
- package/dist/__tests__/fixtures/example-b-extended.d.ts +5 -0
- package/dist/__tests__/fixtures/example-b-extended.d.ts.map +1 -0
- package/dist/__tests__/fixtures/example-b-extended.js +60 -0
- package/dist/__tests__/fixtures/example-b-extended.js.map +1 -0
- package/dist/__tests__/fixtures/example-c-custom.d.ts +5 -0
- package/dist/__tests__/fixtures/example-c-custom.d.ts.map +1 -0
- package/dist/__tests__/fixtures/example-c-custom.js +61 -0
- package/dist/__tests__/fixtures/example-c-custom.js.map +1 -0
- package/dist/__tests__/fixtures/example-c-decorators.d.ts +5 -0
- package/dist/__tests__/fixtures/example-c-decorators.d.ts.map +1 -0
- package/dist/__tests__/fixtures/example-c-decorators.js +4 -0
- package/dist/__tests__/fixtures/example-c-decorators.js.map +1 -0
- package/dist/__tests__/fixtures/example-d-mixed-decorators.d.ts +6 -0
- package/dist/__tests__/fixtures/example-d-mixed-decorators.d.ts.map +1 -0
- package/dist/__tests__/fixtures/example-d-mixed-decorators.js +75 -0
- package/dist/__tests__/fixtures/example-d-mixed-decorators.js.map +1 -0
- package/dist/__tests__/fixtures/example-e-decorators.d.ts +11 -0
- package/dist/__tests__/fixtures/example-e-decorators.d.ts.map +1 -0
- package/dist/__tests__/fixtures/example-e-decorators.js +10 -0
- package/dist/__tests__/fixtures/example-e-decorators.js.map +1 -0
- package/dist/__tests__/fixtures/example-e-no-namespace.d.ts +5 -0
- package/dist/__tests__/fixtures/example-e-no-namespace.d.ts.map +1 -0
- package/dist/__tests__/fixtures/example-e-no-namespace.js +61 -0
- package/dist/__tests__/fixtures/example-e-no-namespace.js.map +1 -0
- package/dist/__tests__/fixtures/example-jsdoc-constraints.d.ts +16 -0
- package/dist/__tests__/fixtures/example-jsdoc-constraints.d.ts.map +1 -0
- package/dist/__tests__/fixtures/example-jsdoc-constraints.js +98 -0
- package/dist/__tests__/fixtures/example-jsdoc-constraints.js.map +1 -0
- package/dist/__tests__/fixtures/example-nested-class.d.ts +45 -0
- package/dist/__tests__/fixtures/example-nested-class.d.ts.map +1 -0
- package/dist/__tests__/fixtures/example-nested-class.js +248 -0
- package/dist/__tests__/fixtures/example-nested-class.js.map +1 -0
- package/dist/__tests__/fixtures/sample-forms.d.ts +55 -0
- package/dist/__tests__/fixtures/sample-forms.d.ts.map +1 -0
- package/dist/__tests__/fixtures/sample-forms.js +78 -0
- package/dist/__tests__/fixtures/sample-forms.js.map +1 -0
- package/dist/__tests__/generator.test.js +6 -6
- package/dist/__tests__/generator.test.js.map +1 -1
- package/dist/__tests__/integration.test.js +1 -3
- package/dist/__tests__/integration.test.js.map +1 -1
- package/dist/__tests__/jsdoc-constraints.test.d.ts +10 -0
- package/dist/__tests__/jsdoc-constraints.test.d.ts.map +1 -0
- package/dist/__tests__/jsdoc-constraints.test.js +199 -0
- package/dist/__tests__/jsdoc-constraints.test.js.map +1 -0
- package/dist/__tests__/write-schemas.test.js.map +1 -1
- package/dist/analyzer/class-analyzer.d.ts +85 -0
- package/dist/analyzer/class-analyzer.d.ts.map +1 -0
- package/dist/analyzer/class-analyzer.js +215 -0
- package/dist/analyzer/class-analyzer.js.map +1 -0
- package/dist/analyzer/decorator-extractor.d.ts +78 -0
- package/dist/analyzer/decorator-extractor.d.ts.map +1 -0
- package/dist/analyzer/decorator-extractor.js +336 -0
- package/dist/analyzer/decorator-extractor.js.map +1 -0
- package/dist/analyzer/jsdoc-constraints.d.ts +27 -0
- package/dist/analyzer/jsdoc-constraints.d.ts.map +1 -0
- package/dist/analyzer/jsdoc-constraints.js +91 -0
- package/dist/analyzer/jsdoc-constraints.js.map +1 -0
- package/dist/analyzer/program.d.ts +37 -0
- package/dist/analyzer/program.d.ts.map +1 -0
- package/dist/analyzer/program.js +87 -0
- package/dist/analyzer/program.js.map +1 -0
- package/dist/analyzer/type-converter.d.ts +75 -0
- package/dist/analyzer/type-converter.d.ts.map +1 -0
- package/dist/analyzer/type-converter.js +436 -0
- package/dist/analyzer/type-converter.js.map +1 -0
- package/dist/browser.d.ts +3 -2
- package/dist/browser.d.ts.map +1 -1
- package/dist/browser.js +1 -0
- package/dist/browser.js.map +1 -1
- package/dist/build.d.ts +196 -2
- package/dist/cli.js +1 -3
- package/dist/cli.js.map +1 -1
- package/dist/codegen/index.d.ts +75 -0
- package/dist/codegen/index.d.ts.map +1 -0
- package/dist/codegen/index.js +597 -0
- package/dist/codegen/index.js.map +1 -0
- package/dist/generators/class-schema.d.ts +84 -0
- package/dist/generators/class-schema.d.ts.map +1 -0
- package/dist/generators/class-schema.js +91 -0
- package/dist/generators/class-schema.js.map +1 -0
- package/dist/generators/method-schema.d.ts +67 -0
- package/dist/generators/method-schema.d.ts.map +1 -0
- package/dist/generators/method-schema.js +108 -0
- package/dist/generators/method-schema.js.map +1 -0
- package/dist/index.d.ts +8 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +9 -1
- package/dist/index.js.map +1 -1
- package/dist/internals.d.ts +19 -0
- package/dist/internals.d.ts.map +1 -0
- package/dist/internals.js +22 -0
- package/dist/internals.js.map +1 -0
- package/dist/json-schema/generator.d.ts.map +1 -1
- package/dist/json-schema/generator.js +1 -2
- package/dist/json-schema/generator.js.map +1 -1
- package/dist/json-schema/types.d.ts +28 -0
- package/dist/json-schema/types.d.ts.map +1 -1
- package/dist/json-schema/types.js +27 -1
- package/dist/json-schema/types.js.map +1 -1
- package/dist/ui-schema/generator.d.ts.map +1 -1
- package/dist/ui-schema/generator.js +1 -3
- package/dist/ui-schema/generator.js.map +1 -1
- package/dist/ui-schema/types.d.ts.map +1 -1
- package/package.json +11 -3
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"class-analyzer.d.ts","sourceRoot":"","sources":["../../src/analyzer/class-analyzer.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,KAAK,EAAE,MAAM,YAAY,CAAC;AACjC,OAAO,EAAuC,KAAK,aAAa,EAAE,MAAM,0BAA0B,CAAC;AAGnG;;GAEG;AACH,MAAM,WAAW,SAAS;IACxB,iBAAiB;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,yCAAyC;IACzC,QAAQ,EAAE,EAAE,CAAC,QAAQ,GAAG,SAAS,CAAC;IAClC,0CAA0C;IAC1C,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC;IACd,qDAAqD;IACrD,QAAQ,EAAE,OAAO,CAAC;IAClB,sCAAsC;IACtC,UAAU,EAAE,aAAa,EAAE,CAAC;IAC5B,oDAAoD;IACpD,UAAU,EAAE,OAAO,CAAC;IACpB,kFAAkF;IAClF,YAAY,EAAE,OAAO,CAAC;CACvB;AAED;;GAEG;AACH,MAAM,WAAW,aAAa;IAC5B,iBAAiB;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,sBAAsB;IACtB,MAAM,EAAE,SAAS,EAAE,CAAC;IACpB,uBAAuB;IACvB,eAAe,EAAE,UAAU,EAAE,CAAC;IAC9B,qBAAqB;IACrB,aAAa,EAAE,UAAU,EAAE,CAAC;CAC7B;AAED;;GAEG;AACH,MAAM,WAAW,UAAU;IACzB,kBAAkB;IAClB,IAAI,EAAE,MAAM,CAAC;IACb,wBAAwB;IACxB,UAAU,EAAE,aAAa,EAAE,CAAC;IAC5B,uBAAuB;IACvB,cAAc,EAAE,EAAE,CAAC,QAAQ,GAAG,SAAS,CAAC;IACxC,2BAA2B;IAC3B,UAAU,EAAE,EAAE,CAAC,IAAI,CAAC;CACrB;AAED;;GAEG;AACH,MAAM,WAAW,aAAa;IAC5B,qBAAqB;IACrB,IAAI,EAAE,MAAM,CAAC;IACb,2BAA2B;IAC3B,QAAQ,EAAE,EAAE,CAAC,QAAQ,GAAG,SAAS,CAAC;IAClC,oBAAoB;IACpB,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC;IACd,0DAA0D;IAC1D,kBAAkB,EAAE,MAAM,GAAG,IAAI,CAAC;IAClC,iEAAiE;IACjE,QAAQ,EAAE,OAAO,CAAC;CACnB;AAED;;;;;;GAMG;AACH,wBAAgB,YAAY,CAC1B,SAAS,EAAE,EAAE,CAAC,gBAAgB,EAC9B,OAAO,EAAE,EAAE,CAAC,WAAW,GACtB,aAAa,CA+Bf;AAED;;GAEG;AACH,wBAAgB,YAAY,CAC1B,IAAI,EAAE,EAAE,CAAC,mBAAmB,EAC5B,OAAO,EAAE,EAAE,CAAC,WAAW,GACtB,SAAS,GAAG,IAAI,CAsClB"}
|
|
@@ -0,0 +1,215 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Class analyzer for extracting fields, types, and decorators.
|
|
3
|
+
*
|
|
4
|
+
* Analyzes a TypeScript class declaration to extract:
|
|
5
|
+
* - Field names and TypeScript types
|
|
6
|
+
* - Decorator metadata (Field, Minimum, Maximum, etc.)
|
|
7
|
+
* - Field optionality
|
|
8
|
+
* - TSDoc @deprecated tags
|
|
9
|
+
* - Default values from property initializers
|
|
10
|
+
*/
|
|
11
|
+
import * as ts from "typescript";
|
|
12
|
+
import { extractDecorators, resolveDecorator } from "./decorator-extractor.js";
|
|
13
|
+
import { extractJSDocConstraints } from "./jsdoc-constraints.js";
|
|
14
|
+
/**
|
|
15
|
+
* Analyzes a class declaration to extract fields and methods.
|
|
16
|
+
*
|
|
17
|
+
* @param classDecl - The class declaration to analyze
|
|
18
|
+
* @param checker - TypeScript type checker
|
|
19
|
+
* @returns Analysis result with fields and methods
|
|
20
|
+
*/
|
|
21
|
+
export function analyzeClass(classDecl, checker) {
|
|
22
|
+
const name = classDecl.name?.text ?? "AnonymousClass";
|
|
23
|
+
const fields = [];
|
|
24
|
+
const instanceMethods = [];
|
|
25
|
+
const staticMethods = [];
|
|
26
|
+
for (const member of classDecl.members) {
|
|
27
|
+
if (ts.isPropertyDeclaration(member)) {
|
|
28
|
+
const fieldInfo = analyzeField(member, checker);
|
|
29
|
+
if (fieldInfo) {
|
|
30
|
+
fields.push(fieldInfo);
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
else if (ts.isMethodDeclaration(member)) {
|
|
34
|
+
const methodInfo = analyzeMethod(member, checker);
|
|
35
|
+
if (methodInfo) {
|
|
36
|
+
const isStatic = member.modifiers?.some((m) => m.kind === ts.SyntaxKind.StaticKeyword);
|
|
37
|
+
if (isStatic) {
|
|
38
|
+
staticMethods.push(methodInfo);
|
|
39
|
+
}
|
|
40
|
+
else {
|
|
41
|
+
instanceMethods.push(methodInfo);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
return {
|
|
47
|
+
name,
|
|
48
|
+
fields,
|
|
49
|
+
instanceMethods,
|
|
50
|
+
staticMethods,
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Analyzes a property declaration to extract field info.
|
|
55
|
+
*/
|
|
56
|
+
export function analyzeField(prop, checker) {
|
|
57
|
+
// Skip computed property names
|
|
58
|
+
if (!ts.isIdentifier(prop.name)) {
|
|
59
|
+
return null;
|
|
60
|
+
}
|
|
61
|
+
const name = prop.name.text;
|
|
62
|
+
const typeNode = prop.type;
|
|
63
|
+
const type = checker.getTypeAtLocation(prop);
|
|
64
|
+
const optional = prop.questionToken !== undefined;
|
|
65
|
+
const decorators = extractDecorators(prop);
|
|
66
|
+
// Resolve each decorator via the type checker to detect extended/custom decorators
|
|
67
|
+
for (const dec of decorators) {
|
|
68
|
+
if (dec.node) {
|
|
69
|
+
const resolved = resolveDecorator(dec.node, checker);
|
|
70
|
+
if (resolved) {
|
|
71
|
+
dec.resolved = resolved;
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
// Merge JSDoc constraint tags (e.g., /** @Minimum 0 @Maximum 100 */)
|
|
76
|
+
const jsdocConstraints = extractJSDocConstraints(prop);
|
|
77
|
+
decorators.push(...jsdocConstraints);
|
|
78
|
+
const deprecated = hasDeprecatedTag(prop);
|
|
79
|
+
const defaultValue = extractDefaultValue(prop.initializer);
|
|
80
|
+
return {
|
|
81
|
+
name,
|
|
82
|
+
typeNode,
|
|
83
|
+
type,
|
|
84
|
+
optional,
|
|
85
|
+
decorators,
|
|
86
|
+
deprecated,
|
|
87
|
+
defaultValue,
|
|
88
|
+
};
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* Checks if a node has a TSDoc `@deprecated` tag.
|
|
92
|
+
*/
|
|
93
|
+
function hasDeprecatedTag(node) {
|
|
94
|
+
const jsDocTags = ts.getJSDocTags(node);
|
|
95
|
+
return jsDocTags.some((tag) => tag.tagName.text === "deprecated");
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* Extracts a default value from a property initializer.
|
|
99
|
+
*
|
|
100
|
+
* Only extracts literal values (strings, numbers, booleans, null).
|
|
101
|
+
* Non-literal initializers (function calls, expressions, etc.) return undefined.
|
|
102
|
+
*/
|
|
103
|
+
function extractDefaultValue(initializer) {
|
|
104
|
+
if (!initializer)
|
|
105
|
+
return undefined;
|
|
106
|
+
// String literal
|
|
107
|
+
if (ts.isStringLiteral(initializer)) {
|
|
108
|
+
return initializer.text;
|
|
109
|
+
}
|
|
110
|
+
// Numeric literal
|
|
111
|
+
if (ts.isNumericLiteral(initializer)) {
|
|
112
|
+
return Number(initializer.text);
|
|
113
|
+
}
|
|
114
|
+
// Boolean literals
|
|
115
|
+
if (initializer.kind === ts.SyntaxKind.TrueKeyword) {
|
|
116
|
+
return true;
|
|
117
|
+
}
|
|
118
|
+
if (initializer.kind === ts.SyntaxKind.FalseKeyword) {
|
|
119
|
+
return false;
|
|
120
|
+
}
|
|
121
|
+
// Null literal
|
|
122
|
+
if (initializer.kind === ts.SyntaxKind.NullKeyword) {
|
|
123
|
+
return null;
|
|
124
|
+
}
|
|
125
|
+
// Negative number
|
|
126
|
+
if (ts.isPrefixUnaryExpression(initializer)) {
|
|
127
|
+
if (initializer.operator === ts.SyntaxKind.MinusToken &&
|
|
128
|
+
ts.isNumericLiteral(initializer.operand)) {
|
|
129
|
+
return -Number(initializer.operand.text);
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
// Non-literal initializer — can't extract statically
|
|
133
|
+
return undefined;
|
|
134
|
+
}
|
|
135
|
+
/**
|
|
136
|
+
* Analyzes a method declaration to extract method info.
|
|
137
|
+
*/
|
|
138
|
+
function analyzeMethod(method, checker) {
|
|
139
|
+
// Skip computed method names
|
|
140
|
+
if (!ts.isIdentifier(method.name)) {
|
|
141
|
+
return null;
|
|
142
|
+
}
|
|
143
|
+
const name = method.name.text;
|
|
144
|
+
const parameters = [];
|
|
145
|
+
for (const param of method.parameters) {
|
|
146
|
+
if (ts.isIdentifier(param.name)) {
|
|
147
|
+
const paramInfo = analyzeParameter(param, checker);
|
|
148
|
+
parameters.push(paramInfo);
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
const returnTypeNode = method.type;
|
|
152
|
+
const signature = checker.getSignatureFromDeclaration(method);
|
|
153
|
+
const returnType = signature
|
|
154
|
+
? checker.getReturnTypeOfSignature(signature)
|
|
155
|
+
: checker.getTypeAtLocation(method);
|
|
156
|
+
return {
|
|
157
|
+
name,
|
|
158
|
+
parameters,
|
|
159
|
+
returnTypeNode,
|
|
160
|
+
returnType,
|
|
161
|
+
};
|
|
162
|
+
}
|
|
163
|
+
/**
|
|
164
|
+
* Analyzes a parameter declaration.
|
|
165
|
+
*/
|
|
166
|
+
function analyzeParameter(param, checker) {
|
|
167
|
+
const name = ts.isIdentifier(param.name) ? param.name.text : "param";
|
|
168
|
+
const typeNode = param.type;
|
|
169
|
+
const type = checker.getTypeAtLocation(param);
|
|
170
|
+
const formSpecExportName = detectFormSpecReference(typeNode);
|
|
171
|
+
// Parameter is optional if it has a question token or a default value
|
|
172
|
+
const optional = param.questionToken !== undefined || param.initializer !== undefined;
|
|
173
|
+
return {
|
|
174
|
+
name,
|
|
175
|
+
typeNode,
|
|
176
|
+
type,
|
|
177
|
+
formSpecExportName,
|
|
178
|
+
optional,
|
|
179
|
+
};
|
|
180
|
+
}
|
|
181
|
+
/**
|
|
182
|
+
* Detects if a type node is InferSchema<typeof X> or InferFormSchema<typeof X> and extracts X.
|
|
183
|
+
*
|
|
184
|
+
* @param typeNode - The type node to check
|
|
185
|
+
* @returns The export name X, or null if not a FormSpec inference pattern
|
|
186
|
+
*/
|
|
187
|
+
function detectFormSpecReference(typeNode) {
|
|
188
|
+
if (!typeNode)
|
|
189
|
+
return null;
|
|
190
|
+
// Looking for: InferSchema<typeof X> or InferFormSchema<typeof X>
|
|
191
|
+
if (!ts.isTypeReferenceNode(typeNode))
|
|
192
|
+
return null;
|
|
193
|
+
// Get the type name - could be Identifier or QualifiedName
|
|
194
|
+
const typeName = ts.isIdentifier(typeNode.typeName)
|
|
195
|
+
? typeNode.typeName.text
|
|
196
|
+
: ts.isQualifiedName(typeNode.typeName)
|
|
197
|
+
? typeNode.typeName.right.text
|
|
198
|
+
: null;
|
|
199
|
+
// Support both InferSchema (for elements) and InferFormSchema (for FormSpec)
|
|
200
|
+
if (typeName !== "InferSchema" && typeName !== "InferFormSchema")
|
|
201
|
+
return null;
|
|
202
|
+
const typeArg = typeNode.typeArguments?.[0];
|
|
203
|
+
if (!typeArg || !ts.isTypeQueryNode(typeArg))
|
|
204
|
+
return null;
|
|
205
|
+
// typeArg.exprName is the identifier (e.g., "ActivateParams")
|
|
206
|
+
if (ts.isIdentifier(typeArg.exprName)) {
|
|
207
|
+
return typeArg.exprName.text;
|
|
208
|
+
}
|
|
209
|
+
// Could be qualified name like Namespace.ActivateParams
|
|
210
|
+
if (ts.isQualifiedName(typeArg.exprName)) {
|
|
211
|
+
return typeArg.exprName.right.text;
|
|
212
|
+
}
|
|
213
|
+
return null;
|
|
214
|
+
}
|
|
215
|
+
//# sourceMappingURL=class-analyzer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"class-analyzer.js","sourceRoot":"","sources":["../../src/analyzer/class-analyzer.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Decorator extractor for parsing decorator AST nodes.
|
|
3
|
+
*
|
|
4
|
+
* Extracts decorator names and arguments from class field decorators,
|
|
5
|
+
* supporting the FormSpec decorator DSL (@Field, @Minimum, @Maximum, etc.).
|
|
6
|
+
*
|
|
7
|
+
* Also supports branded type resolution via the TypeScript type checker
|
|
8
|
+
* to detect custom decorators created with `extendDecorator` and
|
|
9
|
+
* `customDecorator` from `@formspec/decorators`.
|
|
10
|
+
*/
|
|
11
|
+
import * as ts from "typescript";
|
|
12
|
+
import { type FormSpecDecoratorName } from "@formspec/core";
|
|
13
|
+
/**
|
|
14
|
+
* Extracted decorator information.
|
|
15
|
+
*/
|
|
16
|
+
export interface DecoratorInfo {
|
|
17
|
+
/** Decorator name (e.g., "Field", "Minimum") */
|
|
18
|
+
name: string;
|
|
19
|
+
/** Decorator arguments as literal values */
|
|
20
|
+
args: DecoratorArg[];
|
|
21
|
+
/** Raw AST node for the decorator (undefined for synthetic JSDoc constraint entries) */
|
|
22
|
+
node: ts.Decorator | undefined;
|
|
23
|
+
/** Resolved brand information from the type checker (populated by analyzeField) */
|
|
24
|
+
resolved?: ResolvedDecorator;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* A decorator argument value.
|
|
28
|
+
* Can be a primitive, array, or object literal.
|
|
29
|
+
*/
|
|
30
|
+
export type DecoratorArg = string | number | boolean | null | DecoratorArg[] | {
|
|
31
|
+
[key: string]: DecoratorArg;
|
|
32
|
+
};
|
|
33
|
+
/**
|
|
34
|
+
* Result of resolving a decorator via the type checker.
|
|
35
|
+
*/
|
|
36
|
+
export interface ResolvedDecorator {
|
|
37
|
+
/** Decorator name as it appears in source */
|
|
38
|
+
name: string;
|
|
39
|
+
/** If this extends a built-in, the built-in name (e.g., "Field") */
|
|
40
|
+
extendsBuiltin?: string;
|
|
41
|
+
/** If this belongs to a CLI extension namespace, the namespace name */
|
|
42
|
+
extensionName?: string;
|
|
43
|
+
/** Whether this is a known FormSpec decorator (built-in or factory-created) */
|
|
44
|
+
isFormSpec: boolean;
|
|
45
|
+
/** Whether this is a marker (zero-arg) decorator */
|
|
46
|
+
isMarker: boolean;
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Extracts decorators from a class member (property or method).
|
|
50
|
+
*
|
|
51
|
+
* @param member - The class member to extract decorators from
|
|
52
|
+
* @returns Array of extracted decorator info
|
|
53
|
+
*/
|
|
54
|
+
export declare function extractDecorators(member: ts.PropertyDeclaration | ts.MethodDeclaration): DecoratorInfo[];
|
|
55
|
+
/**
|
|
56
|
+
* Known FormSpec decorators and their expected argument types.
|
|
57
|
+
*
|
|
58
|
+
* This metadata object provides additional information about each decorator's
|
|
59
|
+
* expected argument types. The keys are constrained to match FormSpecDecoratorName.
|
|
60
|
+
*/
|
|
61
|
+
export declare const FORMSPEC_DECORATORS: Record<FormSpecDecoratorName, {
|
|
62
|
+
argTypes: readonly string[];
|
|
63
|
+
}>;
|
|
64
|
+
/**
|
|
65
|
+
* Resolves a decorator via the TypeScript type checker to determine
|
|
66
|
+
* if it is a FormSpec decorator (built-in, extended, or custom).
|
|
67
|
+
*
|
|
68
|
+
* This enables detection of:
|
|
69
|
+
* 1. Direct imports of built-in decorators from `@formspec/decorators`
|
|
70
|
+
* 2. Extended decorators created via `extendDecorator(...).as(...)`
|
|
71
|
+
* 3. Custom decorators created via `customDecorator(...).as(...)` or `.marker(...)`
|
|
72
|
+
*
|
|
73
|
+
* @param decorator - The decorator AST node
|
|
74
|
+
* @param checker - TypeScript type checker
|
|
75
|
+
* @returns Resolved decorator information, or null if not resolvable
|
|
76
|
+
*/
|
|
77
|
+
export declare function resolveDecorator(decorator: ts.Decorator, checker: ts.TypeChecker): ResolvedDecorator | null;
|
|
78
|
+
//# sourceMappingURL=decorator-extractor.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"decorator-extractor.d.ts","sourceRoot":"","sources":["../../src/analyzer/decorator-extractor.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,KAAK,EAAE,MAAM,YAAY,CAAC;AACjC,OAAO,EAAE,KAAK,qBAAqB,EAAE,MAAM,gBAAgB,CAAC;AAE5D;;GAEG;AACH,MAAM,WAAW,aAAa;IAC5B,gDAAgD;IAChD,IAAI,EAAE,MAAM,CAAC;IACb,4CAA4C;IAC5C,IAAI,EAAE,YAAY,EAAE,CAAC;IACrB,wFAAwF;IACxF,IAAI,EAAE,EAAE,CAAC,SAAS,GAAG,SAAS,CAAC;IAC/B,mFAAmF;IACnF,QAAQ,CAAC,EAAE,iBAAiB,CAAC;CAC9B;AAED;;;GAGG;AACH,MAAM,MAAM,YAAY,GACpB,MAAM,GACN,MAAM,GACN,OAAO,GACP,IAAI,GACJ,YAAY,EAAE,GACd;IAAE,CAAC,GAAG,EAAE,MAAM,GAAG,YAAY,CAAA;CAAE,CAAC;AAEpC;;GAEG;AACH,MAAM,WAAW,iBAAiB;IAChC,6CAA6C;IAC7C,IAAI,EAAE,MAAM,CAAC;IACb,oEAAoE;IACpE,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,uEAAuE;IACvE,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,+EAA+E;IAC/E,UAAU,EAAE,OAAO,CAAC;IACpB,oDAAoD;IACpD,QAAQ,EAAE,OAAO,CAAC;CACnB;AAED;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAC/B,MAAM,EAAE,EAAE,CAAC,mBAAmB,GAAG,EAAE,CAAC,iBAAiB,GACpD,aAAa,EAAE,CAgBjB;AA0KD;;;;;GAKG;AACH,eAAO,MAAM,mBAAmB,EAAE,MAAM,CAAC,qBAAqB,EAAE;IAAE,QAAQ,EAAE,SAAS,MAAM,EAAE,CAAA;CAAE,CAuBrF,CAAC;AAgBX;;;;;;;;;;;;GAYG;AACH,wBAAgB,gBAAgB,CAC9B,SAAS,EAAE,EAAE,CAAC,SAAS,EACvB,OAAO,EAAE,EAAE,CAAC,WAAW,GACtB,iBAAiB,GAAG,IAAI,CAyH1B"}
|
|
@@ -0,0 +1,336 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Decorator extractor for parsing decorator AST nodes.
|
|
3
|
+
*
|
|
4
|
+
* Extracts decorator names and arguments from class field decorators,
|
|
5
|
+
* supporting the FormSpec decorator DSL (@Field, @Minimum, @Maximum, etc.).
|
|
6
|
+
*
|
|
7
|
+
* Also supports branded type resolution via the TypeScript type checker
|
|
8
|
+
* to detect custom decorators created with `extendDecorator` and
|
|
9
|
+
* `customDecorator` from `@formspec/decorators`.
|
|
10
|
+
*/
|
|
11
|
+
import * as ts from "typescript";
|
|
12
|
+
import {} from "@formspec/core";
|
|
13
|
+
/**
|
|
14
|
+
* Extracts decorators from a class member (property or method).
|
|
15
|
+
*
|
|
16
|
+
* @param member - The class member to extract decorators from
|
|
17
|
+
* @returns Array of extracted decorator info
|
|
18
|
+
*/
|
|
19
|
+
export function extractDecorators(member) {
|
|
20
|
+
const decorators = [];
|
|
21
|
+
// TC39 decorators are in the modifiers array
|
|
22
|
+
const modifiers = ts.canHaveDecorators(member) ? ts.getDecorators(member) : undefined;
|
|
23
|
+
if (!modifiers)
|
|
24
|
+
return decorators;
|
|
25
|
+
for (const decorator of modifiers) {
|
|
26
|
+
const info = parseDecorator(decorator);
|
|
27
|
+
if (info) {
|
|
28
|
+
decorators.push(info);
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
return decorators;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Parses a single decorator node.
|
|
35
|
+
*/
|
|
36
|
+
function parseDecorator(decorator) {
|
|
37
|
+
const expr = decorator.expression;
|
|
38
|
+
// Simple decorator: @Decorator
|
|
39
|
+
if (ts.isIdentifier(expr)) {
|
|
40
|
+
return {
|
|
41
|
+
name: expr.text,
|
|
42
|
+
args: [],
|
|
43
|
+
node: decorator,
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
// Call expression: @Decorator(args)
|
|
47
|
+
if (ts.isCallExpression(expr)) {
|
|
48
|
+
const callee = expr.expression;
|
|
49
|
+
// Get decorator name
|
|
50
|
+
let name = null;
|
|
51
|
+
if (ts.isIdentifier(callee)) {
|
|
52
|
+
name = callee.text;
|
|
53
|
+
}
|
|
54
|
+
else if (ts.isPropertyAccessExpression(callee)) {
|
|
55
|
+
// For namespaced decorators like @formspec.Field()
|
|
56
|
+
name = callee.name.text;
|
|
57
|
+
}
|
|
58
|
+
if (!name)
|
|
59
|
+
return null;
|
|
60
|
+
// Extract arguments
|
|
61
|
+
const args = expr.arguments.map(extractArgValue);
|
|
62
|
+
return {
|
|
63
|
+
name,
|
|
64
|
+
args,
|
|
65
|
+
node: decorator,
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
return null;
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Extracts the value from an expression node.
|
|
72
|
+
* Supports literals, arrays, object literals, and RegExp.
|
|
73
|
+
*/
|
|
74
|
+
function extractArgValue(node) {
|
|
75
|
+
// String literal
|
|
76
|
+
if (ts.isStringLiteral(node)) {
|
|
77
|
+
return node.text;
|
|
78
|
+
}
|
|
79
|
+
// Numeric literal
|
|
80
|
+
if (ts.isNumericLiteral(node)) {
|
|
81
|
+
return Number(node.text);
|
|
82
|
+
}
|
|
83
|
+
// Boolean literals (true/false are identifiers in TS AST)
|
|
84
|
+
if (node.kind === ts.SyntaxKind.TrueKeyword) {
|
|
85
|
+
return true;
|
|
86
|
+
}
|
|
87
|
+
if (node.kind === ts.SyntaxKind.FalseKeyword) {
|
|
88
|
+
return false;
|
|
89
|
+
}
|
|
90
|
+
// Null literal
|
|
91
|
+
if (node.kind === ts.SyntaxKind.NullKeyword) {
|
|
92
|
+
return null;
|
|
93
|
+
}
|
|
94
|
+
// Prefix unary expression (for negative numbers)
|
|
95
|
+
if (ts.isPrefixUnaryExpression(node)) {
|
|
96
|
+
if (node.operator === ts.SyntaxKind.MinusToken && ts.isNumericLiteral(node.operand)) {
|
|
97
|
+
return -Number(node.operand.text);
|
|
98
|
+
}
|
|
99
|
+
if (node.operator === ts.SyntaxKind.PlusToken && ts.isNumericLiteral(node.operand)) {
|
|
100
|
+
return Number(node.operand.text);
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
// Array literal
|
|
104
|
+
if (ts.isArrayLiteralExpression(node)) {
|
|
105
|
+
return node.elements.map((el) => {
|
|
106
|
+
if (ts.isSpreadElement(el)) {
|
|
107
|
+
// Can't evaluate spread at compile time
|
|
108
|
+
return null;
|
|
109
|
+
}
|
|
110
|
+
return extractArgValue(el);
|
|
111
|
+
});
|
|
112
|
+
}
|
|
113
|
+
// Object literal
|
|
114
|
+
if (ts.isObjectLiteralExpression(node)) {
|
|
115
|
+
const obj = {};
|
|
116
|
+
for (const prop of node.properties) {
|
|
117
|
+
if (ts.isPropertyAssignment(prop)) {
|
|
118
|
+
const key = getPropertyName(prop.name);
|
|
119
|
+
if (key) {
|
|
120
|
+
obj[key] = extractArgValue(prop.initializer);
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
else if (ts.isShorthandPropertyAssignment(prop)) {
|
|
124
|
+
// { foo } shorthand - we can't resolve the value
|
|
125
|
+
const key = prop.name.text;
|
|
126
|
+
obj[key] = null;
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
return obj;
|
|
130
|
+
}
|
|
131
|
+
// Template literal (simple case)
|
|
132
|
+
if (ts.isNoSubstitutionTemplateLiteral(node)) {
|
|
133
|
+
return node.text;
|
|
134
|
+
}
|
|
135
|
+
// RegExp literal: extract the source pattern string
|
|
136
|
+
if (ts.isRegularExpressionLiteral(node)) {
|
|
137
|
+
const regexText = node.text;
|
|
138
|
+
// RegExp literal format is /pattern/flags
|
|
139
|
+
const lastSlash = regexText.lastIndexOf("/");
|
|
140
|
+
if (lastSlash > 0) {
|
|
141
|
+
return regexText.substring(1, lastSlash);
|
|
142
|
+
}
|
|
143
|
+
return regexText;
|
|
144
|
+
}
|
|
145
|
+
// new RegExp("pattern") — extract pattern from constructor call
|
|
146
|
+
if (ts.isNewExpression(node)) {
|
|
147
|
+
if (ts.isIdentifier(node.expression) &&
|
|
148
|
+
node.expression.text === "RegExp" &&
|
|
149
|
+
node.arguments &&
|
|
150
|
+
node.arguments.length > 0) {
|
|
151
|
+
const firstArg = node.arguments[0];
|
|
152
|
+
if (firstArg && ts.isStringLiteral(firstArg)) {
|
|
153
|
+
return firstArg.text;
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
// Identifier - could be an enum member or constant
|
|
158
|
+
// We can't resolve it statically, return null
|
|
159
|
+
if (ts.isIdentifier(node)) {
|
|
160
|
+
return null;
|
|
161
|
+
}
|
|
162
|
+
// For other expressions, return null
|
|
163
|
+
return null;
|
|
164
|
+
}
|
|
165
|
+
/**
|
|
166
|
+
* Gets the property name from a property name node.
|
|
167
|
+
*/
|
|
168
|
+
function getPropertyName(name) {
|
|
169
|
+
if (ts.isIdentifier(name)) {
|
|
170
|
+
return name.text;
|
|
171
|
+
}
|
|
172
|
+
if (ts.isStringLiteral(name)) {
|
|
173
|
+
return name.text;
|
|
174
|
+
}
|
|
175
|
+
if (ts.isNumericLiteral(name)) {
|
|
176
|
+
return name.text;
|
|
177
|
+
}
|
|
178
|
+
// Computed property names can't be resolved statically
|
|
179
|
+
return null;
|
|
180
|
+
}
|
|
181
|
+
/**
|
|
182
|
+
* Known FormSpec decorators and their expected argument types.
|
|
183
|
+
*
|
|
184
|
+
* This metadata object provides additional information about each decorator's
|
|
185
|
+
* expected argument types. The keys are constrained to match FormSpecDecoratorName.
|
|
186
|
+
*/
|
|
187
|
+
export const FORMSPEC_DECORATORS = {
|
|
188
|
+
// Display metadata
|
|
189
|
+
Field: { argTypes: ["object"] },
|
|
190
|
+
// Grouping
|
|
191
|
+
Group: { argTypes: ["string"] },
|
|
192
|
+
// Conditional display
|
|
193
|
+
ShowWhen: { argTypes: ["object"] },
|
|
194
|
+
// Enum options
|
|
195
|
+
EnumOptions: { argTypes: ["array"] },
|
|
196
|
+
// Numeric constraints
|
|
197
|
+
Minimum: { argTypes: ["number"] },
|
|
198
|
+
Maximum: { argTypes: ["number"] },
|
|
199
|
+
ExclusiveMinimum: { argTypes: ["number"] },
|
|
200
|
+
ExclusiveMaximum: { argTypes: ["number"] },
|
|
201
|
+
// String constraints
|
|
202
|
+
MinLength: { argTypes: ["number"] },
|
|
203
|
+
MaxLength: { argTypes: ["number"] },
|
|
204
|
+
Pattern: { argTypes: ["string"] },
|
|
205
|
+
};
|
|
206
|
+
/**
|
|
207
|
+
* Checks if a file path belongs to the @formspec/decorators package.
|
|
208
|
+
*
|
|
209
|
+
* Matches both installed node_modules paths and local monorepo paths.
|
|
210
|
+
*/
|
|
211
|
+
function isFormSpecDecoratorsPath(fileName) {
|
|
212
|
+
// Normalize separators for cross-platform matching
|
|
213
|
+
const normalized = fileName.replace(/\\/g, "/");
|
|
214
|
+
return (normalized.includes("node_modules/@formspec/decorators") ||
|
|
215
|
+
normalized.includes("/packages/decorators/"));
|
|
216
|
+
}
|
|
217
|
+
/**
|
|
218
|
+
* Resolves a decorator via the TypeScript type checker to determine
|
|
219
|
+
* if it is a FormSpec decorator (built-in, extended, or custom).
|
|
220
|
+
*
|
|
221
|
+
* This enables detection of:
|
|
222
|
+
* 1. Direct imports of built-in decorators from `@formspec/decorators`
|
|
223
|
+
* 2. Extended decorators created via `extendDecorator(...).as(...)`
|
|
224
|
+
* 3. Custom decorators created via `customDecorator(...).as(...)` or `.marker(...)`
|
|
225
|
+
*
|
|
226
|
+
* @param decorator - The decorator AST node
|
|
227
|
+
* @param checker - TypeScript type checker
|
|
228
|
+
* @returns Resolved decorator information, or null if not resolvable
|
|
229
|
+
*/
|
|
230
|
+
export function resolveDecorator(decorator, checker) {
|
|
231
|
+
const expr = decorator.expression;
|
|
232
|
+
// Get the identifier to resolve
|
|
233
|
+
let targetNode;
|
|
234
|
+
let name;
|
|
235
|
+
if (ts.isIdentifier(expr)) {
|
|
236
|
+
// Simple marker decorator: @Decorator
|
|
237
|
+
targetNode = expr;
|
|
238
|
+
name = expr.text;
|
|
239
|
+
}
|
|
240
|
+
else if (ts.isCallExpression(expr)) {
|
|
241
|
+
// Parameterized decorator: @Decorator(args)
|
|
242
|
+
if (ts.isIdentifier(expr.expression)) {
|
|
243
|
+
targetNode = expr.expression;
|
|
244
|
+
name = expr.expression.text;
|
|
245
|
+
}
|
|
246
|
+
else {
|
|
247
|
+
return null;
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
else {
|
|
251
|
+
return null;
|
|
252
|
+
}
|
|
253
|
+
// Check if it's a known built-in by name
|
|
254
|
+
if (name in FORMSPEC_DECORATORS) {
|
|
255
|
+
// Verify it actually comes from @formspec/decorators by checking the symbol
|
|
256
|
+
const symbol = checker.getSymbolAtLocation(targetNode);
|
|
257
|
+
if (symbol) {
|
|
258
|
+
const declarations = symbol.declarations;
|
|
259
|
+
if (declarations && declarations.length > 0) {
|
|
260
|
+
const decl = declarations[0];
|
|
261
|
+
if (decl) {
|
|
262
|
+
const sourceFile = decl.getSourceFile();
|
|
263
|
+
const fileName = sourceFile.fileName;
|
|
264
|
+
if (isFormSpecDecoratorsPath(fileName)) {
|
|
265
|
+
return {
|
|
266
|
+
name,
|
|
267
|
+
isFormSpec: true,
|
|
268
|
+
isMarker: !ts.isCallExpression(expr),
|
|
269
|
+
};
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
// Try to resolve branded types for custom/extended decorators
|
|
276
|
+
const resolvedSymbol = checker.getSymbolAtLocation(targetNode);
|
|
277
|
+
if (!resolvedSymbol)
|
|
278
|
+
return null;
|
|
279
|
+
const type = checker.getTypeOfSymbol(resolvedSymbol);
|
|
280
|
+
const props = type.getProperties();
|
|
281
|
+
let extendsBuiltin;
|
|
282
|
+
let extensionName;
|
|
283
|
+
let isMarker = false;
|
|
284
|
+
for (const prop of props) {
|
|
285
|
+
// __String is a branded string type; cast is safe for read-only string operations
|
|
286
|
+
const escapedName = prop.getEscapedName();
|
|
287
|
+
// TypeScript represents unique symbol properties as __@<name>@<uniqueId>
|
|
288
|
+
// in escaped names. The <name> portion may be either the Symbol description
|
|
289
|
+
// (e.g., "formspec.extends") or the const variable name (e.g., "FORMSPEC_EXTENDS"),
|
|
290
|
+
// depending on how the symbol is declared and resolved by the type checker.
|
|
291
|
+
// We check for both patterns to handle all cases.
|
|
292
|
+
if (escapedName.startsWith("__@") &&
|
|
293
|
+
(escapedName.includes("formspec.extends") || escapedName.includes("FORMSPEC_EXTENDS"))) {
|
|
294
|
+
const propType = checker.getTypeOfSymbol(prop);
|
|
295
|
+
if (propType.isStringLiteral()) {
|
|
296
|
+
extendsBuiltin = propType.value;
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
if (escapedName.startsWith("__@") &&
|
|
300
|
+
(escapedName.includes("formspec.extension") || escapedName.includes("FORMSPEC_EXTENSION"))) {
|
|
301
|
+
const propType = checker.getTypeOfSymbol(prop);
|
|
302
|
+
if (propType.isStringLiteral()) {
|
|
303
|
+
extensionName = propType.value;
|
|
304
|
+
}
|
|
305
|
+
}
|
|
306
|
+
if (escapedName.startsWith("__@") &&
|
|
307
|
+
(escapedName.includes("formspec.marker") || escapedName.includes("FORMSPEC_MARKER"))) {
|
|
308
|
+
isMarker = true;
|
|
309
|
+
}
|
|
310
|
+
}
|
|
311
|
+
if (extendsBuiltin) {
|
|
312
|
+
return {
|
|
313
|
+
name,
|
|
314
|
+
extendsBuiltin,
|
|
315
|
+
isFormSpec: true,
|
|
316
|
+
isMarker: false,
|
|
317
|
+
};
|
|
318
|
+
}
|
|
319
|
+
if (extensionName) {
|
|
320
|
+
return {
|
|
321
|
+
name,
|
|
322
|
+
extensionName,
|
|
323
|
+
isFormSpec: true,
|
|
324
|
+
isMarker,
|
|
325
|
+
};
|
|
326
|
+
}
|
|
327
|
+
if (isMarker) {
|
|
328
|
+
return {
|
|
329
|
+
name,
|
|
330
|
+
isFormSpec: true,
|
|
331
|
+
isMarker: true,
|
|
332
|
+
};
|
|
333
|
+
}
|
|
334
|
+
return null;
|
|
335
|
+
}
|
|
336
|
+
//# sourceMappingURL=decorator-extractor.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"decorator-extractor.js","sourceRoot":"","sources":["../../src/analyzer/decorator-extractor.ts"],"names":[],"mappings":"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"}
|