Skip to content

Commit 4f9253f

Browse files
committed
feat: legacy view support
1 parent 36206fc commit 4f9253f

File tree

11 files changed

+2175
-511
lines changed

11 files changed

+2175
-511
lines changed

type-gen/demos/solid/types/@nativescript-community_ui-collectionview_solid_jsx.d.ts

Lines changed: 1530 additions & 81 deletions
Large diffs are not rendered by default.
Lines changed: 200 additions & 143 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,21 @@
11
import { toSimpleType } from "ts-simple-type";
2-
import { BinaryExpression, ExpressionStatement, Node, ReturnStatement } from "typescript";
3-
import { AnalyzerDeclarationVisitContext, ComponentMember, getJsDoc, } from "web-component-analyzer";
4-
import { getMemberVisibilityFromNode, getModifiersFromNode, hasModifier, isNamePrivate } from "./ast-util";
2+
import {
3+
BinaryExpression,
4+
ExpressionStatement,
5+
Node,
6+
ReturnStatement,
7+
} from "typescript";
8+
import {
9+
AnalyzerDeclarationVisitContext,
10+
ComponentMember,
11+
getJsDoc,
12+
} from "web-component-analyzer";
13+
import {
14+
getMemberVisibilityFromNode,
15+
getModifiersFromNode,
16+
hasModifier,
17+
isNamePrivate,
18+
} from "./ast-util";
519
import { lazy } from "./lazy";
620
import { resolveNodeValue } from "./resolve-node-value";
721
import { relaxType } from "./type-util";
@@ -11,143 +25,186 @@ import { relaxType } from "./type-util";
1125
* @param node
1226
* @param context
1327
*/
14-
export function discoverMembers(node: Node, context: AnalyzerDeclarationVisitContext): ComponentMember[] | undefined {
15-
const { ts, checker } = context;
16-
17-
// Never pick up members not declared directly on the declaration node being traversed
18-
if (node.parent !== context.declarationNode) {
19-
return undefined;
20-
}
21-
22-
const jsDoc = getJsDoc(node, ts);
23-
const found = jsDoc?.tags?.find((tag) => tag.tag === "nsProperty");
24-
if (!found) return undefined;
25-
26-
// static get observedAttributes() { return ['c', 'l']; }
27-
if (ts.isGetAccessor(node) && hasModifier(node, ts.SyntaxKind.StaticKeyword, ts)) {
28-
if (node.name.getText() === "observedAttributes" && node.body != null) {
29-
const members: ComponentMember[] = [];
30-
31-
// Find either the first "return" statement or the first "array literal expression"
32-
const arrayLiteralExpression =
33-
(node.body.statements.find(statement => ts.isReturnStatement(statement)) as ReturnStatement | undefined)?.expression ??
34-
node.body.statements.find(statement => ts.isArrayLiteralExpression(statement));
35-
36-
if (arrayLiteralExpression != null && ts.isArrayLiteralExpression(arrayLiteralExpression)) {
37-
// Emit an attribute for each string literal in the array.
38-
for (const attrNameNode of arrayLiteralExpression.elements) {
39-
const attrName = ts.isStringLiteralLike(attrNameNode) ? attrNameNode.text : undefined;
40-
if (attrName == null) continue;
41-
42-
members.push({
43-
priority: "medium",
44-
node: attrNameNode,
45-
jsDoc: getJsDoc(attrNameNode, ts),
46-
kind: "attribute",
47-
attrName,
48-
type: undefined // () => ({ kind: "ANY" } as SimpleType),
49-
});
50-
}
51-
}
52-
53-
return members;
54-
}
55-
}
56-
57-
// class { myProp = "hello"; }
58-
else if (ts.isPropertyDeclaration(node) || ts.isPropertySignature(node)) {
59-
const { name, initializer } = (() => {
60-
if (ts.isPropertySignature(node)) {
61-
return { name: node.name, initializer: undefined };
62-
}
63-
return node;
64-
})();
65-
66-
if (ts.isIdentifier(name) || ts.isStringLiteralLike(name)) {
67-
// Always ignore the "prototype" property
68-
if (name.text === "prototype") {
69-
return undefined;
70-
}
71-
72-
// Find default value based on initializer
73-
const resolvedDefaultValue = initializer != null ? resolveNodeValue(initializer, context) : undefined;
74-
const def = resolvedDefaultValue != null ? resolvedDefaultValue.value : initializer?.getText();
75-
76-
return [
77-
{
78-
priority: "high",
79-
node,
80-
kind: "property",
81-
jsDoc: getJsDoc(node, ts),
82-
propName: name.text,
83-
type: lazy(() => checker.getTypeAtLocation(node)),
84-
default: def,
85-
visibility: getMemberVisibilityFromNode(node, ts),
86-
modifiers: getModifiersFromNode(node, ts)
87-
//required: isPropertyRequired(node, context.checker),
88-
}
89-
];
90-
}
91-
}
92-
93-
// class { set myProp(value: string) { ... } }
94-
else if (ts.isSetAccessor(node) || ts.isGetAccessor(node)) {
95-
const { name, parameters } = node;
96-
97-
if (ts.isIdentifier(name)) {
98-
const parameter = ts.isSetAccessor(node) != null && parameters?.length > 0 ? parameters[0] : undefined;
99-
100-
return [
101-
{
102-
priority: "high",
103-
node,
104-
jsDoc: getJsDoc(node, ts),
105-
kind: "property",
106-
propName: name.text,
107-
type: lazy(() => (parameter == null ? context.checker.getTypeAtLocation(node) : context.checker.getTypeAtLocation(parameter))),
108-
visibility: getMemberVisibilityFromNode(node, ts),
109-
modifiers: getModifiersFromNode(node, ts)
110-
}
111-
];
112-
}
113-
}
114-
115-
// constructor { super(); this.title = "Hello"; }
116-
else if (ts.isConstructorDeclaration(node)) {
117-
if (node.body != null) {
118-
const assignments = node.body.statements
119-
.filter((stmt): stmt is ExpressionStatement => ts.isExpressionStatement(stmt))
120-
.map(stmt => stmt.expression)
121-
.filter((exp): exp is BinaryExpression => ts.isBinaryExpression(exp));
122-
123-
const members: ComponentMember[] = [];
124-
for (const assignment of assignments) {
125-
const { left, right } = assignment;
126-
127-
if (ts.isPropertyAccessExpression(left)) {
128-
if (left.expression.kind === ts.SyntaxKind.ThisKeyword) {
129-
const propName = left.name.getText();
130-
131-
const resolvedInitializer = resolveNodeValue(right, context);
132-
const def = resolvedInitializer != null ? resolvedInitializer.value : undefined; //right.getText();
133-
134-
members.push({
135-
priority: "low",
136-
node,
137-
kind: "property",
138-
propName,
139-
default: def,
140-
type: () => relaxType(toSimpleType(checker.getTypeAtLocation(right), checker)),
141-
jsDoc: getJsDoc(assignment.parent, ts),
142-
visibility: isNamePrivate(propName) ? "private" : undefined
143-
});
144-
}
145-
}
146-
}
147-
148-
return members;
149-
}
150-
}
151-
152-
return undefined;
153-
}
28+
export function discoverMembers(
29+
node: Node,
30+
context: AnalyzerDeclarationVisitContext
31+
): ComponentMember[] | undefined {
32+
const { ts, checker } = context;
33+
34+
// Never pick up members not declared directly on the declaration node being traversed
35+
if (node.parent !== context.declarationNode) {
36+
return undefined;
37+
}
38+
39+
const jsDoc = getJsDoc(node, ts);
40+
const found = jsDoc?.tags?.find((tag) => tag.tag === "nsProperty");
41+
42+
if (
43+
!found &&
44+
(!globalThis.LEGACY_MODE || node.parent.getText().includes("@nsView"))
45+
)
46+
return undefined;
47+
48+
// static get observedAttributes() { return ['c', 'l']; }
49+
if (
50+
ts.isGetAccessor(node) &&
51+
hasModifier(node, ts.SyntaxKind.StaticKeyword, ts)
52+
) {
53+
if (node.name.getText() === "observedAttributes" && node.body != null) {
54+
const members: ComponentMember[] = [];
55+
56+
// Find either the first "return" statement or the first "array literal expression"
57+
const arrayLiteralExpression =
58+
(
59+
node.body.statements.find((statement) =>
60+
ts.isReturnStatement(statement)
61+
) as ReturnStatement | undefined
62+
)?.expression ??
63+
node.body.statements.find((statement) =>
64+
ts.isArrayLiteralExpression(statement)
65+
);
66+
67+
if (
68+
arrayLiteralExpression != null &&
69+
ts.isArrayLiteralExpression(arrayLiteralExpression)
70+
) {
71+
// Emit an attribute for each string literal in the array.
72+
for (const attrNameNode of arrayLiteralExpression.elements) {
73+
const attrName = ts.isStringLiteralLike(attrNameNode)
74+
? attrNameNode.text
75+
: undefined;
76+
if (attrName == null) continue;
77+
78+
members.push({
79+
priority: "medium",
80+
node: attrNameNode,
81+
jsDoc: getJsDoc(attrNameNode, ts),
82+
kind: "attribute",
83+
attrName,
84+
type: undefined, // () => ({ kind: "ANY" } as SimpleType),
85+
});
86+
}
87+
}
88+
89+
return members;
90+
}
91+
}
92+
93+
// class { myProp = "hello"; }
94+
else if (ts.isPropertyDeclaration(node) || ts.isPropertySignature(node)) {
95+
const { name, initializer } = (() => {
96+
if (ts.isPropertySignature(node)) {
97+
return { name: node.name, initializer: undefined };
98+
}
99+
return node;
100+
})();
101+
102+
if (ts.isIdentifier(name) || ts.isStringLiteralLike(name)) {
103+
// Always ignore the "prototype" property
104+
if (name.text === "prototype") {
105+
return undefined;
106+
}
107+
108+
// Find default value based on initializer
109+
const resolvedDefaultValue =
110+
initializer != null
111+
? resolveNodeValue(initializer, context)
112+
: undefined;
113+
const def =
114+
resolvedDefaultValue != null
115+
? resolvedDefaultValue.value
116+
: initializer?.getText();
117+
118+
return [
119+
{
120+
priority: "high",
121+
node,
122+
kind: "property",
123+
jsDoc: getJsDoc(node, ts),
124+
propName: name.text,
125+
type: lazy(() => checker.getTypeAtLocation(node)),
126+
default: def,
127+
visibility: getMemberVisibilityFromNode(node, ts),
128+
modifiers: getModifiersFromNode(node, ts),
129+
//required: isPropertyRequired(node, context.checker),
130+
},
131+
];
132+
}
133+
}
134+
135+
// class { set myProp(value: string) { ... } }
136+
else if (ts.isSetAccessor(node) || ts.isGetAccessor(node)) {
137+
const { name, parameters } = node;
138+
139+
if (ts.isIdentifier(name)) {
140+
const parameter =
141+
ts.isSetAccessor(node) != null && parameters?.length > 0
142+
? parameters[0]
143+
: undefined;
144+
145+
return [
146+
{
147+
priority: "high",
148+
node,
149+
jsDoc: getJsDoc(node, ts),
150+
kind: "property",
151+
propName: name.text,
152+
type: lazy(() =>
153+
parameter == null
154+
? context.checker.getTypeAtLocation(node)
155+
: context.checker.getTypeAtLocation(parameter)
156+
),
157+
visibility: getMemberVisibilityFromNode(node, ts),
158+
modifiers: getModifiersFromNode(node, ts),
159+
},
160+
];
161+
}
162+
}
163+
164+
// constructor { super(); this.title = "Hello"; }
165+
else if (ts.isConstructorDeclaration(node)) {
166+
if (node.body != null) {
167+
const assignments = node.body.statements
168+
.filter((stmt): stmt is ExpressionStatement =>
169+
ts.isExpressionStatement(stmt)
170+
)
171+
.map((stmt) => stmt.expression)
172+
.filter((exp): exp is BinaryExpression => ts.isBinaryExpression(exp));
173+
174+
const members: ComponentMember[] = [];
175+
for (const assignment of assignments) {
176+
const { left, right } = assignment;
177+
178+
if (ts.isPropertyAccessExpression(left)) {
179+
if (left.expression.kind === ts.SyntaxKind.ThisKeyword) {
180+
const propName = left.name.getText();
181+
182+
const resolvedInitializer = resolveNodeValue(right, context);
183+
const def =
184+
resolvedInitializer != null
185+
? resolvedInitializer.value
186+
: undefined; //right.getText();
187+
188+
members.push({
189+
priority: "low",
190+
node,
191+
kind: "property",
192+
propName,
193+
default: def,
194+
type: () =>
195+
relaxType(
196+
toSimpleType(checker.getTypeAtLocation(right), checker)
197+
),
198+
jsDoc: getJsDoc(assignment.parent, ts),
199+
visibility: isNamePrivate(propName) ? "private" : undefined,
200+
});
201+
}
202+
}
203+
}
204+
205+
return members;
206+
}
207+
}
208+
209+
return undefined;
210+
}

0 commit comments

Comments
 (0)