±à¼ÍƼö: |
±¾ÎÄÀ´×ÔÓÚcsdn,±¾ÎĽéÉÜÁËÔÚÃÀÍŵãÆÀÒµÎñ¿ìËÙ·¢Õ¹±³¾°Ï£¬Õë¶Ô´óÐÍÒÆ¶¯ÏîÄ¿µÄ¾²Ì¬·ÖÎöÐèÇ󣬽áºÏ¿ªÔ´ÏîÄ¿Àû±×£¬×îÖÕÉè¼ÆÊµÏֵľ²Ì¬·ÖÎö¿ò¼Ü
Hades¡£ |
|
±³¾°
×÷ΪȫÇò×î´óµÄ»¥ÁªÍø + Éú»î·þÎñƽ̨£¬ÃÀÍŵãÆÀ½üÄêÀ´ÔÚÒµÎñÉÏÈ¡µÃÁË·ÉËٵķ¢Õ¹¡£ÎªÖ§³ÖÒµÎñµÄ¿ìËÙ·¢Õ¹£¬Òƶ¯Ñз¢ÍŶӹæÄ£Ò²Öð½¥´ÓÁãÐǵÄС×÷·»Ê½ÔËÓª£¬ÑݱäΪǧÈ˼¶Ñз¢¾üÍÅÐͬ×÷Õ½¡£
ÔÚ¹«Ë¾Å·¢Õ¹µÄ´ó±³¾°Ï£¬Òƶ¯ÏîÄ¿¼Ü¹¹Ò²ÓÐÁËȫеÄÑݽø·½Ïò£ºÐèÒªÖ§³Ö¸ßЧµÄ¼¯³É²ßÂÔ£¬Ö§³ÖÑз¢Á÷³Ì×Ô¶¯»¯µÈµÈ£¬×îÖÕÌáÉýÑз¢Ð§ÄÜ£¬¼ÓËÙ²úÆ·µü´úºÍ½»¸¶ÄÜÁ¦¡£
ËäÈ»¸ßЧµÄÑз¢½»¸¶Ìåϵ°ïÖú App ÏîÄ¿Ëõ¶ÌÁ˵ü´úÖÜÆÚ£¬µ«¾®ÅçʽµÄÄ£¿é·¢°æºÍƵ·±µÄÏîÄ¿¼¯³É£¬Ê¹µÃ´¿È˹¤µÄÏîĿά»¤ºÍÖÊÁ¿±£Ö¤±äµÃ¡°¶ÀľÄÑÖ§¡±¡£

ÉÏͼÂþ»ÖУ¬ÁоÙÁË´óÐÍÏîÄ¿ÔÚ³ÖÐøÓÅ»¯ºÍά»¤¹ý³ÌÖнÏΪ³£¼ûµÄ¼¸ÀàÐèÇó¡£ÕâЩÐèÇóÖ÷Òª°üÀ¨ÒÔϼ¸¸ö·½Ã棺
ÔÚ CI Á÷³ÌÖмÓÈ뾲̬׼Èë¼ì²é£¬±ÜÃâ·±ËöµÄÈ˹¤ Review ÒÔ¼°¼õÉÙÈ˹¤ Review ¿ÉÄÜ´øÀ´µÄʧÎó¡£
ΪÁËÍÆ½øÏîÄ¿µÄÓÅ»¯¹ý³Ì£¬ÐèÒª·½·¨Êý¼à¿Ø¡¢ºê¶¨Òå·ÖÎöµÈ´úÂë·ÖÎö±¨±íºÍ¼à¿Ø¡£
Áã PV ±¨±í¡¢ÒÀÀµ·ÖÎöºÍÍ·ÎļþÒýÓù淶¡¢ÎÞÓôúÂë·ÖÎöµÈÏîÄ¿ÓÅ»¯·½°¸¡£
²»ÄÑ·¢ÏÖ£¬ÕâЩÐèÇóµÄ±¾ÖÊÊÇ£º½èÖú´úÂ뾲̬·ÖÎöÄÜÁ¦£¬ÌáÉýÏîÄ¿¿É³ÖÐø·¢Õ¹ËùÐèÒªµÄ×Ô¶¯»¯Ë®Æ½¡£Õë¶Ô C/Objective-C
Ö÷Á÷µÄ¾²Ì¬·ÖÎö¿ªÔ´ÏîÄ¿°üÀ¨£ºStatic Analyzer¡¢Infer¡¢OCLint µÈ¡£µ«ÊÇ£¬ÕâЩ·ÖÎö¹¤¾ß¶ÔÎÒÃǶøÑÔ´æÔÚһЩÎÊÌ⣺
¿ª·¢³É±¾¸ß£¬ÊÕÒæÓÐÏÞ£¬Ñз¢²ÎÓë»ý¼«ÐÔ²»¹»¡£
Õë¶Ô¾Ö²¿´úÂë·ÖÎö£¬¿ç±àÒëµ¥ÔªÒÔ¼°È«¾ÖÐÔ·ÖÎö½ÏÄÑ¡£
ÔöÁ¿·ÖÎöÀ§ÄÑ£¬CI ¾²Ì¬¼ì²éЧÂʵÍÏ¡£
¹¤¾ßÐÔ½ÏÇ¿£¬´ó²¿·ÖÖ»×÷´úÂë¹æ·¶¼ì²é£¬Ó¦Ó÷¶³ë¾ÖÏÞ¡£
½ÓÈëºÍά»¤³É±¾¸ß£¬ÄÑÒÔÆ½Ì¨»¯¡£
Õë¶ÔÒÔÉϱ³¾°ºÍÏÖÓз½°¸µÄ²»×㣬ÎÒÃǾö¶¨×ÔÑлùÓÚÓïÒåµÄ¾²Ì¬·ÖÎö¿ò¼Ü¡£
Hades ÏîÄ¿¼ò½é
´óÖÚµãÆÀ¾²Ì¬·ÖÎö¿ò¼Ü Hades£¬È¡ÃûÔ´ÓÚ¹ÅÏ£À°Éñ»°ÖеÄÚ¤Íõ¡£Ú¤Íõ Hades ¹«ÕýÎÞ˽£¬Äܹ»ÉóÊÓÁé»êµÄÊÇ·ÇÉÆ¶ñ¡£
Hades ¿ò¼ÜÖ§³ÖÓïÒå·ÖÎöÄÜÁ¦£¬ÎÒÃÇÏ£ÍûÕâÖÖÄÜÁ¦²»½ö½öÄܹ»È¥ÊµÏÖÒ»¸ö´«Í³µÄ Lint ¹¤¾ß£¬¶øÇÒÄܳÉΪ´´Ôì¸ü¶àÄÜÁ¦µÄ»ù´¡£¬¿ÉÒÔ°ïÖúÎÒÃǸüÇáËɵØÉóÊÓ´úÂ룬Àí½â°Ñ¿Ø´óÐÍÏîÄ¿¡£
Hades ·½°¸Ñ¡ÐÍ
Îı¾´¦Àí·½Ê½
Ê×ÏÈ£¬×î¼òµ¥µÄ¾²Ì¬·ÖÎöÊÇ×Ö·ûÆ¥ÅäºÍÎı¾´¦Àí¡£ÕâÖÖ·½Ê½ËäȻʵÏÖ¼òµ¥£¬µ«ÊÇ´æÔÚÄÜÁ¦ÉÏÏÞ£¬Ò²²»¿ÉÄÜÔÚÓïÒåÀí½âÉÏÓÐ×ã¹»µÄ°Ñ¿ØÁ¦¡£ÁíÍ⣬ÒÔÕýÔòÆ¥ÅäΪºËÐĽ¨Á¢µÄ¹¤¾ßÕ»ÄÑÒԵõ½³ÖÐøÓÅ»¯¡£ÎªÁË·ÖÎöÏîÄ¿µÄÒÀÀµ¹ØÏµ£¬ÎÒÃÇÐèÒªÅжϴúÂëÖеķûºÅº¬ÒåÒÔ¼°·ûºÅ¼ä¹ØÏµ£¨Èç°üº¬ÄÄЩÀ࣬ÀàÖÐÓÐÄÄЩ·½·¨µÈ£©£¬·ÖÎö¹ý³ÌµÄÕýÔò±í´ïʽÈçÏÂͼËùʾ¡£

