1
+ using System . Linq ;
1
2
using Microsoft . CodeAnalysis ;
2
3
using Semmle . Extraction . Kinds ;
3
4
@@ -11,33 +12,74 @@ public Expression Expr
11
12
private set ;
12
13
}
13
14
14
- public ImplicitCast ( ExpressionNodeInfo info )
15
+ private ImplicitCast ( ExpressionNodeInfo info )
15
16
: base ( new ExpressionInfo ( info . Context , info . ConvertedType , info . Location , ExprKind . CAST , info . Parent , info . Child , true , info . ExprValue ) )
16
17
{
17
18
Expr = Factory . Create ( new ExpressionNodeInfo ( Context , info . Node , this , 0 ) ) ;
18
19
}
19
20
20
- public ImplicitCast ( ExpressionNodeInfo info , IMethodSymbol method )
21
+ private ImplicitCast ( ExpressionNodeInfo info , IMethodSymbol method )
21
22
: base ( new ExpressionInfo ( info . Context , info . ConvertedType , info . Location , ExprKind . OPERATOR_INVOCATION , info . Parent , info . Child , true , info . ExprValue ) )
22
23
{
23
24
Expr = Factory . Create ( info . SetParent ( this , 0 ) ) ;
24
25
26
+ AddOperatorCall ( method ) ;
27
+ }
28
+
29
+ private ImplicitCast ( ExpressionInfo info , IMethodSymbol method , object value ) : base ( info )
30
+ {
31
+ Expr = Literal . CreateGenerated ( Context , this , 0 , method . Parameters [ 0 ] . Type , value , info . Location ) ;
32
+
33
+ AddOperatorCall ( method ) ;
34
+ }
35
+
36
+ private void AddOperatorCall ( IMethodSymbol method )
37
+ {
25
38
var target = Method . Create ( Context , method ) ;
26
- if ( target is not null )
27
- Context . TrapWriter . Writer . expr_call ( this , target ) ;
39
+ Context . TrapWriter . Writer . expr_call ( this , target ) ;
40
+ }
41
+
42
+ private static IMethodSymbol ? GetImplicitConversionMethod ( ITypeSymbol type , object value ) =>
43
+ type
44
+ . GetMembers ( )
45
+ . Where ( m =>
46
+ m is IMethodSymbol method &&
47
+ method . GetName ( ) == "op_Implicit" &&
48
+ method . Parameters . Length == 1 &&
49
+ method . Parameters [ 0 ] . Type . Name == value . GetType ( ) . Name
50
+ )
51
+ . Cast < IMethodSymbol > ( )
52
+ . FirstOrDefault ( ) ;
53
+
54
+ // Creates a new generated expression with an implicit cast added, if needed.
55
+ public static Expression CreateGenerated ( Context cx , IExpressionParentEntity parent , int childIndex , ITypeSymbol type , object value ,
56
+ Extraction . Entities . Location location )
57
+ {
58
+ ExpressionInfo create ( ExprKind kind , string ? v ) =>
59
+ new ExpressionInfo (
60
+ cx ,
61
+ AnnotatedTypeSymbol . CreateNotAnnotated ( type ) ,
62
+ location ,
63
+ kind ,
64
+ parent ,
65
+ childIndex ,
66
+ true ,
67
+ v ) ;
68
+
69
+ var method = GetImplicitConversionMethod ( type , value ) ;
70
+ if ( method is not null )
71
+ {
72
+ var info = create ( ExprKind . OPERATOR_INVOCATION , null ) ;
73
+ return new ImplicitCast ( info , method , value ) ;
74
+ }
28
75
else
29
- Context . ModelError ( info . Node , "Failed to resolve target for operator invocation" ) ;
76
+ {
77
+ cx . ModelError ( location , "Failed to resolve target for implicit operator invocation for a parameter default." ) ;
78
+ return new Expression ( create ( ExprKind . UNKNOWN , ValueAsString ( value ) ) ) ;
79
+ }
30
80
}
31
81
32
- /// <summary>
33
- /// Creates a new expression, adding casts as required.
34
- /// </summary>
35
- /// <param name="cx">The extraction context.</param>
36
- /// <param name="node">The expression node.</param>
37
- /// <param name="parent">The parent of the expression.</param>
38
- /// <param name="child">The child number.</param>
39
- /// <param name="type">A type hint.</param>
40
- /// <returns>A new expression.</returns>
82
+ // Creates a new expression, adding casts as required.
41
83
public static Expression Create ( ExpressionNodeInfo info )
42
84
{
43
85
var resolvedType = info . ResolvedType ;
0 commit comments