2323import liquidjava .utils .constants .Keys ;
2424import spoon .reflect .declaration .CtClass ;
2525import spoon .reflect .declaration .CtElement ;
26+ import spoon .reflect .declaration .CtMethod ;
2627import spoon .reflect .declaration .CtModifiable ;
2728import spoon .reflect .declaration .CtType ;
2829import spoon .reflect .reference .CtExecutableReference ;
@@ -200,27 +201,24 @@ private StateMachine build(CtTypeReference<?> type, List<CtTypeReference<?>> sup
200201 if (!function .hasStateChange ())
201202 continue ;
202203 boolean constructor = CtExecutableReference .CONSTRUCTOR_NAME .equals (function .getName ());
203- if (className .equals (function .getTargetClass ()) && constructor ) {
204+ boolean own = className .equals (function .getTargetClass ());
205+ if (own && constructor ) {
204206 if (abstractType (type ) || privateConstructor (function , type ))
205207 continue ; // cannot be suggested as a new object
206208 Optional <Set <State >> created = createdStates (function );
207209 created .ifPresent (s -> constructors .put (function , s ));
208210 continue ;
209211 }
210- if (className .equals (function .getTargetClass ()) && !appliesToOwnType (function , type , supertypes )) {
212+ if (!own && (constructor || !inherited .contains (function .getTargetClass ())))
213+ continue ;
214+ if (!own && overridden (function , className ))
215+ continue ; // the class's own refinement for it is the one in the machine
216+ boolean applies = own ? appliesToOwnType (function , type , supertypes )
217+ : resolvesTo (function , type , supertypes ) && publiclyInherited (function );
218+ if (!applies ) {
211219 complete = false ;
212220 continue ;
213221 }
214- if (!className .equals (function .getTargetClass ())) {
215- if (constructor || !inherited .contains (function .getTargetClass ()))
216- continue ;
217- if (overridden (function , className ))
218- continue ; // the class's own refinement for it is the one in the machine
219- if (!resolvesTo (function , type , supertypes ) || !publiclyInherited (function )) {
220- complete = false ;
221- continue ;
222- }
223- }
224222 Optional <List <Transition >> calls = transitionsOf (function );
225223 if (calls .isPresent ()) {
226224 methods .add (function );
@@ -271,15 +269,11 @@ private static List<String> parameterTypes(RefinedFunction function) {
271269 * parameters, so an overload can hide an inherited method, which only leaves the machine incomplete.
272270 */
273271 private boolean resolvesTo (RefinedFunction method , CtTypeReference <?> type , List <CtTypeReference <?>> supertypes ) {
274- String name = Utils .getSimpleName (method .getName ());
275- int arity = method .getArguments ().size ();
276272 for (CtTypeReference <?> t : Stream .concat (Stream .of (type ), supertypes .stream ()).toList ()) {
277273 CtType <?> declaration = t .getTypeDeclaration ();
278274 if (declaration == null )
279275 return false ; // cannot tell which type declares it
280- boolean declares = declaration .getMethods ().stream ()
281- .anyMatch (m -> m .getSimpleName ().equals (name ) && m .getParameters ().size () == arity );
282- if (declares )
276+ if (declarationsOf (method , declaration ).findAny ().isPresent ())
283277 return t .getQualifiedName ().equals (method .getTargetClass ());
284278 }
285279 return false ;
@@ -288,18 +282,22 @@ private boolean resolvesTo(RefinedFunction method, CtTypeReference<?> type, List
288282 /**
289283 * Whether any caller can call {@code method} on an object of a subtype of the type it is specified for. The machine
290284 * is shared by every caller, so a method that only some callers can reach (private, package-private or protected)
291- * is left out, which only leaves the machine incomplete. Methods are matched by name and number of parameters.
285+ * is left out, which only leaves the machine incomplete.
292286 */
293287 private boolean publiclyInherited (RefinedFunction method ) {
294288 CtType <?> declaring = tc .getFactory ().Type ().createReference (method .getTargetClass ()).getTypeDeclaration ();
295289 if (declaring == null )
296290 return false ; // cannot tell whether it is public
291+ // interface methods are public unless declared private
292+ return declarationsOf (method , declaring ).allMatch (m -> declaring .isInterface () ? !m .isPrivate () : m .isPublic ());
293+ }
294+
295+ /** The methods of {@code type} that {@code method} may refer to: those with its name and number of parameters */
296+ private static Stream <CtMethod <?>> declarationsOf (RefinedFunction method , CtType <?> type ) {
297297 String name = Utils .getSimpleName (method .getName ());
298298 int arity = method .getArguments ().size ();
299- // interface methods are public unless declared private
300- return declaring .getMethods ().stream ()
301- .filter (m -> m .getSimpleName ().equals (name ) && m .getParameters ().size () == arity )
302- .allMatch (m -> declaring .isInterface () ? !m .isPrivate () : m .isPublic ());
299+ return type .getMethods ().stream ()
300+ .filter (m -> m .getSimpleName ().equals (name ) && m .getParameters ().size () == arity );
303301 }
304302
305303 private static boolean abstractType (CtTypeReference <?> type ) {
0 commit comments