Java: Fix FunctionalInterface.

This commit is contained in:
Anders Schack-Mulligen
2021-09-09 15:04:22 +02:00
parent 5d58edb3b9
commit ec3990c619
2 changed files with 38 additions and 31 deletions

View File

@@ -874,6 +874,44 @@ class ClassOrInterface extends RefType, @classorinterface {
}
}
private string getAPublicObjectMethodSignature() {
exists(Method m |
m.getDeclaringType() instanceof TypeObject and
m.isPublic() and
result = m.getSignature()
)
}
private Method getAnAbstractMethod(Interface interface) {
interface.inherits(result) and
result.isAbstract() and
// JLS 9.8, ignore Object methods
not result.getSignature() = getAPublicObjectMethodSignature() and
// Make sure that there is no other non-abstract method
// (e.g. `default`) which overrides the abstract one
not exists(Method m |
interface.inherits(m) and
not m.isAbstract() and
m.overrides(result)
)
}
/**
* A functional interface is an interface that has just one abstract method
* (aside from the methods of Object), and thus represents a single function
* contract.
*
* See JLS 9.8, Functional Interfaces.
*/
class FunctionalInterface extends Interface {
Method run;
FunctionalInterface() { run = unique(Method r | r = getAnAbstractMethod(this)) }
/** Gets the single abstract method of this interface. */
Method getRunMethod() { result = run }
}
/**
* A primitive type.
*

View File

@@ -6,37 +6,6 @@
import java
import VirtualDispatch
private string getAPublicObjectMethodSignature() {
exists(Method m |
m.getDeclaringType() instanceof TypeObject and
m.isPublic() and
result = m.getSignature()
)
}
private Method getAPotentialRunMethod(Interface i) {
i.inherits(result) and
result.isPublic() and
not result.getSignature() = getAPublicObjectMethodSignature()
}
/**
* A functional interface is an interface that has just one abstract method
* (aside from the methods of Object), and thus represents a single function
* contract.
*
* See JLS 9.8, Functional Interfaces.
*/
class FunctionalInterface extends Interface {
FunctionalInterface() {
1 = strictcount(getAPotentialRunMethod(this)) and
not exists(Method m | this.inherits(m) and m.isDefault())
}
/** Gets the single method of this interface. */
Method getRunMethod() { getAPotentialRunMethod(this).getSourceDeclaration() = result }
}
/**
* Holds if `m` might invoke `runmethod` through a functional interface on the
* `n`th parameter.