Skip to content

Commit fb92d9b

Browse files
committed
JS: Update type usage in UnreachableMethodOverloads
This query depended on the cons-hashing performed by type extraction to determine if two types are the same. This is not trivial to restore, but not important enough to reimplement right now, so for now just simplifying the query's ability to recognise that two types are the same.
1 parent 8b2a424 commit fb92d9b

File tree

3 files changed

+30
-21
lines changed

3 files changed

+30
-21
lines changed

javascript/ql/src/Declarations/UnreachableMethodOverloads.ql

Lines changed: 27 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -45,20 +45,22 @@ string getKind(MemberDeclaration m) {
4545
/**
4646
* A call-signature that originates from a MethodSignature in the AST.
4747
*/
48-
private class MethodCallSig extends CallSignatureType {
49-
string name;
50-
51-
MethodCallSig() {
52-
exists(MethodSignature sig |
53-
this = sig.getBody().getCallSignature() and
54-
name = sig.getName()
55-
)
48+
private class MethodCallSig extends Function {
49+
private MethodSignature signature;
50+
51+
MethodCallSig() { this = signature.getBody() }
52+
53+
int getNumOptionalParameter() {
54+
result = count(Parameter p | p = this.getParameter(_) and p.isDeclaredOptional())
55+
}
56+
57+
int getNumRequiredParameter() {
58+
result = count(Parameter p | p = this.getParameter(_) and not p.isDeclaredOptional())
5659
}
5760

58-
/**
59-
* Gets the name of any member that has this signature.
60-
*/
61-
string getName() { result = name }
61+
SignatureKind getKind() { result = SignatureKind::function() }
62+
63+
TypeExpr getTypeParameterBound(int i) { result = this.getTypeParameter(i).getBound() }
6264
}
6365

6466
pragma[noinline]
@@ -75,6 +77,7 @@ private MethodCallSig getMethodCallSigWithFingerprint(
7577
/**
7678
* Holds if the two call signatures could be overloads of each other and have the same parameter types.
7779
*/
80+
pragma[inline]
7881
predicate matchingCallSignature(MethodCallSig method, MethodCallSig other) {
7982
other =
8083
getMethodCallSigWithFingerprint(method.getName(), method.getNumOptionalParameter(),
@@ -109,6 +112,16 @@ private MethodSignature getMethodSignatureWithFingerprint(
109112
result.getBody().getNumParameter() = numParameters
110113
}
111114

115+
bindingset[t1, t2]
116+
pragma[inline_late]
117+
private predicate sameType(TypeExpr t1, TypeExpr t2) {
118+
t1.(PredefinedTypeExpr).getName() = t2.(PredefinedTypeExpr).getName()
119+
or
120+
t1 instanceof ThisTypeExpr and t2 instanceof ThisTypeExpr
121+
or
122+
t1.(LocalTypeAccess).getLocalTypeName() = t2.(LocalTypeAccess).getLocalTypeName()
123+
}
124+
112125
/**
113126
* Holds if the two method signatures are overloads of each other and have the same parameter types.
114127
*/
@@ -122,14 +135,13 @@ predicate signaturesMatch(MethodSignature method, MethodSignature other) {
122135
not exists(method.getBody().getThisTypeAnnotation()) and
123136
not exists(other.getBody().getThisTypeAnnotation())
124137
or
125-
method.getBody().getThisTypeAnnotation().getType() =
126-
other.getBody().getThisTypeAnnotation().getType()
138+
sameType(method.getBody().getThisTypeAnnotation(), other.getBody().getThisTypeAnnotation())
127139
) and
128140
// The types are compared in matchingCallSignature. This is a consistency check that the textual representation of the type-annotations are somewhat similar.
129141
forall(int i | i in [0 .. -1 + method.getBody().getNumParameter()] |
130142
getParameterTypeAnnotation(method, i) = getParameterTypeAnnotation(other, i)
131143
) and
132-
matchingCallSignature(method.getBody().getCallSignature(), other.getBody().getCallSignature())
144+
matchingCallSignature(method.getBody(), other.getBody())
133145
}
134146

135147
from ClassOrInterface decl, string name, MethodSignature previous, MethodSignature unreachable
Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,2 @@
1-
| tst.ts:3:3:3:30 | method( ... number; | This overload of method() is unreachable, the $@ overload will always be selected. | tst.ts:2:3:2:30 | method( ... string; | previous |
21
| tst.ts:6:3:6:17 | types1(): any[] | This overload of types1() is unreachable, the $@ overload will always be selected. | tst.ts:5:3:5:18 | types1<T>(): T[] | previous |
3-
| tst.ts:15:3:15:74 | on(even ... nction; | This overload of on() is unreachable, the $@ overload will always be selected. | tst.ts:14:3:14:74 | on(even ... nction; | previous |
42
| tst.ts:21:3:21:28 | bar(thi ... number; | This overload of bar() is unreachable, the $@ overload will always be selected. | tst.ts:20:3:20:28 | bar(thi ... string; | previous |
5-
| tst.ts:27:3:27:30 | method( ... number; | This overload of method() is unreachable, the $@ overload will always be selected. | tst.ts:26:3:26:30 | method( ... string; | previous |

javascript/ql/test/query-tests/Declarations/UnreachableOverloads/tst.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
declare class Foobar {
22
method(foo: number): string;
3-
method(foo: number): number; // $ Alert
3+
method(foo: number): number; // $ MISSING: Alert
44

55
types1<T>(): T[]
66
types1(): any[] // $ Alert
@@ -12,7 +12,7 @@ declare class Foobar {
1212
types3<T extends string>(t: T): number
1313

1414
on(event: string, fn?: (event?: any, ...args: any[]) => void): Function;
15-
on(event: string, fn?: (event?: any, ...args: any[]) => void): Function; // $ Alert
15+
on(event: string, fn?: (event?: any, ...args: any[]) => void): Function; // $ MISSING: Alert
1616

1717
foo(this: string): string;
1818
foo(this: number): number;
@@ -24,7 +24,7 @@ declare class Foobar {
2424

2525
declare class Base {
2626
method(foo: number): string;
27-
method(foo: number): number; // $ Alert
27+
method(foo: number): number; // $ MISSING: Alert
2828

2929
overRiddenInSub(): string;
3030
overRiddenInSub(): number;

0 commit comments

Comments
 (0)