|
5 | 5 | #include "tree_sitter/api.h" // TSNode, ts_node_* |
6 | 6 | #include <stdint.h> // uint32_t |
7 | 7 | #include <string.h> |
| 8 | +#include <strings.h> /* strcasecmp */ |
8 | 9 | #include <ctype.h> |
9 | 10 |
|
10 | 11 | // Field name lengths for ts_node_child_by_field_name() calls. |
@@ -1184,11 +1185,72 @@ static void extract_func_def(CBMExtractCtx *ctx, TSNode node, const CBMLangSpec |
1184 | 1185 | } |
1185 | 1186 | } |
1186 | 1187 |
|
1187 | | - // main is always an entry point |
1188 | | - if (strcmp(name, "main") == 0) { |
| 1188 | + // main/Main is always an entry point (case-insensitive for C#/Java) |
| 1189 | + if (strcasecmp(name, "main") == 0) { |
1189 | 1190 | def.is_entry_point = true; |
1190 | 1191 | } |
1191 | 1192 |
|
| 1193 | + // C# entry point detection: Windows Service lifecycle, ASP.NET controllers |
| 1194 | + if (ctx->language == CBM_LANG_CSHARP && !def.is_entry_point) { |
| 1195 | + // Windows Service lifecycle entry points |
| 1196 | + if (strcmp(name, "OnStart") == 0 || strcmp(name, "OnStartImpl") == 0 || |
| 1197 | + strcmp(name, "OnStop") == 0 || strcmp(name, "OnStopImpl") == 0 || |
| 1198 | + strcmp(name, "Run") == 0 || strcmp(name, "Execute") == 0 || |
| 1199 | + strcmp(name, "Configure") == 0 || strcmp(name, "ConfigureServices") == 0) { |
| 1200 | + def.is_entry_point = true; |
| 1201 | + } |
| 1202 | + // ASP.NET controller decorators: [HttpGet], [HttpPost], [Route], etc. |
| 1203 | + if (!def.is_entry_point && def.decorators) { |
| 1204 | + for (const char **d = def.decorators; *d; d++) { |
| 1205 | + if (strstr(*d, "HttpGet") || strstr(*d, "HttpPost") || |
| 1206 | + strstr(*d, "HttpPut") || strstr(*d, "HttpDelete") || |
| 1207 | + strstr(*d, "HttpPatch") || strstr(*d, "Route") || |
| 1208 | + strstr(*d, "ApiController") || strstr(*d, "Authorize")) { |
| 1209 | + def.is_entry_point = true; |
| 1210 | + break; |
| 1211 | + } |
| 1212 | + } |
| 1213 | + } |
| 1214 | + // Test entry points: [TestMethod], [Fact], [Test], [SetUp] |
| 1215 | + if (!def.is_entry_point && def.decorators) { |
| 1216 | + for (const char **d = def.decorators; *d; d++) { |
| 1217 | + if (strstr(*d, "TestMethod") || strstr(*d, "Fact") || |
| 1218 | + strstr(*d, "Test") || strstr(*d, "SetUp") || |
| 1219 | + strstr(*d, "TestInitialize")) { |
| 1220 | + def.is_entry_point = true; |
| 1221 | + break; |
| 1222 | + } |
| 1223 | + } |
| 1224 | + } |
| 1225 | + } |
| 1226 | + |
| 1227 | + // Java entry point detection: Spring Boot, Vert.x, JAX-RS, JUnit |
| 1228 | + if (ctx->language == CBM_LANG_JAVA && !def.is_entry_point) { |
| 1229 | + // Vert.x lifecycle and common server patterns |
| 1230 | + if (strcmp(name, "start") == 0 || strcmp(name, "configure") == 0 || |
| 1231 | + strcmp(name, "init") == 0 || strcmp(name, "run") == 0 || |
| 1232 | + strcmp(name, "handle") == 0) { |
| 1233 | + def.is_entry_point = true; |
| 1234 | + } |
| 1235 | + // Spring/JAX-RS/JUnit decorators |
| 1236 | + if (!def.is_entry_point && def.decorators) { |
| 1237 | + for (const char **d = def.decorators; *d; d++) { |
| 1238 | + if (strstr(*d, "RequestMapping") || strstr(*d, "GetMapping") || |
| 1239 | + strstr(*d, "PostMapping") || strstr(*d, "PutMapping") || |
| 1240 | + strstr(*d, "DeleteMapping") || strstr(*d, "PatchMapping") || |
| 1241 | + strstr(*d, "Endpoint") || strstr(*d, "EventHandler") || |
| 1242 | + strstr(*d, "Scheduled") || strstr(*d, "Bean") || |
| 1243 | + strstr(*d, "Override") || strstr(*d, "Test") || |
| 1244 | + strstr(*d, "GET") || strstr(*d, "POST") || |
| 1245 | + strstr(*d, "PUT") || strstr(*d, "DELETE") || |
| 1246 | + strstr(*d, "Path") || strstr(*d, "Consumes")) { |
| 1247 | + def.is_entry_point = true; |
| 1248 | + break; |
| 1249 | + } |
| 1250 | + } |
| 1251 | + } |
| 1252 | + } |
| 1253 | + |
1192 | 1254 | cbm_defs_push(&ctx->result->defs, a, def); |
1193 | 1255 | } |
1194 | 1256 |
|
@@ -1658,6 +1720,58 @@ static void push_method_def(CBMExtractCtx *ctx, TSNode child, const char *class_ |
1658 | 1720 | def.complexity = cbm_count_branching(child, spec->branching_node_types); |
1659 | 1721 | } |
1660 | 1722 |
|
| 1723 | + // Entry point detection for class methods (same rules as extract_func_def) |
| 1724 | + // Case-insensitive "main" check |
| 1725 | + if (strcasecmp(name, "main") == 0) { |
| 1726 | + def.is_entry_point = true; |
| 1727 | + } |
| 1728 | + |
| 1729 | + // C# entry point detection: Windows Service lifecycle, ASP.NET controllers |
| 1730 | + if (ctx->language == CBM_LANG_CSHARP && !def.is_entry_point) { |
| 1731 | + if (strcmp(name, "OnStart") == 0 || strcmp(name, "OnStartImpl") == 0 || |
| 1732 | + strcmp(name, "OnStop") == 0 || strcmp(name, "OnStopImpl") == 0 || |
| 1733 | + strcmp(name, "Run") == 0 || strcmp(name, "Execute") == 0 || |
| 1734 | + strcmp(name, "Configure") == 0 || strcmp(name, "ConfigureServices") == 0) { |
| 1735 | + def.is_entry_point = true; |
| 1736 | + } |
| 1737 | + if (!def.is_entry_point && def.decorators) { |
| 1738 | + for (const char **d = def.decorators; *d; d++) { |
| 1739 | + if (strstr(*d, "HttpGet") || strstr(*d, "HttpPost") || |
| 1740 | + strstr(*d, "HttpPut") || strstr(*d, "HttpDelete") || |
| 1741 | + strstr(*d, "HttpPatch") || strstr(*d, "Route") || |
| 1742 | + strstr(*d, "ApiController") || strstr(*d, "Authorize")) { |
| 1743 | + def.is_entry_point = true; |
| 1744 | + break; |
| 1745 | + } |
| 1746 | + } |
| 1747 | + } |
| 1748 | + } |
| 1749 | + |
| 1750 | + // Java entry point detection |
| 1751 | + if (ctx->language == CBM_LANG_JAVA && !def.is_entry_point) { |
| 1752 | + if (strcmp(name, "start") == 0 || strcmp(name, "configure") == 0 || |
| 1753 | + strcmp(name, "init") == 0 || strcmp(name, "run") == 0 || |
| 1754 | + strcmp(name, "handle") == 0) { |
| 1755 | + def.is_entry_point = true; |
| 1756 | + } |
| 1757 | + if (!def.is_entry_point && def.decorators) { |
| 1758 | + for (const char **d = def.decorators; *d; d++) { |
| 1759 | + if (strstr(*d, "RequestMapping") || strstr(*d, "GetMapping") || |
| 1760 | + strstr(*d, "PostMapping") || strstr(*d, "PutMapping") || |
| 1761 | + strstr(*d, "DeleteMapping") || strstr(*d, "PatchMapping") || |
| 1762 | + strstr(*d, "Endpoint") || strstr(*d, "EventHandler") || |
| 1763 | + strstr(*d, "Scheduled") || strstr(*d, "Bean") || |
| 1764 | + strstr(*d, "Override") || strstr(*d, "Test") || |
| 1765 | + strstr(*d, "GET") || strstr(*d, "POST") || |
| 1766 | + strstr(*d, "PUT") || strstr(*d, "DELETE") || |
| 1767 | + strstr(*d, "Path") || strstr(*d, "Consumes")) { |
| 1768 | + def.is_entry_point = true; |
| 1769 | + break; |
| 1770 | + } |
| 1771 | + } |
| 1772 | + } |
| 1773 | + } |
| 1774 | + |
1661 | 1775 | cbm_defs_push(&ctx->result->defs, a, def); |
1662 | 1776 | } |
1663 | 1777 |
|
|
0 commit comments