Change namespace with conditional compilation attribute in bulk - c#

Suppose we have an existing code as;
namespace Company.Product1
{
class Class1
{
}
}
Now we need to change the namespace based on conditional symbol so that it becomes;
#if PRODUCT1
namespace Company.Product1
#else
namespace Company.Product2
#endif
{
class Class1
{
}
}
Since we have hundreds of classes, it will take a lot of time doing manually. Is there any simple way? Or how can I do this using regex?
Any help will be appreciated.

It seems like an anti-pattern to have the same code in two different namespaces but you may have some reasons that I am not aware of so I will try to answer you question anyway. Also, note that a tool like Resharper makes it easy to rename an entire namespace using the refactor tool.
To simply replace the namespace definition in each source file you can use the Visual Studio 2013 text editor (should also work in previous versions):
1) Select Edit > Find and Replace > Quick Replace
2) In the Search term text box enter the text namespace Company.Product1
3) In the Replacement term text box enter the text #if PRODUCT1\nnamespace Company.Product1\n#else\nnamespace Company.Product2\n#endif. Notice how newlines are entered using \n.
4) Make sure that Use Regular Expressions is checked. This is the option that allows you to have escaped newlines in the replacement text. You can also check Match case and Match whole word.
5) Set the scope to Entire Solution.
6) Click on Replace all to make the replacement.

Related

Replace beginning and end of string with unique midle?

I have lots of code like below:
PlusEnvironment.EnumToBool(Row["block_friends"].ToString())
I need to convert them to something like this.
Row["block_friends"].ToString() == "1"
The value that gets passed to EnumToBool is always unique, meaning there is no guarantee that itll be passed by a row, it could be passed by a variable, or even a method that returns a string.
I've tried doing this with regex, but its sort of sketchy and doesn't work 100%.
PlusEnvironment\.EnumToBool\((.*)\)
I need to do this in Visual Studio's find and replace. I'm using VS 17.
If you had a few places where PlusEnvironment.EnumToBool() was called, I would have done the same thing that #IanMercer suggested: just replace PlusEnvironment.EnumToBool( with empty string and the fix all the syntax errors.
#IanMercer has also given you a link to super cool, advanced regex usage that will help you.
But if you are skeptical about using such a complex regex on hundreds of files, here is what I would have done:
Define my own PlusEnvironment class with EnumToBool functionality in my own namespace. And then just replace the using Plus; line with using <my own namespace>; in those hundreds of files. That way my changes will be limited to only the using... line, 1 line per file, and it will be simple find and replace, no regex needed.
(Note: I'm assuming that you don't want to use PlusEnvironment, or the complete library and hence you want to do this type of replacement.)
in Find and Replace Window:
Find:
PlusEnvironment\.EnumToBool\((.*))
Replace:
$1 == "1"
Make sure "Use Regular Expressions" is selected

Custom naming rules in ReSharper

