@@ -8,7 +8,6 @@ import Stmt
8
8
import Type
9
9
import exprs.Call
10
10
private import commons.QualifiedName
11
- private import dotnet
12
11
private import semmle.code.csharp.ExprOrStmtParent
13
12
private import semmle.code.csharp.metrics.Complexity
14
13
private import TypeRef
@@ -21,8 +20,73 @@ private import TypeRef
21
20
* an anonymous function (`AnonymousFunctionExpr`), or a local function
22
21
* (`LocalFunction`).
23
22
*/
24
- class Callable extends DotNet:: Callable , Parameterizable , ExprOrStmtParent , @callable {
25
- override Type getReturnType ( ) { none ( ) }
23
+ class Callable extends Parameterizable , ExprOrStmtParent , @callable {
24
+ pragma [ noinline]
25
+ private string getDeclaringTypeLabel ( ) { result = this .getDeclaringType ( ) .getLabel ( ) }
26
+
27
+ pragma [ noinline]
28
+ private string getParameterTypeLabelNonGeneric ( int p ) {
29
+ not this instanceof Generic and
30
+ result = this .getParameter ( p ) .getType ( ) .getLabel ( )
31
+ }
32
+
33
+ language [ monotonicAggregates]
34
+ pragma [ nomagic]
35
+ private string getMethodParamListNonGeneric ( ) {
36
+ result =
37
+ concat ( int p |
38
+ p in [ 0 .. this .getNumberOfParameters ( ) - 1 ]
39
+ |
40
+ this .getParameterTypeLabelNonGeneric ( p ) , "," order by p
41
+ )
42
+ }
43
+
44
+ pragma [ noinline]
45
+ private string getParameterTypeLabelGeneric ( int p ) {
46
+ this instanceof Generic and
47
+ result = this .getParameter ( p ) .getType ( ) .getLabel ( )
48
+ }
49
+
50
+ language [ monotonicAggregates]
51
+ pragma [ nomagic]
52
+ private string getMethodParamListGeneric ( ) {
53
+ result =
54
+ concat ( int p |
55
+ p in [ 0 .. this .getNumberOfParameters ( ) - 1 ]
56
+ |
57
+ this .getParameterTypeLabelGeneric ( p ) , "," order by p
58
+ )
59
+ }
60
+
61
+ pragma [ noinline]
62
+ private string getLabelNonGeneric ( ) {
63
+ not this instanceof Generic and
64
+ result =
65
+ this .getReturnTypeLabel ( ) + " " + this .getDeclaringTypeLabel ( ) + "." +
66
+ this .getUndecoratedName ( ) + "(" + this .getMethodParamListNonGeneric ( ) + ")"
67
+ }
68
+
69
+ pragma [ noinline]
70
+ private string getLabelGeneric ( ) {
71
+ result =
72
+ this .getReturnTypeLabel ( ) + " " + this .getDeclaringTypeLabel ( ) + "." +
73
+ this .getUndecoratedName ( ) + getGenericsLabel ( this ) + "(" + this .getMethodParamListGeneric ( ) +
74
+ ")"
75
+ }
76
+
77
+ final override string getLabel ( ) {
78
+ result = this .getLabelNonGeneric ( ) or
79
+ result = this .getLabelGeneric ( )
80
+ }
81
+
82
+ private string getReturnTypeLabel ( ) {
83
+ result = this .getReturnType ( ) .getLabel ( )
84
+ or
85
+ not exists ( this .getReturnType ( ) ) and result = "System.Void"
86
+ }
87
+
88
+ /** Gets the return type of this callable. */
89
+ Type getReturnType ( ) { none ( ) }
26
90
27
91
/** Gets the annotated return type of this callable. */
28
92
final AnnotatedType getAnnotatedReturnType ( ) { result .appliesTo ( this ) }
@@ -65,7 +129,8 @@ class Callable extends DotNet::Callable, Parameterizable, ExprOrStmtParent, @cal
65
129
result = this .getExpressionBody ( )
66
130
}
67
131
68
- override predicate hasBody ( ) { exists ( this .getBody ( ) ) }
132
+ /** Holds if this callable has a body or an implementation. */
133
+ predicate hasBody ( ) { exists ( this .getBody ( ) ) }
69
134
70
135
/**
71
136
* Holds if this callable has a non-empty body. That is, either it has
@@ -196,7 +261,8 @@ class Callable extends DotNet::Callable, Parameterizable, ExprOrStmtParent, @cal
196
261
)
197
262
}
198
263
199
- override predicate canReturn ( DotNet:: Expr e ) {
264
+ /** Holds if this callable can return expression `e`. */
265
+ predicate canReturn ( Expr e ) {
200
266
exists ( ReturnStmt ret | ret .getEnclosingCallable ( ) = this | e = ret .getExpr ( ) )
201
267
or
202
268
e = this .getExpressionBody ( ) and
@@ -218,8 +284,6 @@ class Callable extends DotNet::Callable, Parameterizable, ExprOrStmtParent, @cal
218
284
219
285
/** Gets a `Call` that has this callable as a target. */
220
286
Call getACall ( ) { this = result .getTarget ( ) }
221
-
222
- override Parameter getAParameter ( ) { result = Parameterizable .super .getAParameter ( ) }
223
287
}
224
288
225
289
/**
@@ -325,7 +389,7 @@ class ExtensionMethod extends Method {
325
389
* }
326
390
* ```
327
391
*/
328
- class Constructor extends DotNet :: Constructor , Callable , Member , Attributable , @constructor {
392
+ class Constructor extends Callable , Member , Attributable , @constructor {
329
393
override string getName ( ) { constructors ( this , result , _, _) }
330
394
331
395
override Type getReturnType ( ) {
@@ -435,7 +499,7 @@ class PrimaryConstructor extends Constructor {
435
499
* }
436
500
* ```
437
501
*/
438
- class Destructor extends DotNet :: Destructor , Callable , Member , Attributable , @destructor {
502
+ class Destructor extends Callable , Member , Attributable , @destructor {
439
503
override string getName ( ) { destructors ( this , result , _, _) }
440
504
441
505
override Type getReturnType ( ) {
@@ -497,10 +561,33 @@ class Operator extends Callable, Member, Attributable, Overridable, @operator {
497
561
override Parameter getRawParameter ( int i ) { result = this .getParameter ( i ) }
498
562
}
499
563
564
+ pragma [ nomagic]
565
+ private ValueOrRefType getARecordBaseType ( ValueOrRefType t ) {
566
+ exists ( Callable c |
567
+ c .hasName ( "<Clone>$" ) and
568
+ c .getNumberOfParameters ( ) = 0 and
569
+ t = c .getDeclaringType ( ) and
570
+ result = t
571
+ )
572
+ or
573
+ result = getARecordBaseType ( t ) .getABaseType ( )
574
+ }
575
+
500
576
/** A clone method on a record. */
501
- class RecordCloneMethod extends Method , DotNet:: RecordCloneCallable {
502
- override Constructor getConstructor ( ) {
503
- result = DotNet:: RecordCloneCallable .super .getConstructor ( )
577
+ class RecordCloneMethod extends Method {
578
+ RecordCloneMethod ( ) {
579
+ this .hasName ( "<Clone>$" ) and
580
+ this .getNumberOfParameters ( ) = 0 and
581
+ this .getReturnType ( ) = getARecordBaseType ( this .getDeclaringType ( ) ) and
582
+ this .( Member ) .isPublic ( ) and
583
+ not this .( Member ) .isStatic ( )
584
+ }
585
+
586
+ /** Gets the constructor that this clone method calls. */
587
+ Constructor getConstructor ( ) {
588
+ result .getDeclaringType ( ) = this .getDeclaringType ( ) and
589
+ result .getNumberOfParameters ( ) = 1 and
590
+ result .getParameter ( 0 ) .getType ( ) = this .getDeclaringType ( )
504
591
}
505
592
}
506
593
0 commit comments