4

I'm writing an impact analysis tool that will parse a bunch of selected file types and find the class and method calls inside the file (in this case a .cs file). I have managed to write a regular expression that will find if a line of code is a method call.

Regex re = new Regex(
               @"\b(public|private|internal|protected)\s*" +
                "(static|virtual|abstract)?\s*[a-zA-Z]*\s[a-zA-Z]+\s*" +
                "\((([a-zA-Z\[\]\<\>]*\s*[a-zA-Z]*\s*)[,]?\s*)+\)");

However; I can't figure out how to get the Method name out of the regular expression. It recognises a line as a Match but how do i pull out the actual method name. Any help on this would be amazing.

Furthermore; I'm not sure if this is how it's actually done but is there any other (up to date) c# file parsers that will be able to provide me a list of method names and class names from the file?

M4N
  • 94,805
  • 45
  • 217
  • 260
Joshy
  • 657
  • 8
  • 20
  • http://stackoverflow.com/questions/906493/regex-named-capturing-groups-in-net – meziantou Sep 29 '11 at 06:09
  • 1
    `[a-zA-Z]` is not going to cut it for C# method names. E.g. "private void µäか<בֵּ>() {}" is a valid C# method declaration. – Jens Sep 29 '11 at 07:57
  • Thanks Jens, This tool is not for external commercial use only within my company, and we only write code in english so it will work for 'us', but thankyou for pointing that out, it's a very valid point. – Joshy Oct 03 '11 at 23:49

3 Answers3

6

You can put the part that represents a method into a group like this:

(?<method>[a-zA-Z]+)

Then you can access it like this:

Match match = regex.Match(line);
if (match.Success)
{
    string method = match.Groups["method"].Value;
}

However, your regex at the moment has various problems in terms of matching method names:

  • It doesn't handle generics (generic methods, parameters or return values)
  • It doesn't handle identifiers with digits or _ in
  • It doesn't handle methods with the default access modifier
  • It will match string literals containing something looking like a method declaration

To get method names out of a C# file, you really need something which understands C#. Note that the Roslyn project may well make this sort of thing a lot easier - we'll see when the first preview comes out, very soon now...

Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
  • Thanks for your help, I have modified the regex as per your input, private const string IsMethodRegex = @"\b(public|private|internal|protected)?\s*(static|virtual|abstract)?\s*([a-zA-Z\<\>_1-9]*)\s(?[a-zA-Z\<\>_1-9]+)\s*\(((([a-zA-Z\[\]\<\>_1-9]*\s*[a-zA-Z_1-9]*\s*)[,]?\s*)+)\)"; – Joshy Sep 29 '11 at 06:35
2

Your pattern can be modified to capture method name by adding a group. Here's the complete code:

string method_pattern = @"\b(public|private|internal|protected)\s*" + @"\b(static|virtual|abstract)?\s*[a-zA-Z]*(?<method>\s[a-zA-Z]+\s*)" + @"\((([a-zA-Z\[\]\<\>]*\s*[a-zA-Z]*\s*)[,]?\s*)+\)";
while ((line = file.ReadLine()) != null)
{
    Regex expression = new Regex(method_pattern);
    Match match = expression.Match(line);
    if (match.Success)
    {
        string result = match.Groups["method"].Value;
        MessageBox.Show(result);
    }
}
Mickael Maison
  • 25,067
  • 7
  • 71
  • 68
0

Here's how you can match method names of a C# class.

Regex Expression:

\b(public|private|internal|protected|void)\s*s*\b(async)?\s*\b(static|virtual|abstract|void)?\s*\b(async)?\b(Task)?\s*[a-zA-Z]*(?<method>\s[A-Za-z_][A-Za-z_0-9]*\s*)\((([a-zA-Z\[\]\<\>]*\s*[A-Za-z_][A-Za-z_0-9]*\s*)[,]?\s*)+\)

Usage:

private void FindMethods(string input)
{
    try
    {
        const string methodPattern =
            @"\b(public|private|internal|protected|void)\s*s*\b(async)?\s*\b(static|virtual|abstract|void)?\s*\b(async)?\b(Task)?\s*[a-zA-Z]*(?<method>\s[A-Za-z_][A-Za-z_0-9]*\s*)\((([a-zA-Z\[\]\<\>]*\s*[A-Za-z_][A-Za-z_0-9]*\s*)[,]?\s*)+\)";
        foreach (Match m in Regex.Matches(input, methodPattern, RegexOptions.IgnorePatternWhitespace))
        {
            Console.WriteLine(m.Value);
            Console.WriteLine(m.Groups["method"].Value);
        }
    }
    catch (ArgumentException ex)
    {
        // Syntax error in the regular expression
    }
}

proof

Alper Ebicoglu
  • 8,884
  • 1
  • 49
  • 55