8000 Fix issue 132 and refactor entrypoint detection logic. · codellm-devkit/codeanalyzer-java@4a4108d · GitHub
[go: up one dir, main page]

Skip to content

Commit 4a4108d

Browse files
committed
Fix issue 132 and refactor entrypoint detection logic.
Signed-off-by: Rahul Krishna <i.m.ralk@gmail.com>
1 parent 545fe76 commit 4a4108d

File tree

12 files changed

+258
-246
lines changed

12 files changed

+258
-246
lines changed

gradle.properties

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
version=2.3.2
1+
version=2.3.3

src/main/java/com/ibm/cldk/SymbolTable.java

Lines changed: 6 additions & 216 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
import com.github.javaparser.ast.comments.JavadocComment;
2222
import com.github.javaparser.ast.nodeTypes.NodeWithJavadoc;
2323
import com.github.javaparser.ast.stmt.*;
24+
import com.ibm.cldk.javaee.EntrypointsFinderFactory;
2425
import org.apache.commons.lang3.tuple.Pair;
2526

2627
import com.github.javaparser.JavaParser;
@@ -72,7 +73,7 @@
7273
import com.ibm.cldk.javaee.utils.enums.CRUDQueryType;
7374
import com.ibm.cldk.utils.Log;
7475

75-
@SuppressWarnings("rawtypes")
76+
@SuppressWarnings({"unchecked", "rawtypes"})
7677
public class SymbolTable {
7778

7879
private static JavaSymbolSolver javaSymbolSolver;
@@ -466,149 +467,8 @@ private static Map<String, Object> mapRecordConstructorDefaults(RecordDeclaratio
466467
}
467468

468469
private static boolean isEntryPointClass(TypeDeclaration typeDecl) {
469-
return isSpringEntrypointClass(typeDecl) || isStrutsEntryPointClass(typeDecl)
470-
|| isCamelEntryPointClass(typeDecl) || isJaxRSEntrypointClass(typeDecl)
471-
|| isJakartaServletEntryPointClass(typeDecl);
472-
473-
}
474-
475-
private static boolean isSpringEntrypointClass(TypeDeclaration typeDeclaration) {
476-
List<AnnotationExpr> annotations = typeDeclaration.getAnnotations();
477-
for (AnnotationExpr annotation : annotations) {
478-
// Existing checks
479-
if (annotation.getNameAsString().contains("RestController")
480-
|| annotation.getNameAsString().contains("Controller")
481-
|| annotation.getNameAsString().contains("HandleInterceptor")
482-
|| annotation.getNameAsString().contains("HandlerInterceptor")) {
483-
return true;
484-
}
485-
486-
// Spring Boot specific checks
487-
if (annotation.getNameAsString().contains("SpringBootApplication")
488-
|| annotation.getNameAsString().contains("Configuration")
489-
|| annotation.getNameAsString().contains("Component")
490-
|| annotation.getNameAsString().contains("Service")
491-
|| annotation.getNameAsString().contains("Repository")) {
492-
return true;
493-
}
494-
}
495-
496-
// Check if class implements CommandLineRunner or ApplicationRunner
497-
if (typeDeclaration instanceof ClassOrInterfaceDeclaration) {
498-
ClassOrInterfaceDeclaration classDecl = (ClassOrInterfaceDeclaration) typeDeclaration;
499-
for (ClassOrInterfaceType implementedType : classDecl.getImplementedTypes()) {
500-
String typeName = implementedType.getNameAsString();
501-
if (typeName.equals("CommandLineRunner") || typeName.equals("ApplicationRunner")) {
502-
return true;
503-
}
504-
}
505-
}
506-
507-
return false;
508-
}
509-
510-
private static boolean isJaxRSEntrypointClass(TypeDeclaration typeDeclaration) {
511-
List<CallableDeclaration> callableDeclarations = typeDeclaration.findAll(CallableDeclaration.class);
512-
for (CallableDeclaration callableDeclaration : callableDeclarations) {
513-
if (callableDeclaration.getAnnotations().stream().anyMatch(a -> a.toString().contains("POST"))
514-
|| callableDeclaration.getAnnotations().stream().anyMatch(a -> a.toString().contains("PUT"))
515-
|| callableDeclaration.getAnnotations().stream().anyMatch(a -> a.toString().contains("GET"))
516-
|| callableDeclaration.getAnnotations().stream().anyMatch(a -> a.toString().contains("HEAD"))
517-
|| callableDeclaration.getAnnotations().stream().anyMatch(a -> a.toString().contains("DELETE"))) {
518-
return true;
519-
}
520-
}
521-
522-
return false;
523-
}
524-
525-
private static boolean isStrutsEntryPointClass(TypeDeclaration typeDeclaration) {
526-
if (!(typeDeclaration instanceof ClassOrInterfaceDeclaration)) {
527-
return false;
528-
}
529-
530-
ClassOrInterfaceDeclaration classDecl = (ClassOrInterfaceDeclaration) typeDeclaration;
531-
532-
// Check class-level Struts annotations
533-
if (classDecl.getAnnotations().stream().anyMatch(a -> a.getNameAsString().contains("Action")
534-
|| a.getNameAsString().contains("Namespace") || a.getNameAsString().contains("InterceptorRef"))) {
535-
return true;
536-
}
537-
538-
// Check if extends ActionSupport or implements Interceptor
539-
try {
540-
ResolvedReferenceTypeDeclaration resolved = classDecl.resolve();
541-
return resolved.getAllAncestors().stream().anyMatch(ancestor -> {
542-
String name = ancestor.getQualifiedName();
543-
return name.contains("ActionSupport") || name.contains("Interceptor");
544-
});
545-
} catch (UnsolvedSymbolException e) {
546-
Log.warn("Could not resolve class: " + e.getMessage());
547-
}
548-
549-
return false;
550-
}
551-
552-
private static boolean isCamelEntryPointClass(TypeDeclaration typeDeclaration) {
553-
if (!(typeDeclaration instanceof ClassOrInterfaceDeclaration)) {
554-
return false;
555-
}
556-
557-
ClassOrInterfaceDeclaration classDecl = (ClassOrInterfaceDeclaration) typeDeclaration;
558-
559-
// Check Camel class annotations
560-
if (classDecl.getAnnotations().stream().anyMatch(a -> a.getNameAsString().contains("Component"))) {
561-
return true;
562-
}
563-
564-
// Check Camel parent classes and interfaces
565-
try {
566-
ResolvedReferenceTypeDeclaration resolved = classDecl.resolve();
567-
return resolved.getAllAncestors().stream().anyMatch(ancestor -> {
568-
String name = ancestor.getQualifiedName();
569-
return name.contains("RouteBuilder") || name.contains("Processor") || name.contains("Producer")
570-
|| name.contains("Consumer");
571-
});
572-
} catch (UnsolvedSymbolException e) {
573-
Log.warn("Could not resolve class: " + e.getMessage());
574-
}
575-
576-
return false;
577-
}
578-
579-
/**
580-
* Checks if the given class is a Jakarta Servlet entry point class.
581-
*
582-
* @param typeDecl Type declaration to check
583-
* @return True if the class is a Jakarta Servlet entry point class, false
584-
* otherwise
585-
*/
586-
private static boolean isJakartaServletEntryPointClass(TypeDeclaration typeDecl) {
587-
if (!(typeDecl instanceof ClassOrInterfaceDeclaration)) {
588-
return false;
589-
}
590-
591-
ClassOrInterfaceDeclaration classDecl = (ClassOrInterfaceDeclaration) typeDecl;
592-
593-
// Check annotations
594-
if (classDecl.getAnnotations().stream()
595-
.anyMatch(a -> a.getNameAsString().contains("WebServlet") || a.getNameAsString().contains("WebFilter")
596-
|| a.getNameAsString().contains("WebListener") || a.getNameAsString().contains("ServerEndpoint")
597-
|| a.getNameAsString().contains("MessageDriven")
598-
|| a.getNameAsString().contains("WebService"))) {
599-
return true;
600-
}
601-
602-
// Check types
603-
return classDecl.getExtendedTypes().stream()
604-
.map(ClassOrInterfaceType::getNameAsString)
605-
.anyMatch(name -> name.contains("HttpServlet") || name.contains("GenericServlet"))
606-
|| classDecl.getImplementedTypes().stream().map(
607-
ClassOrInterfaceType::asString).anyMatch(
608-
name -> name.contains("ServletContextListener")
609-
|| name.contains("HttpSessionListener")
610-
|| name.contains("ServletRequestListener")
611-
|| name.contains("MessageListener"));
470+
return EntrypointsFinderFactory.getEntrypointFinders()
471+
.anyMatch(finder -> finder.isEntrypointClass(typeDecl));
612472
}
613473

614474
/**
@@ -752,80 +612,10 @@ private static Pair<String, Callable> processCallableDeclaration(CallableDeclara
752612
}
753613

754614
private static boolean isEntryPointMethod(CallableDeclaration callableDecl) {
755-
return isServletEntrypointMethod(callableDecl) || isJaxRsEntrypointMethod(callableDecl)
756-
|| isSpringEntrypointMethod(callableDecl) | isStrutsEntryPointMethod(callableDecl);
757-
}
758-
759-
@SuppressWarnings("unchecked")
760-
private static boolean isServletEntrypointMethod(CallableDeclaration callableDecl) {
761-
return ((NodeList<Parameter>) callableDecl.getParameters()).stream()
762-
.anyMatch(parameter -> parameter.getType().asString().contains("HttpServletRequest") ||
763-
parameter.getType().asString().contains("HttpServletResponse"))
764-
&& callableDecl.getAnnotations().stream().anyMatch(a -> a.toString().contains("Override"));
765-
}
766-
767-
@SuppressWarnings("unchecked")
768-
private static boolean isJaxRsEntrypointMethod(CallableDeclaration callableDecl) {
769-
return callableDecl.getAnnotations().stream()
770-
.anyMatch(a -> a.toString().contains("POST") || a.toString().contains("PUT")
771-
|| a.toString().contains("GET") || a.toString().contains("HEAD")
772-
|| a.toString().contains("DELETE"));
615+
return EntrypointsFinderFactory.getEntrypointFinders()
616+
.anyMatch(finder -> finder.isEntrypointMethod(callableDecl));
773617
}
774618

775-
@SuppressWarnings("unchecked")
776-
private static boolean isSpringEntrypointMethod(CallableDeclaration callableDecl) {
777-
return callableDecl.getAnnotations().stream().anyMatch(a -> a.toString().contains("GetMapping") ||
778-
a.toString().contains("PostMapping") ||
779-
a.toString().contains("PutMapping") ||
780-
a.toString().contains("DeleteMapping") ||
781-
a.toString().contains("PatchMapping") ||
782-
a.toString().contains("RequestMapping") ||
783-
a.toString().contains("EventListener") ||
784-
a.toString().contains("Scheduled") ||
785-
a.toString().contains("KafkaListener") ||
786-
a.toString().contains("RabbitListener") ||
787-
a.toString().contains("JmsListener") ||
788-
a.toString().contains("PreAuthorize") ||
789-
a.toString().contains("PostAuthorize") ||
790-
a.toString().contains("PostConstruct") ||
791-
a.toString().contains("PreDestroy") ||
792-
a.toString().contains("Around") ||
793-
a.toString().contains("Before") ||
794-
a.toString().contains("After") ||
795-
a.toString().contains("JobScope") ||
796-
a.toString().contains("StepScope"));
797-
}
798-
799-
@SuppressWarnings("unchecked")
800-
private static boolean isStrutsEntryPointMethod(CallableDeclaration callableDecl) {
801-
// First check if this method is in a Struts Action class
802-
Optional<Node> parentNode = callableDecl.getParentNode();
803-
if (parentNode.isEmpty() || !(parentNode.get() instanceof ClassOrInterfaceDeclaration)) {
804-
return false;
805-
}
806-
807-
ClassOrInterfaceDeclaration parentClass = (ClassOrInterfaceDeclaration) parentNode.get();
808-
if (parentClass.getExtendedTypes().stream()
809-
.map(ClassOrInterfaceType::asString)
810-
.noneMatch(type -> type.contains("ActionSupport") || type.contains("Action")))
811-
return false;
812-
813-
return callableDecl.getAnnotations().stream().anyMatch(a -> a.toString().contains("Action") ||
814-
a.toString().contains("Actions") ||
815-
a.toString().contains("ValidationMethod") ||
816-
a.toString().contains("InputConfig") ||
817-
a.toString().contains("BeforeResult") ||
818-
a.toString().contains("After") ||
819-
a.toString().contains("Before") ||
820-
a.toString().contains("Result") ||
821-
a.toString().contains("Results")) || callableDecl.getNameAsString().equals("execute"); // Check for
822-
// execute()
823-
// method which
824-
// is the default
825-
// action method
826-
// of the Action
827-
// class
828-
}
829619

830620
/**
831621
* Computes cyclomatic complexity for the given callable.
Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,10 @@
11
package com.ibm.cldk.javaee;
22

3-
import com.ibm.cldk.javaee.utils.interfaces.AbstractCRUDFinder;
3+
import com.ibm.cldk.javaee.camel.CamelEntrypointFinder;
4+
import com.ibm.cldk.javaee.jax.JaxRsEntrypointFinder;
5+
import com.ibm.cldk.javaee.spring.SpringEntrypointFinder;
46
import com.ibm.cldk.javaee.utils.interfaces.AbstractEntrypointFinder;
5-
import com.ibm.cldk.javaee.jakarta.JPACRUDFinder;
67
import com.ibm.cldk.javaee.jakarta.JakartaEntrypointFinder;
7-
import com.ibm.cldk.javaee.jdbc.JDBCCRUDFinder;
8-
import com.ibm.cldk.javaee.spring.SpringCRUDFinder;
98
import com.ibm.cldk.javaee.struts.StrutsEntrypointFinder;
109
import org.apache.commons.lang3.NotImplementedException;
1110

@@ -17,7 +16,7 @@ public static AbstractEntrypointFinder getEntrypointFinder(String framework) {
1716
case "jakarta":
1817
return new JakartaEntrypointFinder();
1918
case "spring":
20-
return new StrutsEntrypointFinder();
19+
return new SpringEntrypointFinder();
2120
case "camel":
2221
throw new NotImplementedException("Camel CRUD finder not implemented yet");
2322
case "struts":
@@ -27,7 +26,7 @@ public static AbstractEntrypointFinder getEntrypointFinder(String framework) {
2726
}
2827
}
2928

30-
public static Stream<AbstractCRUDFinder> getEntrypointFinders() {
31-
return Stream.of(new JPACRUDFinder(), new SpringCRUDFinder(), new JDBCCRUDFinder());
29+
public static Stream<AbstractEntrypointFinder> getEntrypointFinders() {
30+
return Stream.of(new JakartaEntrypointFinder(), new StrutsEntrypointFinder(), new SpringEntrypointFinder(), new CamelEntrypointFinder(), new JaxRsEntrypointFinder());
3231
}
3332
}
Lines changed: 40 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,55 @@
11
package com.ibm.cldk.javaee.camel;
22

3+
import com.github.javaparser.ast.body.CallableDeclaration;
4+
import com.github.javaparser.ast.body.ClassOrInterfaceDeclaration;
5+
import com.github.javaparser.ast.body.TypeDeclaration;
6+
import com.github.javaparser.resolution.UnsolvedSymbolException;
7+
import com.github.javaparser.resolution.declarations.ResolvedReferenceTypeDeclaration;
38
import com.ibm.cldk.javaee.utils.interfaces.AbstractEntrypointFinder;
9+
import com.ibm.cldk.utils.Log;
410
import com.ibm.cldk.utils.annotations.NotImplemented;
511

612
@NotImplemented(comment = "This class is not implemented yet. Leaving this here to refactor entrypoint detection.")
713
public class CamelEntrypointFinder extends AbstractEntrypointFinder {
14+
/**
15+
* Detect if the method is an entrypoint.
16+
*
17+
* @param typeDecl@return True if the method is an entrypoint, false otherwise.
18+
*/
819
@Override
9-
public boolean isEntrypointClass(String receiverType, String name) {
20+
public boolean isEntrypointClass(TypeDeclaration typeDecl) {
21+
if (!(typeDecl instanceof ClassOrInterfaceDeclaration)) {
22+
return false;
23+
}
24+
25+
ClassOrInterfaceDeclaration classDecl = (ClassOrInterfaceDeclaration) typeDecl;
26+
27+
// Check Camel class annotations
28+
if (classDecl.getAnnotations().stream().anyMatch(a -> a.getNameAsString().contains("Component"))) {
29+
return true;
30+
}
31+
32+
// Check Camel parent classes and interfaces
33+
try {
34+
ResolvedReferenceTypeDeclaration resolved = classDecl.resolve();
35+
return resolved.getAllAncestors().stream().anyMatch(ancestor -> {
36+
String name = ancestor.getQualifiedName();
37+
return name.contains("RouteBuilder") || name.contains("Processor") || name.contains("Producer")
38+
|| name.contains("Consumer");
39+
});
40+
} catch (UnsolvedSymbolException e) {
41+
Log.warn("Could not resolve class: " + e.getMessage());
42+
}
43+
1044
return false;
1145
}
1246

47+
/**
48+
* @param callableDecl
49+
* @return
50+
*/
1351
@Override
14-
public boolean isEntrypointMethod(String receiverType, String name) {
52+
public boolean isEntrypointMethod(CallableDeclaration callableDecl) {
1553
return false;
1654
}
1755
}

0 commit comments

Comments
 (0)
0