11using EmmyLua . CodeAnalysis . Type ;
22using EmmyLua . CodeAnalysis . Type . Manager ;
3+ using EmmyLua . CodeAnalysis . Type . Manager . TypeInfo ;
34
45namespace EmmyLua . CodeAnalysis . Compilation . Search ;
56
67public class SameTypeInfer ( SearchContext context )
78{
89 private LuaTypeManager TypeManager => context . Compilation . TypeManager ;
910
11+ private Dictionary < SameTypeKey , SameTypeResult > SameTypeCaches { get ; } = new ( ) ;
12+
13+ enum SameTypeResult
14+ {
15+ NoAnswer ,
16+ True ,
17+ False ,
18+ }
19+
20+ private record struct SameTypeKey ( TypeInfo Left , TypeInfo Right ) ;
21+
1022 public bool IsSameType ( LuaType ? left , LuaType ? right )
1123 {
1224 if ( left is null || right is null )
@@ -21,6 +33,8 @@ private bool InnerSameTypeOf(LuaType left, LuaType right)
2133 {
2234 switch ( ( left , right ) )
2335 {
36+ case ( LuaGenericType leftGenericType , LuaGenericType rightGenericType ) :
37+ return IsSameTypeOfGenericType ( leftGenericType , rightGenericType ) ;
2438 case ( LuaNamedType leftNamedType , LuaNamedType rightNamedType ) :
2539 return IsSameTypeOfNamedType ( leftNamedType , rightNamedType ) ;
2640 case ( LuaArrayType leftArrayType , LuaArrayType rightArrayType ) :
@@ -32,8 +46,72 @@ private bool InnerSameTypeOf(LuaType left, LuaType right)
3246 return false ;
3347 }
3448
49+ private bool IsSameTypeOfGenericType ( LuaGenericType left , LuaGenericType right )
50+ {
51+ if ( ! IsSameTypeOfNamedType ( left , right ) )
52+ {
53+ return false ;
54+ }
55+
56+ if ( left . GenericArgs . Count != right . GenericArgs . Count )
57+ {
58+ return false ;
59+ }
60+
61+ for ( var i = 0 ; i < left . GenericArgs . Count ; i ++ )
62+ {
63+ if ( ! IsSameType ( left . GenericArgs [ i ] , right . GenericArgs [ i ] ) )
64+ {
65+ return false ;
66+ }
67+ }
68+
69+ return true ;
70+ }
71+
3572 private bool IsSameTypeOfNamedType ( LuaNamedType left , LuaNamedType right )
3673 {
37- return context . Compilation . TypeManager . IsSameType ( left , right ) ;
74+ if ( left . DocumentId == right . DocumentId && left . Name == right . Name )
75+ {
76+ return true ;
77+ }
78+
79+ var leftTypeInfo = TypeManager . FindTypeInfo ( left ) ;
80+ if ( leftTypeInfo is null )
81+ {
82+ return false ;
83+ }
84+
85+ var rightTypeInfo = TypeManager . FindTypeInfo ( right ) ;
86+ if ( rightTypeInfo is null )
87+ {
88+ return false ;
89+ }
90+
91+ if ( leftTypeInfo == rightTypeInfo )
92+ {
93+ return true ;
94+ }
95+
96+ var key = new SameTypeKey ( leftTypeInfo , rightTypeInfo ) ;
97+ if ( SameTypeCaches . TryGetValue ( key , out var result ) )
98+ {
99+ return result == SameTypeResult . True ;
100+ }
101+
102+ SameTypeCaches [ key ] = SameTypeResult . NoAnswer ;
103+
104+ var sameType = false ;
105+ if ( leftTypeInfo . Kind == NamedTypeKind . Alias )
106+ {
107+ sameType = IsSameType ( leftTypeInfo . BaseType , right ) ;
108+ }
109+ else if ( rightTypeInfo . Kind == NamedTypeKind . Alias )
110+ {
111+ sameType = IsSameType ( left , rightTypeInfo . BaseType ) ;
112+ }
113+
114+ SameTypeCaches [ key ] = sameType ? SameTypeResult . True : SameTypeResult . False ;
115+ return sameType ;
38116 }
39117}
0 commit comments