Take the 2-minute tour ×
Salesforce Stack Exchange is a question and answer site for Salesforce administrators, implementation experts, developers and anybody in-between. It's 100% free, no registration required.

I want to calculate some metrics on Apex classes. So I need to somewhat "parse" them with the means that exist in Apex e.g. regexp patterns, groups and regions.

I want to match class declarations and public method declarations and would love to be able to directly access those parts of the matched fragment:

  • Is it static, abstract or default?
  • Is it a class or an interface?
  • What's the methodname?
  • What's the Returntype?
  • What's the param list?

So the resulting code could do this:

private static Pattern classDef = Pattern.compile('???');
private static Pattern publicMethods = Pattern.compile('???');

for(ApexClass c : [SELECT NamespacePrefix, Name, ApiVersion, Status, IsValid, Body 
                  FROM ApexClass 
                  ORDER BY NamespacePrefix, Name]) {

    // Parse class declaration
    String classModifier;   // abstract, static
    String classType;       // class, interface
    String className = c.Name;
    String superType;       // extends, implements
    String superName;       // name of super class/interface

    Matcher result = classDef.matcher(c.Body);

    if (result.find()) {
        classModifier = result.group(0);
        classType = result.group(1);
        superType = result.group(2);
        superName = result.group(3);
        ...
    }

    // Parse class body for public methods
    result = publicMethods.matcher(c.Body);

    while (result.find()) {
        String methodModifier = result.group(0);
        String returnType = result.group(1);
        String methodName = result.group(2);
        String params = result.group(3);

        ...
    }
}
share|improve this question
add comment

2 Answers

After beginning to write this reply, I see you received a response regarding the new Tooling API. If that doesn't provide what you're looking for, here's a response along the lines of your original question.

I can answer at least parts of your questions. First, I'd consider this to be a utility class. Unless you're using the same RegEx pattern,

private static Pattern publicMethods = Pattern.compile(RegEx);

the above pattern would not be static. You can go to http://gskinner.com/RegExr/ where you'll find a "utility" that will be of great assistance in helping you put together the RegularExpression you'll need. You can even save match and replace expressions for future reference and sharing with others. If you use the same RegEx pattern, then you can declare it as Static.

private static Pattern classDef = Pattern.compile('???')

What objects are you planning to pass to your class? Both pattern and matcher objects have their own classes. By creating this as a utility, all you're really doing is calling instances of their classes. I don't believe you'd need to declare them. What's important to declare is the form of the variables you'll be passing the information to and from your class to. Typically, you need a RegularExpression that describes the pattern you're searching for and then a string for it to search through using that pattern to match against.

classModifier = result.group(0);

Group(o) contains the entire RegExpr. GroupCount() returns the number of capturing Groups in the matching object's expression which determines the maximum number of groups that will be returned from the pattern match.

In addition to what you're doing, you may also want to look at string methods to see how much of this might be accomplished using those as well as there's a great deal of overlap as well.

If you look at the APEX documentation on the Pattern and Matcher methods, you'll see that the return types from these methods are always going to be strings, except in the case of certain methods that are boolean. The ones you've listed are all strings. Again, I'd see this as a utility class where you're going to need to pass objects, probably collect schema information, parse everything into strings, then run your pattern matches.

Hope you find this helpful

share|improve this answer
6  
@RobertS That is a terrible reason to downvote this. The user clearly took some time to write this out to help you. It doesn't matter if you particularly found it useful as it may be useful to people down the line and is full of really well thought out, well written information. The purpose of upvotes and downvotes is to help promote good and bad behavior. Good behavior is taking the time to answer the question as thoroughly as possible. A bad answer is normally spam or something detrimental to a question. –  Jesse Altman Feb 15 '13 at 22:14
    
Jesse you are right. I will redo it. But the anwer felt a little bit like spam. –  Robert Sösemann Feb 16 '13 at 21:09
add comment

You will have a really hard time parsing apex with regular expressions since, like java, the language is defined with a context free grammar which can't necessarily be parsed by regular expressions.

However, there is a way to get at this information without parsing the language at all. The new tooling api has an object called SymbolTable which has a lot of this information. A SymbolTable contains an array of method objects that have the following information:

Description Contains the position, name, scope, signature, and return type of available Apex methods. Method includes the following fields:
• location
• name
• references
• visibility (scope: Global, Public or Private)
• parameters
• returnType

share|improve this answer
    
I know that Regexp is not the advised way of parsing. But its a pracmatic solution when real parsing is not feasable. While in the meantime I came up with my own regexp pattern I appreciate your answer. Is this availble now with Spring '13?! –  Robert Sösemann Feb 15 '13 at 20:44
    
When I read the api I find no way to learn about the class itself. Its modifiers, superClasses and so on... Shouldn't that be part?! –  Robert Sösemann Feb 15 '13 at 20:45
    
The tooling api is GA in spring '13: blogs.developerforce.com/developer-relations/2013/01/… –  Greg Grinberg Feb 15 '13 at 21:57
1  
I don't see this information in the api from the docs but I would poke around with the symboltable a bit. This is fairly new so documentation may be lacking. If it really isn't there parsing this one line out with regex should be much easier and less error-prone. –  Greg Grinberg Feb 15 '13 at 22:02
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.