Óɴ˿ɼû£¬·±ËöµÄÎı¾Æ¥Åä²»½ö¿É¶ÁÐԲҲ´æÔÚÈÝÒ×·ÖÎö³ö´íµÄÎÊÌâ¡£
»ùÓÚ±àÒëÆ÷µÄ¾²Ì¬·ÖÎö·½°¸
ÎÒÃÇÐèÇóµÄ±¾ÖÊÊǶԴúÂë½øÐзÖÎö£¬¶øÔÚÔ´´úÂë±àÒë¹ý³ÌÖУ¬Óï·¨·ÖÎöÆ÷»á´´½¨³ö³éÏóÓï·¨Ê÷£¨Abstract
Syntax Tree ËõдΪ AST£©¡£AST ÊÇÔ´´úÂëµÄ³éÏóÓï·¨½á¹¹µÄÊ÷×´±íÏÖÐÎʽ£¬Ê÷ÉϵÄÿ¸ö½Úµã¶¼±íʾԴÂëµÄÒ»Öֽṹ¡£

ÒÔÉÏͼΪÀý£¬´úÂë¿éÇøÓòÊÇÓà Objective-C ºÍ TypeScript ±àдµÄÒ»¸ö¼òµ¥Ìõ¼þÓï¾äÔ´Â룬ÏÂÃæÊÇÆä¶ÔÓ¦µÄ³éÏóÓï·¨½á¹¹±í´ï¡£ÕâÖÖÊ÷×´µÄ½á¹¹±í´ï£¬Ê¡ÂÔÁËһЩϸ½Ú£¨±ÈÈ磺ûÓÐÉú³ÉÀ¨ºÅ½Úµã£©£¬´ÓͼÖеÄÕâÖÖÓ³Éä¹ØÏµÖÐÎÒÃÇÒ²¿ÉÒÔ·¢ÏÖ£º
Ô´ÂëµÄÓï·¨½á¹¹ÊÇ¿ÉÒÔͨ¹ýÃ÷È·µÄÊý¾Ý½á¹¹±íʾµÄ¡£
´ó¶àÊý±à³ÌÓïÑÔ¶¼¿ÉÒÔÓÃÏàËÆµÄ AST ±í´ïµÄ¡£
¶ÔÓÚ C/Objective-C ¶øÑÔ£¬Ö÷Á÷±àÒëÆ÷ÊÇ Clang/LLVM£¨Low Level Virtual
Machine£©µÄ£¬ËüÊÇÒ»¸ö¿ªÔ´µÄ±àÒëÆ÷¼Ü¹¹£¬²¢±»³É¹¦Ó¦Óõ½¶à¸öÓ¦ÓÃÁìÓò¡£Clang£¨·¢ÒôΪ/kl??/£¬²»ÊÇCÀË£©ÊÇ
LLVMµÄÒ»¸ö±àÒëÆ÷ǰ¶Ë£¬ËüĿǰ֧³Ö C, C++, Objective-C µÈ±à³ÌÓïÑÔ¡£Clang
»á¶ÔÔ´³ÌÐò½øÐдʷ¨·ÖÎöºÍÓïÒå·ÖÎö£¬½«·ÖÎö½á¹ûת»»Îª AST¡£ÏÖÓз½°¸Öв»ÉÙ Lint ¹¤¾ß±ãÊÇ»ùÓÚ
Clang µÄ£¬Clang °üº¬ÁËÒÔÏÂÌØµã£º
±àÒëËٶȿ죺Clang µÄ±àÒëËÙ¶ÈÔ¶¿ìÓÚ GCC¡£
Õ¼ÓÃÄÚ´æÐ¡£ºClang Éú³ÉµÄ AST ËùÕ¼ÓõÄÄÚ´æÊÇ GCC µÄÎå·ÖÖ®Ò»×óÓÒ¡£
Ä£¿é»¯Éè¼Æ£ºClang ²ÉÓûùÓÚ¿âµÄÄ£¿é»¯Éè¼Æ£¬Ò×ÓÚ IDE ¼¯³É¼°ÆäËûÓÃ;µÄÖØÓá£
Òò´Ë£¬½èÖú Clang µÄÄ£¿é»¯Éè¼ÆºÍ¸ßЧ±àÒëµÈÖî¶àÓŵ㣬Hades Ò²½«¸üÈÝÒ׿ª·¢ºÍÉý¼¶Î¬»¤¡£Clang
¶ÔÔ´ÂëÇ¿ÓÐÁ¦µÄ·ÖÎöÄÜÁ¦Ò²ÊÇÖ÷Á÷¾²Ì¬·ÖÎö¹¤¾ßµÄ²»¶þ֮ѡ¡£
Clang AST ³õʶ
Clang ÏîÄ¿·Ç³£ÅÓ´ó¡£½ö½öÊÇ Clang AST Ïà¹Ø´úÂë¾Í³¬¹ý 10W+ ÐдúÂë¡£ÈçºÎÀûÓà Clang
ʵÏÖ AST ·ÖÎö¹¤×÷£¬ÕâÀï¿ÉÒԲο¼¹ÙÍøÌṩµÄÎĵµ Choosing the Right Interface
for Your Application £¬ÒÔÏÂÊÇÈýÖÖ·½Ê½£º
LibClang
Ìṩ C ÓïÑÔµÄÎȶ¨½Ó¿Ú£¬Ö§³ÖPython Binding¡£AST ²¢²»ÍêÕû£¬²»ÄÜÍêÈ«ÕÆ¿Ø Clang
AST¡£
Clang Plugins
Ìṩ C++ ½Ó¿Ú£¬¸üп죬²»Äܱ£ÁôÉÏÏÂÎÄÐÅÏ¢¡£²å¼þµÄ´æÔÚÐÎʽÊÇÒ»¸ö¶¯Ì¬Á´½Ó¿â£¬²»ÄÜÔÚ¹¹½¨»·¾³Íâ¶ÀÁ¢´æÔÚ¡£
LibTooling
Ìṩ C++ ½Ó¿Ú£¬¸üп죬¿ÉÒÔͨ¹ý±ê×¼µÄ main() º¯Êý×÷ΪÈë¿Ú£¬¿É¶ÀÁ¢ÔËÐУ¬Äܹ»ÍêÈ«ÕÆ¿Ø AST£¬Ïà±È
Plugin ¸üÈÝÒ×ÉèÖá£
ÕâÀïÎÒÃÇÑ¡Ôñ¿É¶ÀÁ¢ÔËÐв¢ÇÒÄÜÍêÈ«ÕÆ¿Ø AST µÄ LibTooling ×÷Ϊ Hades µÄ»ù´¡¡£
ÔÚʹÓà Clang µÄѧϰ¹ý³ÌÖУ¬»ù±¾µÄ¸ÅÄî±ãÊDZíʾ AST µÄ½ÚµãÀàÐÍ£¬ÕâÀïÖØÒªµÄ¼¸µãÊÇ£º
ASTContext¡£
ASTContext ÊDZàÒëʵÀýÓÃÀ´±£´æ AST Ïà¹ØÐÅÏ¢µÄÒ»Öֽṹ£¬Ò²°üº¬Á˱àÒëÆÚ¼äµÄ·ûºÅ±í¡£ÎÒÃÇ¿ÉÒÔͨ¹ý
TranslationUnitDecl * getTranslationUnitDecl()£º ·½·¨µÃµ½Õû¸ö·Òëµ¥ÔªµÄ
AST µÄÈë¿Ú½Úµã¡£
½ÚµãÀàÐÍ¡£
AST ͨ¹ýÈý×éºËÐÄÀ๹½¨£ºDecl (declarations)¡¢Stmt (statements)¡¢Type
(types)¡£ÆäËü½ÚµãÀàÐͲ¢²»»á´Ó¹«¹²»ùÀà¼Ì³Ð£¬Òò´Ë£¬Ã»ÓÐÓÃÓÚ·ÃÎÊÊ÷ÖÐËùÓнڵãµÄͨÓýӿڡ£
±éÀú·½Ê½¡£
ΪÁË·ÖÎö AST£¬ÎÒÃÇÐèÒª±éÀúÓï·¨Ê÷¡£Clang ÌṩÁËÁ½ÖÖ·½Ê½£ºRecursiveASTVisitor
ºÍ ASTMatcher¡£RecursiveASTVisitor Äܹ»ÈÃÎÒÃÇÒÔÉî¶ÈÓÅÏȵķ½Ê½±éÀú Clang
AST ½Úµã¡£ÎÒÃÇ¿ÉÒÔͨ¹ýÀ©Õ¹ÀಢʵÏÖËùÐèµÄ VisitXXX ·½·¨À´·ÃÎÊÌØ¶¨½Úµã¡£
ASTMatcher API ÌṩÁËÒ»ÖÖÓòÌØ¶¨ÓïÑÔ£¨DSL£©À´¹¹½¨»ùÓÚ Clang AST µÄν´Ê£¬ËüÄܸßЧµØÆ¥Åäµ½ÎÒÃǸÐÐËȤµÄ½Úµã¡£
³ýÁËÕâÁ½ÖÖ·½Ê½Í⣬LibClang Ò²ÌṩÁË Cursors À´±éÀú AST¡£¸ü¶àϸ½ÚÄÚÈÝ¿ÉÒÔǰÍù
£ºclang.llvm.org ¡£
³£ÓÿªÔ´¹¤¾ßµÄ²»×ã
ͨ¹ýÉÏÒ»Õ½ڵĽéÉÜ£¬ÎÒÃÇ´óÖÂÁ˽âÁË Clang µÄ»ù±¾Ìص㡣 µ«ÊÇÔÚʵ¼ù¿ª·¢¹ý³ÌÖз¢ÏÖ£ºÍ¨¹ý Clang
API È¥±éÀúºÍ·ÖÎö AST µÄÔ´ÂëÊ÷Ðνṹ½ÏΪ¸´ÔÓ¡£ÏÖÓо²Ì¬·ÖÎö·½°¸£¨È磺OCLint£©£¬´ó¶àÊÇÖ±½Ó¸ø³ö·â×°ºÃµÄ
Lint ¹¤¾ß£¬À©Õ¹·½ÃæÒ²ÊÇÌṩ½ÅÊÖ¼ÜÉú³É Rule Îļþ£¬È»ºóÔÚ Rule Öбàд·ÃÎÊÌØ¶¨ AST
½ÚµãµÄ·½·¨£¨ÀýÈ磺VisitObjCMethodDecl ·½·¨ÓÃÀ´·ÃÎÊ Objective-C µÄ·½·¨¶¨Ò壩¡£
Òò´Ë£¬ÏÖÓз½°¸´ó¶àÊýÖ»ÌṩÁËÖ±½Ó·ÃÎÊ AST µÄ·½Ê½£¬¶øÇÒÕâÖÖ·½Ê½½ÏΪ¡°¾Ö²¿¡±¡£Ã¿ÊµÏÖÒ»¸öʵ¼ÊÐèÇóÐèÒªºÄ·Ñ´óÁ¿¾«Á¦È¥Àí½âÈçºÎ´Ó
AST ·ÖÎöÓ³Éäµ½Ô´ÂëµÄÓïÒåÂß¼¡£
µ«ÊÇ£¬Code Review ʱÎÒÃDz¢²»»á½«Ä¿±ê´úÂëת»»Îª AST È»ºóÔÙÈ¥·ÖÎö´úÂëµÄÓïÒåÈçºÎ£¬¸ü¶àµÄÊÇÖ±½ÓÀí½â´úÂëµÄ¾ßÌåÂß¼ºÍµ÷ÓùØÏµ¡£AST
Ê÷×´½á¹¹·ÖÎöµÄ¸´ÔÓÐÔÈÝÒ×´øÀ´Àí½âÉϵIJîÒìºè¹µ¡£Òò´Ë£¬ÕâÒ²²»ÀûÓÚµ÷¶¯ÒµÎñÑз¢ÍŶӵĻý¼«ÐÔ£¬ºÜ¶à»ùÓÚÔ´Âë·ÖÎö¹¤×÷Ò²ÄÑÒÔÂ䵨¡£
Hades ºËÐÄʵÏÖ
ΪÁËÈ÷ÖÎö¹ý³Ì¸üÇåÎú£¬ÎÒÃÇÐèÒªÔÚ AST µÄ»ù´¡Ö®ÉÏÔÙ½øÐÐÒ»´Î³éÏó¡£±¾Õ½ÚÖ÷ÒªÄÚÈݰüº¬£ºHades
µÄÕûÌå¼Ü¹¹¡¢ÎªÊ²Ã´Òª¶¨ÒåÓïÒåÄ£ÐÍ¡¢¶¨ÒåʲôÑùµÄÓïÒåÄ£ÐÍ¡¢ÈçºÎÊä³öÓïÒåÄ£ÐÍÒÔ¼°Ä£Ð͵ÄÐòÁл¯ºÍ³Ö¾Ã»¯¡£
Hades ×ÜÌå¼Ü¹¹
°´ÕÕ Hades µÄ¼Ü¹¹Ä¿±ê½øÐлù´¡·½°¸Ñ¡ÐÍÒÔºó£¬ÎÒÃÇÀ´¿´Ï Hades
µÄÕûÌå¼¼Êõ¿ò¼Ü£¬¿ÉÒÔÓÃÏÂͼËùʾµÄËIJã¼Ü¹¹±íʾ£º

