@@ -38,13 +38,19 @@ private predicate parsedRawMethodName(string rawName, string name, string argLab
3838 )
3939}
4040
41- private string getNameFromExpr ( Expr e ) {
41+ private string getSimpleNameFromExpr ( Expr e ) {
4242 result = e .( Identifier ) .getValue ( )
4343 or
4444 result = e .( MemberAccessExpr ) .getMemberName ( )
4545}
4646
47- private string getCalleeName ( CallExpr call ) { result = getNameFromExpr ( call .getCallee ( ) ) }
47+ private string getQualifiedNameFromExpr ( Expr e ) {
48+ result = e .( Identifier ) .getValue ( )
49+ or
50+ exists ( MemberAccessExpr access | e = access |
51+ result = getQualifiedNameFromExpr ( access .getBase ( ) ) + "." + access .getMemberName ( )
52+ )
53+ }
4854
4955private string getArgLabelsFromCall ( CallExpr call ) {
5056 result =
@@ -64,8 +70,14 @@ private string getArgLabelsFromCall(CallExpr call) {
6470}
6571
6672pragma [ nomagic]
67- private predicate callSelector ( CallExpr call , string name , string argLabels ) {
68- name = getCalleeName ( call ) and
73+ private predicate methodCallSelector ( CallExpr call , string name , string argLabels ) {
74+ name = getSimpleNameFromExpr ( call .getCallee ( ) ) and
75+ argLabels = getArgLabelsFromCall ( call )
76+ }
77+
78+ pragma [ nomagic]
79+ private predicate constructorCallSelector ( CallExpr call , string name , string argLabels ) {
80+ name = getQualifiedNameFromExpr ( call .getCallee ( ) ) and
6981 argLabels = getArgLabelsFromCall ( call )
7082}
7183
@@ -74,7 +86,7 @@ private import codeql.unified.internal.NameBinding as NameBinding
7486private predicate isSubclassOfType ( ClassLikeDeclaration cls , string typeName ) {
7587 typeName = any ( Selector s ) .getTypeString ( ) and
7688 (
77- getNameFromExpr ( cls .getABaseType ( ) .getType ( ) ) = typeName
89+ getQualifiedNameFromExpr ( cls .getABaseType ( ) .getType ( ) ) = typeName
7890 or
7991 isSubclassOfType ( cls .getABaseClass ( ) , typeName )
8092 )
@@ -146,26 +158,26 @@ private class Selector extends TSelector {
146158 ")" + this .getArgTypes ( )
147159 }
148160
149- /** Holds if `name,argLabels` should be used to join with `callSelector`. */
150- private predicate effectiveCallSelector ( string name , string argLabels ) {
161+ /** Holds if `name,argLabels` should be used to join with `methodCallSelector`. */
162+ pragma [ nomagic]
163+ private predicate matchesMethodCallSelector ( string name , string argLabels ) {
151164 this = MkSelector ( _, _, name , argLabels , _) and
152165 name != "init"
153- or
154- // For "init" models there are two issues at play:
155- // - Constructor calls do not mention "init", they just mention the type name, e.g. `String(...)` not `String.init(...)`.
156- // - The name "init" is too common to match on anyway. It is more precise to match on the type name in this case.
157- //
158- // So to wire up "init" calls correctly, we just use the type name as the method name.
159- //
160- // TODO: does not work for compound access like `String.Index(...)` where the type is `String.Index` but the
161- // call selector only uses `Index`.
166+ }
167+
168+ /** Holds if `name,argLabels` should be used to join with `constructorCallSelector`. */
169+ pragma [ nomagic]
170+ private predicate matchesConstructorCallSelector ( string name , string argLabels ) {
162171 this = MkSelector ( name , _, "init" , argLabels , _)
163172 }
164173
165174 predicate matchesCall ( CallExpr call ) {
166175 exists ( string name , string argLabels |
167- this .effectiveCallSelector ( name , argLabels ) and
168- callSelector ( call , name , argLabels )
176+ this .matchesMethodCallSelector ( name , argLabels ) and
177+ methodCallSelector ( call , name , argLabels )
178+ or
179+ this .matchesConstructorCallSelector ( name , argLabels ) and
180+ constructorCallSelector ( call , name , argLabels )
169181 )
170182 }
171183
0 commit comments