1+ using System . Linq ;
12using Microsoft . CodeAnalysis ;
23using Semmle . Extraction . Kinds ;
34
@@ -11,33 +12,74 @@ public Expression Expr
1112 private set ;
1213 }
1314
14- public ImplicitCast ( ExpressionNodeInfo info )
15+ private ImplicitCast ( ExpressionNodeInfo info )
1516 : base ( new ExpressionInfo ( info . Context , info . ConvertedType , info . Location , ExprKind . CAST , info . Parent , info . Child , true , info . ExprValue ) )
1617 {
1718 Expr = Factory . Create ( new ExpressionNodeInfo ( Context , info . Node , this , 0 ) ) ;
1819 }
1920
20- public ImplicitCast ( ExpressionNodeInfo info , IMethodSymbol method )
21+ private ImplicitCast ( ExpressionNodeInfo info , IMethodSymbol method )
2122 : base ( new ExpressionInfo ( info . Context , info . ConvertedType , info . Location , ExprKind . OPERATOR_INVOCATION , info . Parent , info . Child , true , info . ExprValue ) )
2223 {
2324 Expr = Factory . Create ( info . SetParent ( this , 0 ) ) ;
2425
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+ {
2538 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+ }
2875 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+ }
3080 }
3181
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.
4183 public static Expression Create ( ExpressionNodeInfo info )
4284 {
4385 var resolvedType = info . ResolvedType ;
0 commit comments