Search and replace C # expression

From time to time I need to change the use of one method call to another.

eg. I have 100 method calls like this:

Helper.GetIntFromData(packetData.Skip(offset).Take(length).ToArray()); 

which need to be changed to

 Helper.GetIntFromData(packetData, offset, length); 

This is relatively easy to solve with regex. But what if whitespace comes into play (sometimes)?

 Helper.GetIntFromData(packetData .Skip( offset ) .Take( length ) .ToArray() ); 

Still executed with regex, but now it's an unreadable mess of optional tokens for scrolling.

OK, but what if the parameters are not always simple identifiers, but arbitrary expressions ?

 Helper.GetIntFromData(obj.GetData(true).Skip( 7 + GetOffset( item.GetData() ) ) .Take( length1 / length2 ).ToArray()); 

Here regular expressions really break.

My question is:

Can this be done today? (so that you remain operational, that is, without regular expression)

Is there a VS extension or a standalone tool that can handle searching and replacing C # code at a higher (semantic) level?

Something to let me search (I think):

 Helper.GetIntFromData($expr1.Skip($expr2).Take($expr3).ToArray()) 

and replace with

 Helper.GetIntFromData($1, $2, $3) 

Is there such a tool for C #? (I suppose it could be built around Roslin.)

+8
c # regex visual-studio roslyn
source share
3 answers

Thinking another thought, what you are trying to achieve is dangerous and better avoided. RegEx compliance / replacement is a limited feature. He cannot "understand" complex code and must fail. Let's consider an example like (let it ignore the second, if this code even makes sense):

Helper.GetIntFromData(packetData.Skip(skipArray.Take(1)).Take(length).ToArray());

A regular expression that is not specifically designed to prevent a “wrong Take ” has no chance. It is a matter of time until your automatic replacement method breaks your code, and your only hope is that it is rude enough to generate a compile-time error. It can also create a complex task to find a runtime exception or worse, inexplicable behavior. Code refactoring should be done with a tool that understands the code, not a tool that recognizes text patterns.

+1
source share

Resharper has semantic search and replaces

 Helper.GetIntFromData(packetData.Skip($offset$).Take($length$).ToArray()); 

from

 Helper.GetIntFromData(packetData, $offset$, $length$); 

This is an unsafe space, and you can limit the coincidence of markers to certain types. I use it all the time to do what you are trying to do. I have not seen any roslin-based projects that all users do so trivially.

Here is an introduction to the function on the resharpers website

http://blog.jetbrains.com/dotnet/2010/04/07/introducing-resharper-50-structural-search-and-replace/

+1
source share

If at all possible, I would do it “manually”, but using simple regular expressions (yes, I know what you said without them, and Amit’s answer “looks right”, although I did not check it for cases of edges).

Something like that:

 Helper.GetIntFromData(packetData.Skip(offset).Take(length).ToArray()); Helper.GetIntFromData(obj.GetData(true).Skip( 7 + GetOffset( item.GetData() ) ) .Take( length1 / length2 ).ToArray()); 

Replace (Helper.GetIntFromData.*?)\.Skip\( with \1, , to get

 Helper.GetIntFromData(packetData, offset).Take(length).ToArray()); Helper.GetIntFromData(obj.GetData(true), 7 + GetOffset( item.GetData() ) ) .Take( length1 / length2 ).ToArray()); 

Then replace (Helper.GetIntFromData.*?)\)\.Take\( with \1, , to get

 Helper.GetIntFromData(packetData, offset, length).ToArray()); Helper.GetIntFromData(obj.GetData(true), 7 + GetOffset( item.GetData() ) , length1 / length2 ).ToArray()); 

And finally, replace (Helper.GetIntFromData.*?)\)\.ToArray\(\)\); on \1\); , To obtain

 Helper.GetIntFromData(packetData, offset, length); Helper.GetIntFromData(obj.GetData(true), 7 + GetOffset( item.GetData() ) , length1 / length2 ); 
0
source share

All Articles