ÏÂÃæ¼òÊöÏÂÕ⼸²ãµÄ²»Í¬Ö°Ôð¡£
±àÒëÆ÷¼Ü¹¹²ã¡£Clang µÄÖî¶àÓÅÊÆÇ°ÎÄÒѾÌáµ½£¬ÕâÒ²ÊÇ Hades µÄ»ù´¡ÒÀÀµ¡£
Hades ºËÐIJ㡣ÔÚ±àÒëÆ÷¼Ü¹¹²ã£¬ÎÒÃǽèÖú Clang µÃµ½ÁË´úÂëµÄ³éÏóÓï·¨½á¹¹±íʾ AST¡£¶ø
Hades ºËÐIJãµÄÖ°Ôð±ãÊǽ« AST ½âÎö³ÉÈËÃǸüÈÝÒ×Àí½âµÄ£¬¸ü¸ß²ã¼¶µÄÓïÒåÄ£ÐÍ¡£
Hades ½Ó¿Ú·â×°²ã¡£³éÏó³öµÄÄ£ÐÍ£¬Äܹ»Ïñ Clang Ìṩ·á¸» AST ·ÃÎʽӿÚÄÇÑù£¬Îª¿ª·¢ÕßÌṩ·á¸»µÄÄ£ÐÍ·ÃÎʽӿڡ£
¾²Ì¬·ÖÎöÓ¦Óá£Í¨¹ý Hades ½Ó¿Ú·â×°£¬ÎÒÃÇÎÞÐèÇå³þµ×²ãÄ£ÐÍÊÇÈçºÎÉú³ÉµÄ£¬ÔÚÕâÒ»²ãÎÒÃÇ¿ÉÒÔÖÆ×÷ Lint
»òÕ߯äËü¼à¿Ø¡¢·ÖÎö¹¤¾ß¡£
Ϊʲô Hades µÄ¼Ü¹¹Éè¼ÆÊÇÕâÑùµÄÄØ£¿ÏÂÃæÎÒÃǽ«Ò»Ò»µÀÀ´¡£
ΪºÎÒª¶¨ÒåÓïÒåÄ£ÐÍ £¿
Ê×ÏÈ£¬ÕýÈ硸³£ÓÿªÔ´¹¤¾ßµÄ²»×㡹Õ½ÚËùÊö£¬´ó¶àÏÖÓз½°¸ÊÇÖ±½Óͨ¹ý±àÒëÆ÷ǰ¶ËÌṩµÄ½Ó¿ÚʵÏÖ¶Ô AST
µÄ²Ù×÷£¬´Ó¶ø´ïµ½¾²Ì¬·ÖÎöµÄÄ¿µÄ¡£
µ±È»£¬³ýÁËÏÖÓз½°¸µÄ²»×ãÒÔÍ⣬ÔÚÒµÎñÑз¢¹ý³ÌÖгöÏÖµÄ Case £¬ÆäÔÒò´ó¶àÊý²¢²»ÊÇÎ¥·´ÁËÏÖÓеÄ
Lint ¹¤¾ßÖÐËù¶¨ÒåµÄ»ù±¾Óï·¨¹æ·¶£¬ÕâЩ¹æÔò·ÖÎöµÄÍùÍùÊÇ¡°³£Ê¶¡±ÀàÎÊÌâ¡£ÔÚ¾²Ì¬·ÖÎöÖУ¬¸ü¶àµÄÊǶÔÏóµÄ´íÎó·½·¨µ÷ÓúͷǷ¨µÄ¼Ì³Ð/¸´Ð´¹ØÏµµÈÎÊÌ⣬¼´±ã¾ß±¸Á¼ºÃµÄ±àÂë¹æ·¶Ò²»áÊèºö¡£ÕâÀïÕ§Ò»¿´Ã»Ì«´óÇø±ð£¬µ«ÊÇ´Ó×ÅÖØµãÀ´Ëµ£¬Hades
µÄÉè¼ÆÀíÄîÉÏ»á´æÔÚ±¾ÖÊÇø±ð¡£

