Skip to content

Commit 5177ec4

Browse files
authored
Merge pull request #1 from pdelvo/SA1139NoRegularExpressions
Don't use regular expressions for SA1139 contributor: pdelvo
2 parents 7d1a4ca + 1d25e80 commit 5177ec4

2 files changed

Lines changed: 32 additions & 89 deletions

File tree

StyleCop.Analyzers/StyleCop.Analyzers/Helpers/LiteralExpressionHelpers.cs

Lines changed: 29 additions & 87 deletions
Original file line numberDiff line numberDiff line change
@@ -5,105 +5,47 @@
55

66
namespace StyleCop.Analyzers.Helpers
77
{
8-
using System;
9-
using System.Collections.Generic;
10-
using System.Linq;
11-
using System.Text.RegularExpressions;
12-
using Microsoft.CodeAnalysis.CSharp;
138
using Microsoft.CodeAnalysis.CSharp.Syntax;
149

1510
internal static class LiteralExpressionHelpers
1611
{
17-
private static readonly IDictionary<string, SyntaxKind> IntegerLiteralSuffixToLiteralSyntaxKind =
18-
new Dictionary<string, SyntaxKind>(StringComparer.OrdinalIgnoreCase)
19-
{
20-
{ string.Empty, SyntaxKind.IntKeyword },
21-
{ "L", SyntaxKind.LongKeyword },
22-
{ "UL", SyntaxKind.ULongKeyword },
23-
{ "LU", SyntaxKind.ULongKeyword },
24-
{ "U", SyntaxKind.UIntKeyword },
25-
{ "D", SyntaxKind.DoubleKeyword },
26-
};
27-
28-
private static readonly IDictionary<string, SyntaxKind> RealLiteralSuffixToLiteralSyntaxKind =
29-
new Dictionary<string, SyntaxKind>(StringComparer.OrdinalIgnoreCase)
30-
{
31-
{ "F", SyntaxKind.FloatKeyword },
32-
{ "D", SyntaxKind.DoubleKeyword },
33-
{ "M", SyntaxKind.DecimalKeyword }
34-
};
35-
36-
private static readonly char[] LettersAllowedInIntegerLiteralSuffix =
37-
GetCharsFromKeysLowerAndUpperCase(IntegerLiteralSuffixToLiteralSyntaxKind);
38-
39-
private static readonly char[] LettersAllowedInRealLiteralSuffix =
40-
GetCharsFromKeysLowerAndUpperCase(RealLiteralSuffixToLiteralSyntaxKind);
41-
42-
private static readonly RegexOptions LiteralRegexOptions = RegexOptions.IgnoreCase | RegexOptions.CultureInvariant;
43-
private static readonly Regex IntegerBase10Regex = new Regex("^([0-9]*)(|u|l|ul|lu)$", LiteralRegexOptions, Regex.InfiniteMatchTimeout);
44-
private static readonly Regex IntegerBase16Regex = new Regex("^(0x)([0-9a-f]*)(|u|l|ul|lu)$", LiteralRegexOptions, Regex.InfiniteMatchTimeout);
45-
private static readonly Regex RealRegex = new Regex("^([0-9]*)(m|f|d)|([0-9]*)[.[0-9]*[e[0-9{1,2}]]([|m|f|d])]$", LiteralRegexOptions, Regex.InfiniteMatchTimeout);
46-
47-
internal static SyntaxKind GetCorrespondingSyntaxKind(this LiteralExpressionSyntax literalExprssionSyntax)
48-
{
49-
var literalText = literalExprssionSyntax.Token.Text;
50-
var suffixStartIndex = SuffixStartIndex(literalText);
51-
52-
var suffix = suffixStartIndex == -1 ?
53-
string.Empty :
54-
literalText.Substring(suffixStartIndex, length: literalText.Length - suffixStartIndex);
55-
return GetLiteralSyntaxKindBySuffix(suffix);
56-
}
57-
5812
internal static string StripLiteralSuffix(this LiteralExpressionSyntax literalExpressionSyntax)
5913
{
6014
var literalText = literalExpressionSyntax.Token.Text;
61-
int suffixStartIndex = SuffixStartIndex(literalText);
62-
return suffixStartIndex == -1 ? literalText : literalText.Substring(0, suffixStartIndex);
63-
}
6415

65-
private static SyntaxKind GetLiteralSyntaxKindBySuffix(string suffix)
66-
{
67-
SyntaxKind syntaxKind;
68-
if (IntegerLiteralSuffixToLiteralSyntaxKind.TryGetValue(suffix, out syntaxKind))
69-
{
70-
return syntaxKind;
71-
}
72-
else if (RealLiteralSuffixToLiteralSyntaxKind.TryGetValue(suffix, out syntaxKind))
73-
{
74-
return syntaxKind;
75-
}
16+
bool isBase16 = literalText.Length > 2 && (literalText[1] == 'x' || literalText[1] == 'X');
7617

77-
throw new ArgumentException($"There is no integer nor real numeric literal with suffix '{suffix}'.");
78-
}
79-
80-
private static int SuffixStartIndex(string literalText)
81-
{
82-
int suffixStartIndex = -1;
83-
if (IsIntegerLiteral(literalText))
18+
for (int i = literalText.Length - 1; i >= 0; i--)
8419
{
85-
suffixStartIndex = literalText.IndexOfAny(LettersAllowedInIntegerLiteralSuffix);
20+
switch (literalText[i])
21+
{
22+
case 'L':
23+
case 'U':
24+
case 'M':
25+
case 'l':
26+
case 'u':
27+
case 'm':
28+
continue;
29+
case 'D':
30+
case 'F':
31+
case 'd':
32+
case 'f':
33+
if (isBase16)
34+
{
35+
goto default;
36+
}
37+
else
38+
{
39+
continue;
40+
}
41+
42+
default:
43+
return literalText.Substring(0, i + 1);
44+
}
8645
}
87-
else if (IsRealLiteral(literalText))
88-
{
89-
suffixStartIndex = literalText.IndexOfAny(LettersAllowedInRealLiteralSuffix);
90-
}
91-
92-
return suffixStartIndex;
93-
}
9446

95-
private static bool IsIntegerLiteral(string literal) =>
96-
IntegerBase10Regex.IsMatch(literal) || IntegerBase16Regex.IsMatch(literal);
97-
98-
private static bool IsRealLiteral(string literal) =>
99-
RealRegex.IsMatch(literal);
100-
101-
private static char[] GetCharsFromKeysLowerAndUpperCase(IDictionary<string, SyntaxKind> dict)
102-
{
103-
return dict.Keys
104-
.SelectMany(s => s.ToCharArray()).Distinct()
105-
.SelectMany(c => new[] { char.ToLowerInvariant(c), char.ToUpperInvariant(c) })
106-
.ToArray();
47+
// If this is reached literalText does not contain a literal
48+
return string.Empty;
10749
}
10850
}
10951
}

StyleCop.Analyzers/StyleCop.Analyzers/ReadabilityRules/SA1139UseLiteralSuffixNotationInsteadOfCasting.cs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ private static void HandleGenericName(SyntaxNodeAnalysisContext context)
6767
if (unaryExpressionSyntax.Kind() != SyntaxKind.UnaryPlusExpression
6868
&& unaryExpressionSyntax.Kind() != SyntaxKind.UnaryMinusExpression)
6969
{
70-
// don't raport diagnostic if bit operations are performed and for some invalid code (eg. "(long)++1")
70+
// don't report diagnostic if bit operations are performed and for some invalid code (eg. "(long)++1")
7171
return;
7272
}
7373
}
@@ -94,7 +94,8 @@ private static void HandleGenericName(SyntaxNodeAnalysisContext context)
9494
return;
9595
}
9696

97-
if (castedElementTypeSyntax.GetCorrespondingSyntaxKind() == syntaxKindKeyword)
97+
if (context.SemanticModel.GetTypeInfo(castedElementTypeSyntax).Type
98+
== context.SemanticModel.GetTypeInfo(castExpressionSyntax).Type)
9899
{
99100
// cast is redundant which is reported by another diagnostic.
100101
return;

0 commit comments

Comments
 (0)