33using Microsoft . CodeAnalysis . CSharp . Syntax ;
44using Semmle . Extraction . CSharp . Populators ;
55using Semmle . Extraction . Kinds ;
6- using Semmle . Extraction . Entities ;
6+ using System . Collections . Generic ;
7+ using System . Linq ;
8+ using System . Collections . Immutable ;
79
810namespace Semmle . Extraction . CSharp . Entities . Expressions
911{
@@ -47,69 +49,91 @@ private static VariableDeclaration CreateSingle(Context cx, DeclarationExpressio
4749 /// Create a tuple expression representing a parenthesized variable declaration.
4850 /// That is, we consider `var (x, y) = ...` to be equivalent to `(var x, var y) = ...`.
4951 /// </summary>
50- public static Expression CreateParenthesized ( Context cx , DeclarationExpressionSyntax node , ParenthesizedVariableDesignationSyntax designation , IExpressionParentEntity parent , int child )
52+ public static Expression CreateParenthesized ( Context cx , DeclarationExpressionSyntax node , ParenthesizedVariableDesignationSyntax designation , IExpressionParentEntity parent , int child , INamedTypeSymbol ? t )
5153 {
52- AnnotatedTypeSymbol ? type = null ; // Should ideally be a corresponding tuple type
54+ var type = t is null ? ( AnnotatedTypeSymbol ? ) null : new AnnotatedTypeSymbol ( t , t . NullableAnnotation ) ;
5355 var tuple = new Expression ( new ExpressionInfo ( cx , type , cx . CreateLocation ( node . GetLocation ( ) ) , ExprKind . TUPLE , parent , child , false , null ) ) ;
5456
5557 cx . Try ( null , null , ( ) =>
5658 {
57- var child0 = 0 ;
58- foreach ( var variable in designation . Variables )
59- Create ( cx , node , variable , tuple , child0 ++ ) ;
59+ for ( var child0 = 0 ; child0 < designation . Variables . Count ; child0 ++ )
60+ {
61+ Create ( cx , node , designation . Variables [ child0 ] , tuple , child0 , t ? . TypeArguments [ child0 ] as INamedTypeSymbol ) ;
62+ }
6063 } ) ;
6164
6265 return tuple ;
6366 }
6467
6568 public static Expression CreateParenthesized ( Context cx , VarPatternSyntax varPattern , ParenthesizedVariableDesignationSyntax designation , IExpressionParentEntity parent , int child )
6669 {
67- AnnotatedTypeSymbol ? type = null ; // Should ideally be a corresponding tuple type
68- var tuple = new Expression ( new ExpressionInfo ( cx , type , cx . CreateLocation ( varPattern . GetLocation ( ) ) , ExprKind . TUPLE , parent , child , false , null ) ) ;
70+ var tuple = new Expression (
71+ new ExpressionInfo ( cx , null , cx . CreateLocation ( varPattern . GetLocation ( ) ) , ExprKind . TUPLE , parent , child , false , null ) ,
72+ shouldPopulate : false ) ;
6973
74+ var elementTypes = new List < ITypeSymbol ? > ( ) ;
7075 cx . Try ( null , null , ( ) =>
7176 {
7277 var child0 = 0 ;
7378 foreach ( var variable in designation . Variables )
7479 {
80+ Expression sub ;
7581 switch ( variable )
7682 {
7783 case ParenthesizedVariableDesignationSyntax paren :
78- CreateParenthesized ( cx , varPattern , paren , tuple , child0 ++ ) ;
84+ sub = CreateParenthesized ( cx , varPattern , paren , tuple , child0 ++ ) ;
7985 break ;
8086 case SingleVariableDesignationSyntax single :
8187 if ( cx . GetModel ( variable ) . GetDeclaredSymbol ( single ) is ILocalSymbol local )
8288 {
8389 var decl = Create ( cx , variable , local . GetAnnotatedType ( ) , tuple , child0 ++ ) ;
8490 var l = LocalVariable . Create ( cx , local ) ;
8591 l . PopulateManual ( decl , true ) ;
92+ sub = decl ;
8693 }
8794 else
8895 {
8996 throw new InternalError ( single , "Failed to access local variable" ) ;
9097 }
9198 break ;
9299 case DiscardDesignationSyntax discard :
93- new Discard ( cx , discard , tuple , child0 ++ ) ;
100+ sub = new Discard ( cx , discard , tuple , child0 ++ ) ;
101+ if ( ! sub . Type . HasValue || sub . Type . Value . Symbol is null )
102+ {
103+ // The type is only updated in memory, it will not be written to the trap file.
104+ sub . SetType ( cx . Compilation . GetSpecialType ( SpecialType . System_Object ) ) ;
105+ }
94106 break ;
95107 default :
96108 throw new InternalError ( variable , "Unhandled designation type" ) ;
97109 }
110+
111+ elementTypes . Add ( sub . Type . HasValue && sub . Type . Value . Symbol ? . Kind != SymbolKind . ErrorType
112+ ? sub . Type . Value . Symbol
113+ : null ) ;
98114 }
99115 } ) ;
100116
117+ INamedTypeSymbol ? tupleType = null ;
118+ if ( ! elementTypes . Any ( et => et is null ) )
119+ {
120+ tupleType = cx . Compilation . CreateTupleTypeSymbol ( elementTypes . ToImmutableArray ( ) ! ) ;
121+ }
122+
123+ tuple . SetType ( tupleType ) ;
124+ tuple . TryPopulate ( ) ;
125+
101126 return tuple ;
102127 }
103128
104-
105- private static Expression Create ( Context cx , DeclarationExpressionSyntax node , VariableDesignationSyntax ? designation , IExpressionParentEntity parent , int child )
129+ private static Expression Create ( Context cx , DeclarationExpressionSyntax node , VariableDesignationSyntax ? designation , IExpressionParentEntity parent , int child , INamedTypeSymbol ? declarationType )
106130 {
107131 switch ( designation )
108132 {
109133 case SingleVariableDesignationSyntax single :
110134 return CreateSingle ( cx , node , single , parent , child ) ;
111135 case ParenthesizedVariableDesignationSyntax paren :
112- return CreateParenthesized ( cx , node , paren , parent , child ) ;
136+ return CreateParenthesized ( cx , node , paren , parent , child , declarationType ) ;
113137 case DiscardDesignationSyntax discard :
114138 var type = cx . GetType ( discard ) ;
115139 return Create ( cx , node , type , parent , child ) ;
@@ -120,7 +144,7 @@ private static Expression Create(Context cx, DeclarationExpressionSyntax node, V
120144 }
121145
122146 public static Expression Create ( Context cx , DeclarationExpressionSyntax node , IExpressionParentEntity parent , int child ) =>
123- Create ( cx , node , node . Designation , parent , child ) ;
147+ Create ( cx , node , node . Designation , parent , child , cx . GetTypeInfo ( node ) . Type . DisambiguateType ( ) as INamedTypeSymbol ) ;
124148
125149 public static VariableDeclaration Create ( Context cx , CSharpSyntaxNode c , AnnotatedTypeSymbol ? type , IExpressionParentEntity parent , int child ) =>
126150 new VariableDeclaration ( new ExpressionInfo ( cx , type , cx . CreateLocation ( c . FixedLocation ( ) ) , ExprKind . LOCAL_VAR_DECL , parent , child , false , null ) ) ;
0 commit comments