ÈçÉÏͼËùʾ£¬ÏÖÓз½°¸Èç OCLint »òÕß Clang Static Analyser µÈ£¬ÆäºËÐÄÔÀíÊÇÔÚ±àÒëÆ÷½«Ô´ÂëÉú³É
AST ʱ£¬Í¨¹ý·ÖÎö½ÚµãºÍ½Úµã¼äµÄ¹ØÏµ£¬´Ó¶ø´ïµ½¾²Ì¬·ÖÎöµÄÄ¿µÄ¡£ÕâÖÖ·½Ê½²»ÀûÓÚ¿ç±àÒëµ¥Ôª·ÖÎö£¬×ÔÈ»¶ÔÏîÄ¿¼¶±ðµÄÀí½â·ÖÎö´æÔÚ¾ÖÏÞÐÔ¡£
ËùÒÔ£¬ÕâÀï¿ÉÒÔ½èÖú AST Õë¶Ôÿ¸ö±àÒëµ¥Ôª½¨Á¢¸üÖ±¹ÛµÄ¡¢¸üÈÝÒ×Àí½âµÄ½á¹¹»¯±í´ï¡£ÎÒÃǽ«Õâ¸ö¸ü¸ß²ã¼¶µÄÓïÒå±í´ï³ÆÎª
HadesModel¡£
¶¨ÒåʲôÑùµÄÓïÒåÄ£ÐÍ £¿
½¨Á¢ HadesModel ÒÔºóµÄ¾²Ì¬·ÖÎöÖУ¬ÎÒÃǵÄ×ÅÖØµã±ä»¯ÈçÏÂͼËùʾ£º

