@@ -325,10 +325,30 @@ function vm.isSubType(uri, child, parent, mark, errs)
325325 return true
326326 else
327327 local weakNil = config .get (uri , ' Lua.type.weakNilCheck' )
328+ local skipTable
328329 for n in child :eachObject () do
330+ if skipTable == nil and n .type == " table" and parent .type == " vm.node" then -- skip table type check if child has class
331+ --- @cast parent vm.node
332+ for _ , c in ipairs (child ) do
333+ if c .type == ' global' and c .cate == ' type' then
334+ for _ , set in ipairs (c :getSets (uri )) do
335+ if set .type == ' doc.class' then
336+ skipTable = true
337+ break
338+ end
339+ end
340+ end
341+ if skipTable then
342+ break
343+ end
344+ end
345+ if not skipTable then
346+ skipTable = false
347+ end
348+ end
329349 local nodeName = vm .getNodeName (n )
330350 if nodeName
331- and not (nodeName == ' nil' and weakNil )
351+ and not (nodeName == ' nil' and weakNil ) and not ( skipTable and n . type == ' table ' )
332352 and vm .isSubType (uri , n , parent , mark , errs ) == false then
333353 if errs then
334354 errs [# errs + 1 ] = ' TYPE_ERROR_UNION_DISMATCH'
@@ -463,44 +483,65 @@ function vm.isSubType(uri, child, parent, mark, errs)
463483 return true
464484 end
465485 if childName == ' table' and not guide .isBasicType (parentName ) then
466- local requiresKeys = {}
467- local t = parent
468- local set = {}
469- vm .getClassFields (uri , parent , vm .ANY , function (field , isMark )
470- if not set [field ] then
471- set [field ] = true
472- set [# set + 1 ] = field
486+ local set = parent :getSets (uri )
487+ local missedKeys = {}
488+ local failedCheck
489+ local myKeys
490+ for _ , def in ipairs (set ) do
491+ if not def .fields or # def .fields == 0 then
492+ goto continue
493+ end
494+ if not myKeys then
495+ myKeys = {}
496+ for _ , field in ipairs (child ) do
497+ local key = vm .getKeyName (field ) or field .tindex
498+ if key then
499+ myKeys [key ] = vm .compileNode (field )
500+ end
501+ end
473502 end
474- end )
475503
476- for i , field in ipairs (set ) do
477- local key = vm .getKeyName (field )
478- local node = vm .compileNode (field )
479- if key and not requiresKeys [key ] then
480- requiresKeys [key ] = node
504+ for _ , field in ipairs (def .fields ) do
505+ local key = vm .getKeyName (field )
506+ if not key then
507+ local fieldnode = vm .compileNode (field .field )[1 ]
508+ if fieldnode and fieldnode .type == ' doc.type.integer' then
509+ --- @cast fieldnode parser.object
510+ key = vm .getKeyName (fieldnode )
511+ end
512+ end
513+ if not key then
514+ goto continue
515+ end
516+
517+ local ok
518+ local nodeField = vm .compileNode (field )
519+ if myKeys [key ] then
520+ ok = vm .isSubType (uri , myKeys [key ], nodeField , mark , errs )
521+ if ok == false then
522+ errs [# errs + 1 ] = ' TYPE_ERROR_PARENT_ALL_DISMATCH' -- error display can be greatly improved
523+ errs [# errs + 1 ] = myKeys [key ]
524+ errs [# errs + 1 ] = nodeField
525+ failedCheck = true
526+ end
527+ elseif not nodeField :isNullable () then
528+ if type (key ) == " number" then
529+ missedKeys [# missedKeys + 1 ] = (' `[%s]`' ):format (key )
530+ else
531+ missedKeys [# missedKeys + 1 ] = (' `%s`' ):format (key )
532+ end
533+ failedCheck = true
534+ end
481535 end
536+ :: continue::
482537 end
483- if not next (requiresKeys ) then
484- return true
485- end
486- local refkey = {}
487- for _ , field in ipairs (child ) do
488- local name = vm .getKeyName (field )
489- local node = vm .compileNode (field )
490- if name then
491- refkey [name ] = node
492- end
538+ if # missedKeys > 0 then
539+ errs [# errs + 1 ] = ' DIAG_MISSING_FIELDS'
540+ errs [# errs + 1 ] = parent
541+ errs [# errs + 1 ] = table.concat (missedKeys , ' , ' )
493542 end
494- local ok
495- for key , node in pairs (requiresKeys ) do
496- if refkey [key ] then
497- ok = vm .isSubType (uri , refkey [key ], requiresKeys [key ], mark , errs )
498- elseif not node :isNullable () then
499- return false
500- end
501- if not ok then
502- return false
503- end
543+ if failedCheck then
544+ return false
504545 end
505546
506547 return true
@@ -754,6 +795,7 @@ local ErrorMessageMap = {
754795 TYPE_ERROR_NUMBER_LITERAL_TO_INTEGER = {' child' },
755796 TYPE_ERROR_NUMBER_TYPE_TO_INTEGER = {},
756797 TYPE_ERROR_DISMATCH = {' child' , ' parent' },
798+ DIAG_MISSING_FIELDS = {" 1" , " 2" },
757799}
758800
759801--- @param uri uri
0 commit comments