HiveBrain v1.2.0
Get Started
← Back to all entries
patterncsharpMinor

The stripping extensions

Submitted by: @import:stackexchange-codereview··
0
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 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 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.