Skip to content

Commit 150b76d

Browse files
committed
Jsx: display compilation warning on missing props
1 parent c539162 commit 150b76d

File tree

1 file changed

+37
-0
lines changed

1 file changed

+37
-0
lines changed

src/lib/react/ReactMacro.hx

+37
Original file line numberDiff line numberDiff line change
@@ -185,6 +185,31 @@ class ReactMacro
185185
}
186186
}
187187

188+
static function extractNeededAttrs(type:Expr)
189+
{
190+
var neededAttrs = [];
191+
192+
try {
193+
var tprops = Context.storeTypedExpr(Context.typeExpr(macro @:pos(type.pos) {
194+
function get<T>(c:Class<T>):T return null;
195+
@:privateAccess get($type).props;
196+
}));
197+
198+
switch (Context.typeof(tprops))
199+
{
200+
case TType(_.get() => _.type => TAnonymous(_.get().fields => fields), _):
201+
for (f in fields)
202+
if (!f.meta.has(':optional'))
203+
neededAttrs.push(f.name);
204+
205+
default:
206+
}
207+
208+
} catch (e:Dynamic) {}
209+
210+
return neededAttrs;
211+
}
212+
188213
static function child(c:Child)
189214
{
190215
return switch (c.value) {
@@ -208,6 +233,7 @@ class ReactMacro
208233
var key = null;
209234
var ref = null;
210235
var pos = n.name.pos;
236+
var neededAttrs = extractNeededAttrs(type);
211237

212238
function add(name:StringAt, e:Expr)
213239
{
@@ -223,14 +249,18 @@ class ReactMacro
223249
{
224250
case Splat(e):
225251
spread.push(e);
252+
// Spread is not handled, so we assume every needed prop is passed
253+
neededAttrs = [];
226254

227255
case Empty(invalid = { value: 'key' | 'ref'}):
228256
invalid.pos.error('attribute ${invalid.value} must have a value');
229257

230258
case Empty(name):
259+
neededAttrs.remove(name.value);
231260
add(name, macro @:pos(name.pos) true);
232261

233262
case Regular(name, value):
263+
neededAttrs.remove(name.value);
234264
var expr = value.getString()
235265
.map(function (s) return macro $v{replaceEntities(s, value.pos)})
236266
.orUse(value);
@@ -246,6 +276,13 @@ class ReactMacro
246276

247277
// parse children
248278
var children = children(n.children);
279+
if (children.compound != null) neededAttrs.remove('children');
280+
281+
for (attr in neededAttrs)
282+
Context.warning(
283+
'Missing prop `$attr` for component `${n.name.value}`',
284+
c.pos
285+
);
249286

250287
// inline declaration or createElement?
251288
var typeInfo = getComponentInfo(type);

0 commit comments

Comments
 (0)