1- using EmmyLua . CodeAnalysis . Compilation . Search ;
1+ using EmmyLua . CodeAnalysis . Common ;
2+ using EmmyLua . CodeAnalysis . Compilation . Declaration ;
3+ using EmmyLua . CodeAnalysis . Compilation . Search ;
24using EmmyLua . CodeAnalysis . Compilation . Type ;
35using EmmyLua . CodeAnalysis . Syntax . Node . SyntaxNodes ;
46
@@ -12,19 +14,42 @@ public static void InferByExpr(
1214 TypeSubstitution substitution ,
1315 SearchContext context )
1416 {
15- if ( type is LuaTemplateType templateType && expr is LuaLiteralExprSyntax
16- {
17- Literal : LuaStringToken { } stringToken
18- } )
17+ if ( SpecialInferByExpr ( type , expr , substitution , context ) )
1918 {
20- substitution . Add ( templateType . TemplateName , new LuaNamedType ( templateType . PrefixName + stringToken . Value ) ) ;
2119 return ;
2220 }
2321
2422 var exprType = context . InferAndUnwrap ( expr ) ;
2523 InferByType ( type , exprType , substitution , context ) ;
2624 }
2725
26+ private static bool SpecialInferByExpr (
27+ LuaType type ,
28+ LuaExprSyntax expr ,
29+ TypeSubstitution substitution ,
30+ SearchContext context )
31+ {
32+ if ( type is LuaTemplateType templateType && expr is LuaLiteralExprSyntax
33+ {
34+ Literal : LuaStringToken { } stringToken1
35+ } )
36+ {
37+ substitution . Add ( templateType . TemplateName , new LuaNamedType ( templateType . PrefixName + stringToken1 . Value ) ) ;
38+ return true ;
39+ }
40+
41+ if ( type is LuaGenericType { Name : "strFmt" } genericType && expr is LuaLiteralExprSyntax
42+ {
43+ Literal : LuaStringToken { } stringToken2
44+ } )
45+ {
46+ StrFmtInstantiateByString ( genericType , stringToken2 . Value , substitution , context ) ;
47+ return true ;
48+ }
49+
50+ return false ;
51+ }
52+
2853 public static void InferByExpandTypeAndExprs (
2954 LuaExpandType expandType ,
3055 IEnumerable < LuaExprSyntax > expr ,
@@ -320,4 +345,70 @@ private static void TupleTypeInstantiateByType(
320345 }
321346 }
322347 }
348+
349+ private static void StrFmtInstantiateByString (
350+ LuaGenericType genericType ,
351+ string fmt ,
352+ TypeSubstitution substitution ,
353+ SearchContext context )
354+ {
355+ var firstTemp = genericType . GenericArgs . FirstOrDefault ( ) ;
356+ if ( firstTemp is not LuaNamedType templateName )
357+ {
358+ return ;
359+ }
360+
361+ var spreadParameter = new List < IDeclaration > ( ) ;
362+ for ( var i = 0 ; i < fmt . Length ; i ++ )
363+ {
364+ var ch = fmt [ i ] ;
365+ if ( fmt [ i ] == '%' )
366+ {
367+ if ( i + 1 < fmt . Length )
368+ {
369+ var nextCh = fmt [ i + 1 ] ;
370+ if ( nextCh == '%' )
371+ {
372+ i ++ ;
373+ }
374+ else
375+ {
376+ var index = i + 1 ;
377+ while ( index < fmt . Length && char . IsDigit ( fmt [ index ] ) )
378+ {
379+ index ++ ;
380+ }
381+
382+ if ( index < fmt . Length )
383+ {
384+ var type = fmt [ index ] ;
385+ if ( type is 's' or 'q' )
386+ {
387+ spreadParameter . Add ( new LuaDeclaration (
388+ $ "%{ type } ",
389+ new VirtualInfo ( Builtin . Any )
390+ ) ) ;
391+ }
392+ else if ( type is 'c' or 'd' or 'i' or 'u' or 'x' or 'X' or 'o' )
393+ {
394+ spreadParameter . Add ( new LuaDeclaration (
395+ $ "%{ type } ",
396+ new VirtualInfo ( Builtin . Integer )
397+ ) ) ;
398+ }
399+ else if ( type is 'A' or 'a' or 'E' or 'e' or 'f' or 'G' or 'g' )
400+ {
401+ spreadParameter . Add ( new LuaDeclaration (
402+ $ "%{ type } ",
403+ new VirtualInfo ( Builtin . Number )
404+ ) ) ;
405+ }
406+ }
407+ }
408+ }
409+ }
410+ }
411+
412+ substitution . AddSpreadParameter ( templateName . Name , spreadParameter ) ;
413+ }
323414}
0 commit comments