The project I'm working on (C# on VS 2015 with ReSharper 2016.1.2) has a new requirement which requires us to remove all usages of p_ prefixes in parameter names (p_Param becomes param).
I'd like to create a ReSharper Code Inspection Custom Pattern to take care of this for me (to match the string pattern with squiggly lines and auto-fix in the solution).
I've followed the tutorial at https://www.jetbrains.com/help/resharper/2016.1/Code_Inspection__Creating_Custom_Inspections_and_QuickFixes.html but I'm a bit stuck.
I've tried the following patterns:
Var 1
Find: $prefix$$varName$ ($prefix$ - identifier, matching regex [^p_*] (start with p_, continue with anything, $varName$ - identifier)
Replace $varName$
Var 2
Find: p_$varName$ ($varName$ - identifier)
Replace $varName
I'd also need to transform the $varName$ identifier from PascalCase to cammelCase (no ideea how to do this).
When searching via 'Search now' - no results are found in either situation.
Any help is appreciated.
Using ReSharper, you can change the naming style of variables and have it apply to an entire solution.
The location of this option will (probably) vary but for my version of R# (2016.1.2), it's under ReSharper->Options->Code Editing->C#->Naming Style:
From there, change the Entity Kinds to how you want them to appear. In mine, I prefer _lowerCamelCase for private instance fields for example.
Once your changes are made, find any field of that type in code (I'll use a private variable) that doesn't follow that format, click it and then click the light bulb to the left. From there mouse-over the arrow on "Rename to ......" and select Fix naming in solution.
You might have to do it a few times but that's how I rename stuff based on my preferred code style.

removing #region

I had to take over a c# project. The guy who developed the software in the first place was deeply in love with #region because he wrapped everything with regions.
It makes me almost crazy and I was looking for a tool or addon to remove all #region from the project. Is there something around?
Just use Visual Studio's built-in "Find and Replace" (or "Replace in Files", which you can open by pressing Ctrl + Shift + H).
To remove #region, you'll need to enable Regular Expression matching; in the "Replace In Files" dialog, check "Use: Regular Expressions". Then, use the following pattern: "\#region .*\n", replacing matches with "" (the empty string).
To remove #endregion, do the same, but use "\#endregion .*\n" as your pattern. Regular Expressions might be overkill for #endregion, but it wouldn't hurt (in case the previous developer ever left comments on the same line as an #endregion or something).
Note: Others have posted patterns that should work for you as well, they're slightly different than mine but you get the general idea.
Use one regex ^[ \t]*\#[ \t]*(region|endregion).*\n to find both: region and endregion. After replacing by empty string, the whole line with leading spaces will be removed.
[ \t]* - finds leading spaces
\#[ \t]*(region|endregion) - finds #region or #endregion (and also very rare case with spaces after #)
.*\n - finds everything after #region or #endregion (but in the same line)
EDIT: Answer changed to be compatible with old Visual Studio regex syntax. Was: ^[ \t]*\#(end)?region.*\n (question marks do not work for old syntax)
EDIT 2: Added [ \t]* after # to handle very rare case found by #Volkirith
In Find and Replace use {[#]<region[^]*} for Find what: and replace it with empty string.
#EndRegion is simple enough to replace.
Should you have to cooperate with region lovers (and keep regions untouched ), then I would recommend "I hate #Regions" Visual Studio extension. It makes regions tolerable - all regions are expanded by default and #region directives are rendered with very small font.
For anyone using ReSharper it's just a simple Atr-Enter on the region line. You will then have the option to remove regions in file, in project, or in solution.
More info on JetBrains.
To remove #region with a newline after it, replace following with empty string:
^(?([^\r\n])\s)*\#region\ ([^\r\n])*\r?\n(?([^\r\n])\s)*\r?\n
To replace #endregion with a leading empty line, replace following with an empty string:
^(?([^\r\n])\s)*\r?\n(?([^\r\n])\s)*\#endregion([^\r\n])*\r?\n
How about writing your own program for it, to replace regions with nothing in all *.cs files in basePath recursively ?
(Hint: Careful with reading files as UTF8 if they aren't.)
public static void StripRegions(string fileName, System.Text.RegularExpressions.Regex re)
{
string input = System.IO.File.ReadAllText(fileName, System.Text.Encoding.UTF8);
string output = re.Replace(input, "");
System.IO.File.WriteAllText(fileName, output, System.Text.Encoding.UTF8);
}
public static void StripRegions(string basePath)
{
System.Text.RegularExpressions.Regex re = new System.Text.RegularExpressions.Regex(#"(^[ \t]*\#[ \t]*(region|endregion).*)(\r)?\n", System.Text.RegularExpressions.RegexOptions.Multiline);
foreach (string file in System.IO.Directory.GetFiles(basePath, "*.cs", System.IO.SearchOption.AllDirectories))
{
StripRegions(file, re);
}
}
Usage:
StripRegions(#"C:\sources\TestProject")
You can use the wildcard find/replace:
*\#region *
*\#endregion
And replace with no value. (Note the # needs to be escaped, as visual stuido uses it to match "any number")

find all occurrences of comparison with == in visual studio

I made the mistake of using == for comparing IP addresses instead of using the equals() method of the IPAddress class in C#, which will result in the comparison of references instead of values.
Since the solution I am currently working on is very large for a one-man project (> 100.000 lines of source code), I am very sure that I still have some of these wrong statements in my code.
Is there any possibility to tell Visual Studio to find all occurrences of == operations on a specific class for me, so that I can find and clean up the bugged comparisons?
with best regards, emi
It's a bit of a hack but you can temporarily add this class to your project:
namespace System.Net
{
class IPAddress
{
[Obsolete]
public static bool operator ==(IPAddress a, IPAddress b) { return true; }
[Obsolete]
public static bool operator !=(IPAddress a, IPAddress b) { return true; }
}
}
Compile and look for warnings about using obsolete methods:
Warning 'IPAddress.operator ==(IPAddress, IPAddress)' is obsolete
Once you have fixed the code, remove the class definition.
You could always use a find / replace on "==". You can use the filters to determine what / where you want to search or just use the Entire Solution.
You might be able to use .NET Reflector or maybe the Visual Studio call hierarchy window to look for calls to the operator== method of the IPAdress class. I don't know if this is possible, just throwing out an idea.
If you know the name of the variable representing the IP address over your code, then yes, it is possible with some workaround. Say your variable is called 'ipAddress'. Then do this:
Using wildcards search for:
ipAddress*==
Then loop through the results and make a macro that make the change for you. For example, let's suppose your statement looks like this:
if (ipAddress == anotherIpAddress) {
Then you make a micro as follows:
Start Recording
Press Home # This will go to the beginning of the line
Ctrl+Right Three Times # This will keep the cursor on the beginning of anotherIpAddress
Backspace # This will remove the space
.equals( # This will write .equals(
Del Three Times # This will delete the == and the space after it
Ctrl+Right # This will keep you at the closing bracket ).
) # This will write another closing bracket for the equals functions.
Stop Recording
Now you have a macro that change the line for you. All you have to do is to repeatedly press F4 then Ctrl^P. Pressing F4 moves you to the next results in Find in Files (I suppose you will use this), and pressing Ctrl^P executes the macro.
There is a better solution actually using regular expressions but I am not sure whether it works with visual studio. Basically, it groups elements in Find and use them in Replace. So you search for something like "ipAddress == ( < my variable pattern > )" and replace it with "ipAddress.equals(\1)", the one here refers to the first group.
Hope that helps!
You might subclass IPAddress and override the == operator. This of course depends on how easily you can replace the references. Once you've done that, you could stop there or replace all instances of your == operator with .Equals()

How do I display only the class name in doxygen class diagrams?

Using doxygen and graphviz with my C# project, I can generate class diagrams in the documentation pages. These diagrams have the full class names and namespaces in them, e.g.
Acme.MyProduct.MyClasses.MyClass
Is it possible to configure doxygen to cut this down a bit to just the class name?
MyClass
The fully qualified paths make even simple diagrams rather wide and unwieldy. I'd like to minimize the need for horizontal scrolling.
I suspect that you've already solved this as it is a year old, but an answer might be useful for anyone else searching for this (as I just did). You can use the "HIDE_SCOPE_NAMES" option. Setting it to YES (or checking it in the doxywizard GUI) will hide namespaces. From my doxygen file:
# If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen
# will show members with their full class and namespace scopes in the
# documentation. If set to YES the scope will be hidden.
HIDE_SCOPE_NAMES = YES
The HIDE_SCOPE_NAMES works great but only hides the scope in the class diagram but not the caller/callee graphs for each method.
To reduce the width of those diagrams to a readable size you can rename the scope using the input filter. This will not remove the namespace but will reduce it to a more readable width.
For example to rename the namespace "COMPANY_NAMESPACE" to "sf" use:
# The INPUT_FILTER tag can be used to specify a program that doxygen should
# invoke to filter for each input file. Doxygen will invoke the filter program
# by executing (via popen()) the command <filter> <input-file>, where <filter>
# is the value of the INPUT_FILTER tag, and <input-file> is the name of an
# input file. Doxygen will then use the output that the filter program writes
# to standard output. If FILTER_PATTERNS is specified, this tag will be
# ignored.
INPUT_FILTER = "sed 's,COMPANY_NAMESPACE,sf,'"

Categories