more fixes
This commit is contained in:
@@ -55,7 +55,26 @@ public class ConstantResolver {
|
|||||||
return resolveManual(sn, context, visited);
|
return resolveManual(sn, context, visited);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if (expr instanceof MethodInvocation mi) {
|
if (expr instanceof MethodInvocation mi) {
|
||||||
|
if ((mi.getName().getIdentifier().equals("name") || mi.getName().getIdentifier().equals("toString")) && mi.arguments().isEmpty()) {
|
||||||
|
String val = resolveInternal(mi.getExpression(), context, visited);
|
||||||
|
if (val != null) {
|
||||||
|
// If it was resolved as a fully qualified enum string like "MyEvents.ORDER_PAID", strip it
|
||||||
|
if (val.contains(".")) {
|
||||||
|
return val.substring(val.lastIndexOf('.') + 1);
|
||||||
|
}
|
||||||
|
return val;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fallback for unresolved AST nodes
|
||||||
|
if (mi.getExpression() instanceof QualifiedName qn) {
|
||||||
|
return qn.getName().getIdentifier();
|
||||||
|
} else if (mi.getExpression() instanceof SimpleName sn) {
|
||||||
|
return sn.getIdentifier();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
IMethodBinding mb = mi.resolveMethodBinding();
|
IMethodBinding mb = mi.resolveMethodBinding();
|
||||||
if (mb != null) {
|
if (mb != null) {
|
||||||
ITypeBinding returnType = mb.getReturnType();
|
ITypeBinding returnType = mb.getReturnType();
|
||||||
|
|||||||
@@ -1081,4 +1081,260 @@ class CallGraphBuilderTest {
|
|||||||
assertThat(chains).hasSize(1);
|
assertThat(chains).hasSize(1);
|
||||||
assertThat(chains.get(0).getTriggerPoint().getPolymorphicEvents()).containsExactlyInAnyOrder("EVENT_A", "EVENT_B");
|
assertThat(chains.get(0).getTriggerPoint().getPolymorphicEvents()).containsExactlyInAnyOrder("EVENT_A", "EVENT_B");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void shouldResolveConstantsFromSwitchStatementInMethod() throws IOException {
|
||||||
|
String source = """
|
||||||
|
package com.example;
|
||||||
|
public class OrderController {
|
||||||
|
private OrderService service;
|
||||||
|
public void handleStatus(DomainEvent domainEvent) {
|
||||||
|
service.process(domainEvent.getEventForStatus());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class DomainEvent {
|
||||||
|
private OrderStatus status;
|
||||||
|
public String getEventForStatus() {
|
||||||
|
switch (status) {
|
||||||
|
case NEW: return "CREATE_EVENT";
|
||||||
|
case PAID: return "PAY_EVENT";
|
||||||
|
default: return "CANCEL_EVENT";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class OrderService {
|
||||||
|
public void process(String event) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
enum OrderStatus { NEW, PAID }
|
||||||
|
""";
|
||||||
|
Path tempDir = Files.createTempDirectory("callgraph_switch");
|
||||||
|
Files.writeString(tempDir.resolve("OrderConfig.java"), source);
|
||||||
|
CodebaseContext context = new CodebaseContext();
|
||||||
|
context.scan(tempDir);
|
||||||
|
CallGraphBuilder builder = new CallGraphBuilder(context);
|
||||||
|
|
||||||
|
EntryPoint entryPoint = EntryPoint.builder().className("com.example.OrderController").methodName("handleStatus").build();
|
||||||
|
TriggerPoint trigger = TriggerPoint.builder().className("com.example.OrderService").methodName("process").event("event").build();
|
||||||
|
List<CallChain> chains = builder.findChains(List.of(entryPoint), List.of(trigger));
|
||||||
|
|
||||||
|
org.assertj.core.api.Assertions.assertThat(chains).hasSize(1);
|
||||||
|
org.assertj.core.api.Assertions.assertThat(chains.get(0).getTriggerPoint().getPolymorphicEvents()).containsExactlyInAnyOrder("CREATE_EVENT", "PAY_EVENT", "CANCEL_EVENT");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void shouldGracefullyHandleComplexMethodChainsWithoutCrashing() throws IOException {
|
||||||
|
String source = """
|
||||||
|
package com.example;
|
||||||
|
import java.util.Optional;
|
||||||
|
public class OrderController {
|
||||||
|
private OrderService service;
|
||||||
|
public void handleStatus(DomainEvent domainEvent) {
|
||||||
|
service.process(Optional.of(domainEvent).get().getEvent());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class DomainEvent {
|
||||||
|
public String getEvent() { return "COMPLEX_EVENT"; }
|
||||||
|
}
|
||||||
|
|
||||||
|
class OrderService {
|
||||||
|
public void process(String event) {}
|
||||||
|
}
|
||||||
|
""";
|
||||||
|
Path tempDir = Files.createTempDirectory("callgraph_complex_chain");
|
||||||
|
Files.writeString(tempDir.resolve("OrderConfig.java"), source);
|
||||||
|
CodebaseContext context = new CodebaseContext();
|
||||||
|
context.scan(tempDir);
|
||||||
|
CallGraphBuilder builder = new CallGraphBuilder(context);
|
||||||
|
|
||||||
|
EntryPoint entryPoint = EntryPoint.builder().className("com.example.OrderController").methodName("handleStatus").build();
|
||||||
|
TriggerPoint trigger = TriggerPoint.builder().className("com.example.OrderService").methodName("process").event("event").build();
|
||||||
|
List<CallChain> chains = builder.findChains(List.of(entryPoint), List.of(trigger));
|
||||||
|
|
||||||
|
org.assertj.core.api.Assertions.assertThat(chains).hasSize(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void shouldNotCrashOnStaticMethodWrapping() throws IOException {
|
||||||
|
String source = """
|
||||||
|
package com.example;
|
||||||
|
public class OrderController {
|
||||||
|
private OrderService service;
|
||||||
|
public void handleStatus(DomainEvent domainEvent) {
|
||||||
|
service.process(String.valueOf(domainEvent.getEvent()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class DomainEvent {
|
||||||
|
public String getEvent() { return "STATIC_WRAP_EVENT"; }
|
||||||
|
}
|
||||||
|
|
||||||
|
class OrderService {
|
||||||
|
public void process(String event) {}
|
||||||
|
}
|
||||||
|
""";
|
||||||
|
Path tempDir = Files.createTempDirectory("callgraph_static_wrap");
|
||||||
|
Files.writeString(tempDir.resolve("OrderConfig.java"), source);
|
||||||
|
CodebaseContext context = new CodebaseContext();
|
||||||
|
context.scan(tempDir);
|
||||||
|
CallGraphBuilder builder = new CallGraphBuilder(context);
|
||||||
|
|
||||||
|
EntryPoint entryPoint = EntryPoint.builder().className("com.example.OrderController").methodName("handleStatus").build();
|
||||||
|
TriggerPoint trigger = TriggerPoint.builder().className("com.example.OrderService").methodName("process").event("event").build();
|
||||||
|
List<CallChain> chains = builder.findChains(List.of(entryPoint), List.of(trigger));
|
||||||
|
|
||||||
|
org.assertj.core.api.Assertions.assertThat(chains).hasSize(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void shouldResolveConstantsFromStringConcatenation() throws IOException {
|
||||||
|
String source = """
|
||||||
|
package com.example;
|
||||||
|
public class OrderController {
|
||||||
|
private OrderService service;
|
||||||
|
public void handleStatus(DomainEvent domainEvent) {
|
||||||
|
service.process(domainEvent.getCustomEvent());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class DomainEvent {
|
||||||
|
public static final String PREFIX = "ORDER_";
|
||||||
|
public String getCustomEvent() {
|
||||||
|
return PREFIX + "CREATED";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class OrderService {
|
||||||
|
public void process(String event) {}
|
||||||
|
}
|
||||||
|
""";
|
||||||
|
Path tempDir = Files.createTempDirectory("callgraph_concat");
|
||||||
|
Files.writeString(tempDir.resolve("OrderConfig.java"), source);
|
||||||
|
CodebaseContext context = new CodebaseContext();
|
||||||
|
context.scan(tempDir);
|
||||||
|
CallGraphBuilder builder = new CallGraphBuilder(context);
|
||||||
|
|
||||||
|
EntryPoint entryPoint = EntryPoint.builder().className("com.example.OrderController").methodName("handleStatus").build();
|
||||||
|
TriggerPoint trigger = TriggerPoint.builder().className("com.example.OrderService").methodName("process").event("event").build();
|
||||||
|
List<CallChain> chains = builder.findChains(List.of(entryPoint), List.of(trigger));
|
||||||
|
|
||||||
|
org.assertj.core.api.Assertions.assertThat(chains).hasSize(1);
|
||||||
|
org.assertj.core.api.Assertions.assertThat(chains.get(0).getTriggerPoint().getPolymorphicEvents()).containsExactlyInAnyOrder("ORDER_CREATED");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void shouldResolveConstantsFromEnumReturn() throws IOException {
|
||||||
|
String source = """
|
||||||
|
package com.example;
|
||||||
|
public class OrderController {
|
||||||
|
private OrderService service;
|
||||||
|
public void handleStatus(DomainEvent domainEvent) {
|
||||||
|
service.process(domainEvent.getEventEnum());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class DomainEvent {
|
||||||
|
public String getEventEnum() {
|
||||||
|
return MyEvents.ORDER_PAID.name();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class OrderService {
|
||||||
|
public void process(String event) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
enum MyEvents { ORDER_PAID }
|
||||||
|
""";
|
||||||
|
Path tempDir = Files.createTempDirectory("callgraph_enum_return");
|
||||||
|
Files.writeString(tempDir.resolve("OrderConfig.java"), source);
|
||||||
|
CodebaseContext context = new CodebaseContext();
|
||||||
|
context.scan(tempDir);
|
||||||
|
CallGraphBuilder builder = new CallGraphBuilder(context);
|
||||||
|
|
||||||
|
EntryPoint entryPoint = EntryPoint.builder().className("com.example.OrderController").methodName("handleStatus").build();
|
||||||
|
TriggerPoint trigger = TriggerPoint.builder().className("com.example.OrderService").methodName("process").event("event").build();
|
||||||
|
List<CallChain> chains = builder.findChains(List.of(entryPoint), List.of(trigger));
|
||||||
|
|
||||||
|
org.assertj.core.api.Assertions.assertThat(chains).hasSize(1);
|
||||||
|
org.assertj.core.api.Assertions.assertThat(chains.get(0).getTriggerPoint().getPolymorphicEvents()).containsExactlyInAnyOrder("ORDER_PAID");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void shouldResolveConstantsFromAlternativeGetterName() throws IOException {
|
||||||
|
String source = """
|
||||||
|
package com.example;
|
||||||
|
public class OrderController {
|
||||||
|
private OrderService service;
|
||||||
|
public void handleStatus(DomainEvent domainEvent) {
|
||||||
|
service.process(domainEvent.get2Type());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class DomainEvent {
|
||||||
|
public String get2Type() {
|
||||||
|
return "ALTERNATIVE_EVENT";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class OrderService {
|
||||||
|
public void process(String event) {}
|
||||||
|
}
|
||||||
|
""";
|
||||||
|
Path tempDir = Files.createTempDirectory("callgraph_alt_getter");
|
||||||
|
Files.writeString(tempDir.resolve("OrderConfig.java"), source);
|
||||||
|
CodebaseContext context = new CodebaseContext();
|
||||||
|
context.scan(tempDir);
|
||||||
|
CallGraphBuilder builder = new CallGraphBuilder(context);
|
||||||
|
|
||||||
|
EntryPoint entryPoint = EntryPoint.builder().className("com.example.OrderController").methodName("handleStatus").build();
|
||||||
|
TriggerPoint trigger = TriggerPoint.builder().className("com.example.OrderService").methodName("process").event("event").build();
|
||||||
|
List<CallChain> chains = builder.findChains(List.of(entryPoint), List.of(trigger));
|
||||||
|
|
||||||
|
org.assertj.core.api.Assertions.assertThat(chains).hasSize(1);
|
||||||
|
org.assertj.core.api.Assertions.assertThat(chains.get(0).getTriggerPoint().getPolymorphicEvents()).containsExactlyInAnyOrder("ALTERNATIVE_EVENT");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void shouldResolveConstantsFromStringToString() throws IOException {
|
||||||
|
String source = """
|
||||||
|
package com.example;
|
||||||
|
public class OrderController {
|
||||||
|
private OrderService service;
|
||||||
|
public void handleStatus(DomainEvent domainEvent) {
|
||||||
|
service.process(domainEvent.getEventString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class DomainEvent {
|
||||||
|
public static final String ACTUAL_STRING = "STRING_LITERAL_EVENT";
|
||||||
|
public String getEventString() {
|
||||||
|
return ACTUAL_STRING.toString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class OrderService {
|
||||||
|
public void process(String event) {}
|
||||||
|
}
|
||||||
|
""";
|
||||||
|
Path tempDir = Files.createTempDirectory("callgraph_string_tostring");
|
||||||
|
Files.writeString(tempDir.resolve("OrderConfig.java"), source);
|
||||||
|
CodebaseContext context = new CodebaseContext();
|
||||||
|
context.scan(tempDir);
|
||||||
|
CallGraphBuilder builder = new CallGraphBuilder(context);
|
||||||
|
|
||||||
|
EntryPoint entryPoint = EntryPoint.builder().className("com.example.OrderController").methodName("handleStatus").build();
|
||||||
|
TriggerPoint trigger = TriggerPoint.builder().className("com.example.OrderService").methodName("process").event("event").build();
|
||||||
|
List<CallChain> chains = builder.findChains(List.of(entryPoint), List.of(trigger));
|
||||||
|
|
||||||
|
org.assertj.core.api.Assertions.assertThat(chains).hasSize(1);
|
||||||
|
org.assertj.core.api.Assertions.assertThat(chains.get(0).getTriggerPoint().getPolymorphicEvents()).containsExactlyInAnyOrder("STRING_LITERAL_EVENT");
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user