ÏÂÃæÎÒÃÇ¿ÉÒÔ¼òµ¥ÃèÊöÐèÒªÉè¼ÆµÄ HadesModel µÄ»ù±¾Ìص㣺
1.HadesModel ¿ÉÒԽṹ»¯±í´ïÔ´ÂëµÄÓïÒå¡£ËüÄܹ»±í´ïÒ»¸ö±àÒëµ¥Ôª¶¨ÒåÁËÄÄЩ½Ó¿ÚÉùÃ÷¡¢ÊµÏÖÁËÄÄЩÀà/Àà±ðµÄ·½·¨¡¢¶¨ÒåºÍÕ¹¿ªÁËÄÄЩºê¶¨Òå¡¢¶ÔÏóµÄ·½·¨µ÷Óúͺ¯ÊýʹÓÃÇé¿öµÈµÈ¡£
2.HadesModel ʹÎÒÃDz»ÐèÒªÁ˽â Clang ±àÒëÆ÷ÒÔ¼°
AST ÈçºÎ±í´ïÔ´Âë¡£
3.HadesModel ÒÔÒ»¸öÍêÕûµÄ±àÒ뵥ԪΪµ¥Î»£¬Ö§³Ö JSON
¸ñʽ±í´ï¡£
4.¶ÔÓÚ Objective-C £¬·ÖÎö¹ý³Ì²»±ØÇ¿ÒÀÀµÓÚ xcodebuild
±àÒë¹¹½¨¹ý³Ì¡£
ͨ¹ýÒÔÉϼ¸µãÌØÕ÷ÃèÊö£¬ÎÒÃǵõ½ÁË HadesModel ¸üÇåÎúµÄ±íÊö£º
HadesModel ÊÇ»ùÓÚ AST µÄ¸ü¸ß²ã¼¶ÓïÒå±í´ï£¬ËüÄܹ»ÐòÁл¯Îª JSON ¸ñʽ²¢ÃèÊöÍêÕûµÄ±àÒëµ¥Ôª£¬ÕâÖֽṹ»¯ÐÅϢʹµÃ¾²Ì¬·ÖÎöÄܸü½Ó½üÓÚ¿ª·¢ÕßÔĶÁÀí½âÔ´ÂëµÄ˼άϰ¹ß¡£
ÔÚ½éÉÜÍê HadesModel µÄ»ù±¾Ä¿±êºó£¬ÎÒÃÇÓÃÏÂÃæÒ»¶Î¼òµ¥µÄ
Objective-C ´úÂëΪÀýÀ´Ã÷È· HadesModel µÄ¾ßÌå±í´ïÐÎʽ£º

ÔÚʾÀý´úÂëÖУ¬ÎÒÃǼòµ¥Á˽âϰüº¬µÄÓïÒåÂß¼£º
ÕâÊÇÒ»¶Î Objective-C ´úÂ룬ʵÏÖÎļþÃûΪ HadesViewController.m¡£
ÔÚʵÏÖÎļþÖУ¬¶¨ÒåÁËÒ»¸öÃûΪ HadesMacro µÄºê¶¨Òå¡£
ʵÏÖÎļþÖаüº¬ÁË HadesViewController ÀàµÄʵÏÖ²¿·Ö£¬HadesViewController
ÊÇ UIViewController µÄ×ÓÀà¡£
HadesViewController ÀàÖаüº¬ÁËÁ½¸ö·½·¨ÊµÏÖ¡£ÆäÖеÚÒ»¸ö·½·¨ÃûΪ sayHello
£¬ÀïÃæ°üº¬Á˾ֲ¿¶ÔÏó testView µÄ³õʼ»¯ÒÔ¼°¶ÔÏóµÄ·½·¨µ÷Óã¬ÁíÍ⻹°üº¬Á˺궨ÒåµÄʹÓá£
¿ÉÒÔ·¢ÏÖ£¬HadesModel Äܹ»±í´ï¿ª·¢Õß¶ÔÓïÒåÐÅÏ¢µÄÖ±¹ÛÀí½â¼´¿É¡£
ÈçºÎÉú³ÉÓïÒåÄ£ÐÍ£ºHadesModel £¿
½ÓÏÂÀ´½éÉÜ Hades »ù±¾¼Ü¹¹Í¼ÖÐ HadesCore µÄºËÐÄʵÏÖ£¬ÖصãÔÚÈçºÎÉú³ÉǰÎÄËùÊöµÄ HadesModel¡£
ÕâÀï HadesCore ½èÖú Clang LibTooling
·ÖÎöÔ´ÂëµÄ AST£¬È»ºó½«ÎÒÃÇËùÐèµÄÓïÒåÐÅÏ¢³éÏó³É HadesModel¡£½«Êý¾Ý³éÏóºÍת»»¹ý³ÌÓÃÒÔϼòÒªÁ÷³Ì±íʾ£º

ÏÂÃæ½«´ÓÒ»¸öÁ÷³ÌͼÀ´¿´¿´ HadesCore ÊÇÈçºÎÉú³É HadesModel
µÄʵÏÖϸ½Ú£º

