-
Notifications
You must be signed in to change notification settings - Fork 4
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add MEN016 Avoid Top-Level Statements rule
- Loading branch information
Showing
7 changed files
with
248 additions
and
3 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,57 @@ | ||
namespace Menees.Analyzers | ||
{ | ||
[DiagnosticAnalyzer(LanguageNames.CSharp)] | ||
public sealed class Men016AvoidTopLevelStatements : Analyzer | ||
{ | ||
#region Public Constants | ||
|
||
public const string DiagnosticId = "MEN016"; | ||
|
||
#endregion | ||
|
||
#region Private Data Members | ||
|
||
private static readonly LocalizableString Title = | ||
new LocalizableResourceString(nameof(Resources.Men016Title), Resources.ResourceManager, typeof(Resources)); | ||
|
||
private static readonly LocalizableString MessageFormat = | ||
new LocalizableResourceString(nameof(Resources.Men016MessageFormat), Resources.ResourceManager, typeof(Resources)); | ||
|
||
private static readonly LocalizableString Description = | ||
new LocalizableResourceString(nameof(Resources.Men016Description), Resources.ResourceManager, typeof(Resources)); | ||
|
||
private static readonly DiagnosticDescriptor Rule = | ||
new(DiagnosticId, Title, MessageFormat, Rules.Usage, DiagnosticSeverity.Warning, Rules.EnabledByDefault, Description); | ||
|
||
#endregion | ||
|
||
#region Public Properties | ||
|
||
public override ImmutableArray<DiagnosticDescriptor> SupportedDiagnostics => ImmutableArray.Create(Rule); | ||
|
||
#endregion | ||
|
||
#region Public Methods | ||
|
||
public override void Initialize(AnalysisContext context) | ||
{ | ||
base.Initialize(context); | ||
context.RegisterSyntaxNodeActionHonorExclusions(this, HandleGlobalStatement, SyntaxKind.GlobalStatement); | ||
} | ||
|
||
#endregion | ||
|
||
#region Private Methods | ||
|
||
private static void HandleGlobalStatement(SyntaxNodeAnalysisContext context) | ||
{ | ||
if (context.Node is GlobalStatementSyntax statement) | ||
{ | ||
Location location = statement.GetLocation(); | ||
context.ReportDiagnostic(Diagnostic.Create(Rule, location)); | ||
} | ||
} | ||
|
||
#endregion | ||
} | ||
} |
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,151 @@ | ||
namespace Menees.Analyzers.Test | ||
{ | ||
[TestClass] | ||
public class Men016UnitTests : CodeFixVerifier | ||
{ | ||
#region Private Data Members | ||
|
||
private const string ExpectedMessage = "Use object-oriented methods instead of top-level statements."; | ||
|
||
#endregion | ||
|
||
#region Protected Properties | ||
|
||
protected override DiagnosticAnalyzer CSharpDiagnosticAnalyzer => new Men016AvoidTopLevelStatements(); | ||
|
||
#endregion | ||
|
||
#region ValidCodeTest | ||
|
||
[TestMethod] | ||
public void ValidCodeTest() | ||
{ | ||
this.VerifyCSharpDiagnostic(string.Empty); | ||
|
||
const string test = @" | ||
using System.Collections.Generic; | ||
using System.Diagnostics; | ||
class Testing | ||
{ | ||
Dictionary<string, string> _entries = new(); | ||
public Testing() | ||
{ | ||
Dictionary<string, int> test = new(); | ||
if (test.ContainsKey(""a"")) | ||
{ | ||
Debug.WriteLine(""Contains a""); | ||
} | ||
} | ||
public void Mask() | ||
{ | ||
if (_entries.ContainsKey(""Password"")) | ||
{ | ||
_entries[""Password""] = ""********""; | ||
} | ||
} | ||
public bool ContainsKey(string key) => _entries.ContainsKey(key); | ||
}"; | ||
this.VerifyCSharpDiagnostic(test); | ||
} | ||
|
||
#endregion | ||
|
||
#region InvalidCodeTests | ||
|
||
[TestMethod] | ||
public void InvalidCodeSimpleTest() | ||
{ | ||
const string test = @" | ||
using System; | ||
Console.WriteLine(""Test""); | ||
"; | ||
|
||
var analyzer = this.CSharpDiagnosticAnalyzer; | ||
DiagnosticResult[] expected = new[] | ||
{ | ||
new DiagnosticResult(analyzer) | ||
{ | ||
Message = ExpectedMessage, | ||
Locations = new[] { new DiagnosticResultLocation("Test0.cs", 3, 1) }, | ||
}, | ||
}; | ||
|
||
this.VerifyCSharpDiagnostic(test, expected); | ||
} | ||
|
||
[TestMethod] | ||
public void InvalidCodeWithClassTest() | ||
{ | ||
const string test = @" | ||
using System; | ||
using static System.Console; | ||
WriteLine(""Test""); | ||
MyClass.TestMethod(); | ||
public class MyClass | ||
{ | ||
public static void TestMethod() | ||
{ | ||
Console.WriteLine(""Hello World!""); | ||
} | ||
} | ||
"; | ||
|
||
var analyzer = this.CSharpDiagnosticAnalyzer; | ||
DiagnosticResult[] expected = new[] | ||
{ | ||
new DiagnosticResult(analyzer) | ||
{ | ||
Message = ExpectedMessage, | ||
Locations = new[] { new DiagnosticResultLocation("Test0.cs", 5, 1) }, | ||
}, | ||
new DiagnosticResult(analyzer) | ||
{ | ||
Message = ExpectedMessage, | ||
Locations = new[] { new DiagnosticResultLocation("Test0.cs", 6, 1) }, | ||
}, | ||
}; | ||
|
||
this.VerifyCSharpDiagnostic(test, expected); | ||
} | ||
|
||
[TestMethod] | ||
public void InvalidCodeWithNamespaceTest() | ||
{ | ||
const string test = @" | ||
using System; | ||
MyNamespace.MyClass.MyMethod(); | ||
namespace MyNamespace | ||
{ | ||
class MyClass | ||
{ | ||
public static void MyMethod() | ||
{ | ||
Console.WriteLine(""Hello World from MyNamespace.MyClass.MyMethod!""); | ||
} | ||
} | ||
}"; | ||
|
||
var analyzer = this.CSharpDiagnosticAnalyzer; | ||
DiagnosticResult[] expected = new[] | ||
{ | ||
new DiagnosticResult(analyzer) | ||
{ | ||
Message = ExpectedMessage, | ||
Locations = new[] { new DiagnosticResultLocation("Test0.cs", 4, 1) }, | ||
}, | ||
}; | ||
|
||
this.VerifyCSharpDiagnostic(test, expected); | ||
} | ||
|
||
|
||
#endregion | ||
} | ||
} |