Let's try to break this down to highlight a few problems. Apex syntax not being especially amenable to regex parsing, I'm very skeptical this approach will ever work effectively and with full generality. I would rather call out to the Tooling API and work with the symbol table access provided there, if that's enough to achieve whatever your actual end goal is. (See Andrew Fawcett's old blog post on finding dead code in Apex for an example of that approach).
The Java Pattern documentation is a critical reference here.
Basically, it kind of works if you provide the correct flags. You need the (?si)
flag element, asking for case-insensitive matching and dotall mode, where .
will match a newline. Here's an example of this working correctly:
String q;
q = 'class Test {\n' +
' public static void test(Integer i) { \n'+
' if (true) { \n' +
' test2(1); \n' +
' }\n'+
'}\n';
Pattern regPattern = Pattern.compile('(?si)(Public Static)\\s*(\\w+)\\s*(\\w+)\\(.*?\\)\\s*(\\{(?:\\{(?:\\{[^\\{\\}]*\\}|.)*?[^\\{\\}]*\\}|.)*?\\})');
Matcher regMatcher = regPattern.matcher(q);
while (regMatcher.find()) {
System.debug('group:' + regMatcher.group());
This does in fact log the right value - the text of the method test()
. The problem is that it's really easy to break: just add a second method.
q = 'class Test {\n' +
' public static void test(Integer i) { \n'+
' if (true) { \n' +
' test2(1); \n' +
' }\n'+
' public static void test2(Integer i) \n' +
' {' +
' test(2);' +
' }\n' +
'}\n';
This gets you back only a single group, containing the text of both methods. (I don't immediately have a recommendation for how to fix this).
There's lots of other ways to break this, a couple of which I'll note below.
(Public Static)\s*
If we're only matching public static
methods, okay. What if the method's declared static public
? This won't match, and that's perfectly legal Apex. Additionally, regexes are case sensitive unless specified otherwise, so this won't actually match unless your methods are declared with Uppercase Modifiers
or you specify (?i)
as above.
(\w+)\s*
This looks like it's supposed to match the type name of the return type. But the \w
character class includes alphanumerics and underscores only, and Apex type names also include <>
. So any method that returns a parameterized type will fail to match.
Inner classes may pose other issues - I didn't even try testing with an inner class present.
In general, it's not a good idea to "send a regex to do a parser's job". Far more stable an approach is to trust the actual Apex compiler by talking to the Tooling API or doing your work on the tooling/development side rather than in Apex itself.