Á÷³ÌͼÖÐÖ÷Òª°üÀ¨ÒÔϼ¸µãÄÚÈÝ£º
1. ¹¹½¨±àÒëÊý¾Ý¿â
Ê×ÏÈ£¬Hades ÊÇ»ùÓÚ Clang µÄÄ£¿é»¯Éè¼Æ¿ª·¢£¬ËùÒÔËü¿ÉÒÔ¶ÀÁ¢ÔËÐУ¬Òò´Ë£¬¿ÉÒÔÀûÓà RubyGem
µÄ·½Ê½½«Ä£ÐÍÉú³É¹ý³Ì·â×°²¢ÌṩÃüÁîÐй¤¾ß¡£¶ÔÓÚÐèÒªµÃµ½ HadesModel µÄ±àÒëµ¥Ôª.m£¬Ê×ÏÈÐèÒª×÷ΪԴÎļþ¼¯³Éµ½
workspace £¨iOS ¿ÉÒÔÓà CocoaPods£©£¬È»ºóÀûÓà Xcode ÌṩµÄ xcodebuild
½áºÏ xcpretty ±àÒëµÃµ½ÏîÄ¿µÄ±àÒëÊý¾Ý¿â compile_commands.json¡£±àÒëÊý¾Ý¿âÓÃÀ´Ö¸¶¨Ã¿¸ö±àÒëµ¥ÔªµÄÃüÁîÐвÎÊý¡£
2. ´´½¨ HadesDriver
ÔÚ´´½¨Çý¶¯Æ÷֮ǰ£¬¿ÉÒÔʹÓà Clang ÌṩµÄ CommonOptionsParser À࣬Ëü½«¸ºÔð½âÎöÓë±àÒëÊý¾Ý¿âºÍÊäÈëÏà¹ØµÄÃüÁîÐвÎÊý£¬È»ºó½«Æä×÷ΪÇý¶¯Æ÷µÄÊäÈë¡£Çý¶¯Æ÷¿ØÖÆÕû¸öÄ£ÐÍÉú³ÉÖÜÆÚ£¬ËüµÄÊä³ö½á¹û±ãÊÇ
HadesModel¡£
3. ¹¹½¨ HadesModel
ÔÚ HadesDriver µÄÇý¶¯Ï£¬Ê×ÏÈÐèÒª´´½¨±àÒëÆ÷ʵÀý£¬Ö´ÐбàÒëǰ¿ÉÒÔ·ÖÎöºê¶¨ÒåºÍÍ·ÎļþÕ¹¿ªµÈÔ¤´¦ÀíÐÅÏ¢£¬²¢½«ÕâЩÄÚÈݳõʼ»¯µ½
HadesModel ¶ÔÏó¡£½Ó×Å£¬ÔÚ±àÒëÆ÷ʵÀýÖн« FrontendAction ½Ó¿Ú×÷ΪÀ©Õ¹±àÒë¹ý³ÌµÄÖ´ÐÐÈë¿Ú£¬ÀûÓÃ
Clang LibTooling ÌṩµÄ ASTVistor ·ÃÎÊ AST ½Úµã£¨¸ü¶à Clang
¼¼Êõϸ½Ú¼û£ºClang 8 documentation£©£¬×îÖÕ½«ËùÓзÒëµ¥ÔªµÄ¡°ÔªÊý¾Ý¡±Ìî³äµ½ HadesModel¡£
ÒÔǰÎÄµÄ HadesViewController.m ΪÀý£¬ÎÒÃǵõ½
HadesModel ²¢ÐòÁл¯Îª JSON Êý¾ÝÒÔºó£¬ÈçÏÂͼËùʾ£º

ÏÔÈ»£¬Ê¾Àý HadesModel ÒѾÄܹ»±í´ï¿ª·¢Õß Code Review ʱ£¬¾ø´ó¶àÊý¡°Ö±°×¡±µÄÓïÒåÐÅÏ¢ÁË¡£
HadesModel µÄÐòÁл¯/³Ö¾Ã»¯
ÓÉÓÚ HadesModel ×îÖÕÐèÒªÒÔ JSON ¸ñʽ×÷ΪÌṩ¾²Ì¬·ÖÎöµÄÔʼÊý¾ÝÀàÐÍ£¬ËùÒÔÐèÒª±£Ö¤
HadesModel ¾ß±¸ÐòÁл¯µÄÄÜÁ¦¡£
JSON ¸ñʽʹ Hades ¾ß±¸ÁËÈ«¾Ö·ÖÎöÄÜÁ¦£¬Ò²·ûºÏÉè¼ÆÖ®³õµÄ·ÖÎöºÍƽ̨¡¢ÓïÑÔÎ޹صÄÒªÇó¡£ÔÙÕߣ¬JSON
ÀàÐÍÒ²·½±ãÀûÓþ߱¸½ÏºÃÀàÐÍϵͳµÄÓïÑÔ×÷Ϊ·ÖÎö½Ó¿Ú²ã¡£
ʵ¼ùÖУ¬ÒÔ iOS ³£ÓÃµÄ CocoaPods µÄ Pod Ϊµ¥Î»£¬ÔÚ˽ÓÐ Pod ·¢°æÊ±Éú³ÉÄ£ÐÍÊý¾ÝÈ»ºó´ò°ü´æ´¢ÔÚ
Maven ÖУ¬ÒÔ±ãÓÚÔöÁ¿·ÖÎö¡£
ÔÚ CI ϵͳÖУ¬ÌرðÊÇ´óÐÍÏîÄ¿³Ö¾Ã»¯µÄÄ£ÐÍ´æ´¢·Ç³£ÖØÒª¡£CI ÖÐΪÁ˼ӿ켯³ÉËÙ¶È£¬²»µÃ²»Ê¹Óò¿·Ö¶þ½øÖƵɷ½Ê½£¬µ«ÊÇÕâÑù½«ÎÞ·¨¶Ô¾²Ì¬¿â½øÐÐÔ´Âë·ÖÎö¡£ÀûÓÃ
Hades µÄÄ£ÐÍ»º´æ£¬ÎÒÃÇ¿ÉÒÔ½â¾ö¶þ½øÖƼ¯³ÉµÄ¾ÖÏÞÐÔ¡£»º´æÊý¾ÝÒ²²»ÐèÒªÔٴαàÒ롢ģÐÍÉú³ÉµÈºÄʱ²Ù×÷£¬ËùÒÔ½ÓÈë
Hades ºó»ù±¾²»Ó°Ï켯³ÉÏîÄ¿µÄ¼¯³ÉËÙ¶È¡£
Hades Ó¦Óð¸Àý£¨1£©£ºÖÆ×÷ Lint ¹¤¾ß
ÔÚÕâÒ»Õ£¬ÎÒÃǽ«½éÉÜ Hades ¼Ü¹¹ÖеĽӿڲ㣬ÒÔ¼°ÔÚ Lint ¹¤¾ßÉϵÄÓ¦Óá£
HadesLint ¼Ü¹¹ÃèÊö
HadesLint ÊÇ»ùÓÚ Hades ¿ò¼ÜÖÆ×÷µÄ¾²Ì¬·ÖÎö¹¤¾ß¡£×÷Ϊƽ̨±ê×¼µÄ Lint ¹¤¾ß£¬Ä¿Ç°ÔÚ³ÖÐø¼¯³ÉÓÐÁ˹㷺ӦÓã¨ÏêÇé¼û´ËƪÎÄÕ£ºMCI£º´óÖÚµãÆÀǧÈËÒÆ¶¯Ñз¢ÍŶÓÔõÑù×ö³ÖÐø¼¯³É£¿£©¡£
HadesLint ¿ª·¢ÓïÑÔÊÇ TypeScript¡£Ëü¾ß±¸ÍêÉÆµÄÀàÐÍϵͳ£¬½áºÏ VSCode µÄÖÇÄܲ¹È«ºÍÍêÉÆµÄ
Debug ÄÜÁ¦£¬Ê¹µÃ HadesLint ¾ß±¸Á¼ºÃµÄ¿ª·¢ÌåÑé¡£
HadesLint µÄʵÏÖϸ½ÚÈçÏÂͼËùʾ£º

