|
13 | 13 | import liquidjava.diagnostics.hints.Hint.Kind; |
14 | 14 | import liquidjava.processor.context.RefinedFunction; |
15 | 15 | import liquidjava.processor.context.Variable; |
| 16 | +import liquidjava.processor.state_machine.DecidingArgument; |
16 | 17 | import liquidjava.processor.state_machine.State; |
17 | 18 | import liquidjava.processor.state_machine.StateMachine; |
18 | 19 | import liquidjava.processor.state_machine.Transition; |
19 | 20 | import liquidjava.utils.Utils; |
| 21 | +import spoon.reflect.reference.CtExecutableReference; |
20 | 22 | import spoon.reflect.reference.CtTypeReference; |
21 | 23 |
|
22 | 24 | /** |
@@ -59,6 +61,18 @@ public static List<Hint> forCall(StateMachine machine, RefinedFunction call, Set |
59 | 61 | .toList(); |
60 | 62 | } |
61 | 63 |
|
| 64 | + /** The earlier call whose arguments decided the receiver's state, and values that would allow the call */ |
| 65 | + public static Hint decidingArgument(DecidingArgument deciding, String receiver) { |
| 66 | + RefinedFunction function = deciding.call().function(); |
| 67 | + String call = CtExecutableReference.CONSTRUCTOR_NAME.equals(function.getName()) ? constructor(function) |
| 68 | + : receiver + "." + signature(function); |
| 69 | + String values = deciding.values().isEmpty() ? "other arguments" : deciding.values().entrySet().stream() |
| 70 | + .map(e -> e.getKey() + " == " + e.getValue()).collect(Collectors.joining(" and ")); |
| 71 | + return new Hint(Kind.DECIDING_ARGUMENT, |
| 72 | + String.format("%s on line %d decides the state of %s: with %s, this call would be allowed", call, |
| 73 | + deciding.call().position().getLine(), receiver, values)); |
| 74 | + } |
| 75 | + |
62 | 76 | /** Nothing is known about the receiver's state: list what leads to a state where {@code call} is allowed */ |
63 | 77 | private List<Hint> reachingCalls(RefinedFunction call, Set<State> goal) { |
64 | 78 | Map<RefinedFunction, List<State>> sources = new LinkedHashMap<>(); |
|
0 commit comments