0

Iam looking for a way to match a full class, starting with the first bracket and ending with the closing bracket. I need this for an add-in, to limit the area the add-in should be applied to. My Problem is, that in those classes, there could be extra "sub-classes", also having brackets opening and closing. I would need a way to count those and ignore them until i find the right closing bracket of the first class.

Example:

public class Test
**{**

 doSomeThing();

 private partial class Test2
   {
     doSomeThing2();
   }
**}**

I need the match from the first marked bracket to the last one.

Thanks for any help!

  • 2
    Regex here?.This is a very bad idea.. Drop this approach before it explodes. – TheLostMind Sep 22 '14 at 07:38
  • 2
    I don't think it is good idea to parse C# syntax with regex. I would use `Roslyn`: http://stackoverflow.com/questions/16338131/using-roslyn-to-parse-transform-generate-code-am-i-aiming-too-high-or-too-low –  Sep 22 '14 at 07:39
  • Regex would deliver me the exact starting and ending index of the class, this would be exactly what I am looking for. – ElyasMTarek Sep 22 '14 at 07:41
  • @T4R3K Why do you need the start and end index of the class? – Rawling Sep 22 '14 at 07:48
  • @Rawling I am working on a Visual Studio Add-in which "edits, sorts and looks for certain things" in the code of the current opened Document. The whole Add-in is working fine but, my only problem is that the Add-in is looking in the whole document currently opened and it just takes ages for Regex to look through it. I want the user to specify in what class the add-in should look for. – ElyasMTarek Sep 22 '14 at 07:53
  • @T4R3K can't you use the EnvDTE object to ask the Visual Studio itself where the class begins/ends? Something like this: http://www.mztools.com/articles/2006/mz2006009.aspx – naivists Sep 22 '14 at 09:38

3 Answers3

1

How about counting curly brackets, without using any regex-es? The same way you do it when building an arithmentic expression validator, except that in this case you have to skip the brackets that are commented out or inside string literals.

naivists
  • 32,681
  • 5
  • 61
  • 85
1

You can do this through regular expressions thanks to balancing groups.

This is a feature specific to C# and made specially for recursive patterns (such as the nested braces from your problem, or the nested XML markups from the MSDN example).

Note however that C# is quite the exception here: regular expressions typically do not support recursion (unless hard-coded for a finite depth).

Victor Victis
  • 313
  • 1
  • 8
0

Increase the count when you encounter an opening brace, decrease the count when you encounter a closing brace:

        var braceCount = 0;
        var nextChar = "{";
        do
        {
            if (nextChar == "{") braceCount++;
            if (nextChar == "}") braceCount--;
            nextChar = GetNextChar();
        }
        while (braceCount > 0);

I also got a good regex result, but don't understand why, the match should have stopped at the first closing brace. At my regex tester, with options .net, C#, dot matches all characters including newline: http://www.myregextester.com/index.php

Select All (to copy etc.) Raw Match Pattern: {.*}

C#.NET Code Example:

using System;
using System.Text.RegularExpressions;
namespace myapp
{
  class Class1
    {
      static void Main(string[] args)
        {
          String sourcestring = "source string to match with pattern";
          Regex re = new Regex(@"{.*}",RegexOptions.Singleline);
          MatchCollection mc = re.Matches(sourcestring);
          int mIdx=0;
          foreach (Match m in mc)
           {
            for (int gIdx = 0; gIdx < m.Groups.Count; gIdx++)
              {
                Console.WriteLine("[{0}][{1}] = {2}", mIdx, re.GetGroupNames()[gIdx], m.Groups[gIdx].Value);
              }
            mIdx++;
          }
        }
    }
}

Matches Found:

[0][0] = {**

 doSomeThing();

 private partial class Test2
   {
     doSomeThing2();
   }
**}
MrFox
  • 4,852
  • 7
  • 45
  • 81
  • Your regex doesn't stop because by default `*` is *greedy* - it consumes as much as possible before allowing the `}` to match. For this reason, this won't work unless the class is the single (or last) top-level item in the file (no namespace!) – Rawling Sep 22 '14 at 08:21
  • Thanks it seems this will then work for the given scenario. Although not ideal in case there is a namespace around it. – MrFox Sep 23 '14 at 06:52