Skip to content

Commit ec3990c

Browse files
committed
Java: Fix FunctionalInterface.
1 parent 5d58edb commit ec3990c

File tree

2 files changed

+38
-31
lines changed

2 files changed

+38
-31
lines changed

java/ql/lib/semmle/code/java/Type.qll

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -874,6 +874,44 @@ class ClassOrInterface extends RefType, @classorinterface {
874874
}
875875
}
876876

877+
private string getAPublicObjectMethodSignature() {
878+
exists(Method m |
879+
m.getDeclaringType() instanceof TypeObject and
880+
m.isPublic() and
881+
result = m.getSignature()
882+
)
883+
}
884+
885+
private Method getAnAbstractMethod(Interface interface) {
886+
interface.inherits(result) and
887+
result.isAbstract() and
888+
// JLS 9.8, ignore Object methods
889+
not result.getSignature() = getAPublicObjectMethodSignature() and
890+
// Make sure that there is no other non-abstract method
891+
// (e.g. `default`) which overrides the abstract one
892+
not exists(Method m |
893+
interface.inherits(m) and
894+
not m.isAbstract() and
895+
m.overrides(result)
896+
)
897+
}
898+
899+
/**
900+
* A functional interface is an interface that has just one abstract method
901+
* (aside from the methods of Object), and thus represents a single function
902+
* contract.
903+
*
904+
* See JLS 9.8, Functional Interfaces.
905+
*/
906+
class FunctionalInterface extends Interface {
907+
Method run;
908+
909+
FunctionalInterface() { run = unique(Method r | r = getAnAbstractMethod(this)) }
910+
911+
/** Gets the single abstract method of this interface. */
912+
Method getRunMethod() { result = run }
913+
}
914+
877915
/**
878916
* A primitive type.
879917
*

java/ql/lib/semmle/code/java/dispatch/WrappedInvocation.qll

Lines changed: 0 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -6,37 +6,6 @@
66
import java
77
import VirtualDispatch
88

9-
private string getAPublicObjectMethodSignature() {
10-
exists(Method m |
11-
m.getDeclaringType() instanceof TypeObject and
12-
m.isPublic() and
13-
result = m.getSignature()
14-
)
15-
}
16-
17-
private Method getAPotentialRunMethod(Interface i) {
18-
i.inherits(result) and
19-
result.isPublic() and
20-
not result.getSignature() = getAPublicObjectMethodSignature()
21-
}
22-
23-
/**
24-
* A functional interface is an interface that has just one abstract method
25-
* (aside from the methods of Object), and thus represents a single function
26-
* contract.
27-
*
28-
* See JLS 9.8, Functional Interfaces.
29-
*/
30-
class FunctionalInterface extends Interface {
31-
FunctionalInterface() {
32-
1 = strictcount(getAPotentialRunMethod(this)) and
33-
not exists(Method m | this.inherits(m) and m.isDefault())
34-
}
35-
36-
/** Gets the single method of this interface. */
37-
Method getRunMethod() { getAPotentialRunMethod(this).getSourceDeclaration() = result }
38-
}
39-
409
/**
4110
* Holds if `m` might invoke `runmethod` through a functional interface on the
4211
* `n`th parameter.

0 commit comments

Comments
 (0)