ÔÚ½ÓÈë HadesLint µÄÏîÄ¿ºó£¬ÎÒÃǽ«ÏîÄ¿ÒÔ Pod Ϊµ¥Î»£¬´Ó Maven ÖжÁÈ¡»º´æÄ£ÐÍ
Zip °ü¡£Èç¹û²»´æÔÚ»º´æ£¬ÄÇô½«ÀûÓÃǰÎÄËùÊö·â×°ºÃµÄ HadesGem ͨ¹ý±àÒëÊý¾Ý¿âʵʱÉú³Éÿ¸ö±àÒëµ¥ÔªµÄ
HadesModel¡£
ÓÉÓÚÎÒÃǵÄÏîÄ¿½Ï´ó£¬Ä£ÐÍÊý¾ÝÁ¿Ò²·Ç³£ÅÓ´ó£¬ÎªÁË·ÀÖ¹·ÖÎö¹ý³ÌÄÚ´æÐ¹Â¶µÄΣÏÕ£¬ÌáÉý·ÖÎöÐÔÄÜ£¬¿ÉÒÔͨ¹ýLazy.js½øÐжèÐÔÇóÖµ£¬½¥½ø¼ÓÔØÓÐЧ½â¾öÁËÄ£ÐÍÊý¾ÝÅÓ´óµÄÎÊÌâ¡£
±» Lazy.js ¼ÓÔØµÄ JSON ¶ÔÏó£¬ÐèҪͨ¹ý TypeScript ÉùÃ÷À´±£Ö¤ HadesModel
¾ß±¸ÀàÐÍ¡£ÕâÑù£¬ÎÒÃǾͿÉÒÔÔÚ VSCode Öбàд´úÂëʱ£¬ÏíÊÜ×Ô¶¯²¹È«¡¢ÀàÐÍÍÆ¶Ï£¬´Ó¶ø±£Ö¤±àд¹ý³Ì¸ü¼Ó°²È«¡¢¸ßЧ¡£½èÖú
VSCode ¶Ô TypeScript µÄÁ¼ºÃÖ§³Ö£¬ÔÚ±àд·ÖÎö¹ý³ÌÖз½±ãµØ Debug¡£
×îºó HadesLint Driver »á¼ÓÔØÃ¿¸ö¹æÔò¶ÔÏó£¬ÔÚ¹æÔòÖзÖÎö HadesModel È»ºóÈ·¶¨¼ì²éÏîÊÇ·ñºÏ·¨¡£
µ±È»£¬Èç¹ûÏ£Íû³ÌÐòÖ´ÐÐЧÂʸü¸ßЩ£¬Ò²¿ÉÒÔ³¢ÊÔ OCaml+ATD À´¹¹½¨ Lint ÏîÄ¿¡£
HadesLint Ó¦Óð¸Àý£º´òÓ¡ÏîÄ¿ÖеÄÀàÃû
ÐèÇóÃèÊö£ºÎÒÃÇÐèÒªÕÒµ½ÏîÄ¿Öж¨ÒåµÄËùÓÐÀàÃû¡£
ÎÒÃÇÖ»ÐèҪͨ¹ý½ÅÊּܴ´½¨ÐµĹæÔò£¬È»ºó±àдÒÔÏ´úÂ룺
this.hadesModels.each((hadesModel:
HadesModel.HModel) => {
hadesModel.class_list.forEach((occlass: HadesNode.Class)
=> {
console.log(occlass.name);
})
});
|
±àд´úÂëÒԺ󣬿ÉÒÔÔÚ VSCode µÄ Debug Ãæ°åÖпªÆôµ÷ÊÔ£º

