mirror of
https://github.com/github/codeql.git
synced 2025-12-17 01:03:14 +01:00
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.
This commit is contained in:
@@ -45,20 +45,22 @@ string getKind(MemberDeclaration m) {
|
||||
/**
|
||||
* A call-signature that originates from a MethodSignature in the AST.
|
||||
*/
|
||||
private class MethodCallSig extends CallSignatureType {
|
||||
string name;
|
||||
private class MethodCallSig extends Function {
|
||||
private MethodSignature signature;
|
||||
|
||||
MethodCallSig() {
|
||||
exists(MethodSignature sig |
|
||||
this = sig.getBody().getCallSignature() and
|
||||
name = sig.getName()
|
||||
)
|
||||
MethodCallSig() { this = signature.getBody() }
|
||||
|
||||
int getNumOptionalParameter() {
|
||||
result = count(Parameter p | p = this.getParameter(_) and p.isDeclaredOptional())
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the name of any member that has this signature.
|
||||
*/
|
||||
string getName() { result = name }
|
||||
int getNumRequiredParameter() {
|
||||
result = count(Parameter p | p = this.getParameter(_) and not p.isDeclaredOptional())
|
||||
}
|
||||
|
||||
SignatureKind getKind() { result = SignatureKind::function() }
|
||||
|
||||
TypeExpr getTypeParameterBound(int i) { result = this.getTypeParameter(i).getBound() }
|
||||
}
|
||||
|
||||
pragma[noinline]
|
||||
@@ -75,6 +77,7 @@ private MethodCallSig getMethodCallSigWithFingerprint(
|
||||
/**
|
||||
* Holds if the two call signatures could be overloads of each other and have the same parameter types.
|
||||
*/
|
||||
pragma[inline]
|
||||
predicate matchingCallSignature(MethodCallSig method, MethodCallSig other) {
|
||||
other =
|
||||
getMethodCallSigWithFingerprint(method.getName(), method.getNumOptionalParameter(),
|
||||
@@ -109,6 +112,16 @@ private MethodSignature getMethodSignatureWithFingerprint(
|
||||
result.getBody().getNumParameter() = numParameters
|
||||
}
|
||||
|
||||
bindingset[t1, t2]
|
||||
pragma[inline_late]
|
||||
private predicate sameType(TypeExpr t1, TypeExpr t2) {
|
||||
t1.(PredefinedTypeExpr).getName() = t2.(PredefinedTypeExpr).getName()
|
||||
or
|
||||
t1 instanceof ThisTypeExpr and t2 instanceof ThisTypeExpr
|
||||
or
|
||||
t1.(LocalTypeAccess).getLocalTypeName() = t2.(LocalTypeAccess).getLocalTypeName()
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if the two method signatures are overloads of each other and have the same parameter types.
|
||||
*/
|
||||
@@ -122,14 +135,13 @@ predicate signaturesMatch(MethodSignature method, MethodSignature other) {
|
||||
not exists(method.getBody().getThisTypeAnnotation()) and
|
||||
not exists(other.getBody().getThisTypeAnnotation())
|
||||
or
|
||||
method.getBody().getThisTypeAnnotation().getType() =
|
||||
other.getBody().getThisTypeAnnotation().getType()
|
||||
sameType(method.getBody().getThisTypeAnnotation(), other.getBody().getThisTypeAnnotation())
|
||||
) and
|
||||
// The types are compared in matchingCallSignature. This is a consistency check that the textual representation of the type-annotations are somewhat similar.
|
||||
forall(int i | i in [0 .. -1 + method.getBody().getNumParameter()] |
|
||||
getParameterTypeAnnotation(method, i) = getParameterTypeAnnotation(other, i)
|
||||
) and
|
||||
matchingCallSignature(method.getBody().getCallSignature(), other.getBody().getCallSignature())
|
||||
matchingCallSignature(method.getBody(), other.getBody())
|
||||
}
|
||||
|
||||
from ClassOrInterface decl, string name, MethodSignature previous, MethodSignature unreachable
|
||||
|
||||
@@ -1,5 +1,2 @@
|
||||
| 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 |
|
||||
| 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 |
|
||||
| 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 |
|
||||
| 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 |
|
||||
| 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 |
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
declare class Foobar {
|
||||
method(foo: number): string;
|
||||
method(foo: number): number; // $ Alert
|
||||
method(foo: number): number; // $ MISSING: Alert
|
||||
|
||||
types1<T>(): T[]
|
||||
types1(): any[] // $ Alert
|
||||
@@ -12,7 +12,7 @@ declare class Foobar {
|
||||
types3<T extends string>(t: T): number
|
||||
|
||||
on(event: string, fn?: (event?: any, ...args: any[]) => void): Function;
|
||||
on(event: string, fn?: (event?: any, ...args: any[]) => void): Function; // $ Alert
|
||||
on(event: string, fn?: (event?: any, ...args: any[]) => void): Function; // $ MISSING: Alert
|
||||
|
||||
foo(this: string): string;
|
||||
foo(this: number): number;
|
||||
@@ -24,7 +24,7 @@ declare class Foobar {
|
||||
|
||||
declare class Base {
|
||||
method(foo: number): string;
|
||||
method(foo: number): number; // $ Alert
|
||||
method(foo: number): number; // $ MISSING: Alert
|
||||
|
||||
overRiddenInSub(): string;
|
||||
overRiddenInSub(): number;
|
||||
|
||||
Reference in New Issue
Block a user