patterncsharpMinor
The stripping extensions
Viewed 0 times
strippingtheextensions
Problem
In order to make my life easier with parsing some VBA code, I have written a few extension methods to extend the
```
[ComVisible(false)]
public static class StringExtensions
{
public static readonly char StringDelimiter = '"';
public static readonly char CommentMarker = '\'';
///
/// Strips any trailing comment from specified line of code.
///
///
/// Returns a new string, without the trailing comment.
public static string StripTrailingComment(this string line)
{
int index;
if (line.HasComment(out index))
{
return line.Substring(0, index).TrimEnd();
}
return line;
}
///
/// Returns a value indicating whether line of code is/contains a comment.
///
///
/// Returns the start index of the comment string, including the comment marker.
///
public static bool HasComment(this string line, out int index)
{
index = -1;
var instruction = line.StripStringLiterals();
for (int cursor = 0; cursor
/// Strips all string literals from a line of code or instruction.
/// Replaces string literals with whitespace characters, to maintain original length.
///
///
/// Returns a new string, stripped of all string literals and string delimiters.
public static string StripStringLiterals(this string line)
{
var builder = new StringBuilder(line.Length);
var isInsideString = false;
for (int cursor = 0; cursor 0 && (line[cursor - 1] == StringDelimiter);
}
else
{
isInsideString = true;
}
}
if (!isInsideString && line[cursor] != StringDelimiter)
{
builder.Append(line[cursor]);
}
else
{
builder.Append(' ');
}
}
r
string type, and put them in this StringExtensions class:```
[ComVisible(false)]
public static class StringExtensions
{
public static readonly char StringDelimiter = '"';
public static readonly char CommentMarker = '\'';
///
/// Strips any trailing comment from specified line of code.
///
///
/// Returns a new string, without the trailing comment.
public static string StripTrailingComment(this string line)
{
int index;
if (line.HasComment(out index))
{
return line.Substring(0, index).TrimEnd();
}
return line;
}
///
/// Returns a value indicating whether line of code is/contains a comment.
///
///
/// Returns the start index of the comment string, including the comment marker.
///
public static bool HasComment(this string line, out int index)
{
index = -1;
var instruction = line.StripStringLiterals();
for (int cursor = 0; cursor
/// Strips all string literals from a line of code or instruction.
/// Replaces string literals with whitespace characters, to maintain original length.
///
///
/// Returns a new string, stripped of all string literals and string delimiters.
public static string StripStringLiterals(this string line)
{
var builder = new StringBuilder(line.Length);
var isInsideString = false;
for (int cursor = 0; cursor 0 && (line[cursor - 1] == StringDelimiter);
}
else
{
isInsideString = true;
}
}
if (!isInsideString && line[cursor] != StringDelimiter)
{
builder.Append(line[cursor]);
}
else
{
builder.Append(' ');
}
}
r
Solution
In
I find it odd that you have to iterate over the characters.
Isn't there something like
So that the loop could be replaced with this:
A test for
I'm guessing the part you dislike the most is the implementation of
if that's even possible.
Short of that, it seems that these two
to get:
And this line is too long to read:
HasComment,I find it odd that you have to iterate over the characters.
Isn't there something like
indexOf that returns the index or -1 otherwise?So that the loop could be replaced with this:
index = instruction.IndexOf(CommentMarker);
return index > -1;A test for
StripTrailingComment would be good too:[TestMethod]
public void StripTrailingComment()
{
var comment = " 'but this is one.";
var instruction = "Debug.Print \"'this isn't a comment\"";
var instructionWithComment = instruction + comment;
var result = instructionWithComment.StripTrailingComment();
Assert.AreEqual(instruction, result);
}I'm guessing the part you dislike the most is the implementation of
StripStringLiterals. I'd look for a clever regex for this,if that's even possible.
Short of that, it seems that these two
if can be simplified by joining with else if:if (line[cursor] == StringDelimiter)
{
// ...
}
if (!isInsideString && line[cursor] != StringDelimiter)
{
// ...
}to get:
if (line[cursor] == StringDelimiter)
{
// ...
}
else if (!isInsideString)
{
// ...
}And this line is too long to read:
isInsideString = cursor + 1 == line.Length || line[cursor + 1] == StringDelimiter || cursor > 0 && (line[cursor - 1] == StringDelimiter);Code Snippets
index = instruction.IndexOf(CommentMarker);
return index > -1;[TestMethod]
public void StripTrailingComment()
{
var comment = " 'but this is one.";
var instruction = "Debug.Print \"'this isn't a comment\"";
var instructionWithComment = instruction + comment;
var result = instructionWithComment.StripTrailingComment();
Assert.AreEqual(instruction, result);
}if (line[cursor] == StringDelimiter)
{
// ...
}
if (!isInsideString && line[cursor] != StringDelimiter)
{
// ...
}if (line[cursor] == StringDelimiter)
{
// ...
}
else if (!isInsideString)
{
// ...
}isInsideString = cursor + 1 == line.Length || line[cursor + 1] == StringDelimiter || cursor > 0 && (line[cursor - 1] == StringDelimiter);Context
StackExchange Code Review Q#69551, answer score: 7
Revisions (0)
No revisions yet.