µ±È»£¬³ýÁËÒÔÉϼòµ¥µÄ²éѯ¹¦ÄÜÒÔÍ⣬ÎÒÃÇÒ²¿ÉÒÔ¶¨ÖÆÏà¶Ô¸´Ôӵļì²é¹æÔò£¬±ÈÈç¼Ì³ÐÁ´¹Ü¿Ø¡¢·½·¨¸´Ð´¼ì²é¡¢·Ç¿Õ¼ì²éµÈ¡£
ÔÚÒý³ö·½·¨¸´Ð´¹Ü¿ØÖ®Ç°£¬¿ª·¢ÕßÍùÍù»áͨ¹ýËæÒâ¼Ì³ÐµÄ·½Ê½¸´Ð´´úÂ룬»òÕßͨ¹ý²»ºÏÀíÀ©Õ¹·½Ê½À´Âú×㵱ǰÐèÇó¡£µ«ÊÇ£¬È˹¤
Review ´úÂëºÜÄѱ£Ö¤¼¯³ÉÏîÄ¿ÖУ¬ÕâЩÀ©Õ¹»òÕß×ÓÀàÔÚÔËÐÐʱµÄÐÐΪ¡£Òò´Ë£¬¶Ô¼Ì³ÐÁ´¹Ü¿ØµÄÐèÇó·Ç³£ÓбØÒª¡£ÎÒÃǵÄ
App ֮ǰ¾Í³öÏÖÁËÀ©Õ¹Í¬Ãû·½·¨£¬ÒâÍâµ¼Ö·½·¨¸´Ð´£¬´Ó¶øÔÚ³ÌÐòÔËÐÐʱ³öÏÖÎÊÌ⣬ÉõÖÁµ¼Ö Crash¡£
Ϊ´Ë£¬ÎÒÃÇÔÚ¼¯³É×¼Èë¼ì²éÖмÓÈëÁË·½·¨¸²¸Ç¼ì²é¡£µ±È»£¬Èç¹û¸¸ÀàÉè¼ÆÖ®³õ±¾ÉíÊÇÏ£Íû×ÓÀิд£¬ÎÒÃÇÔÚ Lint
¹ý³ÌÖÐͨ³£»áºöÂÔÕâЩºÏ·¨µÄ¸´Ð´Çé¿ö¡£
¶ÔÓÚÕâÀà¿ç±àÒëµ¥ÔªµÄ·ÖÎöÐèÇó£¬Èç¹ûÎÒÃǰ´ÕÕ Clang Static Analyser ÊǽÏÄÑ·ÖÎöµÄ£¬µ«ÊÇ
Hades ¾Í¿ÉÒԷdz£ÇáËɵØ×öµ½£¬ÒòΪ Hades ¿ÉÒÔÇáËÉ»ñÈ¡Õû¸ö¼Ì³ÐÁ´ÒÔ¼°Ã¿¸öÀàµÄʵÏÖ¶¨Òå¡£
Hades Ó¦Óð¸Àý£¨2£©£º¹¹½¨ HadesDB
HadesModel Êǽṹ»¯Êý¾Ý£¬Òò´Ë£¬ÎÒÃÇÒ²¿ÉÒÔ½«ÕâЩģÐÍÊý¾ÝÒÔ Document µÄÐÎʽ´æ´¢µ½ÎĵµÐÍÊý¾Ý¿âÖУ¬ÀýÈ磺CouchDB¡£
ÔÚ CouchDB µÄ»ù´¡ÉϽ¨Á¢Ä£ÐÍÊý¾Ý¿â£¬ÕâÑù±ãÄܹ»·½±ãµØÍ¨¹ý Map-Reduce ½¨Á¢ÊÓͼÎĵµ£¨Design
Documents£©£¬È»ºó£¬ÎÒÃÇ¿ÉÒÔ»ñÈ¡ÏîÄ¿Öаüº¬µÄÀ༰Æä·½·¨ÁÐ±í¡¢·ÖÎöÿ¸ö Document µÄ×ֶΰ´ÐèÊä³ö½á¹û¡£
ÀýÈ磬´æ´¢½¨Á¢ÍêÕûµÄÏîÄ¿ HadesModel Êý¾Ýºó£¬ÔÚ CouchDB Öн¨Á¢ Design Document£¬È»ºóÔÚ
Map Function ÖбàдÒÔÏ´úÂë:
function
(doc) {
if (doc.extracontext.macro_list !== null) {
emit(doc._id, doc.extracontext.macro_list);
}
} |
CouchDB Ö§³Ö JS ´úÂë±àд map-reduce£¬ÒÔÉÏ´úÂë±íʾÔÚµ±Ç°µÄÊý¾Ý¿âÖУ¬¶ÔÓÚÿ¸ö
HadesModel Document ÅжÏÊÇ·ñ´æÔں궨Ò壬Èç¹û´æÔÚ£¬ÄÇôÊä³öºê¶¨Òå×÷Ϊ Design
Document µÄ½á¹û¡£
×îºó£¬Í¨¹ý CouchDB ½Ó¿Ú·µ»Ø¿ÉÒÔ»ñÈ¡ÈçϽá¹û£º
App
ÏîÄ¿ÖÐÔ´ÂëÖÐʹÓõÄËùÓк궨ÒåÐÅÏ¢£º
{ "total_rows": xxx, "offset":
0, "rows": [
{ "id": "NVShopInfoBlackPearlMultiDealCell",
"key": "NVShopInfoBlackPearlMultiDealCell",
"value": [
{ "name": "NVActionSheet",
"expanded": true, "expandstr":
"UIResponder<NVActionSheetDelegate>
*", "location": ${path_location},
...
}
]
},
...
]
}
|
ÓÐÁË HadesDB ÒÔºó£¬ÎÒÃÇÄܸ³Óè´úÂëÓïÒå·ÖÎö¸ü´óµÄÏëÏó¿Õ¼ä¡£±ÈÈ磬¿ÉÒÔÀûÓà HadesDB ÖÆ×÷
Web ÏîÄ¿£¬Í¨¹ý Web Ò³ÃæËÑË÷¡¢²éѯÎÒÃÇËùÐèÒªÖªµÀµÄÓïÒåÐÅÏ¢ºÍ·ÖÎöÊý¾Ý¡£
×ܽá
Hades ×÷Ϊ´óÖÚµãÆÀÒÆ¶¯Ñз¢µÄ»ù´¡Éèʩ֮һ£¬ÔÚʵ¼ùÖеõ½Á˹㷺µÄÓ¦Óã¬Îª´óÐÍ App ÏîÄ¿µÄÈÕ³£Î¬»¤¡¢´úÂë·ÖÎöÌṩ֧³Ö¡£»ùÓÚ
HadesModel µÄ¾²Ì¬·ÖÎöÒ×ÉÏÊÖ£¬¿ª·¢½ÓÈë³É±¾µÍ£¬Äܹ»Àí½â´úÂëÓïÒ壬¾ß±¸È«¾Ö·ÖÎöÄÜÁ¦µÈÖî¶àÓŵ㡣
×îºó£¬ÎÒÃÇҲϣÍû Hades µÄÉè¼ÆÊǸ³Óè´´ÔìÄÜÁ¦µÄÄÜÁ¦£¬¶ø²»½ö½öÊÇ×÷Ϊ´«Í³ÒâÒåÉ쵀 Lint ¸¨Öú¹¤¾ß£¬ÕâÒ²ÊÇÎÒÃÇΪʲô²»È¡ÃûΪ¡°¹¤¾ß¡±£¬¶øÊdzÆÖ®Îª¡°¿ò¼Ü¡±µÄÔÒò¡£µ±È»£¬»ùÓÚ
Hades ÎÒÃÇÒ²ÊÇÄܹ»ºÜ·½±ãµØÖÆ×÷³ö Lint ¹¤¾ßµÄ¡£
|